From e070dab2f0b93cabec383d0b7aa1b789a9b5e52f Mon Sep 17 00:00:00 2001 From: jdp_ <42700985+jdpatdiscord@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:26:35 -0400 Subject: [PATCH 001/147] Allow builds on MSYS2 & improve Windows build steps documentation --- CMakeLists.txt | 25 ++++++++++-- documents/building-windows.md | 74 ++++++++++++++++++++++++++++++----- 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 679325ec8..7337d18b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -643,23 +643,40 @@ if (ENABLE_QT_GUI) endif() if (WIN32) - target_link_libraries(shadps4 PRIVATE mincore winpthreads clang_rt.builtins-x86_64.lib) - add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) + target_link_libraries(shadps4 PRIVATE mincore winpthreads) + + if (MSVC) + # MSVC likes putting opinions on what people can use, disable: + add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) + endif() + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) + if (MSVC) # Needed for conflicts with time.h of windows.h add_definitions(-D_TIMESPEC_DEFINED) endif() + # Target Windows 10 RS5 add_definitions(-DNTDDI_VERSION=0x0A000006 -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00) - # Increase stack commit area - target_link_options(shadps4 PRIVATE /STACK:0x200000,0x200000) + + if (MSVC) + target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib) + endif() + # Disable ASLR so we can reserve the user area if (MSVC) target_link_options(shadps4 PRIVATE /DYNAMICBASE:NO) else() target_link_options(shadps4 PRIVATE -Wl,--disable-dynamicbase) endif() + + # Increase stack commit area (Needed, otherwise there are crashes) + if (MSVC) + target_link_options(shadps4 PRIVATE /STACK:0x200000,0x200000) + else() + target_link_options(shadps4 PRIVATE -Wl,--stack,2097152) + endif() endif() if (WIN32) diff --git a/documents/building-windows.md b/documents/building-windows.md index e00ed90d9..21c0c12b8 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -5,21 +5,75 @@ SPDX-License-Identifier: GPL-2.0-or-later # Build shadPS4 for Windows -## Download Visual Studio Community 2022 +This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation. +If you are building to contribute to the project, please omit `--depth 1` from the git invokations. -Download link: [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/) +## Option 1: Visual Studio 2022 -## Requirements +### (Prerequisite) Download the Community edition from [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/) -### From Visual Studio Community +Once you are within the installer: +1. Select `Desktop development with C++` +2. Go to "Individual Components" tab +3. Make sure `C++ Clang Compiler for Windows`, `MSBuild support for LLVM` and `C++ CMake Tools for Windows` are selected +4. Continue the installation -- Desktop development with C++ +### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html) -### From individual components tab install +Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead. -- C++ Clang Compiler for Windows (17.0.3) -- MSBuild support for LLVM (Clang-cl) toolset +1. Select Qt for Visual Studio plugin +2. Select `msvc2019_64` option or similar. If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `msvc2019_arm64` -- ## Compiling +Go through the installation normally. If you do not know what components to select, just select the newest Qt version it gives you. +If you know what you are doing, you may unselect individual components that eat up too much disk space. -- Open Visual Studio Community and select the **x64-Clang-Release**, **x64-Clang-Debug** or **x64-Clang-RelWithDebInfo**. It should compile just fine. +Once you are finished, you will have to configure Qt within Visual Studio: +1. Tools -> Options -> Qt -> Versions +2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.1\msvc2019_64` +3. Enable the default checkmark on the new version you just created. + +### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win) + +Go through the Git for Windows installation as normal + +### Compiling with Visual Studio GUI + +1. Open Git for Windows, navigate to a place where you want to store the shadPS4 source code folder +2. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` +3. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` +4. Build -> Build All + +## Option 2: MSYS2/MinGW + +### (Prerequisite) Download [**MSYS2**](https://www.msys2.org/) + +Go through the MSYS2 installation as normal + +If you are building to distribute, please omit `-DCMAKE_CXX_FLAGS="-O2 -march=native"` within the build configuration step. + +Normal x86-based computers, follow: +1. Open "MSYS2 MINGW64" from your new applications +2. Run `pacman -Syu`, let it complete; +3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-qt6-base` +4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` +5. Run `cd shadPS4` +6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` +7. Run `cmake --build build` +8. To run the finished product, run `./build/shadPS4.exe` + +ARM64-based computers, follow: +1. Open "MSYS2 CLANGARM64" from your new applications +2. Run `pacman -Syu`, let it complete; +3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-qt6-base` +4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` +5. Run `cd shadPS4` +6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` +7. Run `cmake --build build` +8. To run the finished product, run `./build/shadPS4.exe` + +## Note on MSYS2 builds + +These builds may not be easily copyable to people who do not also have a MSYS2 installation. +If you want to distribute these builds, you need to copy over the correct DLLs into a distribution folder. +In order to run them, you must be within the MSYS2 shell environment. \ No newline at end of file From 34a1339a2ba2e42e02d183a4374906c9ff1295ff Mon Sep 17 00:00:00 2001 From: jdp_ <42700985+jdpatdiscord@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:26:35 -0400 Subject: [PATCH 002/147] Allow builds on MSYS2 & improve Windows build steps documentation --- CMakeLists.txt | 25 ++++++++++-- documents/building-windows.md | 76 ++++++++++++++++++++++++++++++----- 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 679325ec8..7337d18b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -643,23 +643,40 @@ if (ENABLE_QT_GUI) endif() if (WIN32) - target_link_libraries(shadps4 PRIVATE mincore winpthreads clang_rt.builtins-x86_64.lib) - add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) + target_link_libraries(shadps4 PRIVATE mincore winpthreads) + + if (MSVC) + # MSVC likes putting opinions on what people can use, disable: + add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) + endif() + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) + if (MSVC) # Needed for conflicts with time.h of windows.h add_definitions(-D_TIMESPEC_DEFINED) endif() + # Target Windows 10 RS5 add_definitions(-DNTDDI_VERSION=0x0A000006 -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00) - # Increase stack commit area - target_link_options(shadps4 PRIVATE /STACK:0x200000,0x200000) + + if (MSVC) + target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib) + endif() + # Disable ASLR so we can reserve the user area if (MSVC) target_link_options(shadps4 PRIVATE /DYNAMICBASE:NO) else() target_link_options(shadps4 PRIVATE -Wl,--disable-dynamicbase) endif() + + # Increase stack commit area (Needed, otherwise there are crashes) + if (MSVC) + target_link_options(shadps4 PRIVATE /STACK:0x200000,0x200000) + else() + target_link_options(shadps4 PRIVATE -Wl,--stack,2097152) + endif() endif() if (WIN32) diff --git a/documents/building-windows.md b/documents/building-windows.md index e00ed90d9..684e5fe95 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -5,21 +5,77 @@ SPDX-License-Identifier: GPL-2.0-or-later # Build shadPS4 for Windows -## Download Visual Studio Community 2022 +This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation. +If you are building to contribute to the project, please omit `--depth 1` from the git invokations. -Download link: [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/) +Note: **ARM64 is not supported!** As of writing, it will not build nor run. The instructions with respect to ARM64 are for developers only. -## Requirements +## Option 1: Visual Studio 2022 -### From Visual Studio Community +### (Prerequisite) Download the Community edition from [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/) -- Desktop development with C++ +Once you are within the installer: +1. Select `Desktop development with C++` +2. Go to "Individual Components" tab +3. Make sure `C++ Clang Compiler for Windows`, `MSBuild support for LLVM` and `C++ CMake Tools for Windows` are selected +4. Continue the installation -### From individual components tab install +### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html) -- C++ Clang Compiler for Windows (17.0.3) -- MSBuild support for LLVM (Clang-cl) toolset +Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead. -- ## Compiling +1. Select Qt for Visual Studio plugin +2. Select `msvc2019_64` option or similar. If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `msvc2019_arm64` -- Open Visual Studio Community and select the **x64-Clang-Release**, **x64-Clang-Debug** or **x64-Clang-RelWithDebInfo**. It should compile just fine. +Go through the installation normally. If you do not know what components to select, just select the newest Qt version it gives you. +If you know what you are doing, you may unselect individual components that eat up too much disk space. + +Once you are finished, you will have to configure Qt within Visual Studio: +1. Tools -> Options -> Qt -> Versions +2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.1\msvc2019_64` +3. Enable the default checkmark on the new version you just created. + +### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win) + +Go through the Git for Windows installation as normal + +### Compiling with Visual Studio GUI + +1. Open Git for Windows, navigate to a place where you want to store the shadPS4 source code folder +2. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` +3. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` +4. Build -> Build All + +## Option 2: MSYS2/MinGW + +### (Prerequisite) Download [**MSYS2**](https://www.msys2.org/) + +Go through the MSYS2 installation as normal + +If you are building to distribute, please omit `-DCMAKE_CXX_FLAGS="-O2 -march=native"` within the build configuration step. + +Normal x86-based computers, follow: +1. Open "MSYS2 MINGW64" from your new applications +2. Run `pacman -Syu`, let it complete; +3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-qt6-base` +4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` +5. Run `cd shadPS4` +6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` +7. Run `cmake --build build` +8. To run the finished product, run `./build/shadPS4.exe` + +ARM64-based computers, follow: +1. Open "MSYS2 CLANGARM64" from your new applications +2. Run `pacman -Syu`, let it complete; +3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-qt6-base` +4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` +5. Run `cd shadPS4` +6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` +7. Run `cmake --build build` +8. To run the finished product, run `./build/shadPS4.exe` + +## Note on MSYS2 builds + +These builds may not be easily copyable to people who do not also have a MSYS2 installation. +If you want to distribute these builds, you need to copy over the correct DLLs into a distribution folder. +In order to run them, you must be within the MSYS2 shell environment. \ No newline at end of file From 42c4d8353a65b2dd88bb810e131b60d66a6e8d8c Mon Sep 17 00:00:00 2001 From: xezrunner <8061077+xezrunner@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:48:28 +0200 Subject: [PATCH 003/147] Fix control.sopp.simm flipping sign in CFG label generation This used to cause a fatal crash that would prevent Amplitude [CUSA02480] from booting beyond initialization. A conditional true label would get an address starting with 0xffff...., which wasn't realistic with the given shader. The multiplication by 4 causes the value to have its MSB set due to the smaller type. --- src/shader_recompiler/frontend/instruction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shader_recompiler/frontend/instruction.cpp b/src/shader_recompiler/frontend/instruction.cpp index d4847708b..756d3b4e2 100644 --- a/src/shader_recompiler/frontend/instruction.cpp +++ b/src/shader_recompiler/frontend/instruction.cpp @@ -7,7 +7,7 @@ namespace Shader::Gcn { u32 GcnInst::BranchTarget(u32 pc) const { - const s16 simm = static_cast(control.sopp.simm * 4); + const s32 simm = static_cast(control.sopp.simm) * 4; const u32 target = pc + simm + 4; return target; } From 32cb3649d31a1eceb4e8b871c205b05aa138c63b Mon Sep 17 00:00:00 2001 From: Lizardy <6063922+lzardy@users.noreply.github.com> Date: Tue, 20 Aug 2024 21:47:17 +0000 Subject: [PATCH 004/147] rtc errors (#485) * rtc errors * add system libs to cmakelists * this.[func] * fix errors * declaration * log handle addr * missed --------- Co-authored-by: microsoftv <6063922+microsoftv@users.noreply.github.com> --- CMakeLists.txt | 6 ++++++ src/core/libraries/ngs2/ngs2_impl.cpp | 23 ++++++++++++----------- src/core/libraries/ngs2/ngs2_impl.h | 2 +- src/core/libraries/rtc/rtc.cpp | 4 ++-- src/core/libraries/rtc/rtc_error.h | 17 +++++++++++++++++ 5 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 src/core/libraries/rtc/rtc_error.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 679325ec8..84a863e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,6 +193,7 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/app_content/app_content.h src/core/libraries/rtc/rtc.cpp src/core/libraries/rtc/rtc.h + src/core/libraries/rtc/rtc_error.h src/core/libraries/disc_map/disc_map.cpp src/core/libraries/disc_map/disc_map.h src/core/libraries/disc_map/disc_map_codes.h @@ -208,6 +209,11 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/avplayer/avplayer_state.h src/core/libraries/avplayer/avplayer.cpp src/core/libraries/avplayer/avplayer.h + src/core/libraries/ngs2/ngs2.cpp + src/core/libraries/ngs2/ngs2.h + src/core/libraries/ngs2/ngs2_error.h + src/core/libraries/ngs2/ngs2_impl.cpp + src/core/libraries/ngs2/ngs2_impl.h ) set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h diff --git a/src/core/libraries/ngs2/ngs2_impl.cpp b/src/core/libraries/ngs2/ngs2_impl.cpp index 185be94d7..50c62f5e4 100644 --- a/src/core/libraries/ngs2/ngs2_impl.cpp +++ b/src/core/libraries/ngs2/ngs2_impl.cpp @@ -12,22 +12,23 @@ using namespace Libraries::Kernel; namespace Libraries::Ngs2 { -s32 Ngs2::ReportInvalid(u32 handle_type) const { +s32 Ngs2::ReportInvalid(Ngs2Handle* handle, u32 handle_type) const { + uintptr_t hAddress = reinterpret_cast(handle); switch (handle_type) { case 1: - LOG_ERROR(Lib_Ngs2, "Invalid system handle {}", this); + LOG_ERROR(Lib_Ngs2, "Invalid system handle {}", hAddress); return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE; case 2: - LOG_ERROR(Lib_Ngs2, "Invalid rack handle {}", this); + LOG_ERROR(Lib_Ngs2, "Invalid rack handle {}", hAddress); return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE; case 4: - LOG_ERROR(Lib_Ngs2, "Invalid voice handle {}", this); + LOG_ERROR(Lib_Ngs2, "Invalid voice handle {}", hAddress); return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE; case 8: - LOG_ERROR(Lib_Ngs2, "Invalid report handle {}", this); + LOG_ERROR(Lib_Ngs2, "Invalid report handle {}", hAddress); return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE; default: - LOG_ERROR(Lib_Ngs2, "Invalid handle {}", this); + LOG_ERROR(Lib_Ngs2, "Invalid handle {}", hAddress); return ORBIS_NGS2_ERROR_INVALID_HANDLE; } } @@ -58,24 +59,24 @@ s32 Ngs2::HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut) { } } } - return HandleReportInvalid(handle, hType); + return this->ReportInvalid(handle, hType); } s32 Ngs2::HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut) { if (!handle) { - return HandleReportInvalid(handle, 0); + return this->ReportInvalid(handle, 0); } if (handle->selfPointer != handle || !handle->atomicPtr || !handle->dataPointer || (~hType & handle->handleType)) { - return HandleReportInvalid(handle, handle->handleType); + return this->ReportInvalid(handle, handle->handleType); } std::atomic* atomic = handle->atomicPtr; while (true) { u32 i = atomic->load(); if (i == 0) { - return HandleReportInvalid(handle, handle->handleType); + return this->ReportInvalid(handle, handle->handleType); } if (atomic->compare_exchange_strong(i, i + 1)) { break; @@ -83,7 +84,7 @@ s32 Ngs2::HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut) { } if (handleOut) { - *handleOut = handle; + handleOut = handle; } return ORBIS_OK; } diff --git a/src/core/libraries/ngs2/ngs2_impl.h b/src/core/libraries/ngs2/ngs2_impl.h index 360017799..fea87c51c 100644 --- a/src/core/libraries/ngs2/ngs2_impl.h +++ b/src/core/libraries/ngs2/ngs2_impl.h @@ -9,7 +9,7 @@ namespace Libraries::Ngs2 { class Ngs2 { public: - s32 ReportInvalid(u32 handle_type) const; + s32 ReportInvalid(Ngs2Handle* handle, u32 handle_type) const; s32 HandleSetup(Ngs2Handle* handle, void* data, std::atomic* atomic, u32 type, u32 flags); s32 HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut); s32 HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut); diff --git a/src/core/libraries/rtc/rtc.cpp b/src/core/libraries/rtc/rtc.cpp index 82e6db67e..f6faa5382 100644 --- a/src/core/libraries/rtc/rtc.cpp +++ b/src/core/libraries/rtc/rtc.cpp @@ -7,6 +7,7 @@ #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "rtc.h" +#include "rtc_error.h" namespace Libraries::Rtc { @@ -123,8 +124,7 @@ int PS4_SYSV_ABI sceRtcGetTick() { } int PS4_SYSV_ABI sceRtcGetTickResolution() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; + return 1000000; } int PS4_SYSV_ABI sceRtcGetTime_t() { diff --git a/src/core/libraries/rtc/rtc_error.h b/src/core/libraries/rtc/rtc_error.h new file mode 100644 index 000000000..04eecbbdf --- /dev/null +++ b/src/core/libraries/rtc/rtc_error.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_RTC_ERROR_INVALID_PARAMETER = 0x80010602; +constexpr int ORBIS_RTC_ERROR_INVALID_TICK_PARAMETER = 0x80010603; +constexpr int ORBIS_RTC_ERROR_INVALID_DATE_PARAMETER = 0x80010604; +constexpr int ORBIS_RTC_ERROR_NOT_IMPLEMENTED = 0x80010605; +constexpr int ORBIS_RTC_ERROR_INVALID_TIMEZONE_FORMAT = 0x80010607; +constexpr int ORBIS_RTC_ERROR_INVALID_YEARS_PARAMETER = 0x80010621; +constexpr int ORBIS_RTC_ERROR_INVALID_MONTHS_PARAMETER = 0x80010622; +constexpr int ORBIS_RTC_ERROR_INVALID_DAYS_PARAMETER = 0x80010623; +constexpr int ORBIS_RTC_ERROR_INVALID_HOURS_PARAMETER = 0x80010624; +constexpr int ORBIS_RTC_ERROR_INVALID_MINUTES_PARAMETER = 0x80010625; +constexpr int ORBIS_RTC_ERROR_INVALID_SECONDS_PARAMETER = 0x80010626; +constexpr int ORBIS_RTC_ERROR_INVALID_MILLISECONDS_PARAMETER = 0x80010627; \ No newline at end of file From 3f9c86ad33428b29a81ddcb218fbb34de072698b Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Wed, 21 Aug 2024 02:00:24 +0300 Subject: [PATCH 005/147] vk_pipeline_cache: Avoid recompiling new shaders on each new PL (#480) * cfg: Add one more divergence case * Seen in RDR shaders * renderer_vulkan: Reduce number of compiled shaders * vk_pipeline_cache: Remove some unnecessary checks --- src/core/libraries/kernel/time_management.cpp | 7 ++ .../frontend/control_flow_graph.cpp | 5 +- .../renderer_vulkan/vk_compute_pipeline.cpp | 27 +++---- .../renderer_vulkan/vk_compute_pipeline.h | 14 +++- .../renderer_vulkan/vk_graphics_pipeline.cpp | 61 ++++++++------- .../renderer_vulkan/vk_graphics_pipeline.h | 9 +-- .../renderer_vulkan/vk_pipeline_cache.cpp | 77 +++++++++++-------- .../renderer_vulkan/vk_pipeline_cache.h | 5 +- .../renderer_vulkan/vk_rasterizer.cpp | 2 +- src/video_core/texture_cache/tile_manager.cpp | 4 +- 10 files changed, 125 insertions(+), 86 deletions(-) diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index c4854937b..214f039b4 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -143,6 +143,7 @@ int PS4_SYSV_ABI sceKernelGettimeofday(OrbisKernelTimeval* tp) { return ORBIS_KERNEL_ERROR_EFAULT; } +#ifdef _WIN64 auto now = std::chrono::system_clock::now(); auto duration = now.time_since_epoch(); auto seconds = std::chrono::duration_cast(duration); @@ -150,6 +151,12 @@ int PS4_SYSV_ABI sceKernelGettimeofday(OrbisKernelTimeval* tp) { tp->tv_sec = seconds.count(); tp->tv_usec = microsecs.count(); +#else + timeval tv; + gettimeofday(&tv, nullptr); + tp->tv_sec = tv.tv_sec; + tp->tv_usec = tv.tv_usec; +#endif return ORBIS_OK; } diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp index 4f3ab86e4..3faf8665b 100644 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ b/src/shader_recompiler/frontend/control_flow_graph.cpp @@ -37,6 +37,7 @@ static IR::Condition MakeCondition(Opcode opcode) { return IR::Condition::Execnz; case Opcode::S_AND_SAVEEXEC_B64: case Opcode::S_ANDN2_B64: + case Opcode::V_CMPX_NE_U32: return IR::Condition::Execnz; default: return IR::Condition::True; @@ -93,7 +94,7 @@ void CFG::EmitDivergenceLabels() { // While this instruction does not save EXEC it is often used paired // with SAVEEXEC to mask the threads that didn't pass the condition // of initial branch. - inst.opcode == Opcode::S_ANDN2_B64; + inst.opcode == Opcode::S_ANDN2_B64 || inst.opcode == Opcode::V_CMPX_NE_U32; }; const auto is_close_scope = [](const GcnInst& inst) { // Closing an EXEC scope can be either a branch instruction @@ -187,7 +188,7 @@ void CFG::LinkBlocks() { const auto end_inst{block.end_inst}; // Handle divergence block inserted here. if (end_inst.opcode == Opcode::S_AND_SAVEEXEC_B64 || - end_inst.opcode == Opcode::S_ANDN2_B64) { + end_inst.opcode == Opcode::S_ANDN2_B64 || end_inst.opcode == Opcode::V_CMPX_NE_U32) { // Blocks are stored ordered by address in the set auto next_it = std::next(it); auto* target_block = &(*next_it); diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 62b50eeb1..81cf9c02a 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -12,18 +12,19 @@ namespace Vulkan { ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler_, - vk::PipelineCache pipeline_cache, const Shader::Info* info_, - u64 compute_key_, vk::ShaderModule module) - : instance{instance_}, scheduler{scheduler_}, compute_key{compute_key_}, info{*info_} { + vk::PipelineCache pipeline_cache, u64 compute_key_, + const Program* program) + : instance{instance_}, scheduler{scheduler_}, compute_key{compute_key_}, + info{&program->pgm.info} { const vk::PipelineShaderStageCreateInfo shader_ci = { .stage = vk::ShaderStageFlagBits::eCompute, - .module = module, + .module = program->module, .pName = "main", }; u32 binding{}; boost::container::small_vector bindings; - for (const auto& buffer : info.buffers) { + for (const auto& buffer : info->buffers) { bindings.push_back({ .binding = binding++, .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer @@ -32,7 +33,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler .stageFlags = vk::ShaderStageFlagBits::eCompute, }); } - for (const auto& image : info.images) { + for (const auto& image : info->images) { bindings.push_back({ .binding = binding++, .descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage @@ -41,7 +42,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler .stageFlags = vk::ShaderStageFlagBits::eCompute, }); } - for (const auto& sampler : info.samplers) { + for (const auto& sampler : info->samplers) { bindings.push_back({ .binding = binding++, .descriptorType = vk::DescriptorType::eSampler, @@ -96,8 +97,8 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, Shader::PushData push_data{}; u32 binding{}; - for (const auto& buffer : info.buffers) { - const auto vsharp = buffer.GetVsharp(info); + for (const auto& buffer : info->buffers) { + const auto vsharp = buffer.GetVsharp(*info); const VAddr address = vsharp.base_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 @@ -139,9 +140,9 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, }); } - for (const auto& image_desc : info.images) { + for (const auto& image_desc : info->images) { const auto tsharp = - info.ReadUd(image_desc.sgpr_base, image_desc.dword_offset); + info->ReadUd(image_desc.sgpr_base, image_desc.dword_offset); VideoCore::ImageInfo image_info{tsharp}; VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; const auto& image_view = texture_cache.FindTexture(image_info, view_info); @@ -161,8 +162,8 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (texture)"); } } - for (const auto& sampler : info.samplers) { - const auto ssharp = sampler.GetSsharp(info); + for (const auto& sampler : info->samplers) { + const auto ssharp = sampler.GetSsharp(*info); const auto vk_sampler = texture_cache.GetSampler(ssharp); image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); set_writes.push_back({ diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 16de5635f..5da9dc7e7 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h @@ -3,6 +3,7 @@ #pragma once +#include "shader_recompiler/ir/program.h" #include "shader_recompiler/runtime_info.h" #include "video_core/renderer_vulkan/vk_common.h" @@ -16,11 +17,18 @@ namespace Vulkan { class Instance; class Scheduler; +struct Program { + Shader::IR::Program pgm; + std::vector spv; + vk::ShaderModule module; + u32 end_binding; +}; + class ComputePipeline { public: explicit ComputePipeline(const Instance& instance, Scheduler& scheduler, - vk::PipelineCache pipeline_cache, const Shader::Info* info, - u64 compute_key, vk::ShaderModule module); + vk::PipelineCache pipeline_cache, u64 compute_key, + const Program* program); ~ComputePipeline(); [[nodiscard]] vk::Pipeline Handle() const noexcept { @@ -37,7 +45,7 @@ private: vk::UniquePipelineLayout pipeline_layout; vk::UniqueDescriptorSetLayout desc_layout; u64 compute_key; - Shader::Info info{}; + const Shader::Info* info; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 04486290e..887a6d871 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -19,15 +19,14 @@ namespace Vulkan { GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& scheduler_, const GraphicsPipelineKey& key_, vk::PipelineCache pipeline_cache, - std::span infos, - std::array modules) + std::span programs) : instance{instance_}, scheduler{scheduler_}, key{key_} { const vk::Device device = instance.GetDevice(); for (u32 i = 0; i < MaxShaderStages; i++) { - if (!infos[i]) { + if (!programs[i]) { continue; } - stages[i] = *infos[i]; + stages[i] = &programs[i]->pgm.info; } BuildDescSetLayout(); @@ -49,14 +48,14 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul boost::container::static_vector bindings; boost::container::static_vector attributes; const auto& vs_info = stages[u32(Shader::Stage::Vertex)]; - for (const auto& input : vs_info.vs_inputs) { + for (const auto& input : vs_info->vs_inputs) { if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { // Skip attribute binding as the data will be pulled by shader continue; } - const auto buffer = vs_info.ReadUd(input.sgpr_base, input.dword_offset); + const auto buffer = vs_info->ReadUd(input.sgpr_base, input.dword_offset); attributes.push_back({ .location = input.binding, .binding = input.binding, @@ -192,21 +191,21 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul .maxDepthBounds = key.depth_bounds_max, }; - u32 shader_count{}; auto stage = u32(Shader::Stage::Vertex); - std::array shader_stages; - shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{ + boost::container::static_vector + shader_stages; + shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ .stage = vk::ShaderStageFlagBits::eVertex, - .module = modules[stage], + .module = programs[stage]->module, .pName = "main", - }; + }); stage = u32(Shader::Stage::Fragment); - if (modules[stage]) { - shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{ + if (programs[stage]) { + shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ .stage = vk::ShaderStageFlagBits::eFragment, - .module = modules[stage], + .module = programs[stage]->module, .pName = "main", - }; + }); } const auto it = std::ranges::find(key.color_formats, vk::Format::eUndefined); @@ -280,7 +279,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul const vk::GraphicsPipelineCreateInfo pipeline_info = { .pNext = &pipeline_rendering_ci, - .stageCount = shader_count, + .stageCount = static_cast(shader_stages.size()), .pStages = shader_stages.data(), .pVertexInputState = &vertex_input_info, .pInputAssemblyState = &input_assembly, @@ -306,8 +305,11 @@ GraphicsPipeline::~GraphicsPipeline() = default; void GraphicsPipeline::BuildDescSetLayout() { u32 binding{}; boost::container::small_vector bindings; - for (const auto& stage : stages) { - for (const auto& buffer : stage.buffers) { + for (const auto* stage : stages) { + if (!stage) { + continue; + } + for (const auto& buffer : stage->buffers) { bindings.push_back({ .binding = binding++, .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer @@ -316,7 +318,7 @@ void GraphicsPipeline::BuildDescSetLayout() { .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, }); } - for (const auto& image : stage.images) { + for (const auto& image : stage->images) { bindings.push_back({ .binding = binding++, .descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage @@ -325,7 +327,7 @@ void GraphicsPipeline::BuildDescSetLayout() { .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, }); } - for (const auto& sampler : stage.samplers) { + for (const auto& sampler : stage->samplers) { bindings.push_back({ .binding = binding++, .descriptorType = vk::DescriptorType::eSampler, @@ -352,13 +354,16 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, Shader::PushData push_data{}; u32 binding{}; - for (const auto& stage : stages) { - if (stage.uses_step_rates) { + for (const auto* stage : stages) { + if (!stage) { + continue; + } + if (stage->uses_step_rates) { push_data.step0 = regs.vgt_instance_step_rate_0; push_data.step1 = regs.vgt_instance_step_rate_1; } - for (const auto& buffer : stage.buffers) { - const auto vsharp = buffer.GetVsharp(stage); + for (const auto& buffer : stage->buffers) { + const auto vsharp = buffer.GetVsharp(*stage); if (vsharp) { const VAddr address = vsharp.base_address; if (texture_cache.IsMeta(address)) { @@ -391,9 +396,9 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, } boost::container::static_vector tsharps; - for (const auto& image_desc : stage.images) { + for (const auto& image_desc : stage->images) { const auto& tsharp = tsharps.emplace_back( - stage.ReadUd(image_desc.sgpr_base, image_desc.dword_offset)); + stage->ReadUd(image_desc.sgpr_base, image_desc.dword_offset)); VideoCore::ImageInfo image_info{tsharp}; VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; const auto& image_view = texture_cache.FindTexture(image_info, view_info); @@ -413,8 +418,8 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (texture)"); } } - for (const auto& sampler : stage.samplers) { - auto ssharp = sampler.GetSsharp(stage); + for (const auto& sampler : stage->samplers) { + auto ssharp = sampler.GetSsharp(*stage); if (sampler.disable_aniso) { const auto& tsharp = tsharps[sampler.associated_image]; if (tsharp.base_level == 0 && tsharp.last_level == 0) { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index bc8e9913c..f7ea32d95 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -3,9 +3,9 @@ #include #include "common/types.h" -#include "shader_recompiler/runtime_info.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_common.h" +#include "video_core/renderer_vulkan/vk_compute_pipeline.h" namespace VideoCore { class BufferCache; @@ -58,8 +58,7 @@ class GraphicsPipeline { public: explicit GraphicsPipeline(const Instance& instance, Scheduler& scheduler, const GraphicsPipelineKey& key, vk::PipelineCache pipeline_cache, - std::span infos, - std::array modules); + std::span programs); ~GraphicsPipeline(); void BindResources(const Liverpool::Regs& regs, VideoCore::BufferCache& buffer_cache, @@ -74,7 +73,7 @@ public: } const Shader::Info& GetStage(Shader::Stage stage) const noexcept { - return stages[u32(stage)]; + return *stages[u32(stage)]; } bool IsEmbeddedVs() const noexcept { @@ -99,7 +98,7 @@ private: vk::UniquePipeline pipeline; vk::UniquePipelineLayout pipeline_layout; vk::UniqueDescriptorSetLayout desc_layout; - std::array stages{}; + std::array stages{}; GraphicsPipelineKey key; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index c11705e7c..617a78125 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -20,6 +20,10 @@ namespace Vulkan { using Shader::VsOutput; +[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) { + return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)); +} + void BuildVsOutputs(Shader::Info& info, const AmdGpu::Liverpool::VsOutputControl& ctl) { const auto add_output = [&](VsOutput x, VsOutput y, VsOutput z, VsOutput w) { if (x != VsOutput::None || y != VsOutput::None || z != VsOutput::None || @@ -246,23 +250,14 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline() { } u32 binding{}; - std::array programs; - std::array infos{}; - for (u32 i = 0; i < MaxShaderStages; i++) { if (!graphics_key.stage_hashes[i]) { - stages[i] = VK_NULL_HANDLE; + programs[i] = nullptr; continue; } auto* pgm = regs.ProgramForStage(i); const auto code = pgm->Code(); - const auto it = module_map.find(graphics_key.stage_hashes[i]); - if (it != module_map.end()) { - stages[i] = *it->second; - continue; - } - // Dump shader code if requested. const auto stage = Shader::Stage{i}; const u64 hash = graphics_key.stage_hashes[i]; @@ -273,39 +268,56 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline() { block_pool.ReleaseContents(); inst_pool.ReleaseContents(); - if (stage != Shader::Stage::Compute && stage != Shader::Stage::Fragment && - stage != Shader::Stage::Vertex) { + if (stage != Shader::Stage::Fragment && stage != Shader::Stage::Vertex) { LOG_ERROR(Render_Vulkan, "Unsupported shader stage {}. PL creation skipped.", stage); return {}; } + const u64 lookup_hash = HashCombine(hash, binding); + auto it = program_cache.find(lookup_hash); + if (it != program_cache.end()) { + const Program* program = it.value().get(); + ASSERT(program->pgm.info.stage == stage); + programs[i] = program; + binding = program->end_binding; + continue; + } + // Recompile shader to IR. try { + auto program = std::make_unique(); + block_pool.ReleaseContents(); + inst_pool.ReleaseContents(); + LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x}", stage, hash); Shader::Info info = MakeShaderInfo(stage, pgm->user_data, regs); info.pgm_base = pgm->Address(); info.pgm_hash = hash; - programs[i] = + program->pgm = Shader::TranslateProgram(inst_pool, block_pool, code, std::move(info), profile); // Compile IR to SPIR-V - auto spv_code = Shader::Backend::SPIRV::EmitSPIRV(profile, programs[i], binding); + program->spv = Shader::Backend::SPIRV::EmitSPIRV(profile, program->pgm, binding); if (Config::dumpShaders()) { - DumpShader(spv_code, hash, stage, "spv"); + DumpShader(program->spv, hash, stage, "spv"); } - stages[i] = CompileSPV(spv_code, instance.GetDevice()); - infos[i] = &programs[i].info; + + // Compile module and set name to hash in renderdoc + program->end_binding = binding; + program->module = CompileSPV(program->spv, instance.GetDevice()); + const auto name = fmt::format("{}_{:#x}", stage, hash); + Vulkan::SetObjectName(instance.GetDevice(), program->module, name); + + // Cache program + const auto [it, _] = program_cache.emplace(lookup_hash, std::move(program)); + programs[i] = it.value().get(); } catch (const Shader::Exception& e) { UNREACHABLE_MSG("{}", e.what()); } - - // Set module name to hash in renderdoc - const auto name = fmt::format("{}_{:#x}", stage, hash); - Vulkan::SetObjectName(instance.GetDevice(), stages[i], name); } return std::make_unique(instance, scheduler, graphics_key, *pipeline_cache, - infos, stages); + programs); } std::unique_ptr PipelineCache::CreateComputePipeline() { @@ -322,26 +334,31 @@ std::unique_ptr PipelineCache::CreateComputePipeline() { // Recompile shader to IR. try { + auto program = std::make_unique(); LOG_INFO(Render_Vulkan, "Compiling cs shader {:#x}", compute_key); Shader::Info info = MakeShaderInfo(Shader::Stage::Compute, cs_pgm.user_data, liverpool->regs); info.pgm_base = cs_pgm.Address(); info.pgm_hash = compute_key; - auto program = + program->pgm = Shader::TranslateProgram(inst_pool, block_pool, code, std::move(info), profile); // Compile IR to SPIR-V u32 binding{}; - const auto spv_code = Shader::Backend::SPIRV::EmitSPIRV(profile, program, binding); + program->spv = Shader::Backend::SPIRV::EmitSPIRV(profile, program->pgm, binding); if (Config::dumpShaders()) { - DumpShader(spv_code, compute_key, Shader::Stage::Compute, "spv"); + DumpShader(program->spv, compute_key, Shader::Stage::Compute, "spv"); } - const auto module = CompileSPV(spv_code, instance.GetDevice()); - // Set module name to hash in renderdoc + + // Compile module and set name to hash in renderdoc + program->module = CompileSPV(program->spv, instance.GetDevice()); const auto name = fmt::format("cs_{:#x}", compute_key); - Vulkan::SetObjectName(instance.GetDevice(), module, name); - return std::make_unique(instance, scheduler, *pipeline_cache, - &program.info, compute_key, module); + Vulkan::SetObjectName(instance.GetDevice(), program->module, name); + + // Cache program + const auto [it, _] = program_cache.emplace(compute_key, std::move(program)); + return std::make_unique(instance, scheduler, *pipeline_cache, compute_key, + it.value().get()); } catch (const Shader::Exception& e) { UNREACHABLE_MSG("{}", e.what()); return nullptr; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index d41723ec8..8f3b806cb 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -5,6 +5,7 @@ #include #include "shader_recompiler/ir/basic_block.h" +#include "shader_recompiler/ir/program.h" #include "shader_recompiler/profile.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" @@ -43,10 +44,10 @@ private: AmdGpu::Liverpool* liverpool; vk::UniquePipelineCache pipeline_cache; vk::UniquePipelineLayout pipeline_layout; - tsl::robin_map module_map; - std::array stages{}; + tsl::robin_map> program_cache; tsl::robin_map> compute_pipelines; tsl::robin_map> graphics_pipelines; + std::array programs{}; Shader::Profile profile{}; GraphicsPipelineKey graphics_key{}; u64 compute_key{}; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 542624a0e..9ec8fe218 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -153,7 +153,7 @@ void Rasterizer::BeginRendering() { }; texture_cache.TouchMeta(htile_address, false); state.has_depth = true; - state.has_stencil = image.info.usage.stencil; + state.has_stencil = regs.depth_control.stencil_enable; } scheduler.BeginRendering(state); } diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index f08f2094c..6bb104a66 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -249,11 +249,11 @@ struct DetilerParams { u32 sizes[14]; }; -static constexpr size_t StreamBufferSize = 128_MB; +static constexpr size_t StreamBufferSize = 1_GB; TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler) : instance{instance}, scheduler{scheduler}, - stream_buffer{instance, scheduler, MemoryUsage::Stream, StreamBufferSize} { + stream_buffer{instance, scheduler, MemoryUsage::Upload, StreamBufferSize} { static const std::array detiler_shaders{ HostShaders::DETILE_M8X1_COMP, HostShaders::DETILE_M8X2_COMP, HostShaders::DETILE_M32X1_COMP, HostShaders::DETILE_M32X2_COMP, From 6596fe091c3e69e206b277b4adfd5c177eec5f56 Mon Sep 17 00:00:00 2001 From: Borchev <4501931+Borchev@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:10:38 -0700 Subject: [PATCH 006/147] Workaround for readonly memory mapping of files issue --- src/common/io_file.cpp | 5 ++--- src/core/address_space.cpp | 28 +++++++++++++++++++++------- src/core/address_space.h | 2 +- src/core/memory.cpp | 3 ++- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp index e1c22d2a1..fbc37a10c 100644 --- a/src/common/io_file.cpp +++ b/src/common/io_file.cpp @@ -217,7 +217,7 @@ void IOFile::Close() { file = nullptr; #ifdef _WIN64 - if (file_mapping) { + if (file_mapping && file_access_mode == FileAccessMode::ReadWrite) { CloseHandle(std::bit_cast(file_mapping)); } #endif @@ -259,8 +259,7 @@ uintptr_t IOFile::GetFileMapping() { mapping = CreateFileMapping2(hfile, NULL, FILE_MAP_WRITE, PAGE_READWRITE, SEC_COMMIT, 0, NULL, NULL, 0); } else { - mapping = CreateFileMapping2(hfile, NULL, FILE_MAP_READ, PAGE_READONLY, SEC_COMMIT, 0, NULL, - NULL, 0); + mapping = hfile; } file_mapping = std::bit_cast(mapping); diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index 77d021a6e..6444790fe 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/alignment.h" #include "common/assert.h" #include "common/error.h" #include "core/address_space.h" @@ -129,9 +130,10 @@ struct AddressSpace::Impl { } void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, uintptr_t fd = 0) { + const size_t aligned_size = Common::AlignUp(size, 16_KB); const auto it = placeholders.find(virtual_addr); ASSERT_MSG(it != placeholders.end(), "Cannot map already mapped region"); - ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + size <= it->upper(), + ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + aligned_size <= it->upper(), "Map range must be fully contained in a placeholder"); // Windows only allows splitting a placeholder into two. @@ -140,7 +142,7 @@ struct AddressSpace::Impl { // one at the start and at the end. const VAddr placeholder_start = it->lower(); const VAddr placeholder_end = it->upper(); - const VAddr virtual_end = virtual_addr + size; + const VAddr virtual_end = virtual_addr + aligned_size; // If the placeholder doesn't exactly start at virtual_addr, split it at the start. if (placeholder_start != virtual_addr) { @@ -161,11 +163,23 @@ struct AddressSpace::Impl { void* ptr = nullptr; if (phys_addr != -1) { HANDLE backing = fd ? reinterpret_cast(fd) : backing_handle; - ptr = MapViewOfFile3(backing, process, reinterpret_cast(virtual_addr), phys_addr, - size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0); + if (fd && prot == PAGE_READONLY) { + DWORD resultvar; + ptr = VirtualAlloc2(process, reinterpret_cast(virtual_addr), aligned_size, + MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, + PAGE_READWRITE, nullptr, 0); + bool ret = ReadFile(backing, ptr, size, &resultvar, NULL); + ASSERT_MSG(ret, "ReadFile failed. {}", Common::GetLastErrorMsg()); + ret = VirtualProtect(ptr, size, prot, &resultvar); + ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg()); + } else { + ptr = MapViewOfFile3(backing, process, reinterpret_cast(virtual_addr), + phys_addr, aligned_size, MEM_REPLACE_PLACEHOLDER, prot, + nullptr, 0); + } } else { ptr = - VirtualAlloc2(process, reinterpret_cast(virtual_addr), size, + VirtualAlloc2(process, reinterpret_cast(virtual_addr), aligned_size, MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0); } ASSERT_MSG(ptr, "{}", Common::GetLastErrorMsg()); @@ -455,12 +469,12 @@ void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, u32 } void AddressSpace::Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VAddr end_in_vma, - PAddr phys_base, bool is_exec, bool has_backing) { + PAddr phys_base, bool is_exec, bool has_backing, bool readonly) { #ifdef _WIN32 // There does not appear to be comparable support for partial unmapping on Windows. // Unfortunately, a least one title was found to require this. The workaround is to unmap // the entire allocation and remap the portions outside of the requested unmapping range. - impl->Unmap(virtual_addr, size, has_backing); + impl->Unmap(virtual_addr, size, has_backing && !readonly); // TODO: Determine if any titles require partial unmapping support for flexible allocations. ASSERT_MSG(has_backing || (start_in_vma == 0 && end_in_vma == size), diff --git a/src/core/address_space.h b/src/core/address_space.h index 53041bccb..dc38de4d0 100644 --- a/src/core/address_space.h +++ b/src/core/address_space.h @@ -92,7 +92,7 @@ public: /// Unmaps specified virtual memory area. void Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VAddr end_in_vma, - PAddr phys_base, bool is_exec, bool has_backing); + PAddr phys_base, bool is_exec, bool has_backing, bool readonly); void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 6d0d581f9..6c3b50058 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -242,10 +242,11 @@ void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { vma.disallow_merge = false; vma.name = ""; MergeAdjacent(vma_map, new_it); + bool readonly = vma.prot == MemoryProt::CpuRead; // Unmap the memory region. impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base, is_exec, - has_backing); + has_backing, readonly); TRACK_FREE(virtual_addr, "VMEM"); } From fc300b526561a2d57cb69a4442c24d4c532bb4cc Mon Sep 17 00:00:00 2001 From: Borchev <4501931+Borchev@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:07:32 -0700 Subject: [PATCH 007/147] Fix unmapping bug --- src/core/address_space.cpp | 4 ++-- src/core/address_space.h | 2 +- src/core/memory.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index 6444790fe..235113700 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -469,12 +469,12 @@ void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, u32 } void AddressSpace::Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VAddr end_in_vma, - PAddr phys_base, bool is_exec, bool has_backing, bool readonly) { + PAddr phys_base, bool is_exec, bool has_backing, bool readonly_file) { #ifdef _WIN32 // There does not appear to be comparable support for partial unmapping on Windows. // Unfortunately, a least one title was found to require this. The workaround is to unmap // the entire allocation and remap the portions outside of the requested unmapping range. - impl->Unmap(virtual_addr, size, has_backing && !readonly); + impl->Unmap(virtual_addr, size, has_backing && !readonly_file); // TODO: Determine if any titles require partial unmapping support for flexible allocations. ASSERT_MSG(has_backing || (start_in_vma == 0 && end_in_vma == size), diff --git a/src/core/address_space.h b/src/core/address_space.h index dc38de4d0..2a3488d57 100644 --- a/src/core/address_space.h +++ b/src/core/address_space.h @@ -92,7 +92,7 @@ public: /// Unmaps specified virtual memory area. void Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VAddr end_in_vma, - PAddr phys_base, bool is_exec, bool has_backing, bool readonly); + PAddr phys_base, bool is_exec, bool has_backing, bool readonly_file); void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 6c3b50058..552c4039c 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -242,11 +242,11 @@ void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { vma.disallow_merge = false; vma.name = ""; MergeAdjacent(vma_map, new_it); - bool readonly = vma.prot == MemoryProt::CpuRead; + bool readonly_file = vma.prot == MemoryProt::CpuRead && type == VMAType::File; // Unmap the memory region. impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base, is_exec, - has_backing, readonly); + has_backing, readonly_file); TRACK_FREE(virtual_addr, "VMEM"); } From 9275b0966e65c707cfc522d74eb1e36abd6c9af3 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 21 Aug 2024 03:06:10 -0700 Subject: [PATCH 008/147] Untranslocate app bundle path if needed on macOS. --- src/common/path_util.cpp | 50 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index c1e8a5c0a..d69f72163 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -8,6 +8,7 @@ #ifdef __APPLE__ #include +#include #include #endif @@ -26,23 +27,52 @@ namespace Common::FS { namespace fs = std::filesystem; #ifdef __APPLE__ +using IsTranslocatedURLFunc = Boolean (*)(CFURLRef path, bool* isTranslocated, + CFErrorRef* __nullable error); +using CreateOriginalPathForURLFunc = CFURLRef __nullable (*)(CFURLRef translocatedPath, + CFErrorRef* __nullable error); + +static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) { + if (void* security_handle = + dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY)) { + SCOPE_EXIT { + dlclose(security_handle); + }; + + const auto IsTranslocatedURL = reinterpret_cast( + dlsym(security_handle, "SecTranslocateIsTranslocatedURL")); + const auto CreateOriginalPathForURL = reinterpret_cast( + dlsym(security_handle, "SecTranslocateCreateOriginalPathForURL")); + + bool is_translocated = false; + if (IsTranslocatedURL && CreateOriginalPathForURL && + IsTranslocatedURL(bundle_path, &is_translocated, nullptr) && is_translocated) { + return CreateOriginalPathForURL(bundle_path, nullptr); + } + } + return nullptr; +} + static std::filesystem::path GetBundleParentDirectory() { if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) { if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) { SCOPE_EXIT { CFRelease(bundle_url_ref); }; - if (CFStringRef bundle_path_ref = - CFURLCopyFileSystemPath(bundle_url_ref, kCFURLPOSIXPathStyle)) { - SCOPE_EXIT { - CFRelease(bundle_path_ref); - }; - char app_bundle_path[MAXPATHLEN]; - if (CFStringGetFileSystemRepresentation(bundle_path_ref, app_bundle_path, - sizeof(app_bundle_path))) { - std::filesystem::path bundle_path{app_bundle_path}; - return bundle_path.parent_path(); + + CFURLRef untranslocated_url_ref = UntranslocateBundlePath(bundle_url_ref); + SCOPE_EXIT { + if (untranslocated_url_ref) { + CFRelease(untranslocated_url_ref); } + }; + + char app_bundle_path[MAXPATHLEN]; + if (CFURLGetFileSystemRepresentation( + untranslocated_url_ref ? untranslocated_url_ref : bundle_url_ref, true, + reinterpret_cast(app_bundle_path), sizeof(app_bundle_path))) { + std::filesystem::path bundle_path{app_bundle_path}; + return bundle_path.parent_path(); } } } From 6d0d2eaa59c7947044ee486cdd27358f61adebe1 Mon Sep 17 00:00:00 2001 From: Dzmitry Dubrova Date: Wed, 21 Aug 2024 14:37:34 +0300 Subject: [PATCH 009/147] avplayer: Fix sceAvPlayerGetAudioData --- src/core/libraries/avplayer/avplayer_source.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index 776d389f0..e05a2cdf4 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -359,6 +359,7 @@ bool AvPlayerSource::GetAudioData(SceAvPlayerFrameInfo& audio_info) { audio_info = {}; audio_info.timestamp = frame->info.timestamp; audio_info.pData = reinterpret_cast(frame->info.pData); + audio_info.details.audio.sample_rate = frame->info.details.audio.sample_rate; audio_info.details.audio.size = frame->info.details.audio.size; audio_info.details.audio.channel_count = frame->info.details.audio.channel_count; return true; @@ -655,6 +656,7 @@ Frame AvPlayerSource::PrepareAudioFrame(FrameBuffer buffer, const AVFrame& frame .audio = { .channel_count = u16(frame.ch_layout.nb_channels), + .sample_rate = u32(frame.sample_rate), .size = u32(size), }, }, From ba0a6ab03818f14b10b2aa7e87c858a08de7c968 Mon Sep 17 00:00:00 2001 From: Sebastian Kassai <8061077+xezrunner@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:13:06 +0200 Subject: [PATCH 010/147] Expand documentation on configuration and debugging (#513) * documents: more info on config.toml * documents: add Debugging * documents: link to Debugging in README * documents: link to main branch for Debugging Once it's merged, it should link properly. Quickstart already exists in main. * documents: remove "troubleshooting" from Debugging Not entirely relevant. * documents: elaborate on a few points with stack traces * documents: formatting, indentation fixup * documents: remove unnecessary indent * documents: fix some inline code blocks + misc * documents: move the technical jargon out of Quickstart * documents: improve configuration sections Simplified the Quickstart config listing, added more technical info to the Debugging listing. * documents: link quickstart config link to proper section * documents: something ate my hash symbol * documents: use *:Critical for log silencing example * documents: add note about Start Without Debugging * documents: use correct CUSA code in example --- README.md | 4 + documents/Debugging/Debugging.md | 151 +++++++++++++++++++++++++++++ documents/Quickstart/Quickstart.md | 22 ++++- 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 documents/Debugging/Debugging.md diff --git a/README.md b/README.md index 7089b3c01..542acca9e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,10 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad |macOS Qt Build|[![macOS-qt](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos-qt.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos-qt.yml) +# Debugging and reporting issues + +For more information on how to test, debug and report issues with the emulator or games, read the [Debugging documentation](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md). + # Keyboard Mapping | Controller button | Keyboard | diff --git a/documents/Debugging/Debugging.md b/documents/Debugging/Debugging.md new file mode 100644 index 000000000..5e207b52e --- /dev/null +++ b/documents/Debugging/Debugging.md @@ -0,0 +1,151 @@ +# Debugging and reporting issues about shadPS4 and games + +This document covers information about debugging, troubleshooting and reporting developer-side issues related to shadPS4 and games. + +## Setup + +This section will guide you through setting up tools for debugging the emulator. This list will likely expand as more tools and platforms receive consistent setups. + +
+Windows and Visual Studio + +Make sure you have the project set up for building on Windows with Visual Studio and CMake: [Build shadPS4 for Windows +](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md) + +1. Open the project folder in Visual Studio **as a folder**. _Do not run `cmake ..` or other commands that set up the project._ + +2. In the Solution Explorer, click the **Switch between solutions and available views** button.\ + ![image](https://github.com/user-attachments/assets/4e2be2b1-ba5a-4451-9ab2-f4ecf246213d) + +3. Double-click on **CMake Targets View**.\ + ![image](https://github.com/user-attachments/assets/5ce7cf90-cd61-4cfa-bef5-645909827290) + +4. Under **shadPS4 Project**, right-click on the **shadps4 (executable)** solution and click **Set as Startup Item**. This will let you start and debug shadPS4 using the VS debug buttons, as well as the default F5 shortcut.\ + ![image](https://github.com/user-attachments/assets/34c7c047-28a3-499f-be8f-df781134d104) + +5. Right-click the **shadps4 (executable)** solution once more and click **Add debug configuration**. + +6. Add an `"args: []"` section into the first `configurations` entry.\ + List your game path as an argument, as if you were launching the non-GUI emulator from the command line. + ![image](https://github.com/user-attachments/assets/8c7c3e69-f38f-4d6b-bdfd-4f1c41c50be7) + +7. Set the appropriate CMake configuration for debugging or testing. + - For debugging the emulator and games within it, select `x64-Clang-Debug`. + - For testing the emulator with compiler optimizations as a release build, it is recommended to select `x64-Clang-RelWithDebInfo`, + as debug symbols will still be generated in case you encounter release configuration-exclusive bugs/errors. + ![image](https://github.com/user-attachments/assets/0d975f7a-7bea-4f89-87ef-5d685bea4381) + +Launch and debug the emulator through **Debug > Start Debugging** (F5 by default), or **Debug > Start Without Debugging** (Ctrl+F5 by default) when testing games for performance. + +
+ +## Configuration + +You can configure the emulator by editing the `config.toml` file found in the `user` folder created after starting the application. + +
+ Some configuration entries worth changing + +- `[General]` + + - `logType`: Configures logging synchronization (`sync`/`async`) + - By default, the emulator logs messages asynchronously for better performance. Some log messages may end up being received out-of-order. + - It can be beneficial to set this to `sync` in order for the log to accurately maintain message order, at the cost of performance. + - When communicating about issues with games and the log messages aren't clear due to potentially confusing order, set this to `sync` and send that log as well. + - `logFilter`: Sets the logging category for various logging classes. + - Format: `: ...` + - Multiple classes can be set by separating them with a space. (example: `Render:Warning Debug:Critical Lib.Pad:Error`) + - Sub-classes can be specified in the same format as seen in the console/log (such as `Core.Linker`). + - All classes and sub-classes can be set by specifying a `*` symbol. (example: `Kernel.*:Critical`) + - Valid log levels: `Trace, Debug, Info, Warning, Error, Critical` - in this order, setting a level silences all levels preceding it and logs every level after it. + - Examples: + - If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages. + - If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Critical Render.Vulkan:Info` + + - `Fullscreen`: Display the game in a full screen borderless window. + +- `[GPU]` + - `dumpShaders`: Dump shaders that are loaded by the emulator. Dump path: `../user/shader/dumps` + - `nullGpu`: Disables rendering. + - `screenWidth` and `screenHeight`: Configures the game window width and height. + +- `[Vulkan]` + - `validation`-related settings: Use when debugging Vulkan. + - `rdocEnable`: Automatically hook RenderDoc when installed. Useful for debugging shaders and game rendering. + - `rdocMarkersEnable`: Enable automatic RenderDoc event annotation + +- `[LLE]` + - `libc`: Use LLE with `libc`. + +
+ +## Quick analysis + +This section will provide some preliminary steps to take and tips on what to do when you encounter scenarios that require debugging. + +
+When a game crashes and breaks in the debugger + +1. Analyze the log + - A console will open by default when you launch the emulator. It shows the same log messages that go into the log file found at `/user/log/shad_log.txt`. + + - It is recommended that you start analyzing the log bottom-up first: + - Are there any critical or error-level messages at the end of the log that would point to a reason for the game crashing? + - Do any of the last few messages contain information about the game loading files? + - Did the game window draw anything on-screen? + + - Continue analyzing the log from the start to see other errors (such as with initialization, memory mapping, linker errors etc.) + +2. Analyze the stack trace + - When the emulator is launched through a debugger, it will **break** when an exception or violation is encountered.\ + _(**breaking** in this context means pausing execution of the program before it continues or stops altogether. + Breaks can be intentional as well - these are set with various kinds of **breakpoints**.)_ + + - Default setups of most debuggers include a **Stack trace** window/panel that lists the functions the program has called before breaking. + + - The stack trace entries can be navigated to and will show the relevant function, as well as switch to the state that the program was in at the time of execution.\ + Use the **Locals** and **Watch** windows to investigate variables and other code in these contexts. + + 3. Identify the reason for the crash + - **Logs aren't always accurate in determining the reason for a crash.**\ + Some log entries are reported as errors but may not be fatal for the execution to stop. `Critical` entries are most likely to be the cause for crashes. + + - Pinpoint the area of the emulator where the crash occured\ + If the stack trace ends with functions that are relevant to rendering, it is safe to assume that the issue is with **rendering**.\ + Similarly, if a crash is in a library responsible for playing videos, your issue can be narrowed down to the scope of video playback in the emulator. + + - **⚠ Some crashes are intentional** + - If you identify **Access violations for writing operations** where the function is (or in cases of game libraries, _looks like_ it is) copying memory, + it most likely is an **intentional exception** meant to catch game data being written by the game. + This is used by the emulator developers to identify procedures that have to do with game data changing. + - Debugging tools usually include an option to not break on certain types of exceptions. **Exclude access violations and other intentional exceptions when debugging to skip these exceptions.** + - You can also identify such cases if the game works in Release builds of the emulator. These intentional exceptions are development-time only. + - Attempt to **Continue** and observe whether the stack trace and/or variables and registers change when you encounter exceptions. + +
+ +## Reporting and communicating about issues + +When communicating with the project about game-specific issues, specify an **uniquely identifable game name** along with its `CUSA-xxxxx` code that is specific to the region/variant of the game you're testing.\ +The version number is also important to add at least in the description, especially if you can verify that the game behaves differently across versions.\ +Accurately identifying games will help other developers that own that game recognize your issue by its title and jump in to help test and debug it. + +- Examples of good naming schemes: + - Amplitude (2016) `CUSA02480` + - Rock Band 4 (`CUSA02084`) v1.0 + - inFamous: Second Son \[`CUSA-00004`\] +- Examples of unideal naming schemes: + - _The Witness_ + - _GTA 5_ + - _Watch Dogs_ + +- If your issue is small or you aren't sure whether you have properly identified something, [join the Discord server](https://discord.gg/MyZRaBngxA) and use the #development channel + to concisely explain the issue, as well as any findings you currently have. + +- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-emu/shadps4-game-compatibility/issues) and post very short summaries of progress changes there, + (such as the game now booting into the menu or getting in-game) for organizational and status update purposes. + +- ⚠ **Do not post theoretical, unproven game-specific issues in the emulator issue tracker that you cannot verify and locate in the emulator source code as being a bug.**\ + Do, however, add information about the game you experienced the issue in, so that it can be tested in a reproducible environment. + - Good example: "_Crash in `Shader::Gcn::CFG::EmitBlocks()`, out of bounds list access_" -> _issue description shares stack trace, points to code in the repository and provides relevant information_ + - Bad example: "_Amplitude crashes on boot, access violation_" -> _issue description reiterates title, focuses on the game instead of the emulator and refuses to elaborate_ \ No newline at end of file diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md index 4c51b288a..4dd897d85 100644 --- a/documents/Quickstart/Quickstart.md +++ b/documents/Quickstart/Quickstart.md @@ -58,4 +58,24 @@ To install PKG files (game and updates), you will need the Qt application (with ## Configure the emulator -You can configure the emulator in the "user" folder (created after the first start of the application) then in the "config.toml" file. Here you can find lots of parameters to set with True or False. +You can configure the emulator by editing the `config.toml` file found in the `user` folder created after starting the application.\ +Some settings may be related to more technical development and debugging. For more information on those, see [Debugging](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration). + +Here's a list of configuration entries that are worth changing: + +- `[General]` + + - `Fullscreen`: Display the game in a full screen borderless window. + + - `logType`: Configures logging synchronization (`sync`/`async`) + - It can be beneficial to set this to `sync` in order for the log to accurately maintain message order, at the cost of performance. + - Use when sending logs to developers. See more about [reporting issues](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#reporting-and-communicating-about-issues). + - `logFilter`: Sets the logging category for various logging classes. + - Format: `: ...`, `: <*:level> ...` + - Valid log levels: `Trace, Debug, Info, Warning, Error, Critical` - in this order, setting a level silences all levels preceding it and logs every level after it. + - Examples: + - If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages. + - If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Error Render.Vulkan:Info` + +- `[GPU]` + - `screenWidth` and `screenHeight`: Configures the game window width and height. \ No newline at end of file From dfd305ff77369adf737157921526f7bf99a83d1e Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 21 Aug 2024 22:16:03 +0300 Subject: [PATCH 011/147] Update Debugging.md fixed reuse --- documents/Debugging/Debugging.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/documents/Debugging/Debugging.md b/documents/Debugging/Debugging.md index 5e207b52e..ef9aab879 100644 --- a/documents/Debugging/Debugging.md +++ b/documents/Debugging/Debugging.md @@ -1,4 +1,9 @@ -# Debugging and reporting issues about shadPS4 and games + + + # Debugging and reporting issues about shadPS4 and games This document covers information about debugging, troubleshooting and reporting developer-side issues related to shadPS4 and games. @@ -148,4 +153,4 @@ Accurately identifying games will help other developers that own that game recog - ⚠ **Do not post theoretical, unproven game-specific issues in the emulator issue tracker that you cannot verify and locate in the emulator source code as being a bug.**\ Do, however, add information about the game you experienced the issue in, so that it can be tested in a reproducible environment. - Good example: "_Crash in `Shader::Gcn::CFG::EmitBlocks()`, out of bounds list access_" -> _issue description shares stack trace, points to code in the repository and provides relevant information_ - - Bad example: "_Amplitude crashes on boot, access violation_" -> _issue description reiterates title, focuses on the game instead of the emulator and refuses to elaborate_ \ No newline at end of file + - Bad example: "_Amplitude crashes on boot, access violation_" -> _issue description reiterates title, focuses on the game instead of the emulator and refuses to elaborate_ From 79680c50c085f45bd5a4ce01f52565d9a2c175d8 Mon Sep 17 00:00:00 2001 From: Vladislav Mikhalin Date: Wed, 21 Aug 2024 23:54:23 +0300 Subject: [PATCH 012/147] Misc fixes (#517) * Misc fixes * Removed the skip for draw calls without RTs * Remove Srgb image stores to rework later --- .../libraries/avplayer/avplayer_source.cpp | 3 ++ src/core/libraries/system/msgdialog.cpp | 21 ++++++++++++-- src/video_core/amdgpu/liverpool.h | 1 + .../renderer_vulkan/liverpool_to_vk.cpp | 28 +++++++++++-------- .../renderer_vulkan/vk_graphics_pipeline.cpp | 3 +- .../renderer_vulkan/vk_graphics_pipeline.h | 1 + .../renderer_vulkan/vk_pipeline_cache.cpp | 17 ++++++++++- .../renderer_vulkan/vk_rasterizer.cpp | 15 +++++++--- .../renderer_vulkan/vk_scheduler.cpp | 13 +++++++-- src/video_core/texture_cache/image.cpp | 14 ++++++++-- 10 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index e05a2cdf4..f5479870c 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -366,6 +366,9 @@ bool AvPlayerSource::GetAudioData(SceAvPlayerFrameInfo& audio_info) { } u64 AvPlayerSource::CurrentTime() { + if (!IsActive()) { + return 0; + } using namespace std::chrono; return duration_cast(high_resolution_clock::now() - m_start_time).count(); } diff --git a/src/core/libraries/system/msgdialog.cpp b/src/core/libraries/system/msgdialog.cpp index 1c8653f50..452feec93 100644 --- a/src/core/libraries/system/msgdialog.cpp +++ b/src/core/libraries/system/msgdialog.cpp @@ -6,6 +6,8 @@ #include "core/libraries/libs.h" #include "core/libraries/system/msgdialog.h" +#include + namespace Libraries::MsgDialog { int PS4_SYSV_ABI sceMsgDialogClose() { @@ -30,9 +32,22 @@ int PS4_SYSV_ABI sceMsgDialogInitialize() { s32 PS4_SYSV_ABI sceMsgDialogOpen(const OrbisMsgDialogParam* param) { LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - OrbisMsgDialogUserMessageParam* userMsgParam = param->userMsgParam; - const char* msg = userMsgParam->msg; - printf("sceMsgDialogOpen msg : %s", msg); + switch (param->mode) { + case ORBIS_MSG_DIALOG_MODE_USER_MSG: + LOG_INFO(Lib_MsgDlg, "sceMsgDialogOpen userMsg type = %s msg = %s", + magic_enum::enum_name(param->userMsgParam->buttonType), param->userMsgParam->msg); + break; + case ORBIS_MSG_DIALOG_MODE_PROGRESS_BAR: + LOG_INFO(Lib_MsgDlg, "sceMsgDialogOpen progressBar type = %s msg = %s", + magic_enum::enum_name(param->progBarParam->barType), param->progBarParam->msg); + break; + case ORBIS_MSG_DIALOG_MODE_SYSTEM_MSG: + LOG_INFO(Lib_MsgDlg, "sceMsgDialogOpen systemMsg type: %s", + magic_enum::enum_name(param->sysMsgParam->sysMsgType)); + break; + default: + break; + } return ORBIS_OK; } diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 896927df6..595c98f56 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -848,6 +848,7 @@ struct Liverpool { u32 raw; BitField<0, 1, u32> depth_clear_enable; BitField<1, 1, u32> stencil_clear_enable; + BitField<5, 1, u32> stencil_compress_disable; BitField<6, 1, u32> depth_compress_disable; }; diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index e86d0652f..daf64a4d3 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -5,6 +5,8 @@ #include "video_core/amdgpu/pixel_format.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" +#include + namespace Vulkan::LiverpoolToVK { using DepthBuffer = Liverpool::DepthBuffer; @@ -588,6 +590,8 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, return is_vo_surface ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb; case vk::Format::eB8G8R8A8Srgb: return is_vo_surface ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb; + default: + break; } } else { if (is_vo_surface && base_format == vk::Format::eR8G8B8A8Srgb) { @@ -601,27 +605,29 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, } vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) { - if (z_format == DepthBuffer::ZFormat::Z32Float && - stencil_format == DepthBuffer::StencilFormat::Stencil8) { + using ZFormat = DepthBuffer::ZFormat; + using StencilFormat = DepthBuffer::StencilFormat; + + if (z_format == ZFormat::Z32Float && stencil_format == StencilFormat::Stencil8) { return vk::Format::eD32SfloatS8Uint; } - if (z_format == DepthBuffer::ZFormat::Z32Float && - stencil_format == DepthBuffer::StencilFormat::Invalid) { + if (z_format == ZFormat::Z32Float && stencil_format == StencilFormat::Invalid) { return vk::Format::eD32Sfloat; } - if (z_format == DepthBuffer::ZFormat::Z16 && - stencil_format == DepthBuffer::StencilFormat::Invalid) { + if (z_format == ZFormat::Z16 && stencil_format == StencilFormat::Invalid) { return vk::Format::eD16Unorm; } - if (z_format == DepthBuffer::ZFormat::Z16 && - stencil_format == DepthBuffer::StencilFormat::Stencil8) { + if (z_format == ZFormat::Z16 && stencil_format == StencilFormat::Stencil8) { return vk::Format::eD16UnormS8Uint; } - if (z_format == DepthBuffer::ZFormat::Invalid && - stencil_format == DepthBuffer::StencilFormat::Invalid) { + if (z_format == ZFormat::Invalid && stencil_format == StencilFormat::Stencil8) { + return vk::Format::eD32SfloatS8Uint; + } + if (z_format == ZFormat::Invalid && stencil_format == StencilFormat::Invalid) { return vk::Format::eUndefined; } - UNREACHABLE(); + UNREACHABLE_MSG("Unsupported depth/stencil format. depth = {} stencil = {}", + magic_enum::enum_name(z_format), magic_enum::enum_name(stencil_format)); } void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 887a6d871..c2649b96c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -214,8 +214,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul .colorAttachmentCount = num_color_formats, .pColorAttachmentFormats = key.color_formats.data(), .depthAttachmentFormat = key.depth_format, - .stencilAttachmentFormat = - key.depth.stencil_enable ? key.depth_format : vk::Format::eUndefined, + .stencilAttachmentFormat = key.stencil_format, }; std::array attachments; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index f7ea32d95..548e7d451 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -26,6 +26,7 @@ struct GraphicsPipelineKey { std::array stage_hashes; std::array color_formats; vk::Format depth_format; + vk::Format stencil_format; Liverpool::DepthControl depth; float depth_bounds_min; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 617a78125..55f04bac4 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -180,11 +180,26 @@ void PipelineCache::RefreshGraphicsKey() { key.num_samples = regs.aa_config.NumSamples(); const auto& db = regs.depth_buffer; - key.depth_format = LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format); + const auto ds_format = LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format); + + if (db.z_info.format != AmdGpu::Liverpool::DepthBuffer::ZFormat::Invalid) { + key.depth_format = ds_format; + } else { + key.depth_format = vk::Format::eUndefined; + } if (key.depth.depth_enable) { key.depth.depth_enable.Assign(key.depth_format != vk::Format::eUndefined); } + if (db.stencil_info.format != AmdGpu::Liverpool::DepthBuffer::StencilFormat::Invalid) { + key.stencil_format = key.depth_format; + } else { + key.stencil_format = vk::Format::eUndefined; + } + if (key.depth.stencil_enable) { + key.depth.stencil_enable.Assign(key.stencil_format != vk::Format::eUndefined); + } + const auto skip_cb_binding = regs.color_control.mode == AmdGpu::Liverpool::ColorControl::OperationMode::Disable; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9ec8fe218..6cd803934 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -10,6 +10,7 @@ #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/texture_cache/image_view.h" #include "video_core/texture_cache/texture_cache.h" +#include "vk_rasterizer.h" namespace Vulkan { @@ -129,8 +130,12 @@ void Rasterizer::BeginRendering() { texture_cache.TouchMeta(col_buf.CmaskAddress(), false); } - if (regs.depth_buffer.z_info.format != Liverpool::DepthBuffer::ZFormat::Invalid && - regs.depth_buffer.Address() != 0) { + using ZFormat = AmdGpu::Liverpool::DepthBuffer::ZFormat; + using StencilFormat = AmdGpu::Liverpool::DepthBuffer::StencilFormat; + if (regs.depth_buffer.Address() != 0 && + ((regs.depth_control.depth_enable && regs.depth_buffer.z_info.format != ZFormat::Invalid) || + regs.depth_control.stencil_enable && + regs.depth_buffer.stencil_info.format != StencilFormat::Invalid)) { const auto htile_address = regs.depth_htile_data_base.GetAddress(); const bool is_clear = regs.depth_render_control.depth_clear_enable || texture_cache.IsMetaCleared(htile_address); @@ -152,8 +157,10 @@ void Rasterizer::BeginRendering() { .stencil = regs.stencil_clear}}, }; texture_cache.TouchMeta(htile_address, false); - state.has_depth = true; - state.has_stencil = regs.depth_control.stencil_enable; + state.has_depth = + regs.depth_buffer.z_info.format != AmdGpu::Liverpool::DepthBuffer::ZFormat::Invalid; + state.has_stencil = regs.depth_buffer.stencil_info.format != + AmdGpu::Liverpool::DepthBuffer::StencilFormat::Invalid; } scheduler.BeginRendering(state); } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 10ee6ea62..ef0307efd 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -29,15 +29,22 @@ void Scheduler::BeginRendering(const RenderState& new_state) { is_rendering = true; render_state = new_state; + const auto witdh = + render_state.width != std::numeric_limits::max() ? render_state.width : 1; + const auto height = + render_state.height != std::numeric_limits::max() ? render_state.height : 1; + const vk::RenderingInfo rendering_info = { .renderArea = { .offset = {0, 0}, - .extent = {render_state.width, render_state.height}, + .extent = {witdh, height}, }, .layerCount = 1, .colorAttachmentCount = render_state.num_color_attachments, - .pColorAttachments = render_state.color_attachments.data(), + .pColorAttachments = render_state.num_color_attachments > 0 + ? render_state.color_attachments.data() + : nullptr, .pDepthAttachment = render_state.has_depth ? &render_state.depth_attachment : nullptr, .pStencilAttachment = render_state.has_stencil ? &render_state.depth_attachment : nullptr, }; @@ -72,7 +79,7 @@ void Scheduler::EndRendering() { }, }); } - if (render_state.has_depth) { + if (render_state.has_depth || render_state.has_stencil) { barriers.push_back(vk::ImageMemoryBarrier{ .srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite, .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index bae4b89d4..528dda55c 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -131,11 +131,19 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, usage = ImageUsageFlags(info); - if (info.pixel_format == vk::Format::eD32Sfloat) { + switch (info.pixel_format) { + case vk::Format::eD16Unorm: + case vk::Format::eD32Sfloat: + case vk::Format::eX8D24UnormPack32: aspect_mask = vk::ImageAspectFlagBits::eDepth; - } - if (info.pixel_format == vk::Format::eD32SfloatS8Uint) { + break; + case vk::Format::eD16UnormS8Uint: + case vk::Format::eD24UnormS8Uint: + case vk::Format::eD32SfloatS8Uint: aspect_mask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil; + break; + default: + break; } const vk::ImageCreateInfo image_ci = { From ca4b520272cfbbb2cd02629ad597bf53dbbc2d53 Mon Sep 17 00:00:00 2001 From: Aiden Turner Date: Wed, 21 Aug 2024 18:52:08 -0400 Subject: [PATCH 013/147] Added logging for debugging configs (#518) * added logging for config file * forgot a setting * fixed bloated settings logging. * fixed compile error --- src/emulator.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/emulator.cpp b/src/emulator.cpp index 37e227ddf..99a0fa2ab 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -52,6 +52,19 @@ Emulator::Emulator() { LOG_INFO(Loader, "Branch {}", Common::g_scm_branch); LOG_INFO(Loader, "Description {}", Common::g_scm_desc); + LOG_INFO(Config, "General isNeo: {}", Config::isNeoMode()); + LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu()); + LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders()); + LOG_INFO(Config, "GPU shouldDumpPM4: {}", Config::dumpPM4()); + LOG_INFO(Config, "GPU vblankDivider: {}", Config::vblankDiv()); + LOG_INFO(Config, "Vulkan gpuId: {}", Config::getGpuId()); + LOG_INFO(Config, "Vulkan vkValidation: {}", Config::vkValidationEnabled()); + LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled()); + LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled()); + LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled()); + LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::isMarkersEnabled()); + LOG_INFO(Config, "LLE isLibc: {}", Config::isLleLibc()); + // Defer until after logging is initialized. memory = Core::Memory::Instance(); controller = Common::Singleton::Instance(); From aed9a737d6d72cecd8e2016bb8a64ddb3f619323 Mon Sep 17 00:00:00 2001 From: Herman Semenov Date: Thu, 22 Aug 2024 02:56:01 +0300 Subject: [PATCH 014/147] Added const reference params if possible, removed less 16 size --- src/common/config.cpp | 12 ++++++------ src/common/config.h | 12 ++++++------ src/common/uint128.h | 2 +- src/core/file_format/playgo_chunk.cpp | 2 +- src/core/file_format/playgo_chunk.h | 2 +- src/core/file_format/psf.cpp | 2 +- src/core/file_format/psf.h | 2 +- src/core/libraries/avplayer/avplayer_source.cpp | 2 +- src/shader_recompiler/ir/opcodes.h | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index 24db6b039..6289e2af1 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -189,15 +189,15 @@ void setNeoMode(bool enable) { isNeo = enable; } -void setLogType(std::string type) { +void setLogType(const std::string& type) { logType = type; } -void setLogFilter(std::string type) { +void setLogFilter(const std::string& type) { logFilter = type; } -void setUserName(std::string type) { +void setUserName(const std::string& type) { userName = type; } @@ -234,15 +234,15 @@ void setMainWindowWidth(u32 width) { void setMainWindowHeight(u32 height) { m_window_size_H = height; } -void setPkgViewer(std::vector pkgList) { +void setPkgViewer(const std::vector& pkgList) { m_pkg_viewer.resize(pkgList.size()); m_pkg_viewer = pkgList; } -void setElfViewer(std::vector elfList) { +void setElfViewer(const std::vector& elfList) { m_elf_viewer.resize(elfList.size()); m_elf_viewer = elfList; } -void setRecentFiles(std::vector recentFiles) { +void setRecentFiles(const std::vector& recentFiles) { m_recent_files.resize(recentFiles.size()); m_recent_files = recentFiles; } diff --git a/src/common/config.h b/src/common/config.h index 3006f2e2a..f2b7fe09d 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -43,10 +43,10 @@ void setScreenHeight(u32 height); void setFullscreenMode(bool enable); void setLanguage(u32 language); void setNeoMode(bool enable); -void setUserName(std::string type); +void setUserName(const std::string& type); -void setLogType(std::string type); -void setLogFilter(std::string type); +void setLogType(const std::string& type); +void setLogFilter(const std::string& type); void setVkValidation(bool enable); void setVkSyncValidation(bool enable); @@ -67,9 +67,9 @@ void setSliderPositonGrid(u32 pos); void setTableMode(u32 mode); void setMainWindowWidth(u32 width); void setMainWindowHeight(u32 height); -void setPkgViewer(std::vector pkgList); -void setElfViewer(std::vector elfList); -void setRecentFiles(std::vector recentFiles); +void setPkgViewer(const std::vector& pkgList); +void setElfViewer(const std::vector& elfList); +void setRecentFiles(const std::vector& recentFiles); u32 getMainWindowGeometryX(); u32 getMainWindowGeometryY(); diff --git a/src/common/uint128.h b/src/common/uint128.h index c44357916..77c4a271d 100644 --- a/src/common/uint128.h +++ b/src/common/uint128.h @@ -94,7 +94,7 @@ namespace Common { // This function divides a u128 by a u32 value and produces two u64 values: // the result of division and the remainder -[[nodiscard]] static inline std::pair Divide128On32(u128 dividend, u32 divisor) { +[[nodiscard]] static inline std::pair Divide128On32(const u128& dividend, u32 divisor) { u64 remainder = dividend[0] % divisor; u64 accum = dividend[0] / divisor; if (dividend[1] == 0) diff --git a/src/core/file_format/playgo_chunk.cpp b/src/core/file_format/playgo_chunk.cpp index a430b1ac1..4e2faea45 100644 --- a/src/core/file_format/playgo_chunk.cpp +++ b/src/core/file_format/playgo_chunk.cpp @@ -60,7 +60,7 @@ bool PlaygoFile::LoadChunks(const Common::FS::IOFile& file) { return false; } -bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk, +bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t chunk, std::string& data) { if (file.IsOpen()) { if (file.Seek(chunk.offset)) { diff --git a/src/core/file_format/playgo_chunk.h b/src/core/file_format/playgo_chunk.h index 439e27d05..b6d38e0e1 100644 --- a/src/core/file_format/playgo_chunk.h +++ b/src/core/file_format/playgo_chunk.h @@ -123,7 +123,7 @@ public: } private: - bool load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk, std::string& data); + bool load_chunk_data(const Common::FS::IOFile& file, const chunk_t chunk, std::string& data); private: PlaygoHeader playgoHeader; diff --git a/src/core/file_format/psf.cpp b/src/core/file_format/psf.cpp index c11dc05c8..3d076acdc 100644 --- a/src/core/file_format/psf.cpp +++ b/src/core/file_format/psf.cpp @@ -9,7 +9,7 @@ PSF::PSF() = default; PSF::~PSF() = default; -bool PSF::open(const std::string& filepath, std::vector psfBuffer) { +bool PSF::open(const std::string& filepath, const std::vector& psfBuffer) { if (!psfBuffer.empty()) { psf.resize(psfBuffer.size()); psf = psfBuffer; diff --git a/src/core/file_format/psf.h b/src/core/file_format/psf.h index 17e515de2..9a162b1d5 100644 --- a/src/core/file_format/psf.h +++ b/src/core/file_format/psf.h @@ -35,7 +35,7 @@ public: PSF(); ~PSF(); - bool open(const std::string& filepath, std::vector psfBuffer); + bool open(const std::string& filepath, const std::vector& psfBuffer); std::string GetString(const std::string& key); u32 GetInteger(const std::string& key); diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index f5479870c..2fc360a0e 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -82,7 +82,7 @@ static s32 CodecTypeToStreamType(AVMediaType codec_type) { } } -static f32 AVRationalToF32(const AVRational& rational) { +static f32 AVRationalToF32(const AVRational rational) { return f32(rational.num) / rational.den; } diff --git a/src/shader_recompiler/ir/opcodes.h b/src/shader_recompiler/ir/opcodes.h index 66b602219..06f1a6117 100644 --- a/src/shader_recompiler/ir/opcodes.h +++ b/src/shader_recompiler/ir/opcodes.h @@ -101,7 +101,7 @@ struct fmt::formatter { return ctx.begin(); } template - auto format(const Shader::IR::Opcode& op, FormatContext& ctx) const { + auto format(const Shader::IR::Opcode op, FormatContext& ctx) const { return fmt::format_to(ctx.out(), "{}", Shader::IR::NameOf(op)); } }; From 12a65e3fb87473f1e15d3868b378325725bedd60 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 22 Aug 2024 11:24:31 +0300 Subject: [PATCH 015/147] LLE libc removal --- CMakeLists.txt | 16 +- src/common/config.cpp | 12 - src/common/config.h | 1 - src/core/libraries/libc/libc.cpp | 496 ---------------- src/core/libraries/libc/libc.h | 14 - src/core/libraries/libc/libc_cxa.cpp | 161 ----- src/core/libraries/libc/libc_cxa.h | 15 - src/core/libraries/libc/libc_math.cpp | 55 -- src/core/libraries/libc/libc_math.h | 21 - src/core/libraries/libc/libc_stdio.cpp | 78 --- src/core/libraries/libc/libc_stdio.h | 23 - src/core/libraries/libc/libc_stdlib.cpp | 45 -- src/core/libraries/libc/libc_stdlib.h | 19 - src/core/libraries/libc/libc_string.cpp | 61 -- src/core/libraries/libc/libc_string.h | 24 - src/core/libraries/libc/printf.h | 753 ------------------------ src/core/libraries/libc/va_ctx.h | 110 ---- src/core/libraries/libs.cpp | 4 - src/emulator.cpp | 23 +- 19 files changed, 7 insertions(+), 1924 deletions(-) delete mode 100644 src/core/libraries/libc/libc.cpp delete mode 100644 src/core/libraries/libc/libc.h delete mode 100644 src/core/libraries/libc/libc_cxa.cpp delete mode 100644 src/core/libraries/libc/libc_cxa.h delete mode 100644 src/core/libraries/libc/libc_math.cpp delete mode 100644 src/core/libraries/libc/libc_math.h delete mode 100644 src/core/libraries/libc/libc_stdio.cpp delete mode 100644 src/core/libraries/libc/libc_stdio.h delete mode 100644 src/core/libraries/libc/libc_stdlib.cpp delete mode 100644 src/core/libraries/libc/libc_stdlib.h delete mode 100644 src/core/libraries/libc/libc_string.cpp delete mode 100644 src/core/libraries/libc/libc_string.h delete mode 100644 src/core/libraries/libc/printf.h delete mode 100644 src/core/libraries/libc/va_ctx.h diff --git a/CMakeLists.txt b/CMakeLists.txt index edd670155..478fb43d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,21 +223,7 @@ set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h src/core/libraries/videoout/video_out.h ) -set(LIBC_SOURCES src/core/libraries/libc/libc.cpp - src/core/libraries/libc/libc.h - src/core/libraries/libc/printf.h - src/core/libraries/libc/va_ctx.h - src/core/libraries/libc/libc_cxa.cpp - src/core/libraries/libc/libc_cxa.h - src/core/libraries/libc/libc_stdio.cpp - src/core/libraries/libc/libc_stdio.h - src/core/libraries/libc/libc_math.cpp - src/core/libraries/libc/libc_math.h - src/core/libraries/libc/libc_string.cpp - src/core/libraries/libc/libc_string.h - src/core/libraries/libc/libc_stdlib.cpp - src/core/libraries/libc/libc_stdlib.h - src/core/libraries/libc_internal/libc_internal.cpp +set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp src/core/libraries/libc_internal/libc_internal.h ) diff --git a/src/common/config.cpp b/src/common/config.cpp index 6289e2af1..ddd1d3257 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -18,7 +18,6 @@ static std::string logFilter; static std::string logType = "async"; static std::string userName = "shadPS4"; static bool isDebugDump = false; -static bool isLibc = true; static bool isShowSplash = false; static bool isNullGpu = false; static bool shouldDumpShaders = false; @@ -49,10 +48,6 @@ std::vector m_recent_files; // Settings u32 m_language = 1; // english -bool isLleLibc() { - return isLibc; -} - bool isNeoMode() { return isNeo; } @@ -354,12 +349,6 @@ void load(const std::filesystem::path& path) { isDebugDump = toml::find_or(debug, "DebugDump", false); } - if (data.contains("LLE")) { - const toml::value& lle = data.at("LLE"); - - isLibc = toml::find_or(lle, "libc", true); - } - if (data.contains("GUI")) { const toml::value& gui = data.at("GUI"); @@ -425,7 +414,6 @@ void save(const std::filesystem::path& path) { data["Vulkan"]["rdocEnable"] = rdocEnable; data["Vulkan"]["rdocMarkersEnable"] = rdocMarkersEnable; data["Debug"]["DebugDump"] = isDebugDump; - data["LLE"]["libc"] = isLibc; data["GUI"]["theme"] = mw_themes; data["GUI"]["iconSize"] = m_icon_size; data["GUI"]["sliderPos"] = m_slider_pos; diff --git a/src/common/config.h b/src/common/config.h index f2b7fe09d..9bf91e692 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -22,7 +22,6 @@ u32 getScreenHeight(); s32 getGpuId(); bool debugDump(); -bool isLleLibc(); bool showSplash(); bool nullGpu(); bool dumpShaders(); diff --git a/src/core/libraries/libc/libc.cpp b/src/core/libraries/libc/libc.cpp deleted file mode 100644 index dafb16bed..000000000 --- a/src/core/libraries/libc/libc.cpp +++ /dev/null @@ -1,496 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/debug.h" -#include "common/logging/log.h" -#include "common/singleton.h" -#include "core/libraries/libc/libc.h" -#include "core/libraries/libc/libc_cxa.h" -#include "core/libraries/libc/libc_math.h" -#include "core/libraries/libc/libc_stdio.h" -#include "core/libraries/libc/libc_stdlib.h" -#include "core/libraries/libc/libc_string.h" -#include "core/libraries/libs.h" - -namespace Libraries::LibC { - -constexpr bool log_file_libc = true; // disable it to disable logging -static u32 g_need_sceLibc = 1; - -using cxa_destructor_func_t = void (*)(void*); - -struct CxaDestructor { - cxa_destructor_func_t destructor_func; - void* destructor_object; - void* module_id; -}; - -struct CContext { - std::vector cxa; -}; - -static PS4_SYSV_ABI int ps4___cxa_atexit(void (*func)(void*), void* arg, void* dso_handle) { - auto* cc = Common::Singleton::Instance(); - CxaDestructor c{}; - c.destructor_func = func; - c.destructor_object = arg; - c.module_id = dso_handle; - cc->cxa.push_back(c); - return 0; -} - -void PS4_SYSV_ABI ps4___cxa_finalize(void* d) { - BREAKPOINT(); -} - -void PS4_SYSV_ABI ps4___cxa_pure_virtual() { - BREAKPOINT(); -} - -static PS4_SYSV_ABI void ps4_init_env() { - LOG_INFO(Lib_LibC, "called"); -} - -static PS4_SYSV_ABI void ps4_catchReturnFromMain(int status) { - LOG_INFO(Lib_LibC, "returned = {}", status); -} - -static PS4_SYSV_ABI void ps4__Assert() { - LOG_INFO(Lib_LibC, "called"); - BREAKPOINT(); -} - -PS4_SYSV_ABI void ps4__ZdlPv(void* ptr) { - std::free(ptr); -} - -PS4_SYSV_ABI void ps4__ZSt11_Xbad_allocv() { - LOG_INFO(Lib_LibC, "called"); - BREAKPOINT(); -} - -PS4_SYSV_ABI void ps4__ZSt14_Xlength_errorPKc() { - LOG_INFO(Lib_LibC, "called"); - BREAKPOINT(); -} - -PS4_SYSV_ABI void* ps4__Znwm(u64 count) { - if (count == 0) { - LOG_INFO(Lib_LibC, "_Znwm count ={}", count); - BREAKPOINT(); - } - void* ptr = std::malloc(count); - return ptr; -} - -static constexpr u16 lowercaseTable[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, - 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, - 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, - 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, - 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, - 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, - 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, - 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, - 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, - 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, - 0x00FC, 0x00FD, 0x00FE, 0x00FF, -}; - -const PS4_SYSV_ABI u16* ps4__Getptolower() { - return &lowercaseTable[0]; -} - -static constexpr u16 uppercaseTable[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, - 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, - 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, - 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, - 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, - 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, - 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, - 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, - 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, - 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, - 0x00FC, 0x00FD, 0x00FE, 0x00FF, -}; - -const PS4_SYSV_ABI u16* ps4__Getptoupper() { - return &uppercaseTable[0]; -} - -namespace CharacterType { -enum : u16 { - HexDigit = 0x1, // '0'-'9', 'A'-'F', 'a'-'f' - Uppercase = 0x2, // 'A'-'Z' - Space = 0x4, - Punctuation = 0x08, - Lowercase = 0x10, // 'a'-'z' - DecimalDigit = 0x20, // '0'-'9' - Control = 0x40, // CR, FF, HT, NL, VT - Control2 = 0x80, // BEL, BS, etc - ExtraSpace = 0x100, - ExtraAlphabetic = 0x200, - ExtraBlank = 0x400 -}; -} - -static constexpr u16 characterTypeTable[256] = { - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control | CharacterType::Control2 | CharacterType::ExtraBlank, - CharacterType::Control | CharacterType::Control2, - CharacterType::Control | CharacterType::Control2, - CharacterType::Control | CharacterType::Control2, - CharacterType::Control | CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Control2, - CharacterType::Space, // - CharacterType::Punctuation, // ! - CharacterType::Punctuation, // " - CharacterType::Punctuation, // # - CharacterType::Punctuation, // $ - CharacterType::Punctuation, // % - CharacterType::Punctuation, // & - CharacterType::Punctuation, // ' - CharacterType::Punctuation, // ( - CharacterType::Punctuation, // ) - CharacterType::Punctuation, // * - CharacterType::Punctuation, // + - CharacterType::Punctuation, // , - CharacterType::Punctuation, // - - CharacterType::Punctuation, // . - CharacterType::Punctuation, // / - CharacterType::HexDigit | CharacterType::DecimalDigit, // 0 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 1 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 2 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 3 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 4 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 5 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 6 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 7 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 8 - CharacterType::HexDigit | CharacterType::DecimalDigit, // 9 - CharacterType::Punctuation, // : - CharacterType::Punctuation, // ; - CharacterType::Punctuation, // < - CharacterType::Punctuation, // = - CharacterType::Punctuation, // > - CharacterType::Punctuation, // ? - CharacterType::Punctuation, // @ - CharacterType::HexDigit | CharacterType::Uppercase, // A - CharacterType::HexDigit | CharacterType::Uppercase, // B - CharacterType::HexDigit | CharacterType::Uppercase, // C - CharacterType::HexDigit | CharacterType::Uppercase, // D - CharacterType::HexDigit | CharacterType::Uppercase, // E - CharacterType::HexDigit | CharacterType::Uppercase, // F - CharacterType::Uppercase, // G - CharacterType::Uppercase, // H - CharacterType::Uppercase, // I - CharacterType::Uppercase, // J - CharacterType::Uppercase, // K - CharacterType::Uppercase, // L - CharacterType::Uppercase, // M - CharacterType::Uppercase, // N - CharacterType::Uppercase, // O - CharacterType::Uppercase, // P - CharacterType::Uppercase, // Q - CharacterType::Uppercase, // R - CharacterType::Uppercase, // S - CharacterType::Uppercase, // T - CharacterType::Uppercase, // U - CharacterType::Uppercase, // V - CharacterType::Uppercase, // W - CharacterType::Uppercase, // X - CharacterType::Uppercase, // Y - CharacterType::Uppercase, // Z - CharacterType::Punctuation, // [ - CharacterType::Punctuation, // - CharacterType::Punctuation, // ] - CharacterType::Punctuation, // ^ - CharacterType::Punctuation, // _ - CharacterType::Punctuation, // ` - CharacterType::HexDigit | CharacterType::Lowercase, // a - CharacterType::HexDigit | CharacterType::Lowercase, // b - CharacterType::HexDigit | CharacterType::Lowercase, // c - CharacterType::HexDigit | CharacterType::Lowercase, // d - CharacterType::HexDigit | CharacterType::Lowercase, // e - CharacterType::HexDigit | CharacterType::Lowercase, // f - CharacterType::Lowercase, // g - CharacterType::Lowercase, // h - CharacterType::Lowercase, // i - CharacterType::Lowercase, // j - CharacterType::Lowercase, // k - CharacterType::Lowercase, // l - CharacterType::Lowercase, // m - CharacterType::Lowercase, // n - CharacterType::Lowercase, // o - CharacterType::Lowercase, // p - CharacterType::Lowercase, // q - CharacterType::Lowercase, // r - CharacterType::Lowercase, // s - CharacterType::Lowercase, // t - CharacterType::Lowercase, // u - CharacterType::Lowercase, // v - CharacterType::Lowercase, // w - CharacterType::Lowercase, // x - CharacterType::Lowercase, // y - CharacterType::Lowercase, // z - CharacterType::Punctuation, // { - CharacterType::Punctuation, // | - CharacterType::Punctuation, // } - CharacterType::Punctuation, // ~ - CharacterType::Control2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -}; - -const PS4_SYSV_ABI u16* ps4__Getpctype() { - return &characterTypeTable[0]; -} - -void libcSymbolsRegister(Core::Loader::SymbolsResolver* sym) { - // cxa functions - LIB_FUNCTION("3GPpjQdAMTw", "libc", 1, "libc", 1, 1, ps4___cxa_guard_acquire); - LIB_FUNCTION("9rAeANT2tyE", "libc", 1, "libc", 1, 1, ps4___cxa_guard_release); - LIB_FUNCTION("2emaaluWzUw", "libc", 1, "libc", 1, 1, ps4___cxa_guard_abort); - - // stdlib functions - LIB_FUNCTION("uMei1W9uyNo", "libc", 1, "libc", 1, 1, ps4_exit); - LIB_FUNCTION("8G2LB+A3rzg", "libc", 1, "libc", 1, 1, ps4_atexit); - LIB_FUNCTION("gQX+4GDQjpM", "libc", 1, "libc", 1, 1, ps4_malloc); - LIB_FUNCTION("tIhsqj0qsFE", "libc", 1, "libc", 1, 1, ps4_free); - LIB_FUNCTION("cpCOXWMgha0", "libc", 1, "libc", 1, 1, ps4_rand); - LIB_FUNCTION("AEJdIVZTEmo", "libc", 1, "libc", 1, 1, ps4_qsort); - - // math functions - LIB_FUNCTION("EH-x713A99c", "libc", 1, "libc", 1, 1, ps4_atan2f); - LIB_FUNCTION("QI-x0SL8jhw", "libc", 1, "libc", 1, 1, ps4_acosf); - LIB_FUNCTION("ZE6RNL+eLbk", "libc", 1, "libc", 1, 1, ps4_tanf); - LIB_FUNCTION("GZWjF-YIFFk", "libc", 1, "libc", 1, 1, ps4_asinf); - LIB_FUNCTION("9LCjpWyQ5Zc", "libc", 1, "libc", 1, 1, ps4_pow); - LIB_FUNCTION("cCXjU72Z0Ow", "libc", 1, "libc", 1, 1, ps4__Sin); - LIB_FUNCTION("ZtjspkJQ+vw", "libc", 1, "libc", 1, 1, ps4__Fsin); - LIB_FUNCTION("dnaeGXbjP6E", "libc", 1, "libc", 1, 1, ps4_exp2); - LIB_FUNCTION("1D0H2KNjshE", "libc", 1, "libc", 1, 1, ps4_powf); - LIB_FUNCTION("DDHG1a6+3q0", "libc", 1, "libc", 1, 1, ps4_roundf); - - // string functions - LIB_FUNCTION("Ovb2dSJOAuE", "libc", 1, "libc", 1, 1, ps4_strcmp); - LIB_FUNCTION("j4ViWNHEgww", "libc", 1, "libc", 1, 1, ps4_strlen); - LIB_FUNCTION("6sJWiWSRuqk", "libc", 1, "libc", 1, 1, ps4_strncpy); - LIB_FUNCTION("+P6FRGH4LfA", "libc", 1, "libc", 1, 1, ps4_memmove); - LIB_FUNCTION("kiZSXIWd9vg", "libc", 1, "libc", 1, 1, ps4_strcpy); - LIB_FUNCTION("Ls4tzzhimqQ", "libc", 1, "libc", 1, 1, ps4_strcat); - LIB_FUNCTION("DfivPArhucg", "libc", 1, "libc", 1, 1, ps4_memcmp); - LIB_FUNCTION("Q3VBxCXhUHs", "libc", 1, "libc", 1, 1, ps4_memcpy); - LIB_FUNCTION("8zTFvBIAIN8", "libc", 1, "libc", 1, 1, ps4_memset); - LIB_FUNCTION("9yDWMxEFdJU", "libc", 1, "libc", 1, 1, ps4_strrchr); - LIB_FUNCTION("aesyjrHVWy4", "libc", 1, "libc", 1, 1, ps4_strncmp); - LIB_FUNCTION("g7zzzLDYGw0", "libc", 1, "libc", 1, 1, ps4_strdup); - - // stdio functions - LIB_FUNCTION("xeYO4u7uyJ0", "libc", 1, "libc", 1, 1, ps4_fopen); - // LIB_FUNCTION("hcuQgD53UxM", "libc", 1, "libc", 1, 1, ps4_printf); - LIB_FUNCTION("Q2V+iqvjgC0", "libc", 1, "libc", 1, 1, ps4_vsnprintf); - LIB_FUNCTION("YQ0navp+YIc", "libc", 1, "libc", 1, 1, ps4_puts); - // LIB_FUNCTION("fffwELXNVFA", "libc", 1, "libc", 1, 1, ps4_fprintf); - LIB_FUNCTION("QMFyLoqNxIg", "libc", 1, "libc", 1, 1, ps4_setvbuf); - LIB_FUNCTION("uodLYyUip20", "libc", 1, "libc", 1, 1, ps4_fclose); - LIB_FUNCTION("rQFVBXp-Cxg", "libc", 1, "libc", 1, 1, ps4_fseek); - LIB_FUNCTION("SHlt7EhOtqA", "libc", 1, "libc", 1, 1, ps4_fgetpos); - LIB_FUNCTION("lbB+UlZqVG0", "libc", 1, "libc", 1, 1, ps4_fread); - LIB_FUNCTION("Qazy8LmXTvw", "libc", 1, "libc", 1, 1, ps4_ftell); - - // misc - LIB_OBJ("P330P3dFF68", "libc", 1, "libc", 1, 1, &g_need_sceLibc); - LIB_OBJ("2sWzhYqFH4E", "libc", 1, "libc", 1, 1, stdout); - LIB_OBJ("H8AprKeZtNg", "libc", 1, "libc", 1, 1, stderr); - LIB_FUNCTION("bzQExy189ZI", "libc", 1, "libc", 1, 1, ps4_init_env); - LIB_FUNCTION("XKRegsFpEpk", "libc", 1, "libc", 1, 1, ps4_catchReturnFromMain); - LIB_FUNCTION("-QgqOT5u2Vk", "libc", 1, "libc", 1, 1, ps4__Assert); - LIB_FUNCTION("z+P+xCnWLBk", "libc", 1, "libc", 1, 1, ps4__ZdlPv); - LIB_FUNCTION("eT2UsmTewbU", "libc", 1, "libc", 1, 1, ps4__ZSt11_Xbad_allocv); - LIB_FUNCTION("tQIo+GIPklo", "libc", 1, "libc", 1, 1, ps4__ZSt14_Xlength_errorPKc); - LIB_FUNCTION("fJnpuVVBbKk", "libc", 1, "libc", 1, 1, ps4__Znwm); - LIB_FUNCTION("tsvEmnenz48", "libc", 1, "libc", 1, 1, ps4___cxa_atexit); - LIB_FUNCTION("H2e8t5ScQGc", "libc", 1, "libc", 1, 1, ps4___cxa_finalize); - LIB_FUNCTION("zr094EQ39Ww", "libc", 1, "libc", 1, 1, ps4___cxa_pure_virtual); - LIB_FUNCTION("1uJgoVq3bQU", "libc", 1, "libc", 1, 1, ps4__Getptolower); - LIB_FUNCTION("rcQCUr0EaRU", "libc", 1, "libc", 1, 1, ps4__Getptoupper); - LIB_FUNCTION("sUP1hBaouOw", "libc", 1, "libc", 1, 1, ps4__Getpctype); -} - -}; // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc.h b/src/core/libraries/libc/libc.h deleted file mode 100644 index 6504b8d71..000000000 --- a/src/core/libraries/libc/libc.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace Core::Loader { -class SymbolsResolver; -} - -namespace Libraries::LibC { - -void libcSymbolsRegister(Core::Loader::SymbolsResolver* sym); - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_cxa.cpp b/src/core/libraries/libc/libc_cxa.cpp deleted file mode 100644 index ff10d3f08..000000000 --- a/src/core/libraries/libc/libc_cxa.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/libraries/libc/libc_cxa.h" - -// adapted from -// https://opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx.auto.html - -namespace Libraries::LibC { - -// This file implements the __cxa_guard_* functions as defined at: -// http://www.codesourcery.com/public/cxx-abi/abi.html -// -// The goal of these functions is to support thread-safe, one-time -// initialization of function scope variables. The compiler will generate -// code like the following: -// -// if ( obj_guard.first_byte == 0 ) { -// if ( __cxa_guard_acquire(&obj_guard) ) { -// try { -// ... initialize the object ...; -// } -// catch (...) { -// __cxa_guard_abort(&obj_guard); -// throw; -// } -// ... queue object destructor with __cxa_atexit() ...; -// __cxa_guard_release(&obj_guard); -// } -// } -// -// Notes: -// ojb_guard is a 64-bytes in size and statically initialized to zero. -// -// Section 6.7 of the C++ Spec says "If control re-enters the declaration -// recursively while the object is being initialized, the behavior is -// undefined". This implementation calls abort(). -// - -// Note don't use function local statics to avoid use of cxa functions... -static pthread_mutex_t __guard_mutex; -static pthread_once_t __once_control = PTHREAD_ONCE_INIT; - -static void makeRecusiveMutex() { - pthread_mutexattr_t recursiveMutexAttr; - pthread_mutexattr_init(&recursiveMutexAttr); - pthread_mutexattr_settype(&recursiveMutexAttr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&__guard_mutex, &recursiveMutexAttr); -} - -__attribute__((noinline)) static pthread_mutex_t* guard_mutex() { - pthread_once(&__once_control, &makeRecusiveMutex); - return &__guard_mutex; -} - -// helper functions for getting/setting flags in guard_object -static bool initializerHasRun(u64* guard_object) { - return (*((u8*)guard_object) != 0); -} - -static void setInitializerHasRun(u64* guard_object) { - *((u8*)guard_object) = 1; -} - -static bool inUse(u64* guard_object) { - return (((u8*)guard_object)[1] != 0); -} - -static void setInUse(u64* guard_object) { - ((u8*)guard_object)[1] = 1; -} - -static void setNotInUse(u64* guard_object) { - ((u8*)guard_object)[1] = 0; -} - -// -// Returns 1 if the caller needs to run the initializer and then either -// call __cxa_guard_release() or __cxa_guard_abort(). If zero is returned, -// then the initializer has already been run. This function blocks -// if another thread is currently running the initializer. This function -// aborts if called again on the same guard object without an intervening -// call to __cxa_guard_release() or __cxa_guard_abort(). -// -int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) { - // Double check that the initializer has not already been run - if (initializerHasRun(guard_object)) - return 0; - - // We now need to acquire a lock that allows only one thread - // to run the initializer. If a different thread calls - // __cxa_guard_acquire() with the same guard object, we want - // that thread to block until this thread is done running the - // initializer and calls __cxa_guard_release(). But if the same - // thread calls __cxa_guard_acquire() with the same guard object, - // we want to abort. - // To implement this we have one global pthread recursive mutex - // shared by all guard objects, but only one at a time. - - int result = ::pthread_mutex_lock(guard_mutex()); - if (result != 0) { - LOG_ERROR(Lib_LibC, "pthread_mutex_lock failed with {}", result); - } - // At this point all other threads will block in __cxa_guard_acquire() - - // Check if another thread has completed initializer run - if (initializerHasRun(guard_object)) { - int result = ::pthread_mutex_unlock(guard_mutex()); - if (result != 0) { - LOG_ERROR(Lib_LibC, "pthread_mutex_lock failed with {}", result); - } - return 0; - } - - // The pthread mutex is recursive to allow other lazy initialized - // function locals to be evaluated during evaluation of this one. - // But if the same thread can call __cxa_guard_acquire() on the - // *same* guard object again, we call abort(); - if (inUse(guard_object)) { - LOG_ERROR(Lib_LibC, - "initializer for function local static variable called enclosing function"); - } - - // mark this guard object as being in use - setInUse(guard_object); - - // return non-zero to tell caller to run initializer - return 1; -} - -// -// Sets the first byte of the guard_object to a non-zero value. -// Releases any locks acquired by __cxa_guard_acquire(). -// -void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object) { - // first mark initalizer as having been run, so - // other threads won't try to re-run it. - setInitializerHasRun(guard_object); - - // release global mutex - int result = ::pthread_mutex_unlock(guard_mutex()); - if (result != 0) { - LOG_ERROR(Lib_LibC, "pthread_mutex_unlock failed with {}", result); - } -} - -// -// Releases any locks acquired by __cxa_guard_acquire(). -// -void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object) { - int result = ::pthread_mutex_unlock(guard_mutex()); - if (result != 0) { - LOG_ERROR(Lib_LibC, "pthread_mutex_unlock failed with {}", result); - } - - // now reset state, so possible to try to initialize again - setNotInUse(guard_object); -} - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_cxa.h b/src/core/libraries/libc/libc_cxa.h deleted file mode 100644 index 2594493eb..000000000 --- a/src/core/libraries/libc/libc_cxa.h +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include "common/types.h" - -namespace Libraries::LibC { - -int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object); -void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object); -void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object); - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_math.cpp b/src/core/libraries/libc/libc_math.cpp deleted file mode 100644 index 3b51c80e2..000000000 --- a/src/core/libraries/libc/libc_math.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/assert.h" -#include "core/libraries/libc/libc_math.h" - -namespace Libraries::LibC { - -float PS4_SYSV_ABI ps4_atan2f(float y, float x) { - return atan2f(y, x); -} - -float PS4_SYSV_ABI ps4_acosf(float num) { - return acosf(num); -} - -float PS4_SYSV_ABI ps4_tanf(float num) { - return tanf(num); -} - -float PS4_SYSV_ABI ps4_asinf(float num) { - return asinf(num); -} - -double PS4_SYSV_ABI ps4_pow(double base, double exponent) { - return pow(base, exponent); -} - -float PS4_SYSV_ABI ps4_powf(float x, float y) { - return powf(x, y); -} - -float PS4_SYSV_ABI ps4_roundf(float arg) { - return roundf(arg); -} - -double PS4_SYSV_ABI ps4__Sin(double x) { - return sin(x); -} - -float PS4_SYSV_ABI ps4__Fsin(float arg, unsigned int m, int n) { - ASSERT(n == 0); - if (m != 0) { - return cosf(arg); - } else { - return sinf(arg); - } -} - -double PS4_SYSV_ABI ps4_exp2(double arg) { - return exp2(arg); -} - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_math.h b/src/core/libraries/libc/libc_math.h deleted file mode 100644 index f73a33f14..000000000 --- a/src/core/libraries/libc/libc_math.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/types.h" - -namespace Libraries::LibC { - -float PS4_SYSV_ABI ps4_atan2f(float y, float x); -float PS4_SYSV_ABI ps4_acosf(float num); -float PS4_SYSV_ABI ps4_tanf(float num); -float PS4_SYSV_ABI ps4_asinf(float num); -double PS4_SYSV_ABI ps4_pow(double base, double exponent); -double PS4_SYSV_ABI ps4__Sin(double x); -float PS4_SYSV_ABI ps4__Fsin(float arg, unsigned int, int); -double PS4_SYSV_ABI ps4_exp2(double arg); -float PS4_SYSV_ABI ps4_powf(float x, float y); -float PS4_SYSV_ABI ps4_roundf(float arg); - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_stdio.cpp b/src/core/libraries/libc/libc_stdio.cpp deleted file mode 100644 index 2b15bd369..000000000 --- a/src/core/libraries/libc/libc_stdio.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "common/singleton.h" -#include "core/file_sys/fs.h" -#include "core/libraries/libc/libc_stdio.h" - -namespace Libraries::LibC { - -std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode) { - auto* mnt = Common::Singleton::Instance(); - const auto host_path = mnt->GetHostPath(filename).string(); - FILE* f = std::fopen(host_path.c_str(), mode); - if (f != nullptr) { - LOG_INFO(Lib_LibC, "fopen = {}", host_path); - } else { - LOG_INFO(Lib_LibC, "fopen can't open = {}", host_path); - } - return f; -} - -int PS4_SYSV_ABI ps4_fclose(FILE* stream) { - LOG_INFO(Lib_LibC, "callled"); - int ret = 0; - if (stream != nullptr) { - ret = fclose(stream); - } - return ret; -} - -int PS4_SYSV_ABI ps4_setvbuf(FILE* stream, char* buf, int mode, size_t size) { - return setvbuf(stream, buf, mode, size); -} - -int PS4_SYSV_ABI ps4_fseek(FILE* stream, long offset, int whence) { - return fseek(stream, offset, whence); -} - -int PS4_SYSV_ABI ps4_fgetpos(FILE* stream, fpos_t* pos) { - return fgetpos(stream, pos); -} - -std::size_t PS4_SYSV_ABI ps4_fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { - return fread(ptr, size, nmemb, stream); -} - -int PS4_SYSV_ABI ps4_printf(VA_ARGS) { - VA_CTX(ctx); - return printf_ctx(&ctx); -} - -int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS) { - int fd = fileno(file); - if (fd == 1 || fd == 2) { // output stdout and stderr to console - VA_CTX(ctx); - return printf_ctx(&ctx); - } else { - VA_CTX(ctx); - char buf[256]; - fprintf_ctx(&ctx, buf); - return fprintf(file, "%s", buf); - } -} - -int PS4_SYSV_ABI ps4_vsnprintf(char* s, size_t n, const char* format, VaList* arg) { - return vsnprintf_ctx(s, n, format, arg); -} - -int PS4_SYSV_ABI ps4_puts(const char* s) { - return std::puts(s); -} - -long PS4_SYSV_ABI ps4_ftell(FILE* stream) { - return ftell(stream); -} - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_stdio.h b/src/core/libraries/libc/libc_stdio.h deleted file mode 100644 index 806c17c28..000000000 --- a/src/core/libraries/libc/libc_stdio.h +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/types.h" -#include "core/libraries/libc/printf.h" - -namespace Libraries::LibC { - -std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode); -int PS4_SYSV_ABI ps4_printf(VA_ARGS); -int PS4_SYSV_ABI ps4_vsnprintf(char* s, size_t n, const char* format, VaList* arg); -int PS4_SYSV_ABI ps4_puts(const char* s); -int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS); -int PS4_SYSV_ABI ps4_setvbuf(FILE* stream, char* buf, int mode, size_t size); -int PS4_SYSV_ABI ps4_fclose(FILE* stream); -int PS4_SYSV_ABI ps4_fseek(FILE* stream, long offset, int whence); -int PS4_SYSV_ABI ps4_fgetpos(FILE* stream, fpos_t* pos); -std::size_t PS4_SYSV_ABI ps4_fread(void* ptr, size_t size, size_t nmemb, FILE* stream); -long PS4_SYSV_ABI ps4_ftell(FILE* stream); - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_stdlib.cpp b/src/core/libraries/libc/libc_stdlib.cpp deleted file mode 100644 index e71838780..000000000 --- a/src/core/libraries/libc/libc_stdlib.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/assert.h" -#include "core/libraries/libc/libc_stdlib.h" - -namespace Libraries::LibC { - -void PS4_SYSV_ABI ps4_exit(int code) { - std::exit(code); -} - -int PS4_SYSV_ABI ps4_atexit(void (*func)()) { - int rt = std::atexit(func); - ASSERT_MSG(rt == 0, "atexit returned {}", rt); - return rt; -} - -void* PS4_SYSV_ABI ps4_malloc(size_t size) { - return std::malloc(size); -} - -void PS4_SYSV_ABI ps4_free(void* ptr) { - std::free(ptr); -} - -typedef int(PS4_SYSV_ABI* pfunc_QsortCmp)(const void*, const void*); -thread_local static pfunc_QsortCmp compair_ps4; - -int qsort_compair(const void* arg1, const void* arg2) { - return compair_ps4(arg1, arg2); -} - -void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size, - int(PS4_SYSV_ABI* comp)(const void*, const void*)) { - compair_ps4 = comp; - std::qsort(ptr, count, size, qsort_compair); -} - -int PS4_SYSV_ABI ps4_rand() { - return std::rand(); -} - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_stdlib.h b/src/core/libraries/libc/libc_stdlib.h deleted file mode 100644 index 4bb5f6c13..000000000 --- a/src/core/libraries/libc/libc_stdlib.h +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include "common/types.h" - -namespace Libraries::LibC { - -void PS4_SYSV_ABI ps4_exit(int code); -int PS4_SYSV_ABI ps4_atexit(void (*func)()); -void* PS4_SYSV_ABI ps4_malloc(size_t size); -void PS4_SYSV_ABI ps4_free(void* ptr); -void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size, - int(PS4_SYSV_ABI* comp)(const void*, const void*)); -int PS4_SYSV_ABI ps4_rand(); - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_string.cpp b/src/core/libraries/libc/libc_string.cpp deleted file mode 100644 index af7524e6e..000000000 --- a/src/core/libraries/libc/libc_string.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include "core/libraries/libc/libc_string.h" - -namespace Libraries::LibC { - -int PS4_SYSV_ABI ps4_memcmp(const void* s1, const void* s2, size_t n) { - return std::memcmp(s1, s2, n); -} - -void* PS4_SYSV_ABI ps4_memcpy(void* dest, const void* src, size_t n) { - return std::memcpy(dest, src, n); -} - -void* PS4_SYSV_ABI ps4_memset(void* s, int c, size_t n) { - return std::memset(s, c, n); -} - -int PS4_SYSV_ABI ps4_strcmp(const char* str1, const char* str2) { - return std::strcmp(str1, str2); -} - -char* PS4_SYSV_ABI ps4_strncpy(char* dest, const char* src, size_t count) { - return std::strncpy(dest, src, count); -} - -void* PS4_SYSV_ABI ps4_memmove(void* dest, const void* src, std::size_t count) { - return std::memmove(dest, src, count); -} - -char* PS4_SYSV_ABI ps4_strcpy(char* dest, const char* src) { - return std::strcpy(dest, src); -} - -char* PS4_SYSV_ABI ps4_strcat(char* dest, const char* src) { - return std::strcat(dest, src); -} - -size_t PS4_SYSV_ABI ps4_strlen(const char* str) { - return std::strlen(str); -} - -char* PS4_SYSV_ABI ps4_strrchr(const char* s, int c) { - return (char*)strrchr(s, c); -} - -int PS4_SYSV_ABI ps4_strncmp(const char* s1, const char* s2, size_t n) { - return strncmp(s1, s2, n); -} - -char* PS4_SYSV_ABI ps4_strdup(const char* str1) { - char* dup = (char*)std::malloc(std::strlen(str1) + 1); - if (dup != NULL) - strcpy(dup, str1); - return dup; -} - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/libc_string.h b/src/core/libraries/libc/libc_string.h deleted file mode 100644 index 3e575fa30..000000000 --- a/src/core/libraries/libc/libc_string.h +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include "common/types.h" - -namespace Libraries::LibC { - -int PS4_SYSV_ABI ps4_memcmp(const void* s1, const void* s2, size_t n); -void* PS4_SYSV_ABI ps4_memcpy(void* dest, const void* src, size_t n); -void* PS4_SYSV_ABI ps4_memset(void* s, int c, size_t n); -int PS4_SYSV_ABI ps4_strcmp(const char* str1, const char* str2); -char* PS4_SYSV_ABI ps4_strncpy(char* dest, const char* src, size_t count); -void* PS4_SYSV_ABI ps4_memmove(void* dest, const void* src, std::size_t count); -char* PS4_SYSV_ABI ps4_strcpy(char* destination, const char* source); -char* PS4_SYSV_ABI ps4_strcat(char* dest, const char* src); -size_t PS4_SYSV_ABI ps4_strlen(const char* str); -char* PS4_SYSV_ABI ps4_strrchr(const char* s, int c); -int PS4_SYSV_ABI ps4_strncmp(const char* s1, const char* s2, size_t n); -char* PS4_SYSV_ABI ps4_strdup(const char* str1); - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/printf.h b/src/core/libraries/libc/printf.h deleted file mode 100644 index e84654274..000000000 --- a/src/core/libraries/libc/printf.h +++ /dev/null @@ -1,753 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2014-2018 Marco Paland (info@paland.com) -// SPDX-License-Identifier: MIT - -/////////////////////////////////////////////////////////////////////////////// -// \author (c) Marco Paland (info@paland.com) -// 2014-2018, PALANDesign Hannover, Germany -// -// \license The MIT License (MIT) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on -// embedded systems with a very limited resources. -// Use this instead of bloated standard/newlib printf. -// These routines are thread safe and reentrant! -// -/////////////////////////////////////////////////////////////////////////////// -// Vita3K emulator project -// Copyright (C) 2023 Vita3K team -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -// copied from Vita3k project at 6/10/2023 (latest update 30/06/2023) -// modifications for adapting va_args parameters - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -#include "va_ctx.h" - -namespace Libraries::LibC { -// ntoa conversion buffer size, this must be big enough to hold -// one converted numeric number including padded zeros (dynamically created on stack) -// 32 byte is a good default -#define PRINTF_NTOA_BUFFER_SIZE 32U - -// ftoa conversion buffer size, this must be big enough to hold -// one converted float number including padded zeros (dynamically created on stack) -// 32 byte is a good default -#define PRINTF_FTOA_BUFFER_SIZE 32U - -// define this to support floating point (%f) -#define PRINTF_SUPPORT_FLOAT - -// define this to support long long types (%llu or %p) -#define PRINTF_SUPPORT_LONG_LONG - -// define this to support the ptrdiff_t type (%t) -// ptrdiff_t is normally defined in as long or long long type -#define PRINTF_SUPPORT_PTRDIFF_T - -/////////////////////////////////////////////////////////////////////////////// - -// internal flag definitions -#define FLAGS_ZEROPAD (1U << 0U) -#define FLAGS_LEFT (1U << 1U) -#define FLAGS_PLUS (1U << 2U) -#define FLAGS_SPACE (1U << 3U) -#define FLAGS_HASH (1U << 4U) -#define FLAGS_UPPERCASE (1U << 5U) -#define FLAGS_CHAR (1U << 6U) -#define FLAGS_SHORT (1U << 7U) -#define FLAGS_LONG (1U << 8U) -#define FLAGS_LONG_LONG (1U << 9U) -#define FLAGS_PRECISION (1U << 10U) -#define FLAGS_WIDTH (1U << 11U) - -// output function type -typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); - -// wrapper (used as buffer) for output function type -typedef struct { - void (*fct)(char character, void* arg); - void* arg; -} out_fct_wrap_type; - -// internal buffer output -static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) { - if (idx < maxlen) { - ((char*)buffer)[idx] = character; - } -} - -// internal null output -static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) { - (void)character; - (void)buffer; - (void)idx; - (void)maxlen; -} - -// internal output function wrapper -static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) { - (void)idx; - (void)maxlen; - // buffer is the output fct pointer - ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); -} - -// internal strlen -// \return The length of the string (excluding the terminating 0) -static inline unsigned int _strlen(const char* str) { - const char* s; - for (s = str; *s; ++s) - ; - return (unsigned int)(s - str); -} - -// internal test if char is a digit (0-9) -// \return true if char is a digit -static inline bool _is_digit(char ch) { - return (ch >= '0') && (ch <= '9'); -} - -// internal ASCII string to unsigned int conversion -static inline unsigned int _atoi(const char** str) { - unsigned int i = 0U; - while (_is_digit(**str)) { - i = i * 10U + (unsigned int)(*((*str)++) - '0'); - } - return i; -} - -// internal itoa format -static inline size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, - char* buf, size_t len, bool negative, unsigned int base, - unsigned int prec, unsigned int width, unsigned int flags) { - const size_t start_idx = idx; - - // pad leading zeros - while (!(flags & FLAGS_LEFT) && (len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) && - (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - - // handle hash - if (flags & FLAGS_HASH) { - if (((len == prec) || (len == width)) && (len > 0U)) { - len--; - if ((base == 16U) && (len > 0U)) { - len--; - } - } - if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'x'; - } - if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'X'; - } - if (len < PRINTF_NTOA_BUFFER_SIZE) { - buf[len++] = '0'; - } - } - - // handle sign - if ((len == width) && (negative || (flags & FLAGS_PLUS) || (flags & FLAGS_SPACE))) { - len--; - } - if (len < PRINTF_NTOA_BUFFER_SIZE) { - if (negative) { - buf[len++] = '-'; - } else if (flags & FLAGS_PLUS) { - buf[len++] = '+'; // ignore the space if the '+' exists - } else if (flags & FLAGS_SPACE) { - buf[len++] = ' '; - } - } - - // pad spaces up to given width - if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { - for (size_t i = len; i < width; i++) { - out(' ', buffer, idx++, maxlen); - } - } - - // reverse string - for (size_t i = 0U; i < len; i++) { - out(buf[len - i - 1U], buffer, idx++, maxlen); - } - - // append pad spaces up to given width - if (flags & FLAGS_LEFT) { - while (idx - start_idx < width) { - out(' ', buffer, idx++, maxlen); - } - } - - return idx; -} - -// internal itoa for 'long' type -static inline size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, - unsigned long value, bool negative, unsigned long base, - unsigned int prec, unsigned int width, unsigned int flags) { - char buf[PRINTF_NTOA_BUFFER_SIZE]; - size_t len = 0U; - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { - do { - const char digit = (char)(value % base); - buf[len++] = - digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= base; - } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); - } - - return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, - width, flags); -} - -// internal itoa for 'long long' type -#if defined(PRINTF_SUPPORT_LONG_LONG) -static inline size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, - unsigned long long value, bool negative, - unsigned long long base, unsigned int prec, unsigned int width, - unsigned int flags) { - char buf[PRINTF_NTOA_BUFFER_SIZE]; - size_t len = 0U; - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { - do { - const char digit = (char)(value % base); - buf[len++] = - digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= base; - } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); - } - - return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, - width, flags); -} -#endif // PRINTF_SUPPORT_LONG_LONG - -#if defined(PRINTF_SUPPORT_FLOAT) -static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, - unsigned int prec, unsigned int width, unsigned int flags) { - char buf[PRINTF_FTOA_BUFFER_SIZE]; - size_t len = 0U; - double diff = 0.0; - - // if input is larger than thres_max, revert to exponential - const double thres_max = (double)0x7FFFFFFF; - - // powers of 10 - static const double pow10[] = {1, 10, 100, 1000, 10000, - 100000, 1000000, 10000000, 100000000, 1000000000}; - - // test for negative - bool negative = false; - if (value < 0) { - negative = true; - value = 0 - value; - } - - // set default precision to 6, if not set explicitly - if (!(flags & FLAGS_PRECISION)) { - prec = 6U; - } - // limit precision to 9, cause a prec >= 10 can lead to overflow errors - while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { - buf[len++] = '0'; - prec--; - } - - int whole = (int)value; - double tmp = (value - whole) * pow10[prec]; - unsigned long frac = (unsigned long)tmp; - diff = tmp - frac; - - if (diff > 0.5) { - ++frac; - // handle rollover, e.g. case 0.99 with prec 1 is 1.0 - if (frac >= pow10[prec]) { - frac = 0; - ++whole; - } - } else if ((diff == 0.5) && ((frac == 0U) || (frac & 1U))) { - // if halfway, round up if odd, OR if last digit is 0 - ++frac; - } - - // TBD: for very large numbers switch back to native sprintf for exponentials. Anyone want to - // write code to replace this? Normal printf behavior is to print EVERY whole number digit which - // can be 100s of characters overflowing your buffers == bad - if (value > thres_max) { - return 0U; - } - - if (prec == 0U) { - diff = value - (double)whole; - if (diff > 0.5) { - // greater than 0.5, round up, e.g. 1.6 -> 2 - ++whole; - } else if ((diff == 0.5) && (whole & 1)) { - // exactly 0.5 and ODD, then round up - // 1.5 -> 2, but 2.5 -> 2 - ++whole; - } - } else { - unsigned int count = prec; - // now do fractional part, as an unsigned number - while (len < PRINTF_FTOA_BUFFER_SIZE) { - --count; - buf[len++] = (char)(48U + (frac % 10U)); - if (!(frac /= 10U)) { - break; - } - } - // add extra 0s - while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { - buf[len++] = '0'; - } - if (len < PRINTF_FTOA_BUFFER_SIZE) { - // add decimal - buf[len++] = '.'; - } - } - - // do whole part, number is reversed - while (len < PRINTF_FTOA_BUFFER_SIZE) { - buf[len++] = (char)(48 + (whole % 10)); - if (!(whole /= 10)) { - break; - } - } - - // pad leading zeros - while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) && - (len < PRINTF_FTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - - // handle sign - if ((len == width) && (negative || (flags & FLAGS_PLUS) || (flags & FLAGS_SPACE))) { - len--; - } - if (len < PRINTF_FTOA_BUFFER_SIZE) { - if (negative) { - buf[len++] = '-'; - } else if (flags & FLAGS_PLUS) { - buf[len++] = '+'; // ignore the space if the '+' exists - } else if (flags & FLAGS_SPACE) { - buf[len++] = ' '; - } - } - - // pad spaces up to given width - if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { - for (size_t i = len; i < width; i++) { - out(' ', buffer, idx++, maxlen); - } - } - - // reverse string - for (size_t i = 0U; i < len; i++) { - out(buf[len - i - 1U], buffer, idx++, maxlen); - } - - // append pad spaces up to given width - if (flags & FLAGS_LEFT) { - while (idx < width) { - out(' ', buffer, idx++, maxlen); - } - } - - return idx; -} -#endif // PRINTF_SUPPORT_FLOAT - -// internal vsnprintf -static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format, VaList* va_list) { - unsigned int flags, width, precision, n; - size_t idx = 0U; - auto maxlen = static_cast(-1); - - if (!buffer) { - // use null output function - out = _out_null; - } - - while (*format) { - // format specifier? %[flags][width][.precision][length] - if (*format != '%') { - // no - out(*format, buffer, idx++, maxlen); - format++; - continue; - } else { - // yes, evaluate it - format++; - } - - // evaluate flags - flags = 0U; - do { - switch (*format) { - case '0': - flags |= FLAGS_ZEROPAD; - format++; - n = 1U; - break; - case '-': - flags |= FLAGS_LEFT; - format++; - n = 1U; - break; - case '+': - flags |= FLAGS_PLUS; - format++; - n = 1U; - break; - case ' ': - flags |= FLAGS_SPACE; - format++; - n = 1U; - break; - case '#': - flags |= FLAGS_HASH; - format++; - n = 1U; - break; - default: - n = 0U; - break; - } - } while (n); - - // evaluate width field - width = 0U; - if (_is_digit(*format)) { - width = _atoi(&format); - } else if (*format == '*') { - const int w = vaArgInteger(va_list); // const int w = va.next(cpu, mem); - - if (w < 0) { - flags |= FLAGS_LEFT; // reverse padding - width = (unsigned int)-w; - } else { - width = (unsigned int)w; - } - format++; - } - - // evaluate precision field - precision = 0U; - if (*format == '.') { - flags |= FLAGS_PRECISION; - format++; - if (_is_digit(*format)) { - precision = _atoi(&format); - } else if (*format == '*') { - precision = - vaArgInteger(va_list); // precision = (unsigned int)va.next(cpu, mem); - format++; - } - } - - // evaluate length field - switch (*format) { - case 'l': - flags |= FLAGS_LONG; - format++; - if (*format == 'l') { - flags |= FLAGS_LONG_LONG; - format++; - } - break; - case 'h': - flags |= FLAGS_SHORT; - format++; - if (*format == 'h') { - flags |= FLAGS_CHAR; - format++; - } - break; -#if defined(PRINTF_SUPPORT_PTRDIFF_T) - case 't': - flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; -#endif - case 'j': - flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; - case 'z': - flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; - default: - break; - } - - // evaluate specifier - switch (*format) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - case 'b': { - // set the base - unsigned int base; - if (*format == 'x' || *format == 'X') { - base = 16U; - } else if (*format == 'o') { - base = 8U; - } else if (*format == 'b') { - base = 2U; - flags &= ~FLAGS_HASH; // no hash for bin format - } else { - base = 10U; - flags &= ~FLAGS_HASH; // no hash for dec format - } - // uppercase - if (*format == 'X') { - flags |= FLAGS_UPPERCASE; - } - - // no plus or space flag for u, x, X, o, b - if ((*format != 'i') && (*format != 'd')) { - flags &= ~(FLAGS_PLUS | FLAGS_SPACE); - } - - // convert the integer - if ((*format == 'i') || (*format == 'd')) { - // signed - if (flags & FLAGS_LONG_LONG) { -#if defined(PRINTF_SUPPORT_LONG_LONG) - auto value = vaArgLongLong( - va_list); // const long long value = va.next(cpu, mem); - idx = _ntoa_long_long(out, buffer, idx, maxlen, - (unsigned long long)(value > 0 ? value : 0 - value), - value < 0, base, precision, width, flags); -#endif - } else if (flags & FLAGS_LONG) { - auto value = vaArgLong(va_list); // const long value = va.next(cpu, mem); - idx = _ntoa_long(out, buffer, idx, maxlen, - (unsigned long)(value > 0 ? value : 0 - value), value < 0, - base, precision, width, flags); - } else { - // const int value = (flags & FLAGS_CHAR) ? (char)va.next(cpu, mem) : - // (flags & FLAGS_SHORT) ? (short int)va.next(cpu, mem): va.next(cpu, - // mem); - const int value = - (flags & FLAGS_CHAR) ? static_cast(vaArgInteger(va_list)) - : (flags & FLAGS_SHORT) ? static_cast(vaArgInteger(va_list)) - : vaArgInteger(va_list); - idx = _ntoa_long(out, buffer, idx, maxlen, - (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, - precision, width, flags); - } - } else { - // unsigned - if (flags & FLAGS_LONG_LONG) { -#if defined(PRINTF_SUPPORT_LONG_LONG) - // idx = _ntoa_long_long(out, buffer, idx, maxlen, va.next(cpu, mem), false, base, precision, width, flags); - idx = _ntoa_long_long(out, buffer, idx, maxlen, - static_cast(vaArgLongLong(va_list)), false, base, - precision, width, flags); -#endif - } else if (flags & FLAGS_LONG) { - // idx = _ntoa_long(out, buffer, idx, maxlen, va.next(cpu, mem), - // false, base, precision, width, flags); - idx = _ntoa_long(out, buffer, idx, maxlen, static_cast(vaArgLong(va_list)), - false, base, precision, width, flags); - } else { - // const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned - // char)va.next(cpu, mem) : (flags & FLAGS_SHORT) ? - // (unsigned short int)va.next(cpu, mem) : va.next(cpu, mem); - const unsigned int value = - (flags & FLAGS_CHAR) ? static_cast(vaArgInteger(va_list)) - : (flags & FLAGS_SHORT) ? static_cast(vaArgInteger(va_list)) - : static_cast(vaArgInteger(va_list)); - idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, - flags); - } - } - format++; - break; - } -#if defined(PRINTF_SUPPORT_FLOAT) - case 'f': - case 'F': - // idx = _ftoa(out, buffer, idx, maxlen, va.next(cpu, mem), precision, width, - // flags); - idx = _ftoa(out, buffer, idx, maxlen, vaArgDouble(va_list), precision, width, flags); - format++; - break; -#endif // PRINTF_SUPPORT_FLOAT - case 'c': { - unsigned int l = 1U; - // pre padding - if (!(flags & FLAGS_LEFT)) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - // char output - // out((char)va.next(cpu, mem), buffer, idx++, maxlen); - out(static_cast(vaArgInteger(va_list)), buffer, idx++, maxlen); - // post padding - if (flags & FLAGS_LEFT) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - format++; - break; - } - - case 's': { - const char* p = vaArgPtr( - va_list); // const char *p = va.next>(cpu, mem).get(mem); - p = p != nullptr ? p : "(null)"; - unsigned int l = _strlen(p); - // pre padding - if (flags & FLAGS_PRECISION) { - l = (l < precision ? l : precision); - } - if (!(flags & FLAGS_LEFT)) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - // string output - while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { - out(*(p++), buffer, idx++, maxlen); - } - // post padding - if (flags & FLAGS_LEFT) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - format++; - break; - } - - case 'p': { - width = sizeof(void*) * 2U; - flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; -#if defined(PRINTF_SUPPORT_LONG_LONG) - const bool is_ll = sizeof(uintptr_t) == sizeof(long long); - if (is_ll) { - // idx = _ntoa_long_long(out, buffer, idx, maxlen, - // (uintptr_t)va.next>(cpu, mem).address(), false, 16U, precision, width, - // flags); - idx = _ntoa_long_long(out, buffer, idx, maxlen, - reinterpret_cast(vaArgPtr(va_list)), false, - 16U, precision, width, flags); - } else { -#endif - // idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned - // long)((uintptr_t)va.next>(cpu, mem).address()), false, 16U, precision, - // width, flags); - idx = _ntoa_long( - out, buffer, idx, maxlen, - static_cast(reinterpret_cast(vaArgPtr(va_list))), - false, 16U, precision, width, flags); -#if defined(PRINTF_SUPPORT_LONG_LONG) - } -#endif - format++; - break; - } - - case '%': - out('%', buffer, idx++, maxlen); - format++; - break; - - default: - out(*format, buffer, idx++, maxlen); - format++; - break; - } - } - - // termination - out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); - - // return written chars without terminating \0 - return (int)idx; -} - -static int printf_ctx(VaCtx* ctx) { - const char* format = vaArgPtr(&ctx->va_list); - char buffer[256]; - int result = _vsnprintf(_out_buffer, buffer, format, &ctx->va_list); - printf("%s", buffer); - return result; -} - -static int fprintf_ctx(VaCtx* ctx, char* buf) { - const char* format = vaArgPtr(&ctx->va_list); - char buffer[256]; - int result = _vsnprintf(_out_buffer, buffer, format, &ctx->va_list); - std::strcpy(buf, buffer); - return result; -} - -static int vsnprintf_ctx(char* s, size_t n, const char* format, VaList* arg) { - char buffer[n]; - int result = _vsnprintf(_out_buffer, buffer, format, arg); - std::strcpy(s, buffer); - return result; -} -} // namespace Libraries::LibC diff --git a/src/core/libraries/libc/va_ctx.h b/src/core/libraries/libc/va_ctx.h deleted file mode 100644 index 1c0314959..000000000 --- a/src/core/libraries/libc/va_ctx.h +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/types.h" - -#define VA_ARGS \ - uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \ - uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \ - __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ... - -#define VA_CTX(ctx) \ - alignas(16) VaCtx ctx; \ - (ctx).reg_save_area.gp[0] = rdi; \ - (ctx).reg_save_area.gp[1] = rsi; \ - (ctx).reg_save_area.gp[2] = rdx; \ - (ctx).reg_save_area.gp[3] = rcx; \ - (ctx).reg_save_area.gp[4] = r8; \ - (ctx).reg_save_area.gp[5] = r9; \ - (ctx).reg_save_area.fp[0] = xmm0; \ - (ctx).reg_save_area.fp[1] = xmm1; \ - (ctx).reg_save_area.fp[2] = xmm2; \ - (ctx).reg_save_area.fp[3] = xmm3; \ - (ctx).reg_save_area.fp[4] = xmm4; \ - (ctx).reg_save_area.fp[5] = xmm5; \ - (ctx).reg_save_area.fp[6] = xmm6; \ - (ctx).reg_save_area.fp[7] = xmm7; \ - (ctx).va_list.reg_save_area = &(ctx).reg_save_area; \ - (ctx).va_list.gp_offset = offsetof(VaRegSave, gp); \ - (ctx).va_list.fp_offset = offsetof(VaRegSave, fp); \ - (ctx).va_list.overflow_arg_area = &overflow_arg_area; - -namespace Libraries::LibC { - -// https://stackoverflow.com/questions/4958384/what-is-the-format-of-the-x86-64-va-list-structure - -struct VaList { - u32 gp_offset; - u32 fp_offset; - void* overflow_arg_area; - void* reg_save_area; -}; - -struct VaRegSave { - u64 gp[6]; - __m128 fp[8]; -}; - -struct VaCtx { - VaRegSave reg_save_area; - VaList va_list; -}; - -template -T vaArgRegSaveAreaGp(VaList* l) { - auto* addr = reinterpret_cast(static_cast(l->reg_save_area) + l->gp_offset); - l->gp_offset += Size; - return *addr; -} -template -T vaArgOverflowArgArea(VaList* l) { - auto ptr = ((reinterpret_cast(l->overflow_arg_area) + (Align - 1)) & ~(Align - 1)); - auto* addr = reinterpret_cast(ptr); - l->overflow_arg_area = reinterpret_cast(ptr + Size); - return *addr; -} - -template -T vaArgRegSaveAreaFp(VaList* l) { - auto* addr = reinterpret_cast(static_cast(l->reg_save_area) + l->fp_offset); - l->fp_offset += Size; - return *addr; -} - -inline int vaArgInteger(VaList* l) { - if (l->gp_offset <= 40) { - return vaArgRegSaveAreaGp(l); - } - return vaArgOverflowArgArea(l); -} - -inline long long vaArgLongLong(VaList* l) { - if (l->gp_offset <= 40) { - return vaArgRegSaveAreaGp(l); - } - return vaArgOverflowArgArea(l); -} -inline long vaArgLong(VaList* l) { - if (l->gp_offset <= 40) { - return vaArgRegSaveAreaGp(l); - } - return vaArgOverflowArgArea(l); -} - -inline double vaArgDouble(VaList* l) { - if (l->fp_offset <= 160) { - return vaArgRegSaveAreaFp(l); - } - return vaArgOverflowArgArea(l); -} - -template -T* vaArgPtr(VaList* l) { - if (l->gp_offset <= 40) { - return vaArgRegSaveAreaGp(l); - } - return vaArgOverflowArgArea(l); -} - -} // namespace Libraries::LibC diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 20efd3c0e..f0171199b 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -8,7 +8,6 @@ #include "core/libraries/disc_map/disc_map.h" #include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/kernel/libkernel.h" -#include "core/libraries/libc/libc.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/network/http.h" @@ -46,9 +45,6 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::Kernel::LibKernel_Register(sym); Libraries::GnmDriver::RegisterlibSceGnmDriver(sym); Libraries::VideoOut::RegisterLib(sym); - if (!Config::isLleLibc()) { - Libraries::LibC::libcSymbolsRegister(sym); - } // New libraries folder from autogen Libraries::UserService::RegisterlibSceUserService(sym); diff --git a/src/emulator.cpp b/src/emulator.cpp index 99a0fa2ab..836b989e5 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -19,7 +19,6 @@ #include "core/file_sys/fs.h" #include "core/libraries/disc_map/disc_map.h" #include "core/libraries/kernel/thread_management.h" -#include "core/libraries/libc/libc.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/ngs2/ngs2.h" @@ -63,7 +62,6 @@ Emulator::Emulator() { LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled()); LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled()); LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::isMarkersEnabled()); - LOG_INFO(Config, "LLE isLibc: {}", Config::isLleLibc()); // Defer until after logging is initialized. memory = Core::Memory::Instance(); @@ -167,23 +165,14 @@ void Emulator::Run(const std::filesystem::path& file) { // check if we have system modules to load LoadSystemModules(file); - // Check if there is a libc.prx in sce_module folder - bool found = false; - if (Config::isLleLibc()) { - std::filesystem::path sce_module_folder = file.parent_path() / "sce_module"; - if (std::filesystem::is_directory(sce_module_folder)) { - for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) { - if (entry.path().filename() == "libc.prx") { - found = true; - } - LOG_INFO(Loader, "Loading {}", entry.path().string().c_str()); - linker->LoadModule(entry.path()); - } + // Load all prx from game's sce_module folder + std::filesystem::path sce_module_folder = file.parent_path() / "sce_module"; + if (std::filesystem::is_directory(sce_module_folder)) { + for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) { + LOG_INFO(Loader, "Loading {}", entry.path().string().c_str()); + linker->LoadModule(entry.path()); } } - if (!found) { - Libraries::LibC::libcSymbolsRegister(&linker->GetHLESymbols()); - } // start execution std::jthread mainthread = From d4be3dbb3165d2729cfdd45c96dea1d1f888f25d Mon Sep 17 00:00:00 2001 From: Xphalnos <164882787+Xphalnos@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:35:31 +0200 Subject: [PATCH 016/147] Lot of small fixes --- .gitmodules | 26 ++- CMakeLists.txt | 2 +- documents/Quickstart/1.png | Bin 52618 -> 0 bytes documents/changelog.txt | 60 +++-- documents/readme.txt | 35 --- externals/CMakeLists.txt | 5 - externals/discord-rpc | 1 - src/qt_gui/about_dialog.ui | 4 +- src/qt_gui/settings_dialog.ui | 205 ++++++------------ .../frontend/translate/flat_memory.cpp | 0 10 files changed, 127 insertions(+), 211 deletions(-) delete mode 100644 documents/Quickstart/1.png delete mode 100644 documents/readme.txt delete mode 160000 externals/discord-rpc delete mode 100644 src/shader_recompiler/frontend/translate/flat_memory.cpp diff --git a/.gitmodules b/.gitmodules index 60fb5fbbf..949965866 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,66 +1,84 @@ -[submodule "externals/discord-rpc"] - path = externals/discord-rpc - url = https://github.com/shadps4-emu/ext-discord-rpc.git [submodule "externals/cryptopp-cmake"] path = externals/cryptopp-cmake url = https://github.com/shadps4-emu/ext-cryptopp-cmake.git + shallow = true [submodule "externals/cryptopp"] path = externals/cryptopp url = https://github.com/shadps4-emu/ext-cryptopp.git + shallow = true [submodule "externals/cryptoppwin"] path = externals/cryptoppwin url = https://github.com/shadps4-emu/ext-cryptoppwin.git + shallow = true [submodule "externals/zlib-ng"] path = externals/zlib-ng url = https://github.com/shadps4-emu/ext-zlib-ng.git + shallow = true [submodule "externals/sdl3"] path = externals/sdl3 url = https://github.com/shadps4-emu/ext-SDL.git + shallow = true [submodule "externals/fmt"] path = externals/fmt url = https://github.com/shadps4-emu/ext-fmt.git + shallow = true [submodule "externals/vulkan-headers"] path = externals/vulkan-headers url = https://github.com/KhronosGroup/Vulkan-Headers.git + shallow = true [submodule "externals/vma"] path = externals/vma url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git + shallow = true [submodule "externals/glslang"] path = externals/glslang url = https://github.com/KhronosGroup/glslang.git + shallow = true [submodule "externals/robin-map"] path = externals/robin-map url = https://github.com/Tessil/robin-map.git + shallow = true [submodule "externals/xbyak"] path = externals/xbyak url = https://github.com/herumi/xbyak.git + shallow = true [submodule "externals/winpthreads"] path = externals/winpthreads url = https://github.com/shadps4-emu/winpthreads.git + shallow = true [submodule "externals/magic_enum"] path = externals/magic_enum url = https://github.com/Neargye/magic_enum.git + shallow = true [submodule "externals/toml11"] path = externals/toml11 url = https://github.com/ToruNiina/toml11.git + shallow = true [submodule "externals/zydis"] path = externals/zydis url = https://github.com/zyantific/zydis.git + shallow = true [submodule "externals/sirit"] path = externals/sirit url = https://github.com/shadps4-emu/sirit.git + shallow = true [submodule "externals/xxhash"] path = externals/xxhash url = https://github.com/Cyan4973/xxHash.git + shallow = true [submodule "externals/tracy"] path = externals/tracy url = https://github.com/shadps4-emu/tracy.git + shallow = true [submodule "externals/ext-boost"] path = externals/ext-boost url = https://github.com/shadps4-emu/ext-boost.git + shallow = true [submodule "externals/date"] path = externals/date url = https://github.com/HowardHinnant/date.git + shallow = true [submodule "externals/ffmpeg-core"] path = externals/ffmpeg-core - url = https://github.com/shadps4-emu/ext-ffmpeg-core + url = https://github.com/shadps4-emu/ext-ffmpeg-core.git + shallow = true \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 478fb43d1..8e349e588 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,6 +262,7 @@ set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp src/core/libraries/np_trophy/np_trophy.cpp src/core/libraries/np_trophy/np_trophy.h ) + set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp src/core/libraries/screenshot/screenshot.h ) @@ -411,7 +412,6 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/backend/spirv/spirv_emit_context.h src/shader_recompiler/frontend/translate/data_share.cpp src/shader_recompiler/frontend/translate/export.cpp - src/shader_recompiler/frontend/translate/flat_memory.cpp src/shader_recompiler/frontend/translate/scalar_alu.cpp src/shader_recompiler/frontend/translate/scalar_memory.cpp src/shader_recompiler/frontend/translate/translate.cpp diff --git a/documents/Quickstart/1.png b/documents/Quickstart/1.png deleted file mode 100644 index 6dc0ce2e39181b3f0d80305582dd0512705de998..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52618 zcmce;cTiJn)Gm%k0TmEEf*=U!v7jPFsRAK#P`V;rI*9Zxoj{^+07W4x0#bw0dk-Z9 zL z#g21vaS0gc-!8Ply!KDOIW=WkxVEIV`3_ur4WUe4V-=rR}Ao2#+^`MK#q$ARO{r=u$WzIb-`)PG(5 z*VMmfxch7xM^LoK+z;#)mFX-83$1 zwRDPhLDcL`SV8GFAI$6})I(}7!qxjvh=OL?!YTfC{?pSlNIxG$3^OxkYekwqRB1zp zvnb6XP7wqZ->H-92UC$>EnEQlBj4Ry$am^V>itS3jDoxYTZZ+tDTeu7dM+yq_jo|I z$`3_H-lPRg>q$+k5~EL78%!c`^jazu+7ZL~R#53SknZB$4mWdaWfW(xrF0VfonY+H z4+o=_j}&hBFZ;zFCU%|v=$N{#hWt4;xtW;Y<6Rv|U7Replp#%d1^bNF$D=zvOtk6PB!Y!kwPkSC!*xQkrnH8Wj2 z0v(?`J|*ET4HzUf1Acn_w0rinLn@_i$U!~v+IO|Zmie_kK6(BO;G0}Rc79EIToxv& z%#{JK6D*FliqWvY1zG(r?T1^(uf4C6o)!-<7Brt<8BJkPP{VYo4g_sBO2&=^n%r!l z!u*Li2qN&?AZZc(&eU|or`(`Wqq*vKB4-ulMg9;^$MsjGSoPSqx{z^H$#+3go zvH`8k2G5yUI-tTDkYrq<(X`)eZPyuD`!}HvGwk~Y7Cyq*17Xu{*uZP#Euy2lsv|6> z#i9j5;Uto2XiB`1mq!j=2ci^uR@v%TTuOLLeb3Ow&~sJ62w$xW&m#7 zMANDfF~ytJ_UVXtma>n(_1+51JTv2;YpwVo+$9KWa98iF_n*Ea`ENK-8YZyp3vs<| zKu(k6F=saC$fAVcyh&BvMUB!@urJVv{_k^t9*oc9Z_P2aSORP2BN049fOsGW5iCcA zA)T6z7{84-F4~XxY^(RPte@PFFG=fpH1FzkOYx5H!0d}>{&<|!UbnzV<#lLp*Beb`Y>y~yZ^@a)bW(|KnbMZKbwcn%@NViUevx%HQ>d1K^zaI&3u%kD1 zY3RF;tpd!^6ebc*oMXiY3rj})+!x~(`<;iPAWf{I|CB3gnhr6?&7&X*M)%{zhy&!I zy1B>b62VHT>5;%P=yVU1y84u*V2KbOub^i;e8JQY++~Fq(RQW`=E{$+?ELOViT}v{ z1MrD0hXrrX5_Tyh%RdC_i+z*vL8QUSn2M?@Yf6WUcNnkz(^Q8ThlG`P-Bms<_v=da zbnNrB-&fOSs;|dza-DfY_(Y!Dj$Gn-vDSgHnzN7hDAtr1vLrHTBy#*xNxYG8)K2wo z&#PkRrI#MKjld3VQDmwBl-g+(88IB?zRFlQ{9aP)``R`v{tz#>*nVijbYUEtW*O%$ zunq!lY5fn9Z%5=u-5?gMRN(<~x1d%nfz6D+HVukoz{yKXo^68!q?^jZ&fM05Ag*st zrRS5L^etX7Wc^_|1ET&o(-{7UEA->lE*`cE97GFYZQfp5P-YKLFWENxe@mfJ()Cg@t2E1cDG0s$b#}!G12&9sG8;v+960%&sNvtk_y?!EL!<0@q%jq= zN-OS1YIgQXZNG?<(Mgl!LB~?h~r)WUHAm@6}}NjDj#JzPkmJJ_DUD`!iTI$%{a?6nRe<+%qI#H zjV#yOAs)*)xAJt-x2$KDu4qI)`XE^)LYabQUdMO^N}e4v4G^yK=&px@hjzc+E%y2- zSupje>f^<&F?HI7)0hq&=)A%2v5&5Ofz^Na4VD)#$YUZpX4XD!RMV`|^5!XSB?!N; z>M@uWCMtzxGqqu&{7Wz^AQ2T~MoMsUI3@Hjj*+CLno$GB>fT$Af-s7UyQOJJ8OK~t z4PH`xnsn$aNpE`G1K!-~VyGgGXP4$`f!keS--N^?(HaRBTFrCTC1SsLLFojQr&`Km zeoGU)WO2Hc)-WU)-6tvO5jJpPu9XvQ*z#A^Qj5j&;mNi*a=Jw~ba#3^I;;-LcRlKg zy^^u>`AYY-+2F)de0OS z*?zHG=fJ*etx;w+AJv|08)es)_?1Ge?E>Fed;9vMPVlV09kbS9Vdra$EZPq{dU~zU z-((8o(z$N z?lUK%5E%i6wH-@WH5%LbGY1NOc740%;UW6O3@vbdeYJ$L3vW8CTbM#E(TI~>qa~8P zsPI!D)c~B~lDVRep!!HU$WdRlxmNG_?Cp-N)(2=UdnjHqvtA+e=62n7aoLV*^dtIv zl%#btymrr34;RRpU3#jQ3!J?Xym5{p|2 zYhbtj+5jf({-jS$htQtby^=vyLG$YxyBic-g&~E0E zEQLq6l(zyZcJ~>ZuJ9RLk;crMeBRG;DiNOEXudNy*l@I;zk_6(gnvQXLgdA&cMiUs z!&PRjgm$tD<=m~6EcKc|q&;#A=4lee;0?972JfetH5p6IWRELOxTHltbW(nKQ#`%q zk>rr&6oeSl-MZ>C`YE1VKTthq7B5`J6Gkh$8HuKy5PN4SmH5KE6~$40o5#oJ>!0@Q zjtXTac1v#e=E7MB+`(n3Z%-_aehhNBu()nPzzKV2a=SD)&$zvWi>VMjKuCf4*3@gj zo4ciDjd$uFW?qbwm9yROSIc_~q*#uUm?vIWoG&$$Mt;6;9j|x>LgIn zH#D09KDHnFO9tHb%Lpx>ID0N->12oW!l7J+52xGpc8=Hq06|Had7CL-jh@kBZX9M! z-^-Yihk+dbAbOq%NIs170q|5BlY1R9ZSS zdDTt$@O>Wh4)A7a9+%V->|#}t@$-1!tSUUtHtVN=*-kM;H9Mne@{% z#eTVNv=3Z=HuFV^OUMfl*^EN4)Jl)>qD34w!;gZoSsj#4itXtVNECi<*VyMVQ>nU&1rW zbYq}lga;S3?}F;n6cCvKlt!uR41_$pc_ zvmJ9gRp&yx}*qd!kp*@?(mCV~mid+(}E zLHIB9=E557*7zZ6vy@?#BD3KH)B}BGO_s&>-)cWMJ%P3<14Ha^LRteQ_ODsbfA8_bDCn;$XkJBL&^)0EKYSVSRq8IG>t! zi~Z%V)M1b-Tr;9mBI28iO5n(w^Hou1$qPj~w>1B*`%xU-ZqArL(#7>+?tJn)NtwAs zVYv8jrsaz}Ox+n=K+8>mr;+%)s4v&qVm;Z-@o|6mzOT5&j=KA(gVc-rsd{Bb!i6e} z+#8oNh%vAE2J>A-MO5br1Q1k4i$j7Vi&9(}c~Ywd@7|s9E2k-*)JY)w24F(Yr~NUp z9dR1UvJ(&QYVs4_Cd6jqD3Flp!{Pb@I3aI2QF4eEIiH<{84dtP$~m<6@b6_E=Fyj`f)kb z^z3cQOu2l=QS;;0G>sCm6<%CDaf#)5x1H!1lze}8A)XFI(8VyGt$g@exqe_i5J;=c zg z|3gL+2|xf`TlqWz=Z|W7&MlUe^apRk5dhDnQi)inD%1Q6yKXQ3f-XgePu{?}4pX=f z#s6Hop?E~B(Ghourk%PneV!#1@r=Dtv*N+E&mwZBTnhAXUM28`S1^VV3jl*_UA$7Y zPV8SIUCh$waXizhCVhh2&4F`&h$~08R5>(UG4{Her8|5;j3~)9;U&N8g2Wz-ncT5j z>3U;7%p+jTVHcz{ka_uQRs2*0%w+%{apkCz<}MuKci+b5!|{pSE5g2SUO^cH`Mh!G zf|f5F1i9SQ){xbS@9rHe#}sRYKlbxguFsL}qUE*fEu0-9@egUgz1b(qw=i zS*@URz4hJ=FlGY;3-$c@ll&I%&M%Zir*)>JTI6dBG4}9Zi8FP25?)g69O#EE2daD8 zFom*1@L`eBBF_(IBmaaD>R$$D+ec_Xi}}sA(f8E0=2WG5iGuRkeiO!Zm_&)_KKs`z z8J1D{l#G0b z^FX?+K(p^`2*Cm6=jMk)@|piiON;T6Dp~a;&osFh;-_4Gp3epa>$d#E{B*(5$Wv|i z#{&YeP32^rIF_+R-GA3Z?}WAYtN8A!7$15!+GH1wbK9ZJ)aHf@>~|0|mB;s~GXrH< z8~XsRH`1{Jw9nx@{Ee)`oc&+U9Y8RF+}SXlM6;|^Xl2rCE7DR%Y~JPz zkFcUEC$<5ykbhls$tb)u#2`wC1voHy5umb9L>pRk+4Fycsq(mfryt+CU>sPD3air?;Ppt9iZvXxGunN*mXj zPG&utIra(}J>55#clGPNdFdlCET6~^K65T5t0sVZazMD12|kI*3~vi1`Afmt8_jIZ z8}Z>`wL#$hm*_o;$QnX$Hh?r4bGo{$mRgO%jk-Q)^csH9)F%~r)!5HI1e+g@*ymP0 zA>p9Iw>W%l)nTO@u0F{lAn8499Qh?hlOBOuX#?Bf!pOdBWhK0QSlEZQZu)jA9AF0| zYRqX2+a#6ZThr2*NB4!l?%!IuLK@{W`w&y zgUw13@dK09HrdP}x@llCtmCO$ZHJA4A`8(l>^BjLZ@Zy@ynDn#7tz|0u_1cY- z(c$hmRbnBhmj+AHO65Iq);rG3yySu16b;rklYYZdv{G;X6O6>j$8#we-;+9T=I~<} zwfrZ*+xdNYzs*bM(wpvb?W6tYOK0*ag|H~)!*iO_hTnSs-bR{#E^6Fr-knmpl zsx1W8u?`o&0OJC_UL|#4CSAPeKdrB0&}SMEboncI{78@rE}9zhcX{c6IcMcy8=^@O zd9o4AFGzMc4^Q~CHylQu#E04wCzgE5?yd5ntHmAUgT_S=HI3=njg3{!)05EXp~$fH zVR@uVw!hfoL-V!=>9}0i?jCh>r+(89Jk(6|0o8T5l9*8B;@GW)PYXwAtX6Hnzrz~B zJ%*8IWV3LE+11UQ4!U=b$9Q||oMX>VtlKQdt*0h{<~&}uyq}qiq<*y?r{M97=Hp{5 zr5_yL0v>_0XSDo7YH6!@>`W8oVaK^#U5SW?E!JA^_H(LMlyhd69N!U~>PNKf7@09_ zjJ1p5+=DhqD;x57;WS_MsI~OW(A-n!HPBpWo{7UG-XlRWLvx#@7jL9|lIPGsP1hg$ zy*@*LpNJ%vm6&;XH3KxXB$1sb0j689`hKJ0^rE*4f-Ap!JT}AHu`7M@RfJ`y^5xu1 za`p=>y4Q|DHshDROdK}?GZj2b1qeZU8gsv;&YTP!kyoQwwQBc z*c1R3aRK)QJKCA*ejTlTWZID+0zha2ck>~nL4}oz;e5W+@o!$A;p7hv-3-yl1@rqA z9lKu~p_>e6M+XxJRW0t({T&l)9_m5bW@D!Q-m9NY3Vh^roiQwRF7?NQPOYsX{>Yb| zJdzEY7k8QuE9J8Cr{79HTCBCSy;)O~V}^*oe0c@Fm@Gbq&9ob;`lWun7$ILf&cW1D zIwqwvwHov!1K+TJdx%)AqL+mBGeMI>64-$=vbLTok3(pkS39)`bYnCpbX1|DY^>U$ z%A|9@Yocs?5&8W}_Ir7~5<(31*cZlb&fw+UuVpT(G?XO58>A<(jv>p1EnjW8H`#|2 zH2+-~r#tnDo04D@IvgXI43+Skth}V`w#!e~st7jApK~f$^P*508{9bMBrcafZ5utk zO7b>cH7H-4j*xjhC^3n+w|x=;u+Akp2rUhkSjHvx4oEU=Yu}_#1kry{ho{ZqY#HM! z@1RvajGrp;NgR)0ovX<=3U0$7-044QdKk#qz#yiM*|bw+XiD4q7Nqnp?^g|H=PUV( zMIS}kbk_5CdM;|Jz9@}X#2ZuIlpDO?6SmIXSxZLNMDNhL1qscIgLaRw)%foBe=MJf ztvC&y$-W5^dzmcfQC840|Kua$(hq-L*5*CCX(DIawk5}AJvylyWP)JMyoC;K7Zq}G z&ce{3@!)HCYt-6X2<#Z6oh#0@r*Z5T9Ll7Vs=E!bQ9;*4Ax!x2 z3IF<)#oyn-n%!ZXb;q!u7ZRsk^dwycXT#xWdcV=!B<55ZeBwQe^Tv~{OFYccF!f|5 z?a62*l2(YfAHD)2dr^fz{Z(*<06j`l>V(l5S^l;H!E;JVqBiOp?4|e2zZQAL{@N~D z26$-PoXhXsPYjQ#?sY-U%WeDi;%UtDrGaC3_{<7**hDW+F!S-nR}o7Ek>#dhY(}9~ zm7NWXPL4auI%8)gdCm6Xc_TZ@fG^ZcD$6?CK`4)ERn(Wr>FO!+5OLDO4Ai*&2GdJN zJ5iI!w(xe)8M(giX(r?8%;9z4hG1I9nhHVbk~z``ge4lNa63qKNla16XT$q8kK7Ze z2$wKG`Zy;l2AF_#gWgVCN)w+nbZ;9ch01!Z35K2~QX#B=u6dWz%O{lWU6m{OcrO{< z-RL1Imq%|NEH3brf0ESjEujo+D8;RMm~4oxiIuj7I32Bstg_H69`@A>*XnHO{%rU> z{%>$YXbHAh>&%|RtP-aE{M*u-@0hsyq@9IyZtvPP_e7I1u2A#1s8XR9f_Ha}Fcb^! zE7xJ)$+zV!yF3yZa$706%*T5hY8A^jsnly-^kfsv@V8m4Tl^l_#2jWaOw3sZ-2WEE zEo%^kbbc%HNK|7c$|Q0M%HFjgp&fR$8wbKBHO6*Rj;{_{lr))(h>1QzpD6(02${FL z^X{{WbK`fuR+%OLwq)!_jgka$6$NWBn zRdzpYxp#HkwZtQjsz@3us=x=5mAfKD&GRB|9Gy*><>a3q$$xI>Q|-=4ybIyZyz>EL+$rC83nTQLSEz2%sS*yoAS ztJPpeb?3}HT+^4sHd)YMteRaH%k2n6S2^`kUl_qtD^iXR%4;Z}gfo7YsO*m_d^|Q4 z`DPK+>Q-b|ADAr}$#c(U(m(n6~T0ts-A zjT9-xD-rgF;a`W9c1d={cFrTE6<=29hDxVD+}P%WIuhp5mXX$cZ~dH(E2%6tcH(ZluJcX2fy^mglR>;r{!?+tcj-*flT{Ohn8D%o$hWckXX5#`hzzA%5m6c zS+QxajnKoSeTSOM8!#D|K{G@uC!CE~OEpR7^#YKSJY;KBFZNEi(cFB6@)Aa`i<4-< zzER4|y=u2_O8ZGUS9%Xv647j$wf0W$!azFDsR2J^mAWkua`?p}Ojpfj2L0RD;S2%h z788OzpOf7Dc@gla+nid(svVkPc=+))RZtf5-I*&QUG29i#bT1(Uy6>4eYbaYxXbG) zrtT|khmHzWAl!3N8X2TbYG~FZt-A)Tw0^|^Tb^Ar)Im)|dFFvyJt`EuHM1?TLJd>K z(Msy#?)EOF^6x|kBDC1C*itR_I0>?|BHn(c_|pR^$>z^;Ta>#(_y5zsD5JH?Ar6a? z0zcZm@9)o4)A4cL3;cjP0d3a6W)L;|Itn$C{PRPa(z|P@-?7xSrKP>8>YQD1*1|B% zo4VK`5}j#j!ppct3wKh?BnzZ22w{PyP*4p0;r;8{2 z4ffz`mGfan+M=*eRWc>dUOh;b{>gJ@EEy|}Nui64;&#^EhBYNc^z|`r8|`iw`!$w&5RZ_5wwq-b}?B*-BnT@(k4aZ<^Z z^+xHEgswh^6U}d_QWZ@oGLsYVMPB|W^lXpn!uP&E`IVlSr*aC)3-uJ78D<0C zbJY!k;AkRrJC%ApS)sx|>bO#=UN?tLK^zx#P#IH}FEDmGvM2b`-pN_SDnvw}7@rg- zvP2v<;o}h&M+T?76*L!O<2`ouAwe^W+NzyjRt`T{3htQ3><7CCtxP|uDELCPGq*Z3 zbT2ZF={5F2pvJ+6ckdSUu<#~hVpa~dev03sajRiCR{Ql#`0~kWgK@RX1t&!P08vs| z?rz+8>`sLOGIM5fgj9+EUrvs%&c;rkN9jM(4{l8XQ)hRH0 zM@D-_t5$PE8KKEcLLQwzyjCR>sVlo!xtv#d0f?-lx65Z!G!5Mvi&}4?CjcBugLFtr<4JL0#CD2-myl zAHd0#SSvJtz}L(B0f32QCqec_dpk9dhnQvnrERHqi*%bQx&Bx>83W0sG>Puy^%N!c zy<*P}S-W5jLxsqS8qpIMK#v^b!$nG8g-xA5*0yK`b%H96ax`8sZbdIinI~uIv-83e zXg{c?Rk_jx^G&y1Ji~_9%Fq6It6W125MhJd%=dh3hPz-4w|nq1_rYu&fyHm)fYsnu zjXiPu*EhrP9Sm^}5AYr=qb>9wW6$H?dcbdi%Y~J^hqZ7~@>vM=fg1#g0LcDq`D-K!j@t7OXW4YaNrUdAOmidRq6j`uSb^A)zO)mFao!KpTN9a9&#_Nh{^=Cc9lvwKmAf34unI9<0TR7p?t&c)>9hR?~9 zD{8PavYeexZLX3)*Q#GTJ>y_;+fBQH%&~Fp+`M^7fl2ms@oyWwAck8rzr_pl{9gf@d@3&go3^z4cIyeX&3MBkuc8!7gtO%zyORE}mS%;bB_ zx@8}D9gP~3hs^FS`K)0(+eaLkJA7TP;Lgr9GuC)oXGPIi^3L?)< zczka3C`qteS{VY*j2Da{a#vQw8W7geDk4z!#BY@L_KXpbhlTwkP*bFLb>hUspNp#` z|9%LwTN&#n!CM`*#Rgx8;4V1g0arxRKA^spVQPZPpX9AkrTgH70b%SdqxBS z^9LA`r>kIOiJzZZeWYvQ+gtz+IIX;L@7RtH>Ds%keKP;UHXN#7O(my`eL_)hL9kfXmpWfF~PT)KEIYpEjG@>^X z+5K62&J4Q!Z9FZ*Eroj72|ItlioX_X^i#Rd zG0s|#lCx>Q>dB?dP1Xo$^lK*DJiKTc+VJH2r%%L}y4}ZAj$;4xHZtG;@gNKO5g;|2 z1v0h@f}XAxZk7=H!4T*n(A{TIuX}?JeLEot2_oQzCs^25m) zzbsi_my&1K4pIJA6%de_I&W{p^=HX>oeiT4=H$P`+&zy>6wDoGZ@V96a?r>k(pCF6 zWkkmo(AEECa;@y>>NrmUX6|BAthKx?~R| z=g6mnY%N8`I${J-g_vi7Zje#1!9}UzmKx0SVr!`V641wIC zz~2Zc+i!pN_J7DanMpVQALz6H=idDv3cde#4LuYfc5b>s0th-`E-k)#1W);)Y!5;E zb8=W|?P*6O3C^F<(6aF{vWzhYt z9pvM9?|ll^sv?<(1ra-t4#bOV{R$Gm)mJSZcP01(*=<~d2e;FZRLrlJ3d*;w?L&)l zspE(laya2sG1r|s`zI(tdlwn4o8q;sdoH%FCBZ6oH`!hg1>=JxUAau1bN7@~j&GHU zm++4rG7d{8cp#iR9$wT-b!$w zju^@P0|texqN zb3u{UT3l0(0j5M#8cA@`4;|f{#0r77n2ife^+4YG5e zMnCU2^+1EWhHE7M-0iUh|JE;rXy)^YFT(VGn<6V!BznYS>fz zz%wvnbi>|2;UaCS=T%L+Z%M9}+*CC+J$C>*5HI2+^aH#xqSI9$Jfh7z-6;v1b?=}) zsCBHdB?Q+{;_V8r1yq3-r(DT3;dsjqcCdWAGit5Ps3nb?1=`){PTNAw6=#2G;u1qq z;IpIZu&spqmX#M44DX2}XGe9P_&}ECpO=saue;tk=Yv| zauejR_kOxmMp3}IwICPao$GYkw>dFaV$t-a*mj9vqp*pCCyop)P6h|VCy=SWR^FCx z(r3bJ6cx!I{yf54-DoOha$Vl2mhw4BxYO1YA1u&s$40+gtKH*V!TVm+OFrIQxse(?T-U*7&Q#ho_~P3_ zwKJid#O)8Htj@V&algbvhkY6K3))bzi+`_hWyN0f`&v7c#%sVYS+wk{qc^EG<7{41 zQ>w{xcjVRM;z2{@Qj{-g3;zBBrUmT#Gs)s``_rF4yA*ehiv6;Ta`5${FQ$3)3T`cP zi#icjQQ%P0IimDIU+SwC1i@uN;Szhf?9e@&A#iAKe2GDPTcK#4#XucT+6L`)-D zDWnv%`}r^(JpZ8int9%Fq(hUpW$gp=96q`BtIMW04^s3HB3^MSEF(9esN=^_W4f%} zj8_Rl(%)tdAYU6m;W*F~9ng-PF7#_4t7s1=;diDk9*vD=u9T=m6JuiibdyE>vGy_d zYbBoPuK!B)vtV2ldcZVI8tT@a+%-+&ML@f)9+kBs!vd{givwXxdNS>MESnwK!E||p zj0-aZT^X&|o?Cq3Rpp#y`eT7V1lC1l+|j>y#r}Rv;K$s?@@CvH${pUP^K#zu1EZj% zuY5w~+$MY5S{IwGJzF3IU`|i48f`)W1Kb;9aGBYlJ|{8_>nONbLHem9D6nNM_@ZH0 zQ_=W7YH1x6hdmT$MohXW8D0AeN*p&YKJuK~bT}z8c!|3+;$tMpFzENF9ybY4Ht==H zJnJR@-Bef=yb%#AS@3k+%TTV<$LX+k+$`;#J`rQx4f6be%6|?$*6ltc13OBuh2k|z zJho`x^;A@Is&0fjmQVt6!IAydWmfqY7QRVNUd|aT6I=3zseM733myZ#J2e5CS3c;I z1<tdY`TY8&50e{x;|})hd_uWt?Ob8%gX2*mrK+D-EeeQ; zj=ik`=j<*WUhA{e^WSftR1aA`Ib=EV=)@<2aD1EFm~2;pXlKjrUl3ANbEQt-iLlMf zo&3dnF;P%|*+3M?6kjh}|bN20!ye zGXIumWuNBbx6{I5g?~t6PN@B8f|v8}i5~ysc-nyDa;p{nSuPqCtGV(S&^2+1rHgTk zC&160YJb21ib5i%Y7J9+T^_nRq4`qO7e6?orWHd2Mtpx9>$9T}&~Xg4LBo2H`>vXv zYrG3EcCu4KHms| zCUEVCj0~aj%c6nx6A1}$VKwdUc2bHkh${zt&ZT*1qCg^zvO)5YGa3K*5uYQ{4dNJw*yZV7AXU#Xa;)t-B09Dp}t4jN5TFX~O~df*KIpqFr91OKC3yZROIx}5%IW@xlShuEXfQuG8y}&a z+hq$|PlfZWo!k~3XYIiPd==Rc#m0f`F-mUn4YVWq{nreolH=wRQ+I$PLnU-Ph6rq9Z z5pfjVP72%$xxLd)tu)GzTZkM)XbeNc8DGT&J&)xtGPg+xX7+CtRbah6BwA_!1%XY; z|03uSg^6A4Rp2ymME^I`5Wc}Y)Sz$i`F4&4-VEyJ9M=eY*fKRDpgw)2aLD6}iD09g ziy8Z8C%gx0qWJyk55rI^5jQ{`tS<=^BEA_rOunJKI~($4B=BAx+H1$*>07+&MSI_o zwrS`^o~gC(BGdo)AZiy}uGfDY0;XdAE>O@Y&a+hIfZX%b&2|78E?)77<#eXr|d%t>^K*)Q&$?}qeN zSTo})GT-#^^L@4%HuBSdRarcn-w2~KUspRuwG1XDxrW-z(M_mu<@~~UnmU^$9BK9E zcbTi!8X8mbIz_h@)R1jV1mth#IlYi(le|cory`ClsQ`_s;>qCV2^9x$-O_BU<#nBV z_$TEJ*B8PTu2!i*8y{RRvv>f*ZNx-dF0BspLed5(Al4%pDmc*@pD{VE;T}b#JnB3J zu|*h$x?A?23D0RC$fBYThT1VXPGB%wwHZjs*^yML%xkJDEoH7;xl)|um3m*L&b@5- zWwN*`kNJHe*{O$C?&L5qA!QmLprG#kVci||Uar1#f1R^7DvSrDq^$R~<3m;r3xwDde1K{l2xd97) z1xvQA+LYfrc}0tSw-fd8HPfJ`092y+64fL-uWsmizZI2K5g8?aiSG<(j=HT#Ku)hR zB~K`|Py#C+W!$2!LwxDax>ocQ(&d|l9ol#zL(i&RZKAxkC{O@xIb}=?tYsR-G5WW_ zlUrrxW~7GAt$w4~x*ml5-A4Y~t2a){>Ul@5W_M+kFKiVN`cP*-`q0#WDh;$i-nunFsd62~;jnhQtObJmp4 zHQ2bzq{lZbeCfs4H=8BnwN>&Pvjs#Of4G~lr>u?$^n3)g8pf;zv)q_>`Pw&19xVlr z#d%EbWhmB9*a(zK-(j3bbh%1!_p?A1L$`gsSp2FeaLt{#)CIN3H070@6F_JL#+*=T zoPClC1j<|3lUf?-Cg_3UDp6;R-x!5~iO(Sd=pul+O`mKv^3Gle!2Pi34xm>~?B!Qa zMy99prB&RtGhT5T{1EsZ+5kM%SAOIF1oyO8UlUtjsmgD4c`4) zeBaTZ^;_cGJKw(V&6Nfn;lMC3zKi*Kf;N;$A!FOlW9>EfUNIrzf8JqR%7Zn`k|!E; zfx^5?80P_!$R86exH0_8{u4>nf9o{e#?zqjskor4WW4L&bqphA#F$=u~W&j zRJ(T!uKMsyGR2EKO=_-tra#i9gO^ISm-*inHl-wRS z#8dpXEa|?Js0lAcO2@Z#rw*s6%EXC~kPHv9ZfEx1>t?@u9u!6-$Rhy5D(lV+ck&r; zJLlv$B;hU;wFE5#X((gVB=WSduD-f?EKp}3u)pHMEMw(Lc1Tcyl|H!N@ADWB((I!2NczA$=yhVU5pef})cBK}~w5w2DB7Ysn z7}nhZ`)!)G=#!lS+2wPT}*Tex|f@F>cHr;gu>-69_8N{eGU~Ub}m*rcb&>h z=?u^i#Eq`Evep%Z53b^RV!rL%z1fF2sWi1S>rWqMc(K+R0$MEN zTU>?B+&eY1w)Oulapn@R0pxA0byN+T)gwYCHxrIK!ZzZh{_)vr{>{Fu9Y+iTU9vA| z*Mm!Tsr(Y#jat)AO<7Uhx(AY-jY4dVw?Wohan-G>*EN1^bjPysu0rF*AQAt}bn+uc zx=oje1U0cF@6X>sjIS@dqWyhzfMe+hz(D>X$K_lWP*yG6UhYyI zgW1I@d2`rtZVP38jgHi65unj5&~+i9Z@-b9vyzqO`4@oV=>Fy(4-i^0aadldUA>bZ z{#7>TUy!k_)fVtEz33ReCw~^K^(btGVK#3kKqJIN@v=HLfS9C_tb*f74ylqUe7+u~ zy*q)rWB)n7cuTe+mT%SIW1Fc210MHpLq{G0>aq%5bw&fZh9D7EC2Nu5F017 zZP_cpv=vrNkAR9lhPM7dfaP-rj2A4pe%22_#fvQv8de={Rwl=Hj>bpDdh!Eo1#kcz zKO#Qs%Clea$FC^iUAXdZ9k_E#ml#I;PU>P>apoO|byLG`nv|5_2aXBsQe20@g)rNj!_IvrJ>=#dK0X1ubK7Mm~?hyuOKHvk=b zpDvh&p~-!d{`rOk%)>Ou-R#?kf7c(^gvVvFMw&nWQpMEX@60*-8IN#&{-qx?;hs`M zhwiulI$wz);bK5YrUF~f`L_)IPK;&afAN9i2N>qyxOCm8)@42+;7e;i_1_a*LG?W1 zlO2&dC!dTIMiP6I>vTX|cW!8D0G~eVl_zn%oo@6W@3lqxo{~Fs2MScx1OVlh;&Q?X zhyDUgK1=vGm1`8DizU0sRG2(GBmd|>tbUSr7 z2ipMsx9|NC*{r47Lr*>p^Tg;bH~ft_d(a-SPH*`10dD-a<$!fv(0@>xT>t+gCpJa7 zpYaq-!A+HXCTG?C2;XNKrzdQi{3VJH${em9JZ(Zi_hy_xwtrh$=vrfITH#{n{-QXL zw@r6E7=?UiP2EHJ-_7AX++r%xtg0BsLIxd^)ift|&;rccCJ&wFb-Varu7?`w&}|nr zYs2Il*Hx=p7obL>smUouc-wQTHc00`9tF`B z@%oQDsU=z^yC|V+}}##X}y9Km3lhbd7UEl zU_pTOQG_RXCxqF#_T}TsZ|3h(arq`Rfs@U4-Z-hTU2XEk;=ty;dx9#)nd-_%Z?u%j zF&0KbzVB|%WwjMNJsEOH?4^i&!^g6OFa?R|BDC-oYthFdT3Oz25^?OG0Ti5L2Ekdc zXtF)D=YlXRfn;`ehHQN`qu_t=_TF(#ebJhC6afVh5f!D{rASda7>Wp}^d@d;HCwx+;hr~*B2-WoA`KrX1pQmM%@}j z#rqL(V`Q&?+1WVkSgp8oRQX{Fl}Jk2=epKH`L({;LUf>+1z@Iy`CvcgHut7HP5Eu})Z5b37*_wgtm`+L@_BsR>lQbaW3`ZC$<-nX*zx}APH&nXW&9l!y zJc+Vsvi&UTJWrZSU_903PQd!zz!|#fX8UmO+?~EL2=Au64Ea= zQoVloRjS)d8}C-@fQn6nyq5^0RJt3yx@M)TyY+igN5b_ecm10qD<_D)Rrs<7u)R+{@&0;v3F05^{S&j_6^1iI$}EltG((g|gg z*jO2>4w_niGhgjAm@OI|Y948HQ46R8@0shnXxXQ`Q1B@#L9{7mTY~nsfLh~k1EOV{yMQuJR zzB#3QZX`|+9v18gjG7l$r-~OHyzh3*3hvi!dzuAWnu@;kRok`~c-atkM@}&&9+ouw z_?o>xd7pTq@y6kuCITO()s32=mC2xYF74l^`KJ>mqg4Wg<&CV{yM*f`+W8HGKJxtw-NMSQt ztlYiM2WhvxF&As9mU(4?HFNc;Ysl|`+nUEO@JBsd-F?%zsm+0vJ`^wXzHsfw7kYng z!cg>j@#GDGCnwOS@B zT`Zp%L~5JtZ2q{C+GDV7mzJ345`feZ3*lk}aRFlE_9t~tOP0%csPns5lS63nte}Y; z=Iwi;=iZ5A++sSLgxS~y$$&H@YuI}N&mOI0H_(%PhsSSan%`20)Hr_Wun^}!f?21{ zVbhSnwRaw)^hV=1|3LSBXuD(0YD&7d{PZjH15yoKWnoh5a_5{+$0z=+w5v64{UDUI{M zm7Up2C;0FCD;&?JE%n?(9N2B|Q`z=>a&_{3z{(4|pzxyz=84ezUWv_3uKRg`%uLeh zL`q2ErIl?%u9`dYpTwvi2NaGcGIPM`@aJoEGfw10eN#Z50Po~>KfO?0u&cY|`}ScW zdlA)9FRK%~Z=G7;KaRkjQy^dK82O^Y+}z-Tq3D^QpC=&$XO6_cmFo_irYJlUbT%X( zpnq;hf&G;G!)+@D&aio;wWi%pqzB`tqxRsoezqA0k9wrCw5EP=ZiURPC03_p03pwP zuL$)E&sP35n*Wd!q`LFF-Alw`XROoYG=YcDse+-XE&q8yfE)%66cI-uy8c-Q7~u;LM*WSw02v{B`PX$e>}(s@ zI19TtdulM9%VYb)>a2S=rs!cYb5E>Cvn)fV1`cRhU!YtnFlGLB>R{-D4%}BGi&iB# z(MEQ++Fr&QD0VO=$ajniNDye*CXJO(qG>vOdL(-Gopb6-VPej?jwHvlQ-?(Uyg`jV zc&^Lssr` z9?m6qmy}moUC|Q_P5par7$IPPq}xJnS+h-k#d6fgNJ>3I)x|a=B;XdpaB=krRe`zn zZwaIt-RM8Nt|!G97dErV<(>UMzGOR5|Cg!z|MdP{O7g6h>n+=uCXJ$Otz4U-R<47n z`Z5dSC$95}V^<9%tC1=YJ`ctYO~z)!4HWj=Z=xucqt0KO;J-0C`tZ(G+~X*{QVYWT zXn80r!N*XZ))ya9hBLA%Pzlia4CYPH=|rHZ^S$ggzTP;Jg4=_S#unuiN^h=}Cr5Y5 z5ehc0$Rwhud~s)>_NOm)+uOd=R5T?4FPkS~QcovHG^pVAJb>q8`2-LH-%+ErrC4OJ zqtFQgR*@oR@iLxI@G)bZ4Tv#0UFQdzcu#=77?)Arjx+fjm#-e(&`cfck`PdxL=kZE zy3C>`Otzsyv--;7x|M5o<9x#fR#TYT^@-|!mL8v-I&V23xfrIm^q6Oi{v$2<> zc&z%d9Ur z3O>p+^MM&*`AY+KgXp z&$7-+s0=jk{T2uzKEX4f0~|SX#eB1FqtK~&CxBLyM)-DpyM-3+aCLZ3!nP|7-I_tt zcU-<9>0wm{3n1`AT9UIJpi3UbBqdZli8^Qjxh8x??$^5`)_8YA4H9*L|`3)5G za9mMHHih^_;A;0i?YKE-qF(A5nJrnQxp-GIRRzYcsxUKu>eJVk>}t37?;ijaiUZSG zW~AIywXZ^=#n{A%oa0Y7+RBSl58qh46p&}{^!=(8eNNU8V(tu`g<+l=X?%uO-Uq2g zKWsfeM;05`#??1rUd6cH)O5DOGVd;ln1nY4E1`OPTCKlo7%5T$vE;0Iva&Y@`J&<#q{K;;c*pr6DwKEtWS9b2461R|k|vc>rEyzCE!uL<8{1Uj6!iGK&0dWAcutwSuS*Ah_lbD2 z1)*#lP;82>=W4y+v zsV>35YfqySE+(V5@U6aOur+byEU)!=mt-KMfxK3sE+V1!jw~?i=HSb5i>gw{wG0b| z(Ha`Qe?hYLMu{QAkNsST$3Tx?oucOuawVn~mN5v|Qd--qpz^EU$M_XM=NhP|IfhW&Z`cH#-26{};~mBtb->bUQX zkjI++4rS16}%;$EME5`~CKNv;=NXh507v5;E6;&voz# zyX$DSo=a9jvT4!m;!~ya7)}hVR?uw#|ICT!7Rc%A{QxG_?$N8%8gZ?-@h6RL9?g>7 z{7w(39ZFW!xz`}Y_h70ccYc!_8vFHOjvK%V$7VD4y}FOhW<;U;OI{=K_IA{=2clRL{4ld4e zTo|$I-8`&${zJ>LwfFA(JDV!z1tCG(g4#Etqcf)?0{1B`jcW?Ue9WuaOWA^F*bKKR z1p#^WlV`^^Vd1U=d^!i!ZeXf2HA`Yr|8Hv>oVXkHt@o2h!rhNnUZvya7)1b?J?e7mgR>`?Ha zd&xzsv5jJCFXy$w%3=rL`g}07!akGq2-Tx31t$QHlH}CvV(_Ti!-y2pe%egKl;@{#*3jgXa``Ej@VqM#^@KkDb$J2+Dlz+qaigZw5cR zv!-JPT~vJ>?7iBPy&p#DP`7T8;Z`i*jpD~TEoxBrH^iZ@|ZF9cRd|H zma5}89_i_Gn=g#T!+0x7^o7iCKGC$2$AP(7az!_n-P;}_zln;&nRSD>mQ- zETih_-Bu^Vz9#U1z69*YXl{=6WIWed9Sy1IoTu*z9OQ6{+uhfo?3WzmXt+3aQuu4; zdKu@`MN^je7ivs~myW~?W}efiJ;-5fWv>YuF4*7c z``K_Njf0dl-Z~OXc;H5+2)(tK%uSgIGKt7Ova&YL-;(7%BZ+Z?{FUo0_oi) z^ahT74vj(g?r?J2Sa~Mx#q&}iA4BFm+H&1b8hR~_OWdPL1}}};1$yI{IP@Y`0&~*Y zJp3F&2X5@M>*u$9&ju`3KzGK+I~+FWR?ON=<)}TW5$Xp4Ig_}q*l!AlLJ+Ka5}^0J z<{8&&;>r1}F#2-!267z4VH9yxu8q1qQ*LKW94x=g$}fXlJs|V}k z31K54t@n(uec*SQ^>x*!BNtCLA8T$Jx_DZB{2_NlI%hJuhF<8!F`y6!P@@gkQ$39* z`frIWelpNFz@hOk{HU?dn|Miv`G_ToXsjCI?=#C{WsbTD0WD`-;d29i_a9eaXjuRu zX0%i@#jA+q_MmmNg$~$v94QRt{RMi@xB`Yea-~+>|2&AtfEW}wz7BVKV#jun1eEr( z7^Dw~a`x}*!k;>!uI}`4g9z=jz=KqF=g-ms4a#hBoh;UCJOaS77}pff$`@t3E5lwQ ziXGkPD>2}iOMFsJ6}`!;{uL8>H6_-+du+$9irxRQHrEp_gYJDZ*Hcp3(=kV#0Lth@ zI%=n0(cOEKZxBWr4ZPf1Q@tI&-S2dwJ8gfwes#R%q877>%7U!dz;U3AFe9F9Vm$Qy zw74#U*T#)oqBXneZE^LmR=U*_rR)sr z9?RKHPftT%s-JRBYm8&TiQ8^g>ecJ z6pA<=PX!rX-1*22kWI%IJ%9|e#tOyU=GdAkIow2F^6jq-D+qRZGflGjE79U&k0XwW;@Csw8+&KGT4|PF@7*mT=}P3jyu3LupFf`7C>J>YR6`wXln~zMKnX`%OH)ke9;8IV(Rv-%z0IvbU?w?yr4V|{3lz7nv!CqXv3A9lzzC3`6 zJ_$CMLpIfBj5@$oC;YvkT;P^gTS&-EHh>k;wXrYHI-H16R^P4`A7^`f;p6n_%LhTA4WCnPeyFke0Ag- zyndS?O(`|BfTZDJRBQEd4y+CLHP>!TyIS<))qY76ypxTylIq;j$z;JiLdQs2c}~#c z%?ZWr-KJe%v*tR2*#Ty1`VKj58Jwa!hfyh~zFUj#(I6vBBHYN@sD@X{=(^pXePc!q zw~=|tn1@&P>bvINFY!Y{ys=6^ZV1pmK$JM%RTtsH)y0GCE>A^4S(2NU8Lv^$=zv}^ zsjT4L4GU>8(jzVGl3C9^tiMu1&TNT#mQ0z+S{C1YqWq<>1Z`Ra>&?fSI_sz`?KC?#Qu_f3xuCA+h+o2yB6MwU02T=gvu zy$QuOh98qa3af%~wD)BaKSw*}cwl|?nA~I1%*?yKh@Oj9X&_MYF~Bd~(100cVPZQ! zvgi$aF!JL*=(B;?71<9XuM9P8yM|XI?6gJo2$(P;l=iX$a2z$WsiJPSVLpx zNLFMOyJg|CoQ7{0HI9Q9EO;N0QUP%GD>Jw0%Rx9MFqiO|Q|7iqG2h6`p&YVx){<=2 z4Z^rj^l;E(vJYjNcSttRmmB8cp{S3d<|z5hC2lBQeQzs+$R!*C4R`^S4q@=_;BE7q zamu3sYfbTzO30nrbBmW}WGhZddBqis*0Uto)UJ^1iXRqfm98Cz-w+;ne{a2r_1Vy_ z&GDGTY_dW6k z>jsf5y~v4+!Dirv{~odv=1g2A3_dN4>pM7ppI-g&ZhT_CST~cQibR`Ox}}W+DBF>s7CNBuS|yVy~6n_FmNa*XxW}>S?NrOq=o&d%kIYaU9%; zj4aBzIr0>S&!PZKi+z#2=9vi~wVC&t*J%9eSLu;=-!a5-*|3uJI~pn&1*pTouS9T6 zcTs0~E{XIbE;bh!u2aHf#v-yyB*Y zD0p|hiWP4KW+8{hgzOK6?YaSvm0#ZKW(7HI-5ZCA;?MLksWp!l*oLO4!u0FnQXkE+ z%gDOe6Ihi$Eq7P@;|kN`cIoLwo~qi+w)9T}Z&pKTP4D*MR>Ii+uJkY2ts&u`*KVfFfy@ zFYuCs9s5V73+pT{1oL(B2bQ{H(VkM)N+C^pfM)0Qw>N-OsSEM?o4~6E$86}6947ht zy*~)&ach7=6-Unb#*-+-I2BMKxc0PL-Q(S-4CN`%erLljV5kf|o~;=bZo|2JzaCY%0OkJ!BdwzjkHgsv z`}V6??TPXH+YkKJ*%{$Z@D2sN?Yr0CoLt*PdKe^*5`p2Ryz5 zcEC~&{J+x~7wGrDlI_6OzZNk4@7C2YzTp2&CYkZ`|5)o;p6z<6<7}CJ1L{&2mp>hjiYM-D)-s0A{2z^5t=$Z;M+PYM zA1yQ@k3^nkqQkF3Bb3w3XGTW4<%xT;6*>o9$@NH0P*Son)A znVN6dkdZjrXumu{srrp5I|5o8^e)hsn;sV^!wp(ly*!`h7Ap?$i)ATRje7#6J?i)s zW%FYw4{i6fonPWdsEn`4TaX<+R`GcC=UQa54Umo=19;@Amf#2(SyF8;Af&SP7!@G+ zcy3yHFKw;*k9~Rl&}GN_Eznqjg#aYVv0|TQ!VfF8z)fB$?=24IL^w1z*ql~M$Eglq z2c0XXPxqGgGvlm!V#M3yiti=MS9^51+2gz104V9&PLLT$&g7kZw>#lrgHin`RzBo7 zA0^R4>bB5Wsa}K11ngLs^}>$CuS9XU{l))QGd3O!=U|hl18g3)){Xa(Z zdIKFQq%yw!$xb$S^H1;$0m*{Apfm`H`NE}!kO}7kX0Y(>F7tD@{DR^u9g#L|RW{a= z?9RfrVFxhHPsDXfyAbe~I`vR+X=Clupd7?SVPl&PWWL%K+)T2y()NUmey4zBeilAM zwsHoOy(VBs@DB!I7l6O|nK*o}>|(*j*^FGoaGE;VVAC2`vnU~I=W%~girR-ZK)AC zdhlZ4a~jQShe{Tb+0mQ|^qcK4Qp8h_H5a4v8qZ(oCdc4BITNpa#7u2H}+TO=o3n ztcJRixN_1aY+H%cM5p_~luQx>ym2ngJyr|TYa=JcOLSl+P-KK|P0Kra4!IhKjsIpa z{HxAEFC-+Hik*XJNRO1YrseBWxXV1Rk`#>gre4;;2VjSTrv{sBYWb;?vE|g} z*vFtc(CrP+Q$T9KxW+D`P#x(JvL~ruC?7GjA!G+#)FCl)OcHsmKelW37#dpQ5P_~1 zuG}IPn?T73g-Ei;O9Ni32W0fh8qvoVzRQI)4z}z#xz|0uFXvg?+q^4)tI@W?&12rM z_*b9q_1RN;q0)*`^R~_#iJmf=)yy!EkSgw1l#QfE#p_`Ir$bzl|Dkl=tU+-}a$R+z7B`#poa!89LQq`KT^{?6P`8`SR zfFdr@Jpo62+GgXhc9GzQLgw0Oy3pMJPynYSY>U~;b|+;# zCMh+m9YmzV{x}l|a7dH=ktu1t)88+|-bOdpL`hnXEk>p9&0=^C>kXcJHcC(pLfhaP zBwzlFA$R`*68ifZFq(_8VhN6kNsW8(f2J&Rgs@dxlyrm7TGn`S^_k^$zT;JQS!`&` zBURtwU|;Pj@W!L9XYXSwd}s~96aEsCcnYS8SKT`U>S0T*KP#>+ zP`@NIHs^wF|{uhBf&3%mxbQFo(der(ro^!X~QD&Zr9bMS*T_S}SKSeAlQrcf- za&Ou7JbgyM6^l-zG;b-J0X;YN*5A;xA?;YQ7O}1q(Z7GR z=L<1M3&Ea0-y^%5O>5ZDom-u=%(#nMTlTe$et?JGZy+QH0;7W0Nx~L(RoQl|JD;i^ zt-^d3V`rw(Pgl*Rn$lc?%c){QNz1h#vCkgkR80bWz9rb|{Yera-w{OaO=)0K)XB9i zI>JJF$>uFFg2Mxpf-voTvRDY{+OXrTa{7Uj=6BZ<0PIQIbqp0%>xQk}GFetoN{?Ze z0sN%qF9Zg{ZyMZ=Ba>9^s>M~GuQ zW;pCKWIj#%)NFA1UAn?Hf7k06jcn=^*fNU>wiKMpQ;S@S8MV#VzB18dmFOOtaZnKS z!F;GHy4I=sg{B5qQD%Fn3fUlIKet27LK8G36(8Sagcp9rqsK$}WEj?sRP7b(rSyG8wQ@ru zCLf#teaK2@7Po{RO@A}HoWuUH+(yakAr~gd?AY#j!%5lv$X2-Bk-|A2` z(Pc4i4#Opr@~Rbp-$_C|38iz(-I}$fjxIY=K(#0~QEdrA!_t?=jF?Bb`I;U-<7nO2F`5Zw>ro>oS^6zA!jcX(`+0c5X1w= zp3q<7x+L)~)~$h-zjp?sd000 zYL<(m!4}X7;mnqE{45~NOmF^{)Mn9--SfaH4`+5=-hHjc6qbMcK=_M&exXDB8_Nfe zvYpm#^+DSW$*~F7`MLAt(Gy$zTq~OEh|eM;|I!GUcW~h?q(1p#h-bS*knBeY=mH<* z$%AbVxEB_wqO)JjF>w5E7$0`Q5P67V>ILRIc?Xot_O}6>;U$SrnV&RNz%Um&R=k4FuPuk5k)S^O&1#LM;YvufJ z{h6UkW|=4g0Eyuwb>^RKN;2AI*yEN0Cx|jWZ{_w-OqC`Bxu;*bR#tQ*(e@!N=8Tz2 zaMhz1;L=snjiFe5Mf%%& za}pxXr&m%$f(Jiu2;;q3j`2QnOs7?cZ{B?aIL2`B(miM z!}#T{K@Ns>&UO;^9&=07f6WI=kHiT2-uh_S=zm7$Yl0;0hZ0Pr?4*++Q^4liv+CP2 z&MA%sDrPOE&K+;&)GZ-!Ibe*Z(&;|L*h>PEciAvol-mB^T*hV##yrIcwD>Qe#mOay*VSbOUW#mQhH^M5hVTA zy=AdB0WHe49}Z}6H(6l^w%h1ObOF3)1agVWKBiKVdjj1~oX_iS26+VIQ0@`#0EHnC zrw+bWn)}6nESR&AoZk4ktYm1-NQLR@X6C< zV4m4wz0l$`S)N*qt1a^DCF~4BPy8QixbKkJ8*WeG-6wIdR{H0>n#HQO{Ia4Hp|Q_i zMGuWXJzfi@j(xO8)B;;qjw`)l42TtU&gIjmHg!)BMQ{NBJ6P-Owbm$c7rzdpzXC3* zUmlSpJ;_FTS7QDGl>`L!`?A~@-Kwp5m^)lT@1}T%4vF697hggP;=QWYmh}U!0y%v70udnr+QL+JfRjsYL zU@x!$-hahJu@(Wxz4|Zcx}X=r_bO&4zs0)a1i=8X7Ij*@7z3IL%mBJ_bP2N0)3wh} zTs#GbuB%W|y$Bfl3*EM=4$BxR*)-BZ9)JDT+u%o&JJMDg82`mLY<2t zjD7Mi!Ww`-3owD!W_UAQ-qv+S9OO&`T0~qe^3!uUSHi`mt$x5gM+<=11li6lZn?aw zbKh7#)br3@v+FnCHy2$oana=RPcK|Ed2V&3%Ss2oydSU#*^Nvat&eOXnKo|ULVtVN zy*7c_NDI+kSX#cnd$U&m01q|fUd_w`$~?lr8L-Ipj9+dU*bp|i8ACr1@G1K%TNaSK*qF#PeEwb_cDL=0O&F!VJNrW4e3oRi5sC|8TSD+t7gr_qC zA%bJehd^PM7|rGYkSS4qg|fq7s=$Ifn?%0cBCc}xU9AQK4k+b>VU9HiT)XWBAPgi> zFT8qFZXVVy`x_cW$v+O;9n8^Y?SVs^ule0XhvwTWC?V^7e=|u)a57*1OFDzL2L!Za z1xM@*XFqwvhVXGjiCkW(aV<=R*Y>Y&4Gudz*zByIBL*)3t!d3^>|uMQ;Bx3m!z_QI zU|wXXOxS>7VMtE17C-Z2Q`V5o^YvtOTf&5=Cu<>Q)f!L{Y>;gSI#!?l1yM+o4^HQTu zGp{E>p0+W!mGBaO!q27t0iS>QNFF~wNO74cVSTZ<#diBu4D!b2%81y5(Gr5gdD2sr zR&>Oa#)X)JT%dP{WH+EN<7iK;$$1kE$kGSrH2Cqt1I3M>$JTy}gk^T7@_r4`&|cr$ zvqVM~=0KBpwFdoU;WzN&Jj_afOkFq0t;9*`J3cofc)f^S2_+Ua3->H^i&?%$Nh-Pe za`|gC-?Y<|F4WSgVYa&jpat~T_tMD1%(>z2pQ%9hgK{ARo^QYPvwKM}@9R~s%Sn@* zS4n5azA$nEBk{KdI_KZ#0TjJ;riscQxXWo9RC*-1av@kmDAcu=o=N#7@Z)Xzk zSGKS^dI#mLp^B)sDFn_B#LBs18CPIOo85RgNKh3OfigsCa zwcvQ9&7qP=x-wS)UmZ3@y8JHYS{(9o%hSnPN;+hJC>I6jL=7o&l%+KZD$v<*u1w2C zg~Ml#u&fz7TcC~LI%TdOuMRy66irEz=w3f#xUO1-0CRMYzqsaQqnAl*U;U50hy!py zw|@lgtNOE-88GxfbsJbEQ=9kXV=siLg3FJ_O3vMF2!Os*NDmlt$lzR|?)LW2QL#H& z+Ui=-cQ_m3#DqZglqKxce196Z#N~nq+XpG{c|R`S&oKCu*FYm!xj1?mp>7_v0SQ}DfM#EWSbeazD% zBUzKI@M{`iW*N&1hibWe(_w{&>SDc^vh85V&?aRs2{HfP&004z6kucv_AdNXt zWws^iLNDb&{$+Zq8?EKCVr=x!S&7M7W0G+mw%WPGn#)4zK?mFsMxsX#CQ zbn<#@x82eR=qywq%!W!3A1NO_!-!~w@1%HbpK2>{3UpTnmRU~-FgZ99adCXBV2bhmM(IKTa~O!>xy6f!L2Xa-`~%q z*86YI>ebglIL^uMJM=YW0I?FwR6zElZ7o?re z&mHzlqmrkl^o8Who7}ph&)O#jglaQtMT|Z68=}hlQLQ+H>nV_7;+yg6nffAwMENGo zwy-g20D;gxa6le_VQK2k7i!9e=z=GbP}tliaz+sBUCX1fH9M;#qtRz9S`fm9({=X3 z4>Hvv=7FVtt`8NOe?zn`v&r=IK@PRyfl`Oplr1B&mk7H2B@_*8R3mjbx)@muncS0? zobF)?P1=b=tFz8c=M#9h2G!bQ+9R2fY=sm(Yvq10&8^}Z+fCuaS%1lDu3s}-2blCM z$>Aa&+(YBl9ae#i7|>%{_D2QKjYYlPD%w}CVOU6@OAUMiW7S5kJU8w+{}$c7(C8<^ zF)!_|3P2|JaQ(^K{=Y>n3)I4J+Un2y9@_leG#aoQmtNZcV&-A=`y6i1+u_hajaz-F zIqvcL{TT+%9_n1;2y6;1eiv$LWNXFpO3P1rX;hT5JT=ME%Kn}d8-(P&qyyW`X=ZYX z*i$)q#w%1P1}zc_h{eX-|3VBR1wWrjLw8N7E2f(U zD-8a>X1d|u)j2|X31&Us8Wr0A{JRnS;j%Tg`ylbe+Kn4wsK5j$!aabvB?F z_+h8-Ox}nqkGav!LlgE#tH`h3x0TdgKQ+;CYs4=U6m3f&m9;BYM^AawAXO~+B$DEL zt=xSjL%ZaNgQFsW;386v$SmZzZ1eaj$k`14}ku2A^dkif$ovD&7~g_ zo_a6J6N7q6?yi$6S%??Cmy)ho)=B-)ijB#l?>6{i1n_w4`yu5~L69+1`JaH6Zn~@7 z*Pu*<6(EekjL=SfGMlAX3@KJ(!iQBq&yd^{r*^z4W$t)|!!P)?5og3LYlI>9CT!)6bc2Dg}Oi zaYvquT;uG7+$me{avM+r3(kx>i(c|FOrwuPXfWM#skj5uQ(J#yoA`h-y0A&=@Wd6% ztD;B9rB#ZpY3?bTB%vXFk znv(C90~HoPk;g5ga1P#eH3Xjmukav8!WruYLA?QZvr9AY772Ux_IkPb?R;W~xa$ek zx~y|AtQIz3CurcDd?x%qIPbeT_~9CTSqAFLZ0jXbr3nh9vF?ghn0Z@zc`vP9d9>V9 znGm=ND?Y^gn7(j|rdc0}oQfXzjuy&rz1HDPD;&&WLF5P3M*`JeiRnc*f$9k9Z})9v zw=l0ptR3?jJ(hs6Quu6s4GODTk1unB3t<*b-l=okm)(Fc8Ip@OM|L1&bCnw-uGf)F z-+&2p?biqK*5sD{ks=}6^H`HO_$MGKH0jE`7Kg}pGBiLqFYcIpx@dx6RRtw1NuS5= zf!>tl2I#m>HssX0;W{i)1j}6!D8GO~7c+0T<Fs^p{y$R62g^w#|BsdO z#!hax-*CY#@G(&4kNY>@lbGjl{~40~RqbEsa}t)+w-|43eX6OOkxFYS_Kth41H-*u zGnwrH(6VhB#Ih#qS9d0b^d9sNn=Sp#%m(YUk>QNcLCm678&?(pHv3DO=WqVdAGJ0J zm&LIF*$36&TSl*Pkr6?Uajh-Qe{NGt*Lz+2i^5yelcCMz@|!WsTIx-JO2Zm?&@_bZ zY~x%G(?ZeHrg=9yKY-pHrCf6wEVi#RmG=vRD*%kA3_yVvin;P6=0&guSXLK)Pf$$` z41`AA|D^s5q!%)+4zn5w^Cn<=)SSl_NtLMe^`4Qk3E3~wvQ86t_*_ih7clOy zL>r{&OV^v7d9-ZYeL(bIG9#x5JutKf2r?M%au%wb$#!Bdd3l(2jWNJlx&~>bvvt$Y z3(?PTDsWxq8@CTInajy5j!*5=u&dUbkwHM-*7S<}l_O!lWL)ck{^aOo9mOz({}|<_ z&|;ujC%&PREc!Dxs(YzFZs>k>BeJ@>k$@VG9m$_vt{~p1yEBr-CxA*j{O;{Wx-Uft{YX6`eMBa6(1*igFb&Gg>!;l!V)#ydfq+%F_Er}JVvzTj6tp73 zkB+d(+;NXSb-rf{3(60BPC*z-STQie?aHyn;TJflX)~}cO`12 zM_{@~nLPPaDQ!9Sg+&Axp`}#G{0Tt_g^$O|1|ae4)m3o+tduEKxEU^D-N8lT{?Gn_u3kkrY=V4%u=zF>L2$`X2`BT>%GS^!Yz27Qn%naXxD`t2iiX zkI+Cg%A76XR|{s8!~q9eg*V>Ps +9=YJPx<_xscU5Q*-i|=V#%C&`wzL*YgOwk ze?HX!0(7!)`x>J>mL5p9r>)3;)>;Y8Bq~3OBYwO`Xr;s4s(Y2jlB;f5Rp(!uU;_PQ zbn*Pt`!4U-NwKL*EAo#*mFG63!~6C1E?@2q@BhvovMm-!N-AhCdt?83&OA;CD-Z~X z=!N68a}2HBwP%!pRDX`^HdQS~*fi4~Bo39wqlSI*;oWhhjFQmwu5_;t0@Cwe!uvv} zGtc|a*Q=Jq!iNLu)`xaiETqdyS94k{_<;Nw&Fm7o!6ay!*?V`>xfJ<`?dh%)e9%Vq)ZOt0?qersYE+b^8 zh*(1)ZO;1k0Tth#WG_ijSWf4JO1t)t=Q< zrj?|^dFJL9o6xyAyTDfTa};)G5g$6ZGbZh5x@2~|*?0fjn^SFaqU$2Fdj-268-@!7 z50TEOhdfMHMs|jxzAFOv_iyIF-dKZ|NPFdhD_q~T3Bnof5P_)W zOXcV=u_&DFvyTy+;0t$rXuI>1fX7O#?pMdkp&&K9@V)*>f8sdqNt)7FDs{3JIu*p7 z|74T2GKLDl!*M=603?Q~lk&cuR_cPo=}EjR(t-DP&fG&Dlf4IxS*Cck*J7U+o$@1nAkw{{ z$I;Q@SIe7}3Y<9En|Vm2mgQ@f+8_Gmvh81uIxbseRn;j0v&i~rRlY9x=#3He-y!+S zdX$APBMw9TJC3#_;_C6YFZ25WW1qbHT>m_`6- z4in06ZETy%I`+Pc-*F*5^u4%E&8JBqcQGNR3UHnr;fFj9hUIt5j>>Ff3}Mlpy|BB% z&M@_(i7Kv7I;^{NCwM~i#;-QC+SHc%b(Q%}RPjD=aeL)j(V%sELh;L>fWEBX$n=1U zi`PP<=M|USMgDyN$S(esqqV7WQ7b|Ixu445w6+R>bx#3UcNl{7&nvV&7vfi=tjx zjY({;>N4->6|I&l?}^3=AI`4Yj$Tm!)FEoA%Fwpx$9GHMuLZ|U9S5~sY9!Kb4ZGfQ z7!~lvD)hcA7cu9oKghm4RR3C89?gFhM>7(rU(?x1jr}T_tUUxh2oi1qRHcuKv+lI6 zVCs*N)(j_eh)SEs&XlYBke>VxA>>vX-Q)Aq##zbOl~!b{3ll3R2lcBv1Ka#pjpk$X z_234)a)6H%GBaXo_B`+NfjtjAgX%1LLZ?ytKT3p1vh90EEmnfgiR}24MF!TC1jmsQ zM5WGe%M4|!zYR9Aon+^l$kHQ{WAcC+XM9nwcGkjlAs?F8-R1Dr5nD3K)5ZEVNHny{FTo%b&t!sx{r0~5ZgHueiWP8#(7FVU6i7cY^K=f*BLOWDVxmg zXnxt^rmprsz6z5lwhMnOY3Mg4)fg3ib2LU~l)6rns{qa=DTB+)y57`&O~JM@QVU(j_J zt)1)6ZWw{SUjn}>VUnGo%fLAPOe+6D<|kZ-)9acju(*DpU7dBalh5u3B-GJ+&h)Hl z;`X8WpMUZk-c^h|M~fTQ*z^RD+d{Z47~a_ioVyAbII~}gsyYz|t5}z8`2zG>wey_} z?gDyra?rMB^ES7;kAnLEZ(os=H#!%XPEF)C_Ao9-B2W*O3Oj3Xj0sQ)~>6f6_A=IdW9^)65zUfQY3=!ZTl5bpeiSylgP^0RH@?0no`r z7MWf&&n^2rPy}tlnL*#{X&ME}P57_x1BUGEWfs-*qm{!?Mzewgt(u&SDte8&{=eGZ zJRZun?;oEwx(MxxP*)2PDqF@fB(zz|mc5dFk0HYhQK^K=7P3TkGh-Xe*pebkb_Qce zjA6!%3^QYl<$I2<`+DyCexBd=`ToAk`A@wVGsijSc^=2-cz@oDxOc=e(^rEfUIcJ0 zEk(wYK{mU0-HB}J)A8{d(E+%kKX6lfv-M2ZcE)Yr=39U8y$ei}bA?zd7DmnnwgmuU ze*WO;;T|Ax2?#Pt0?hAWpK>=@jPsZ>WaW5^l~-S%p2Wi^(6h1v>HPysk7}ecGfVd? zR)+ImnqA}*_$7rX(XKzHxDn33-DPdp(ZEsHrXu=n@sV(WUii-k{NbRhJWV{AGycvs z4O2J(XmD8pLK|NbSYsW6$Kd(E?B6q%%) zg^1+N%(Qs<0Hz-{;&+X+Cp5^J_Q+om0zc7#+oC+0c&g@CTIv1Sjjy*I5849Y0i!pd zOE^-gZ-fWf2*nl|nt)$1=ltM&R5zpwV#^4oj3R5Pp+A}eNYtwMSiri@_jkQ7paa+- zHYlf7mI{g~^V>CUthxgQTI5ifZpU2$mO%-(0Db#Sz5%{7B2Ma}WvvquNRKa&wJJHj zTk(1Lo}F8+Zy*;NH(5ZM#641Ye$#FK&&l!mZ<%S=Rh}(@jM4vrgzK|WXJvj9;s^fr zs{8tlYbfVZ2w28#jp5YanHr`@z_@!4zD;gpa3>d_5BM>w;~8gQ_0)aqg<1}`2QG*z zQwG|e3F1dqnG|np?{Z}Q@=rzU)n5I8Z<7;M826!3Zf!JDK3=KIfA~o-NK3uNgZtMa z&t{OL6{&l>Bn$nLR-2nzbx^E4bukGZEscnow!5uu7 zNqv1j1>xIYMhVOANqYHv%ca$93|Jguy)hVB%eqT8FRLCbe*WPbHH5@JIa@=$rTuleIOQs2~Up9E3S#!@_>rJ@8#L@FTu;qD2g>i(!%>s{4pR}1p9SCPY zb?WG&vfLqWfuGe8;>XP>!6nVs%^<9Gp2gzQbFVyNwP(VNgwC87B%zr^e@IbUxDxxvz*FnZiD>1?w^8BO z>fbc1{ERwYZ>fM7=IS`Ko@Q0-^-o&DSlCsvm-+~Al@Jl`ua+r|X<|Y1i^@w>l?dmL zjqFwT;2#Zb%D_SdRJdJD$~E(~69^_CYuFVxqZ=#h!PV!WTaR!Z!moGGeEF4_!m?He zi%nJ&EX>qrd;!IQHa0aY2&=9aBVyL@9ay(`IbS^~CU>vYUl?nUj+EH>roT11C?0)4 zR@68NFtB&Yi{X^Qfq+HjDWuAlqaWz1%=MBF@LDFY&Fubsy4)dF!X4ORy=CCNg4JkW zB!<<>okw*xS86@S-igcIC$=wF0x3L)>zt-wf8_fvwCMf{7Mw2QiZP;9#`bnPk3ur) z*0ervId`z<1Gx<$uH-;2XX#cDKtRe3;a4@vymQcHW%4Mbk{kYw-BKGlBQWOBTbaIc=TTzbGrbMSCihUoGGpT|6mN0(Ns4*;o>=EGTEYeKj8 zYh0cL#EwsU90X~;Pqt)2va=U{46$R+Unz(T$J?8nunB8UGTM7$qHNpO>FolrdnMqysZXS3<7Rzi?S|&U^vHUJ#^J=&R$j24tal&M;mH=D>JGo&0{AQ37pVou7 zMIKrgFy0d)!QM3rX?S zR=C-AKHJ&=jCZ3g;GWwp0K}MoK-*XU5?xJ+Ph22ua64uS-C!A;mwDe2<+#v0cm@)4 zBoHn_5T8ak$CDT~36x^Pfbjdt4eqmi*Boeay25@vd2+VehdV#!*#=f|gXRGYV}4Oz zTu|gRck8_pbn}+bbB^SMnEDPu(8%%@k-%WH-QextbCvAy5B!5T^MFsY5uV?A(u#FE z4g;d2%fa(+B7r=V*k)PKah0vr0hoGZnt1fJBLS_n`Kskj&^NBLFc&D08hs~_9J2Hs z_m7oj+6@D&+5=Z~W=DF84g6#@s%tS++>n(wVaTe&)5|?Eek6tM$ZYHHm@g8-J+tPn z0MXoc6VQVTDRUj9JcIQl+($|s-`yT*@m3jb6$){=A+gruu|uLBc&$sF8{+~W$fbCc z+hDaRfqP_X|C=rdU=K>Ht)c$aRVo_MHN3udo-Duq9qsQkl3+=j}&z}E5u ztK+S4%~)#yGHlLy<^bsFw%V+K`segbR}o+v(*i^rN!0qUJ>t4;ZW$ntZ2kS{!%b9W z+YIt^PUlePW}kWY>Yp|jxdvF1HqDvhy8*+fdw(|*dsX(F?@Vr%PaFu$)_b-44B#Qa z+A{v}Y;Y#|$d#AX6nS=i8DWm_13@w6fSNi8f|Gixt_tj{68)l4gWX`-DYBEZ|^NurJMf>Ka~?HDBJe z#*J|a;`nvzAM}R9aVuDmL`A;e9%9KQT@Up|lQG zRhq$XoM;8+8#AtYIK|Cwf7d%CjN%u}`dQ^Un3{nn2bzz(pXjPI2=;V?hnChWxtrBU z>O?VRKi3ov9Jzh+s(>xy%Mz$t)`^y8n6nScp*X7Js=88cP$V5fh}Of<$b z;cLLv;>Zb!#{b;D6WC)4+4;4ZE3@*S21_V*J?%2v##5j7-!<2?k8d^C0B%JgmnNcA zfgoaix{9Yt3@eG>Zl{JaYLyp+7VgwGP>UD7P895SdCkbMm=`9BG%U@S`6~tf?Y@L9 zDypqdp%XMGtE`5dT;$s~&_`~F+d0<)s4g0+{$2sd+eg}@w)@1=SB;Y*+-z|m6 z>!w|N%js_R$ZiILc+#Z)@Dlj72gh03NN$8)G{+UiEFOBOvCSprdP-Hr3{uUiqtdq6 zu@-f+Cf8J>puyDJMP%y%LDG2;@kk?@tMw}>%=dtiF_?Y4YEKC*3R>xO&9d6`-OX*g zHw`_MQ5%eZ??w$40m$Hvv z;p!!B{k!~wSF7LjpVb{&ankYyu-ov0ann$jwUrLwhP7J!(mHAL)YFLSSl>l+{;txt zcA@s?iySA>&rkRGTMULGY;3B0ka03-tn{M3HNb!jH2dOK4IBm@`D);vN z?Ii?qf%!W(aQ%<=7wRzdg(6#G0RsC#58wbZ_d`2<=$v#pF?MF$4lcJirObdVtwZtW-ABZ03FXk&J6G2fjff_Z^s&6 z!a&8i&Ss_=nn5(!LZyM%MOEP)q$Oi;T3M4AK=Ww8wNveIe2@~1CJc|Uu!Gz zhOHVp2q`A$OL8>~fb+|k(}X#O<)9g`GWo!I<=g4XfUj%kzn1@HOq6*c>%VO*-S%nf zJ-M5koD7J^rC;^F-a{_!1vZ{QAH!@-Dt_eQ6js1od9$M!NEe8HEUx#n&)5&d_4ZZR*53*`kxUC{ALS?;1Wxbscjx)r^mf1z-NHnjm-FwjuCj<2oo@E;qpX7bIfQ~70$&Y+wlW{=pz%S!5!bjEzMNsKOg!*65dCmab$ zX07#?r?fBq0eY!5btyzO*zA15_tQOLx!SQeRt`Mo0U5k-e^hh}tyd>Pa4QD-IgeiF zUc*Zn^gFG~^nFztI<(tou4cPHR!bwkfiW|;mh+naAloxBmx*KA!z<74HouxXrPqC< z=?_KQ-vqJa+fYeic1oD>tiYZX@qo!9AXOp9G23qYsItZ0Pjm1u3mr>=+jt~j(53E{ z&~hPjZCT|u!Kw^dK0N`j5N&`2 zNlyMzX`y3Z*dKS?B|Tsgcf<9WvTFq*+2nAhNx&0!^gOL zCy=)O=&Adxd#y|Nv;1oMRhtb>YAwCKpeZDG3T2RUcJ~QByJ=}5k>8aI=ruZ;E%fE1 z_#Qs#YVjQ@1D7m(v;|l$*cDgUsS{p4y1tYOB<%7u?8ym~`pAmL`3f}sxf+T;Maq`r zC~LHh@%-5f`)ojiuJ{r72PjocmWITTmQlb0#+XGl0{oP$4uht@+haXPwpKM-zh|7?ii!e&)8>CD;{QLTCNCU}F17LO5%J(k9L@!vrMd~P z(Jh!jH-*d6JO16X{63p5O?l|c)?jt^-@Cq;#^_%H(r02z;QFul&TI}_RaJTzc(A#& zxxdsYf3(xQNhG!4p_?)?oQqdu)mkri!MW|UB$brVV}Rk{5{Xh|%#>R^$Q9iS6-jdk5&Cp*HsZ4E;LfbScmdtA;(C1LBz{!b52r zl?ZX5>xaLV+qey+1!TT#1CdV4!cCK`4&2E^|f&e6o5?1wteuO z7oT^AU@$}o$|=%+k`2X*Qi047uH6pMUfPMD6Re{9Em`HYe3)=J;Slt>Oz*5g&;(!? z)KnK!6qEsTpOs@*IOp=Pc{TpLjlM2K)@n6WI;>c5;?~Wk8mCLK`Ws2=<9N=NeC5yLU|S7H*Sj@$7%N4w<9W-r`0!(P*HZ@K~M?GlNn%O~h((@}WTf?B9k=YGNI|i;S}-&OTc&p*ev``~qwsKCP&{}3?~N1y2AQ!5LPyL6&8#Uyv{ zeF{bSSEU7q()T50jN?2O667riQK;{LRH(Do?xClIY)0sMK`9lN%->K0^A)(B(2rdD z>M7sL`i%AyF7YcPPWcJgNzyc4w8w{5!hW&m3f;vz>Ydr?I%C-CHM#~mzk2Emk<=)k z9KL5ZX?1ZI?`aR1_FFmeKryk|u!*1CLn!FV9w6r>&Nu^y*^rrg)oTOo86R zhaa>(Wd6E_P6~e==Q5fniP_J*b-e>B=oZg4C;}Hw&d|)ke27a;zHWPmpJzMNhUr~k zxB3c{q_KhBZOy<$1m#aZd`YE6hxO{1(eQ#36EXt?ETRadt zMYiL(*;eR3PhZCc|8#-a>igoI_seF4Uu{xKI(eS>K#dhL3uaPm*hIH6{W%nD*=9*L z3E!eoITd5;qwyr;Xfmq%cbCb4q9!c|0ep>A+4q;e-IfG}O>dpyP5YFu04py0Qx53{ zr)VEh{EuG?nleTNOaLKf%fKi{14N+7LBFiPk?`@=iu={TR(jP zDKQn3>pt>7-ninX4~ezXpn6E281+Ui6Xtz$a>~%Mn+z{Ggm7 zgjv#4pH_d;&zAi!f{n74s|pySLy&+IjLb$8i;1mM{Q~IRHAx9nk*Jp)-A3IEm88F0 zLu{GfnTCK0)aqY+2Y=3?Fb!i-B6)7RkE%oSae*QOeZ&)lE8 zZwHC+019A`Tbc-%c8h=Rc3?|F2x)*CxJ}bws0ZDQ3#q zdl7|0EkdJj%-c>}uGalZ54mZ1#+gU|`37>` zHCy_F95SWQ%-HmNlHKjTs}*0Emp$Zp4tm*r8h#XL;8_O`EnlkB3|4m@4`QWZCOTLr zqsNmKoV(tuD%6fHy;oS+>W~;qZ(T#67BRJrN)j~4qX2$b${wThEljFGRlA8(4Pl3d z*KCTCmrs8t1>)Vq5M)-j37;989)1!`owOj73g`8`2figO4)6_RIw}U2+-ozEg}Qr> z{8&v~&N*9d(CF7!Pmh(yCN-{S`AM<|`GIS~{OW!XWE}oA>HU=Q7y_Z#bKF*gKpUe> zP=`FMQ*$d4)hfLMA)}2DcJWtw!)D)&{`e6$s<$$0Jkb8Oy{wC!5Opm190>Gdo;xE8 zkZF{M6a*BGHN%r*k-j@9JpITaU-lu3>d@ddUsge?*L4$cv%D9620<(97?bdrppBRN zI-~$1?l5&=XOgKcqlq1@cOMD&m%&dD-(n4=H_s*dkq~Qj{zxSkp3kFD${22;MsmcQ zx6Z`l=8iqVti(+|p>_aU@<}q8rbs__exe(j_BrU^Q2l=$s*aHVR6Aw8w#Hg%|%Ir9NsX#Cw(7TGV z+4k69CKarm($GkKCi-@clhWcnuy~7PKW7D8TIb<~tL)a7F}E~jZluj-rAZRu^S%0U zj7SNX)LDF3=B3!Ve#02Ur0HDltp!* zBJ13|3rOm~9pcZuzPB`N=U)2hr^EU+mYzyrPi}H@gDG<-y%v)62%q0P^_mjy4kYk9 zbw8N39ZN-}8K#|ph7a@(dTeLcimAOdq6`;AJeX(jP{v+@%>#;d)G{?oN zA`Fj#(^0Bb(|tK!U(Iy9=8ZCZIh!l4RW4J1RxR=`Xvp>)mmCLH=WpN!4l5(Y&8v86 zs=Vv=E3xcbw$V(tv+ZESWNBi$nS?!Z-I7i&63hUXiU2+=2C1<*&bRaj+A(kDv*_ep zPG&C`WV>hfx@r3^Y#!L0<4!>TSvCsQ%-GSUrdgzknNGmXa)-D=28QRKivl7H`y0P7 z1W*s*QRd|XR?^gu%-gje6u6}!kJw_v%B?QWK#6sO$Btg>r1BjCtwIukaq>4m zS~J@Cv{p`*26?PvWtmo5;;Hv0CGrZ0mL}63hl|kQU*f0 zoO&1qrxVd3r`hq=-nFu9Q<79vj`SeEChSVT871Gumpg ztPTRl>dgcTpSxCdUf2!dbg2RY%*{QS1tdwQaNb=8nktimh`a#AIzMFBv4gvNe)5Vd zjuyrgQTxyB$RYO5meSe8!4z{ZF<(kG+oQtH(PbJZZ>@0RCUX5k5Ch}NS~b-uUOIAv z^)!g|C)#Uu0KT+?pIq!#TWlfKnG6#QDV@S7_QMlvDq_*IK_LG`TEo*h5fN>*%0|@J z8_q8sIq5(1E*c$-npDHFVeG6c$_u!!y(tpl?4(;Sh&3iR8p|D5xvbtn3cPE zD<@r06QrmHXKCftfiILij1aA1da0~h+3g(Ks z=yw9Q%*FTqv>G(kPkxN!F%x)UZQ?@}p<`mB6dz3T0=&Gf`Q(n&hXcYfr=1`z>q#|{ zc3_YiPJmO!Q3H+g6X#33dKi1ULM}`%FUEP@pLd}JDuSq5=wmAfU0jws0Ay`s79#VY zS85|QSi-jmqP`To&?X;xo^1o$Fjt|MCgV!%fO?3Qv$+!W0RFvu{PuSlFmohy^=I)~ zVxm5YYJcHvF^5e-8XZm@ISy_u#Q_X5)h}J5cDVjfxC68E*~=+?qs?)d3Zc)}K<9;) zH3aqbV^4K_(cCUDy9Z|b*?zYoX!g|5qIsTO+9N1-(9#~Zk#H^LF!5GOqMvfcbzw@e z%-*|m7yw!8Y9ub$E1NV7m}IE8FFhnaB0`ugk5An>VM!7|1HhWU-0$_9fllbKFr^IukGIA~U z-?v9eRT>2;9mpDz*;BeYz36;*_D;e+HS{inc+}KGiiy5jmeS&c6sY2r`KmXNzLcrK zSeExC)bE%Z8gm)2pI1BdnQG`m{}LZe8lLp$r#?^KDqM|w+NR>>M#tvNc7{4d*lEmu z)QX7jjdAe;?!}&q@3GM*8I)u=_h``Aj)_`~_9=IpWPjXfDuQcmX* z$MGpKol4oGWDN&pS}p=CejwhkQm*!4RP9nsw?&eE;D$Sv)wvQW#>&9>3HvsE6|Rjy zH~ch5iKH9?T$_Kc+OJ;0La(1ApcX0ioTZQ74bFv%CwwRy2&md<@y;tqJ4s2Gnmvzo zx4@(gwp@>k^{y=)bpq=(Mb@oRF9RxZEj0(H9bt*R*AzqtO0lb>_E*98CTB-}Wa-j& zNURw{O--{sl;3)tY$li3hE7Sw^*Tli+COUJj0vT$piebItS_@M5cel$9R0uru&4QB z$bKXdv$%LFmK@UW9GU|&j9zoq3rjnBR^Fi84=)ukq$D+bQN3>5)~EMtIsN6}Js+R* zs!op{!28aa3)>bQrY@mn6TJp1n-f;8tsRND8u>;yO7ZFuBBzO!ag~-#zSl~O9$0N% zp=c5UaO0pLXbH7Mebcg(vKIrrgg?HJe(X_z$B^Gg(yi{q^g}q} zSSVz%{uI3T$Ite~C}~otv_j~x+`aX+*`hTRXb0H2A}5 zkN)8xj8RbNsnE8xf?;*+-=5d|u+Ter=B{ zru0>&!`BgeH;;Cx#eNxW>qBmAbccsh5q6EQirtMh+g6W)K%FgsIjYNLVLSg9q7smI zulC~ZXE$2ORhRT#FwzgRK-rjyi49@1FnNg zZikyS?AOZ`F&Csw81hlHgh7MHM{0Rf1nyGN%WkQrqxJcBf;KuuN{uk^OZ_>s8ohp} zlsQeIJgqWm!wEV?eaNGT4dXiy+j1xK=j}|q7Ew9_Wzu@owsvqZwCg_mbe(X(_jb{) zCv7tN12Lm$-D1Jg;QjOtTzA$qCZfAh5N@UM8RnGM`~@X%Zil4Y#y;u3Gp}AsU*o*Z z`POYRq;x0960!pnHo`5=qRL~+qN|TW{gK&u46_7CmhAI;bHM=_npWg;$S2I~yI+ss zZq{=x%%gboNd3^YDCjY2?CP-67nd)$9`i#%{;#$l)Q$aqU#y{V6Yo8EP9JxG2NH5k zE9dqzvQt{}#TC|docrU2U1PA9u^LQ2>6kMlQvmo0Iow=Y^o;=a(XNfoWt1pv^On|oRZ z&9c}1IW;Q5Vi|k6bm>d`(!vdM<4=vuJ4b^&w}bMdf!2%ShX+qoW-A`_N;H#i-qHHu zVM0RN`PJ}1H4jzy%w~aI4j*)l4?iwKG*6qk4h0`zHA7;dpG4l6rH@*k{4_MuZUQ{x znIAdxyn>&T_W+Fgn~}w9A4(91zm##3ltihmL{|2Yo)?LQH_HU{5rAs-abr}o+@BLAr=+G6eZjUt*E#q-JM}@e{K1fdJyz^f~3eH!x-7~ zg`%~RK(+h%=m{9hp6coUK0W8o#<_dz^M}HRi*|gdbCW3o;szM@4{ia_e;9P$D)f6`vhI1XMhbdS@xG@?45NSwQ?qEOb2rw%M*2n`vnCZ^jZ};U z?*~^M#zdj=JYp9@sz;r4X(qBTLbIJk&)=uvjE4ypr428$|H#mNK{x=No)^bwO;Ll& z6barrU+Iw^8TJq)WjJfw`StfB7@X*p{kBD7Xr`I?-RDjWCzIK;J`YH*P zC$=1Xf~g=?>i1WyYE4TI5b{SqwdXJIXnR0p|fvi;lZaTXbD+$KC}9{|%eT**DE@ z2?exdnNXnq=(z~|0yvP57q-?~5Gdy#aLjeU`I-AGQ2ak|9jQZq;X3~Wef(}tg0u>L zzYi$v_CL_3|JfUv;eO`m^v{7oiWq@Z<=Rqsa6gisKi2l*g+G9CfV8r=hP!ms<6Z1S zE)ZqN1wFV&rs@CQ2mW6h`Ty*Vu!rTvQVen1G7CJ1D@LNJ_*Aciyv~QUys)tzCHJu( zx!SnU@l1-?yf3hMt8Od(gEiWW#yZFw=BRQ{lF7B&?r>q=ZGM|!MIIV2YhuXG-7s-V zMUXxQ6D92ZiU{A#NyRMk3nzM56+4BTL8LB}~_!*TU1s~-NzvDT=q{(g` z5|4MMB+9k{cv_d{){f0l!ZI1-?;XnxvtA@hvU+ zmV0C0%OQ(-r9IZgw9;kcVH9FSlUSa7OildJ@eyUqR_mG;6doeyUD!w*M95g_+P-_pI zP}C3=!y|UGbopGj*rnIgy;**IHGcL)6gLCJ<;`wo#} z)ET+KGyD*L{SB4@Yp7p;Y+ODX`}8C~p+!D@0V~{@-qurFtzxT|2G$|(EXXbz*+~yn z3pkZARBFQ8HcSy1syPHLp1-5kLbtR``H%^P=AM&%(5kueBcjduPHc%ssUUV>)cfTS z4tOoN1s!~j5EwZ6;UNEBkMTNHcJXPn7qjpwffwHW6a~<&2qtPnqZgwl1g(UNxN&$% zWQ^myH#n4&IK3u6=fp)hNO z3^6q6D9`<642JGBaFcPB@kfQ*^vbfOj z7L``UoY|*BcTctHt}P4w9uvxPBpK$49#t$PH$vo;WoG2iRq|5Hb_auJ>BMlQY+u*Td{9^&$)agw1Ub2aetdef~VB^^SOGJ7QlD^gylM zuEX;f-ul813!cW2N(+Zx!s6GD9efkW1up-Ayog74vgGc(^|~iFfavsb3Ee`dO}dRb zcM9>Pgm`@xTQj7ttqLRfE=ldp{3@jGQeh@$fzPw#x!#f8>p)!UC{jX>fqxG9E{(X< zxA%NQ+gCaP2AdoQI@!IS#wdW@AzetM@h^4h+7Xruwg^_1g8`Ok<97;-V=MPt-Cc7z z=lonH?0W$S?HmEl-;ZIc0Ps!ik0hf_(M&0^qKjqzx77j)|8L+zAGDgjVFGJ=8^Lg< z!#+OcV=GB&V*@L9Qhp|D&czrVyQ$I>v$c>KheWsc9Qq^}SsxmG1dgy6oPXMB0KpPnFPFIYg!qWU{9{Ok|a6Ha_ z<1W2sc@60`?VzBL{okQIOADCwHO7!+)GpC0q)W`v$8JAP1dRW}rf*P0%OeC1wZ^7z zNK23M0)>Ta_FRNO`eSGW%GqZo>O@{_hW`NveZNM)9)K4{{G^|`O-t?NE>XGlF;-Dp zAhenYAR$;k2tCTpfDr;q7CH{TC@%V6{*pq{x61r#Z6zUBE+Jh`dCGXHH7mPPj*r}-S$t571XrXU^@U`)$PwnRCGZTwfubQ(j_^HZ+ zg?<-X?|577LIZ|a!bjlV;S+O0_BZwhA8K;C7 z!-X;A2gK77;Y^&2Jm~h_voOla`6K?gN_ZAt6hw?m& zF*{niWYu$J4jf}44HmWE`$wi@MW65$Ae@eA+S1riA@2dO1$S4eZQooiqh8oD*ah){ z*anbaanWpU-f2z_JlswCINig*@k1zoVmHwsY`B0gkY&*4i&yaT2IxfkR81 zd_3b3#|Qhg#+b9uW$V!eew-=T-R3o_sDq)7x%Pb!|K zb=7V@FlTRIT4#@RkkBecR?tqj;1`%hUE#)V!fI+`+()!k{U~*W(R@l{A-%Io!B@gR z=Fe`^^z!w(_#i}MamiRYJne&1kr3$a#xDR7s(8*td}wu3OI|EgUSB+$ivmfKtZLly zM@QiPq{cI(O2?43yKi#^7iUqngUcPLv9}-FxL_8I3lEjq4d5D?q-(01B~yq%iuYPT z%BX7Ds3tlZ(m-u-OPxEiOM*_X;a11fBGDc?CzP`A-y zbmrs_k*0=UZ&@`G>WlW*R*4p#$QU2I)K8^GAKSOxdJ%_q_mn0YdBleR*v`>?65^H_ z11H{J`w$X$;6R&84S8n4L_;rd;d-B$gsgN&m*`M;UPwT_bbm~TXaOU35eIKa-`ac- znxmPR>lvyXwle1?uV!Q?=Am}3J44_;?u1*vPo=gUUgA-}x$qcxh8{FrCBt_dnd^T0$ zMs}0$y4^zLuoWFHXHUmM$`sD}`FGzOnY{V3qtYg!(`|Qw!x@oe?|5?lYNF%XU<554 zyna*H<35+o+L$xw3R{t(#oN^dIX?%wfy7+N#hqN0w$Cke_njqGx z;tUj!Rd&UZ6%yRKJZs=+RagFy zh1o_=_tHvNWE^A_lkc~;@9IZ8+a5%;mYvV!*TFYev%8AGm=ifNyYGp;J~F7X2jCwe z(oCTFX672qc_0?Jh;lp6h;%Jn(Y5w0f&MgY4SlXC1dRy|PMFbRK8(Lhy+#T#jhsaa&Z zB?O*HC%~RM#uLtf!iKH@TdL7ldLpNfT^pFq23J^Br0b?xKv4s?zLOv2dq8YSJr{z? z4~3AQ92BFfY!nMnK+2biwvT#G&kdbLz#gU7fxomLh~|@QJ$z&^8UrtmX3!c5?!CSu zz9>@q6Gpkk?)zxLCv;T(?)vb_s+#s9m2V%MRqKYb7-j0r(U`PaTEJCj&I65%|BS1= z=?6yG1rSp}DevmdGhLaw`EiAi4d|=Qjaulh!I}!!UduEDrNR+vI(WitL=$>(U~-V{ zaVxLzCTzVq*R^QJa6T7jGqe8}^n~nhrdFEJg`v5ci+&x|9BPqPNZ$4)x4@yeB8&9} zc;fo8G12wly?yh$Ynd>B&Et-l8f#JphMp)mQ_~nBEnWNKEbQJ;+Jjpz z1K8oR6~xcdaoSc#gRuitQTgu`6f@VFn2dhdJ34TyZ~51sCwr-v#k8P;OLmR3I~_4P zYU(-wDiT(6p9_dwb=q}M4DRh*(R?$k$w~UxO%Q12C9p true - - true - @@ -106,5 +103,6 @@ + diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index dbb15206e..d11f177d1 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -51,8 +51,8 @@ 0 0 - 832 - 418 + 836 + 428 @@ -74,7 +74,7 @@ - + System @@ -112,28 +112,11 @@ - - + - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::MinimumExpanding - - - - 0 - 0 - - - - @@ -148,35 +131,39 @@ - - - Enable Fullscreen - - - - - - - Show Splash - - - - - - - Is PS4 Pro - - + + + + + Enable Fullscreen + + + + + + + Show Splash + + + + + + + Is PS4 Pro + + + + - Qt::Orientation::Vertical + Qt::Orientation::Horizontal - 20 - 40 + 40 + 20 @@ -261,19 +248,6 @@ - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - @@ -282,34 +256,29 @@ - - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + - + - GPU + Graphics - + - + - + @@ -323,8 +292,8 @@ - - + + 0 @@ -340,44 +309,10 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::MinimumExpanding - - - - 0 - 0 - - - - - + @@ -505,26 +440,10 @@ - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::MinimumExpanding - - - - 0 - 0 - - - - - + 12 @@ -534,7 +453,7 @@ - Additional Settings + Advanced Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter @@ -565,17 +484,14 @@ - + Qt::Orientation::Vertical - - QSizePolicy::Policy::MinimumExpanding - - 0 - 0 + 20 + 40 @@ -584,6 +500,19 @@ + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + diff --git a/src/shader_recompiler/frontend/translate/flat_memory.cpp b/src/shader_recompiler/frontend/translate/flat_memory.cpp deleted file mode 100644 index e69de29bb..000000000 From 3e8d7c2040fbe353a09bd17e458676782f5fb1b9 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 22 Aug 2024 19:43:45 +0300 Subject: [PATCH 017/147] possible R2/L2 fix --- src/sdl_window.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 9fd596699..eec31c901 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -306,7 +306,13 @@ void WindowSDL::onGamepadEvent(const SDL_Event* event) { : event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER ? Input::Axis::TriggerRight : Input::Axis::AxisMax; if (axis != Input::Axis::AxisMax) { - controller->Axis(0, axis, Input::GetAxis(-0x8000, 0x8000, event->gaxis.value)); + if (event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || + event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) { + controller->Axis(0, axis, Input::GetAxis(0, 0x8000, event->gaxis.value)); + + } else { + controller->Axis(0, axis, Input::GetAxis(-0x8000, 0x8000, event->gaxis.value)); + } } break; } From 6545b09b7477b0dc1cd64934ca3307d4a78d9f2b Mon Sep 17 00:00:00 2001 From: Exhigh Date: Fri, 23 Aug 2024 16:27:03 +0400 Subject: [PATCH 018/147] savedata: Handle missed case in saveDataMount This should help P5D get past the intro. P.S: The game requires Fiber and USBD modules to boot. --- src/core/libraries/save_data/savedata.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 20496d76d..6652ee571 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -516,6 +516,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, mount_result->mount_status = 1; } } break; + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { From a71d0d8dbb2254dd1f40f131e8ca2bc1bd488221 Mon Sep 17 00:00:00 2001 From: Alexandre Bouvier Date: Wed, 21 Aug 2024 06:17:18 +0200 Subject: [PATCH 019/147] cmake: fix version constraints --- CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e349e588..0ff00d6f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,9 +66,8 @@ git_branch_name(GIT_BRANCH) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp" @ONLY) find_package(Boost 1.84.0 CONFIG) -find_package(cryptopp 8.9.0 MODULE) find_package(FFmpeg 5.1.2 MODULE) -find_package(fmt 10.2.1 CONFIG) +find_package(fmt 10.2.0 CONFIG) find_package(glslang 14.2.0 CONFIG) find_package(magic_enum 0.9.6 CONFIG) find_package(RenderDoc 1.6.0 MODULE) @@ -79,8 +78,12 @@ find_package(VulkanHeaders 1.3.289 CONFIG) find_package(VulkanMemoryAllocator 3.1.0 CONFIG) find_package(xbyak 7.07 CONFIG) find_package(xxHash 0.8.2 MODULE) -find_package(zlib-ng 2.2.0 MODULE) -find_package(Zydis 4.1.0 CONFIG) +find_package(zlib-ng 2.1.7 MODULE) +find_package(Zydis 5.0.0 CONFIG) + +if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC) + find_package(cryptopp 8.9.0 MODULE) +endif() if (APPLE) find_package(date 3.0.1 CONFIG) From a0774c0e87688a9ecdb6e2e24a8ef5a122904651 Mon Sep 17 00:00:00 2001 From: Herman Semenov Date: Fri, 23 Aug 2024 22:04:55 +0300 Subject: [PATCH 020/147] Fixed invalid set public exponent Crypto::DebugRifKeyset_init() --- src/core/crypto/crypto.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp index 630faa344..fc64edc2d 100644 --- a/src/core/crypto/crypto.cpp +++ b/src/core/crypto/crypto.cpp @@ -51,8 +51,8 @@ CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() { params.SetPrime2( CryptoPP::Integer(DebugRifKeyset_keyset.Prime2, sizeof(DebugRifKeyset_keyset.Prime2))); - params.SetPublicExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent, - sizeof(DebugRifKeyset_keyset.PrivateExponent))); + params.SetPublicExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PublicExponent, + sizeof(DebugRifKeyset_keyset.PublicExponent))); params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent, sizeof(DebugRifKeyset_keyset.PrivateExponent))); From 0c5b91e1fb4b016667c660ea3de55f1d0cc5c80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Fri, 23 Aug 2024 21:38:55 +0200 Subject: [PATCH 021/147] Warnings fixes (#541) * Warnings fixes * Warnings fixes --- src/qt_gui/elf_viewer.cpp | 2 -- src/qt_gui/elf_viewer.h | 10 ------- src/qt_gui/game_grid_frame.h | 10 ------- src/qt_gui/game_info.cpp | 3 -- src/qt_gui/game_info.h | 6 ++-- src/qt_gui/game_list_frame.h | 12 -------- src/qt_gui/game_list_utils.h | 5 ---- src/qt_gui/gui_context_menus.h | 12 ++------ src/qt_gui/main.cpp | 7 ++--- src/qt_gui/main_window.cpp | 5 ---- src/qt_gui/main_window.h | 5 ---- src/qt_gui/main_window_ui.h | 30 ++++---------------- src/qt_gui/pkg_viewer.cpp | 5 +--- src/qt_gui/pkg_viewer.h | 9 ------ src/qt_gui/settings_dialog.cpp | 3 +- src/qt_gui/trophy_viewer.h | 2 -- src/video_core/texture_cache/texture_cache.h | 2 +- 17 files changed, 15 insertions(+), 113 deletions(-) diff --git a/src/qt_gui/elf_viewer.cpp b/src/qt_gui/elf_viewer.cpp index 72861d15f..e80fa25c1 100644 --- a/src/qt_gui/elf_viewer.cpp +++ b/src/qt_gui/elf_viewer.cpp @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include - #include "elf_viewer.h" ElfViewer::ElfViewer(QWidget* parent) : QTableWidget(parent) { diff --git a/src/qt_gui/elf_viewer.h b/src/qt_gui/elf_viewer.h index a3b85223d..1a65d70de 100644 --- a/src/qt_gui/elf_viewer.h +++ b/src/qt_gui/elf_viewer.h @@ -3,17 +3,7 @@ #pragma once -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include "core/loader/elf.h" #include "game_list_frame.h" diff --git a/src/qt_gui/game_grid_frame.h b/src/qt_gui/game_grid_frame.h index ce775315e..50b53a581 100644 --- a/src/qt_gui/game_grid_frame.h +++ b/src/qt_gui/game_grid_frame.h @@ -3,17 +3,7 @@ #pragma once -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include "common/config.h" #include "game_info.h" diff --git a/src/qt_gui/game_info.cpp b/src/qt_gui/game_info.cpp index 0a472eaef..d2bf3bb2d 100644 --- a/src/qt_gui/game_info.cpp +++ b/src/qt_gui/game_info.cpp @@ -1,10 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include #include -#include #include "game_info.h" diff --git a/src/qt_gui/game_info.h b/src/qt_gui/game_info.h index b2b102e00..ae02114a2 100644 --- a/src/qt_gui/game_info.h +++ b/src/qt_gui/game_info.h @@ -3,10 +3,8 @@ #pragma once -#include -#include -#include -#include +#include +#include #include "common/config.h" #include "core/file_format/psf.h" diff --git a/src/qt_gui/game_list_frame.h b/src/qt_gui/game_list_frame.h index d8bccf466..ab70e6f6b 100644 --- a/src/qt_gui/game_list_frame.h +++ b/src/qt_gui/game_list_frame.h @@ -3,19 +3,7 @@ #pragma once -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include "game_info.h" #include "game_list_utils.h" diff --git a/src/qt_gui/game_list_utils.h b/src/qt_gui/game_list_utils.h index 2e25f1220..8f934388d 100644 --- a/src/qt_gui/game_list_utils.h +++ b/src/qt_gui/game_list_utils.h @@ -3,11 +3,6 @@ #pragma once -#include -#include -#include -#include - struct GameInfo { std::string path; // root path of game directory (normaly directory that contains eboot.bin) std::string icon_path; // path of icon0.png diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 2f4b884cf..16afdb188 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -4,17 +4,9 @@ #pragma once #include -#include #include -#include -#include -#include #include #include -#include -#include -#include -#include #include #include @@ -84,7 +76,7 @@ public: QTableWidget* tableWidget = new QTableWidget(rows, 2); tableWidget->setAttribute(Qt::WA_DeleteOnClose); connect(widget->parent(), &QWidget::destroyed, tableWidget, - [widget, tableWidget]() { tableWidget->deleteLater(); }); + [tableWidget]() { tableWidget->deleteLater(); }); tableWidget->verticalHeader()->setVisible(false); // Hide vertical header int row = 0; @@ -135,7 +127,7 @@ public: TrophyViewer* trophyViewer = new TrophyViewer(trophyPath, gameTrpPath); trophyViewer->show(); connect(widget->parent(), &QWidget::destroyed, trophyViewer, - [widget, trophyViewer]() { trophyViewer->deleteLater(); }); + [trophyViewer]() { trophyViewer->deleteLater(); }); } if (selected == &createShortcut) { diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index cff01cc2b..02957c6d5 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -1,14 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include - #include "common/config.h" #include "core/file_sys/fs.h" #include "emulator.h" -#include "qt_gui/game_install_dialog.h" -#include "qt_gui/main_window.h" +#include "game_install_dialog.h" +#include "main_window.h" // Custom message handler to ignore Qt logs void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 34ef0d868..b6711d719 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -1,13 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include -#include -#include #include -#include -#include #include "about_dialog.h" #include "common/io_file.h" diff --git a/src/qt_gui/main_window.h b/src/qt_gui/main_window.h index 24de15b92..1abe17625 100644 --- a/src/qt_gui/main_window.h +++ b/src/qt_gui/main_window.h @@ -3,13 +3,8 @@ #pragma once -#include #include #include -#include -#include -#include -#include #include "common/config.h" #include "common/path_util.h" diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 7d0c58dd2..1a2a560e0 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -1,29 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -/******************************************************************************** -** Form generated from reading UI file 'main_window.ui' -** -** Created by: Qt User Interface Compiler version 6.6.1 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ +#pragma once -#ifndef MAIN_WINDOW_UI_H -#define MAIN_WINDOW_UI_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -369,6 +351,4 @@ namespace Ui { class MainWindow : public Ui_MainWindow {}; } // namespace Ui -QT_END_NAMESPACE - -#endif // MAIN_WINDOW_UI_H +QT_END_NAMESPACE \ No newline at end of file diff --git a/src/qt_gui/pkg_viewer.cpp b/src/qt_gui/pkg_viewer.cpp index cd2ce2b6e..49005c720 100644 --- a/src/qt_gui/pkg_viewer.cpp +++ b/src/qt_gui/pkg_viewer.cpp @@ -1,9 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include - #include "pkg_viewer.h" PKGViewer::PKGViewer(std::shared_ptr game_info_get, QWidget* parent, @@ -54,7 +51,7 @@ PKGViewer::PKGViewer(std::shared_ptr game_info_get, QWidget* pare InstallDragDropPkg); }); - connect(parent, &QWidget::destroyed, this, [parent, this]() { this->deleteLater(); }); + connect(parent, &QWidget::destroyed, this, [this]() { this->deleteLater(); }); } PKGViewer::~PKGViewer() {} diff --git a/src/qt_gui/pkg_viewer.h b/src/qt_gui/pkg_viewer.h index e040d5950..9598328a0 100644 --- a/src/qt_gui/pkg_viewer.h +++ b/src/qt_gui/pkg_viewer.h @@ -3,18 +3,9 @@ #pragma once -#include -#include -#include -#include #include -#include -#include #include #include -#include -#include -#include #include "common/io_file.h" #include "core/file_format/pkg.h" diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index aa2c73384..09247951a 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "settings_dialog.h" #include "ui_settings_dialog.h" @@ -86,7 +87,7 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge [](const QString& text) { Config::setUserName(text.toStdString()); }); connect(ui->consoleLanguageComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this](int index) { + this, [](int index) { if (index >= 0 && index < languageIndexes.size()) { int languageCode = languageIndexes[index]; Config::setLanguage(languageCode); diff --git a/src/qt_gui/trophy_viewer.h b/src/qt_gui/trophy_viewer.h index 2b794593f..81b9b1adc 100644 --- a/src/qt_gui/trophy_viewer.h +++ b/src/qt_gui/trophy_viewer.h @@ -10,11 +10,9 @@ #include #include #include -#include #include #include #include -#include #include #include "common/types.h" diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 137b60141..7266d7a56 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -124,7 +124,7 @@ private: using FuncReturn = typename std::invoke_result::type; static constexpr bool BOOL_BREAK = std::is_same_v; boost::container::small_vector images; - ForEachPage(cpu_addr, size, [this, &images, cpu_addr, size, func](u64 page) { + ForEachPage(cpu_addr, size, [this, &images, func](u64 page) { const auto it = page_table.find(page); if (it == nullptr) { if constexpr (BOOL_BREAK) { From 0ed4614464207fb235b254f2689b52c0d32ba2fb Mon Sep 17 00:00:00 2001 From: Matthew Wells <91291346+richarm4@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:29:00 -0700 Subject: [PATCH 022/147] Fix typo in CONTRIBUTING.md comment "intitialize" -> "initialize" --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a428598c7..cdda7c8c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ enum class SomeEnum { * Note that the asterisks are indented by one space to align to the first line. */ struct Position { - // Always intitialize member variables! + // Always initialize member variables! int x{}; int y{}; }; From fc745ee767c889598577115fdd146ddc391f808e Mon Sep 17 00:00:00 2001 From: Random <28494085+Random06457@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:50:46 +0200 Subject: [PATCH 023/147] Fix a few issues with the intel anv vulkan driver from mesa (#514) * add fallback format for d16UnormS8Uint which is not supported by intel * fix depth/stencil buffer creation issues causing asserts in intel driver --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 1 + src/video_core/renderer_vulkan/vk_instance.cpp | 2 ++ src/video_core/texture_cache/image.cpp | 13 +++++++------ src/video_core/texture_cache/texture_cache.cpp | 1 + 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index daf64a4d3..c42e4f609 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -306,6 +306,7 @@ std::span GetAllFormats() { vk::Format::eBc7UnormBlock, vk::Format::eD16Unorm, vk::Format::eD16UnormS8Uint, + vk::Format::eD24UnormS8Uint, vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eR4G4B4A4UnormPack16, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 66da030f1..c0923b743 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -481,6 +481,8 @@ bool Instance::IsFormatSupported(const vk::Format format) const { vk::Format Instance::GetAlternativeFormat(const vk::Format format) const { if (format == vk::Format::eB5G6R5UnormPack16) { return vk::Format::eR5G6B5UnormPack16; + } else if (format == vk::Format::eD16UnormS8Uint) { + return vk::Format::eD24UnormS8Uint; } return format; } diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 528dda55c..0b725655b 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -73,14 +73,15 @@ static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) { if (!info.IsBlockCoded() && !info.IsPacked()) { usage |= vk::ImageUsageFlagBits::eColorAttachment; } + + // In cases where an image is created as a render/depth target and cleared with compute, + // we cannot predict whether it will be used as a storage image. A proper solution would + // involve re-creating the resource with a new configuration and copying previous content + // into it. However, for now, we will set storage usage for all images (if the format + // allows), sacrificing a bit of performance. Note use of ExtendedUsage flag set by default. + usage |= vk::ImageUsageFlagBits::eStorage; } - // In cases where an image is created as a render/depth target and cleared with compute, - // we cannot predict whether it will be used as a storage image. A proper solution would - // involve re-creating the resource with a new configuration and copying previous content into - // it. However, for now, we will set storage usage for all images (if the format allows), - // sacrificing a bit of performance. Note use of ExtendedUsage flag set by default. - usage |= vk::ImageUsageFlagBits::eStorage; return usage; } diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 6bc893b09..8cc6ccbd5 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -200,6 +200,7 @@ ImageView& TextureCache::FindDepthTarget(const ImageInfo& image_info, Image& image = slot_images[image_id]; image.flags |= ImageFlagBits::GpuModified; image.flags &= ~ImageFlagBits::CpuModified; + image.aspect_mask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil; const auto new_layout = view_info.is_storage ? vk::ImageLayout::eDepthStencilAttachmentOptimal : vk::ImageLayout::eDepthStencilReadOnlyOptimal; From 243fd0be78d2a7abd1b2b8165c2be2da36d93652 Mon Sep 17 00:00:00 2001 From: Herman Semenov Date: Sat, 24 Aug 2024 13:18:12 +0000 Subject: [PATCH 024/147] core,shader_recompiler: align structures for 64-bit platforms (#447) Decreased sizes: * TextureDefinition 32 bytes -> 24 bytes * PortOut 72 bytes -> 64 bytes * Request 48 bytes -> 40 bytes * WindowSystemInfo 32 bytes -> 24 bytes --- src/audio_core/sdl_audio.h | 8 ++++---- src/core/libraries/videoout/driver.cpp | 4 ++-- src/core/libraries/videoout/driver.h | 4 ++-- src/sdl_window.h | 6 +++--- .../backend/spirv/spirv_emit_context.cpp | 2 +- src/shader_recompiler/backend/spirv/spirv_emit_context.h | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/audio_core/sdl_audio.h b/src/audio_core/sdl_audio.h index 7844bd61b..07e82145e 100644 --- a/src/audio_core/sdl_audio.h +++ b/src/audio_core/sdl_audio.h @@ -22,15 +22,15 @@ public: private: struct PortOut { - bool isOpen = false; - int type = 0; + SDL_AudioStream* stream = nullptr; u32 samples_num = 0; - u8 sample_size = 0; u32 freq = 0; u32 format = -1; + int type = 0; int channels_num = 0; int volume[8] = {}; - SDL_AudioStream* stream = nullptr; + u8 sample_size = 0; + bool isOpen = false; }; std::shared_mutex m_mutex; std::array portsOut; // main up to 8 ports , BGM 1 port , voice up to 4 ports , diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 25de48a4d..dbbcb1def 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -252,8 +252,8 @@ void VideoOutDriver::SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_ requests.push({ .frame = frame, .port = port, - .index = index, .flip_arg = flip_arg, + .index = index, .eop = is_eop, }); } diff --git a/src/core/libraries/videoout/driver.h b/src/core/libraries/videoout/driver.h index bee800602..6fc74e012 100644 --- a/src/core/libraries/videoout/driver.h +++ b/src/core/libraries/videoout/driver.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -92,8 +92,8 @@ private: struct Request { Vulkan::Frame* frame; VideoOutPort* port; - s32 index; s64 flip_arg; + s32 index; bool eop; operator bool() const noexcept { diff --git a/src/sdl_window.h b/src/sdl_window.h index cf6c37116..11ee92896 100644 --- a/src/sdl_window.h +++ b/src/sdl_window.h @@ -25,9 +25,6 @@ enum class WindowSystemType : u8 { }; struct WindowSystemInfo { - // Window system type. Determines which GL context or Vulkan WSI is used. - WindowSystemType type = WindowSystemType::Headless; - // Connection to a display server. This is used on X11 and Wayland platforms. void* display_connection = nullptr; @@ -38,6 +35,9 @@ struct WindowSystemInfo { // Scale of the render surface. For hidpi systems, this will be >1. float render_surface_scale = 1.0f; + + // Window system type. Determines which GL context or Vulkan WSI is used. + WindowSystemType type = WindowSystemType::Headless; }; class WindowSDL { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index d61e108f6..e48b89f4b 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -485,8 +485,8 @@ void EmitContext::DefineImagesAndSamplers() { Name(id, fmt::format("{}_{}{}_{:02x}", stage, "img", image_desc.sgpr_base, image_desc.dword_offset)); images.push_back({ - .id = id, .data_types = data_types, + .id = id, .sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type), .pointer_type = pointer_type, .image_type = image_type, diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 768b591f5..5a09c4116 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -193,8 +193,8 @@ public: Id shared_memory_u32_type{}; struct TextureDefinition { - Id id; const VectorIds* data_types; + Id id; Id sampled_type; Id pointer_type; Id image_type; From 6a84f6e188a8e99a386cea2ddab034fe1920d037 Mon Sep 17 00:00:00 2001 From: Exhigh Date: Sat, 24 Aug 2024 17:38:50 +0400 Subject: [PATCH 025/147] savedata: Add another missing case to saveDataMount This helps Five Nights at Freddy's: Sister Location (CUSA17983) boot and is playable. Fixes issue #554 --- src/core/libraries/save_data/savedata.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 6652ee571..d62e39f88 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -519,7 +519,9 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { + ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | + ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { if (!std::filesystem::exists(mount_dir)) { std::filesystem::create_directories(mount_dir); } From 41dec15869d910a73384f56d35839e69b62d42e1 Mon Sep 17 00:00:00 2001 From: Vladislav Mikhalin Date: Sat, 24 Aug 2024 16:58:53 +0300 Subject: [PATCH 026/147] Fixed video dimensions alignment and image cache --- src/core/libraries/avplayer/avplayer.cpp | 3 ++ .../libraries/avplayer/avplayer_source.cpp | 53 ++++++++++++++----- .../libraries/avplayer/avplayer_state.cpp | 5 +- .../texture_cache/texture_cache.cpp | 1 - 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/core/libraries/avplayer/avplayer.cpp b/src/core/libraries/avplayer/avplayer.cpp index bd1f6b503..406583a8c 100644 --- a/src/core/libraries/avplayer/avplayer.cpp +++ b/src/core/libraries/avplayer/avplayer.cpp @@ -40,9 +40,11 @@ int PS4_SYSV_ABI sceAvPlayerChangeStream() { s32 PS4_SYSV_ABI sceAvPlayerClose(SceAvPlayerHandle handle) { LOG_TRACE(Lib_AvPlayer, "called"); if (handle == nullptr) { + LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS"); return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } delete handle; + LOG_TRACE(Lib_AvPlayer, "returning ORBIS_OK"); return ORBIS_OK; } @@ -257,6 +259,7 @@ s32 PS4_SYSV_ABI sceAvPlayerStart(SceAvPlayerHandle handle) { s32 PS4_SYSV_ABI sceAvPlayerStop(SceAvPlayerHandle handle) { LOG_TRACE(Lib_AvPlayer, "called"); if (handle == nullptr) { + LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS"); return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } const auto res = handle->Stop(); diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index 2fc360a0e..2e4ea8aab 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -5,6 +5,7 @@ #include "avplayer_file_streamer.h" +#include "common/alignment.h" #include "common/singleton.h" #include "core/file_sys/fs.h" #include "core/libraries/kernel/time_management.h" @@ -111,8 +112,8 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) LOG_INFO(Lib_AvPlayer, "Stream {} is a video stream.", stream_index); info.details.video.aspect_ratio = f32(p_stream->codecpar->width) / p_stream->codecpar->height; - info.details.video.width = p_stream->codecpar->width; - info.details.video.height = p_stream->codecpar->height; + info.details.video.width = Common::AlignUp(u32(p_stream->codecpar->width), 16); + info.details.video.height = Common::AlignUp(u32(p_stream->codecpar->height), 16); if (p_lang_node != nullptr) { std::memcpy(info.details.video.language_code, p_lang_node->value, std::min(strlen(p_lang_node->value), size_t(3))); @@ -167,8 +168,9 @@ bool AvPlayerSource::EnableStream(u32 stream_index) { LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", stream_index); return false; } - const auto width = m_video_codec_context->width; - const auto size = (width * m_video_codec_context->height * 3) / 2; + const auto width = Common::AlignUp(u32(m_video_codec_context->width), 16); + const auto height = Common::AlignUp(u32(m_video_codec_context->height), 16); + const auto size = (width * height * 3) / 2; for (u64 index = 0; index < m_num_output_video_framebuffers; ++index) { m_video_buffers.Push(FrameBuffer(m_memory_replacement, 0x100, size)); } @@ -284,11 +286,6 @@ bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfo& video_info) { return true; } -static void CopyNV12Data(u8* dst, const AVFrame& src) { - std::memcpy(dst, src.data[0], src.width * src.height); - std::memcpy(dst + src.width * src.height, src.data[1], (src.width * src.height) / 2); -} - bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfoEx& video_info) { if (!IsActive()) { return false; @@ -493,13 +490,17 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram nv12_frame->width = frame.width; nv12_frame->height = frame.height; nv12_frame->sample_aspect_ratio = frame.sample_aspect_ratio; + nv12_frame->crop_top = frame.crop_top; + nv12_frame->crop_bottom = frame.crop_bottom; + nv12_frame->crop_left = frame.crop_left; + nv12_frame->crop_right = frame.crop_right; av_frame_get_buffer(nv12_frame.get(), 0); if (m_sws_context == nullptr) { m_sws_context = SWSContextPtr(sws_getContext(frame.width, frame.height, AVPixelFormat(frame.format), - frame.width, frame.height, AV_PIX_FMT_NV12, + nv12_frame->width, nv12_frame->height, AV_PIX_FMT_NV12, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr), &ReleaseSWSContext); } @@ -512,6 +513,26 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram return nv12_frame; } +static void CopyNV12Data(u8* dst, const AVFrame& src) { + const auto width = Common::AlignUp(u32(src.width), 16); + const auto height = Common::AlignUp(u32(src.height), 16); + + if (src.width == width) { + std::memcpy(dst, src.data[0], src.width * src.height); + std::memcpy(dst + src.width * height, src.data[1], (src.width * src.height) / 2); + } else { + const auto luma_dst = dst; + for (u32 y = 0; y < src.height; ++y) { + std::memcpy(luma_dst + y * width, src.data[0] + y * src.width, src.width); + } + const auto chroma_dst = dst + width * height; + for (u32 y = 0; y < src.height / 2; ++y) { + std::memcpy(chroma_dst + y * (width / 2), src.data[0] + y * (src.width / 2), + src.width / 2); + } + } +} + Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame) { ASSERT(frame.format == AV_PIX_FMT_NV12); @@ -525,6 +546,9 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame const auto num = time_base.num; const auto timestamp = (num != 0 && den > 1) ? (pkt_dts * num) / den : pkt_dts; + const auto width = Common::AlignUp(u32(frame.width), 16); + const auto height = Common::AlignUp(u32(frame.height), 16); + return Frame{ .buffer = std::move(buffer), .info = @@ -535,9 +559,14 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame { .video = { - .width = u32(frame.width), - .height = u32(frame.height), + .width = u32(width), + .height = u32(height), .aspect_ratio = AVRationalToF32(frame.sample_aspect_ratio), + .crop_left_offset = u32(frame.crop_left), + .crop_right_offset = u32(frame.crop_right + (width - frame.width)), + .crop_top_offset = u32(frame.crop_top), + .crop_bottom_offset = + u32(frame.crop_bottom + (height - frame.height)), .pitch = u32(frame.linesize[0]), .luma_bit_depth = 8, .chroma_bit_depth = 8, diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index 884cd9408..cb3be2f57 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -222,8 +222,11 @@ bool AvPlayerState::Stop() { if (!SetState(AvState::Stop)) { return false; } + if (!m_up_source->Stop()) { + return false; + } OnPlaybackStateChanged(AvState::Stop); - return m_up_source->Stop(); + return true; } bool AvPlayerState::GetVideoData(SceAvPlayerFrameInfo& video_info) { diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 8cc6ccbd5..cd3afc59f 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -329,7 +329,6 @@ void TextureCache::UnregisterImage(ImageId image_id) { } image_ids.erase(vector_it); }); - slot_images.erase(image_id); } void TextureCache::TrackImage(Image& image, ImageId image_id) { From 9e4fc17e6c2e18b4e4c7707115378b31a1ee4210 Mon Sep 17 00:00:00 2001 From: Vinicius Rangel Date: Sat, 24 Aug 2024 12:36:40 -0300 Subject: [PATCH 027/147] shader_recompiler: handle fetch shader address offsets (#538) * shader_recompiler: handle fetch shader address offsets parse index & offset sgpr from fetch shader and propagate them to vkBindVertexBuffers * shader_recompiler: fix fetch_shader when offset is not present * video_core: propagate index/offset SGPRs to vkCmdDraw instead of offsetting the buffer address * video_core: add vertex_offset to non-indexed draw calls renamed fetch offset fields --- .../frontend/fetch_shader.cpp | 24 +++++++++++++++---- src/shader_recompiler/frontend/fetch_shader.h | 8 ++++++- .../frontend/translate/translate.cpp | 7 ++++-- src/shader_recompiler/runtime_info.h | 15 ++++++++++++ .../renderer_vulkan/vk_rasterizer.cpp | 8 +++++-- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/shader_recompiler/frontend/fetch_shader.cpp b/src/shader_recompiler/frontend/fetch_shader.cpp index 81e4093f2..16938410c 100644 --- a/src/shader_recompiler/frontend/fetch_shader.cpp +++ b/src/shader_recompiler/frontend/fetch_shader.cpp @@ -3,6 +3,7 @@ #include #include +#include "common/assert.h" #include "shader_recompiler/frontend/decode.h" #include "shader_recompiler/frontend/fetch_shader.h" @@ -33,8 +34,8 @@ namespace Shader::Gcn { * We take the reverse way, extract the original input semantics from these instructions. **/ -std::vector ParseFetchShader(const u32* code, u32* out_size) { - std::vector attributes; +FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { + FetchShaderData data{}; GcnCodeSlice code_slice(code, code + std::numeric_limits::max()); GcnDecodeContext decoder; @@ -59,6 +60,21 @@ std::vector ParseFetchShader(const u32* code, u32* out_size) { continue; } + if (inst.opcode == Opcode::V_ADD_I32) { + const auto vgpr = inst.dst[0].code; + const auto sgpr = s8(inst.src[0].code); + switch (vgpr) { + case 0: // V0 is always the vertex offset + data.vertex_offset_sgpr = sgpr; + break; + case 3: // V3 is always the instance offset + data.instance_offset_sgpr = sgpr; + break; + default: + UNREACHABLE(); + } + } + if (inst.inst_class == InstClass::VectorMemBufFmt) { // SRSRC is in units of 4 SPGRs while SBASE is in pairs of SGPRs const u32 base_sgpr = inst.src[2].code * 4; @@ -68,7 +84,7 @@ std::vector ParseFetchShader(const u32* code, u32* out_size) { const auto it = std::ranges::find_if( loads, [&](VsharpLoad& load) { return load.dst_reg == base_sgpr; }); - auto& attrib = attributes.emplace_back(); + auto& attrib = data.attributes.emplace_back(); attrib.semantic = semantic_index++; attrib.dest_vgpr = inst.src[1].code; attrib.num_elements = inst.control.mubuf.count; @@ -83,7 +99,7 @@ std::vector ParseFetchShader(const u32* code, u32* out_size) { } } - return attributes; + return data; } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/fetch_shader.h b/src/shader_recompiler/frontend/fetch_shader.h index 0858061a1..0e5d15419 100644 --- a/src/shader_recompiler/frontend/fetch_shader.h +++ b/src/shader_recompiler/frontend/fetch_shader.h @@ -17,6 +17,12 @@ struct VertexAttribute { u8 instance_data; ///< Indicates that the buffer will be accessed in instance rate }; -std::vector ParseFetchShader(const u32* code, u32* out_size); +struct FetchShaderData { + std::vector attributes; + s8 vertex_offset_sgpr = -1; ///< SGPR of vertex offset from VADDR + s8 instance_offset_sgpr = -1; ///< SGPR of instance offset from VADDR +}; + +FetchShaderData ParseFetchShader(const u32* code, u32* out_size); } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 4070560ae..e59cd5656 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -346,7 +346,7 @@ void Translator::EmitFetch(const GcnInst& inst) { // Parse the assembly to generate a list of attributes. u32 fetch_size{}; - const auto attribs = ParseFetchShader(code, &fetch_size); + const auto fetch_data = ParseFetchShader(code, &fetch_size); if (Config::dumpShaders()) { using namespace Common::FS; @@ -359,7 +359,10 @@ void Translator::EmitFetch(const GcnInst& inst) { file.WriteRaw(code, fetch_size); } - for (const auto& attrib : attribs) { + info.vertex_offset_sgpr = fetch_data.vertex_offset_sgpr; + info.instance_offset_sgpr = fetch_data.instance_offset_sgpr; + + for (const auto& attrib : fetch_data.attributes) { const IR::Attribute attr{IR::Attribute::Param0 + attrib.semantic}; IR::VectorReg dst_reg{attrib.dest_vgpr}; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index b1eb6aea7..7d36dbe1b 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -175,6 +175,9 @@ struct Info { AttributeFlags stores{}; boost::container::static_vector vs_outputs; + s8 vertex_offset_sgpr = -1; + s8 instance_offset_sgpr = -1; + BufferResourceList buffers; ImageResourceList images; SamplerResourceList samplers; @@ -210,6 +213,18 @@ struct Info { std::memcpy(&data, base + dword_offset, sizeof(T)); return data; } + + [[nodiscard]] std::pair GetDrawOffsets() const noexcept { + u32 vertex_offset = 0; + u32 instance_offset = 0; + if (vertex_offset_sgpr != -1) { + vertex_offset = user_data[vertex_offset_sgpr]; + } + if (instance_offset_sgpr != -1) { + instance_offset = user_data[instance_offset_sgpr]; + } + return {vertex_offset, instance_offset}; + } }; constexpr AmdGpu::Buffer BufferResource::GetVsharp(const Info& info) const noexcept { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 6cd803934..3b02a98ab 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -52,13 +52,17 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { BeginRendering(); UpdateDynamicState(*pipeline); + const auto [vertex_offset, instance_offset] = vs_info.GetDrawOffsets(); + if (is_indexed) { - cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, 0, 0); + cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, s32(vertex_offset), + instance_offset); } else { const u32 num_vertices = regs.primitive_type == AmdGpu::Liverpool::PrimitiveType::RectList ? 4 : regs.num_indices; - cmdbuf.draw(num_vertices, regs.num_instances.NumInstances(), 0, 0); + cmdbuf.draw(num_vertices, regs.num_instances.NumInstances(), vertex_offset, + instance_offset); } } From c79b10edc1994d663c6ed0a51d6b1a288494ffa7 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sat, 24 Aug 2024 22:51:47 +0300 Subject: [PATCH 028/147] video_core: Bloodborne stabilization pt1 (#543) * shader_recompiler: Writelane elimination pass + null image fix * spirv: Implement image derivatives * texture_cache: Reduce page bit size * clang format * slot_vector: Back to debug assert * vk_graphics_pipeline: Handle null tsharp * spirv: Revert some change * vk_instance: Support primitive restart on list topology * page_manager: Adjust windows exception handler * clang format * Remove subres tracking * Will be done separately --- src/common/slot_vector.h | 22 ++++--------- .../libraries/kernel/thread_management.cpp | 1 - .../backend/spirv/emit_spirv_image.cpp | 33 ++++++++++++++++--- .../backend/spirv/emit_spirv_instructions.h | 7 ++-- .../backend/spirv/emit_spirv_warp.cpp | 12 +++++++ .../frontend/translate/data_share.cpp | 16 +++++---- .../frontend/translate/scalar_alu.cpp | 7 ++-- .../frontend/translate/vector_memory.cpp | 24 ++++++++++---- src/shader_recompiler/ir/ir_emitter.cpp | 16 ++++++--- src/shader_recompiler/ir/ir_emitter.h | 4 ++- src/shader_recompiler/ir/opcodes.inc | 26 ++++++++------- .../ir/passes/constant_propogation_pass.cpp | 14 ++++++++ .../ir/passes/resource_tracking_pass.cpp | 31 ++++++++--------- .../ir/passes/ssa_rewrite_pass.cpp | 20 +---------- src/shader_recompiler/ir/reg.h | 1 + src/shader_recompiler/recompiler.cpp | 2 +- src/video_core/amdgpu/resource.h | 4 +++ src/video_core/page_manager.cpp | 6 ++-- .../renderer_vulkan/vk_graphics_pipeline.cpp | 19 +++++++---- .../renderer_vulkan/vk_instance.cpp | 8 +++++ .../renderer_vulkan/vk_pipeline_cache.cpp | 3 -- src/video_core/texture_cache/image_info.cpp | 7 +++- src/video_core/texture_cache/image_info.h | 3 ++ .../texture_cache/texture_cache.cpp | 6 +++- src/video_core/texture_cache/texture_cache.h | 2 +- 25 files changed, 187 insertions(+), 107 deletions(-) diff --git a/src/common/slot_vector.h b/src/common/slot_vector.h index f0982e290..36e647971 100644 --- a/src/common/slot_vector.h +++ b/src/common/slot_vector.h @@ -28,9 +28,13 @@ struct SlotId { template class SlotVector { - constexpr static std::size_t InitialCapacity = 1024; + constexpr static std::size_t InitialCapacity = 2048; public: + SlotVector() { + Reserve(InitialCapacity); + } + ~SlotVector() noexcept { std::size_t index = 0; for (u64 bits : stored_bitset) { @@ -67,19 +71,6 @@ public: return SlotId{index}; } - template - [[nodiscard]] SlotId swap_and_insert(SlotId existing_id, Args&&... args) noexcept { - const u32 index = FreeValueIndex(); - T& existing_value = values[existing_id.index].object; - - new (&values[index].object) T(std::move(existing_value)); - existing_value.~T(); - new (&values[existing_id.index].object) T(std::forward(args)...); - SetStorageBit(index); - - return SlotId{index}; - } - void erase(SlotId id) noexcept { values[id.index].object.~T(); free_list.push_back(id.index); @@ -151,7 +142,8 @@ private: const std::size_t old_free_size = free_list.size(); free_list.resize(old_free_size + (new_capacity - values_capacity)); - std::iota(free_list.begin() + old_free_size, free_list.end(), + const std::size_t new_free_size = free_list.size(); + std::iota(free_list.rbegin(), free_list.rbegin() + new_free_size - old_free_size, static_cast(values_capacity)); delete[] values; diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 689532693..567fff184 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1123,7 +1123,6 @@ int PS4_SYSV_ABI posix_pthread_join(ScePthread thread, void** res) { } int PS4_SYSV_ABI scePthreadDetach(ScePthread thread) { - LOG_INFO(Kernel_Pthread, "thread create name = {}", thread->name); thread->is_detached = true; return ORBIS_OK; } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 5526e5411..530f381d7 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -16,6 +16,12 @@ struct ImageOperands { static_cast(new_mask)); operands.push_back(value); } + void Add(spv::ImageOperandsMask new_mask, Id value1, Id value2) { + mask = static_cast(static_cast(mask) | + static_cast(new_mask)); + operands.push_back(value1); + operands.push_back(value2); + } void AddOffset(EmitContext& ctx, const IR::Value& offset, bool can_use_runtime_offsets = false) { @@ -53,6 +59,15 @@ struct ImageOperands { } } + void AddDerivatives(EmitContext& ctx, Id derivatives) { + if (!Sirit::ValidId(derivatives)) { + return; + } + const Id dx{ctx.OpVectorShuffle(ctx.F32[2], derivatives, derivatives, 0, 1)}; + const Id dy{ctx.OpVectorShuffle(ctx.F32[2], derivatives, derivatives, 2, 3)}; + Add(spv::ImageOperandsMask::Grad, dx, dy); + } + spv::ImageOperandsMask mask{}; boost::container::static_vector operands; }; @@ -117,7 +132,7 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); const u32 comp = inst->Flags().gather_comp.Value(); ImageOperands operands; - operands.AddOffset(ctx, offset); + operands.AddOffset(ctx, offset, true); return ctx.OpImageGather(ctx.F32[4], sampled_image, coords, ctx.ConstU32(comp), operands.mask, operands.operands); } @@ -129,7 +144,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); ImageOperands operands; - operands.AddOffset(ctx, offset); + operands.AddOffset(ctx, offset, true); return ctx.OpImageDrefGather(ctx.F32[4], sampled_image, coords, dref, operands.mask, operands.operands); } @@ -181,9 +196,17 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords) { return ctx.OpImageQueryLod(ctx.F32[2], sampled_image, coords); } -Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivatives, const IR::Value& offset, Id lod_clamp) { - UNREACHABLE_MSG("SPIR-V Instruction"); +Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives, + const IR::Value& offset, Id lod_clamp) { + const auto& texture = ctx.images[handle & 0xFFFF]; + const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); + const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); + ImageOperands operands; + operands.AddDerivatives(ctx, derivatives); + operands.AddOffset(ctx, offset); + return ctx.OpImageSampleExplicitLod(ctx.F32[4], sampled_image, coords, operands.mask, + operands.operands); } Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index bc39bc0f3..0703efb96 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -387,8 +387,8 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const Id lod, Id ms); Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords); -Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivatives, const IR::Value& offset, Id lod_clamp); +Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives, + const IR::Value& offset, Id lod_clamp); Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id color); @@ -407,5 +407,8 @@ Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id co Id EmitLaneId(EmitContext& ctx); Id EmitWarpId(EmitContext& ctx); Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index); +Id EmitReadFirstLane(EmitContext& ctx, Id value); +Id EmitReadLane(EmitContext& ctx, Id value, u32 lane); +Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane); } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index 38afd90f1..c55763c5d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp @@ -22,4 +22,16 @@ Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index) { return ctx.OpGroupNonUniformQuadBroadcast(ctx.U32[1], SubgroupScope(ctx), value, index); } +Id EmitReadFirstLane(EmitContext& ctx, Id value) { + UNREACHABLE(); +} + +Id EmitReadLane(EmitContext& ctx, Id value, u32 lane) { + UNREACHABLE(); +} + +Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane) { + return ctx.u32_zero_value; +} + } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index b7b5aa138..7580f7444 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -127,7 +127,6 @@ void Translator::DS_ADD_U32(const GcnInst& inst, bool rtn) { const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 addr_offset = ir.IAdd(addr, offset); - IR::VectorReg dst_reg{inst.dst[0].code}; const IR::Value original_val = ir.SharedAtomicIAdd(addr_offset, data); if (rtn) { SetDst(inst.dst[0], IR::U32{original_val}); @@ -139,7 +138,6 @@ void Translator::DS_MIN_U32(const GcnInst& inst, bool rtn) { const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 addr_offset = ir.IAdd(addr, offset); - IR::VectorReg dst_reg{inst.dst[0].code}; const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, false); if (rtn) { SetDst(inst.dst[0], IR::U32{original_val}); @@ -151,7 +149,6 @@ void Translator::DS_MAX_U32(const GcnInst& inst, bool rtn) { const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 addr_offset = ir.IAdd(addr, offset); - IR::VectorReg dst_reg{inst.dst[0].code}; const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, false); if (rtn) { SetDst(inst.dst[0], IR::U32{original_val}); @@ -168,13 +165,18 @@ void Translator::V_READFIRSTLANE_B32(const GcnInst& inst) { } void Translator::V_READLANE_B32(const GcnInst& inst) { - ASSERT(info.stage != Stage::Compute); - SetDst(inst.dst[0], GetSrc(inst.src[0])); + const IR::ScalarReg dst{inst.dst[0].code}; + const IR::U32 value{GetSrc(inst.src[0])}; + const IR::U32 lane{GetSrc(inst.src[1])}; + ir.SetScalarReg(dst, ir.ReadLane(value, lane)); } void Translator::V_WRITELANE_B32(const GcnInst& inst) { - ASSERT(info.stage != Stage::Compute); - SetDst(inst.dst[0], GetSrc(inst.src[0])); + const IR::VectorReg dst{inst.dst[0].code}; + const IR::U32 value{GetSrc(inst.src[0])}; + const IR::U32 lane{GetSrc(inst.src[1])}; + const IR::U32 old_value{GetSrc(inst.dst[0])}; + ir.SetVectorReg(dst, ir.WriteLane(old_value, value, lane)); } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 812d93bae..7f7c9d7e0 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -440,13 +440,16 @@ void Translator::S_SUB_U32(const GcnInst& inst) { void Translator::S_GETPC_B64(u32 pc, const GcnInst& inst) { // This only really exists to let resource tracking pass know // there is an inline cbuf. - SetDst(inst.dst[0], ir.Imm32(pc)); + const IR::ScalarReg dst{inst.dst[0].code}; + ir.SetScalarReg(dst, ir.Imm32(pc)); + ir.SetScalarReg(dst + 1, ir.Imm32(0)); } void Translator::S_ADDC_U32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IAdd(ir.IAdd(src0, src1), ir.GetSccLo())); + const IR::U32 carry{ir.Select(ir.GetScc(), ir.Imm32(1U), ir.Imm32(0U))}; + SetDst(inst.dst[0], ir.IAdd(ir.IAdd(src0, src1), carry)); } void Translator::S_MAX_U32(const GcnInst& inst) { diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 08674fa2d..41eb91234 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -17,6 +17,7 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { case Opcode::IMAGE_SAMPLE_C_O: case Opcode::IMAGE_SAMPLE_B: case Opcode::IMAGE_SAMPLE_C_LZ_O: + case Opcode::IMAGE_SAMPLE_D: return IMAGE_SAMPLE(inst); case Opcode::IMAGE_GATHER4_C: case Opcode::IMAGE_GATHER4_LZ: @@ -162,12 +163,15 @@ void Translator::IMAGE_SAMPLE(const GcnInst& inst) { flags.test(MimgModifier::LodBias) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; const IR::F32 dref = flags.test(MimgModifier::Pcf) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; - - // Derivatives are tricky because their number depends on the texture type which is located in - // T#. We don't have access to T# though until resource tracking pass. For now assume no - // derivatives are present, otherwise we don't know where coordinates are placed in the address - // stream. - ASSERT_MSG(!flags.test(MimgModifier::Derivative), "Derivative image instruction"); + const IR::Value derivatives = [&] -> IR::Value { + if (!flags.test(MimgModifier::Derivative)) { + return {}; + } + addr_reg = addr_reg + 4; + return ir.CompositeConstruct( + ir.GetVectorReg(addr_reg - 4), ir.GetVectorReg(addr_reg - 3), + ir.GetVectorReg(addr_reg - 2), ir.GetVectorReg(addr_reg - 1)); + }(); // Now we can load body components as noted in Table 8.9 Image Opcodes with Sampler // Since these are at most 4 dwords, we load them into a single uvec4 and place them @@ -177,6 +181,10 @@ void Translator::IMAGE_SAMPLE(const GcnInst& inst) { ir.GetVectorReg(addr_reg), ir.GetVectorReg(addr_reg + 1), ir.GetVectorReg(addr_reg + 2), ir.GetVectorReg(addr_reg + 3)); + // Derivatives are tricky because their number depends on the texture type which is located in + // T#. We don't have access to T# though until resource tracking pass. For now assume if + // derivatives are present, that a 2D image is bound. + const bool has_derivatives = flags.test(MimgModifier::Derivative); const bool explicit_lod = flags.any(MimgModifier::Level0, MimgModifier::Lod); IR::TextureInstInfo info{}; @@ -186,9 +194,13 @@ void Translator::IMAGE_SAMPLE(const GcnInst& inst) { info.force_level0.Assign(flags.test(MimgModifier::Level0)); info.has_offset.Assign(flags.test(MimgModifier::Offset)); info.explicit_lod.Assign(explicit_lod); + info.has_derivatives.Assign(has_derivatives); // Issue IR instruction, leaving unknown fields blank to patch later. const IR::Value texel = [&]() -> IR::Value { + if (has_derivatives) { + return ir.ImageGradient(handle, body, derivatives, offset, {}, info); + } if (!flags.test(MimgModifier::Pcf)) { if (explicit_lod) { return ir.ImageSampleExplicitLod(handle, body, offset, info); diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 3ae068072..0f2fb2f7c 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -209,10 +209,6 @@ U1 IREmitter::GetVcc() { return Inst(Opcode::GetVcc); } -U32 IREmitter::GetSccLo() { - return Inst(Opcode::GetSccLo); -} - U32 IREmitter::GetVccLo() { return Inst(Opcode::GetVccLo); } @@ -445,6 +441,18 @@ U32 IREmitter::QuadShuffle(const U32& value, const U32& index) { return Inst(Opcode::QuadShuffle, value, index); } +U32 IREmitter::ReadFirstLane(const U32& value) { + return Inst(Opcode::ReadFirstLane, value); +} + +U32 IREmitter::ReadLane(const U32& value, const U32& lane) { + return Inst(Opcode::ReadLane, value, lane); +} + +U32 IREmitter::WriteLane(const U32& value, const U32& write_value, const U32& lane) { + return Inst(Opcode::WriteLane, value, write_value, lane); +} + F32F64 IREmitter::FPAdd(const F32F64& a, const F32F64& b) { if (a.Type() != b.Type()) { UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index be7f25153..45fa5f216 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -65,7 +65,6 @@ public: [[nodiscard]] U1 GetScc(); [[nodiscard]] U1 GetExec(); [[nodiscard]] U1 GetVcc(); - [[nodiscard]] U32 GetSccLo(); [[nodiscard]] U32 GetVccLo(); [[nodiscard]] U32 GetVccHi(); void SetScc(const U1& value); @@ -122,6 +121,9 @@ public: [[nodiscard]] U32 LaneId(); [[nodiscard]] U32 WarpId(); [[nodiscard]] U32 QuadShuffle(const U32& value, const U32& index); + [[nodiscard]] U32 ReadFirstLane(const U32& value); + [[nodiscard]] U32 ReadLane(const U32& value, const U32& lane); + [[nodiscard]] U32 WriteLane(const U32& value, const U32& write_value, const U32& lane); [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index e9ecd4350..9be89f648 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -58,7 +58,6 @@ OPCODE(SetAttribute, Void, Attr OPCODE(GetScc, U1, Void, ) OPCODE(GetExec, U1, Void, ) OPCODE(GetVcc, U1, Void, ) -OPCODE(GetSccLo, U32, Void, ) OPCODE(GetVccLo, U32, Void, ) OPCODE(GetVccHi, U32, Void, ) OPCODE(SetScc, Void, U1, ) @@ -330,19 +329,22 @@ OPCODE(ImageRead, U32x4, Opaq OPCODE(ImageWrite, Void, Opaque, Opaque, U32x4, ) // Image atomic operations -OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicSMin32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicUMin32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicSMax32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicUMax32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicInc32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicDec32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicAnd32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicSMin32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicUMin32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicSMax32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicUMax32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicInc32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicDec32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicAnd32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, ) // Warp operations OPCODE(LaneId, U32, ) OPCODE(WarpId, U32, ) OPCODE(QuadShuffle, U32, U32, U32 ) +OPCODE(ReadFirstLane, U32, U32, U32 ) +OPCODE(ReadLane, U32, U32, U32 ) +OPCODE(WriteLane, U32, U32, U32, U32 ) diff --git a/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp b/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp index 94218b32f..b0d9dcc45 100644 --- a/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp +++ b/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp @@ -250,6 +250,18 @@ void FoldCmpClass(IR::Inst& inst) { } } +void FoldReadLane(IR::Inst& inst) { + const u32 lane = inst.Arg(1).U32(); + IR::Inst* prod = inst.Arg(0).InstRecursive(); + while (prod->GetOpcode() == IR::Opcode::WriteLane) { + if (prod->Arg(2).U32() == lane) { + inst.ReplaceUsesWith(prod->Arg(1)); + return; + } + prod = prod->Arg(0).InstRecursive(); + } +} + void ConstantPropagation(IR::Block& block, IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::IAdd32: @@ -289,6 +301,8 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { case IR::Opcode::SelectF32: case IR::Opcode::SelectF64: return FoldSelect(inst); + case IR::Opcode::ReadLane: + return FoldReadLane(inst); case IR::Opcode::FPNeg32: FoldWhenAllImmediates(inst, [](f32 a) { return -a; }); return; diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 20a66ad0c..efee710db 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -345,6 +345,7 @@ SharpLocation TrackSharp(const IR::Inst* inst) { // Retrieve SGPR pair that holds sbase const auto pred1 = [](const IR::Inst* inst) -> std::optional { + ASSERT(inst->GetOpcode() != IR::Opcode::ReadConst); if (inst->GetOpcode() == IR::Opcode::GetUserData) { return inst->Arg(0).ScalarReg(); } @@ -402,24 +403,13 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, // is used to define an inline constant buffer IR::Inst* handle = inst.Arg(0).InstRecursive(); - IR::Inst* p0 = handle->Arg(0).InstRecursive(); - if (p0->GetOpcode() != IR::Opcode::IAdd32 || !p0->Arg(0).IsImmediate() || - !p0->Arg(1).IsImmediate()) { - return -1; - } - IR::Inst* p1 = handle->Arg(1).InstRecursive(); - if (p1->GetOpcode() != IR::Opcode::IAdd32) { - return -1; - } - if (!handle->Arg(3).IsImmediate() || !handle->Arg(2).IsImmediate()) { + if (!handle->AreAllArgsImmediates()) { return -1; } // We have found this pattern. Build the sharp. - std::array buffer; - buffer[0] = info.pgm_base + p0->Arg(0).U32() + p0->Arg(1).U32(); - buffer[1] = 0; - buffer[2] = handle->Arg(2).U32(); - buffer[3] = handle->Arg(3).U32(); + std::array buffer; + buffer[0] = info.pgm_base + (handle->Arg(0).U32() | u64(handle->Arg(1).U32()) << 32); + buffer[1] = handle->Arg(2).U32() | u64(handle->Arg(3).U32()) << 32; cbuf = std::bit_cast(buffer); // Assign a binding to this sharp. return descriptors.Add(BufferResource{ @@ -617,7 +607,11 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip const IR::Value arg = inst.Arg(arg_pos); ASSERT_MSG(arg.Type() == IR::Type::U32, "Unexpected offset type"); - const auto read = [&](u32 offset) -> auto { + const auto read = [&](u32 offset) -> IR::U32 { + if (arg.IsImmediate()) { + const u16 comp = (arg.U32() >> offset) & 0x3F; + return ir.Imm32(s32(comp << 26) >> 26); + } return ir.BitFieldExtract(IR::U32{arg}, ir.Imm32(offset), ir.Imm32(6), true); }; @@ -637,7 +631,10 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip UNREACHABLE(); } } - + if (inst_info.has_derivatives) { + ASSERT_MSG(image.GetType() == AmdGpu::ImageType::Color2D, + "User derivatives only supported for 2D images"); + } if (inst_info.has_lod_clamp) { const u32 arg_pos = [&]() -> u32 { switch (inst.GetOpcode()) { diff --git a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp index eef73a659..9edb157db 100644 --- a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp @@ -32,7 +32,6 @@ struct SccFlagTag : FlagTag {}; struct ExecFlagTag : FlagTag {}; struct VccFlagTag : FlagTag {}; struct VccLoTag : FlagTag {}; -struct SccLoTag : FlagTag {}; struct VccHiTag : FlagTag {}; struct GotoVariable : FlagTag { @@ -45,7 +44,7 @@ struct GotoVariable : FlagTag { }; using Variant = std::variant; + VccFlagTag, VccLoTag, VccHiTag>; using ValueMap = std::unordered_map; struct DefTable { @@ -84,13 +83,6 @@ struct DefTable { exec_flag.insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, SccLoTag) { - return scc_lo_flag[block]; - } - void SetDef(IR::Block* block, SccLoTag, const IR::Value& value) { - scc_lo_flag.insert_or_assign(block, value); - } - const IR::Value& Def(IR::Block* block, VccLoTag) { return vcc_lo_flag[block]; } @@ -133,10 +125,6 @@ IR::Opcode UndefOpcode(const VccLoTag) noexcept { return IR::Opcode::UndefU32; } -IR::Opcode UndefOpcode(const SccLoTag) noexcept { - return IR::Opcode::UndefU32; -} - IR::Opcode UndefOpcode(const VccHiTag) noexcept { return IR::Opcode::UndefU32; } @@ -336,9 +324,6 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::SetVcc: pass.WriteVariable(VccFlagTag{}, block, inst.Arg(0)); break; - case IR::Opcode::SetSccLo: - pass.WriteVariable(SccLoTag{}, block, inst.Arg(0)); - break; case IR::Opcode::SetVccLo: pass.WriteVariable(VccLoTag{}, block, inst.Arg(0)); break; @@ -371,9 +356,6 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::GetVcc: inst.ReplaceUsesWith(pass.ReadVariable(VccFlagTag{}, block)); break; - case IR::Opcode::GetSccLo: - inst.ReplaceUsesWith(pass.ReadVariable(SccLoTag{}, block)); - break; case IR::Opcode::GetVccLo: inst.ReplaceUsesWith(pass.ReadVariable(VccLoTag{}, block)); break; diff --git a/src/shader_recompiler/ir/reg.h b/src/shader_recompiler/ir/reg.h index e3d04260b..7868a5a3b 100644 --- a/src/shader_recompiler/ir/reg.h +++ b/src/shader_recompiler/ir/reg.h @@ -58,6 +58,7 @@ union TextureInstInfo { BitField<4, 1, u32> explicit_lod; BitField<5, 1, u32> has_offset; BitField<6, 2, u32> gather_comp; + BitField<8, 1, u32> has_derivatives; }; union BufferInstInfo { diff --git a/src/shader_recompiler/recompiler.cpp b/src/shader_recompiler/recompiler.cpp index 0f9fd6d41..0efac4ff1 100644 --- a/src/shader_recompiler/recompiler.cpp +++ b/src/shader_recompiler/recompiler.cpp @@ -56,11 +56,11 @@ IR::Program TranslateProgram(Common::ObjectPool& inst_pool, // Run optimization passes Shader::Optimization::SsaRewritePass(program.post_order_blocks); - Shader::Optimization::ResourceTrackingPass(program); Shader::Optimization::ConstantPropagationPass(program.post_order_blocks); if (program.info.stage != Stage::Compute) { Shader::Optimization::LowerSharedMemToRegisters(program); } + Shader::Optimization::ResourceTrackingPass(program); Shader::Optimization::IdentityRemovalPass(program.blocks); Shader::Optimization::DeadCodeEliminationPass(program); Shader::Optimization::CollectShaderInfoPass(program); diff --git a/src/video_core/amdgpu/resource.h b/src/video_core/amdgpu/resource.h index ef5bf1b66..8c3b675ea 100644 --- a/src/video_core/amdgpu/resource.h +++ b/src/video_core/amdgpu/resource.h @@ -179,6 +179,10 @@ struct Image { return base_address << 8; } + operator bool() const noexcept { + return base_address != 0; + } + u32 DstSelect() const { return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9); } diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index 6225f11ba..18b8aee21 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -51,7 +51,8 @@ struct PageManager::Impl { if (ec == EXCEPTION_ACCESS_VIOLATION) { const auto info = pExp->ExceptionRecord->ExceptionInformation; if (info[0] == 1) { // Write violation - rasterizer->InvalidateMemory(info[1], sizeof(u64)); + const VAddr addr_aligned = Common::AlignDown(info[1], PAGESIZE); + rasterizer->InvalidateMemory(addr_aligned, PAGESIZE); return EXCEPTION_CONTINUE_EXECUTION; } /* else { UNREACHABLE(); @@ -199,7 +200,8 @@ struct PageManager::Impl { const greg_t err = ctx->uc_mcontext.gregs[REG_ERR]; #endif if (err & 0x2) { - rasterizer->InvalidateMemory(address, sizeof(u64)); + const VAddr addr_aligned = Common::AlignDown(address, PAGESIZE); + rasterizer->InvalidateMemory(addr_aligned, PAGESIZE); } else { // Read not supported! UNREACHABLE(); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index c2649b96c..95d3a4b2d 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -396,13 +396,18 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, boost::container::static_vector tsharps; for (const auto& image_desc : stage->images) { - const auto& tsharp = tsharps.emplace_back( - stage->ReadUd(image_desc.sgpr_base, image_desc.dword_offset)); - VideoCore::ImageInfo image_info{tsharp}; - VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; - const auto& image_view = texture_cache.FindTexture(image_info, view_info); - const auto& image = texture_cache.GetImage(image_view.image_id); - image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); + const auto tsharp = + stage->ReadUd(image_desc.sgpr_base, image_desc.dword_offset); + if (tsharp) { + tsharps.emplace_back(tsharp); + VideoCore::ImageInfo image_info{tsharp}; + VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; + const auto& image_view = texture_cache.FindTexture(image_info, view_info); + const auto& image = texture_cache.GetImage(image_view.image_id); + image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); + } else { + image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); + } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, .dstBinding = binding++, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index c0923b743..12db47576 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -210,6 +210,8 @@ bool Instance::CreateDevice() { color_write_en &= add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); const bool calibrated_timestamps = add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME); const bool robustness = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); + const bool topology_restart = + add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME); // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 // with extensions. @@ -330,6 +332,9 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{ .vertexInputDynamicState = true, }, + vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT{ + .primitiveTopologyListRestart = true, + }, #ifdef __APPLE__ feature_chain.get(), #endif @@ -351,6 +356,9 @@ bool Instance::CreateDevice() { if (!workgroup_memory_explicit_layout) { device_chain.unlink(); } + if (!topology_restart) { + device_chain.unlink(); + } if (robustness) { device_chain.get().nullDescriptor = feature_chain.get().nullDescriptor; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 55f04bac4..139edcf7c 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -280,9 +280,6 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline() { DumpShader(code, hash, stage, "bin"); } - block_pool.ReleaseContents(); - inst_pool.ReleaseContents(); - if (stage != Shader::Stage::Fragment && stage != Shader::Stage::Vertex) { LOG_ERROR(Render_Vulkan, "Unsupported shader stage {}. PL creation skipped.", stage); return {}; diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 17b78a6d5..a073d046e 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -219,7 +219,12 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { guest_address = image.Address(); mips_layout.reserve(resources.levels); + tiling_idx = image.tiling_index; + UpdateSize(); +} +void ImageInfo::UpdateSize() { + mips_layout.clear(); MipInfo mip_info{}; guest_size_bytes = 0; for (auto mip = 0u; mip < resources.levels; ++mip) { @@ -265,7 +270,7 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { ASSERT(!props.is_block); ASSERT(num_samples == 1); std::tie(mip_info.pitch, mip_info.size) = - ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, image.tiling_index); + ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, tiling_idx); break; } default: { diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 9dad0dd67..ddad318d9 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -29,6 +29,8 @@ struct ImageInfo { bool IsPacked() const; bool IsDepthStencil() const; + void UpdateSize(); + struct { VAddr cmask_addr; VAddr fmask_addr; @@ -69,6 +71,7 @@ struct ImageInfo { boost::container::small_vector mips_layout; VAddr guest_address{0}; u32 guest_size_bytes{0}; + u32 tiling_idx{0}; // TODO: merge with existing! }; } // namespace VideoCore diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index cd3afc59f..cae124220 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -18,11 +18,15 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& BufferCache& buffer_cache_, PageManager& tracker_) : instance{instance_}, scheduler{scheduler_}, buffer_cache{buffer_cache_}, tracker{tracker_}, tile_manager{instance, scheduler} { - ImageInfo info; + ImageInfo info{}; info.pixel_format = vk::Format::eR8G8B8A8Unorm; info.type = vk::ImageType::e2D; + info.tiling_idx = u32(AmdGpu::TilingMode::Texture_MicroTiled); + info.num_bits = 32; + info.UpdateSize(); const ImageId null_id = slot_images.insert(instance, scheduler, info); ASSERT(null_id.index == 0); + slot_images[null_id].flags = ImageFlagBits{}; ImageViewInfo view_info; void(slot_image_views.insert(instance, view_info, slot_images[null_id], null_id)); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 7266d7a56..8af68424a 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -28,7 +28,7 @@ class TextureCache { using Entry = boost::container::small_vector; static constexpr size_t AddressSpaceBits = 39; static constexpr size_t FirstLevelBits = 9; - static constexpr size_t PageBits = 22; + static constexpr size_t PageBits = 20; }; using PageTable = MultiLevelPageTable; From 1e90f4594105c5e14f3d9099572dc765ab0e8d7a Mon Sep 17 00:00:00 2001 From: SaynedBread <114937220+CyntexMore@users.noreply.github.com> Date: Sun, 25 Aug 2024 02:53:13 +0200 Subject: [PATCH 029/147] docs: Added some fancy Markdown formating to the README --- README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 542acca9e..ba94b64bd 100644 --- a/README.md +++ b/README.md @@ -32,25 +32,28 @@ SPDX-License-Identifier: GPL-2.0-or-later

-# shadPS4 +# General information -shadPS4 is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++ +shadPS4 is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++. If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/Quickstart.md). To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility). -To discuss shadPS4 development or suggest ideas, join the [**Discord server**](https://discord.gg/MyZRaBngxA). +To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/MyZRaBngxA). -To get the latest news, go to our [**X (twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/). +To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/). # Status -In development, small games are working like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4), [**Dysmantle**](https://youtu.be/b9xzhLBdESE) and others... +> [!IMPORTANT] +> shadPS4 is early in developement, don't expect a flawless experience. + +Currently, the emulator successfully runs small games like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4), [**Dysmantle**](https://youtu.be/b9xzhLBdESE), and a few others. Most importantly shadPS4 can *somewhat* run Bloodborne. # Why -The project started as a fun project. Due to limited free time, it will probably take a while before shadPS4 is able to run anything decent, but we're trying to make small, regular commits. +This project began as a fun project. Given our limited free time, it may take some time before shadPS4 can run more complex games, but we're committed to making small, regular updates. # Build @@ -62,7 +65,7 @@ Check the build instructions for [**Windows**](https://github.com/shadps4-emu/sh Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-linux.md). -## Build status +## Building status
Windows @@ -95,9 +98,12 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad For more information on how to test, debug and report issues with the emulator or games, read the [Debugging documentation](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md). -# Keyboard Mapping +# Keyboard mapping -| Controller button | Keyboard | +> [!NOTE] +> Keyboard mappings can be changed from the Qt interface of shadPS4. Xbox and DualShock controllers work out of the box. + +| Controller button | Keyboard equivelant | |-------------|-------------| LEFT AXIS UP | W | LEFT AXIS DOWN | S | @@ -154,4 +160,4 @@ Open a PR and we'll check it :) # License -- [**GPL-2.0 license**](https://github.com/shadps4-emu/shadPS4/blob/main/LICENSE) \ No newline at end of file +- [**GPL-2.0 license**](https://github.com/shadps4-emu/shadPS4/blob/main/LICENSE) From 41a93dcae41d4c977d430978ba5b01a4ed03e108 Mon Sep 17 00:00:00 2001 From: SaynedBread <114937220+CyntexMore@users.noreply.github.com> Date: Sun, 25 Aug 2024 02:54:46 +0200 Subject: [PATCH 030/147] docs: Added some fancy Markdown formating to the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba94b64bd..25dbbccc2 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Currently, the emulator successfully runs small games like [**Sonic Mania**](htt This project began as a fun project. Given our limited free time, it may take some time before shadPS4 can run more complex games, but we're committed to making small, regular updates. -# Build +# Building ## Windows From 3f445eca407984a3808a1be9efd12ccfcb8299fa Mon Sep 17 00:00:00 2001 From: Dzmitry Dubrova Date: Sun, 25 Aug 2024 11:45:26 +0300 Subject: [PATCH 031/147] gui: Implement gui translations --- CMakeLists.txt | 19 +- src/common/config.cpp | 12 + src/common/config.h | 2 + src/qt_gui/game_info.cpp | 4 +- src/qt_gui/game_install_dialog.cpp | 10 +- src/qt_gui/gui_context_menus.h | 39 +-- src/qt_gui/main_window.cpp | 41 +++ src/qt_gui/main_window.h | 5 + src/qt_gui/settings_dialog.cpp | 33 ++ src/qt_gui/settings_dialog.h | 7 + src/qt_gui/settings_dialog.ui | 69 ++-- src/qt_gui/translations/da_DK.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/de.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/el.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/en.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/es_ES.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/fi.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/fr.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/hu_HU.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/id.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/it.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/ja_JP.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/ko_KR.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/lt_LT.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/nb.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/nl.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/pl_PL.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/pt_BR.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/ro_RO.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/ru_RU.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/tr_TR.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/vi_VN.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/zh_CN.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/translations/zh_TW.ts | 491 +++++++++++++++++++++++++++++ src/qt_gui/trophy_viewer.cpp | 2 +- 35 files changed, 11473 insertions(+), 63 deletions(-) create mode 100644 src/qt_gui/translations/da_DK.ts create mode 100644 src/qt_gui/translations/de.ts create mode 100644 src/qt_gui/translations/el.ts create mode 100644 src/qt_gui/translations/en.ts create mode 100644 src/qt_gui/translations/es_ES.ts create mode 100644 src/qt_gui/translations/fi.ts create mode 100644 src/qt_gui/translations/fr.ts create mode 100644 src/qt_gui/translations/hu_HU.ts create mode 100644 src/qt_gui/translations/id.ts create mode 100644 src/qt_gui/translations/it.ts create mode 100644 src/qt_gui/translations/ja_JP.ts create mode 100644 src/qt_gui/translations/ko_KR.ts create mode 100644 src/qt_gui/translations/lt_LT.ts create mode 100644 src/qt_gui/translations/nb.ts create mode 100644 src/qt_gui/translations/nl.ts create mode 100644 src/qt_gui/translations/pl_PL.ts create mode 100644 src/qt_gui/translations/pt_BR.ts create mode 100644 src/qt_gui/translations/ro_RO.ts create mode 100644 src/qt_gui/translations/ru_RU.ts create mode 100644 src/qt_gui/translations/tr_TR.ts create mode 100644 src/qt_gui/translations/vi_VN.ts create mode 100644 src/qt_gui/translations/zh_CN.ts create mode 100644 src/qt_gui/translations/zh_TW.ts diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ff00d6f5..721f11287 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,11 +113,27 @@ add_subdirectory(externals) include_directories(src) if(ENABLE_QT_GUI) - find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent) + find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools) qt_standard_project_setup() set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) + + set(QT_TRANSLATIONS "${PROJECT_SOURCE_DIR}/src/qt_gui/translations") + file(GLOB_RECURSE TRANSLATIONS_TS ${QT_TRANSLATIONS}/*.ts) + + set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations") + qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS}) + + set(TRANSLATIONS_QRC ${CMAKE_CURRENT_BINARY_DIR}/translations/translations.qrc) + file(WRITE ${TRANSLATIONS_QRC} "\n") + foreach (QM ${TRANSLATIONS_QM}) + get_filename_component(QM_FILE ${QM} NAME) + file(APPEND ${TRANSLATIONS_QRC} "${QM_FILE}\n") + endforeach (QM) + file(APPEND ${TRANSLATIONS_QRC} "") + + qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC}) endif() set(AUDIO_CORE src/audio_core/sdl_audio.cpp @@ -574,6 +590,7 @@ set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/main.cpp ${EMULATOR} ${RESOURCE_FILES} + ${TRANSLATIONS} ) endif() diff --git a/src/common/config.cpp b/src/common/config.cpp index ddd1d3257..0659a987f 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -45,6 +45,7 @@ u32 m_window_size_H = 720; std::vector m_pkg_viewer; std::vector m_elf_viewer; std::vector m_recent_files; +std::string emulator_language = "en"; // Settings u32 m_language = 1; // english @@ -242,6 +243,10 @@ void setRecentFiles(const std::vector& recentFiles) { m_recent_files = recentFiles; } +void setEmulatorLanguage(std::string language) { + emulator_language = language; +} + u32 getMainWindowGeometryX() { return main_window_geometry_x; } @@ -291,6 +296,10 @@ std::vector getRecentFiles() { return m_recent_files; } +std::string getEmulatorLanguage() { + return emulator_language; +} + u32 GetLanguage() { return m_language; } @@ -368,6 +377,7 @@ void load(const std::filesystem::path& path) { m_elf_viewer = toml::find_or>(gui, "elfDirs", {}); m_recent_files = toml::find_or>(gui, "recentFiles", {}); m_table_mode = toml::find_or(gui, "gameTableMode", 0); + emulator_language = toml::find_or(gui, "emulatorLanguage", "en"); } if (data.contains("Settings")) { @@ -430,6 +440,7 @@ void save(const std::filesystem::path& path) { data["GUI"]["pkgDirs"] = m_pkg_viewer; data["GUI"]["elfDirs"] = m_elf_viewer; data["GUI"]["recentFiles"] = m_recent_files; + data["GUI"]["emulatorLanguage"] = emulator_language; data["Settings"]["consoleLanguage"] = m_language; @@ -454,6 +465,7 @@ void setDefaultValues() { vblankDivider = 1; vkValidation = false; rdocEnable = false; + emulator_language = "en"; m_language = 1; gpuId = -1; } diff --git a/src/common/config.h b/src/common/config.h index 9bf91e692..458fa88c3 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -69,6 +69,7 @@ void setMainWindowHeight(u32 height); void setPkgViewer(const std::vector& pkgList); void setElfViewer(const std::vector& elfList); void setRecentFiles(const std::vector& recentFiles); +void setEmulatorLanguage(std::string language); u32 getMainWindowGeometryX(); u32 getMainWindowGeometryY(); @@ -86,6 +87,7 @@ u32 getMainWindowHeight(); std::vector getPkgViewer(); std::vector getElfViewer(); std::vector getRecentFiles(); +std::string getEmulatorLanguage(); void setDefaultValues(); diff --git a/src/qt_gui/game_info.cpp b/src/qt_gui/game_info.cpp index d2bf3bb2d..2821a0322 100644 --- a/src/qt_gui/game_info.cpp +++ b/src/qt_gui/game_info.cpp @@ -23,8 +23,8 @@ void GameInfoClass::GetGameInfo(QWidget* parent) { }).results(); // Progress bar, please be patient :) - QProgressDialog dialog("Loading game list, please wait :3", "Cancel", 0, 0, parent); - dialog.setWindowTitle("Loading..."); + QProgressDialog dialog(tr("Loading game list, please wait :3"), tr("Cancel"), 0, 0, parent); + dialog.setWindowTitle(tr("Loading...")); QFutureWatcher futureWatcher; GameListUtils game_util; diff --git a/src/qt_gui/game_install_dialog.cpp b/src/qt_gui/game_install_dialog.cpp index 4b2b8528b..5f031bdec 100644 --- a/src/qt_gui/game_install_dialog.cpp +++ b/src/qt_gui/game_install_dialog.cpp @@ -21,14 +21,14 @@ GameInstallDialog::GameInstallDialog() : m_gamesDirectory(nullptr) { layout->addStretch(); layout->addWidget(SetupDialogActions()); - setWindowTitle("shadPS4 - Choose directory"); + setWindowTitle(tr("shadPS4 - Choose directory")); setWindowIcon(QIcon(":images/shadps4.ico")); } GameInstallDialog::~GameInstallDialog() {} void GameInstallDialog::Browse() { - auto path = QFileDialog::getExistingDirectory(this, "Directory to install games"); + auto path = QFileDialog::getExistingDirectory(this, tr("Directory to install games")); if (!path.isEmpty()) { m_gamesDirectory->setText(QDir::toNativeSeparators(path)); @@ -36,7 +36,7 @@ void GameInstallDialog::Browse() { } QWidget* GameInstallDialog::SetupGamesDirectory() { - auto group = new QGroupBox("Directory to install games"); + auto group = new QGroupBox(tr("Directory to install games")); auto layout = new QHBoxLayout(group); // Input. @@ -47,7 +47,7 @@ QWidget* GameInstallDialog::SetupGamesDirectory() { layout->addWidget(m_gamesDirectory); // Browse button. - auto browse = new QPushButton("Browse"); + auto browse = new QPushButton(tr("Browse")); connect(browse, &QPushButton::clicked, this, &GameInstallDialog::Browse); @@ -71,7 +71,7 @@ void GameInstallDialog::Save() { if (gamesDirectory.isEmpty() || !QDir(gamesDirectory).exists() || !QDir::isAbsolutePath(gamesDirectory)) { - QMessageBox::critical(this, "Error", + QMessageBox::critical(this, tr("Error"), "The value for location to install games is not valid."); return; } diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 16afdb188..f4bc519a2 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -36,10 +36,10 @@ public: // Setup menu. QMenu menu(widget); - QAction createShortcut("Create Shortcut", widget); - QAction openFolder("Open Game Folder", widget); - QAction openSfoViewer("SFO Viewer", widget); - QAction openTrophyViewer("Trophy Viewer", widget); + QAction createShortcut(tr("Create Shortcut"), widget); + QAction openFolder(tr("Open Game Folder"), widget); + QAction openSfoViewer(tr("SFO Viewer"), widget); + QAction openTrophyViewer(tr("Trophy Viewer"), widget); menu.addAction(&openFolder); menu.addAction(&createShortcut); @@ -47,10 +47,10 @@ public: menu.addAction(&openTrophyViewer); // "Copy" submenu. - QMenu* copyMenu = new QMenu("Copy info", widget); - QAction* copyName = new QAction("Copy Name", widget); - QAction* copySerial = new QAction("Copy Serial", widget); - QAction* copyNameAll = new QAction("Copy All", widget); + QMenu* copyMenu = new QMenu(tr("Copy info"), widget); + QAction* copyName = new QAction(tr("Copy Name"), widget); + QAction* copySerial = new QAction(tr("Copy Serial"), widget); + QAction* copyNameAll = new QAction(tr("Copy All"), widget); copyMenu->addAction(copyName); copyMenu->addAction(copySerial); @@ -116,7 +116,7 @@ public: tableWidget->horizontalHeader()->setVisible(false); tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); - tableWidget->setWindowTitle("SFO Viewer"); + tableWidget->setWindowTitle(tr("SFO Viewer")); tableWidget->show(); } } @@ -170,15 +170,15 @@ public: if (createShortcutLinux(linkPath, ebootPath, iconPath)) { #endif QMessageBox::information( - nullptr, "Shortcut creation", - QString("Shortcut created successfully!\n %1").arg(linkPath)); + nullptr, tr("Shortcut creation"), + QString(tr("Shortcut created successfully!\n %1")).arg(linkPath)); } else { QMessageBox::critical( - nullptr, "Error", - QString("Error creating shortcut!\n %1").arg(linkPath)); + nullptr, tr("Error"), + QString(tr("Error creating shortcut!\n %1")).arg(linkPath)); } } else { - QMessageBox::critical(nullptr, "Error", "Failed to convert icon."); + QMessageBox::critical(nullptr, tr("Error"), tr("Failed to convert icon.")); } } else { // If the icon is already in ICO format, we just create the shortcut @@ -188,11 +188,12 @@ public: if (createShortcutLinux(linkPath, ebootPath, iconPath)) { #endif QMessageBox::information( - nullptr, "Shortcut creation", - QString("Shortcut created successfully!\n %1").arg(linkPath)); + nullptr, tr("Shortcut creation"), + QString(tr("Shortcut created successfully!\n %1")).arg(linkPath)); } else { - QMessageBox::critical(nullptr, "Error", - QString("Error creating shortcut!\n %1").arg(linkPath)); + QMessageBox::critical( + nullptr, tr("Error"), + QString(tr("Error creating shortcut!\n %1")).arg(linkPath)); } } } @@ -249,7 +250,7 @@ public: int itemIndex = GetRowIndex(treeWidget, currentItem); // row QMenu menu(treeWidget); - QAction installPackage("Install PKG", treeWidget); + QAction installPackage(tr("Install PKG"), treeWidget); menu.addAction(&installPackage); diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index b6711d719..64a89c6a6 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -37,6 +37,7 @@ bool MainWindow::Init() { SetLastUsedTheme(); SetLastIconSizeBullet(); GetPhysicalDevices(); + LoadTranslation(); // show ui setMinimumSize(350, minimumSizeHint().height()); setWindowTitle(QString::fromStdString("shadPS4 v" + std::string(Common::VERSION))); @@ -200,11 +201,19 @@ void MainWindow::CreateConnects() { connect(ui->configureAct, &QAction::triggered, this, [this]() { auto settingsDialog = new SettingsDialog(m_physical_devices, this); + + connect(settingsDialog, &SettingsDialog::LanguageChanged, this, + &MainWindow::OnLanguageChanged); + settingsDialog->exec(); }); connect(ui->settingsButton, &QPushButton::clicked, this, [this]() { auto settingsDialog = new SettingsDialog(m_physical_devices, this); + + connect(settingsDialog, &SettingsDialog::LanguageChanged, this, + &MainWindow::OnLanguageChanged); + settingsDialog->exec(); }); @@ -781,3 +790,35 @@ void MainWindow::CreateRecentGameActions() { emulator.Run(gamePath.toUtf8().constData()); }); } + +void MainWindow::LoadTranslation() { + auto language = QString::fromStdString(Config::getEmulatorLanguage()); + + const QString base_dir = QStringLiteral(":/translations"); + QString base_path = QStringLiteral("%1/%2.qm").arg(base_dir).arg(language); + + if (QFile::exists(base_path)) { + if (translator != nullptr) { + qApp->removeTranslator(translator); + } + + translator = new QTranslator(qApp); + if (!translator->load(base_path)) { + QMessageBox::warning( + nullptr, QStringLiteral("Translation Error"), + QStringLiteral("Failed to find load translation file for '%1':\n%2") + .arg(language) + .arg(base_path)); + delete translator; + } else { + qApp->installTranslator(translator); + ui->retranslateUi(this); + } + } +} + +void MainWindow::OnLanguageChanged(const std::string& locale) { + Config::setEmulatorLanguage(locale); + + LoadTranslation(); +} \ No newline at end of file diff --git a/src/qt_gui/main_window.h b/src/qt_gui/main_window.h index 1abe17625..d3b83e619 100644 --- a/src/qt_gui/main_window.h +++ b/src/qt_gui/main_window.h @@ -5,6 +5,7 @@ #include #include +#include #include "common/config.h" #include "common/path_util.h" @@ -43,6 +44,7 @@ private Q_SLOTS: void ShowGameList(); void RefreshGameTable(); void HandleResize(QResizeEvent* event); + void OnLanguageChanged(const std::string& locale); private: Ui_MainWindow* ui; @@ -59,6 +61,7 @@ private: void InstallPkg(); void BootGame(); void AddRecentFiles(QString filePath); + void LoadTranslation(); QIcon RecolorIcon(const QIcon& icon, bool isWhite); bool isIconBlack = false; bool isTableList = true; @@ -84,6 +87,8 @@ private: std::shared_ptr m_game_info = std::make_shared(); + QTranslator* translator; + protected: void dragEnterEvent(QDragEnterEvent* event1) override { if (event1->mimeData()->hasUrls()) { diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 09247951a..d572915c6 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include "main_window.h" #include "settings_dialog.h" #include "ui_settings_dialog.h" @@ -60,6 +62,7 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge completer->setCaseSensitivity(Qt::CaseInsensitive); ui->consoleLanguageComboBox->setCompleter(completer); + InitializeEmulatorLanguages(); LoadValuesFromConfig(); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close); @@ -158,6 +161,7 @@ void SettingsDialog::LoadValuesFromConfig() { languageIndexes.begin(), std::find(languageIndexes.begin(), languageIndexes.end(), Config::GetLanguage())) % languageIndexes.size()); + ui->emulatorLanguageComboBox->setCurrentIndex(languages[Config::getEmulatorLanguage()]); ui->graphicsAdapterBox->setCurrentIndex(Config::getGpuId() + 1); ui->widthSpinBox->setValue(Config::getScreenWidth()); ui->heightSpinBox->setValue(Config::getScreenHeight()); @@ -179,6 +183,35 @@ void SettingsDialog::LoadValuesFromConfig() { ui->rdocCheckBox->setChecked(Config::isRdocEnabled()); } +void SettingsDialog::InitializeEmulatorLanguages() { + QDirIterator it(QStringLiteral(":/translations"), QDirIterator::NoIteratorFlags); + + int idx = 0; + while (it.hasNext()) { + QString locale = it.next(); + locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); + locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); + const QString lang = QLocale::languageToString(QLocale(locale).language()); + const QString country = QLocale::territoryToString(QLocale(locale).territory()); + ui->emulatorLanguageComboBox->addItem(QStringLiteral("%1 (%2)").arg(lang, country), locale); + + languages[locale.toStdString()] = idx; + idx++; + } + + connect(ui->emulatorLanguageComboBox, qOverload(&QComboBox::currentIndexChanged), this, + &SettingsDialog::OnLanguageChanged); +} + +void SettingsDialog::OnLanguageChanged(int index) { + if (index == -1) + return; + + ui->retranslateUi(this); + + emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString()); +} + int SettingsDialog::exec() { return QDialog::exec(); } diff --git a/src/qt_gui/settings_dialog.h b/src/qt_gui/settings_dialog.h index 7d8701093..ddae7daac 100644 --- a/src/qt_gui/settings_dialog.h +++ b/src/qt_gui/settings_dialog.h @@ -22,8 +22,15 @@ public: int exec() override; +signals: + void LanguageChanged(const std::string& locale); + private: void LoadValuesFromConfig(); + void InitializeEmulatorLanguages(); + void OnLanguageChanged(int index); std::unique_ptr ui; + + std::map languages; }; diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index d11f177d1..1ecd12495 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -79,32 +79,6 @@ System - - - - 6 - - - 0 - - - - - - - Username - - - - - - - - - - - - @@ -117,6 +91,18 @@ + + + + Emulator Language + + + + + + + + @@ -156,17 +142,30 @@ - - - Qt::Orientation::Horizontal + + + 6 - - - 40 - 20 - + + 0 - + + + + + + Username + + + + + + + + + + + diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts new file mode 100644 index 000000000..0f4489eed --- /dev/null +++ b/src/qt_gui/translations/da_DK.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts new file mode 100644 index 000000000..1ff204df9 --- /dev/null +++ b/src/qt_gui/translations/de.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts new file mode 100644 index 000000000..b015954e6 --- /dev/null +++ b/src/qt_gui/translations/el.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts new file mode 100644 index 000000000..5ceb11884 --- /dev/null +++ b/src/qt_gui/translations/en.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts new file mode 100644 index 000000000..eedd4f6d4 --- /dev/null +++ b/src/qt_gui/translations/es_ES.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts new file mode 100644 index 000000000..af605d641 --- /dev/null +++ b/src/qt_gui/translations/fi.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts new file mode 100644 index 000000000..d56f6e427 --- /dev/null +++ b/src/qt_gui/translations/fr.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts new file mode 100644 index 000000000..a32b2d2ad --- /dev/null +++ b/src/qt_gui/translations/hu_HU.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts new file mode 100644 index 000000000..502be21e6 --- /dev/null +++ b/src/qt_gui/translations/id.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts new file mode 100644 index 000000000..64d123f2e --- /dev/null +++ b/src/qt_gui/translations/it.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts new file mode 100644 index 000000000..c67352569 --- /dev/null +++ b/src/qt_gui/translations/ja_JP.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts new file mode 100644 index 000000000..b33b5d927 --- /dev/null +++ b/src/qt_gui/translations/ko_KR.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts new file mode 100644 index 000000000..286ec3f43 --- /dev/null +++ b/src/qt_gui/translations/lt_LT.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts new file mode 100644 index 000000000..27fc540c1 --- /dev/null +++ b/src/qt_gui/translations/nb.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts new file mode 100644 index 000000000..2f4f5f9b2 --- /dev/null +++ b/src/qt_gui/translations/nl.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts new file mode 100644 index 000000000..cad5c5829 --- /dev/null +++ b/src/qt_gui/translations/pl_PL.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts new file mode 100644 index 000000000..a35f9b1d8 --- /dev/null +++ b/src/qt_gui/translations/pt_BR.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts new file mode 100644 index 000000000..c7dfae1b4 --- /dev/null +++ b/src/qt_gui/translations/ro_RO.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts new file mode 100644 index 000000000..556875e17 --- /dev/null +++ b/src/qt_gui/translations/ru_RU.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts new file mode 100644 index 000000000..ebb8b9b7c --- /dev/null +++ b/src/qt_gui/translations/tr_TR.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts new file mode 100644 index 000000000..08af9b351 --- /dev/null +++ b/src/qt_gui/translations/vi_VN.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts new file mode 100644 index 000000000..6f6392237 --- /dev/null +++ b/src/qt_gui/translations/zh_CN.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts new file mode 100644 index 000000000..1ddeaa43f --- /dev/null +++ b/src/qt_gui/translations/zh_TW.ts @@ -0,0 +1,491 @@ + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + 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 + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + About shadPS4 + About shadPS4 + + + + Configure... + Configure... + + + + Install application from a .pkg file + Install application from a .pkg file + + + + Recent Games + Recent Games + + + + 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 + + + + 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 + + + + About + About + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + Show Splash + Show Splash + + + + Is PS4 Pro + Is PS4 Pro + + + + Username + Username + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Graphics + Graphics + + + + 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 PM4 Dumping + Enable PM4 Dumping + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/trophy_viewer.cpp b/src/qt_gui/trophy_viewer.cpp index bb17dfc3a..57dce6b4e 100644 --- a/src/qt_gui/trophy_viewer.cpp +++ b/src/qt_gui/trophy_viewer.cpp @@ -5,7 +5,7 @@ #include "trophy_viewer.h" TrophyViewer::TrophyViewer(QString trophyPath, QString gameTrpPath) : QMainWindow() { - this->setWindowTitle("Trophy Viewer"); + this->setWindowTitle(tr("Trophy Viewer")); this->setAttribute(Qt::WA_DeleteOnClose); tabWidget = new QTabWidget(this); gameTrpPath_ = gameTrpPath; From 7766a653d572dd0ead49d9a8fb2894961f23a555 Mon Sep 17 00:00:00 2001 From: Dzmitry Dubrova Date: Sun, 25 Aug 2024 12:30:05 +0300 Subject: [PATCH 032/147] ci: Add LinguistTools to CIs --- .github/workflows/macos-qt.yml | 3 ++- .github/workflows/windows-qt.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml index 4b3672dff..24c71af49 100644 --- a/.github/workflows/macos-qt.yml +++ b/.github/workflows/macos-qt.yml @@ -38,7 +38,7 @@ jobs: host: mac target: desktop arch: clang_64 - archives: qtbase + archives: qtbase qttools - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON @@ -50,6 +50,7 @@ jobs: run: | mkdir upload mv ${{github.workspace}}/build/shadps4.app upload + mv ${{github.workspace}}/build/translations/* upload macdeployqt upload/shadps4.app tar cf shadps4-macos-qt.tar.gz -C upload . diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml index 06a16eb5b..a3adfa90c 100644 --- a/.github/workflows/windows-qt.yml +++ b/.github/workflows/windows-qt.yml @@ -28,7 +28,7 @@ jobs: host: windows target: desktop arch: win64_msvc2019_64 - archives: qtbase + archives: qtbase qttools - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T ClangCL -DENABLE_QT_GUI=ON @@ -40,6 +40,7 @@ jobs: run: | mkdir upload move build/Release/shadPS4.exe upload + move build/Release/translations/* upload windeployqt --dir upload upload/shadPS4.exe - name: Upload executable From e603165e2b7a71bdfa38e0c74f2d344f19f933e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Sun, 25 Aug 2024 12:31:45 +0200 Subject: [PATCH 033/147] Implement French translation --- src/qt_gui/translations/fr.ts | 182 +++++++++++++++++----------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index d56f6e427..54100f17d 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + À propos de shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 est un émulateur expérimental de la PlayStation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Ce logiciel ne doit pas être utilisé pour jouer à des jeux que vous n'avez pas obtenus légalement. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Ouvrir un dossier @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Chargement de la liste de jeu, veuillez attendre... Cancel - Cancel + Annuler Loading... - Loading... + Chargement... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Choisir un répertoire Directory to install games - Directory to install games + Répertoire pour installer les jeux Browse - Browse + Parcourir Error - Error + Erreur The value for location to install games is not valid. - The value for location to install games is not valid. + Le répertoire d'installation des jeux n'est pas valide. @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + Créer un raccourci Open Game Folder - Open Game Folder + Ouvrir le dossier du jeu SFO Viewer - SFO Viewer + Visionneur SFO Trophy Viewer - Trophy Viewer + Visionneur de trophés Copy info - Copy info + Copier les informations Copy Name - Copy Name + Copier le nom Copy Serial - Copy Serial + Copier le numéro de série Copy All - Copy All + Copier tout Shortcut creation - Shortcut creation + Création du raccourci Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Raccourci créé avec succès!\n %1 Error - Error + Erreur Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Erreur lors de la création du raccourci!\n %1 Install PKG - Install PKG + Installer un PKG @@ -151,177 +151,177 @@ Open/Add Elf Folder - Open/Add Elf Folder + Ouvrir/Ajouter un dossier Elf Install Packages (PKG) - Install Packages (PKG) + Installer des packages (PKG) Boot Game - Boot Game + Démarrer un jeu About shadPS4 - About shadPS4 + À propos de shadPS4 Configure... - Configure... + Configurer... Install application from a .pkg file - Install application from a .pkg file + Installer une application depuis un fichier .pkg Recent Games - Recent Games + Jeux récents Exit - Exit + Fermer Exit shadPS4 - Exit shadPS4 + Fermer shadPS4 Exit the application. - Exit the application. + Fermer l'application. Show Game List - Show Game List + Afficher la liste de jeux Game List Refresh - Game List Refresh + Rafraîchir la liste de jeux Tiny - Tiny + Très Petit Small - Small + Petit Medium - Medium + Moyen Large - Large + Grand List View - List View + Mode liste Grid View - Grid View + Mode grille Elf Viewer - Elf Viewer + Visionneur Elf Game Install Directory - Game Install Directory + Répertoire des jeux Dump Game List - Dump Game List + Dumper la liste des jeux PKG Viewer - PKG Viewer + Visionneur PKG Search... - Search... + Chercher... File - File + Fichier View - View + Affichage Game List Icons - Game List Icons + Icones des jeux Game List Mode - Game List Mode + Mode liste Settings - Settings + Paramètres Utils - Utils + Utilitaire Themes - Themes + Thèmes About - About + À propos Dark - Dark + Noir Light - Light + Blanc Green - Green + Vert Blue - Blue + Bleu @@ -331,7 +331,7 @@ toolBar - toolBar + Bare d'outils @@ -339,7 +339,7 @@ Open Folder - Open Folder + Ouvrir un dossier @@ -347,7 +347,7 @@ Trophy Viewer - Trophy Viewer + Visionneur de trophés @@ -355,137 +355,137 @@ Settings - Settings + Paramètres General - General + Général System - System + Système Console Language - Console Language + Langage de la console Emulator Language - Emulator Language + Langage de l'émulateur Emulator - Emulator + Émulateur Enable Fullscreen - Enable Fullscreen + Plein écran Show Splash - Show Splash + Afficher l'image du jeu Is PS4 Pro - Is PS4 Pro + Mode PS4 Pro Username - Username + Nom d'utilisateur Logger - Logger + Journalisation Log Type - Log Type + Type Log Filter - Log Filter + Filtre Graphics - Graphics + Graphismes Graphics Device - Graphics Device + Carte graphique Width - Width + Largeur Height - Height + Hauteur Vblank Divider - Vblank Divider + Vblank Advanced - Advanced + Avancé Enable Shaders Dumping - Enable Shaders Dumping + Dumper les shaders Enable NULL GPU - Enable NULL GPU + NULL GPU Enable PM4 Dumping - Enable PM4 Dumping + Dumper le PM4 Debug - Debug + Débogage Enable Debug Dumping - Enable Debug Dumping + Activer le débogage Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Couche de validation Vulkan Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Synchroniser la validation Vulkan Enable RenderDoc Debugging - Enable RenderDoc Debugging + Activer le débogage RenderDoc - \ No newline at end of file + From 83b43363fa7e63b68dd60bc3039e78ceabe3df18 Mon Sep 17 00:00:00 2001 From: Dzmitry Dubrova Date: Sun, 25 Aug 2024 13:59:22 +0300 Subject: [PATCH 034/147] ci: Fix CI --- .github/workflows/macos-qt.yml | 2 +- .github/workflows/windows-qt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml index 24c71af49..def98ea34 100644 --- a/.github/workflows/macos-qt.yml +++ b/.github/workflows/macos-qt.yml @@ -50,7 +50,7 @@ jobs: run: | mkdir upload mv ${{github.workspace}}/build/shadps4.app upload - mv ${{github.workspace}}/build/translations/* upload + mv ${{github.workspace}}/build/translations upload macdeployqt upload/shadps4.app tar cf shadps4-macos-qt.tar.gz -C upload . diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml index a3adfa90c..70c33ebe9 100644 --- a/.github/workflows/windows-qt.yml +++ b/.github/workflows/windows-qt.yml @@ -40,7 +40,7 @@ jobs: run: | mkdir upload move build/Release/shadPS4.exe upload - move build/Release/translations/* upload + move build/translations upload windeployqt --dir upload upload/shadPS4.exe - name: Upload executable From 5664d45305b310d8716d9eee598964ad53ec0cf2 Mon Sep 17 00:00:00 2001 From: SaynedBread <114937220+CyntexMore@users.noreply.github.com> Date: Sun, 25 Aug 2024 14:12:16 +0200 Subject: [PATCH 035/147] docs: Updated Status --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 25dbbccc2..4e9e6fb9e 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or ou > [!IMPORTANT] > shadPS4 is early in developement, don't expect a flawless experience. -Currently, the emulator successfully runs small games like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4), [**Dysmantle**](https://youtu.be/b9xzhLBdESE), and a few others. Most importantly shadPS4 can *somewhat* run Bloodborne. +Currently, the emulator successfully runs small games like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4) and it can even *somewhat* run [**Bloodborne**](https://www.youtube.com/watch?v=wC6s0avpQRE). # Why From 6a87c37aeb8d49a750696608f187820faeed471b Mon Sep 17 00:00:00 2001 From: SaynedBread <114937220+CyntexMore@users.noreply.github.com> Date: Sun, 25 Aug 2024 14:37:17 +0200 Subject: [PATCH 036/147] docs: Removed misinformation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e9e6fb9e..c99142c78 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ For more information on how to test, debug and report issues with the emulator o # Keyboard mapping > [!NOTE] -> Keyboard mappings can be changed from the Qt interface of shadPS4. Xbox and DualShock controllers work out of the box. +> Xbox and DualShock controllers work out of the box. | Controller button | Keyboard equivelant | |-------------|-------------| From 26b5661dea64da7b1f6dc62d2746b5e5468b21a9 Mon Sep 17 00:00:00 2001 From: Dzmitry Dubrova Date: Sun, 25 Aug 2024 15:19:24 +0300 Subject: [PATCH 037/147] ci: Fix linux-qt CI --- .github/linux-appimage-qt.sh | 4 ++++ .github/workflows/linux-qt.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/linux-appimage-qt.sh b/.github/linux-appimage-qt.sh index 870172457..203d214e3 100755 --- a/.github/linux-appimage-qt.sh +++ b/.github/linux-appimage-qt.sh @@ -19,8 +19,12 @@ chmod a+x linuxdeploy-x86_64.AppImage chmod a+x linuxdeploy-plugin-qt-x86_64.AppImage chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh + # Build AppImage ./linuxdeploy-x86_64.AppImage --appdir AppDir ./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir + +cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin + ./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --plugin qt --output appimage mv Shadps4-x86_64.AppImage Shadps4-qt.AppImage diff --git a/.github/workflows/linux-qt.yml b/.github/workflows/linux-qt.yml index 5611ae50f..26b80d683 100644 --- a/.github/workflows/linux-qt.yml +++ b/.github/workflows/linux-qt.yml @@ -23,7 +23,7 @@ jobs: - name: Install misc packages run: > - sudo apt-get update && sudo apt install libx11-dev libxext-dev libwayland-dev libfuse2 clang build-essential qt6-base-dev + sudo apt-get update && sudo apt install libx11-dev libxext-dev libwayland-dev libfuse2 clang build-essential qt6-base-dev qt6-tools-dev - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON From b687ae5e3474ae4f124a730e4e59b810768c19d7 Mon Sep 17 00:00:00 2001 From: psucien <168137814+psucien@users.noreply.github.com> Date: Sun, 25 Aug 2024 22:01:05 +0200 Subject: [PATCH 038/147] GnmDriver: Clear context support (#567) * gnmdriver: added support for gpu context reset * shader_recompiler: minor validation fixes * shader_recompiler: added `V_CMPX_GT_I32` * shader_recompiler: fix for crash on inline sampler access * compilation warnings and dead code elimination * amdgpu: fix for registers addressing * libraries: videoout: reduce logging pressure * shader_recompiler: fix for devergence scope detection --- CMakeLists.txt | 1 + src/core/libraries/gnmdriver/gnmdriver.cpp | 50 +++++++++++------ src/core/libraries/videoout/video_out.cpp | 16 +++--- .../backend/spirv/emit_spirv.cpp | 1 + .../backend/spirv/spirv_emit_context.cpp | 4 ++ .../frontend/control_flow_graph.cpp | 18 ++++-- .../frontend/instruction.cpp | 14 +++++ src/shader_recompiler/frontend/instruction.h | 1 + .../frontend/translate/vector_alu.cpp | 2 + .../ir/passes/resource_tracking_pass.cpp | 5 +- src/video_core/amdgpu/default_context.cpp | 55 +++++++++++++++++++ src/video_core/amdgpu/liverpool.cpp | 1 + src/video_core/amdgpu/liverpool.h | 2 + src/video_core/buffer_cache/buffer.h | 6 +- .../renderer_vulkan/vk_instance.cpp | 1 + .../renderer_vulkan/vk_rasterizer.cpp | 4 +- src/video_core/texture_cache/image.h | 6 +- src/video_core/texture_cache/image_view.cpp | 3 +- src/video_core/texture_cache/tile_manager.cpp | 7 --- 19 files changed, 147 insertions(+), 50 deletions(-) create mode 100644 src/video_core/amdgpu/default_context.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 721f11287..43ad23e94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -488,6 +488,7 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/amdgpu/pm4_cmds.h src/video_core/amdgpu/pm4_opcodes.h src/video_core/amdgpu/resource.h + src/video_core/amdgpu/default_context.cpp src/video_core/buffer_cache/buffer.cpp src/video_core/buffer_cache/buffer.h src/video_core/buffer_cache/buffer_cache.cpp diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index c2ee6d592..95821a03b 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -55,6 +55,10 @@ static constexpr auto HwInitPacketSize = 0x100u; // clang-format off static constexpr std::array InitSequence{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -94,9 +98,13 @@ static constexpr std::array InitSequence{ 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, 0xc0017900u, 0x200u, 0xe0000000u, }; -static_assert(InitSequence.size() == 0x73); +static_assert(InitSequence.size() == 0x73 + 2); static constexpr std::array InitSequence175{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -136,9 +144,13 @@ static constexpr std::array InitSequence175{ 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, 0xc0017900u, 0x200u, 0xe0000000u, }; -static_assert(InitSequence175.size() == 0x73); +static_assert(InitSequence175.size() == 0x73 + 2); static constexpr std::array InitSequence200{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -179,9 +191,13 @@ static constexpr std::array InitSequence200{ 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, 0xc0017900u, 0x200u, 0xe0000000u, }; -static_assert(InitSequence200.size() == 0x76); +static_assert(InitSequence200.size() == 0x76 + 2); static constexpr std::array InitSequence350{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -224,7 +240,7 @@ static constexpr std::array InitSequence350{ 0xc0017900u, 0x200u, 0xe0000000u, 0xc0016900u, 0x2aau, 0xffu, }; -static_assert(InitSequence350.size() == 0x7c); +static_assert(InitSequence350.size() == 0x7c + 2); static constexpr std::array CtxInitSequence{ 0xc0012800u, 0x80000000u, 0x80000000u, @@ -735,11 +751,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, InitSequence.data(), InitSequence.size() * 4); - cmdbuf += InitSequence.size(); + std::memcpy(cmdbuf, &InitSequence[2], (InitSequence.size() - 2) * 4); + cmdbuf += InitSequence.size() - 2; const auto cmdbuf_left = - HwInitPacketSize - InitSequence.size() - (clear_state ? 0xc : 0) - 1; + HwInitPacketSize - (InitSequence.size() - 2) - (clear_state ? 0xc : 0) - 1; cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); cmdbuf = WriteBody(cmdbuf, 0u); @@ -757,10 +773,10 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState175(u32* cmdbuf, u32 size) { } cmdbuf = ClearContextState(cmdbuf); - std::memcpy(cmdbuf, InitSequence175.data(), InitSequence175.size() * 4); - cmdbuf += InitSequence175.size(); + std::memcpy(cmdbuf, &InitSequence175[2], (InitSequence175.size() - 2) * 4); + cmdbuf += InitSequence175.size() - 2; - constexpr auto cmdbuf_left = HwInitPacketSize - InitSequence175.size() - 0xc - 1; + constexpr auto cmdbuf_left = HwInitPacketSize - (InitSequence175.size() - 2) - 0xc - 1; WriteTrailingNop(cmdbuf); return HwInitPacketSize; @@ -778,11 +794,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState200(u32* cmdbuf, u32 size) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, InitSequence200.data(), InitSequence200.size() * 4); - cmdbuf += InitSequence200.size(); + std::memcpy(cmdbuf, &InitSequence200[2], (InitSequence200.size() - 2) * 4); + cmdbuf += InitSequence200.size() - 2; const auto cmdbuf_left = - HwInitPacketSize - InitSequence200.size() - (clear_state ? 0xc : 0) - 1; + HwInitPacketSize - (InitSequence200.size() - 2) - (clear_state ? 0xc : 0) - 1; cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); cmdbuf = WriteBody(cmdbuf, 0u); @@ -804,11 +820,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState350(u32* cmdbuf, u32 size) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, InitSequence350.data(), InitSequence350.size() * 4); - cmdbuf += InitSequence350.size(); + std::memcpy(cmdbuf, &InitSequence350[2], (InitSequence350.size() - 2) * 4); + cmdbuf += InitSequence350.size() - 2; const auto cmdbuf_left = - HwInitPacketSize - InitSequence350.size() - (clear_state ? 0xc : 0) - 1; + HwInitPacketSize - (InitSequence350.size() - 2) - (clear_state ? 0xc : 0) - 1; cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); cmdbuf = WriteBody(cmdbuf, 0u); @@ -1743,7 +1759,7 @@ s32 PS4_SYSV_ABI sceGnmSetVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u3 return -1; } - const u32 var = shader_modifier == 0 ? vs_regs[2] : (vs_regs[2] & 0xfcfffc3f | shader_modifier); + const u32 var = shader_modifier == 0 ? vs_regs[2] : (vs_regs[2] & 0xfcfffc3f) | shader_modifier; cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], 0u); // SPI_SHADER_PGM_LO_VS cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x4au, var, vs_regs[3]); // SPI_SHADER_PGM_RSRC1_VS cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x207u, vs_regs[6]); // PA_CL_VS_OUT_CNTL diff --git a/src/core/libraries/videoout/video_out.cpp b/src/core/libraries/videoout/video_out.cpp index d13062cd4..a6c1a7623 100644 --- a/src/core/libraries/videoout/video_out.cpp +++ b/src/core/libraries/videoout/video_out.cpp @@ -185,14 +185,16 @@ s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status) { return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE; } - std::unique_lock lock{port->port_mutex}; - *status = port->flip_status; + { + std::unique_lock lock{port->port_mutex}; + *status = port->flip_status; + } - LOG_INFO(Lib_VideoOut, - "count = {}, processTime = {}, tsc = {}, submitTsc = {}, flipArg = {}, gcQueueNum = " - "{}, flipPendingNum = {}, currentBuffer = {}", - status->count, status->processTime, status->tsc, status->submitTsc, status->flipArg, - status->gcQueueNum, status->flipPendingNum, status->currentBuffer); + LOG_TRACE(Lib_VideoOut, + "count = {}, processTime = {}, tsc = {}, submitTsc = {}, flipArg = {}, gcQueueNum = " + "{}, flipPendingNum = {}, currentBuffer = {}", + status->count, status->processTime, status->tsc, status->submitTsc, status->flipArg, + status->gcQueueNum, status->flipPendingNum, status->currentBuffer); return ORBIS_OK; } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index c70427635..09a9fd629 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -179,6 +179,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { spv::ExecutionModel execution_model{}; ctx.AddCapability(spv::Capability::Image1D); ctx.AddCapability(spv::Capability::Sampled1D); + ctx.AddCapability(spv::Capability::ImageQuery); if (info.uses_fp16) { ctx.AddCapability(spv::Capability::Float16); ctx.AddCapability(spv::Capability::Int16); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index e48b89f4b..994c2847e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -405,6 +405,10 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { image.GetNumberFmt() == AmdGpu::NumberFormat::Float) { return spv::ImageFormat::Rg16f; } + if (image.GetDataFmt() == AmdGpu::DataFormat::Format16_16 && + image.GetNumberFmt() == AmdGpu::NumberFormat::Snorm) { + return spv::ImageFormat::Rg16Snorm; + } if (image.GetDataFmt() == AmdGpu::DataFormat::Format8_8 && image.GetNumberFmt() == AmdGpu::NumberFormat::Unorm) { return spv::ImageFormat::Rg8; diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp index 3faf8665b..276bd9db0 100644 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ b/src/shader_recompiler/frontend/control_flow_graph.cpp @@ -21,8 +21,13 @@ struct Compare { } }; -static IR::Condition MakeCondition(Opcode opcode) { - switch (opcode) { +static IR::Condition MakeCondition(const GcnInst& inst) { + if (inst.IsCmpx()) { + ASSERT(inst.opcode == Opcode::V_CMPX_NE_U32); + return IR::Condition::Execnz; + } + + switch (inst.opcode) { case Opcode::S_CBRANCH_SCC0: return IR::Condition::Scc0; case Opcode::S_CBRANCH_SCC1: @@ -37,7 +42,6 @@ static IR::Condition MakeCondition(Opcode opcode) { return IR::Condition::Execnz; case Opcode::S_AND_SAVEEXEC_B64: case Opcode::S_ANDN2_B64: - case Opcode::V_CMPX_NE_U32: return IR::Condition::Execnz; default: return IR::Condition::True; @@ -94,7 +98,8 @@ void CFG::EmitDivergenceLabels() { // While this instruction does not save EXEC it is often used paired // with SAVEEXEC to mask the threads that didn't pass the condition // of initial branch. - inst.opcode == Opcode::S_ANDN2_B64 || inst.opcode == Opcode::V_CMPX_NE_U32; + (inst.opcode == Opcode::S_ANDN2_B64 && inst.dst[0].field == OperandField::ExecLo) || + inst.opcode == Opcode::V_CMPX_NE_U32; }; const auto is_close_scope = [](const GcnInst& inst) { // Closing an EXEC scope can be either a branch instruction @@ -104,7 +109,8 @@ void CFG::EmitDivergenceLabels() { // Sometimes compiler might insert instructions between the SAVEEXEC and the branch. // Those instructions need to be wrapped in the condition as well so allow branch // as end scope instruction. - inst.opcode == Opcode::S_CBRANCH_EXECZ || inst.opcode == Opcode::S_ANDN2_B64; + inst.opcode == Opcode::S_CBRANCH_EXECZ || + (inst.opcode == Opcode::S_ANDN2_B64 && inst.dst[0].field == OperandField::ExecLo); }; // Since we will be adding new labels, avoid iterating those as well. @@ -171,7 +177,7 @@ void CFG::EmitBlocks() { block->begin_index = GetIndex(start); block->end_index = end_index; block->end_inst = end_inst; - block->cond = MakeCondition(end_inst.opcode); + block->cond = MakeCondition(end_inst); blocks.insert(*block); } } diff --git a/src/shader_recompiler/frontend/instruction.cpp b/src/shader_recompiler/frontend/instruction.cpp index 756d3b4e2..a0c132053 100644 --- a/src/shader_recompiler/frontend/instruction.cpp +++ b/src/shader_recompiler/frontend/instruction.cpp @@ -47,4 +47,18 @@ bool GcnInst::IsConditionalBranch() const { return false; } +bool GcnInst::IsCmpx() const { + if ((opcode >= Opcode::V_CMPX_F_F32 && opcode <= Opcode::V_CMPX_T_F32) || + (opcode >= Opcode::V_CMPX_F_F64 && opcode <= Opcode::V_CMPX_T_F64) || + (opcode >= Opcode::V_CMPSX_F_F32 && opcode <= Opcode::V_CMPSX_T_F32) || + (opcode >= Opcode::V_CMPSX_F_F64 && opcode <= Opcode::V_CMPSX_T_F64) || + (opcode >= Opcode::V_CMPX_F_I32 && opcode <= Opcode::V_CMPX_CLASS_F32) || + (opcode >= Opcode::V_CMPX_F_I64 && opcode <= Opcode::V_CMPX_CLASS_F64) || + (opcode >= Opcode::V_CMPX_F_U32 && opcode <= Opcode::V_CMPX_T_U32) || + (opcode >= Opcode::V_CMPX_F_U64 && opcode <= Opcode::V_CMPX_T_U64)) { + return true; + } + return false; +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/instruction.h b/src/shader_recompiler/frontend/instruction.h index f83f43db5..7c2e0bd1e 100644 --- a/src/shader_recompiler/frontend/instruction.h +++ b/src/shader_recompiler/frontend/instruction.h @@ -203,6 +203,7 @@ struct GcnInst { bool IsUnconditionalBranch() const; bool IsConditionalBranch() const; bool IsFork() const; + bool IsCmpx() const; }; } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 1bbc3c162..0216238ab 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -280,6 +280,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_CMP_U32(ConditionOp::GT, true, false, inst); case Opcode::V_CMP_LT_I32: return V_CMP_U32(ConditionOp::LT, true, false, inst); + case Opcode::V_CMPX_GT_I32: + return V_CMP_U32(ConditionOp::GT, true, true, inst); case Opcode::V_CMPX_LT_I32: return V_CMP_U32(ConditionOp::LT, true, true, inst); case Opcode::V_CMPX_F_U32: diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index efee710db..016ba3660 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -246,10 +246,7 @@ public: return true; } // Samplers with different bindings might still be the same. - const auto old_sharp = - info.ReadUd(existing.sgpr_base, existing.dword_offset); - const auto new_sharp = info.ReadUd(desc.sgpr_base, desc.dword_offset); - return old_sharp == new_sharp; + return existing.GetSsharp(info) == desc.GetSsharp(info); })}; return index; } diff --git a/src/video_core/amdgpu/default_context.cpp b/src/video_core/amdgpu/default_context.cpp new file mode 100644 index 000000000..01229e7b1 --- /dev/null +++ b/src/video_core/amdgpu/default_context.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/types.h" +#include "video_core/amdgpu/liverpool.h" + +#include + +namespace AmdGpu { + +// The following values are taken from fpPS4: +// https://github.com/red-prig/fpPS4/blob/436b43064be4c78229500f3d3c054fc76639247d/chip/pm4_pfp.pas#L410 +// +static constexpr std::array reg_array_default{ + 0x00000000u, 0x80000000u, 0x40004000u, 0xdeadbeefu, 0x00000000u, 0x40004000u, 0x00000000u, + 0x40004000u, 0x00000000u, 0x40004000u, 0x00000000u, 0x40004000u, 0xaa99aaaau, 0x00000000u, + 0xdeadbeefu, 0xdeadbeefu, 0x80000000u, 0x40004000u, 0x00000000u, 0x00000000u, 0x80000000u, + 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, + 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, + 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, + 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, + 0x40004000u, 0x80000000u, 0x40004000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, + 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, + 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, + 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, + 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, + 0x2a00161au, +}; + +void Liverpool::Regs::SetDefaults() { + std::memset(reg_array.data(), 0, reg_array.size() * sizeof(u32)); + + std::memcpy(®_array[ContextRegWordOffset + 0x80], reg_array_default.data(), + reg_array_default.size() * sizeof(u32)); + + // Individual context regs values + reg_array[ContextRegWordOffset + 0x000d] = 0x40004000u; + reg_array[ContextRegWordOffset + 0x01b6] = 0x00000002u; + reg_array[ContextRegWordOffset + 0x0204] = 0x00090000u; + reg_array[ContextRegWordOffset + 0x0205] = 0x00000004u; + reg_array[ContextRegWordOffset + 0x0295] = 0x00000100u; + reg_array[ContextRegWordOffset + 0x0296] = 0x00000080u; + reg_array[ContextRegWordOffset + 0x0297] = 0x00000002u; + reg_array[ContextRegWordOffset + 0x02aa] = 0x00001000u; + reg_array[ContextRegWordOffset + 0x02f7] = 0x00001000u; + reg_array[ContextRegWordOffset + 0x02f9] = 0x00000005u; + reg_array[ContextRegWordOffset + 0x02fa] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x02fb] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x02fc] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x02fd] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x0316] = 0x0000000eu; + reg_array[ContextRegWordOffset + 0x0317] = 0x00000010u; +} + +} // namespace AmdGpu diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index dce2d4b42..89ab7fe43 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -216,6 +216,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span usage_override /*= {}*/) - : info{info_}, image_id{image_id_} { + : image_id{image_id_}, info{info_} { vk::ImageViewUsageCreateInfo usage_ci{}; if (usage_override) { usage_ci.usage = usage_override.value(); diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index 6bb104a66..0bed5adc2 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -342,12 +342,6 @@ TileManager::ScratchBuffer TileManager::AllocBuffer(u32 size, bool is_storage /* .usage = usage, }; -#ifdef __APPLE__ - // Fix for detiler artifacts on macOS - const bool is_large_buffer = true; -#else - const bool is_large_buffer = size > 128_MB; -#endif VmaAllocationCreateInfo alloc_info{ .flags = !is_storage ? VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT @@ -462,7 +456,6 @@ std::optional TileManager::TryDetile(Image& image) { (m > 0 ? params.sizes[m - 1] : 0); } - auto pitch = image.info.pitch; cmdbuf.pushConstants(*detiler->pl_layout, vk::ShaderStageFlagBits::eCompute, 0u, sizeof(params), ¶ms); From 2a737d08004e9429720226ed2069397d643bc802 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sun, 25 Aug 2024 17:07:46 -0300 Subject: [PATCH 039/147] V_NOP | PfpSyncMe | S_CMPK_EQ_U32 (#426) * V_NOP V_NOP = Do nothing * PfpSyncMe PfpSyncMe ensures that all previous commands are completed before continuing. 'break' should be enough for now * S_CMPK_EQ_U32 S_CMPK_EQ_U32 SCC = (D.u == SIMM16) * S_CMPK_EQ_U32 * OperandField::Undefined: * Update translate.cpp remove OperandField::Undefined: * Update image_view.cpp [Render.Vulkan] image_view.cpp:ImageViewInfo:109: Storage image (num_comps = 4) requires swizzling [BGRA] format 43 dst_sel 3886 * Update liverpool_to_vk.cpp * S_CMPK_EQ_U32 * S_CMPK_EQ_U32 --- src/shader_recompiler/frontend/translate/scalar_alu.cpp | 9 +++++++++ src/shader_recompiler/frontend/translate/translate.h | 1 + src/shader_recompiler/frontend/translate/vector_alu.cpp | 2 ++ src/video_core/amdgpu/liverpool.cpp | 3 +++ src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 1 + src/video_core/texture_cache/image_view.cpp | 3 +++ 6 files changed, 19 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 7f7c9d7e0..50a550d44 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -96,6 +96,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) { return S_MAX_U32(inst); case Opcode::S_WQM_B64: break; + case Opcode::S_CMPK_EQ_U32: + return S_CMPK_EQ_U32(inst); default: LogMissingOpcode(inst); } @@ -468,4 +470,11 @@ void Translator::S_MIN_U32(const GcnInst& inst) { ir.SetScc(ir.IEqual(result, src0)); } +void Translator::S_CMPK_EQ_U32(const GcnInst& inst) { + const s32 simm16 = inst.control.sopk.simm; + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{ir.Imm32(simm16)}; + ir.SetScc(ir.IEqual(src0, src1)); +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 009acabdf..6de5e3673 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -98,6 +98,7 @@ public: void S_ADDK_I32(const GcnInst& inst); void S_MAX_U32(const GcnInst& inst); void S_MIN_U32(const GcnInst& inst); + void S_CMPK_EQ_U32(const GcnInst& inst); // Scalar Memory void S_LOAD_DWORD(int num_dwords, const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 0216238ab..99543a207 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -307,6 +307,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_MBCNT_U32_B32(true, inst); case Opcode::V_MBCNT_HI_U32_B32: return V_MBCNT_U32_B32(false, inst); + case Opcode::V_NOP: + return; default: LogMissingOpcode(inst); } diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 89ab7fe43..5b3db603a 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -455,6 +455,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(opcode), count); diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index c42e4f609..025f311d8 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -320,6 +320,7 @@ std::span GetAllFormats() { vk::Format::eR8G8Uint, vk::Format::eR8G8Unorm, vk::Format::eR8Sint, + vk::Format::eR8Snorm, vk::Format::eR8Uint, vk::Format::eR8Unorm, vk::Format::eR8Srgb, diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 9f6ec5c4f..08be6bdc5 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -59,6 +59,9 @@ vk::Format TrySwizzleFormat(vk::Format format, u32 dst_sel) { if (format == vk::Format::eR8G8B8A8Unorm && dst_sel == 0b111100101110) { return vk::Format::eB8G8R8A8Unorm; } + if (format == vk::Format::eR8G8B8A8Srgb && dst_sel == 0b111100101110) { + return vk::Format::eB8G8R8A8Srgb; + } return format; } From 6fd4264b5d9784ea9cf327841bff043c74ca37df Mon Sep 17 00:00:00 2001 From: psucien Date: Sun, 25 Aug 2024 22:24:10 +0200 Subject: [PATCH 040/147] video_core: vk_rasterizer: fix for crash on markers with nullGpu --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index b26c36cef..f22f19eaf 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -243,7 +243,7 @@ void Rasterizer::UpdateDepthStencilState() { } void Rasterizer::ScopeMarkerBegin(const std::string_view& str) { - if (!Config::isMarkersEnabled()) { + if (Config::nullGpu() || !Config::isMarkersEnabled()) { return; } @@ -254,7 +254,7 @@ void Rasterizer::ScopeMarkerBegin(const std::string_view& str) { } void Rasterizer::ScopeMarkerEnd() { - if (!Config::isMarkersEnabled()) { + if (Config::nullGpu() || !Config::isMarkersEnabled()) { return; } @@ -263,7 +263,7 @@ void Rasterizer::ScopeMarkerEnd() { } void Rasterizer::ScopedMarkerInsert(const std::string_view& str) { - if (!Config::isMarkersEnabled()) { + if (Config::nullGpu() || !Config::isMarkersEnabled()) { return; } @@ -274,7 +274,7 @@ void Rasterizer::ScopedMarkerInsert(const std::string_view& str) { } void Rasterizer::Breadcrumb(u64 id) { - if (!instance.HasNvCheckpoints()) { + if (Config::nullGpu() || !instance.HasNvCheckpoints()) { return; } scheduler.CommandBuffer().setCheckpointNV(id); From bcc3a105576c54e16def5719959721d116e03864 Mon Sep 17 00:00:00 2001 From: bigol83 <38129260+bigol83@users.noreply.github.com> Date: Mon, 26 Aug 2024 02:22:07 +0200 Subject: [PATCH 041/147] Add Italian translation (#585) * Update it.ts * Update it.ts --- src/qt_gui/translations/it.ts | 178 +++++++++++++++++----------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 64d123f2e..228d798d0 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + Riguardo shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 è un emulatore sperimentale open source per Playstation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Questo programma non dovrebbe essere utilizzato per riprodurre giochi che non vengono ottenuti legalmente. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Apri Cartella @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Caricamento lista giochi, attendere :3 Cancel - Cancel + Annulla Loading... - Loading... + Caricamento... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Scegli cartella Directory to install games - Directory to install games + Cartella di installazione dei giochi Browse - Browse + Sfoglia Error - Error + Errore The value for location to install games is not valid. - The value for location to install games is not valid. + Il valore del percorso di installazione dei giochi non è valido. @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + Crea scorciatoia Open Game Folder - Open Game Folder + Apri cartella del gioco SFO Viewer - SFO Viewer + Visualizzatore SFO Trophy Viewer - Trophy Viewer + Visualizzatore Trofei Copy info - Copy info + Copia informazioni Copy Name - Copy Name + Copia Nome Copy Serial - Copy Serial + Copia Seriale Copy All - Copy All + Copia Tutto Shortcut creation - Shortcut creation + Creazione scorciatoia Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Scorciatoia creata con successo!\n %1 Error - Error + Errore Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Errore nella creazione della scorciatoia!\n %1 Install PKG - Install PKG + Installa PKG @@ -151,117 +151,117 @@ Open/Add Elf Folder - Open/Add Elf Folder + Apri/Aggiungi cartella Elf Install Packages (PKG) - Install Packages (PKG) + Installa Pacchetti (PKG) Boot Game - Boot Game + Avvia Gioco About shadPS4 - About shadPS4 + Riguardo a shadPS4 Configure... - Configure... + Configura... Install application from a .pkg file - Install application from a .pkg file + Installa applicaazione da un .pkg file Recent Games - Recent Games + Giochi Recenti Exit - Exit + Uscita Exit shadPS4 - Exit shadPS4 + Esci da shadPS4 Exit the application. - Exit the application. + Esci dall'applicazione. Show Game List - Show Game List + Mostra Lista Giochi Game List Refresh - Game List Refresh + Aggiorna Lista Giochi Tiny - Tiny + Minuscolo Small - Small + Piccolo Medium - Medium + Medio Large - Large + Grande List View - List View + Visualizzazione lista Grid View - Grid View + Visualizzazione Griglia Elf Viewer - Elf Viewer + Visualizzatore Elf Game Install Directory - Game Install Directory + Cartella Installazione Giochi Dump Game List - Dump Game List + Scarica Lista Giochi PKG Viewer - PKG Viewer + Visualizzatore PKG Search... - Search... + Cerca... @@ -271,67 +271,67 @@ View - View + Visualizza Game List Icons - Game List Icons + Icone Lista Giochi Game List Mode - Game List Mode + Modalità Lista Giochi Settings - Settings + Impostazioni Utils - Utils + Utilità Themes - Themes + Temi About - About + Info su Dark - Dark + Scuro Light - Light + Chiaro Green - Green + Verde Blue - Blue + Blu Violet - Violet + Viola toolBar - toolBar + barra strumenti @@ -339,14 +339,14 @@ Open Folder - Open Folder + Apri Cartella TrophyViewer - Trophy Viewer + Visualizzatore Trofei Trophy Viewer @@ -355,52 +355,52 @@ Settings - Settings + Impostazioni General - General + Generale System - System + Systema Console Language - Console Language + Lingua della console Emulator Language - Emulator Language + Lingua dell'emulatore Emulator - Emulator + Emulatore Enable Fullscreen - Enable Fullscreen + Abilita Schermo Intero Show Splash - Show Splash + Mostra Schermata Iniziale Is PS4 Pro - Is PS4 Pro + Modalità Ps4Pro Username - Username + Nome Utente @@ -410,57 +410,57 @@ Log Type - Log Type + Tipo di Log Log Filter - Log Filter + Filtro Log Graphics - Graphics + Grafica Graphics Device - Graphics Device + Adattatore grafico Width - Width + Larghezza Height - Height + Altezza Vblank Divider - Vblank Divider + Divisore Vblank Advanced - Advanced + Avanzato Enable Shaders Dumping - Enable Shaders Dumping + Abilita Scaricamento Shader Enable NULL GPU - Enable NULL GPU + Abilita NULL GPU Enable PM4 Dumping - Enable PM4 Dumping + Abilita Scaricamento PM4 @@ -470,22 +470,22 @@ Enable Debug Dumping - Enable Debug Dumping + Abilita Scaricamento Debug Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Abilita Vulkan Validation Layers Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Abilita Vulkan Synchronization Validation Enable RenderDoc Debugging - Enable RenderDoc Debugging + Abilita Debugging RenderDoc - \ No newline at end of file + From 5d7407dc7dfeebba3cda7e04be49269056329a5a Mon Sep 17 00:00:00 2001 From: Yury <27062841+f1amy@users.noreply.github.com> Date: Mon, 26 Aug 2024 05:22:30 +0500 Subject: [PATCH 042/147] Add ru translation (#579) --- src/qt_gui/translations/ru_RU.ts | 184 +++++++++++++++---------------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 556875e17..46a30cdeb 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + О shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 это экспериментальный эмулятор с открытым исходным кодом для PlayStation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Это програмное обеспечение не должно использоваться для запуска игр, которые вы получили нелегально. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Открыть папку @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Загрузка списка игр, пожалуйста подождите :3 Cancel - Cancel + Отмена Loading... - Loading... + Загрузка... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Выберите папку Directory to install games - Directory to install games + Папка для установки игр Browse - Browse + Обзор Error - Error + Ошибка The value for location to install games is not valid. - The value for location to install games is not valid. + Недопустимое значение местоположения для установки игр. @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + Создать ярлык Open Game Folder - Open Game Folder + Открыть папку с игрой SFO Viewer - SFO Viewer + Просмотр SFO Trophy Viewer - Trophy Viewer + Просмотр трофеев Copy info - Copy info + Копировать информацию Copy Name - Copy Name + Копировать имя Copy Serial - Copy Serial + Копировать серийный номер Copy All - Copy All + Копировать все Shortcut creation - Shortcut creation + Создание ярлыка Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Ярлык создан успешно!\n %1 Error - Error + Ошибка Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Ошибка создания ярлыка!\n %1 Install PKG - Install PKG + Установить PKG @@ -151,187 +151,187 @@ Open/Add Elf Folder - Open/Add Elf Folder + Открыть/Добавить папку Elf Install Packages (PKG) - Install Packages (PKG) + Установить пакеты (PKG) Boot Game - Boot Game + Запустить игру About shadPS4 - About shadPS4 + О shadPS4 Configure... - Configure... + Настроить... Install application from a .pkg file - Install application from a .pkg file + Установить приложение из файла .pkg Recent Games - Recent Games + Недавние игры Exit - Exit + Выход Exit shadPS4 - Exit shadPS4 + Выйти из 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 + Elf Game Install Directory - Game Install Directory + Каталог установки игры Dump Game List - Dump Game List + Дамп списка игр PKG Viewer - PKG Viewer + Просмотр PKG Search... - Search... + Поиск... File - File + Файл View - View + Вид Game List Icons - Game List Icons + Размер иконок списка игр Game List Mode - Game List Mode + Вид списка игр Settings - Settings + Настройки Utils - Utils + Утилиты Themes - Themes + Темы About - About + Справка Dark - Dark + Темная Light - Light + Светлая Green - Green + Зеленая Blue - Blue + Синяя Violet - Violet + Фиолетовая toolBar - toolBar + Панель инструментов @@ -339,7 +339,7 @@ Open Folder - Open Folder + Открыть папку @@ -347,7 +347,7 @@ Trophy Viewer - Trophy Viewer + Трофеи @@ -355,137 +355,137 @@ Settings - Settings + Настройки General - General + Общее System - System + Система Console Language - Console Language + Язык консоли Emulator Language - Emulator Language + Язык эмулятора Emulator - Emulator + Эмулятор Enable Fullscreen - Enable Fullscreen + Включить полноэкранный режим Show Splash - Show Splash + Показать заставку Is PS4 Pro - Is PS4 Pro + Режим PS4 Pro Username - Username + Имя пользователя Logger - Logger + Логирование Log Type - Log Type + Тип логов Log Filter - Log Filter + Фильтр логов Graphics - Graphics + Графика Graphics Device - Graphics Device + Графическое устройство Width - Width + Ширина Height - Height + Высота Vblank Divider - Vblank Divider + Разделитель Vblank Advanced - Advanced + Продвинутые Enable Shaders Dumping - Enable Shaders Dumping + Включить дамп шейдеров Enable NULL GPU - Enable NULL GPU + Включить NULL GPU Enable PM4 Dumping - Enable PM4 Dumping + Включить дамп PM4 Debug - Debug + Отладка Enable Debug Dumping - Enable Debug Dumping + Включить отладочные дампы Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Включить слои валидации Vulkan Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Включить валидацию синхронизации Vulkan Enable RenderDoc Debugging - Enable RenderDoc Debugging + Включить отладку RenderDoc - \ No newline at end of file + From fae0c0ae8509d69a1d6b38af93629c34e86b5c89 Mon Sep 17 00:00:00 2001 From: "Daniel R." <47796739+polybiusproxy@users.noreply.github.com> Date: Mon, 26 Aug 2024 03:14:21 +0200 Subject: [PATCH 043/147] core/kernel: Miscellaneous memory fixes (#557) * core/libraries/kernel: Fix inaccurate direct memory size * core/memory: Fix available dmem query on non-free dmem areas * core/kernel: return ENOMEM if memory area size is zero * core/kernel: Fix returns on `sceKernelAvailableDirectMemorySize` * core/memory: Remove unneeded size alignment --- src/core/libraries/kernel/memory_management.cpp | 17 +++++++++++++---- src/core/libraries/kernel/memory_management.h | 2 +- src/core/memory.cpp | 5 +++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index 826d47973..fbc457954 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -75,19 +75,28 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE LOG_WARNING(Kernel_Vmm, "called searchStart = {:#x}, searchEnd = {:#x}, alignment = {:#x}", searchStart, searchEnd, alignment); - if (searchEnd <= searchStart) { + if (physAddrOut == nullptr || sizeOut == nullptr) { return ORBIS_KERNEL_ERROR_EINVAL; } if (searchEnd > SCE_KERNEL_MAIN_DMEM_SIZE) { return ORBIS_KERNEL_ERROR_EINVAL; } + if (searchEnd <= searchStart) { + return ORBIS_KERNEL_ERROR_ENOMEM; + } auto* memory = Core::Memory::Instance(); - PAddr physAddr; - s32 result = - memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, sizeOut); + PAddr physAddr{}; + size_t size{}; + s32 result = memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, &size); + + if (size == 0) { + return ORBIS_KERNEL_ERROR_ENOMEM; + } + *physAddrOut = static_cast(physAddr); + *sizeOut = size; return result; } diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index 378449cc5..c9dd86e18 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -6,7 +6,7 @@ #include "common/bit_field.h" #include "common/types.h" -constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 6_GB; // ~ 6GB +constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 4608_MB; // ~ 4.5GB namespace Libraries::Kernel { diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 552c4039c..d6d5c1e36 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -328,6 +328,11 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si PAddr paddr{}; size_t max_size{}; while (dmem_area != dmem_map.end() && dmem_area->second.GetEnd() <= search_end) { + if (!dmem_area->second.is_free) { + dmem_area++; + continue; + } + if (dmem_area->second.size > max_size) { paddr = dmem_area->second.base; max_size = dmem_area->second.size; From 86870e7c8da8a2e1521141702d3a845e46b0e38a Mon Sep 17 00:00:00 2001 From: greggameplayer Date: Mon, 26 Aug 2024 03:39:38 +0200 Subject: [PATCH 044/147] Implement TBUFFER_STORE_FORMAT_XY --- src/shader_recompiler/frontend/translate/vector_memory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 41eb91234..45440da2f 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -94,6 +94,8 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { case Opcode::TBUFFER_STORE_FORMAT_X: return BUFFER_STORE_FORMAT(1, true, true, inst); + case Opcode::TBUFFER_STORE_FORMAT_XY: + return BUFFER_STORE_FORMAT(2, true, true, inst); case Opcode::TBUFFER_STORE_FORMAT_XYZ: return BUFFER_STORE_FORMAT(3, true, true, inst); From e16aa2a012a9a487828374b231f72a5eb4ba7783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:39:24 +0200 Subject: [PATCH 045/147] Update French tranlations (#592) --- src/qt_gui/translations/fr.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 54100f17d..3f3b38baf 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -16,7 +16,7 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 est un émulateur expérimental de la PlayStation 4. + shadPS4 est un émulateur open-source expérimental de la PlayStation 4. @@ -37,7 +37,7 @@ Loading game list, please wait :3 - Chargement de la liste de jeu, veuillez attendre... + Chargement de la liste de jeu, veuillez patienter... @@ -60,7 +60,7 @@ Directory to install games - Répertoire pour installer les jeux + Répertoire d'installation des jeux @@ -93,12 +93,12 @@ SFO Viewer - Visionneur SFO + Visionneuse SFO Trophy Viewer - Visionneur de trophés + Visionneuse de trophées @@ -151,7 +151,7 @@ Open/Add Elf Folder - Ouvrir/Ajouter un dossier Elf + Ouvrir/Ajouter un dossier ELF @@ -241,7 +241,7 @@ Elf Viewer - Visionneur Elf + Visionneuse ELF @@ -256,7 +256,7 @@ PKG Viewer - Visionneur PKG + Visionneuse PKG @@ -276,12 +276,12 @@ Game List Icons - Icones des jeux + Icônes des jeux Game List Mode - Mode liste + Mode d'affichage @@ -347,7 +347,7 @@ Trophy Viewer - Visionneur de trophés + Visionneuse de trophées @@ -488,4 +488,4 @@ Activer le débogage RenderDoc - + \ No newline at end of file From 7aa8cf992f6d7f7d25953f319e2f3ded97236d16 Mon Sep 17 00:00:00 2001 From: nishinji <107111782+nishinji@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:39:49 +0900 Subject: [PATCH 046/147] Add Japanese translation (#591) --- src/qt_gui/translations/ja_JP.ts | 186 +++++++++++++++---------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index c67352569..88e7554ea 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + shadPS4ɂ‚ @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4́APlayStation 4̎IȃI[v\[XG~[^[łB This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + ̃\tgEFÁA@Iɓ肵ĂȂQ[vC邽߂Ɏgp̂ł͂܂B @@ -29,7 +29,7 @@ Open Folder - Open Folder + tH_J @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Q[XgǂݍݒłB҂ :3 Cancel - Cancel + LZ Loading... - Loading... + ǂݍݒ... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - fBNgI Directory to install games - Directory to install games + Q[CXg[fBNg Browse - Browse + Q Error - Error + G[ The value for location to install games is not valid. - The value for location to install games is not valid. + Q[CXg[ꏊłB @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + V[gJbg쐬 Open Game Folder - Open Game Folder + Q[tH_J SFO Viewer - SFO Viewer + SFOr[[ Trophy Viewer - Trophy Viewer + gtB[r[[ Copy info - Copy info + Rs[ Copy Name - Copy Name + ORs[ Copy Serial - Copy Serial + VARs[ Copy All - Copy All + ׂăRs[ Shortcut creation - Shortcut creation + V[gJbg̍쐬 Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + V[gJbgɍ쐬܂!\n %1 Error - Error + G[ Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + V[gJbg̍쐬Ɏs܂!\n %1 Install PKG - Install PKG + PKGCXg[ @@ -151,187 +151,187 @@ Open/Add Elf Folder - Open/Add Elf Folder + ElftH_J/lj Install Packages (PKG) - Install Packages (PKG) + pbP[WCXg[ (PKG) Boot Game - Boot Game + Q[N About shadPS4 - About shadPS4 + shadPS4ɂ‚ Configure... - Configure... + ݒ... Install application from a .pkg file - Install application from a .pkg file + .pkgt@CAvP[VCXg[ Recent Games - Recent Games + ŋ߂̃Q[ Exit - Exit + I Exit shadPS4 - Exit shadPS4 + shadPS4I Exit the application. - Exit the application. + AvP[VI܂B Show Game List - Show Game List + Q[Xg\ Game List Refresh - Game List Refresh + Q[Xg̍XV Tiny - Tiny + ɏ Small - Small + Medium - Medium + Large - Large + + List View - List View + Xgr[ Grid View - Grid View + Obhr[ Elf Viewer - Elf Viewer + Elfr[ Game Install Directory - Game Install Directory + Q[CXg[fBNg Dump Game List - Dump Game List + Q[Xg_v - PKG Viewer - PKG Viewer + PKGr[A[ Search... - Search... + ... File - File + t@C View - View + \ Game List Icons - Game List Icons + Q[XgACR Game List Mode - Game List Mode + Q[Xg[h Settings - Settings + ݒ Utils - Utils + [eBeB Themes - Themes + e[} About - About + Dark - Dark + _[N Light - Light + Cg Green - Green + O[ Blue - Blue + u[ Violet - Violet + oCIbg toolBar - toolBar + c[o[ @@ -339,7 +339,7 @@ Open Folder - Open Folder + tH_[J @@ -347,7 +347,7 @@ Trophy Viewer - Trophy Viewer + gtB[r[A[ @@ -355,137 +355,137 @@ Settings - Settings + ݒ General - General + System - System + VXe Console Language - Console Language + R\[ Emulator Language - Emulator Language + G~[^[ Emulator - Emulator + G~[^[ Enable Fullscreen - Enable Fullscreen + tXN[Lɂ Show Splash - Show Splash + XvbV\ Is PS4 Pro - Is PS4 Pro + PS4 Pro[h Username - Username + [U[ Logger - Logger + K[ Log Type - Log Type + O^Cv Log Filter - Log Filter + OtB^[ Graphics - Graphics + OtBbNX Graphics Device - Graphics Device + OtBbNXfoCX Width - Width + Height - Height + Vblank Divider - Vblank Divider + VblankfBoC_[ Advanced - Advanced + xȐݒ Enable Shaders Dumping - Enable Shaders Dumping + VF[_[̃_vLɂ Enable NULL GPU - Enable NULL GPU + NULL GPULɂ Enable PM4 Dumping - Enable PM4 Dumping + PM4_vLɂ Debug - Debug + fobO Enable Debug Dumping - Enable Debug Dumping + fobO_vLɂ Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Vulkan؃C[Lɂ Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Vulkan؂Lɂ Enable RenderDoc Debugging - Enable RenderDoc Debugging + RenderDocfobOLɂ - \ No newline at end of file + From 78e24852f8bf0634be6631050e6326fdc8fba875 Mon Sep 17 00:00:00 2001 From: psucien Date: Sun, 25 Aug 2024 23:29:22 +0200 Subject: [PATCH 047/147] libraries: kernel: fix for inaccurate `sceKernelGetProcessTime` --- src/common/native_clock.cpp | 12 ++++++------ src/common/native_clock.h | 6 +++--- src/core/libraries/kernel/time_management.cpp | 4 +++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/common/native_clock.cpp b/src/common/native_clock.cpp index 20d0737a6..c3fa637aa 100644 --- a/src/common/native_clock.cpp +++ b/src/common/native_clock.cpp @@ -18,16 +18,16 @@ NativeClock::NativeClock() us_rdtsc_factor{GetFixedPoint64Factor(std::micro::den, rdtsc_frequency)}, ms_rdtsc_factor{GetFixedPoint64Factor(std::milli::den, rdtsc_frequency)} {} -u64 NativeClock::GetTimeNS() const { - return MultiplyHigh(GetUptime(), ns_rdtsc_factor); +u64 NativeClock::GetTimeNS(u64 base_ptc /*= 0*/) const { + return MultiplyHigh(GetUptime() - base_ptc, ns_rdtsc_factor); } -u64 NativeClock::GetTimeUS() const { - return MultiplyHigh(GetUptime(), us_rdtsc_factor); +u64 NativeClock::GetTimeUS(u64 base_ptc /*= 0*/) const { + return MultiplyHigh(GetUptime() - base_ptc, us_rdtsc_factor); } -u64 NativeClock::GetTimeMS() const { - return MultiplyHigh(GetUptime(), ms_rdtsc_factor); +u64 NativeClock::GetTimeMS(u64 base_ptc /*= 0*/) const { + return MultiplyHigh(GetUptime() - base_ptc, ms_rdtsc_factor); } u64 NativeClock::GetUptime() const { diff --git a/src/common/native_clock.h b/src/common/native_clock.h index 227c8d1ae..b5e389452 100644 --- a/src/common/native_clock.h +++ b/src/common/native_clock.h @@ -16,9 +16,9 @@ public: return rdtsc_frequency; } - u64 GetTimeNS() const; - u64 GetTimeUS() const; - u64 GetTimeMS() const; + u64 GetTimeNS(u64 base_ptc = 0) const; + u64 GetTimeUS(u64 base_ptc = 0) const; + u64 GetTimeMS(u64 base_ptc = 0) const; u64 GetUptime() const; u64 GetProcessTimeUS() const; diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index 214f039b4..d01b0c83f 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -3,6 +3,7 @@ #include #include "common/assert.h" +#include "common/debug.h" #include "common/native_clock.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/time_management.h" @@ -30,7 +31,8 @@ u64 PS4_SYSV_ABI sceKernelGetTscFrequency() { } u64 PS4_SYSV_ABI sceKernelGetProcessTime() { - return clock->GetProcessTimeUS(); + // TODO: this timer should support suspends, so initial ptc needs to be updated on wake up + return clock->GetTimeUS(initial_ptc); } u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter() { From 6e340bcdc14d8cc50c95bccbf8ad20938e3ca5d8 Mon Sep 17 00:00:00 2001 From: nishinji <107111782+nishinji@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:56:11 +0900 Subject: [PATCH 048/147] Fix ja_JP.ts (#594) * Fix ja_JP.ts * a --- src/qt_gui/translations/ja_JP.ts | 186 +++++++++++++++---------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index 88e7554ea..557b0760b 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ About shadPS4 - shadPS4ɂ‚ + shadPS4について @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4́APlayStation 4̎IȃI[v\[XG~[^[łB + shadPS4は、PlayStation 4の実験的なオープンソースエミュレーターです。 This software should not be used to play games you have not legally obtained. - ̃\tgEFÁA@Iɓ肵ĂȂQ[vC邽߂Ɏgp̂ł͂܂B + このソフトウェアは、合法的に入手していないゲームをプレイするために使用するものではありません。 @@ -29,7 +29,7 @@ Open Folder - tH_J + フォルダを開く @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Q[XgǂݍݒłB҂ :3 + ゲームリストを読み込み中です。お待ちください :3 Cancel - LZ + キャンセル Loading... - ǂݍݒ... + 読み込み中... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - fBNgI + shadPS4 - ディレクトリを選択 Directory to install games - Q[CXg[fBNg + ゲームをインストールするディレクトリ Browse - Q + 参照 Error - G[ + エラー The value for location to install games is not valid. - Q[CXg[ꏊłB + ゲームをインストールする場所が無効です。 @@ -83,67 +83,67 @@ Create Shortcut - V[gJbg쐬 + ショートカットを作成 Open Game Folder - Q[tH_J + ゲームフォルダを開く SFO Viewer - SFOr[[ + SFOビューワー Trophy Viewer - gtB[r[[ + トロフィービューワー Copy info - Rs[ + 情報をコピー Copy Name - ORs[ + 名前をコピー Copy Serial - VARs[ + シリアルをコピー Copy All - ׂăRs[ + すべてコピー Shortcut creation - V[gJbg̍쐬 + ショートカットの作成 Shortcut created successfully!\n %1 - V[gJbgɍ쐬܂!\n %1 + ショートカットが正常に作成されました!\n %1 Error - G[ + エラー Error creating shortcut!\n %1 - V[gJbg̍쐬Ɏs܂!\n %1 + ショートカットの作成に失敗しました!\n %1 Install PKG - PKGCXg[ + PKGをインストール @@ -151,187 +151,187 @@ Open/Add Elf Folder - ElftH_J/lj + Elfフォルダを開く/追加する Install Packages (PKG) - pbP[WCXg[ (PKG) + パッケージをインストール (PKG) Boot Game - Q[N + ゲームを起動 About shadPS4 - shadPS4ɂ‚ + shadPS4について Configure... - ݒ... + 設定... Install application from a .pkg file - .pkgt@CAvP[VCXg[ + .pkgファイルからアプリケーションをインストールする Recent Games - ŋ߂̃Q[ + 最近のゲーム Exit - I + 終了 Exit shadPS4 - shadPS4I + shadPS4を終了 Exit the application. - AvP[VI܂B + アプリケーションを終了します。 Show Game List - Q[Xg\ + ゲームリストを表示 Game List Refresh - Q[Xg̍XV + ゲームリストの更新 Tiny - ɏ + 極小 Small - + Medium - + Large - + - List View - Xgr[ + リストビュー Grid View - Obhr[ + グリッドビュー Elf Viewer - Elfr[ + Elfビュワー Game Install Directory - Q[CXg[fBNg + ゲームインストールディレクトリ Dump Game List - Q[Xg_v + ゲームリストをダンプ + PKG Viewer - PKGr[A[ + PKGビューアー Search... - ... + 検索... File - t@C + ファイル View - \ + 表示 Game List Icons - Q[XgACR + ゲームリストアイコン Game List Mode - Q[Xg[h + ゲームリストモード Settings - ݒ + 設定 Utils - [eBeB + ユーティリティ Themes - e[} + テーマ About - + 情報 Dark - _[N + ダーク Light - Cg + ライト Green - O[ + グリーン Blue - u[ + ブルー Violet - oCIbg + バイオレット toolBar - c[o[ + ツールバー @@ -339,7 +339,7 @@ Open Folder - tH_[J + フォルダーを開く @@ -347,7 +347,7 @@ Trophy Viewer - gtB[r[A[ + トロフィービューアー @@ -355,137 +355,137 @@ Settings - ݒ + 設定 General - + 一般 System - VXe + システム Console Language - R\[ + コンソール言語 Emulator Language - G~[^[ + エミュレーター言語 Emulator - G~[^[ + エミュレーター Enable Fullscreen - tXN[Lɂ + フルスクリーンを有効にする Show Splash - XvbV\ + スプラッシュを表示する Is PS4 Pro - PS4 Pro[h + PS4 Proモード Username - [U[ + ユーザー名 Logger - K[ + ロガー Log Type - O^Cv + ログタイプ Log Filter - OtB^[ + ログフィルター Graphics - OtBbNX + グラフィックス Graphics Device - OtBbNXfoCX + グラフィックスデバイス Width - + Height - + 高さ Vblank Divider - VblankfBoC_[ + Vblankディバイダー Advanced - xȐݒ + 高度な設定 Enable Shaders Dumping - VF[_[̃_vLɂ + シェーダーのダンプを有効にする Enable NULL GPU - NULL GPULɂ + NULL GPUを有効にする Enable PM4 Dumping - PM4_vLɂ + PM4ダンプを有効にする Debug - fobO + デバッグ Enable Debug Dumping - fobO_vLɂ + デバッグダンプを有効にする Enable Vulkan Validation Layers - Vulkan؃C[Lɂ + Vulkan検証レイヤーを有効にする Enable Vulkan Synchronization Validation - Vulkan؂Lɂ + Vulkan同期検証を有効にする Enable RenderDoc Debugging - RenderDocfobOLɂ + RenderDocデバッグを有効にする From 0b5616c4930576ba6fdf9bdaae2b89ce66044cc7 Mon Sep 17 00:00:00 2001 From: Marcin Mitura Date: Mon, 26 Aug 2024 12:20:12 +0200 Subject: [PATCH 049/147] Polish localization (#580) Initial polish localization for shadPS4 --- src/qt_gui/translations/pl_PL.ts | 984 ++++++++++++++++--------------- 1 file changed, 493 insertions(+), 491 deletions(-) diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index cad5c5829..7d18f203d 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -1,491 +1,493 @@ - - - - AboutDialog - - - 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. - - - - This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. - - - - 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 - - - - The value for location to install games is not valid. - The value for location to install games is not valid. - - - - GuiContextMenus - - - Create Shortcut - Create Shortcut - - - - Open Game Folder - Open Game Folder - - - - SFO Viewer - SFO Viewer - - - - Trophy Viewer - Trophy Viewer - - - - Copy info - Copy info - - - - Copy Name - Copy Name - - - - Copy Serial - Copy Serial - - - - Copy All - Copy All - - - - Shortcut creation - Shortcut creation - - - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 - - - - Error - Error - - - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 - - - - Install PKG - Install PKG - - - - MainWindow - - - Open/Add Elf Folder - Open/Add Elf Folder - - - - Install Packages (PKG) - Install Packages (PKG) - - - - Boot Game - Boot Game - - - - About shadPS4 - About shadPS4 - - - - Configure... - Configure... - - - - Install application from a .pkg file - Install application from a .pkg file - - - - Recent Games - Recent Games - - - - 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 - - - - 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 - - - - About - About - - - - Dark - Dark - - - - Light - Light - - - - Green - Green - - - - Blue - Blue - - - - Violet - Violet - - - - toolBar - toolBar - - - - PKGViewer - - - Open Folder - Open Folder - - - - TrophyViewer - - - Trophy Viewer - Trophy Viewer - - - - SettingsDialog - - - Settings - Settings - - - - General - General - - - - System - System - - - - Console Language - Console Language - - - - Emulator Language - Emulator Language - - - - Emulator - Emulator - - - - Enable Fullscreen - Enable Fullscreen - - - - Show Splash - Show Splash - - - - Is PS4 Pro - Is PS4 Pro - - - - Username - Username - - - - Logger - Logger - - - - Log Type - Log Type - - - - Log Filter - Log Filter - - - - Graphics - Graphics - - - - 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 PM4 Dumping - Enable PM4 Dumping - - - - 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 - - - \ No newline at end of file + + + + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + To oprogramowanie nie służy do grania w gry pochodzące z nielegalnego źródła. + + + + ElfViewer + + + Open Folder + Otwórz folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Ładowanie listy gier, proszę poczekaj :3 + + + + Cancel + Anuluj + + + + Loading... + Ładowanie... + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Wybierz katalog + + + + Directory to install games + Katalog do instalacji gier + + + + Browse + Przeglądaj + + + + Error + Błąd + + + + The value for location to install games is not valid. + Podana ścieżka do instalacji gier nie jest prawidłowa. + + + + GuiContextMenus + + + Create Shortcut + Utwórz skrót + + + + Open Game Folder + Otwórz katalog gry + + + + SFO Viewer + Menedżer plików SFO + + + + Trophy Viewer + Menedżer trofeów + + + + Copy info + Kopiuj informacje + + + + Copy Name + Kopiuj nazwę + + + + Copy Serial + Kopiuj numer seryjny + + + + Copy All + Kopiuj wszystko + + + + Shortcut creation + Tworzenie skrótu + + + + Shortcut created successfully!\n %1 + Utworzenie skrótu zakończone pomyślnie!\n %1 + + + + Error + Błąd + + + + Error creating shortcut!\n %1 + Utworzenie skrótu zakończone niepowodzeniem!\n %1 + + + + Install PKG + Zainstaluj PKG + + + + MainWindow + + + Open/Add Elf Folder + Otwórz/Dodaj folder Elf + + + + Install Packages (PKG) + Zainstaluj paczkę (PKG) + + + + Boot Game + Uruchom grę + + + + About shadPS4 + O programie + + + + Configure... + Konfiguruj... + + + + Install application from a .pkg file + Zainstaluj aplikacje z pliku .pkg + + + + Recent Games + Ostatnie gry + + + + Exit + Wyjdź + + + + Exit shadPS4 + Wyjdź z shadPS4 + + + + Exit the application. + Wyjdź z aplikacji. + + + + Show Game List + Pokaż listę gier + + + + Game List Refresh + Odśwież listę gier + + + + Tiny + Malutkie + + + + Small + Małe + + + + Medium + Średnie + + + + Large + Wielkie + + + + List View + Widok listy + + + + Grid View + Widok siatki + + + + Elf Viewer + Menedżer plików ELF + + + + Game Install Directory + Katalog zainstalowanej gry + + + + Dump Game List + Zgraj listę gier + + + + PKG Viewer + Menedżer plików PKG + + + + Search... + Szukaj... + + + + File + Plik + + + + View + Widok + + + + Game List Icons + Ikony w widoku listy + + + + Game List Mode + Tryb listy gier + + + + Settings + Ustawienia + + + + Utils + Narzędzia + + + + Themes + Motywy + + + + About + O programie + + + + Dark + Ciemny + + + + Light + Jasny + + + + Green + Zielony + + + + Blue + Niebieski + + + + Violet + Fioletowy + + + + toolBar + Pasek narzędzi + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Menedżer trofeów + + + + SettingsDialog + + + Settings + Ustawienia + + + + General + Ogólne + + + + System + System + + + + Console Language + Język konsoli + + + + Emulator Language + Język emulatora + + + + Emulator + Emulator + + + + Enable Fullscreen + Włącz pełny ekran + + + + Show Splash + Pokaż ekran powitania + + + + Is PS4 Pro + Emulacja PS4 Pro + + + + Username + Nazwa użytkownika + + + + Logger + Dziennik zdarzeń + + + + Log Type + Typ dziennika + + + + Log Filter + Filtrowanie dziennika + + + + Graphics + Grafika + + + + Graphics Device + Karta graficzna + + + + Width + Szerokość + + + + Height + Wysokość + + + + Vblank Divider + Dzielnik pionowego blankingu (Vblank) + + + + Advanced + Zaawansowane + + + + Enable Shaders Dumping + Włącz zgrywanie cieni + + + + Enable NULL GPU + Wyłącz kartę graficzną + + + + Enable PM4 Dumping + Włącz zgrywanie PM4 + + + + Debug + Debugowanie + + + + Enable Debug Dumping + Włącz zgrywanie debugowania + + + + Enable Vulkan Validation Layers + Włącz warstwy walidacji Vulkan + + + + Enable Vulkan Synchronization Validation + Włącz walidację synchronizacji Vulkan + + + + Enable RenderDoc Debugging + Włącz debugowanie RenderDoc + + + From d3b6b17c7571a5627fcaf36335574bcf1fbf7dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3bal=20Mart=C3=AD=20M=C3=A9ndez?= <61116988+elCrimar@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:20:26 +0200 Subject: [PATCH 050/147] Add spanish translation (#583) * Add spanish transalation * Update es_ES.ts --- src/qt_gui/translations/es_ES.ts | 180 +++++++++++++++---------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index eedd4f6d4..1b42b18e6 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + Acerca de shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 es un emulador experimental de código abierto para la PlayStation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Este software no debe utilizarse para jugar juegos que no hayas obtenido legalmente. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Abrir carpeta @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Cargando lista de juegos, por favor espera :3 Cancel - Cancel + Cancelar Loading... - Loading... + Cargando... @@ -55,17 +55,17 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Elegir carpeta Directory to install games - Directory to install games + Carpeta para instalar juegos Browse - Browse + Buscar @@ -75,7 +75,7 @@ The value for location to install games is not valid. - The value for location to install games is not valid. + El valor para la ubicación de instalación de los juegos no es válido. @@ -83,52 +83,52 @@ Create Shortcut - Create Shortcut + Crear acceso directo Open Game Folder - Open Game Folder + Abrir carpeta del juego SFO Viewer - SFO Viewer + Vista SFO Trophy Viewer - Trophy Viewer + Ver trofeos Copy info - Copy info + Copiar información Copy Name - Copy Name + Copiar nombre Copy Serial - Copy Serial + Copiar serial Copy All - Copy All + Copiar todo Shortcut creation - Shortcut creation + Acceso directo creado Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + ¡Acceso directo creado con éxito!\n %1 @@ -138,12 +138,12 @@ Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + ¡Error al crear el acceso directo!\n %1 Install PKG - Install PKG + Instalar PKG @@ -151,187 +151,187 @@ Open/Add Elf Folder - Open/Add Elf Folder + Abrir/Agregar carpeta Elf Install Packages (PKG) - Install Packages (PKG) + Instalar paquetes (PKG) Boot Game - Boot Game + Iniciar juego About shadPS4 - About shadPS4 + Acerca de shadPS4 Configure... - Configure... + Configurar... Install application from a .pkg file - Install application from a .pkg file + Instalar aplicación desde un archivo .pkg Recent Games - Recent Games + Juegos recientes Exit - Exit + Salir Exit shadPS4 - Exit shadPS4 + Salir de shadPS4 Exit the application. - Exit the application. + Salir de la aplicación. Show Game List - Show Game List + Mostrar lista de juegos Game List Refresh - Game List Refresh + Actualizar lista de juegos Tiny - Tiny + Muy pequeño Small - Small + Pequeño Medium - Medium + Mediano Large - Large + Grande List View - List View + Vista de lista Grid View - Grid View + Vista de cuadrícula Elf Viewer - Elf Viewer + Vista Elf Game Install Directory - Game Install Directory + Carpeta de instalación de los juegos Dump Game List - Dump Game List + Volcar lista de juegos PKG Viewer - PKG Viewer + Vista PKG Search... - Search... + Buscar... File - File + Archivo View - View + Vista Game List Icons - Game List Icons + Iconos de los juegos Game List Mode - Game List Mode + Tipo de lista Settings - Settings + Configuraciones Utils - Utils + Utilidades Themes - Themes + Temas About - About + Ayuda Dark - Dark + Oscuro Light - Light + Claro Green - Green + Verde Blue - Blue + Azul Violet - Violet + Violeta toolBar - toolBar + barra de herramientas @@ -339,7 +339,7 @@ Open Folder - Open Folder + Abrir carpeta @@ -347,15 +347,15 @@ Trophy Viewer - Trophy Viewer + Vista de trofeos - + SettingsDialog Settings - Settings + Configuraciones @@ -365,127 +365,127 @@ System - System + Sistema Console Language - Console Language + Idioma de la consola Emulator Language - Emulator Language + Idioma del emulador Emulator - Emulator + Emulador Enable Fullscreen - Enable Fullscreen + Habilitar pantalla completa Show Splash - Show Splash + Mostrar splash Is PS4 Pro - Is PS4 Pro + Modo PS4 Pro Username - Username + Nombre de usuario Logger - Logger + Registro Log Type - Log Type + Tipo de registro Log Filter - Log Filter + Filtro de registro Graphics - Graphics + Gráficos Graphics Device - Graphics Device + Dispositivo gráfico Width - Width + Ancho Height - Height + Alto Vblank Divider - Vblank Divider + Divisor de Vblank Advanced - Advanced + Avanzado Enable Shaders Dumping - Enable Shaders Dumping + Habilitar volcado de shaders Enable NULL GPU - Enable NULL GPU + Habilitar GPU NULL Enable PM4 Dumping - Enable PM4 Dumping + Habilitar volcado de PM4 Debug - Debug + Depuración Enable Debug Dumping - Enable Debug Dumping + Habilitar volcado de depuración Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Habilitar capas de validación de Vulkan Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Habilitar validación de sincronización de Vulkan Enable RenderDoc Debugging - Enable RenderDoc Debugging + Habilitar depuración de RenderDoc - \ No newline at end of file + From 6520f3ca171644f4adf7eee6bb1c9fbc0b577656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pl=C3=ADnio=20Larrubia?= Date: Mon, 26 Aug 2024 07:20:40 -0300 Subject: [PATCH 051/147] feat: add pt_BR translation (#584) * feat: add pt_BR translation - Made by @LeDragoX - Revised by @gabsF * fix: change translation string 'Mostrar Tela Inicial' to 'Mostrar Splash Inicial' --- src/qt_gui/translations/pt_BR.ts | 182 +++++++++++++++---------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index a35f9b1d8..c98d84410 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + Sobre o shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 é um emulador experimental de código-fonte aberto para o PlayStation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Este software não deve ser usado para jogar jogos piratas. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Abrir Pasta @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Carregando lista de jogos, por favor aguarde :3 Cancel - Cancel + Cancelar Loading... - Loading... + Carregando... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Escolha o diretório Directory to install games - Directory to install games + Diretório para instalar jogos Browse - Browse + Procurar Error - Error + Erro The value for location to install games is not valid. - The value for location to install games is not valid. + O diretório da instalação dos jogos não é válido. @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + Criar Atalho Open Game Folder - Open Game Folder + Abrir Pasta do Jogo SFO Viewer - SFO Viewer + Visualizador de SFO Trophy Viewer - Trophy Viewer + Visualizador de Troféu Copy info - Copy info + Copiar informação Copy Name - Copy Name + Copiar Nome Copy Serial - Copy Serial + Copiar Serial Copy All - Copy All + Copiar Tudo Shortcut creation - Shortcut creation + Criação de atalho Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Atalho criado com sucesso!\n %1 Error - Error + Erro Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Erro ao criar atalho!\n %1 Install PKG - Install PKG + Instalar PKG @@ -151,187 +151,187 @@ 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 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 de um arquivo .pkg Recent Games - Recent Games + Jogos Recentes 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 Grade Elf Viewer - Elf Viewer + Visualizador de Elf Game Install Directory - Game Install Directory + Diretório de Instalação de Jogos Dump Game List - Dump Game List + Dumpar Lista de Jogos PKG Viewer - PKG Viewer + Visualizador de PKG Search... - Search... + Pesquisar... File - File + Arquivo View - View + Ver Game List Icons - Game List Icons + Ícones da Lista de Jogos Game List Mode - Game List Mode + Modo de Lista de Jogos Settings - Settings + Configurações Utils - Utils + Utilitários Themes - Themes + Temas About - About + Sobre Dark - Dark + Escuro Light - Light + Claro Green - Green + Verde Blue - Blue + Azul Violet - Violet + Violeta toolBar - toolBar + Barra de Ferramentas @@ -339,7 +339,7 @@ Open Folder - Open Folder + Abrir Pasta @@ -347,7 +347,7 @@ Trophy Viewer - Trophy Viewer + Visualizador de Troféu @@ -355,137 +355,137 @@ Settings - Settings + Configurações General - General + Geral System - System + Sistema Console Language - Console Language + Idioma do Console Emulator Language - Emulator Language + Idioma do Emulador Emulator - Emulator + Emulador Enable Fullscreen - Enable Fullscreen + Ativar Tela Cheia Show Splash - Show Splash + Mostrar Splash Inicial Is PS4 Pro - Is PS4 Pro + Modo PS4 Pro Username - Username + Nome de usuário Logger - Logger + Registro Log Type - Log Type + Tipo de Registro Log Filter - Log Filter + Filtro Graphics - Graphics + Gráficos Graphics Device - Graphics Device + Placa de Vídeo 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 NULA Enable PM4 Dumping - Enable PM4 Dumping + Ativar Dumping de PM4 Debug - Debug + Depuração Enable Debug Dumping - Enable Debug Dumping + Ativar Depuração de Dumping 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 de Sincronização do Vulkan Enable RenderDoc Debugging - Enable RenderDoc Debugging + Ativar Depuração por RenderDoc \ No newline at end of file From cd6b5abccfcf408027a06f48f60f1a9dca53cd80 Mon Sep 17 00:00:00 2001 From: Batu Date: Mon, 26 Aug 2024 13:20:53 +0300 Subject: [PATCH 052/147] added tr language support (#587) --- src/qt_gui/translations/tr_TR.ts | 182 +++++++++++++++---------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index ebb8b9b7c..ea5d0765f 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + shadPS4 Hakkında @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - 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. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Bu yazılım, yasal olarak edinmediğiniz oyunları oynamak için kullanılmamalıdır. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Klasörü Aç @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Oyun listesi yükleniyor, lütfen bekleyin :3 Cancel - Cancel + İptal Loading... - Loading... + Yükleniyor... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Klasörü Seç Directory to install games - Directory to install games + Oyunların yükleneceği klasör Browse - Browse + Gözat Error - Error + Hata The value for location to install games is not valid. - The value for location to install games is not valid. + Oyunların yükleneceği konum için girilen klasör geçerli değil. @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + Kısayol Oluştur Open Game Folder - Open Game Folder + Oyun Klasörünü Aç SFO Viewer - SFO Viewer + SFO Görüntüleyici Trophy Viewer - Trophy Viewer + Kupa Görüntüleyici Copy info - Copy info + Bilgiyi Kopyala Copy Name - Copy Name + Adı Kopyala Copy Serial - Copy Serial + Seri Numarasını Kopyala Copy All - Copy All + Tümünü Kopyala Shortcut creation - Shortcut creation + Kısayol oluşturma Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Kısayol başarıyla oluşturuldu!\n %1 Error - Error + Hata Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Kısayol oluşturulurken hata oluştu!\n %1 Install PKG - Install PKG + PKG Yükle @@ -151,187 +151,187 @@ Open/Add Elf Folder - Open/Add Elf Folder + Elf Klasörünü Aç/Ekle Install Packages (PKG) - Install Packages (PKG) + Paketleri Kur (PKG) Boot Game - Boot Game + Oyunu Başlat About shadPS4 - About shadPS4 + shadPS4 Hakkında Configure... - Configure... + Yapılandır... Install application from a .pkg file - Install application from a .pkg file + .pkg dosyasından uygulama yükle Recent Games - Recent Games + Son Oyunlar Exit - Exit + Çıkış Exit shadPS4 - Exit shadPS4 + shadPS4'ten Çık Exit the application. - Exit the application. + Uygulamadan çık. Show Game List - Show Game List + Oyun Listesini Göster Game List Refresh - Game List Refresh + Oyun Listesini Yenile Tiny - Tiny + Küçük Small - Small + Ufak Medium - Medium + Orta Large - Large + Büyük List View - List View + Liste Görünümü Grid View - Grid View + Izgara Görünümü Elf Viewer - Elf Viewer + Elf Görüntüleyici Game Install Directory - Game Install Directory + Oyun Kurulum Klasörü Dump Game List - Dump Game List + Oyun Listesini Kaydet PKG Viewer - PKG Viewer + PKG Görüntüleyici Search... - Search... + Ara... File - File + Dosya View - View + Görünüm Game List Icons - Game List Icons + Oyun Listesi Simgeleri Game List Mode - Game List Mode + Oyun Listesi Modu Settings - Settings + Ayarlar Utils - Utils + Yardımcı Araçlar Themes - Themes + Temalar About - About + Hakkında Dark - Dark + Koyu Light - Light + Açık Green - Green + Yeşil Blue - Blue + Mavi Violet - Violet + Mor toolBar - toolBar + Araç Çubuğu @@ -339,7 +339,7 @@ Open Folder - Open Folder + Klasörü Aç @@ -347,7 +347,7 @@ Trophy Viewer - Trophy Viewer + Kupa Görüntüleyici @@ -355,137 +355,137 @@ Settings - Settings + Ayarlar General - General + Genel System - System + Sistem Console Language - Console Language + Konsol Dili Emulator Language - Emulator Language + Emülatör Dili Emulator - Emulator + Emülatör Enable Fullscreen - Enable Fullscreen + Tam Ekranı Etkinleştir Show Splash - Show Splash + Başlangıç Ekranını Göster Is PS4 Pro - Is PS4 Pro + PS4 Pro mu Username - Username + Kullanıcı Adı Logger - Logger + Kayıt Tutucu Log Type - Log Type + Kayıt Türü Log Filter - Log Filter + Kayıt Filtresi Graphics - Graphics + Grafikler Graphics Device - Graphics Device + Grafik Cihazı Width - Width + Genişlik Height - Height + Yükseklik Vblank Divider - Vblank Divider + Vblank Bölücü Advanced - Advanced + Gelişmiş Enable Shaders Dumping - Enable Shaders Dumping + Shader Kaydını Etkinleştir Enable NULL GPU - Enable NULL GPU + NULL GPU'yu Etkinleştir Enable PM4 Dumping - Enable PM4 Dumping + PM4 Kaydını Etkinleştir Debug - Debug + Hata Ayıklama Enable Debug Dumping - Enable Debug Dumping + Hata Ayıklama Dökümü Etkinleştir Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Vulkan Doğrulama Katmanlarını Etkinleştir Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Vulkan Senkronizasyon Doğrulamasını Etkinleştir Enable RenderDoc Debugging - Enable RenderDoc Debugging + RenderDoc Hata Ayıklamayı Etkinleştir \ No newline at end of file From aae6e5be73a6c43afdfb4bd8d22da5f47d9e380f Mon Sep 17 00:00:00 2001 From: Lizardy <6063922+lzardy@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:21:20 -0400 Subject: [PATCH 053/147] shader_recompiler: BUFFER_ATOMIC_SWAP Opcode (#566) * shader_recompiler: BUFFER_ATOMIC_SWAP Opcode * clang * follow 32 convention --------- Co-authored-by: microsoftv <6063922+microsoftv@users.noreply.github.com> --- src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp | 2 +- .../backend/spirv/emit_spirv_instructions.h | 2 +- src/shader_recompiler/frontend/translate/vector_memory.cpp | 4 +++- src/shader_recompiler/ir/ir_emitter.cpp | 6 +++--- src/shader_recompiler/ir/ir_emitter.h | 4 ++-- src/shader_recompiler/ir/microinstruction.cpp | 2 +- src/shader_recompiler/ir/opcodes.inc | 4 ++-- src/shader_recompiler/ir/passes/resource_tracking_pass.cpp | 3 ++- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 37e91d3b1..1d553dc56 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -102,7 +102,7 @@ Id EmitBufferAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addres return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicXor); } -Id EmitBufferAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { +Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicExchange); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 0703efb96..dd3d8fae9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -91,7 +91,7 @@ Id EmitBufferAtomicDec32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addres Id EmitBufferAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp); Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp); void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, u32 comp); diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 45440da2f..b88cfc46c 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -111,6 +111,8 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { // Buffer atomic operations case Opcode::BUFFER_ATOMIC_ADD: return BUFFER_ATOMIC(AtomicOp::Add, inst); + case Opcode::BUFFER_ATOMIC_SWAP: + return BUFFER_ATOMIC(AtomicOp::Swap, inst); default: LogMissingOpcode(inst); } @@ -476,7 +478,7 @@ void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) { const IR::Value original_val = [&] { switch (op) { case AtomicOp::Swap: - return ir.BufferAtomicExchange(handle, address, vdata_val, info); + return ir.BufferAtomicSwap(handle, address, vdata_val, info); case AtomicOp::Add: return ir.BufferAtomicIAdd(handle, address, vdata_val, info); case AtomicOp::Smin: diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 0f2fb2f7c..a65e538cf 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -404,9 +404,9 @@ Value IREmitter::BufferAtomicXor(const Value& handle, const Value& address, cons return Inst(Opcode::BufferAtomicXor32, Flags{info}, handle, address, value); } -Value IREmitter::BufferAtomicExchange(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicExchange32, Flags{info}, handle, address, value); +Value IREmitter::BufferAtomicSwap(const Value& handle, const Value& address, const Value& value, + BufferInstInfo info) { + return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value); } void IREmitter::StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 45fa5f216..8f806eb50 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -115,8 +115,8 @@ public: const Value& value, BufferInstInfo info); [[nodiscard]] Value BufferAtomicXor(const Value& handle, const Value& address, const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicExchange(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); + [[nodiscard]] Value BufferAtomicSwap(const Value& handle, const Value& address, + const Value& value, BufferInstInfo info); [[nodiscard]] U32 LaneId(); [[nodiscard]] U32 WarpId(); diff --git a/src/shader_recompiler/ir/microinstruction.cpp b/src/shader_recompiler/ir/microinstruction.cpp index e35be8a7f..a8c8b0737 100644 --- a/src/shader_recompiler/ir/microinstruction.cpp +++ b/src/shader_recompiler/ir/microinstruction.cpp @@ -70,7 +70,7 @@ bool Inst::MayHaveSideEffects() const noexcept { case Opcode::BufferAtomicAnd32: case Opcode::BufferAtomicOr32: case Opcode::BufferAtomicXor32: - case Opcode::BufferAtomicExchange32: + case Opcode::BufferAtomicSwap32: case Opcode::WriteSharedU128: case Opcode::WriteSharedU64: case Opcode::WriteSharedU32: diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 9be89f648..26da00bbd 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -95,7 +95,7 @@ OPCODE(StoreBufferFormatF32x4, Void, Opaq OPCODE(StoreBufferU32, Void, Opaque, Opaque, U32, ) // Buffer atomic operations -OPCODE(BufferAtomicIAdd32, U32, Opaque, Opaque, U32 ) +OPCODE(BufferAtomicIAdd32, U32, Opaque, Opaque, U32 ) OPCODE(BufferAtomicSMin32, U32, Opaque, Opaque, U32 ) OPCODE(BufferAtomicUMin32, U32, Opaque, Opaque, U32 ) OPCODE(BufferAtomicSMax32, U32, Opaque, Opaque, U32 ) @@ -105,7 +105,7 @@ OPCODE(BufferAtomicDec32, U32, Opaq OPCODE(BufferAtomicAnd32, U32, Opaque, Opaque, U32, ) OPCODE(BufferAtomicOr32, U32, Opaque, Opaque, U32, ) OPCODE(BufferAtomicXor32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicExchange32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicSwap32, U32, Opaque, Opaque, U32, ) // Vector utility OPCODE(CompositeConstructU32x2, U32x2, U32, U32, ) diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 016ba3660..ccdcfc6e6 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -32,7 +32,7 @@ bool IsBufferAtomic(const IR::Inst& inst) { case IR::Opcode::BufferAtomicAnd32: case IR::Opcode::BufferAtomicOr32: case IR::Opcode::BufferAtomicXor32: - case IR::Opcode::BufferAtomicExchange32: + case IR::Opcode::BufferAtomicSwap32: return true; default: return false; @@ -136,6 +136,7 @@ IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) { case IR::Opcode::ReadConstBufferU32: case IR::Opcode::StoreBufferU32: case IR::Opcode::BufferAtomicIAdd32: + case IR::Opcode::BufferAtomicSwap32: return IR::Type::U32; default: UNREACHABLE(); From ad8373095a4fda41d61ae3105af280ca4484f382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pl=C3=ADnio=20Larrubia?= Date: Mon, 26 Aug 2024 09:22:11 -0300 Subject: [PATCH 054/147] fix typo in LOG_INFO (#559) fix: file name typo constant_propogation_pass.cpp fix typo from 'symbol_vitrual_addr' variable fix typo in emit_spirv_context_get_set.cpp fix typo from constant_propagation_pass.cpp in CMakeLists fix typo in these some config.cpp functions - setSliderPosition - setSliderPositionGrid - getSliderPosition - getSliderPositionGrid fix typo inside src\core\aerolib\stubs.cpp fix typo in a comment from src\core\file_format\pkg.cpp fix typo inside src\core\file_sys\fs.cpp + fs.h - NeedsCaseInsensiveSearch -> NeedsCaseInsensitiveSearch fix 2 function typos: sceAppContentAddcontEnqueueDownloadByEntitlemetId and sceAppContentAddcontMountByEntitlemetId fix typo on comment inside src\core\libraries\kernel\file_system.cpp fix typo on src\core\libraries\videoout\driver.cpp fix typo in src\core\memory.cpp fix typo from comment in src\qt_gui\game_list_utils.h fix typo in src\video_core\amdgpu\liverpool.h - window_offset_disble to window_offset_disable fix typo from comments in src\video_core\host_shaders\detile_m32x1.comp + detile_m32x2.comp - subotimal -> suboptimal fix typo from comment in src\video_core\renderer_vulkan\renderer_vulkan.cpp - dimentions -> dimensions fix typo from enum in src\common\debug.h and other files - MarkersPallete -> MarkersPalette fix last typo in src\video_core\amdgpu\pm4_opcodes.h - PremableCntl -> PreambleCntl --- CMakeLists.txt | 2 +- scripts/aerolib.inl | 4 +-- scripts/ps4_names.txt | 4 +-- src/common/config.cpp | 8 +++--- src/common/config.h | 8 +++--- src/common/debug.h | 2 +- src/core/aerolib/aerolib.inl | 4 +-- src/core/aerolib/stubs.cpp | 2 +- src/core/file_format/pkg.cpp | 4 +-- src/core/file_sys/fs.cpp | 2 +- src/core/file_sys/fs.h | 4 +-- .../libraries/app_content/app_content.cpp | 8 +++--- src/core/libraries/app_content/app_content.h | 4 +-- src/core/libraries/kernel/file_system.cpp | 2 +- src/core/libraries/videoout/driver.cpp | 2 +- src/core/linker.cpp | 12 ++++---- src/core/memory.cpp | 2 +- src/qt_gui/game_list_utils.h | 2 +- src/qt_gui/main_window.cpp | 28 +++++++++---------- .../spirv/emit_spirv_context_get_set.cpp | 4 +-- ...pass.cpp => constant_propagation_pass.cpp} | 0 src/video_core/amdgpu/liverpool.h | 2 +- src/video_core/amdgpu/pm4_opcodes.h | 2 +- src/video_core/host_shaders/detile_m8x1.comp | 2 +- src/video_core/host_shaders/detile_m8x2.comp | 2 +- .../renderer_vulkan/renderer_vulkan.cpp | 4 +-- .../renderer_vulkan/vk_scheduler.cpp | 2 +- 27 files changed, 61 insertions(+), 61 deletions(-) rename src/shader_recompiler/ir/passes/{constant_propogation_pass.cpp => constant_propagation_pass.cpp} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43ad23e94..decc27b17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -450,7 +450,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/frontend/opcodes.h src/shader_recompiler/frontend/structured_control_flow.cpp src/shader_recompiler/frontend/structured_control_flow.h - src/shader_recompiler/ir/passes/constant_propogation_pass.cpp + src/shader_recompiler/ir/passes/constant_propagation_pass.cpp src/shader_recompiler/ir/passes/dead_code_elimination_pass.cpp src/shader_recompiler/ir/passes/identity_removal_pass.cpp src/shader_recompiler/ir/passes/ir_passes.h diff --git a/scripts/aerolib.inl b/scripts/aerolib.inl index a87c3cc4e..64ee32ea2 100644 --- a/scripts/aerolib.inl +++ b/scripts/aerolib.inl @@ -114108,7 +114108,7 @@ STUB( _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V124RequestCompetitiveResultEE7add_refEv) STUB("efPahl2FufA", _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V35Error8fromJsonERKNS_4Json5ValueE) -STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlemetId) +STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlementId) STUB("efXnxYFN5oE", _ZNSt11range_errorD0Ev) STUB("efcwuDLsAM0", _ZThn120_NK7WebCore16HTMLMediaElement5mutedEv) STUB("efhGArzWdxE", _ZN7bmalloc6IsoTLS15s_didInitializeE) @@ -129493,7 +129493,7 @@ STUB( STUB("kJlYH5uMAWI", sceNetResolverDestroy) STUB("kJmdxo4uM+8", _ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE5_InitERKSt8_Locinfo) -STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlemetId) +STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlementId) STUB( "kJoY9lMIFzY", _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_21AdvancedPlayerProfile2V138MatchCompletionRateDisconnectedMetricsEEEEmmEi) diff --git a/scripts/ps4_names.txt b/scripts/ps4_names.txt index caad2b4df..6f95cc734 100644 --- a/scripts/ps4_names.txt +++ b/scripts/ps4_names.txt @@ -80897,10 +80897,10 @@ sceAppCheckerExecute sceAppCheckerExecuteEx sceAppContentAddcontDelete sceAppContentAddcontEnqueueDownload -sceAppContentAddcontEnqueueDownloadByEntitlemetId +sceAppContentAddcontEnqueueDownloadByEntitlementId sceAppContentAddcontEnqueueDownloadSp sceAppContentAddcontMount -sceAppContentAddcontMountByEntitlemetId +sceAppContentAddcontMountByEntitlementId sceAppContentAddcontShrink sceAppContentAddcontUnmount sceAppContentAppParamGetInt diff --git a/src/common/config.cpp b/src/common/config.cpp index 0659a987f..9f55cbd40 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -215,10 +215,10 @@ void setIconSize(u32 size) { void setIconSizeGrid(u32 size) { m_icon_size_grid = size; } -void setSliderPositon(u32 pos) { +void setSliderPosition(u32 pos) { m_slider_pos = pos; } -void setSliderPositonGrid(u32 pos) { +void setSliderPositionGrid(u32 pos) { m_slider_pos_grid = pos; } void setTableMode(u32 mode) { @@ -271,10 +271,10 @@ u32 getIconSize() { u32 getIconSizeGrid() { return m_icon_size_grid; } -u32 getSliderPositon() { +u32 getSliderPosition() { return m_slider_pos; } -u32 getSliderPositonGrid() { +u32 getSliderPositionGrid() { return m_slider_pos_grid; } u32 getTableMode() { diff --git a/src/common/config.h b/src/common/config.h index 458fa88c3..554515a44 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -61,8 +61,8 @@ void setGameInstallDir(const std::string& dir); void setMainWindowTheme(u32 theme); void setIconSize(u32 size); void setIconSizeGrid(u32 size); -void setSliderPositon(u32 pos); -void setSliderPositonGrid(u32 pos); +void setSliderPosition(u32 pos); +void setSliderPositionGrid(u32 pos); void setTableMode(u32 mode); void setMainWindowWidth(u32 width); void setMainWindowHeight(u32 height); @@ -79,8 +79,8 @@ std::string getGameInstallDir(); u32 getMainWindowTheme(); u32 getIconSize(); u32 getIconSizeGrid(); -u32 getSliderPositon(); -u32 getSliderPositonGrid(); +u32 getSliderPosition(); +u32 getSliderPositionGrid(); u32 getTableMode(); u32 getMainWindowWidth(); u32 getMainWindowHeight(); diff --git a/src/common/debug.h b/src/common/debug.h index 50022a156..596ad7b84 100644 --- a/src/common/debug.h +++ b/src/common/debug.h @@ -29,7 +29,7 @@ static inline bool IsProfilerConnected() { #define TRACK_ALLOC(ptr, size, pool) TracyAllocN(std::bit_cast(ptr), (size), (pool)) #define TRACK_FREE(ptr, pool) TracyFreeN(std::bit_cast(ptr), (pool)) -enum MarkersPallete : int { +enum MarkersPalette : int { EmulatorMarkerColor = 0x264653, RendererMarkerColor = 0x2a9d8f, HleMarkerColor = 0xe9c46a, diff --git a/src/core/aerolib/aerolib.inl b/src/core/aerolib/aerolib.inl index a87c3cc4e..64ee32ea2 100644 --- a/src/core/aerolib/aerolib.inl +++ b/src/core/aerolib/aerolib.inl @@ -114108,7 +114108,7 @@ STUB( _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V124RequestCompetitiveResultEE7add_refEv) STUB("efPahl2FufA", _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V35Error8fromJsonERKNS_4Json5ValueE) -STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlemetId) +STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlementId) STUB("efXnxYFN5oE", _ZNSt11range_errorD0Ev) STUB("efcwuDLsAM0", _ZThn120_NK7WebCore16HTMLMediaElement5mutedEv) STUB("efhGArzWdxE", _ZN7bmalloc6IsoTLS15s_didInitializeE) @@ -129493,7 +129493,7 @@ STUB( STUB("kJlYH5uMAWI", sceNetResolverDestroy) STUB("kJmdxo4uM+8", _ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE5_InitERKSt8_Locinfo) -STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlemetId) +STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlementId) STUB( "kJoY9lMIFzY", _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_21AdvancedPlayerProfile2V138MatchCompletionRateDisconnectedMetricsEEEEmmEi) diff --git a/src/core/aerolib/stubs.cpp b/src/core/aerolib/stubs.cpp index 5e2d55cdc..2634fc46a 100644 --- a/src/core/aerolib/stubs.cpp +++ b/src/core/aerolib/stubs.cpp @@ -13,7 +13,7 @@ namespace Core::AeroLib { // on lookup, setting up the nid_entry they are matched with // // If it runs out of stubs with name information, it will return -// a default implemetnation without function name details +// a default implementation without function name details // Up to 512, larger values lead to more resolve stub slots // and to longer compile / CI times diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp index 336d81019..fe3c34547 100644 --- a/src/core/file_format/pkg.cpp +++ b/src/core/file_format/pkg.cpp @@ -279,8 +279,8 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: } } - // let's deal with the root/uroot enteries here. - // Sometimes it's more than 2 enteries (Tomb Raider Remastered) + // let's deal with the root/uroot entries here. + // Sometimes it's more than 2 entries (Tomb Raider Remastered) const std::string_view flat_path_table(&decompressedData[0x10], 15); if (flat_path_table == "flat_path_table") { uroot_reached = true; diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index 40d8212bb..199e42a04 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -48,7 +48,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view guest_directory) { pos = mount->mount.size() + 1; const auto rel_path = std::string_view(corrected_path).substr(pos); const auto host_path = mount->host_path / rel_path; - if (!NeedsCaseInsensiveSearch) { + if (!NeedsCaseInsensitiveSearch) { return host_path; } diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index b0fb63242..2c55b0513 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -14,9 +14,9 @@ namespace Core::FileSys { class MntPoints { #ifdef _WIN64 - static constexpr bool NeedsCaseInsensiveSearch = false; + static constexpr bool NeedsCaseInsensitiveSearch = false; #else - static constexpr bool NeedsCaseInsensiveSearch = true; + static constexpr bool NeedsCaseInsensitiveSearch = true; #endif public: struct MntPair { diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index 882f99e49..ab3c901aa 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -221,12 +221,12 @@ int PS4_SYSV_ABI Func_C59A36FF8D7C59DA() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlemetId() { +int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlementId() { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlemetId() { +int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlementId() { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); return ORBIS_OK; } @@ -313,9 +313,9 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("xZo2-418Wdo", "libSceAppContentBundle", 1, "libSceAppContent", 1, 1, Func_C59A36FF8D7C59DA); LIB_FUNCTION("kJmjt81mXKQ", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, - sceAppContentAddcontEnqueueDownloadByEntitlemetId); + sceAppContentAddcontEnqueueDownloadByEntitlementId); LIB_FUNCTION("efX3lrPwdKA", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, - sceAppContentAddcontMountByEntitlemetId); + sceAppContentAddcontMountByEntitlementId); LIB_FUNCTION("z9hgjLd1SGA", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, sceAppContentGetAddcontInfoByEntitlementId); LIB_FUNCTION("3wUaDTGmjcQ", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, diff --git a/src/core/libraries/app_content/app_content.h b/src/core/libraries/app_content/app_content.h index ecf69199e..3e6f9b540 100644 --- a/src/core/libraries/app_content/app_content.h +++ b/src/core/libraries/app_content/app_content.h @@ -92,8 +92,8 @@ int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOp int PS4_SYSV_ABI sceAppContentTemporaryDataUnmount(); int PS4_SYSV_ABI sceAppContentGetPftFlag(); int PS4_SYSV_ABI Func_C59A36FF8D7C59DA(); -int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlemetId(); -int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlemetId(); +int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlementId(); +int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlementId(); int PS4_SYSV_ABI sceAppContentGetAddcontInfoByEntitlementId(); int PS4_SYSV_ABI sceAppContentGetAddcontInfoListByIroTag(); int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry(); diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 990b11d69..f7f58df59 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -538,7 +538,7 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { // openOrbis (to check if it is valid out of OpenOrbis LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1, - posix_open); // _open shoudld be equal to open function + posix_open); // _open should be equal to open function } } // namespace Libraries::Kernel diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index dbbcb1def..09e9cef5b 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -96,7 +96,7 @@ int VideoOutDriver::RegisterBuffers(VideoOutPort* port, s32 startIndex, void* co } if (attribute->reserved0 != 0 || attribute->reserved1 != 0) { - LOG_ERROR(Lib_VideoOut, "Invalid reserved memebers"); + LOG_ERROR(Lib_VideoOut, "Invalid reserved members"); return ORBIS_VIDEO_OUT_ERROR_INVALID_VALUE; } if (attribute->aspect_ratio != 0) { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index d4a15825b..6f46fdbe3 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -168,7 +168,7 @@ void Linker::Relocate(Module* module) { auto sym_bind = sym.GetBind(); auto sym_type = sym.GetType(); auto sym_visibility = sym.GetVisibility(); - u64 symbol_vitrual_addr = 0; + u64 symbol_virtual_addr = 0; Loader::SymbolRecord symrec{}; switch (sym_type) { case STT_FUN: @@ -185,12 +185,12 @@ void Linker::Relocate(Module* module) { } if (sym_visibility != 0) { - LOG_INFO(Core_Linker, "symbol visilibity !=0"); + LOG_INFO(Core_Linker, "symbol visibility !=0"); } switch (sym_bind) { case STB_LOCAL: - symbol_vitrual_addr = rel_base_virtual_addr + sym.st_value; + symbol_virtual_addr = rel_base_virtual_addr + sym.st_value; module->SetRelaBit(bit_idx); break; case STB_GLOBAL: @@ -200,14 +200,14 @@ void Linker::Relocate(Module* module) { // Only set the rela bit if the symbol was actually resolved and not stubbed. module->SetRelaBit(bit_idx); } - symbol_vitrual_addr = symrec.virtual_address; + symbol_virtual_addr = symrec.virtual_address; break; } default: ASSERT_MSG(0, "unknown bind type {}", sym_bind); } - rel_is_resolved = (symbol_vitrual_addr != 0); - rel_value = (rel_is_resolved ? symbol_vitrual_addr + addend : 0); + rel_is_resolved = (symbol_virtual_addr != 0); + rel_value = (rel_is_resolved ? symbol_virtual_addr + addend : 0); rel_name = symrec.name; break; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index d6d5c1e36..0feef260b 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -349,7 +349,7 @@ void MemoryManager::NameVirtualRange(VAddr virtual_addr, size_t size, std::strin auto it = FindVMA(virtual_addr); ASSERT_MSG(it->second.Contains(virtual_addr, size), - "Range provided is not fully containted in vma"); + "Range provided is not fully contained in vma"); it->second.name = name; } VAddr MemoryManager::SearchFree(VAddr virtual_addr, size_t size, u32 alignment) { diff --git a/src/qt_gui/game_list_utils.h b/src/qt_gui/game_list_utils.h index 8f934388d..7911ce46f 100644 --- a/src/qt_gui/game_list_utils.h +++ b/src/qt_gui/game_list_utils.h @@ -4,7 +4,7 @@ #pragma once struct GameInfo { - std::string path; // root path of game directory (normaly directory that contains eboot.bin) + std::string path; // root path of game directory (normally directory that contains eboot.bin) std::string icon_path; // path of icon0.png std::string pic_path; // path of pic1.png QImage icon; diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 64a89c6a6..8a4281726 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -116,7 +116,7 @@ void MainWindow::CreateDockWindows() { m_elf_viewer->hide(); m_game_list_frame->show(); m_dock_widget->setWidget(m_game_list_frame.data()); - slider_pos = Config::getSliderPositon(); + slider_pos = Config::getSliderPosition(); ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start; isTableList = true; } else if (table_mode == 1) { // Grid @@ -124,7 +124,7 @@ void MainWindow::CreateDockWindows() { m_elf_viewer->hide(); m_game_grid_frame->show(); m_dock_widget->setWidget(m_game_grid_frame.data()); - slider_pos = Config::getSliderPositonGrid(); + slider_pos = Config::getSliderPositionGrid(); ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start; isTableList = false; } else { @@ -184,12 +184,12 @@ void MainWindow::CreateConnects() { 36 + value; // 36 is the minimum icon size to use due to text disappearing. m_game_list_frame->ResizeIcons(36 + value); Config::setIconSize(36 + value); - Config::setSliderPositon(value); + Config::setSliderPosition(value); } else { m_game_grid_frame->icon_size = 69 + value; m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); Config::setIconSizeGrid(69 + value); - Config::setSliderPositonGrid(value); + Config::setSliderPositionGrid(value); } }); @@ -228,11 +228,11 @@ void MainWindow::CreateConnects() { 36; // 36 is the minimum icon size to use due to text disappearing. ui->sizeSlider->setValue(0); // icone_size - 36 Config::setIconSize(36); - Config::setSliderPositon(0); + Config::setSliderPosition(0); } else { ui->sizeSlider->setValue(0); // icone_size - 36 Config::setIconSizeGrid(69); - Config::setSliderPositonGrid(0); + Config::setSliderPositionGrid(0); } }); @@ -241,11 +241,11 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 64; ui->sizeSlider->setValue(28); Config::setIconSize(64); - Config::setSliderPositon(28); + Config::setSliderPosition(28); } else { ui->sizeSlider->setValue(28); Config::setIconSizeGrid(97); - Config::setSliderPositonGrid(28); + Config::setSliderPositionGrid(28); } }); @@ -254,11 +254,11 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 128; ui->sizeSlider->setValue(92); Config::setIconSize(128); - Config::setSliderPositon(92); + Config::setSliderPosition(92); } else { ui->sizeSlider->setValue(92); Config::setIconSizeGrid(160); - Config::setSliderPositonGrid(91); + Config::setSliderPositionGrid(91); } }); @@ -267,11 +267,11 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 256; ui->sizeSlider->setValue(220); Config::setIconSize(256); - Config::setSliderPositon(220); + Config::setSliderPosition(220); } else { ui->sizeSlider->setValue(220); Config::setIconSizeGrid(256); - Config::setSliderPositonGrid(220); + Config::setSliderPositionGrid(220); } }); // List @@ -286,7 +286,7 @@ void MainWindow::CreateConnects() { } isTableList = true; Config::setTableMode(0); - int slider_pos = Config::getSliderPositon(); + int slider_pos = Config::getSliderPosition(); ui->sizeSlider->setEnabled(true); ui->sizeSlider->setSliderPosition(slider_pos); }); @@ -302,7 +302,7 @@ void MainWindow::CreateConnects() { } isTableList = false; Config::setTableMode(1); - int slider_pos_grid = Config::getSliderPositonGrid(); + int slider_pos_grid = Config::getSliderPositionGrid(); ui->sizeSlider->setEnabled(true); ui->sizeSlider->setSliderPosition(slider_pos_grid); }); 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 0b02f3a37..03fc52ff4 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 @@ -305,7 +305,7 @@ static Id ConvertValue(EmitContext& ctx, Id value, AmdGpu::NumberFormat format, case AmdGpu::NumberFormat::Float: return value; default: - UNREACHABLE_MSG("Unsupported number fromat for conversion: {}", + UNREACHABLE_MSG("Unsupported number format for conversion: {}", magic_enum::enum_name(format)); } } @@ -478,7 +478,7 @@ static Id ConvertF32ToFormat(EmitContext& ctx, Id value, AmdGpu::NumberFormat fo case AmdGpu::NumberFormat::Float: return value; default: - UNREACHABLE_MSG("Unsupported number fromat for conversion: {}", + UNREACHABLE_MSG("Unsupported number format for conversion: {}", magic_enum::enum_name(format)); } } diff --git a/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp similarity index 100% rename from src/shader_recompiler/ir/passes/constant_propogation_pass.cpp rename to src/shader_recompiler/ir/passes/constant_propagation_pass.cpp diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 7b2d47853..2806f3308 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -556,7 +556,7 @@ struct Liverpool { union { BitField<0, 15, s32> top_left_x; BitField<15, 15, s32> top_left_y; - BitField<30, 1, s32> window_offset_disble; + BitField<30, 1, s32> window_offset_disable; }; union { BitField<0, 15, s32> bottom_right_x; diff --git a/src/video_core/amdgpu/pm4_opcodes.h b/src/video_core/amdgpu/pm4_opcodes.h index fba0cbb9f..83c1deaa4 100644 --- a/src/video_core/amdgpu/pm4_opcodes.h +++ b/src/video_core/amdgpu/pm4_opcodes.h @@ -48,7 +48,7 @@ enum class PM4ItOpcode : u32 { EventWriteEop = 0x47, EventWriteEos = 0x48, ReleaseMem = 0x49, - PremableCntl = 0x4A, + PreambleCntl = 0x4A, DmaData = 0x50, ContextRegRmw = 0x51, AcquireMem = 0x58, diff --git a/src/video_core/host_shaders/detile_m8x1.comp b/src/video_core/host_shaders/detile_m8x1.comp index 5ec48fae2..3ca2e64bd 100644 --- a/src/video_core/host_shaders/detile_m8x1.comp +++ b/src/video_core/host_shaders/detile_m8x1.comp @@ -4,7 +4,7 @@ #version 450 #extension GL_KHR_shader_subgroup_shuffle : require -// NOTE: Current subgroup utilization is subotimal on most GPUs, so +// NOTE: Current subgroup utilization is suboptimal on most GPUs, so // it will be nice to process two tiles at once here. layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in; diff --git a/src/video_core/host_shaders/detile_m8x2.comp b/src/video_core/host_shaders/detile_m8x2.comp index d27bc6e2d..ee9b72810 100644 --- a/src/video_core/host_shaders/detile_m8x2.comp +++ b/src/video_core/host_shaders/detile_m8x2.comp @@ -3,7 +3,7 @@ #version 450 -// NOTE: Current subgroup utilization is subotimal on most GPUs, so +// NOTE: Current subgroup utilization is suboptimal on most GPUs, so // it will be nice to process two tiles at once here. layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index c78d629e4..b12708088 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -258,7 +258,7 @@ void RendererVulkan::Present(Frame* frame) { { auto* profiler_ctx = instance.GetProfilerContext(); TracyVkNamedZoneC(profiler_ctx, renderer_gpu_zone, cmdbuf, "Host frame", - MarkersPallete::GpuMarkerColor, profiler_ctx != nullptr); + MarkersPalette::GpuMarkerColor, profiler_ctx != nullptr); const vk::Extent2D extent = swapchain.GetExtent(); const std::array pre_barriers{ @@ -380,7 +380,7 @@ Frame* RendererVulkan::GetRenderFrame() { // Reset fence for next queue submission. device.resetFences(frame->present_done); - // If the window dimentions changed, recreate this frame + // If the window dimensions changed, recreate this frame if (frame->width != window.getWidth() || frame->height != window.getHeight()) { RecreateFrame(frame, window.getWidth(), window.getHeight()); } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index ef0307efd..2f1f13d72 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -145,7 +145,7 @@ void Scheduler::AllocateWorkerCommandBuffers() { auto* profiler_ctx = instance.GetProfilerContext(); if (profiler_ctx) { static const auto scope_loc = - GPU_SCOPE_LOCATION("Guest Frame", MarkersPallete::GpuMarkerColor); + GPU_SCOPE_LOCATION("Guest Frame", MarkersPalette::GpuMarkerColor); new (profiler_scope) tracy::VkCtxScope{profiler_ctx, &scope_loc, current_cmdbuf, true}; } } From 7c7d04133e54818cbfdd589ef1e0ccda447db56c Mon Sep 17 00:00:00 2001 From: Exhigh Date: Mon, 26 Aug 2024 19:34:35 +0400 Subject: [PATCH 055/147] savedata: Handle another missed case in saveDataMount This should potentially fix (CUSA01019) - The Walking Dead: The Complete First Season. --- src/core/libraries/save_data/savedata.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index d62e39f88..a6117cba5 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -506,7 +506,9 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { + ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | + ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { if (std::filesystem::exists(mount_dir)) { return ORBIS_SAVE_DATA_ERROR_EXISTS; } From 3e94b533b6c9840c038e529fb95118ec0dd16c0e Mon Sep 17 00:00:00 2001 From: psucien <168137814+psucien@users.noreply.github.com> Date: Mon, 26 Aug 2024 23:14:22 +0200 Subject: [PATCH 056/147] libraries: kernel: skip for protection op; processing logic fixes (#602) --- .../libraries/kernel/memory_management.cpp | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index fbc457954..05c6e6897 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -254,46 +254,54 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries, int* numEntriesOut, int flags) { + int result = ORBIS_OK; int processed = 0; - int result = 0; - for (int i = 0; i < numEntries; i++) { + for (int i = 0; i < numEntries; i++, processed++) { if (entries == nullptr || entries[i].length == 0 || entries[i].operation > 4) { result = ORBIS_KERNEL_ERROR_EINVAL; break; // break and assign a value to numEntriesOut. } - if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT) { + switch (entries[i].operation) { + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT: { result = sceKernelMapNamedDirectMemory(&entries[i].start, entries[i].length, entries[i].protection, flags, static_cast(entries[i].offset), 0, ""); - LOG_INFO( - Kernel_Vmm, - "BatchMap: entry = {}, operation = {}, len = {:#x}, offset = {:#x}, type = {}, " - "result = {}", - i, entries[i].operation, entries[i].length, entries[i].offset, (u8)entries[i].type, - result); - - if (result == 0) - processed++; - } else if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP) { + LOG_INFO(Kernel_Vmm, + "entry = {}, operation = {}, len = {:#x}, offset = {:#x}, type = {}, " + "result = {}", + i, entries[i].operation, entries[i].length, entries[i].offset, + (u8)entries[i].type, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP: { result = sceKernelMunmap(entries[i].start, entries[i].length); - LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}", - i, entries[i].operation, entries[i].length, result); - - if (result == 0) - processed++; - } else if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_FLEXIBLE) { + LOG_INFO(Kernel_Vmm, "entry = {}, operation = {}, len = {:#x}, result = {}", i, + entries[i].operation, entries[i].length, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_FLEXIBLE: { result = sceKernelMapNamedFlexibleMemory(&entries[i].start, entries[i].length, entries[i].protection, flags, ""); LOG_INFO(Kernel_Vmm, - "BatchMap: entry = {}, operation = {}, len = {:#x}, type = {}, " + "entry = {}, operation = {}, len = {:#x}, type = {}, " "result = {}", i, entries[i].operation, entries[i].length, (u8)entries[i].type, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_TYPE_PROTECT: { + // By now, ignore protection and log it instead + LOG_WARNING(Kernel_Vmm, "entry = {}, operation = {}, len = {:#x}, type = {} " + "is UNSUPPORTED and skipped"); + break; + } + default: { + UNREACHABLE(); + } + } - if (result == 0) - processed++; - } else { - UNREACHABLE_MSG("called: Unimplemented Operation = {}", entries[i].operation); + if (result != ORBIS_OK) { + break; } } if (numEntriesOut != NULL) { // can be zero. do not return an error code. From af4356bfe1c58ee596f29b17ecb79ddb3132596d Mon Sep 17 00:00:00 2001 From: psucien Date: Mon, 26 Aug 2024 23:49:36 +0200 Subject: [PATCH 057/147] shader_recompiler: fix for pattern detection in `TryDisableAnisoLod0` Also fix for forgotten log message params. --- src/core/libraries/kernel/memory_management.cpp | 6 ++++-- src/shader_recompiler/ir/passes/resource_tracking_pass.cpp | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index 05c6e6897..ab6aa3985 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -291,8 +291,10 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn } case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_TYPE_PROTECT: { // By now, ignore protection and log it instead - LOG_WARNING(Kernel_Vmm, "entry = {}, operation = {}, len = {:#x}, type = {} " - "is UNSUPPORTED and skipped"); + LOG_WARNING(Kernel_Vmm, + "entry = {}, operation = {}, len = {:#x}, type = {} " + "is UNSUPPORTED and skipped", + i, entries[i].operation, entries[i].length, (u8)entries[i].type); break; } default: { diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index ccdcfc6e6..ace6a37d8 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -293,10 +293,11 @@ std::pair TryDisableAnisoLod0(const IR::Inst* inst) { return not_found; } - // The bits range is for lods + // The bits range is for lods (note that constants are changed after constant propagation pass) const auto* prod0_arg0 = prod0->Arg(0).InstRecursive(); if (prod0_arg0->GetOpcode() != IR::Opcode::BitFieldUExtract || - prod0_arg0->Arg(1).InstRecursive()->Arg(0).U32() != 0x0008000cu) { + !(prod0_arg0->Arg(1).IsIdentity() && prod0_arg0->Arg(1).U32() == 12) || + !(prod0_arg0->Arg(2).IsIdentity() && prod0_arg0->Arg(2).U32() == 8)) { return not_found; } From 7ecc1d3be0ec13b7370b8c72c80097d2b9c482b1 Mon Sep 17 00:00:00 2001 From: SolidStateDj Date: Mon, 26 Aug 2024 18:27:31 -0400 Subject: [PATCH 058/147] Add a toggle fullscreen button Assigns F11 as the key for toggling fullscreen. --- src/sdl_window.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index eec31c901..ff44e6c30 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -273,6 +273,15 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { case SDLK_SPACE: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; break; + case SDLK_F11: + if (event->type == SDL_EVENT_KEY_DOWN) { + { + SDL_WindowFlags flag = SDL_GetWindowFlags(window); + bool is_fullscreen = flag & SDL_WINDOW_FULLSCREEN; + SDL_SetWindowFullscreen(window, !is_fullscreen); + } + } + break; default: break; } From 2d354a095ae41cf58d72cf8ec88fffcd84dd4d68 Mon Sep 17 00:00:00 2001 From: Vladislav Mikhalin Date: Tue, 27 Aug 2024 09:32:42 +0300 Subject: [PATCH 059/147] AvPlayer: Handle Initialization errors --- .../avplayer/avplayer_data_streamer.h | 3 + .../avplayer/avplayer_file_streamer.cpp | 30 +++++---- .../avplayer/avplayer_file_streamer.h | 4 +- src/core/libraries/avplayer/avplayer_impl.cpp | 9 ++- .../libraries/avplayer/avplayer_source.cpp | 64 +++++++++++-------- src/core/libraries/avplayer/avplayer_source.h | 8 +-- .../libraries/avplayer/avplayer_state.cpp | 37 +++++++---- src/core/libraries/avplayer/avplayer_state.h | 6 +- 8 files changed, 95 insertions(+), 66 deletions(-) diff --git a/src/core/libraries/avplayer/avplayer_data_streamer.h b/src/core/libraries/avplayer/avplayer_data_streamer.h index 04097bb4d..319c88a91 100644 --- a/src/core/libraries/avplayer/avplayer_data_streamer.h +++ b/src/core/libraries/avplayer/avplayer_data_streamer.h @@ -7,6 +7,8 @@ #include "common/types.h" +#include + struct AVIOContext; namespace Libraries::AvPlayer { @@ -14,6 +16,7 @@ namespace Libraries::AvPlayer { class IDataStreamer { public: virtual ~IDataStreamer() = default; + virtual bool Init(std::string_view path) = 0; virtual AVIOContext* GetContext() = 0; }; diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.cpp b/src/core/libraries/avplayer/avplayer_file_streamer.cpp index dc1386a47..c7bd5b5de 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.cpp +++ b/src/core/libraries/avplayer/avplayer_file_streamer.cpp @@ -18,19 +18,8 @@ extern "C" { namespace Libraries::AvPlayer { -AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement, - std::string_view path) - : m_file_replacement(file_replacement) { - const auto ptr = m_file_replacement.object_ptr; - m_fd = m_file_replacement.open(ptr, path.data()); - ASSERT(m_fd >= 0); - m_file_size = m_file_replacement.size(ptr); - // avio_buffer is deallocated in `avio_context_free` - const auto avio_buffer = reinterpret_cast(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE)); - m_avio_context = - avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this, - &AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek); -} +AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement) + : m_file_replacement(file_replacement) {} AvPlayerFileStreamer::~AvPlayerFileStreamer() { if (m_avio_context != nullptr) { @@ -43,6 +32,21 @@ AvPlayerFileStreamer::~AvPlayerFileStreamer() { } } +bool AvPlayerFileStreamer::Init(std::string_view path) { + const auto ptr = m_file_replacement.object_ptr; + m_fd = m_file_replacement.open(ptr, path.data()); + if (m_fd < 0) { + return false; + } + m_file_size = m_file_replacement.size(ptr); + // avio_buffer is deallocated in `avio_context_free` + const auto avio_buffer = reinterpret_cast(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE)); + m_avio_context = + avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this, + &AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek); + return true; +} + s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) { const auto self = reinterpret_cast(opaque); if (self->m_position >= self->m_file_size) { diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.h b/src/core/libraries/avplayer/avplayer_file_streamer.h index 658ce8c1e..034e40dd4 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.h +++ b/src/core/libraries/avplayer/avplayer_file_streamer.h @@ -15,9 +15,11 @@ namespace Libraries::AvPlayer { class AvPlayerFileStreamer : public IDataStreamer { public: - AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement, std::string_view path); + AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement); ~AvPlayerFileStreamer(); + bool Init(std::string_view path) override; + AVIOContext* GetContext() override { return m_avio_context; } diff --git a/src/core/libraries/avplayer/avplayer_impl.cpp b/src/core/libraries/avplayer/avplayer_impl.cpp index cdfff8277..6de7b4c20 100644 --- a/src/core/libraries/avplayer/avplayer_impl.cpp +++ b/src/core/libraries/avplayer/avplayer_impl.cpp @@ -110,7 +110,7 @@ s32 AvPlayer::AddSource(std::string_view path) { if (path.empty()) { return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } - if (AVPLAYER_IS_ERROR(m_state->AddSource(path, GetSourceType(path)))) { + if (!m_state->AddSource(path, GetSourceType(path))) { return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; } return ORBIS_OK; @@ -128,7 +128,7 @@ s32 AvPlayer::GetStreamCount() { } s32 AvPlayer::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { - if (AVPLAYER_IS_ERROR(m_state->GetStreamInfo(stream_index, info))) { + if (!m_state->GetStreamInfo(stream_index, info)) { return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; } return ORBIS_OK; @@ -145,7 +145,10 @@ s32 AvPlayer::EnableStream(u32 stream_index) { } s32 AvPlayer::Start() { - return m_state->Start(); + if (!m_state->Start()) { + return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; + } + return ORBIS_OK; } bool AvPlayer::GetVideoData(SceAvPlayerFrameInfo& video_info) { diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index 2e4ea8aab..99ba2e8b6 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -24,31 +24,39 @@ namespace Libraries::AvPlayer { using namespace Kernel; -AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, std::string_view path, - const SceAvPlayerInitData& init_data, - SceAvPlayerSourceType source_type) - : m_state(state), m_memory_replacement(init_data.memory_replacement), - m_num_output_video_framebuffers( - std::min(std::max(2, init_data.num_output_video_framebuffers), 16)) { - AVFormatContext* context = avformat_alloc_context(); - if (init_data.file_replacement.open != nullptr) { - m_up_data_streamer = - std::make_unique(init_data.file_replacement, path); - context->pb = m_up_data_streamer->GetContext(); - ASSERT(!AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr))); - } else { - const auto mnt = Common::Singleton::Instance(); - const auto filepath = mnt->GetHostPath(path); - ASSERT(!AVPLAYER_IS_ERROR( - avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr))); - } - m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext); -} +AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state) : m_state(state) {} AvPlayerSource::~AvPlayerSource() { Stop(); } +bool AvPlayerSource::Init(const SceAvPlayerInitData& init_data, std::string_view path) { + m_memory_replacement = init_data.memory_replacement, + m_num_output_video_framebuffers = + std::min(std::max(2, init_data.num_output_video_framebuffers), 16); + + AVFormatContext* context = avformat_alloc_context(); + if (init_data.file_replacement.open != nullptr) { + m_up_data_streamer = std::make_unique(init_data.file_replacement); + if (!m_up_data_streamer->Init(path)) { + return false; + } + context->pb = m_up_data_streamer->GetContext(); + if (AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr))) { + return false; + } + } else { + const auto mnt = Common::Singleton::Instance(); + const auto filepath = mnt->GetHostPath(path); + if (AVPLAYER_IS_ERROR( + avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr))) { + return false; + } + } + m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext); + return true; +} + bool AvPlayerSource::FindStreamInfo() { if (m_avformat_context == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not find stream info. NULL context."); @@ -87,16 +95,16 @@ static f32 AVRationalToF32(const AVRational rational) { return f32(rational.num) / rational.den; } -s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { +bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { info = {}; if (m_avformat_context == nullptr || stream_index >= m_avformat_context->nb_streams) { LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info.", stream_index); - return -1; + return false; } const auto p_stream = m_avformat_context->streams[stream_index]; if (p_stream == nullptr || p_stream->codecpar == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. NULL stream.", stream_index); - return -1; + return false; } info.type = CodecTypeToStreamType(p_stream->codecpar->codec_type); info.start_time = p_stream->start_time; @@ -140,9 +148,9 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) break; default: LOG_ERROR(Lib_AvPlayer, "Stream {} type is unknown: {}.", stream_index, info.type); - return -1; + return false; } - return 0; + return true; } bool AvPlayerSource::EnableStream(u32 stream_index) { @@ -215,12 +223,12 @@ std::optional AvPlayerSource::HasFrames(u32 num_frames) { return m_video_packets.Size() > num_frames || m_is_eof; } -s32 AvPlayerSource::Start() { +bool AvPlayerSource::Start() { std::unique_lock lock(m_state_mutex); if (m_audio_codec_context == nullptr && m_video_codec_context == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not start playback. NULL context."); - return -1; + return false; } m_demuxer_thread = std::jthread([this](std::stop_token stop) { this->DemuxerThread(stop); }); m_video_decoder_thread = @@ -228,7 +236,7 @@ s32 AvPlayerSource::Start() { m_audio_decoder_thread = std::jthread([this](std::stop_token stop) { this->AudioDecoderThread(stop); }); m_start_time = std::chrono::high_resolution_clock::now(); - return 0; + return true; } bool AvPlayerSource::Stop() { diff --git a/src/core/libraries/avplayer/avplayer_source.h b/src/core/libraries/avplayer/avplayer_source.h index 7144e7ee4..906122142 100644 --- a/src/core/libraries/avplayer/avplayer_source.h +++ b/src/core/libraries/avplayer/avplayer_source.h @@ -120,17 +120,17 @@ private: class AvPlayerSource { public: - AvPlayerSource(AvPlayerStateCallback& state, std::string_view path, - const SceAvPlayerInitData& init_data, SceAvPlayerSourceType source_type); + AvPlayerSource(AvPlayerStateCallback& state); ~AvPlayerSource(); + bool Init(const SceAvPlayerInitData& init_data, std::string_view path); bool FindStreamInfo(); s32 GetStreamCount(); - s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); + bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); bool EnableStream(u32 stream_index); void SetLooping(bool is_looping); std::optional HasFrames(u32 num_frames); - s32 Start(); + bool Start(); bool Stop(); bool GetAudioData(SceAvPlayerFrameInfo& audio_info); bool GetVideoData(SceAvPlayerFrameInfo& video_info); diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index cb3be2f57..a512063f2 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -24,6 +24,7 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i s32 timedtext_stream_index = -1; const s32 stream_count = self->GetStreamCount(); if (AVPLAYER_IS_ERROR(stream_count)) { + self->Stop(); return; } if (stream_count == 0) { @@ -32,7 +33,10 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i } for (u32 stream_index = 0; stream_index < stream_count; ++stream_index) { SceAvPlayerStreamInfo info{}; - self->GetStreamInfo(stream_index, info); + if (!self->GetStreamInfo(stream_index, info)) { + self->Stop(); + return; + } const std::string_view default_language( reinterpret_cast(self->m_default_language)); @@ -116,23 +120,28 @@ AvPlayerState::~AvPlayerState() { } // Called inside GAME thread -s32 AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) { +bool AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) { if (path.empty()) { LOG_ERROR(Lib_AvPlayer, "File path is empty."); - return -1; + return false; } { std::unique_lock lock(m_source_mutex); if (m_up_source != nullptr) { LOG_ERROR(Lib_AvPlayer, "Only one source is supported."); - return -1; + return false; } - m_up_source = std::make_unique(*this, path, m_init_data, source_type); + m_up_source = std::make_unique(*this); + if (!m_up_source->Init(m_init_data, path)) { + SetState(AvState::Error); + m_up_source.reset(); + return false; + } } AddSourceEvent(); - return 0; + return true; } // Called inside GAME thread @@ -146,25 +155,25 @@ s32 AvPlayerState::GetStreamCount() { } // Called inside GAME thread -s32 AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { +bool AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { std::shared_lock lock(m_source_mutex); if (m_up_source == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. No source.", stream_index); - return -1; + return false; } return m_up_source->GetStreamInfo(stream_index, info); } // Called inside GAME thread -s32 AvPlayerState::Start() { +bool AvPlayerState::Start() { std::shared_lock lock(m_source_mutex); - if (m_up_source == nullptr || m_up_source->Start() < 0) { + if (m_up_source == nullptr || !m_up_source->Start()) { LOG_ERROR(Lib_AvPlayer, "Could not start playback."); - return -1; + return false; } SetState(AvState::Play); OnPlaybackStateChanged(AvState::Play); - return 0; + return true; } void AvPlayerState::AvControllerThread(std::stop_token stop) { @@ -219,10 +228,10 @@ bool AvPlayerState::Stop() { if (m_up_source == nullptr || m_current_state == AvState::Stop) { return false; } - if (!SetState(AvState::Stop)) { + if (!m_up_source->Stop()) { return false; } - if (!m_up_source->Stop()) { + if (!SetState(AvState::Stop)) { return false; } OnPlaybackStateChanged(AvState::Stop); diff --git a/src/core/libraries/avplayer/avplayer_state.h b/src/core/libraries/avplayer/avplayer_state.h index ff80b6cea..a5a3bd689 100644 --- a/src/core/libraries/avplayer/avplayer_state.h +++ b/src/core/libraries/avplayer/avplayer_state.h @@ -24,11 +24,11 @@ public: AvPlayerState(const SceAvPlayerInitData& init_data); ~AvPlayerState(); - s32 AddSource(std::string_view filename, SceAvPlayerSourceType source_type); + bool AddSource(std::string_view filename, SceAvPlayerSourceType source_type); s32 GetStreamCount(); - s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); + bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); bool EnableStream(u32 stream_index); - s32 Start(); + bool Start(); bool Stop(); bool GetAudioData(SceAvPlayerFrameInfo& audio_info); bool GetVideoData(SceAvPlayerFrameInfo& video_info); From 288db9a0cfe2d34041f6f1e5cc0029efa4681de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hage?= <33609333+greggameplayer@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:15:32 +0200 Subject: [PATCH 060/147] Implement V_LSHL_B64 (#608) --- src/shader_recompiler/frontend/translate/translate.h | 1 + .../frontend/translate/vector_alu.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 6de5e3673..cde9e58e7 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -117,6 +117,7 @@ public: void V_AND_B32(const GcnInst& inst); void V_LSHLREV_B32(const GcnInst& inst); void V_LSHL_B32(const GcnInst& inst); + void V_LSHL_B64(const GcnInst& inst); void V_ADD_I32(const GcnInst& inst); void V_ADDC_U32(const GcnInst& inst); void V_CVT_F32_I32(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 99543a207..274dcff11 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -11,6 +11,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_LSHLREV_B32(inst); case Opcode::V_LSHL_B32: return V_LSHL_B32(inst); + case Opcode::V_LSHL_B64: + return V_LSHL_B64(inst); case Opcode::V_BFREV_B32: return V_BFREV_B32(inst); case Opcode::V_BFE_U32: @@ -390,6 +392,16 @@ void Translator::V_LSHL_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); } +void Translator::V_LSHL_B64(const GcnInst& inst) { + const IR::U64 src0{GetSrc64(inst.src[0])}; + const IR::U64 src1{GetSrc64(inst.src[1])}; + const IR::VectorReg dst_reg{inst.dst[0].code}; + ASSERT_MSG(src0.IsImmediate() && src0.U64() == 0 && src1.IsImmediate() && src1.U64() == 0, + "V_LSHL_B64 with non-zero src0 or src1 is not supported"); + ir.SetVectorReg(dst_reg, ir.Imm32(0)); + ir.SetVectorReg(dst_reg + 1, ir.Imm32(0)); +} + void Translator::V_ADD_I32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; From 59b651be07dd83217f63843a1bbfe149ea6f54e1 Mon Sep 17 00:00:00 2001 From: Lizardy <6063922+lzardy@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:53:38 -0400 Subject: [PATCH 061/147] [Libs] Error Codes (#612) * ngs2: all errors w/ official names * ajm errors * gnm errors * random errors * clang * random error * linux --------- Co-authored-by: microsoftv <6063922+microsoftv@users.noreply.github.com> --- CMakeLists.txt | 3 + src/core/libraries/ajm/ajm.cpp | 5 +- src/core/libraries/ajm/ajm_error.h | 28 +++++ src/core/libraries/error_codes.h | 11 -- src/core/libraries/gnmdriver/gnm_error.h | 85 ++++++++++++++ src/core/libraries/gnmdriver/gnmdriver.cpp | 4 +- src/core/libraries/ngs2/ngs2_error.h | 124 +++++++++++++++------ src/core/libraries/ngs2/ngs2_impl.cpp | 4 +- src/core/libraries/random/random.cpp | 6 +- src/core/libraries/random/random.h | 2 +- src/core/libraries/random/random_error.h | 8 ++ 11 files changed, 230 insertions(+), 50 deletions(-) create mode 100644 src/core/libraries/ajm/ajm_error.h create mode 100644 src/core/libraries/gnmdriver/gnm_error.h create mode 100644 src/core/libraries/random/random_error.h diff --git a/CMakeLists.txt b/CMakeLists.txt index decc27b17..6450eaf15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,7 @@ set(AUDIO_LIB src/core/libraries/audio/audioin.cpp set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp src/core/libraries/gnmdriver/gnmdriver.h + src/core/libraries/gnmdriver/gnm_error.h ) set(KERNEL_LIB @@ -233,6 +234,7 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/ngs2/ngs2_error.h src/core/libraries/ngs2/ngs2_impl.cpp src/core/libraries/ngs2/ngs2_impl.h + src/core/libraries/ajm/ajm_error.h ) set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h @@ -268,6 +270,7 @@ set(PLAYGO_LIB src/core/libraries/playgo/playgo.cpp set(RANDOM_LIB src/core/libraries/random/random.cpp src/core/libraries/random/random.h + src/core/libraries/random/random_error.h ) set(USBD_LIB src/core/libraries/usbd/usbd.cpp diff --git a/src/core/libraries/ajm/ajm.cpp b/src/core/libraries/ajm/ajm.cpp index d8d8304ab..441a07f63 100644 --- a/src/core/libraries/ajm/ajm.cpp +++ b/src/core/libraries/ajm/ajm.cpp @@ -1,9 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator +#include "ajm.h" +#include "ajm_error.h" + #include "common/logging/log.h" -#include "core/libraries/ajm/ajm.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/ajm/ajm_error.h b/src/core/libraries/ajm/ajm_error.h new file mode 100644 index 000000000..64129554f --- /dev/null +++ b/src/core/libraries/ajm/ajm_error.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_AJM_ERROR_UNKNOWN = 0x80930001; +constexpr int ORBIS_AJM_ERROR_INVALID_CONTEXT = 0x80930002; +constexpr int ORBIS_AJM_ERROR_INVALID_INSTANCE = 0x80930003; +constexpr int ORBIS_AJM_ERROR_INVALID_BATCH = 0x80930004; +constexpr int ORBIS_AJM_ERROR_INVALID_PARAMETER = 0x80930005; +constexpr int ORBIS_AJM_ERROR_OUT_OF_MEMORY = 0x80930006; +constexpr int ORBIS_AJM_ERROR_OUT_OF_RESOURCES = 0x80930007; +constexpr int ORBIS_AJM_ERROR_CODEC_NOT_SUPPORTED = 0x80930008; +constexpr int ORBIS_AJM_ERROR_CODEC_ALREADY_REGISTERED = 0x80930009; +constexpr int ORBIS_AJM_ERROR_CODEC_NOT_REGISTERED = 0x8093000A; +constexpr int ORBIS_AJM_ERROR_WRONG_REVISION_FLAG = 0x8093000B; +constexpr int ORBIS_AJM_ERROR_FLAG_NOT_SUPPORTED = 0x8093000C; +constexpr int ORBIS_AJM_ERROR_BUSY = 0x8093000D; +constexpr int ORBIS_AJM_ERROR_BAD_PRIORITY = 0x8093000E; +constexpr int ORBIS_AJM_ERROR_IN_PROGRESS = 0x8093000F; +constexpr int ORBIS_AJM_ERROR_RETRY = 0x80930010; +constexpr int ORBIS_AJM_ERROR_MALFORMED_BATCH = 0x80930011; +constexpr int ORBIS_AJM_ERROR_JOB_CREATION = 0x80930012; +constexpr int ORBIS_AJM_ERROR_INVALID_OPCODE = 0x80930013; +constexpr int ORBIS_AJM_ERROR_PRIORITY_VIOLATION = 0x80930014; +constexpr int ORBIS_AJM_ERROR_BUFFER_TOO_BIG = 0x80930015; +constexpr int ORBIS_AJM_ERROR_INVALID_ADDRESS = 0x80930016; +constexpr int ORBIS_AJM_ERROR_CANCELLED = 0x80930017; diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index 123edcee8..1453b0a8f 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -233,9 +233,6 @@ constexpr int SCE_KERNEL_ERROR_ESDKVERSION = 0x80020063; constexpr int SCE_KERNEL_ERROR_ESTART = 0x80020064; constexpr int SCE_KERNEL_ERROR_ESTOP = 0x80020065; -// libSceRandom error codes -constexpr int SCE_RANDOM_ERROR_INVALID = 0x817C0016; - // videoOut constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument constexpr int SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS = 0x80290002; // invalid addresses @@ -249,14 +246,6 @@ constexpr int SCE_VIDEO_OUT_ERROR_SLOT_OCCUPIED = 0x80290010; // slot alr constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full constexpr int SCE_VIDEO_OUT_ERROR_INVALID_OPTION = 0x8029001A; // Invalid buffer attribute option -// GnmDriver -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID = 0x80D17000; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID = 0x80D17001; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR = 0x80D17003; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE = 0x80D17002; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR = 0x80D17004; -constexpr int ORBIS_GNM_ERROR_FAILURE = 0x8EEE00FF; - // Generic constexpr int ORBIS_OK = 0x00000000; constexpr int ORBIS_FAIL = 0xFFFFFFFF; diff --git a/src/core/libraries/gnmdriver/gnm_error.h b/src/core/libraries/gnmdriver/gnm_error.h new file mode 100644 index 000000000..eab684a24 --- /dev/null +++ b/src/core/libraries/gnmdriver/gnm_error.h @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_GNM_ERROR_SUBMISSION_FAILED_INVALID_ARGUMENT = 0x80D11000; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_NOT_ENOUGH_RESOURCES = 0x80D11001; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_INVALID_COMMAND_BUFFER = 0x80D11080; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_INVALID_QUEUE_FULL = 0x80D11081; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_REQUEST_FAILED = 0x80D11082; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_FAILED_INTERNAL_ERROR = 0x80D110FF; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING = 0x80D12000; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_RWBUFFER_ROTYPE = 0x80D12001; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_BLENDING = 0x80D12002; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_DRAW_CU_MASK = 0x80D12003; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_MRT_SETUP = 0x80D12004; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_DEPTH_RT_SETUP = 0x80D12005; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_PS_AND_MRT_FORMAT = 0x80D1200F; +constexpr int ORBIS_GNM_ERROR_VALIDATION_ERROR = 0x80D13000; +constexpr int ORBIS_GNM_ERROR_VALIDATION_VSHARP = 0x80D13001; +constexpr int ORBIS_GNM_ERROR_VALIDATION_TSHARP = 0x80D13002; +constexpr int ORBIS_GNM_ERROR_VALIDATION_RESOURCE = 0x80D13003; +constexpr int ORBIS_GNM_ERROR_VALIDATION_TABLE_MEMORY = 0x80D13004; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WRITE_EVENT_OP = 0x80D13005; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INDEX_BUFFER = 0x80D13006; +constexpr int ORBIS_GNM_ERROR_VALIDATION_TESS_FACTOR_BUFFER = 0x80D13007; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SCRATCH_RING = 0x80D13008; +constexpr int ORBIS_GNM_ERROR_VALIDATION_PRIMITIVE_TYPE = 0x80D13009; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INDEX_SIZE = 0x80D1300A; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INLINE_DRAW_SIZE = 0x80D1300B; +constexpr int ORBIS_GNM_ERROR_VALIDATION_NUM_INPUT_PATCHES = 0x80D1300C; +constexpr int ORBIS_GNM_ERROR_VALIDATION_GS_MODE = 0x80D1300D; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SHADER_ADDRESS = 0x80D1300E; +constexpr int ORBIS_GNM_ERROR_VALIDATION_BORDER_COLOR_TABLE = 0x80D1300F; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SSHARP = 0x80D13010; +constexpr int ORBIS_GNM_ERROR_VALIDATION_DISPATCH_DRAW = 0x80D13011; +constexpr int ORBIS_GNM_ERROR_VALIDATION_ACTIVE_SHADER_STAGE = 0x80D13012; +constexpr int ORBIS_GNM_ERROR_VALIDATION_DCB = 0x80D13013; +constexpr int ORBIS_GNM_ERROR_VALIDATION_MISMATCH_SHADER_STAGE = 0x80D13014; +constexpr int ORBIS_GNM_ERROR_VALIDATION_MRT_SETUP = 0x80D13015; +constexpr int ORBIS_GNM_ERROR_VALIDATION_BAD_OP_CODE = 0x80D13016; +constexpr int ORBIS_GNM_ERROR_VALIDATION_DEPTH_RT_SETUP = 0x80D13017; +constexpr int ORBIS_GNM_ERROR_VALIDATION_NUM_INSTANCES = 0x80D13018; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SRT = 0x80D13019; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INVALID_ARGUMENT = 0x80D13FFD; +constexpr int ORBIS_GNM_ERROR_VALIDATION_FAILED_INTERNAL_ERROR = 0x80D13FFE; +constexpr int ORBIS_GNM_ERROR_VALIDATION_NOT_ENABLED = 0x80D13FFF; +constexpr int ORBIS_GNM_ERROR_CAPTURE_FILE_IO = 0x80D15000; +constexpr int ORBIS_GNM_ERROR_CAPTURE_RAZOR_NOT_LOADED = 0x80D15001; +constexpr int ORBIS_GNM_ERROR_CAPTURE_NOTHING_TO_CAPTURE = 0x80D15002; +constexpr int ORBIS_GNM_ERROR_CAPTURE_FAILED_INTERNAL = 0x80D1500F; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID = 0x80D17000; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID = 0x80D17001; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE = 0x80D17002; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR = 0x80D17003; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR = 0x80D17004; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_PRIORITY = 0x80D17005; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INTERNAL = 0x80D170FF; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_ARGUMENT = 0x80D19000; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_SHADER = 0x80D19001; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_STALE_HANDLE = 0x80D19002; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_FULL = 0x80D19003; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_NOT_PERMITTED = 0x80D19004; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OUTPUT_ARGUMENT_IS_NULL = 0x80D19005; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OWNER_HANDLE_INVALID = 0x80D19006; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_HANDLE_INVALID = 0x80D19007; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_TYPE_INVALID = 0x80D19008; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_GDS_RESOURCE_TYPE_INVALID = 0x80D19009; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_SIZE_INVALID = 0x80D1900A; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_ADDRESS_IS_NULL = 0x80D1900B; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_GDS_OFFSET_INVALID = 0x80D1900C; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_NAME_IS_NULL = 0x80D1900D; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OWNER_NAME_IS_NULL = 0x80D1900E; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_FIND_CALLBACK_IS_NULL = 0x80D1900F; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_IS_NOT_SHADER = 0x80D19010; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_USER_MEMORY_PARAM_IS_NULL = 0x80D19011; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_USER_MEMORY_PARAM_NOT_ALIGNED = 0x80D19012; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_NAME_LENGTH_PARAM = 0x80D19013; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_SIZE_PARAM = 0x80D19014; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_NUM_RESOURCES_PARAM = 0x80D19015; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INTERNAL = 0x80D19FFF; +constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_PARAMETER_NULL = 0x80D1B000; +constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_FAILED = 0x80D1B001; +constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_PARAMETER_INVALID = 0x80D1B002; +constexpr int ORBIS_GNM_ERROR_FAILURE = 0x8EEE00FF; diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 95821a03b..6b8b070b8 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "gnm_error.h" +#include "gnmdriver.h" + #include "common/assert.h" #include "common/config.h" #include "common/debug.h" @@ -9,7 +12,6 @@ #include "common/slot_vector.h" #include "core/address_space.h" #include "core/libraries/error_codes.h" -#include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/libs.h" #include "core/libraries/videoout/video_out.h" diff --git a/src/core/libraries/ngs2/ngs2_error.h b/src/core/libraries/ngs2/ngs2_error.h index 254ae26e6..2773168e2 100644 --- a/src/core/libraries/ngs2/ngs2_error.h +++ b/src/core/libraries/ngs2/ngs2_error.h @@ -3,54 +3,116 @@ #pragma once -constexpr int ORBIS_NGS2_ERROR_INVALID_PARAMETERS = 0x804A0001; -constexpr int ORBIS_NGS2_ERROR_INVALID_MAXIMUM_GRAIN_SAMPLES = 0x804A0050; -constexpr int ORBIS_NGS2_ERROR_INVALID_GRAIN_SAMPLES = 0x804A0051; -constexpr int ORBIS_NGS2_ERROR_INVALID_CHANNELS = 0x804A0052; -constexpr int ORBIS_NGS2_ERROR_INVALD_ADDRESS = 0x804A0053; -constexpr int ORBIS_NGS2_ERROR_INVALD_SIZE = 0x804A0054; +constexpr int ORBIS_NGS2_ERROR_FAIL = 0x804A0001; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES = 0x804A0050; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES = 0x804A0051; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_CHANNELS = 0x804A0052; +constexpr int ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS = 0x804A0053; +constexpr int ORBIS_NGS2_ERROR_INVALID_OUT_SIZE = 0x804A0054; +constexpr int ORBIS_NGS2_ERROR_INVALID_OPTION_ADDRESS = 0x804A0080; constexpr int ORBIS_NGS2_ERROR_INVALID_OPTION_SIZE = 0x804A0081; -constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_OPTION_MAX_MATRICES = 0x804A0100; -constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_OPTION_MAX_PORTS = 0x804A0101; -constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_OPTION_MAX_INPUT_DELAY_BLOCKS = 0x804A0102; -constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_LEVELS = 0x804A0150; -constexpr int ORBIS_NGS2_ERROR_SAMPLER_WAVEFORM_TERMINATED = 0x804A0151; -constexpr int ORBIS_NGS2_ERROR_INVALID_ENVELOPE_POINTS = 0x804A0152; +constexpr int ORBIS_NGS2_ERROR_INVALID_OPTION_FLAG = 0x804A0082; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_MATRICES = 0x804A0100; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_PORTS = 0x804A0101; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_INPUT_DELAY_BLOCKS = 0x804A0102; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_VOICES = 0x804A0103; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CHANNELS = 0x804A0104; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CHANNEL_WORKS = 0x804A0105; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_WAVEFORM_BLOCKS = 0x804A0106; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_ENVELOPE_POINTS = 0x804A0107; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_FILTERS = 0x804A0108; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CODEC_CACHES = 0x804A0109; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_ATRAC9_DECODERS = 0x804A010A; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_ATRAC9_CHANNEL_WORKS = 0x804A010B; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_INPUTS = 0x804A010C; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_MATRIX_LEVELS = 0x804A0150; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_WAVEFORM_BLOCKS = 0x804A0151; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_ENVELOPE_POINTS = 0x804A0152; constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_LEVEL_ADDRESS = 0x804A0153; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_BLOCK_ADDRESS = 0x804A0154; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_BLOCK_ADDRESS = 0x804A0154; constexpr int ORBIS_NGS2_ERROR_INVALID_ENVELOPE_POINT_ADDRESS = 0x804A0155; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_PEAKMETER_BLOCKS = 0x804A0156; constexpr int ORBIS_NGS2_ERROR_INVALID_HANDLE = 0x804A0200; constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLE_RATE = 0x804A0201; +constexpr int ORBIS_NGS2_ERROR_INVALID_REPORT_TYPE = 0x804A0202; +constexpr int ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLER = 0x804A0203; constexpr int ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE = 0x804A0204; +constexpr int ORBIS_NGS2_ERROR_EMPTY_REPORT_HANDLE = 0x804A0205; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_INFO = 0x804A0206; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ADDRESS = 0x804A0207; -constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ALIGNMENT = 0x804A0208; +constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ALIGN = 0x804A0208; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE = 0x804A0209; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ALLOCATOR = 0x804A020A; -constexpr int ORBIS_NGS2_ERROR_BUFFER_VERIFY_FAILED = 0x804A020B; -constexpr int ORBIS_NGS2_ERROR_MODULE_PLAYER_DATA_EMPTY = 0x804A020C; +constexpr int ORBIS_NGS2_ERROR_BUFFER_BROKEN = 0x804A020B; +constexpr int ORBIS_NGS2_ERROR_EMPTY_BUFFER = 0x804A020C; constexpr int ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE = 0x804A0230; constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_ID = 0x804A0260; constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE = 0x804A0261; constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE = 0x804A0300; +constexpr int ORBIS_NGS2_ERROR_UNINIT_VOICE = 0x804A0301; constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_INDEX = 0x804A0302; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_EVENT = 0x804A0303; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_PORT_INDEX = 0x804A0304; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_INPUT_OR_RACK_OCCUPIED = 0x804A0305; -constexpr int ORBIS_NGS2_ERROR_INVALID_CONTROL_ID = 0x804A0308; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_PARAMETER = 0x804A0309; -constexpr int ORBIS_NGS2_ERROR_INVALID_PARAMETER_SIZE = 0x804A030A; +constexpr int ORBIS_NGS2_ERROR_INVALID_EVENT_TYPE = 0x804A0303; +constexpr int ORBIS_NGS2_ERROR_INVALID_PORT_INDEX = 0x804A0304; +constexpr int ORBIS_NGS2_ERROR_INVALID_PATCH = 0x804A0305; +constexpr int ORBIS_NGS2_ERROR_EMPTY_CHANNEL_WORK = 0x804A0306; +constexpr int ORBIS_NGS2_ERROR_EMPTY_CODEC_DECODER = 0x804A0307; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_ID = 0x804A0308; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_ADDRESS = 0x804A0309; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_SIZE = 0x804A030A; constexpr int ORBIS_NGS2_ERROR_DETECTED_CIRCULAR_VOICE_CONTROL = 0x804A030B; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_DATA = 0x804A0400; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_FORMAT = 0x804A0401; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_TYPE_NO_ATRAC9_DECODERS = 0x804A0402; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_ATRAC9_CONFIG_DATA = 0x804A0403; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_SAMPLE_RATE = 0x804A0404; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_FRAME = 0x804A0405; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_ADDRESS = 0x804A0406; +constexpr int ORBIS_NGS2_ERROR_UNABLE_CALLBACK = 0x804A030C; +constexpr int ORBIS_NGS2_ERROR_INVALID_CALLBACK_FLAG = 0x804A030D; +constexpr int ORBIS_NGS2_ERROR_INVALID_CALLBACK_HANDLER = 0x804A030E; +constexpr int ORBIS_NGS2_ERROR_INVALID_OPERATION = 0x804A030F; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_FORMAT = 0x804A0400; +constexpr int ORBIS_NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT = 0x804A0401; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_TYPE = 0x804A0402; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_CONFIG = 0x804A0403; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_SAMPLE_RATE = 0x804A0404; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_FRAME = 0x804A0405; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_ADDRESS = 0x804A0406; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_SIZE = 0x804A0407; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_DATA = 0x804A0408; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_BLOCK_NUM_REPEATS = 0x804A0409; constexpr int ORBIS_NGS2_ERROR_INVALID_ENVELOPE_CURVE = 0x804A0500; +constexpr int ORBIS_NGS2_ERROR_INVALID_PEAKMETER_FLAG = 0x804A0510; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CHORUS_PHASES = 0x804A0520; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_CHORUS_PHASES = 0x804A0521; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_DELAY_LENGTH = 0x804A0530; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_DELAY_TAPS = 0x804A0531; +constexpr int ORBIS_NGS2_ERROR_INVALID_DELAY_TYPE = 0x804A0532; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_DELAY_TAPS = 0x804A0533; +constexpr int ORBIS_NGS2_ERROR_INVALID_DELAY_TAP_INFO = 0x804A0534; +constexpr int ORBIS_NGS2_ERROR_INVALID_PITCH_SHIFT_QUALITY = 0x804A0540; constexpr int ORBIS_NGS2_ERROR_INVALID_FILTER_INDEX = 0x804A0600; constexpr int ORBIS_NGS2_ERROR_INVALID_FILTER_TYPE = 0x804A0601; constexpr int ORBIS_NGS2_ERROR_INVALID_FILTER_LOCATION = 0x804A0602; -constexpr int ORBIS_NGS2_ERROR_INVALID_LFE_CUT_OFF_FREQUENCY = 0x804A0603; -constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_INDEX_OR_TYPE = 0x804A0700; \ No newline at end of file +constexpr int ORBIS_NGS2_ERROR_INVALID_LFE_FC = 0x804A0603; +constexpr int ORBIS_NGS2_ERROR_INVALID_USER_FX_PARAM_SIZE = 0x804A0650; +constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_INDEX = 0x804A0700; +constexpr int ORBIS_NGS2_ERROR_CODEC_UNKNOWN_WAVEFORM = 0x804A0800; +constexpr int ORBIS_NGS2_ERROR_CODEC_EMPTY_INSTANCE = 0x804A0801; +constexpr int ORBIS_NGS2_ERROR_CODEC_EMPTY_CHANNEL = 0x804A0802; +constexpr int ORBIS_NGS2_ERROR_CODEC_SETUP_FAIL = 0x804A0803; +constexpr int ORBIS_NGS2_ERROR_CODEC_RESET_FAIL = 0x804A0804; +constexpr int ORBIS_NGS2_ERROR_CODEC_DECODE_FAIL = 0x804A0805; +constexpr int ORBIS_NGS2_ERROR_INVALID_REVERB_SIZE = 0x804A0900; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_UNIT_ANGLE = 0x804A0910; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_SPEAKER = 0x804A0911; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_MATRIX_FORMAT = 0x804A0912; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_WORK = 0x804A0913; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_PARAM = 0x804A0914; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_DISTANCE = 0x804A0920; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_LISTENER_ADDRESS = 0x804A0921; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_SOURCE_ADDRESS = 0x804A0922; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_FLAG = 0x804A0923; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_CONE = 0x804A0924; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_ID = 0x804A0A00; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_MODULES = 0x804A0A01; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_MODULE_BUFFERS = 0x804A0A02; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_BUFFER_ID = 0x804A0A03; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_STATE_OFFSET = 0x804A0A04; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_STATE_SIZE = 0x804A0A05; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_STATE_SIZE = 0x804A0A06; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_INDEX = 0x804A0B00; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_INFO_SIZE = 0x804A0B01; \ No newline at end of file diff --git a/src/core/libraries/ngs2/ngs2_impl.cpp b/src/core/libraries/ngs2/ngs2_impl.cpp index 50c62f5e4..793435d83 100644 --- a/src/core/libraries/ngs2/ngs2_impl.cpp +++ b/src/core/libraries/ngs2/ngs2_impl.cpp @@ -138,13 +138,13 @@ s32 Ngs2::SystemSetupCore(StackBuffer* buf, SystemOptions* options, Ngs2Handle** // Validate maxGrainSamples if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 0x3F) != 0) { LOG_ERROR(Lib_Ngs2, "Invalid system option (maxGrainSamples={},x64)", maxGrainSamples); - return ORBIS_NGS2_ERROR_INVALID_MAXIMUM_GRAIN_SAMPLES; + return ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES; } // Validate numGrainSamples if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 0x3F) != 0) { LOG_ERROR(Lib_Ngs2, "Invalid system option (numGrainSamples={},x64)", numGrainSamples); - return ORBIS_NGS2_ERROR_INVALID_GRAIN_SAMPLES; + return ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES; } // Validate sampleRate diff --git a/src/core/libraries/random/random.cpp b/src/core/libraries/random/random.cpp index 8147c5183..f7cc3fd2c 100644 --- a/src/core/libraries/random/random.cpp +++ b/src/core/libraries/random/random.cpp @@ -1,14 +1,16 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "random.h" +#include "random_error.h" + #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" -#include "random.h" namespace Libraries::Random { -s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, size_t size) { +s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, std::size_t size) { LOG_TRACE(Lib_Random, "called"); if (size > SCE_RANDOM_MAX_SIZE) { return SCE_RANDOM_ERROR_INVALID; diff --git a/src/core/libraries/random/random.h b/src/core/libraries/random/random.h index b5f87f877..7bb41f016 100644 --- a/src/core/libraries/random/random.h +++ b/src/core/libraries/random/random.h @@ -11,7 +11,7 @@ class SymbolsResolver; namespace Libraries::Random { constexpr int32_t SCE_RANDOM_MAX_SIZE = 64; -s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, size_t size); +s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, std::size_t size); void RegisterlibSceRandom(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Random \ No newline at end of file diff --git a/src/core/libraries/random/random_error.h b/src/core/libraries/random/random_error.h new file mode 100644 index 000000000..772316ae5 --- /dev/null +++ b/src/core/libraries/random/random_error.h @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int SCE_RANDOM_ERROR_INVALID = 0x817C0016; +constexpr int SCE_RANDOM_ERROR_OUT_OF_RESOURCES = 0x817C001C; +constexpr int SCE_RANDOM_ERROR_FATAL = 0x817C00FF; \ No newline at end of file From 371d1d009aa936d9c3d7b022e616714f2ae762be Mon Sep 17 00:00:00 2001 From: psucien Date: Tue, 27 Aug 2024 19:17:23 +0200 Subject: [PATCH 062/147] Added missing headers and 2D MSAA image type --- src/shader_recompiler/frontend/structured_control_flow.cpp | 1 + src/video_core/buffer_cache/buffer.h | 1 + src/video_core/texture_cache/image_info.cpp | 1 + src/video_core/texture_cache/image_view.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/src/shader_recompiler/frontend/structured_control_flow.cpp b/src/shader_recompiler/frontend/structured_control_flow.cpp index b50205d46..fefc623fc 100644 --- a/src/shader_recompiler/frontend/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/structured_control_flow.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index 5c64ba65e..87293c768 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include #include "common/types.h" diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index a073d046e..4ac4aee8f 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -34,6 +34,7 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { case AmdGpu::ImageType::Color1DArray: return vk::ImageType::e1D; case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Color2DMsaa: case AmdGpu::ImageType::Cube: case AmdGpu::ImageType::Color2DArray: return vk::ImageType::e2D; diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 08be6bdc5..00c3833fe 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -17,6 +17,7 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) { case AmdGpu::ImageType::Color1DArray: return vk::ImageViewType::e1DArray; case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Color2DMsaa: return vk::ImageViewType::e2D; case AmdGpu::ImageType::Cube: return vk::ImageViewType::eCube; From 3eb47226d99d49f8750238b085d5b11adfe6f963 Mon Sep 17 00:00:00 2001 From: psucien Date: Tue, 27 Aug 2024 22:24:26 +0200 Subject: [PATCH 063/147] libraries: kernel: fix `scePthreadMutexattrSettype` error value return --- src/core/libraries/kernel/thread_management.cpp | 13 +++++++------ src/core/libraries/kernel/thread_management.h | 5 +++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 567fff184..567ac867e 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -510,23 +510,24 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) { int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) { int ptype = PTHREAD_MUTEX_DEFAULT; switch (type) { - case 1: + case ORBIS_PTHREAD_MUTEX_ERRORCHECK: ptype = PTHREAD_MUTEX_ERRORCHECK; break; - case 2: + case ORBIS_PTHREAD_MUTEX_RECURSIVE: ptype = PTHREAD_MUTEX_RECURSIVE; break; - case 3: - case 4: + case ORBIS_PTHREAD_MUTEX_NORMAL: + case ORBIS_PTHREAD_MUTEX_ADAPTIVE: ptype = PTHREAD_MUTEX_NORMAL; break; default: - UNREACHABLE_MSG("Invalid type: {}", type); + return SCE_KERNEL_ERROR_EINVAL; } int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype); + ASSERT(result == 0); - return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; + return SCE_OK; } int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol) { diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index c5935275f..3679af84f 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -20,6 +20,11 @@ constexpr int ORBIS_KERNEL_PRIO_FIFO_DEFAULT = 700; constexpr int ORBIS_KERNEL_PRIO_FIFO_HIGHEST = 256; constexpr int ORBIS_KERNEL_PRIO_FIFO_LOWEST = 767; +constexpr int ORBIS_PTHREAD_MUTEX_ERRORCHECK = 1; +constexpr int ORBIS_PTHREAD_MUTEX_RECURSIVE = 2; +constexpr int ORBIS_PTHREAD_MUTEX_NORMAL = 3; +constexpr int ORBIS_PTHREAD_MUTEX_ADAPTIVE = 4; + struct PthreadInternal; struct PthreadAttrInternal; struct PthreadMutexInternal; From 659e7a467549ebca374acc859c8a0e3d47c0e0b6 Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Tue, 27 Aug 2024 23:16:14 +0200 Subject: [PATCH 064/147] video_core: Added copyGPUCmdBuffers option --- src/common/config.cpp | 11 +++++++++ src/common/config.h | 2 ++ src/video_core/amdgpu/liverpool.cpp | 37 +++++++++++++++++++++++++++++ src/video_core/amdgpu/liverpool.h | 8 +++++++ 4 files changed, 58 insertions(+) diff --git a/src/common/config.cpp b/src/common/config.cpp index 9f55cbd40..04d67d44b 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -20,6 +20,7 @@ static std::string userName = "shadPS4"; static bool isDebugDump = false; static bool isShowSplash = false; static bool isNullGpu = false; +static bool shouldCopyGPUBuffers = false; static bool shouldDumpShaders = false; static bool shouldDumpPM4 = false; static u32 vblankDivider = 1; @@ -93,6 +94,10 @@ bool nullGpu() { return isNullGpu; } +bool copyGPUCmdBuffers() { + return shouldCopyGPUBuffers; +} + bool dumpShaders() { return shouldDumpShaders; } @@ -149,6 +154,10 @@ void setNullGpu(bool enable) { isNullGpu = enable; } +void setCopyGPUCmdBuffers(bool enable) { + shouldCopyGPUBuffers = enable; +} + void setDumpShaders(bool enable) { shouldDumpShaders = enable; } @@ -336,6 +345,7 @@ void load(const std::filesystem::path& path) { screenWidth = toml::find_or(gpu, "screenWidth", screenWidth); screenHeight = toml::find_or(gpu, "screenHeight", screenHeight); isNullGpu = toml::find_or(gpu, "nullGpu", false); + shouldCopyGPUBuffers = toml::find_or(gpu, "copyGPUBuffers", false); shouldDumpShaders = toml::find_or(gpu, "dumpShaders", false); shouldDumpPM4 = toml::find_or(gpu, "dumpPM4", false); vblankDivider = toml::find_or(gpu, "vblankDivider", 1); @@ -414,6 +424,7 @@ void save(const std::filesystem::path& path) { data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenHeight"] = screenHeight; data["GPU"]["nullGpu"] = isNullGpu; + data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers; data["GPU"]["dumpShaders"] = shouldDumpShaders; data["GPU"]["dumpPM4"] = shouldDumpPM4; data["GPU"]["vblankDivider"] = vblankDivider; diff --git a/src/common/config.h b/src/common/config.h index 554515a44..f1347b076 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -24,6 +24,7 @@ s32 getGpuId(); bool debugDump(); bool showSplash(); bool nullGpu(); +bool copyGPUCmdBuffers(); bool dumpShaders(); bool dumpPM4(); bool isRdocEnabled(); @@ -33,6 +34,7 @@ u32 vblankDiv(); void setDebugDump(bool enable); void setShowSplash(bool enable); void setNullGpu(bool enable); +void setCopyGPUCmdBuffers(bool enable); void setDumpShaders(bool enable); void setDumpPM4(bool enable); void setVblankDiv(u32 value); diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 5b3db603a..cec3b06bb 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -5,6 +5,7 @@ #include "common/debug.h" #include "common/polyfill_thread.h" #include "common/thread.h" +#include "common/config.h" #include "core/libraries/videoout/driver.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/pm4_cmds.h" @@ -568,9 +569,45 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { TracyFiberLeave; } +void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& ccb) { + auto& queue = mapped_queues[GfxQueueId]; + + // This is fine because resize doesn't reallocate the buffer on shrink + queue.dcb_buffer.resize(queue.dcb_buffer_offset + dcb.size()); + queue.ccb_buffer.resize(queue.ccb_buffer_offset + dcb.size()); + + u32 prev_dcb_buffer_offset = queue.dcb_buffer_offset; + u32 prev_ccb_buffer_offset = queue.ccb_buffer_offset; + if (!dcb.empty()) { + std::memcpy(queue.dcb_buffer.data() + queue.dcb_buffer_offset, dcb.data(), + dcb.size_bytes()); + queue.dcb_buffer_offset += dcb.size(); + } + + if (!ccb.empty()) { + std::memcpy(queue.ccb_buffer.data() + queue.ccb_buffer_offset, ccb.data(), + ccb.size_bytes()); + queue.ccb_buffer_offset += dcb.size(); + } + + if (!queue.dcb_buffer.empty()) { + dcb = std::span{queue.dcb_buffer.begin() + prev_dcb_buffer_offset, + queue.dcb_buffer.begin() + queue.dcb_buffer_offset}; + } + + if (!queue.ccb_buffer.empty()) { + ccb = std::span{queue.ccb_buffer.begin() + prev_ccb_buffer_offset, + queue.ccb_buffer.begin() + queue.ccb_buffer_offset}; + } +} + void Liverpool::SubmitGfx(std::span dcb, std::span ccb) { auto& queue = mapped_queues[GfxQueueId]; + if (Config::copyGPUCmdBuffers()) { + CopyCmdBuffers(dcb, ccb); + } + auto task = ProcessGraphics(dcb, ccb); { std::scoped_lock lock{queue.m_access}; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 2806f3308..a4e61c92a 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "common/assert.h" #include "common/bit_field.h" @@ -1047,6 +1048,8 @@ public: void SubmitDone() noexcept { std::scoped_lock lk{submit_mutex}; + mapped_queues[GfxQueueId].ccb_buffer_offset = 0; + mapped_queues[GfxQueueId].dcb_buffer_offset = 0; submit_done = true; submit_cv.notify_one(); } @@ -1108,6 +1111,7 @@ private: Handle handle; }; + void CopyCmdBuffers(std::span& dcb, std::span& ccb); Task ProcessGraphics(std::span dcb, std::span ccb); Task ProcessCeUpdate(std::span ccb); Task ProcessCompute(std::span acb, int vqid); @@ -1116,6 +1120,10 @@ private: struct GpuQueue { std::mutex m_access{}; + std::atomic_uint32_t dcb_buffer_offset; + std::atomic_uint32_t ccb_buffer_offset; + std::vector dcb_buffer; + std::vector ccb_buffer; std::queue submits{}; ComputeProgram cs_state{}; }; From 595b845df0f6776cb44201217a7cdc2f7cb679d3 Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Tue, 27 Aug 2024 23:31:04 +0200 Subject: [PATCH 065/147] clang-format fix --- src/video_core/amdgpu/liverpool.cpp | 4 ++-- src/video_core/amdgpu/liverpool.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index cec3b06bb..4b8a83152 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -593,8 +593,8 @@ void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& if (!queue.dcb_buffer.empty()) { dcb = std::span{queue.dcb_buffer.begin() + prev_dcb_buffer_offset, queue.dcb_buffer.begin() + queue.dcb_buffer_offset}; - } - + } + if (!queue.ccb_buffer.empty()) { ccb = std::span{queue.ccb_buffer.begin() + prev_ccb_buffer_offset, queue.ccb_buffer.begin() + queue.ccb_buffer_offset}; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index a4e61c92a..c12c8fdb6 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -10,8 +10,8 @@ #include #include #include -#include #include +#include #include "common/assert.h" #include "common/bit_field.h" From 3d46a5d4920fdf5ab04fb20e6f86bde87235d77c Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Tue, 27 Aug 2024 23:33:24 +0200 Subject: [PATCH 066/147] Do not shrink buffer's size on submit --- src/video_core/amdgpu/liverpool.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 4b8a83152..93099266a 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -573,8 +573,10 @@ void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& auto& queue = mapped_queues[GfxQueueId]; // This is fine because resize doesn't reallocate the buffer on shrink - queue.dcb_buffer.resize(queue.dcb_buffer_offset + dcb.size()); - queue.ccb_buffer.resize(queue.ccb_buffer_offset + dcb.size()); + queue.dcb_buffer.resize( + std::max(queue.dcb_buffer.size(), queue.dcb_buffer_offset + dcb.size())); + queue.ccb_buffer.resize( + std::max(queue.ccb_buffer.size(), queue.ccb_buffer_offset + dcb.size())); u32 prev_dcb_buffer_offset = queue.dcb_buffer_offset; u32 prev_ccb_buffer_offset = queue.ccb_buffer_offset; From 3842993a4310e5f6c392f0898c795a50e5a731a2 Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Wed, 28 Aug 2024 00:21:12 +0200 Subject: [PATCH 067/147] Use input dcb and ccb instead of copy --- src/video_core/amdgpu/liverpool.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 93099266a..3db9ff0d1 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -572,7 +572,6 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& ccb) { auto& queue = mapped_queues[GfxQueueId]; - // This is fine because resize doesn't reallocate the buffer on shrink queue.dcb_buffer.resize( std::max(queue.dcb_buffer.size(), queue.dcb_buffer_offset + dcb.size())); queue.ccb_buffer.resize( @@ -584,20 +583,14 @@ void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& std::memcpy(queue.dcb_buffer.data() + queue.dcb_buffer_offset, dcb.data(), dcb.size_bytes()); queue.dcb_buffer_offset += dcb.size(); + dcb = std::span{queue.dcb_buffer.begin() + prev_dcb_buffer_offset, + queue.dcb_buffer.begin() + queue.dcb_buffer_offset}; } if (!ccb.empty()) { std::memcpy(queue.ccb_buffer.data() + queue.ccb_buffer_offset, ccb.data(), ccb.size_bytes()); queue.ccb_buffer_offset += dcb.size(); - } - - if (!queue.dcb_buffer.empty()) { - dcb = std::span{queue.dcb_buffer.begin() + prev_dcb_buffer_offset, - queue.dcb_buffer.begin() + queue.dcb_buffer_offset}; - } - - if (!queue.ccb_buffer.empty()) { ccb = std::span{queue.ccb_buffer.begin() + prev_ccb_buffer_offset, queue.ccb_buffer.begin() + queue.ccb_buffer_offset}; } From 860b93505423dffed0e2abeb0e278aee2d759210 Mon Sep 17 00:00:00 2001 From: Semenov Herman Date: Wed, 28 Aug 2024 01:32:14 +0300 Subject: [PATCH 068/147] crypto: added destructors fix memleak FakeKeyset, DebugRifKeyset, PkgDerivedKey3Keyset --- src/core/crypto/keys.h | 43 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/core/crypto/keys.h b/src/core/crypto/keys.h index 37b66bd09..58466b764 100644 --- a/src/core/crypto/keys.h +++ b/src/core/crypto/keys.h @@ -132,11 +132,22 @@ public: 0x79, 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51, 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23}; }; + + // Destructor + ~FakeKeyset() { + delete[] PrivateExponent; + delete[] Exponent1; + delete[] Exponent2; + delete[] PublicExponent; + delete[] Coefficient; + delete[] Modulus; + delete[] Prime1; + delete[] Prime2; + }; }; class DebugRifKeyset { public: - // Constructor // std::uint8_t* PrivateExponent; const CryptoPP::byte* Exponent1; // exponent2 = d mod (q - 1) @@ -263,14 +274,22 @@ public: 0x81, 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B, 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D}; }; + + // Destructor + ~DebugRifKeyset() { + delete[] PrivateExponent; + delete[] Exponent1; + delete[] Exponent2; + delete[] PublicExponent; + delete[] Coefficient; + delete[] Modulus; + delete[] Prime1; + delete[] Prime2; + }; }; class PkgDerivedKey3Keyset { public: - // PkgDerivedKey3Keyset(); - //~PkgDerivedKey3Keyset(); - - // Constructor // std::uint8_t* PrivateExponent; const CryptoPP::byte* Exponent1; // exponent2 = d mod (q - 1) @@ -287,8 +306,8 @@ public: const CryptoPP::byte* Prime2; const CryptoPP::byte* PrivateExponent; + // Constructor PkgDerivedKey3Keyset() { - Prime1 = new CryptoPP::byte[0x80]{ 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D, 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, @@ -387,4 +406,16 @@ public: 0xf9, 0xc9, 0xa3, 0xc1}; PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1}; }; + + // Destructor + ~PkgDerivedKey3Keyset() { + delete[] Prime1; + delete[] Prime2; + delete[] PrivateExponent; + delete[] Exponent1; + delete[] Exponent2; + delete[] Coefficient; + delete[] Modulus; + delete[] PublicExponent; + }; }; \ No newline at end of file From 1a02efbd156ff7b07bfa306cd94c39862cba8d56 Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Wed, 28 Aug 2024 05:42:48 +0200 Subject: [PATCH 069/147] clang-format style fix --- src/video_core/amdgpu/liverpool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 3db9ff0d1..6e49aec41 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -2,10 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "common/config.h" #include "common/debug.h" #include "common/polyfill_thread.h" #include "common/thread.h" -#include "common/config.h" #include "core/libraries/videoout/driver.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/pm4_cmds.h" From ed42db47af3ab0cbe92be922110023eda895d34a Mon Sep 17 00:00:00 2001 From: Exhigh Date: Wed, 28 Aug 2024 08:52:20 +0400 Subject: [PATCH 070/147] savedata: Add another missed case in saveDataMount This should potentially fix Deadpool (CUSA03528) #554. --- src/core/libraries/save_data/savedata.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index a6117cba5..eb309183f 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -505,6 +505,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | From 87ccfdfbbdb7b98ba1169174096baffcd1d93729 Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Wed, 28 Aug 2024 09:42:31 +0200 Subject: [PATCH 071/147] Fixed type on function --- src/video_core/amdgpu/liverpool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 6e49aec41..931b5ea84 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -575,7 +575,7 @@ void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& queue.dcb_buffer.resize( std::max(queue.dcb_buffer.size(), queue.dcb_buffer_offset + dcb.size())); queue.ccb_buffer.resize( - std::max(queue.ccb_buffer.size(), queue.ccb_buffer_offset + dcb.size())); + std::max(queue.ccb_buffer.size(), queue.ccb_buffer_offset + ccb.size())); u32 prev_dcb_buffer_offset = queue.dcb_buffer_offset; u32 prev_ccb_buffer_offset = queue.ccb_buffer_offset; @@ -590,7 +590,7 @@ void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& if (!ccb.empty()) { std::memcpy(queue.ccb_buffer.data() + queue.ccb_buffer_offset, ccb.data(), ccb.size_bytes()); - queue.ccb_buffer_offset += dcb.size(); + queue.ccb_buffer_offset += ccb.size(); ccb = std::span{queue.ccb_buffer.begin() + prev_ccb_buffer_offset, queue.ccb_buffer.begin() + queue.ccb_buffer_offset}; } From c37679154eeb59e6bfe73ec2ff99b15096094942 Mon Sep 17 00:00:00 2001 From: Random <28494085+Random06457@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:53:27 +0200 Subject: [PATCH 072/147] Handle PM4 type-2 packets (#556) * video_core: handle PM4 type-2 packets * video_core: rewrite pm4 comand type handling into a switch statement --- src/video_core/amdgpu/liverpool.cpp | 563 ++++++++++++++-------------- 1 file changed, 287 insertions(+), 276 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 5b3db603a..7e6ca14da 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -175,294 +175,305 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(dcb.data()); const u32 type = header->type; - if (type != 3) { - // No other types of packets were spotted so far - UNREACHABLE_MSG("Invalid PM4 type {}", type); - } - const u32 count = header->type3.NumWords(); - const PM4ItOpcode opcode = header->type3.opcode; - switch (opcode) { - case PM4ItOpcode::Nop: { - const auto* nop = reinterpret_cast(header); - if (nop->header.count.Value() == 0) { - break; - } + switch (type) { + case 0: + case 1: + UNREACHABLE_MSG("Unsupported PM4 type {}", type); + break; + case 2: + // Type-2 packet are used for padding purposes + dcb = dcb.subspan(1); + continue; + case 3: + const u32 count = header->type3.NumWords(); + const PM4ItOpcode opcode = header->type3.opcode; + switch (opcode) { + case PM4ItOpcode::Nop: { + const auto* nop = reinterpret_cast(header); + if (nop->header.count.Value() == 0) { + break; + } - switch (nop->data_block[0]) { - case PM4CmdNop::PayloadType::PatchedFlip: { - // There is no evidence that GPU CP drives flip events by parsing - // special NOP packets. For convenience lets assume that it does. - Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxFlip); + switch (nop->data_block[0]) { + case PM4CmdNop::PayloadType::PatchedFlip: { + // There is no evidence that GPU CP drives flip events by parsing + // special NOP packets. For convenience lets assume that it does. + Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxFlip); + break; + } + case PM4CmdNop::PayloadType::DebugMarkerPush: { + const auto marker_sz = nop->header.count.Value() * 2; + const std::string_view label{reinterpret_cast(&nop->data_block[1]), + marker_sz}; + rasterizer->ScopeMarkerBegin(label); + break; + } + case PM4CmdNop::PayloadType::DebugMarkerPop: { + rasterizer->ScopeMarkerEnd(); + break; + } + default: + break; + } break; } - case PM4CmdNop::PayloadType::DebugMarkerPush: { - const auto marker_sz = nop->header.count.Value() * 2; - const std::string_view label{reinterpret_cast(&nop->data_block[1]), - marker_sz}; - rasterizer->ScopeMarkerBegin(label); + case PM4ItOpcode::ContextControl: { break; } - case PM4CmdNop::PayloadType::DebugMarkerPop: { - rasterizer->ScopeMarkerEnd(); + case PM4ItOpcode::ClearState: { + regs.SetDefaults(); + break; + } + case PM4ItOpcode::SetConfigReg: { + const auto* set_data = reinterpret_cast(header); + const auto reg_addr = ConfigRegWordOffset + set_data->reg_offset; + const auto* payload = reinterpret_cast(header + 2); + std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); + break; + } + case PM4ItOpcode::SetContextReg: { + const auto* set_data = reinterpret_cast(header); + const auto reg_addr = ContextRegWordOffset + set_data->reg_offset; + const auto* payload = reinterpret_cast(header + 2); + + std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); + + // In the case of HW, render target memory has alignment as color block operates on + // tiles. There is no information of actual resource extents stored in CB context + // regs, so any deduction of it from slices/pitch will lead to a larger surface + // created. The same applies to the depth targets. Fortunately, the guest always + // sends a trailing NOP packet right after the context regs setup, so we can use the + // heuristic below and extract the hint to determine actual resource dims. + + switch (reg_addr) { + case ContextRegs::CbColor0Base: + case ContextRegs::CbColor1Base: + case ContextRegs::CbColor2Base: + case ContextRegs::CbColor3Base: + case ContextRegs::CbColor4Base: + case ContextRegs::CbColor5Base: + case ContextRegs::CbColor6Base: + case ContextRegs::CbColor7Base: { + const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Base) / + (ContextRegs::CbColor1Base - ContextRegs::CbColor0Base); + ASSERT(col_buf_id < NumColorBuffers); + + const auto nop_offset = header->type3.count; + if (nop_offset == 0x0e || nop_offset == 0x0d || nop_offset == 0x0b) { + ASSERT_MSG(payload[nop_offset] == 0xc0001000, + "NOP hint is missing in CB setup sequence"); + last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; + } else { + last_cb_extent[col_buf_id].raw = 0; + } + break; + } + case ContextRegs::CbColor0Cmask: + case ContextRegs::CbColor1Cmask: + case ContextRegs::CbColor2Cmask: + case ContextRegs::CbColor3Cmask: + case ContextRegs::CbColor4Cmask: + case ContextRegs::CbColor5Cmask: + case ContextRegs::CbColor6Cmask: + case ContextRegs::CbColor7Cmask: { + const auto col_buf_id = + (reg_addr - ContextRegs::CbColor0Cmask) / + (ContextRegs::CbColor1Cmask - ContextRegs::CbColor0Cmask); + ASSERT(col_buf_id < NumColorBuffers); + + const auto nop_offset = header->type3.count; + if (nop_offset == 0x04) { + ASSERT_MSG(payload[nop_offset] == 0xc0001000, + "NOP hint is missing in CB setup sequence"); + last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; + } + break; + } + case ContextRegs::DbZInfo: { + if (header->type3.count == 8) { + ASSERT_MSG(payload[20] == 0xc0001000, + "NOP hint is missing in DB setup sequence"); + last_db_extent.raw = payload[21]; + } else { + last_db_extent.raw = 0; + } + break; + } + default: + break; + } + break; + } + case PM4ItOpcode::SetShReg: { + const auto* set_data = reinterpret_cast(header); + std::memcpy(®s.reg_array[ShRegWordOffset + set_data->reg_offset], header + 2, + (count - 1) * sizeof(u32)); + break; + } + case PM4ItOpcode::SetUconfigReg: { + const auto* set_data = reinterpret_cast(header); + std::memcpy(®s.reg_array[UconfigRegWordOffset + set_data->reg_offset], + header + 2, (count - 1) * sizeof(u32)); + break; + } + case PM4ItOpcode::IndexType: { + const auto* index_type = reinterpret_cast(header); + regs.index_buffer_type.raw = index_type->raw; + break; + } + case PM4ItOpcode::DrawIndex2: { + const auto* draw_index = reinterpret_cast(header); + regs.max_index_size = draw_index->max_size; + regs.index_base_address.base_addr_lo = draw_index->index_base_lo; + regs.index_base_address.base_addr_hi.Assign(draw_index->index_base_hi); + regs.num_indices = draw_index->index_count; + regs.draw_initiator = draw_index->draw_initiator; + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndex2", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->Draw(true); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndexOffset2: { + const auto* draw_index_off = + reinterpret_cast(header); + regs.max_index_size = draw_index_off->max_size; + regs.num_indices = draw_index_off->index_count; + regs.draw_initiator = draw_index_off->draw_initiator; + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin( + fmt::format("dcb:{}:DrawIndexOffset2", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->Draw(true, draw_index_off->index_offset); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndexAuto: { + const auto* draw_index = reinterpret_cast(header); + regs.num_indices = draw_index->index_count; + regs.draw_initiator = draw_index->draw_initiator; + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexAuto", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->Draw(false); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DispatchDirect: { + const auto* dispatch_direct = reinterpret_cast(header); + regs.cs_program.dim_x = dispatch_direct->dim_x; + regs.cs_program.dim_y = dispatch_direct->dim_y; + regs.cs_program.dim_z = dispatch_direct->dim_z; + regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; + if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:Dispatch", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->DispatchDirect(); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::NumInstances: { + const auto* num_instances = reinterpret_cast(header); + regs.num_instances.num_instances = num_instances->num_instances; + break; + } + case PM4ItOpcode::IndexBase: { + const auto* index_base = reinterpret_cast(header); + regs.index_base_address.base_addr_lo = index_base->addr_lo; + regs.index_base_address.base_addr_hi.Assign(index_base->addr_hi); + break; + } + case PM4ItOpcode::IndexBufferSize: { + const auto* index_size = reinterpret_cast(header); + regs.num_indices = index_size->num_indices; + break; + } + case PM4ItOpcode::EventWrite: { + // const auto* event = reinterpret_cast(header); + break; + } + case PM4ItOpcode::EventWriteEos: { + const auto* event_eos = reinterpret_cast(header); + event_eos->SignalFence(); + break; + } + case PM4ItOpcode::EventWriteEop: { + const auto* event_eop = reinterpret_cast(header); + event_eop->SignalFence(); + break; + } + case PM4ItOpcode::DmaData: { + const auto* dma_data = reinterpret_cast(header); + break; + } + case PM4ItOpcode::WriteData: { + const auto* write_data = reinterpret_cast(header); + ASSERT(write_data->dst_sel.Value() == 2 || write_data->dst_sel.Value() == 5); + const u32 data_size = (header->type3.count.Value() - 2) * 4; + u64* address = write_data->Address(); + if (!write_data->wr_one_addr.Value()) { + std::memcpy(address, write_data->data, data_size); + } else { + UNREACHABLE(); + } + break; + } + case PM4ItOpcode::AcquireMem: { + // const auto* acquire_mem = reinterpret_cast(header); + break; + } + case PM4ItOpcode::WaitRegMem: { + const auto* wait_reg_mem = reinterpret_cast(header); + // ASSERT(wait_reg_mem->engine.Value() == PM4CmdWaitRegMem::Engine::Me); + // Optimization: VO label waits are special because the emulator + // will write to the label when presentation is finished. So if + // there are no other submits to yield to we can sleep the thread + // instead and allow other tasks to run. + const u64* wait_addr = wait_reg_mem->Address(); + if (vo_port->IsVoLabel(wait_addr) && num_submits == 1) { + vo_port->WaitVoLabel([&] { return wait_reg_mem->Test(); }); + } + while (!wait_reg_mem->Test()) { + mapped_queues[GfxQueueId].cs_state = regs.cs_program; + TracyFiberLeave; + co_yield {}; + TracyFiberEnter(dcb_task_name); + regs.cs_program = mapped_queues[GfxQueueId].cs_state; + } + break; + } + case PM4ItOpcode::IncrementDeCounter: { + ++cblock.de_count; + break; + } + case PM4ItOpcode::WaitOnCeCounter: { + while (cblock.ce_count <= cblock.de_count) { + TracyFiberLeave; + ce_task.handle.resume(); + TracyFiberEnter(dcb_task_name); + } + break; + } + case PM4ItOpcode::PfpSyncMe: { break; } default: - break; + UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", + static_cast(opcode), count); } + dcb = dcb.subspan(header->type3.NumWords() + 1); break; } - case PM4ItOpcode::ContextControl: { - break; - } - case PM4ItOpcode::ClearState: { - regs.SetDefaults(); - break; - } - case PM4ItOpcode::SetConfigReg: { - const auto* set_data = reinterpret_cast(header); - const auto reg_addr = ConfigRegWordOffset + set_data->reg_offset; - const auto* payload = reinterpret_cast(header + 2); - std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); - break; - } - case PM4ItOpcode::SetContextReg: { - const auto* set_data = reinterpret_cast(header); - const auto reg_addr = ContextRegWordOffset + set_data->reg_offset; - const auto* payload = reinterpret_cast(header + 2); - - std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); - - // In the case of HW, render target memory has alignment as color block operates on - // tiles. There is no information of actual resource extents stored in CB context - // regs, so any deduction of it from slices/pitch will lead to a larger surface created. - // The same applies to the depth targets. Fortunately, the guest always sends - // a trailing NOP packet right after the context regs setup, so we can use the heuristic - // below and extract the hint to determine actual resource dims. - - switch (reg_addr) { - case ContextRegs::CbColor0Base: - case ContextRegs::CbColor1Base: - case ContextRegs::CbColor2Base: - case ContextRegs::CbColor3Base: - case ContextRegs::CbColor4Base: - case ContextRegs::CbColor5Base: - case ContextRegs::CbColor6Base: - case ContextRegs::CbColor7Base: { - const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Base) / - (ContextRegs::CbColor1Base - ContextRegs::CbColor0Base); - ASSERT(col_buf_id < NumColorBuffers); - - const auto nop_offset = header->type3.count; - if (nop_offset == 0x0e || nop_offset == 0x0d || nop_offset == 0x0b) { - ASSERT_MSG(payload[nop_offset] == 0xc0001000, - "NOP hint is missing in CB setup sequence"); - last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; - } else { - last_cb_extent[col_buf_id].raw = 0; - } - break; - } - case ContextRegs::CbColor0Cmask: - case ContextRegs::CbColor1Cmask: - case ContextRegs::CbColor2Cmask: - case ContextRegs::CbColor3Cmask: - case ContextRegs::CbColor4Cmask: - case ContextRegs::CbColor5Cmask: - case ContextRegs::CbColor6Cmask: - case ContextRegs::CbColor7Cmask: { - const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Cmask) / - (ContextRegs::CbColor1Cmask - ContextRegs::CbColor0Cmask); - ASSERT(col_buf_id < NumColorBuffers); - - const auto nop_offset = header->type3.count; - if (nop_offset == 0x04) { - ASSERT_MSG(payload[nop_offset] == 0xc0001000, - "NOP hint is missing in CB setup sequence"); - last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; - } - break; - } - case ContextRegs::DbZInfo: { - if (header->type3.count == 8) { - ASSERT_MSG(payload[20] == 0xc0001000, - "NOP hint is missing in DB setup sequence"); - last_db_extent.raw = payload[21]; - } else { - last_db_extent.raw = 0; - } - break; - } - default: - break; - } - break; - } - case PM4ItOpcode::SetShReg: { - const auto* set_data = reinterpret_cast(header); - std::memcpy(®s.reg_array[ShRegWordOffset + set_data->reg_offset], header + 2, - (count - 1) * sizeof(u32)); - break; - } - case PM4ItOpcode::SetUconfigReg: { - const auto* set_data = reinterpret_cast(header); - std::memcpy(®s.reg_array[UconfigRegWordOffset + set_data->reg_offset], header + 2, - (count - 1) * sizeof(u32)); - break; - } - case PM4ItOpcode::IndexType: { - const auto* index_type = reinterpret_cast(header); - regs.index_buffer_type.raw = index_type->raw; - break; - } - case PM4ItOpcode::DrawIndex2: { - const auto* draw_index = reinterpret_cast(header); - regs.max_index_size = draw_index->max_size; - regs.index_base_address.base_addr_lo = draw_index->index_base_lo; - regs.index_base_address.base_addr_hi.Assign(draw_index->index_base_hi); - regs.num_indices = draw_index->index_count; - regs.draw_initiator = draw_index->draw_initiator; - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndex2", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->Draw(true); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::DrawIndexOffset2: { - const auto* draw_index_off = reinterpret_cast(header); - regs.max_index_size = draw_index_off->max_size; - regs.num_indices = draw_index_off->index_count; - regs.draw_initiator = draw_index_off->draw_initiator; - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexOffset2", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->Draw(true, draw_index_off->index_offset); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::DrawIndexAuto: { - const auto* draw_index = reinterpret_cast(header); - regs.num_indices = draw_index->index_count; - regs.draw_initiator = draw_index->draw_initiator; - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexAuto", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->Draw(false); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::DispatchDirect: { - const auto* dispatch_direct = reinterpret_cast(header); - regs.cs_program.dim_x = dispatch_direct->dim_x; - regs.cs_program.dim_y = dispatch_direct->dim_y; - regs.cs_program.dim_z = dispatch_direct->dim_z; - regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; - if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:Dispatch", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->DispatchDirect(); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::NumInstances: { - const auto* num_instances = reinterpret_cast(header); - regs.num_instances.num_instances = num_instances->num_instances; - break; - } - case PM4ItOpcode::IndexBase: { - const auto* index_base = reinterpret_cast(header); - regs.index_base_address.base_addr_lo = index_base->addr_lo; - regs.index_base_address.base_addr_hi.Assign(index_base->addr_hi); - break; - } - case PM4ItOpcode::IndexBufferSize: { - const auto* index_size = reinterpret_cast(header); - regs.num_indices = index_size->num_indices; - break; - } - case PM4ItOpcode::EventWrite: { - // const auto* event = reinterpret_cast(header); - break; - } - case PM4ItOpcode::EventWriteEos: { - const auto* event_eos = reinterpret_cast(header); - event_eos->SignalFence(); - break; - } - case PM4ItOpcode::EventWriteEop: { - const auto* event_eop = reinterpret_cast(header); - event_eop->SignalFence(); - break; - } - case PM4ItOpcode::DmaData: { - const auto* dma_data = reinterpret_cast(header); - break; - } - case PM4ItOpcode::WriteData: { - const auto* write_data = reinterpret_cast(header); - ASSERT(write_data->dst_sel.Value() == 2 || write_data->dst_sel.Value() == 5); - const u32 data_size = (header->type3.count.Value() - 2) * 4; - u64* address = write_data->Address(); - if (!write_data->wr_one_addr.Value()) { - std::memcpy(address, write_data->data, data_size); - } else { - UNREACHABLE(); - } - break; - } - case PM4ItOpcode::AcquireMem: { - // const auto* acquire_mem = reinterpret_cast(header); - break; - } - case PM4ItOpcode::WaitRegMem: { - const auto* wait_reg_mem = reinterpret_cast(header); - // ASSERT(wait_reg_mem->engine.Value() == PM4CmdWaitRegMem::Engine::Me); - // Optimization: VO label waits are special because the emulator - // will write to the label when presentation is finished. So if - // there are no other submits to yield to we can sleep the thread - // instead and allow other tasks to run. - const u64* wait_addr = wait_reg_mem->Address(); - if (vo_port->IsVoLabel(wait_addr) && num_submits == 1) { - vo_port->WaitVoLabel([&] { return wait_reg_mem->Test(); }); - } - while (!wait_reg_mem->Test()) { - mapped_queues[GfxQueueId].cs_state = regs.cs_program; - TracyFiberLeave; - co_yield {}; - TracyFiberEnter(dcb_task_name); - regs.cs_program = mapped_queues[GfxQueueId].cs_state; - } - break; - } - case PM4ItOpcode::IncrementDeCounter: { - ++cblock.de_count; - break; - } - case PM4ItOpcode::WaitOnCeCounter: { - while (cblock.ce_count <= cblock.de_count) { - TracyFiberLeave; - ce_task.handle.resume(); - TracyFiberEnter(dcb_task_name); - } - break; - } - case PM4ItOpcode::PfpSyncMe: { - break; - } - default: - UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", - static_cast(opcode), count); - } - dcb = dcb.subspan(header->type3.NumWords() + 1); } if (ce_task.handle) { From dfb30ea955279e82f3c86cf9f0f8a0b59c2dcdfd Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Wed, 28 Aug 2024 11:24:15 +0200 Subject: [PATCH 073/147] Use pair of spans instead of references in copy command buffers function --- src/video_core/amdgpu/liverpool.cpp | 7 +++++-- src/video_core/amdgpu/liverpool.h | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 931b5ea84..a3e64b7c0 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -569,7 +569,8 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { TracyFiberLeave; } -void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& ccb) { +std::pair, std::span> Liverpool::CopyCmdBuffers( + std::span dcb, std::span ccb) { auto& queue = mapped_queues[GfxQueueId]; queue.dcb_buffer.resize( @@ -594,13 +595,15 @@ void Liverpool::CopyCmdBuffers(std::span& dcb, std::span& ccb = std::span{queue.ccb_buffer.begin() + prev_ccb_buffer_offset, queue.ccb_buffer.begin() + queue.ccb_buffer_offset}; } + + return std::make_pair(dcb, ccb); } void Liverpool::SubmitGfx(std::span dcb, std::span ccb) { auto& queue = mapped_queues[GfxQueueId]; if (Config::copyGPUCmdBuffers()) { - CopyCmdBuffers(dcb, ccb); + std::tie(dcb, ccb) = CopyCmdBuffers(dcb, ccb); } auto task = ProcessGraphics(dcb, ccb); diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index c12c8fdb6..14284bbc6 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -1111,7 +1111,8 @@ private: Handle handle; }; - void CopyCmdBuffers(std::span& dcb, std::span& ccb); + std::pair, std::span> CopyCmdBuffers(std::span dcb, + std::span ccb); Task ProcessGraphics(std::span dcb, std::span ccb); Task ProcessCeUpdate(std::span ccb); Task ProcessCompute(std::span acb, int vqid); @@ -1120,8 +1121,8 @@ private: struct GpuQueue { std::mutex m_access{}; - std::atomic_uint32_t dcb_buffer_offset; - std::atomic_uint32_t ccb_buffer_offset; + std::atomic dcb_buffer_offset; + std::atomic ccb_buffer_offset; std::vector dcb_buffer; std::vector ccb_buffer; std::queue submits{}; From 79e86a39fcc022f38104986c10252340025cfeda Mon Sep 17 00:00:00 2001 From: InvoxiPlayGames Date: Wed, 28 Aug 2024 10:27:51 +0100 Subject: [PATCH 074/147] add support for configurable special pad type --- src/common/config.cpp | 29 +++++++++++++++++++++++++++++ src/common/config.h | 6 ++++++ src/core/libraries/pad/pad.cpp | 24 +++++++++++++++++++++++- src/core/libraries/pad/pad.h | 9 ++++++++- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index 9f55cbd40..824a70da4 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -17,6 +17,8 @@ static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto static std::string logFilter; static std::string logType = "async"; static std::string userName = "shadPS4"; +static bool useSpecialPad = false; +static int specialPadClass = 1; static bool isDebugDump = false; static bool isShowSplash = false; static bool isNullGpu = false; @@ -81,6 +83,14 @@ std::string getUserName() { return userName; } +bool getUseSpecialPad() { + return useSpecialPad; +} + +int getSpecialPadClass() { + return specialPadClass; +} + bool debugDump() { return isDebugDump; } @@ -197,6 +207,14 @@ void setUserName(const std::string& type) { userName = type; } +void setUseSpecialPad(bool use) { + useSpecialPad = use; +} + +void setSpecialPadClass(int type) { + specialPadClass = type; +} + void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) { main_window_geometry_x = x; main_window_geometry_y = y; @@ -330,6 +348,13 @@ void load(const std::filesystem::path& path) { isShowSplash = toml::find_or(general, "showSplash", true); } + if (data.contains("Input")) { + const toml::value& input = data.at("Input"); + + useSpecialPad = toml::find_or(input, "useSpecialPad", false); + specialPadClass = toml::find_or(input, "specialPadClass", 1); + } + if (data.contains("GPU")) { const toml::value& gpu = data.at("GPU"); @@ -411,6 +436,8 @@ void save(const std::filesystem::path& path) { data["General"]["logType"] = logType; data["General"]["userName"] = userName; data["General"]["showSplash"] = isShowSplash; + data["Input"]["useSpecialPad"] = useSpecialPad; + data["Input"]["specialPadClass"] = specialPadClass; data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenHeight"] = screenHeight; data["GPU"]["nullGpu"] = isNullGpu; @@ -457,6 +484,8 @@ void setDefaultValues() { logFilter = ""; logType = "async"; userName = "shadPS4"; + useSpecialPad = false; + specialPadClass = 1; isDebugDump = false; isShowSplash = false; isNullGpu = false; diff --git a/src/common/config.h b/src/common/config.h index 554515a44..f5140bc9b 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -17,6 +17,9 @@ std::string getLogFilter(); std::string getLogType(); std::string getUserName(); +bool getUseSpecialPad(); +int getSpecialPadClass(); + u32 getScreenWidth(); u32 getScreenHeight(); s32 getGpuId(); @@ -44,6 +47,9 @@ void setLanguage(u32 language); void setNeoMode(bool enable); void setUserName(const std::string& type); +void setUseSpecialPad(bool use); +void setSpecialPadClass(int type); + void setLogType(const std::string& type); void setLogFilter(const std::string& type); diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index 305b20bd6..c4735c9ae 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -4,6 +4,7 @@ // Generated By moduleGenerator #include #include +#include "common/config.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" @@ -25,6 +26,9 @@ int PS4_SYSV_ABI scePadConnectPort() { int PS4_SYSV_ABI scePadDeviceClassGetExtendedInformation( s32 handle, OrbisPadDeviceClassExtendedInformation* pExtInfo) { LOG_ERROR(Lib_Pad, "(STUBBED) called"); + if (Config::getUseSpecialPad()) { + pExtInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass(); + } return ORBIS_OK; } @@ -107,6 +111,10 @@ int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerIn pInfo->connectedCount = 1; pInfo->connected = true; pInfo->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD; + if (Config::getUseSpecialPad()) { + pInfo->connectionType = ORBIS_PAD_PORT_TYPE_SPECIAL; + pInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass(); + } return SCE_OK; } @@ -239,11 +247,25 @@ int PS4_SYSV_ABI scePadMbusTerm() { int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam) { LOG_INFO(Lib_Pad, "(DUMMY) called user_id = {} type = {} index = {}", userId, type, index); + if (Config::getUseSpecialPad()) { + if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) + return -1; + } else { + if (type != ORBIS_PAD_PORT_TYPE_STANDARD) + return -1; + } return 1; // dummy } -int PS4_SYSV_ABI scePadOpenExt() { +int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, const OrbisPadOpenExtParam* pParam) { LOG_ERROR(Lib_Pad, "(STUBBED) called"); + if (Config::getUseSpecialPad()) { + if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) + return -1; + } else { + if (type != ORBIS_PAD_PORT_TYPE_STANDARD) + return -1; + } return 1; // dummy } diff --git a/src/core/libraries/pad/pad.h b/src/core/libraries/pad/pad.h index 3e9c14a17..b18bbc355 100644 --- a/src/core/libraries/pad/pad.h +++ b/src/core/libraries/pad/pad.h @@ -229,6 +229,13 @@ struct OrbisPadOpenParam { u8 reserve[8]; }; +struct OrbisPadOpenExtParam { + u16 vendorId; + u16 productId; + u16 productId_2; + u8 reserve[10]; +}; + struct OrbisPadLightBarParam { u8 r; u8 g; @@ -284,7 +291,7 @@ int PS4_SYSV_ABI scePadIsValidHandle(); int PS4_SYSV_ABI scePadMbusInit(); int PS4_SYSV_ABI scePadMbusTerm(); int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam); -int PS4_SYSV_ABI scePadOpenExt(); +int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, const OrbisPadOpenExtParam* pParam); int PS4_SYSV_ABI scePadOpenExt2(); int PS4_SYSV_ABI scePadOutputReport(); int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num); From 550cf0188d40e20df71d99b76237287be63ba13e Mon Sep 17 00:00:00 2001 From: InvoxiPlayGames Date: Wed, 28 Aug 2024 10:51:30 +0100 Subject: [PATCH 075/147] return proper error code for scePadOpen failure --- src/core/libraries/pad/pad.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index c4735c9ae..c75e71dfe 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -249,10 +249,10 @@ int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenP LOG_INFO(Lib_Pad, "(DUMMY) called user_id = {} type = {} index = {}", userId, type, index); if (Config::getUseSpecialPad()) { if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) - return -1; + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; } else { if (type != ORBIS_PAD_PORT_TYPE_STANDARD) - return -1; + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; } return 1; // dummy } @@ -261,10 +261,10 @@ int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, const OrbisPadOp LOG_ERROR(Lib_Pad, "(STUBBED) called"); if (Config::getUseSpecialPad()) { if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) - return -1; + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; } else { if (type != ORBIS_PAD_PORT_TYPE_STANDARD) - return -1; + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; } return 1; // dummy } From 990da7edcc62cae5800bafc8abd92dae91f092cb Mon Sep 17 00:00:00 2001 From: tGecko Date: Wed, 28 Aug 2024 12:10:04 +0200 Subject: [PATCH 076/147] DOCS: Correct and expand windows build instructions (#617) * correct and expand windows build instructions * fix numbering * remove instructions to clone a different branch --- documents/building-windows.md | 39 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/documents/building-windows.md b/documents/building-windows.md index 684e5fe95..21fd87154 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -17,34 +17,53 @@ Note: **ARM64 is not supported!** As of writing, it will not build nor run. The Once you are within the installer: 1. Select `Desktop development with C++` 2. Go to "Individual Components" tab -3. Make sure `C++ Clang Compiler for Windows`, `MSBuild support for LLVM` and `C++ CMake Tools for Windows` are selected +3. Search and select `C++ Clang Compiler for Windows` and `MSBuild support for LLVM` 4. Continue the installation ### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html) Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead. -1. Select Qt for Visual Studio plugin -2. Select `msvc2019_64` option or similar. If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `msvc2019_arm64` +1. Under the current, non beta version of Qt (at the time of writing 6.7.2), select the option `MSVC 2019 64-bit` or similar. + If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `MSVC 2019 ARM64` instead. -Go through the installation normally. If you do not know what components to select, just select the newest Qt version it gives you. -If you know what you are doing, you may unselect individual components that eat up too much disk space. + Go through the installation normally. If you know what you are doing, you may unselect individual components that eat up too much disk space. +2. Download and install [Qt Visual Studio Tools](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022) + Once you are finished, you will have to configure Qt within Visual Studio: 1. Tools -> Options -> Qt -> Versions -2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.1\msvc2019_64` +2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.2\msvc2019_64` 3. Enable the default checkmark on the new version you just created. ### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win) Go through the Git for Windows installation as normal -### Compiling with Visual Studio GUI +### Cloning the source code 1. Open Git for Windows, navigate to a place where you want to store the shadPS4 source code folder -2. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` -3. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` -4. Build -> Build All +2. Clone the repository by running + `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` + +### Compiling with Visual Studio GUI + +1. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` +2. Change x64-Clang-Debug to x64-Clang-Release if you want a regular, non-debug build. +3. If you want to build shadPS4 with the Qt Gui: + 1. Click x64-Clang-Release and select "Manage Configurations" + 2. Look for "CMake command arguments" and add to the text field + `-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.7.2\msvc2019_64` + (Change Qt path if you've installed it to non-default path) + 3. Press CTRL+S to save and wait a moment for CMake generation +4. Change the project to build to shadps4.exe +5. Build -> Build All + +Your shadps4.exe will be in `c:\path\to\source\Build\x64-Clang-Release\` + +To automatically populate the necessary files to run shadPS4.exe, run in a command prompt or terminal: +`C:\Qt\6.7.2\msvc2019_64\bin\windeployqt.exe c:\path\to\shadps4.exe` +(Change Qt path if you've installed it to non-default path) ## Option 2: MSYS2/MinGW From 9d59ea06c784cef14c62fc79170c66995e90d410 Mon Sep 17 00:00:00 2001 From: InvoxiPlayGames Date: Wed, 28 Aug 2024 11:10:20 +0100 Subject: [PATCH 077/147] clang-format fix: scePadOpenExt --- src/core/libraries/pad/pad.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index c75e71dfe..5bf9c3af8 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -257,7 +257,8 @@ int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenP return 1; // dummy } -int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, const OrbisPadOpenExtParam* pParam) { +int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, + const OrbisPadOpenExtParam* pParam) { LOG_ERROR(Lib_Pad, "(STUBBED) called"); if (Config::getUseSpecialPad()) { if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) From 9f4e55a8e7caf5c2127f1da366b36fdf6aa6df08 Mon Sep 17 00:00:00 2001 From: 0xsegf4ult Date: Wed, 28 Aug 2024 12:10:21 +0200 Subject: [PATCH 078/147] shader_recompiler: constant propagation bitwise operations + S_CMPK_EQ_U32 fix (#613) * rebase on main branch impl of V_LSHL_B64 * remove V_LSHR_B64 * fix S_CMPK_EQ_u32 * fix conflicts * fix broken merge * remove duplicate cases * remove duplicate declaration --- .../backend/spirv/emit_spirv_instructions.h | 1 + .../backend/spirv/emit_spirv_integer.cpp | 7 +++++++ .../frontend/translate/scalar_alu.cpp | 2 +- src/shader_recompiler/ir/ir_emitter.cpp | 14 ++++++++++++-- src/shader_recompiler/ir/ir_emitter.h | 2 +- src/shader_recompiler/ir/opcodes.inc | 1 + .../ir/passes/constant_propagation_pass.cpp | 6 ++++++ 7 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index dd3d8fae9..ce4d3f137 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -286,6 +286,7 @@ Id EmitShiftRightLogical64(EmitContext& ctx, Id base, Id shift); Id EmitShiftRightArithmetic32(EmitContext& ctx, Id base, Id shift); Id EmitShiftRightArithmetic64(EmitContext& ctx, Id base, Id shift); Id EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); +Id EmitBitwiseAnd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitBitwiseOr64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index f20c4fac2..a9becb1eb 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -139,6 +139,13 @@ Id EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { return result; } +Id EmitBitwiseAnd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { + const Id result{ctx.OpBitwiseAnd(ctx.U64, a, b)}; + SetZeroFlag(ctx, inst, result); + SetSignFlag(ctx, inst, result); + return result; +} + Id EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { const Id result{ctx.OpBitwiseOr(ctx.U32[1], a, b)}; SetZeroFlag(ctx, inst, result); diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 50a550d44..7914726f4 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -472,7 +472,7 @@ void Translator::S_MIN_U32(const GcnInst& inst) { void Translator::S_CMPK_EQ_U32(const GcnInst& inst) { const s32 simm16 = inst.control.sopk.simm; - const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src0{GetSrc(inst.dst[0])}; const IR::U32 src1{ir.Imm32(simm16)}; ir.SetScc(ir.IEqual(src0, src1)); } diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index a65e538cf..65de98b7e 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1115,8 +1115,18 @@ U32U64 IREmitter::ShiftRightArithmetic(const U32U64& base, const U32& shift) { } } -U32 IREmitter::BitwiseAnd(const U32& a, const U32& b) { - return Inst(Opcode::BitwiseAnd32, a, b); +U32U64 IREmitter::BitwiseAnd(const U32U64& a, const U32U64& b) { + if (a.Type() != b.Type()) { + UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); + } + switch (a.Type()) { + case Type::U32: + return Inst(Opcode::BitwiseAnd32, a, b); + case Type::U64: + return Inst(Opcode::BitwiseAnd64, a, b); + default: + ThrowInvalidType(a.Type()); + } } U32U64 IREmitter::BitwiseOr(const U32U64& a, const U32U64& b) { diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 8f806eb50..a60f4c288 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -195,7 +195,7 @@ public: [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift); [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift); - [[nodiscard]] U32 BitwiseAnd(const U32& a, const U32& b); + [[nodiscard]] U32U64 BitwiseAnd(const U32U64& a, const U32U64& b); [[nodiscard]] U32U64 BitwiseOr(const U32U64& a, const U32U64& b); [[nodiscard]] U32 BitwiseXor(const U32& a, const U32& b); [[nodiscard]] U32 BitFieldInsert(const U32& base, const U32& insert, const U32& offset, diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 26da00bbd..a49ea1c77 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -260,6 +260,7 @@ OPCODE(ShiftRightLogical64, U64, U64, OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) OPCODE(ShiftRightArithmetic64, U64, U64, U32, ) OPCODE(BitwiseAnd32, U32, U32, U32, ) +OPCODE(BitwiseAnd64, U64, U64, U64, ) OPCODE(BitwiseOr32, U32, U32, U32, ) OPCODE(BitwiseOr64, U64, U64, U64, ) OPCODE(BitwiseXor32, U32, U32, U32, ) diff --git a/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp index b0d9dcc45..87a069338 100644 --- a/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp @@ -352,9 +352,15 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { case IR::Opcode::BitwiseAnd32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a & b; }); return; + case IR::Opcode::BitwiseAnd64: + FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a & b; }); + return; case IR::Opcode::BitwiseOr32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a | b; }); return; + case IR::Opcode::BitwiseOr64: + FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a | b; }); + return; case IR::Opcode::BitwiseXor32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a ^ b; }); return; From 8192eaa668d6a1ba4b70dd3be01fbf6378ea136e Mon Sep 17 00:00:00 2001 From: Vinicius Rangel Date: Wed, 28 Aug 2024 07:11:55 -0300 Subject: [PATCH 079/147] video_core: re-enable culling (#551) --- src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 95d3a4b2d..5623e431c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -94,7 +94,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul .depthClampEnable = false, .rasterizerDiscardEnable = false, .polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode), - .cullMode = vk::CullModeFlagBits::eNone /*LiverpoolToVK::CullMode(key.cull_mode)*/, + .cullMode = LiverpoolToVK::CullMode(key.cull_mode), .frontFace = key.front_face == Liverpool::FrontFace::Clockwise ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise, From da966bedfdffb039069b496c0274e4b0bfbaf6e4 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 28 Aug 2024 03:13:33 -0700 Subject: [PATCH 080/147] kernel: Reimplement POSIX semaphores using std::counting_semaphore. (#600) --- CMakeLists.txt | 4 - .../libraries/kernel/thread_management.cpp | 135 +++++++++--------- src/core/libraries/kernel/thread_management.h | 7 + 3 files changed, 78 insertions(+), 68 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6450eaf15..04740784b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,10 +95,6 @@ check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMED if(HAVE_PTHREAD_MUTEX_TIMEDLOCK OR WIN32) add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK) endif() -check_symbol_exists(sem_timedwait "semaphore.h" HAVE_SEM_TIMEDWAIT) -if(HAVE_SEM_TIMEDWAIT OR WIN32) - add_compile_options(-DHAVE_SEM_TIMEDWAIT) -endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") # libc++ requires -fexperimental-library to enable std::jthread and std::stop_token support. diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 567ac867e..605d0d29f 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include -#include #include "common/alignment.h" #include "common/assert.h" #include "common/error.h" @@ -1374,90 +1374,97 @@ int PS4_SYSV_ABI posix_pthread_detach(ScePthread thread) { return pthread_detach(thread->pth); } -int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { - int result = sem_init(sem, pshared, value); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_init(PthreadSemInternal** sem, int pshared, unsigned int value) { + if (value > ORBIS_KERNEL_SEM_VALUE_MAX) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if (sem != nullptr) { + *sem = new PthreadSemInternal{ + .semaphore = std::counting_semaphore{value}, + .value = {static_cast(value)}, + }; + } + return 0; } -int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { - int result = sem_wait(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_wait(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + (*sem)->semaphore.acquire(); + --(*sem)->value; + return 0; } -int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { - int result = sem_trywait(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_trywait(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if (!(*sem)->semaphore.try_acquire()) { + SetPosixErrno(EAGAIN); + return -1; + } + --(*sem)->value; + return 0; } -#ifndef HAVE_SEM_TIMEDWAIT -int sem_timedwait(sem_t* sem, const struct timespec* abstime) { - int rc; - while ((rc = sem_trywait(sem)) == EAGAIN) { - struct timespec curr_time; - clock_gettime(CLOCK_REALTIME, &curr_time); - - s64 remaining_ns = 0; - remaining_ns += - (static_cast(abstime->tv_sec) - static_cast(curr_time.tv_sec)) * 1000000000L; - remaining_ns += static_cast(abstime->tv_nsec) - static_cast(curr_time.tv_nsec); - - if (remaining_ns <= 0) { - return ETIMEDOUT; - } - - struct timespec sleep_time; - sleep_time.tv_sec = 0; - if (remaining_ns < 5000000L) { - sleep_time.tv_nsec = remaining_ns; - } else { - sleep_time.tv_nsec = 5000000; - } - - nanosleep(&sleep_time, nullptr); +int PS4_SYSV_ABI posix_sem_timedwait(PthreadSemInternal** sem, const timespec* t) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return rc; -} -#endif -int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { - int result = sem_timedwait(sem, t); - if (result == -1) { - SetPosixErrno(errno); + using std::chrono::duration_cast; + using std::chrono::nanoseconds; + using std::chrono::seconds; + using std::chrono::system_clock; + + const system_clock::time_point time{ + duration_cast(seconds{t->tv_sec} + nanoseconds{t->tv_nsec})}; + if (!(*sem)->semaphore.try_acquire_until(time)) { + SetPosixErrno(ETIMEDOUT); + return -1; } - return result; + --(*sem)->value; + return 0; } -int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { - int result = sem_post(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_post(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if ((*sem)->value == ORBIS_KERNEL_SEM_VALUE_MAX) { + SetPosixErrno(EOVERFLOW); + return -1; + } + ++(*sem)->value; + (*sem)->semaphore.release(); + return 0; } -int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { - int result = sem_destroy(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_destroy(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + delete *sem; + *sem = nullptr; + return 0; } -int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) { - int result = sem_getvalue(sem, sval); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_getvalue(PthreadSemInternal** sem, int* sval) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if (sval) { + *sval = (*sem)->value; + } + return 0; } int PS4_SYSV_ABI posix_pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* size) { diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index 3679af84f..27cd7929a 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ namespace Libraries::Kernel { constexpr int ORBIS_KERNEL_PRIO_FIFO_DEFAULT = 700; constexpr int ORBIS_KERNEL_PRIO_FIFO_HIGHEST = 256; constexpr int ORBIS_KERNEL_PRIO_FIFO_LOWEST = 767; +constexpr int ORBIS_KERNEL_SEM_VALUE_MAX = 0x7FFFFFFF; constexpr int ORBIS_PTHREAD_MUTEX_ERRORCHECK = 1; constexpr int ORBIS_PTHREAD_MUTEX_RECURSIVE = 2; @@ -109,6 +111,11 @@ struct PthreadRwInternal { std::string name; }; +struct PthreadSemInternal { + std::counting_semaphore semaphore; + std::atomic value; +}; + class PThreadPool { public: ScePthread Create(); From 4a6ce1e0d6e3cc7497a600dd9a62d68cbbe3422f Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 28 Aug 2024 03:36:15 -0700 Subject: [PATCH 081/147] crypto: Fix deallocation of key data while in use. --- src/core/crypto/crypto.cpp | 61 ++-- src/core/crypto/crypto.h | 4 - src/core/crypto/keys.h | 650 +++++++++++++++---------------------- 3 files changed, 296 insertions(+), 419 deletions(-) diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp index fc64edc2d..aa1c96724 100644 --- a/src/core/crypto/crypto.cpp +++ b/src/core/crypto/crypto.cpp @@ -6,18 +6,18 @@ CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() { CryptoPP::InvertibleRSAFunction params; - params.SetPrime1(CryptoPP::Integer(pkg_derived_key3_keyset.Prime1, 0x80)); - params.SetPrime2(CryptoPP::Integer(pkg_derived_key3_keyset.Prime2, 0x80)); + params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80)); + params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80)); - params.SetPublicExponent(CryptoPP::Integer(pkg_derived_key3_keyset.PublicExponent, 4)); - params.SetPrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.PrivateExponent, 0x100)); + params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4)); + params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100)); - params.SetModPrime1PrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.Exponent1, 0x80)); - params.SetModPrime2PrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.Exponent2, 0x80)); + params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80)); + params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80)); - params.SetModulus(CryptoPP::Integer(pkg_derived_key3_keyset.Modulus, 0x100)); + params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100)); params.SetMultiplicativeInverseOfPrime2ModPrime1( - CryptoPP::Integer(pkg_derived_key3_keyset.Coefficient, 0x80)); + CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80)); CryptoPP::RSA::PrivateKey privateKey(params); @@ -26,18 +26,18 @@ CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() { CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() { CryptoPP::InvertibleRSAFunction params; - params.SetPrime1(CryptoPP::Integer(FakeKeyset_keyset.Prime1, 0x80)); - params.SetPrime2(CryptoPP::Integer(FakeKeyset_keyset.Prime2, 0x80)); + params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80)); + params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80)); - params.SetPublicExponent(CryptoPP::Integer(FakeKeyset_keyset.PublicExponent, 4)); - params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.PrivateExponent, 0x100)); + params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4)); + params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100)); - params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.Exponent1, 0x80)); - params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.Exponent2, 0x80)); + params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80)); + params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80)); - params.SetModulus(CryptoPP::Integer(FakeKeyset_keyset.Modulus, 0x100)); + params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100)); params.SetMultiplicativeInverseOfPrime2ModPrime1( - CryptoPP::Integer(FakeKeyset_keyset.Coefficient, 0x80)); + CryptoPP::Integer(FakeKeyset::Coefficient, 0x80)); CryptoPP::RSA::PrivateKey privateKey(params); @@ -46,25 +46,22 @@ CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() { CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() { CryptoPP::InvertibleRSAFunction params; - params.SetPrime1( - CryptoPP::Integer(DebugRifKeyset_keyset.Prime1, sizeof(DebugRifKeyset_keyset.Prime1))); - params.SetPrime2( - CryptoPP::Integer(DebugRifKeyset_keyset.Prime2, sizeof(DebugRifKeyset_keyset.Prime2))); + params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1))); + params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2))); - params.SetPublicExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PublicExponent, - sizeof(DebugRifKeyset_keyset.PublicExponent))); - params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent, - sizeof(DebugRifKeyset_keyset.PrivateExponent))); + params.SetPublicExponent( + CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent))); + params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent, + sizeof(DebugRifKeyset::PrivateExponent))); - params.SetModPrime1PrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.Exponent1, - sizeof(DebugRifKeyset_keyset.Exponent1))); - params.SetModPrime2PrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.Exponent2, - sizeof(DebugRifKeyset_keyset.Exponent2))); + params.SetModPrime1PrivateExponent( + CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1))); + params.SetModPrime2PrivateExponent( + CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2))); - params.SetModulus( - CryptoPP::Integer(DebugRifKeyset_keyset.Modulus, sizeof(DebugRifKeyset_keyset.Modulus))); - params.SetMultiplicativeInverseOfPrime2ModPrime1(CryptoPP::Integer( - DebugRifKeyset_keyset.Coefficient, sizeof(DebugRifKeyset_keyset.Coefficient))); + params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus))); + params.SetMultiplicativeInverseOfPrime2ModPrime1( + CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient))); CryptoPP::RSA::PrivateKey privateKey(params); diff --git a/src/core/crypto/crypto.h b/src/core/crypto/crypto.h index 0c5bc9955..83249bd7d 100644 --- a/src/core/crypto/crypto.h +++ b/src/core/crypto/crypto.h @@ -17,10 +17,6 @@ class Crypto { public: - PkgDerivedKey3Keyset pkg_derived_key3_keyset; - FakeKeyset FakeKeyset_keyset; - DebugRifKeyset DebugRifKeyset_keyset; - CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init(); CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init(); CryptoPP::RSA::PrivateKey DebugRifKeyset_init(); diff --git a/src/core/crypto/keys.h b/src/core/crypto/keys.h index 58466b764..441082481 100644 --- a/src/core/crypto/keys.h +++ b/src/core/crypto/keys.h @@ -7,415 +7,299 @@ class FakeKeyset { public: // Constructor - const CryptoPP::byte* Exponent1; + static constexpr CryptoPP::byte Exponent1[] = { + 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7, + 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9, + 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6, + 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6, + 0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC, + 0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF, + 0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8, + 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E, + 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25}; // exponent2 = d mod (q - 1) - const CryptoPP::byte* Exponent2; + static constexpr CryptoPP::byte Exponent2[] = { + 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60, + 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8, + 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75, + 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18, + 0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16, + 0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C, + 0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD, + 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA, + 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D}; // e - const CryptoPP::byte* PublicExponent; + static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1}; // (InverseQ)(q) = 1 mod p - const CryptoPP::byte* Coefficient; + static constexpr CryptoPP::byte Coefficient[] = { + 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD, + 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D, + 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B, + 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69, + 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15, + 0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8, + 0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6, + 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67, + 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5}; // n = p * q - const CryptoPP::byte* Modulus; + static constexpr CryptoPP::byte Modulus[] = { + 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E, + 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D, + 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B, + 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7, + 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C, + 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33, + 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01, + 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A, + 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96, + 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80, + 0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F, + 0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53, + 0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22, + 0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F, + 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40, + 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9, + 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E, + 0x27}; // p - const CryptoPP::byte* Prime1; + static constexpr CryptoPP::byte Prime1[] = { + 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35, + 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24, + 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9, + 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F, + 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C, + 0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A, + 0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40, + 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89, + 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D}; // q - const CryptoPP::byte* Prime2; - const CryptoPP::byte* PrivateExponent; - - // Constructor - FakeKeyset() { - // Initialize PrivateExponent - PrivateExponent = new CryptoPP::byte[0x100]{ - 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, - 0xFA, 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, - 0xDB, 0xFD, 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, - 0xB1, 0x22, 0x5C, 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, - 0xD1, 0x49, 0x2C, 0x8F, 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, - 0xD2, 0x21, 0x28, 0x83, 0x09, 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, - 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14, 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, - 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77, 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, - 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90, 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, - 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22, 0x58, 0xD5, 0x43, 0x82, 0x49, - 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0, 0xCE, 0x3D, 0xDF, 0xF4, - 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93, 0x23, 0xDB, 0xBA, - 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5, 0x71, 0x67, - 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5, 0x6C, - 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1, - 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, - 0x85, 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, - 0xEC, 0x39, 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, - 0x79, 0x89, 0xC6, 0xB1}; - - // Initialize Exponent1 - Exponent1 = new CryptoPP::byte[0x80]{ - 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, - 0xD2, 0xC7, 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, - 0x1D, 0xB7, 0xBC, 0xB9, 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, - 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6, 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, - 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6, 0x5A, 0xA0, 0xBE, 0x05, 0x70, - 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC, 0xC1, 0x62, 0x3D, - 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF, 0x08, - 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, - 0xE8, 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, - 0xF0, 0x17, 0x1E, 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25 - - }; - - Exponent2 = new CryptoPP::byte[0x80]{ - 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, - 0xBF, 0x60, 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, - 0xA7, 0xBF, 0xD0, 0xE8, 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, - 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75, 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, - 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18, 0x96, 0x80, 0x11, 0xDB, 0x68, - 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16, 0x0D, 0x3E, 0x12, - 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C, 0xD6, - 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, - 0xAD, 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, - 0xBC, 0x6C, 0xAA, 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D}; - - PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1}; - - Coefficient = new CryptoPP::byte[0x80]{ - 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, - 0x55, 0xFD, 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, - 0xA0, 0x16, 0x27, 0x3D, 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, - 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B, 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, - 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69, 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, - 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15, 0x07, 0x15, 0x6E, - 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8, 0x0A, - 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, - 0xA6, 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, - 0xDA, 0xF1, 0x67, 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5}; - - Modulus = new CryptoPP::byte[0x100]{ - 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, - 0x0E, 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, - 0x35, 0x9D, 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, - 0x02, 0x68, 0x2B, 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, - 0x48, 0x03, 0xC9, 0xE7, 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, - 0xE7, 0x9D, 0xFF, 0x77, 0x0C, 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, - 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33, 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, - 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01, 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, - 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A, 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, - 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96, 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, - 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80, 0x69, 0x2E, 0xFE, 0xFF, - 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F, 0xBB, 0xB7, 0x79, - 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53, 0xC2, 0x69, - 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22, 0xFD, - 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F, - 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, - 0x40, 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, - 0xD1, 0xF9, 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, - 0x7C, 0xBD, 0x3E, 0x27}; - - Prime1 = new CryptoPP::byte[0x80]{ - 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, - 0xE4, 0x35, 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, - 0x19, 0xD1, 0x04, 0x24, 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, - 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9, 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, - 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F, 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, - 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C, 0x21, 0x33, 0x12, - 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A, 0x1B, - 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, - 0x40, 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, - 0xC9, 0x31, 0x89, 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D}; - - Prime2 = new CryptoPP::byte[0x80]{ - 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, - 0xA8, 0x97, 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, - 0x8E, 0x57, 0xEF, 0xF0, 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, - 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D, 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, - 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47, 0x97, 0xCC, 0x90, 0x39, 0x15, - 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92, 0xBE, 0x97, 0xBF, - 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A, 0x7E, - 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, - 0x79, 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, - 0x2A, 0xFE, 0x51, 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23}; - }; - - // Destructor - ~FakeKeyset() { - delete[] PrivateExponent; - delete[] Exponent1; - delete[] Exponent2; - delete[] PublicExponent; - delete[] Coefficient; - delete[] Modulus; - delete[] Prime1; - delete[] Prime2; - }; + static constexpr CryptoPP::byte Prime2[] = { + 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97, + 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0, + 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D, + 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47, + 0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92, + 0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A, + 0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79, + 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51, + 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23}; + static constexpr CryptoPP::byte PrivateExponent[] = { + 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA, + 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD, + 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C, + 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F, + 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09, + 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14, + 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77, + 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90, + 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22, + 0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0, + 0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93, + 0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5, + 0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5, + 0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1, + 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85, + 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39, + 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6, + 0xB1}; }; class DebugRifKeyset { public: // std::uint8_t* PrivateExponent; - const CryptoPP::byte* Exponent1; + static constexpr CryptoPP::byte Exponent1[] = { + 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56, + 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C, + 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F, + 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87, + 0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F, + 0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6, + 0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69, + 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6, + 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9}; // exponent2 = d mod (q - 1) - const CryptoPP::byte* Exponent2; + static constexpr CryptoPP::byte Exponent2[] = { + 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44, + 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B, + 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91, + 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88, + 0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B, + 0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7, + 0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF, + 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F, + 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05}; // e - const CryptoPP::byte* PublicExponent; + static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01}; // (InverseQ)(q) = 1 mod p - const CryptoPP::byte* Coefficient; + static constexpr CryptoPP::byte Coefficient[] = { + 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C, + 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4, + 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4, + 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD, + 0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A, + 0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7, + 0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75, + 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A, + 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB}; // n = p * q - const CryptoPP::byte* Modulus; + static constexpr CryptoPP::byte Modulus[] = { + 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A, + 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB, + 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B, + 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD, + 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53, + 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F, + 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30, + 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A, + 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4, + 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B, + 0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E, + 0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87, + 0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19, + 0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A, + 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C, + 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58, + 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64, + 0xC1}; // p - const CryptoPP::byte* Prime1; + static constexpr CryptoPP::byte Prime1[] = { + 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6, + 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34, + 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8, + 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5, + 0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5, + 0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8, + 0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39, + 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F, + 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05}; // q - const CryptoPP::byte* Prime2; - const CryptoPP::byte* PrivateExponent; - - // Constructor - DebugRifKeyset() { - // Initialize PrivateExponent - PrivateExponent = new CryptoPP::byte[0x100]{ - 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, - 0x01, 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, - 0x64, 0xEC, 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, - 0xC6, 0xA3, 0x73, 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, - 0x23, 0xD8, 0x1B, 0x61, 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, - 0x03, 0x4A, 0xBF, 0xFE, 0xF9, 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, - 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28, 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, - 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36, 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, - 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E, 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, - 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14, 0x3D, 0x90, 0xE4, 0xDE, 0x5D, - 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97, 0x2D, 0x89, 0x2A, 0x51, - 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F, 0xA1, 0x8A, 0x69, - 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C, 0xC7, 0xE8, - 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61, 0xB9, - 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49, - 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, - 0xB3, 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, - 0xAF, 0x6E, 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, - 0xF1, 0xCF, 0x14, 0xA5}; - - // Initialize Exponent1 - Exponent1 = new CryptoPP::byte[0x80]{ - 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, - 0xB7, 0x56, 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, - 0x7F, 0x49, 0xA2, 0x9C, 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, - 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F, 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, - 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87, 0x98, 0x78, 0xBF, 0x26, 0xB5, - 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F, 0xFA, 0x1C, 0x64, - 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6, 0x9C, - 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, - 0x69, 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, - 0xA4, 0x10, 0xB6, 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9 - - }; - - Exponent2 = new CryptoPP::byte[0x80]{ - 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, - 0xDB, 0x44, 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, - 0xC5, 0xFC, 0xFE, 0x4B, 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, - 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91, 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, - 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88, 0x5F, 0x71, 0x03, 0x99, 0x79, - 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B, 0x30, 0x74, 0x57, - 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7, 0x6B, - 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, - 0xDF, 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, - 0x22, 0xD7, 0x7F, 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05}; - - PublicExponent = new CryptoPP::byte[4]{0x00, 0x01, 0x00, 0x01}; - - Coefficient = new CryptoPP::byte[0x80]{ - 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, - 0x94, 0x6C, 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, - 0xEB, 0x2C, 0xFB, 0xD4, 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, - 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4, 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, - 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD, 0xE2, 0xBD, 0x94, 0xA6, 0x2B, - 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A, 0x6C, 0xBF, 0x3C, - 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7, 0x3C, - 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, - 0x75, 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, - 0xC1, 0x8A, 0x4A, 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB}; - - Modulus = new CryptoPP::byte[0x100]{ - 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, - 0x8A, 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, - 0x02, 0xBB, 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, - 0x5A, 0xE0, 0x3B, 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, - 0x34, 0x9A, 0x5B, 0xAD, 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, - 0xB3, 0xDA, 0xB3, 0xB2, 0x53, 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, - 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F, 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, - 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30, 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, - 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A, 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, - 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4, 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, - 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B, 0x32, 0x03, 0xA3, 0x09, - 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E, 0x49, 0xF8, 0xB5, - 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87, 0xED, 0x19, - 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19, 0x3C, - 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A, - 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, - 0x7C, 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, - 0x1B, 0x58, 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, - 0x42, 0x9F, 0x64, 0xC1}; - - Prime1 = new CryptoPP::byte[0x80]{ - 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, - 0xC4, 0xB6, 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, - 0x9C, 0x01, 0x5E, 0x34, 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, - 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8, 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, - 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5, 0x51, 0x3E, 0x7B, 0xE3, 0x53, - 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5, 0x35, 0x0E, 0x6F, - 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8, 0xD7, - 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, - 0x39, 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, - 0x35, 0x48, 0x6F, 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05}; - - Prime2 = new CryptoPP::byte[0x80]{ - 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, - 0x12, 0x9C, 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, - 0xFD, 0xF0, 0xAD, 0x38, 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, - 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D, 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, - 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2, 0x08, 0x92, 0xA7, 0x85, 0xF5, - 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31, 0x20, 0x34, 0x49, - 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE, 0x9A, - 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, - 0x81, 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, - 0x54, 0x91, 0x6B, 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D}; - }; - - // Destructor - ~DebugRifKeyset() { - delete[] PrivateExponent; - delete[] Exponent1; - delete[] Exponent2; - delete[] PublicExponent; - delete[] Coefficient; - delete[] Modulus; - delete[] Prime1; - delete[] Prime2; - }; + static constexpr CryptoPP::byte Prime2[] = { + 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C, + 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38, + 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D, + 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2, + 0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31, + 0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE, + 0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81, + 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B, + 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D}; + static constexpr CryptoPP::byte PrivateExponent[] = { + 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01, + 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC, + 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73, + 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61, + 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9, + 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28, + 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36, + 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E, + 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14, + 0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97, + 0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F, + 0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C, + 0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61, + 0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49, + 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3, + 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E, + 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14, + 0xA5}; }; class PkgDerivedKey3Keyset { public: // std::uint8_t* PrivateExponent; - const CryptoPP::byte* Exponent1; + static constexpr CryptoPP::byte Exponent1[] = { + 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1, + 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7, + 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36, + 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43, + 0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0, + 0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E, + 0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D, + 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC, + 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13}; // exponent2 = d mod (q - 1) - const CryptoPP::byte* Exponent2; + static constexpr CryptoPP::byte Exponent2[] = { + 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5, + 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71, + 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51, + 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D, + 0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00, + 0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98, + 0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1, + 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57, + 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37}; // e - const CryptoPP::byte* PublicExponent; + static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1}; // (InverseQ)(q) = 1 mod p - const CryptoPP::byte* Coefficient; + static constexpr CryptoPP::byte Coefficient[] = { + 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42, + 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3, + 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE, + 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C, + 0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF, + 0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D, + 0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17, + 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6, + 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3}; // n = p * q - const CryptoPP::byte* Modulus; + static constexpr CryptoPP::byte Modulus[] = { + 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27, + 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb, + 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb, + 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef, + 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a, + 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99, + 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d, + 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44, + 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c, + 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65, + 0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6, + 0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65, + 0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f, + 0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01, + 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09, + 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95, + 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3, + 0xc1}; // p - const CryptoPP::byte* Prime1; + static constexpr CryptoPP::byte Prime1[] = { + 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D, + 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42, + 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE, + 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52, + 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D, + 0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23, + 0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80, + 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE, + 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB}; // q - const CryptoPP::byte* Prime2; - const CryptoPP::byte* PrivateExponent; - - // Constructor - PkgDerivedKey3Keyset() { - Prime1 = new CryptoPP::byte[0x80]{ - 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, - 0xB3, 0x4D, 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, - 0xC7, 0x3F, 0xC3, 0x42, 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, - 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE, 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, - 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52, 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, - 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D, 0xB3, 0xCB, 0x3C, - 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23, 0x63, - 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, - 0x80, 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, - 0x89, 0x8E, 0xAE, 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB}; - - Prime2 = new CryptoPP::byte[0x80]{ - 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, - 0xD9, 0x40, 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, - 0xF9, 0xC3, 0x61, 0x0F, 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, - 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89, 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, - 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9, 0xB4, 0xC7, 0xB5, 0x1B, 0x05, - 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E, 0x5C, 0xFB, 0x92, - 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C, 0x07, - 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, - 0x53, 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, - 0x01, 0xEE, 0x10, 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73}; - PrivateExponent = new CryptoPP::byte[0x100]{ - 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, - 0xB3, 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, - 0xDF, 0xC1, 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, - 0x64, 0xB0, 0xBE, 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, - 0xD7, 0x76, 0x01, 0x41, 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, - 0x5A, 0xE2, 0xA0, 0xBC, 0x2D, 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, - 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F, 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, - 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3, 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, - 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB, 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, - 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD, 0x35, 0xE1, 0x20, 0xF8, 0xAD, - 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB, 0x52, 0x08, 0xFD, 0x06, - 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F, 0xAA, 0x10, 0x30, - 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80, 0xEC, 0x8F, - 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65, 0x3E, - 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64, - 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, - 0x1A, 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, - 0xD9, 0x08, 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, - 0xFF, 0x77, 0xFC, 0x0D}; - Exponent1 = new CryptoPP::byte[0x80]{ - 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, - 0x45, 0xD1, 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, - 0xAB, 0x6E, 0x2A, 0xA7, 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, - 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36, 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, - 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43, 0x2A, 0xC0, 0xE5, 0x98, 0xC9, - 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0, 0x6D, 0x88, 0xF2, - 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E, 0xF6, - 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, - 0x3D, 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, - 0x16, 0xC4, 0xAC, 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13}; - Exponent2 = new CryptoPP::byte[0x80]{ - 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, - 0x95, 0xD5, 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, - 0xBB, 0xBF, 0x89, 0x71, 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, - 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51, 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, - 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D, 0x42, 0xD8, 0x03, 0xB7, 0x68, - 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00, 0xC8, 0xF5, 0xEF, - 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98, 0xC0, - 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, - 0xA1, 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, - 0x31, 0x21, 0x57, 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37}; - Coefficient = new CryptoPP::byte[0x80]{ - 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, - 0xAA, 0x42, 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, - 0x6E, 0x3E, 0x32, 0xE3, 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, - 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE, 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, - 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C, 0x26, 0xC8, 0x25, 0xFF, 0x34, - 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF, 0xEB, 0xBA, 0xE3, - 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D, 0xE9, - 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, - 0x17, 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, - 0x62, 0xA7, 0xD6, 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3}; - Modulus = new CryptoPP::byte[0x100]{ - 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, - 0x27, 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, - 0x8c, 0xfb, 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, - 0xcd, 0x2a, 0xbb, 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, - 0x8e, 0xda, 0x4b, 0xef, 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, - 0x32, 0x6a, 0x58, 0x31, 0x2a, 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, - 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99, 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, - 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d, 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, - 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44, 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, - 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c, 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, - 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65, 0x47, 0x84, 0x1e, 0xe5, - 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6, 0x40, 0x98, 0x2c, - 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65, 0xc1, 0xaa, - 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f, 0x61, - 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01, - 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, - 0x09, 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, - 0x0b, 0x95, 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, - 0xf9, 0xc9, 0xa3, 0xc1}; - PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1}; - }; - - // Destructor - ~PkgDerivedKey3Keyset() { - delete[] Prime1; - delete[] Prime2; - delete[] PrivateExponent; - delete[] Exponent1; - delete[] Exponent2; - delete[] Coefficient; - delete[] Modulus; - delete[] PublicExponent; - }; + static constexpr CryptoPP::byte Prime2[] = { + 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40, + 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F, + 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89, + 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9, + 0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E, + 0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C, + 0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53, + 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10, + 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73}; + static constexpr CryptoPP::byte PrivateExponent[] = { + 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3, + 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1, + 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE, + 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41, + 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D, + 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F, + 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3, + 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB, + 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD, + 0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB, + 0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F, + 0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80, + 0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65, + 0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64, + 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A, + 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08, + 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC, + 0x0D}; }; \ No newline at end of file From 905d49fd9691cab31e0a66eb94e3e0181679dbb1 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 28 Aug 2024 03:42:53 -0700 Subject: [PATCH 082/147] memory: Fixes for direct memory allocation. (#615) * memory: Size direct memory based on requested flexible memory. * memory: Guard against OrbisProcParam without an OrbisKernelMemParam. * memory: Account for alignment in direct memory suitability checks and add more debugging. --- .../libraries/kernel/memory_management.cpp | 9 ++-- src/core/libraries/kernel/memory_management.h | 2 +- src/core/linker.cpp | 18 +++++--- src/core/memory.cpp | 44 +++++++++++++++---- src/core/memory.h | 9 ++-- 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index ab6aa3985..3fc837d96 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -15,7 +15,8 @@ namespace Libraries::Kernel { u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() { LOG_WARNING(Kernel_Vmm, "called"); - return SCE_KERNEL_MAIN_DMEM_SIZE; + const auto* memory = Core::Memory::Instance(); + return memory->GetTotalDirectSize(); } int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, @@ -52,8 +53,8 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, s64* physAddrOut) { - return sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, len, alignment, memoryType, - physAddrOut); + const auto searchEnd = static_cast(sceKernelGetDirectMemorySize()); + return sceKernelAllocateDirectMemory(0, searchEnd, len, alignment, memoryType, physAddrOut); } s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) { @@ -78,7 +79,7 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE if (physAddrOut == nullptr || sizeOut == nullptr) { return ORBIS_KERNEL_ERROR_EINVAL; } - if (searchEnd > SCE_KERNEL_MAIN_DMEM_SIZE) { + if (searchEnd > sceKernelGetDirectMemorySize()) { return ORBIS_KERNEL_ERROR_EINVAL; } if (searchEnd <= searchStart) { diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index c9dd86e18..9a447fe8b 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -6,7 +6,7 @@ #include "common/bit_field.h" #include "common/types.h" -constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 4608_MB; // ~ 4.5GB +constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB namespace Libraries::Kernel { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 6f46fdbe3..9783ad96f 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -68,11 +68,19 @@ void Linker::Execute() { } // Configure used flexible memory size. - // if (auto* mem_param = GetProcParam()->mem_param) { - // if (u64* flexible_size = mem_param->flexible_memory_size) { - // memory->SetTotalFlexibleSize(*flexible_size); - // } - // } + if (const auto* proc_param = GetProcParam()) { + if (proc_param->size >= + offsetof(OrbisProcParam, mem_param) + sizeof(OrbisKernelMemParam*)) { + if (const auto* mem_param = proc_param->mem_param) { + if (mem_param->size >= + offsetof(OrbisKernelMemParam, flexible_memory_size) + sizeof(u64*)) { + if (const auto* flexible_size = mem_param->flexible_memory_size) { + memory->SetupMemoryRegions(*flexible_size); + } + } + } + } + } // Init primary thread. Common::SetCurrentThreadName("GAME_MainThread"); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 0feef260b..2722c68a9 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -11,9 +11,11 @@ namespace Core { +constexpr u64 SCE_DEFAULT_FLEXIBLE_MEMORY_SIZE = 448_MB; + MemoryManager::MemoryManager() { - // Insert an area that covers direct memory physical block. - dmem_map.emplace(0, DirectMemoryArea{0, SCE_KERNEL_MAIN_DMEM_SIZE}); + // Set up the direct and flexible memory regions. + SetupMemoryRegions(SCE_DEFAULT_FLEXIBLE_MEMORY_SIZE); // Insert a virtual memory area that covers the entire area we manage. const VAddr system_managed_base = impl.SystemManagedVirtualBase(); @@ -35,6 +37,19 @@ MemoryManager::MemoryManager() { MemoryManager::~MemoryManager() = default; +void MemoryManager::SetupMemoryRegions(u64 flexible_size) { + total_flexible_size = flexible_size; + total_direct_size = SCE_KERNEL_MAIN_DMEM_SIZE - flexible_size; + + // Insert an area that covers direct memory physical block. + // Note that this should never be called after direct memory allocations have been made. + dmem_map.clear(); + dmem_map.emplace(0, DirectMemoryArea{0, total_direct_size}); + + LOG_INFO(Kernel_Vmm, "Configured memory regions: flexible size = {:#x}, direct size = {:#x}", + total_flexible_size, total_direct_size); +} + PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, int memory_type) { std::scoped_lock lk{mutex}; @@ -42,12 +57,17 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, auto dmem_area = FindDmemArea(search_start); const auto is_suitable = [&] { - return dmem_area->second.is_free && dmem_area->second.size >= size; + const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) + : dmem_area->second.base; + const auto alignment_size = aligned_base - dmem_area->second.base; + const auto remaining_size = + dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; + return dmem_area->second.is_free && remaining_size >= size; }; while (!is_suitable() && dmem_area->second.GetEnd() <= search_end) { dmem_area++; } - ASSERT_MSG(is_suitable(), "Unable to find free direct memory area"); + ASSERT_MSG(is_suitable(), "Unable to find free direct memory area: size = {:#x}", size); // Align free position PAddr free_addr = dmem_area->second.base; @@ -333,14 +353,19 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si continue; } - if (dmem_area->second.size > max_size) { - paddr = dmem_area->second.base; - max_size = dmem_area->second.size; + const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) + : dmem_area->second.base; + const auto alignment_size = aligned_base - dmem_area->second.base; + const auto remaining_size = + dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; + if (remaining_size > max_size) { + paddr = aligned_base; + max_size = remaining_size; } dmem_area++; } - *phys_addr_out = alignment > 0 ? Common::AlignUp(paddr, alignment) : paddr; + *phys_addr_out = paddr; *size_out = max_size; return ORBIS_OK; } @@ -418,7 +443,8 @@ MemoryManager::DMemHandle MemoryManager::CarveDmemArea(PAddr addr, size_t size) const PAddr start_in_area = addr - area.base; const PAddr end_in_vma = start_in_area + size; - ASSERT_MSG(end_in_vma <= area.size, "Mapping cannot fit inside free region"); + ASSERT_MSG(end_in_vma <= area.size, "Mapping cannot fit inside free region: size = {:#x}", + size); if (end_in_vma != area.size) { // Split VMA at the end of the allocated region diff --git a/src/core/memory.h b/src/core/memory.h index d58269678..c8638626a 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -130,8 +130,8 @@ public: rasterizer = rasterizer_; } - void SetTotalFlexibleSize(u64 size) { - total_flexible_size = size; + u64 GetTotalDirectSize() const { + return total_direct_size; } u64 GetAvailableFlexibleSize() const { @@ -142,6 +142,8 @@ public: return impl.SystemReservedVirtualBase(); } + void SetupMemoryRegions(u64 flexible_size); + PAddr Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, int memory_type); @@ -217,7 +219,8 @@ private: DMemMap dmem_map; VMAMap vma_map; std::recursive_mutex mutex; - size_t total_flexible_size = 448_MB; + size_t total_direct_size{}; + size_t total_flexible_size{}; size_t flexible_usage{}; Vulkan::Rasterizer* rasterizer{}; }; From 4e6e90dfb9c42151ef9d79493d694068eabc629d Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:48:50 +0200 Subject: [PATCH 083/147] add touchpad support, auto reconnect --- src/core/libraries/pad/pad.cpp | 11 ++++++----- src/input/controller.cpp | 16 ++++++++++++++-- src/input/controller.h | 8 ++++++++ src/sdl_window.cpp | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index 5bf9c3af8..b617f7359 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -309,12 +309,13 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { pData[i].angularVelocity.x = 0.0f; pData[i].angularVelocity.y = 0.0f; pData[i].angularVelocity.z = 0.0f; - pData[i].touchData.touchNum = 0; - pData[i].touchData.touch[0].x = 0; - pData[i].touchData.touch[0].y = 0; + pData[i].touchData.touchNum = (states[i].touchpad[0].state ? 1 : 0) + + (states[i].touchpad[1].state ? 1 : 0); + pData[i].touchData.touch[0].x = states[i].touchpad[0].x; + pData[i].touchData.touch[0].y = states[i].touchpad[0].y; pData[i].touchData.touch[0].id = 1; - pData[i].touchData.touch[1].x = 0; - pData[i].touchData.touch[1].y = 0; + pData[i].touchData.touch[1].x = states[i].touchpad[1].x; + pData[i].touchData.touch[1].y = states[i].touchpad[1].y; pData[i].touchData.touch[1].id = 2; pData[i].connected = connected; pData[i].timestamp = states[i].time; diff --git a/src/input/controller.cpp b/src/input/controller.cpp index 4a3db1633..cb4529a7f 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -132,15 +132,27 @@ bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) { return true; } +void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) { + if (touchIndex < 2) { // DS4 has 2-point multitouch + auto state = GetLastState(); + + state.time = Libraries::Kernel::sceKernelGetProcessTime(); + state.touchpad[touchIndex].state = touchDown; + state.touchpad[touchIndex].x = static_cast(x * 1920); + state.touchpad[touchIndex].y = static_cast(y * 1080); + AddState(state); + } +} + void GameController::TryOpenSDLController() { if (m_sdl_gamepad == nullptr || !SDL_GamepadConnected(m_sdl_gamepad)) { int gamepad_count; SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr; SDL_free(gamepads); - } - SetLightBarRGB(0, 0, 255); + SetLightBarRGB(0, 0, 255); + } } } // namespace Input diff --git a/src/input/controller.h b/src/input/controller.h index ef0991568..cb9fe1726 100644 --- a/src/input/controller.h +++ b/src/input/controller.h @@ -21,10 +21,17 @@ enum class Axis { AxisMax }; +struct TouchpadEntry { + bool state; + u16 x; + u16 y; +}; + struct State { u32 buttonsState = 0; u64 time = 0; int axes[static_cast(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0}; + TouchpadEntry touchpad[2] = {{false, 0, 0}, {false, 0, 0}}; }; inline int GetAxis(int min, int max, int value) { @@ -47,6 +54,7 @@ public: void Axis(int id, Input::Axis axis, int value); void SetLightBarRGB(u8 r, u8 g, u8 b); bool SetVibration(u8 smallMotor, u8 largeMotor); + void SetTouchpadState(int touchIndex, bool touchDown, float x, float y); void TryOpenSDLController(); private: diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index ff44e6c30..b83afd299 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -98,6 +98,11 @@ void WindowSDL::waitEvent() { case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: case SDL_EVENT_GAMEPAD_AXIS_MOTION: + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: onGamepadEvent(&event); break; case SDL_EVENT_QUIT: @@ -299,6 +304,17 @@ void WindowSDL::onGamepadEvent(const SDL_Event* event) { u32 button = 0; Input::Axis axis = Input::Axis::AxisMax; switch (event->type) { + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + controller->TryOpenSDLController(); + break; + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: + controller->SetTouchpadState(event->gtouchpad.finger, + event->type != SDL_EVENT_GAMEPAD_TOUCHPAD_UP, + event->gtouchpad.x, event->gtouchpad.y); + break; case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: button = sdlGamepadToOrbisButton(event->gbutton.button); From 698dade8645fdc542409d6ba1a6d2e1110bbfa11 Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:53:07 +0200 Subject: [PATCH 084/147] * --- src/input/controller.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/input/controller.cpp b/src/input/controller.cpp index cb4529a7f..ed415e232 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -134,12 +134,14 @@ bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) { void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) { if (touchIndex < 2) { // DS4 has 2-point multitouch + std::scoped_lock lock{m_mutex}; auto state = GetLastState(); - state.time = Libraries::Kernel::sceKernelGetProcessTime(); + state.touchpad[touchIndex].state = touchDown; state.touchpad[touchIndex].x = static_cast(x * 1920); state.touchpad[touchIndex].y = static_cast(y * 1080); + AddState(state); } } From 0b24ac6991b8829f2d2dda8c903b0af81bcfb5b5 Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:56:49 +0200 Subject: [PATCH 085/147] actually get rid of that comment --- src/input/controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/controller.cpp b/src/input/controller.cpp index ed415e232..96273555b 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -133,7 +133,7 @@ bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) { } void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) { - if (touchIndex < 2) { // DS4 has 2-point multitouch + if (touchIndex < 2) { std::scoped_lock lock{m_mutex}; auto state = GetLastState(); state.time = Libraries::Kernel::sceKernelGetProcessTime(); From 15fc267f0d8075bbec4c9a68ea878b14dd1c4dda Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:58:37 +0200 Subject: [PATCH 086/147] Update controller.h --- src/input/controller.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/input/controller.h b/src/input/controller.h index cb9fe1726..0a0d663a1 100644 --- a/src/input/controller.h +++ b/src/input/controller.h @@ -22,9 +22,9 @@ enum class Axis { }; struct TouchpadEntry { - bool state; - u16 x; - u16 y; + bool state{}; + u16 x{}; + u16 y{}; }; struct State { From 89bdd3bba20444e1a9627f04b967834d5c8fef02 Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:15:01 +0200 Subject: [PATCH 087/147] it's actually 1920x941 --- src/input/controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/controller.cpp b/src/input/controller.cpp index 96273555b..4de6d83b8 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -140,7 +140,7 @@ void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, f state.touchpad[touchIndex].state = touchDown; state.touchpad[touchIndex].x = static_cast(x * 1920); - state.touchpad[touchIndex].y = static_cast(y * 1080); + state.touchpad[touchIndex].y = static_cast(y * 941); AddState(state); } From 2e2f3bb2c682d0305a69f94b29db93482b051161 Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:22:59 +0200 Subject: [PATCH 088/147] clang format --- src/core/libraries/pad/pad.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index b617f7359..01cc85cca 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -309,8 +309,8 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { pData[i].angularVelocity.x = 0.0f; pData[i].angularVelocity.y = 0.0f; pData[i].angularVelocity.z = 0.0f; - pData[i].touchData.touchNum = (states[i].touchpad[0].state ? 1 : 0) - + (states[i].touchpad[1].state ? 1 : 0); + pData[i].touchData.touchNum = + (states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0); pData[i].touchData.touch[0].x = states[i].touchpad[0].x; pData[i].touchData.touch[0].y = states[i].touchpad[0].y; pData[i].touchData.touch[0].id = 1; From bc661039c541d240c7bb2a4cf6bff9dc66c88c71 Mon Sep 17 00:00:00 2001 From: counter185 <33550839+counter185@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:25:07 +0200 Subject: [PATCH 089/147] get rid of one space --- src/core/libraries/pad/pad.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index 01cc85cca..a0abfdf73 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -309,7 +309,7 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { pData[i].angularVelocity.x = 0.0f; pData[i].angularVelocity.y = 0.0f; pData[i].angularVelocity.z = 0.0f; - pData[i].touchData.touchNum = + pData[i].touchData.touchNum = (states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0); pData[i].touchData.touch[0].x = states[i].touchpad[0].x; pData[i].touchData.touch[0].y = states[i].touchpad[0].y; From 08036d2b49c3ede671afb61c4c230205036a7ddc Mon Sep 17 00:00:00 2001 From: Emulator-Team-2 <38318848+Emulator-Team-2@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:10:23 +0200 Subject: [PATCH 090/147] added data_format=36 and num_format=9 --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 025f311d8..d474cee68 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -296,6 +296,7 @@ std::span GetAllFormats() { vk::Format::eB10G11R11UfloatPack32, vk::Format::eBc1RgbaSrgbBlock, vk::Format::eBc1RgbaUnormBlock, + vk::Format::eBc2SrgbBlock, vk::Format::eBc2UnormBlock, vk::Format::eBc3SrgbBlock, vk::Format::eBc3UnormBlock, @@ -457,6 +458,9 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu } if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eBc7UnormBlock; + } + if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Srgb) { + return vk::Format::eBc2SrgbBlock; } if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eBc2UnormBlock; From 6f938a10ce8cd6027afe61c4a9985efac5e1bfb5 Mon Sep 17 00:00:00 2001 From: Emulator-Team-2 <38318848+Emulator-Team-2@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:12:59 +0200 Subject: [PATCH 091/147] added data_format=3 and num_format=4 --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index d474cee68..89ee01589 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -453,6 +453,9 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eR8G8Unorm; } + if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Uint) { + return vk::Format::eR8G8Uint; + } if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Snorm) { return vk::Format::eR8G8Snorm; } From af18728962f0e9bf6a0bb7690d0b0b6479361571 Mon Sep 17 00:00:00 2001 From: Emulator-Team-2 <38318848+Emulator-Team-2@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:45:32 +0200 Subject: [PATCH 092/147] clang-format fix --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 89ee01589..3ae19a82a 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -462,8 +462,8 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eBc7UnormBlock; } - if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc2SrgbBlock; + if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Srgb) { + return vk::Format::eBc2SrgbBlock; } if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eBc2UnormBlock; From 365e17f64ea126d19e40dbf4d8f7ad7a37677de2 Mon Sep 17 00:00:00 2001 From: bigol83 <38129260+bigol83@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:14:33 +0200 Subject: [PATCH 093/147] Update it.ts --- src/qt_gui/translations/it.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 228d798d0..a47d36823 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -16,7 +16,7 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 è un emulatore sperimentale open source per Playstation 4. + shadPS4 è un emulatore sperimentale open source per PlayStation 4. @@ -176,7 +176,7 @@ Install application from a .pkg file - Installa applicaazione da un .pkg file + Installa applicazione da un file .pkg file @@ -365,7 +365,7 @@ System - Systema + Sistema @@ -450,7 +450,7 @@ Enable Shaders Dumping - Abilita Scaricamento Shader + Abilita Dump Shader @@ -460,7 +460,7 @@ Enable PM4 Dumping - Abilita Scaricamento PM4 + Abilita Dump PM4 @@ -470,7 +470,7 @@ Enable Debug Dumping - Abilita Scaricamento Debug + Abilita Dump Debug From 55be97bca3dacbf9966e6e88c5cd5a9673e47bbb Mon Sep 17 00:00:00 2001 From: CyntexMore Date: Wed, 28 Aug 2024 22:15:03 +0200 Subject: [PATCH 094/147] feat(translation): hu_HU translated --- src/qt_gui/translations/hu_HU.ts | 184 +++++++++++++++---------------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index a32b2d2ad..c6cc0bce2 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + A shadPS4-ről @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + A shadPS4 egy kezdetleges, open-source PlayStation 4 emulátor. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Ne használja ezt a szoftvert olyan játékokkal, amelyeket nem legális módon szerzett be. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Mappa megnyitása @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Játék könyvtár betöltése, kérjük várjon :3 Cancel - Cancel + Megszakítás Loading... - Loading... + Betöltés.. @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Mappa kiválasztása Directory to install games - Directory to install games + Mappa a játékok telepítésére Browse - Browse + Böngészés Error - Error + Hiba The value for location to install games is not valid. - The value for location to install games is not valid. + A játékok telepítéséhez megadott érték nem érvényes. @@ -83,67 +83,67 @@ Create Shortcut - Create Shortcut + Parancsikon Létrehozása Open Game Folder - Open Game Folder + Játék Mappa Megnyitása SFO Viewer - SFO Viewer + SFO Néző Trophy Viewer - Trophy Viewer + Trófeák Megtekintése Copy info - Copy info + Információ Másolása Copy Name - Copy Name + Név Másolása Copy Serial - Copy Serial + Széria Másolása Copy All - Copy All + Összes Másolása Shortcut creation - Shortcut creation + Parancsikon létrehozása Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Parancsikon sikeresen létrehozva!\n %1 Error - Error + Hiba Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Hiba a parancsikon létrehozásával!\n %1 Install PKG - Install PKG + PKG telepítése @@ -151,187 +151,187 @@ Open/Add Elf Folder - Open/Add Elf Folder + Efl Mappa Megnyitása/Hozzáadása Install Packages (PKG) - Install Packages (PKG) + PKG-k Telepítése (PKG) Boot Game - Boot Game + Játék Bootolása About shadPS4 - About shadPS4 + A shadPS4-ről Configure... - Configure... + Konfigurálás... Install application from a .pkg file - Install application from a .pkg file + Program telepítése egy .pkg fájlból Recent Games - Recent Games + Legutóbbi Játékok Exit - Exit + Kilépés Exit shadPS4 - Exit shadPS4 + Kilépés a shadPS4 Exit the application. - Exit the application. + Lépjen ki az programból. Show Game List - Show Game List + Játék Könyvtár Megjelenítése Game List Refresh - Game List Refresh + Játék Könyvtár Újratöltése Tiny - Tiny + Apró Small - Small + Kicsi Medium - Medium + Közepes Large - Large + Nagy List View - List View + Lista Nézet Grid View - Grid View + Rács Nézet Elf Viewer - Elf Viewer + Elf Néző Game Install Directory - Game Install Directory + Játék Telepítési Mappa Dump Game List - Dump Game List + Játék Lista Dumpolása PKG Viewer - PKG Viewer + PKG Néző Search... - Search... + Keresés... File - File + Fájl View - View + Megnézés Game List Icons - Game List Icons + Játék Könyvtár Ikonok Game List Mode - Game List Mode + Játék Könyvtár Mód Settings - Settings + Beállítások Utils - Utils + Segédeszközök Themes - Themes + Témák About - About + Segítség Dark - Dark + Sötét Light - Light + Világos Green - Green + Zöld Blue - Blue + Kék Violet - Violet + Ibolya toolBar - toolBar + Eszköztár @@ -339,7 +339,7 @@ Open Folder - Open Folder + Mappa Megnyitása @@ -347,7 +347,7 @@ Trophy Viewer - Trophy Viewer + Trófeák Megtekintése @@ -355,137 +355,137 @@ Settings - Settings + Beállítások General - General + Általános System - System + Rendszer Console Language - Console Language + A Konzol Nyelvezete Emulator Language - Emulator Language + Az Emulátor Nyelvezete Emulator - Emulator + Emulátor Enable Fullscreen - Enable Fullscreen + Teljesképernyő Engedélyezése Show Splash - Show Splash + Indítóképernyő Mutatása Is PS4 Pro - Is PS4 Pro + PS4 Pro Username - Username + Felhasználónév Logger - Logger + Naplózó Log Type - Log Type + Naplózási Típus Log Filter - Log Filter + Naplózási Filter Graphics - Graphics + Grafika Graphics Device - Graphics Device + Grafikai Eszköz Width - Width + Szélesség Height - Height + Magasság Vblank Divider - Vblank Divider + Vblank Elosztó Advanced - Advanced + Haladó Enable Shaders Dumping - Enable Shaders Dumping + Shader Dumpolás Engedélyezése Enable NULL GPU - Enable NULL GPU + NULL GPU Engedélyezése Enable PM4 Dumping - Enable PM4 Dumping + PM4 Dumpolás Engedélyezése Debug - Debug + Debugolás Enable Debug Dumping - Enable Debug Dumping + Debug Dumpolás Engedélyezése Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Vulkan Validációs Rétegek Engedélyezése Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Vulkan Szinkronizálás Validáció Enable RenderDoc Debugging - Enable RenderDoc Debugging + RenderDoc Debugolás Engedélyezése - \ No newline at end of file + From 3fbb68048e0c28b418fc4a64999cde0c528133fe Mon Sep 17 00:00:00 2001 From: psucien <168137814+psucien@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:27:47 +0200 Subject: [PATCH 095/147] shader_recompiler: frontend: `SOPC` and `SOPK` handling separated; more cmp opcodes (#634) --- .../frontend/translate/scalar_alu.cpp | 238 +++++++++++------- .../frontend/translate/translate.h | 6 +- 2 files changed, 159 insertions(+), 85 deletions(-) diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 7914726f4..da74f9018 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -6,98 +6,150 @@ namespace Shader::Gcn { void Translator::EmitScalarAlu(const GcnInst& inst) { + switch (inst.encoding) { + case InstEncoding::SOPC: { + EmitSOPC(inst); + break; + } + case InstEncoding::SOPK: { + EmitSOPK(inst); + break; + } + default: + switch (inst.opcode) { + case Opcode::S_MOV_B32: + return S_MOV(inst); + case Opcode::S_MUL_I32: + return S_MUL_I32(inst); + case Opcode::S_AND_SAVEEXEC_B64: + return S_AND_SAVEEXEC_B64(inst); + case Opcode::S_MOV_B64: + return S_MOV_B64(inst); + case Opcode::S_OR_B64: + return S_OR_B64(NegateMode::None, false, inst); + case Opcode::S_NOR_B64: + return S_OR_B64(NegateMode::Result, false, inst); + case Opcode::S_XOR_B64: + return S_OR_B64(NegateMode::None, true, inst); + case Opcode::S_ORN2_B64: + return S_OR_B64(NegateMode::Src1, false, inst); + case Opcode::S_AND_B64: + return S_AND_B64(NegateMode::None, inst); + case Opcode::S_NAND_B64: + return S_AND_B64(NegateMode::Result, inst); + case Opcode::S_ANDN2_B64: + return S_AND_B64(NegateMode::Src1, inst); + case Opcode::S_NOT_B64: + return S_NOT_B64(inst); + case Opcode::S_ADD_I32: + return S_ADD_I32(inst); + case Opcode::S_AND_B32: + return S_AND_B32(inst); + case Opcode::S_ASHR_I32: + return S_ASHR_I32(inst); + case Opcode::S_OR_B32: + return S_OR_B32(inst); + case Opcode::S_LSHL_B32: + return S_LSHL_B32(inst); + case Opcode::S_LSHR_B32: + return S_LSHR_B32(inst); + case Opcode::S_CSELECT_B32: + return S_CSELECT_B32(inst); + case Opcode::S_CSELECT_B64: + return S_CSELECT_B64(inst); + case Opcode::S_BFE_U32: + return S_BFE_U32(inst); + case Opcode::S_BFM_B32: + return S_BFM_B32(inst); + case Opcode::S_BREV_B32: + return S_BREV_B32(inst); + case Opcode::S_ADD_U32: + return S_ADD_U32(inst); + case Opcode::S_ADDC_U32: + return S_ADDC_U32(inst); + case Opcode::S_SUB_U32: + case Opcode::S_SUB_I32: + return S_SUB_U32(inst); + case Opcode::S_MIN_U32: + return S_MIN_U32(inst); + case Opcode::S_MAX_U32: + return S_MAX_U32(inst); + case Opcode::S_WQM_B64: + break; + default: + LogMissingOpcode(inst); + } + break; + } +} + +void Translator::EmitSOPC(const GcnInst& inst) { switch (inst.opcode) { - case Opcode::S_MOVK_I32: - return S_MOVK(inst); - case Opcode::S_MOV_B32: - return S_MOV(inst); - case Opcode::S_MUL_I32: - return S_MUL_I32(inst); - case Opcode::S_AND_SAVEEXEC_B64: - return S_AND_SAVEEXEC_B64(inst); - case Opcode::S_MOV_B64: - return S_MOV_B64(inst); - case Opcode::S_CMP_LT_U32: - return S_CMP(ConditionOp::LT, false, inst); - case Opcode::S_CMP_LE_U32: - return S_CMP(ConditionOp::LE, false, inst); - case Opcode::S_CMP_LG_U32: - return S_CMP(ConditionOp::LG, false, inst); - case Opcode::S_CMP_LT_I32: - return S_CMP(ConditionOp::LT, true, inst); + case Opcode::S_CMP_EQ_I32: + return S_CMP(ConditionOp::EQ, true, inst); case Opcode::S_CMP_LG_I32: return S_CMP(ConditionOp::LG, true, inst); case Opcode::S_CMP_GT_I32: return S_CMP(ConditionOp::GT, true, inst); - case Opcode::S_CMP_LE_I32: - return S_CMP(ConditionOp::LE, true, inst); case Opcode::S_CMP_GE_I32: return S_CMP(ConditionOp::GE, true, inst); - case Opcode::S_CMP_EQ_I32: - return S_CMP(ConditionOp::EQ, true, inst); + case Opcode::S_CMP_LT_I32: + return S_CMP(ConditionOp::LT, true, inst); + case Opcode::S_CMP_LE_I32: + return S_CMP(ConditionOp::LE, true, inst); + case Opcode::S_CMP_EQ_U32: return S_CMP(ConditionOp::EQ, false, inst); - case Opcode::S_CMP_GE_U32: - return S_CMP(ConditionOp::GE, false, inst); + case Opcode::S_CMP_LG_U32: + return S_CMP(ConditionOp::LG, false, inst); case Opcode::S_CMP_GT_U32: return S_CMP(ConditionOp::GT, false, inst); - case Opcode::S_OR_B64: - return S_OR_B64(NegateMode::None, false, inst); - case Opcode::S_NOR_B64: - return S_OR_B64(NegateMode::Result, false, inst); - case Opcode::S_XOR_B64: - return S_OR_B64(NegateMode::None, true, inst); - case Opcode::S_ORN2_B64: - return S_OR_B64(NegateMode::Src1, false, inst); - case Opcode::S_AND_B64: - return S_AND_B64(NegateMode::None, inst); - case Opcode::S_NAND_B64: - return S_AND_B64(NegateMode::Result, inst); - case Opcode::S_ANDN2_B64: - return S_AND_B64(NegateMode::Src1, inst); - case Opcode::S_NOT_B64: - return S_NOT_B64(inst); - case Opcode::S_ADD_I32: - return S_ADD_I32(inst); - case Opcode::S_AND_B32: - return S_AND_B32(inst); - case Opcode::S_ASHR_I32: - return S_ASHR_I32(inst); - case Opcode::S_OR_B32: - return S_OR_B32(inst); - case Opcode::S_LSHL_B32: - return S_LSHL_B32(inst); - case Opcode::S_LSHR_B32: - return S_LSHR_B32(inst); - case Opcode::S_CSELECT_B32: - return S_CSELECT_B32(inst); - case Opcode::S_CSELECT_B64: - return S_CSELECT_B64(inst); - case Opcode::S_BFE_U32: - return S_BFE_U32(inst); - case Opcode::S_BFM_B32: - return S_BFM_B32(inst); - case Opcode::S_BREV_B32: - return S_BREV_B32(inst); - case Opcode::S_ADD_U32: - return S_ADD_U32(inst); - case Opcode::S_ADDC_U32: - return S_ADDC_U32(inst); + case Opcode::S_CMP_GE_U32: + return S_CMP(ConditionOp::GE, false, inst); + case Opcode::S_CMP_LT_U32: + return S_CMP(ConditionOp::LT, false, inst); + case Opcode::S_CMP_LE_U32: + return S_CMP(ConditionOp::LE, false, inst); + default: + LogMissingOpcode(inst); + } +} + +void Translator::EmitSOPK(const GcnInst& inst) { + switch (inst.opcode) { + case Opcode::S_MOVK_I32: + return S_MOVK(inst); + + case Opcode::S_CMPK_EQ_I32: + return S_CMPK(ConditionOp::EQ, true, inst); + case Opcode::S_CMPK_LG_I32: + return S_CMPK(ConditionOp::LG, true, inst); + case Opcode::S_CMPK_GT_I32: + return S_CMPK(ConditionOp::GT, true, inst); + case Opcode::S_CMPK_GE_I32: + return S_CMPK(ConditionOp::GE, true, inst); + case Opcode::S_CMPK_LT_I32: + return S_CMPK(ConditionOp::LT, true, inst); + case Opcode::S_CMPK_LE_I32: + return S_CMPK(ConditionOp::LE, true, inst); + + case Opcode::S_CMPK_EQ_U32: + return S_CMPK(ConditionOp::EQ, false, inst); + case Opcode::S_CMPK_LG_U32: + return S_CMPK(ConditionOp::LG, false, inst); + case Opcode::S_CMPK_GT_U32: + return S_CMPK(ConditionOp::GT, false, inst); + case Opcode::S_CMPK_GE_U32: + return S_CMPK(ConditionOp::GE, false, inst); + case Opcode::S_CMPK_LT_U32: + return S_CMPK(ConditionOp::LT, false, inst); + case Opcode::S_CMPK_LE_U32: + return S_CMPK(ConditionOp::LE, false, inst); + case Opcode::S_ADDK_I32: return S_ADDK_I32(inst); case Opcode::S_MULK_I32: return S_MULK_I32(inst); - case Opcode::S_SUB_U32: - case Opcode::S_SUB_I32: - return S_SUB_U32(inst); - case Opcode::S_MIN_U32: - return S_MIN_U32(inst); - case Opcode::S_MAX_U32: - return S_MAX_U32(inst); - case Opcode::S_WQM_B64: - break; - case Opcode::S_CMPK_EQ_U32: - return S_CMPK_EQ_U32(inst); default: LogMissingOpcode(inst); } @@ -154,6 +206,31 @@ void Translator::S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst) { ir.SetScc(result); } +void Translator::S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst) { + const s32 simm16 = inst.control.sopk.simm; + const IR::U32 lhs = GetSrc(inst.dst[0]); + const IR::U32 rhs = ir.Imm32(simm16); + const IR::U1 result = [&] { + switch (cond) { + case ConditionOp::EQ: + return ir.IEqual(lhs, rhs); + case ConditionOp::LG: + return ir.INotEqual(lhs, rhs); + case ConditionOp::GT: + return ir.IGreaterThan(lhs, rhs, is_signed); + case ConditionOp::GE: + return ir.IGreaterThanEqual(lhs, rhs, is_signed); + case ConditionOp::LT: + return ir.ILessThan(lhs, rhs, is_signed); + case ConditionOp::LE: + return ir.ILessThanEqual(lhs, rhs, is_signed); + default: + UNREACHABLE(); + } + }(); + ir.SetScc(result); +} + void Translator::S_AND_SAVEEXEC_B64(const GcnInst& inst) { // This instruction normally operates on 64-bit data (EXEC, VCC, SGPRs) // However here we flatten it to 1-bit EXEC and 1-bit VCC. For the destination @@ -470,11 +547,4 @@ void Translator::S_MIN_U32(const GcnInst& inst) { ir.SetScc(ir.IEqual(result, src0)); } -void Translator::S_CMPK_EQ_U32(const GcnInst& inst) { - const s32 simm16 = inst.control.sopk.simm; - const IR::U32 src0{GetSrc(inst.dst[0])}; - const IR::U32 src1{ir.Imm32(simm16)}; - ir.SetScc(ir.IEqual(src0, src1)); -} - } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index cde9e58e7..8cbf7357e 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -69,6 +69,10 @@ public: void EmitScalarAlu(const GcnInst& inst); void EmitVectorAlu(const GcnInst& inst); + // Instruction encodings + void EmitSOPC(const GcnInst& inst); + void EmitSOPK(const GcnInst& inst); + // Scalar ALU void S_MOVK(const GcnInst& inst); void S_MOV(const GcnInst& inst); @@ -98,7 +102,7 @@ public: void S_ADDK_I32(const GcnInst& inst); void S_MAX_U32(const GcnInst& inst); void S_MIN_U32(const GcnInst& inst); - void S_CMPK_EQ_U32(const GcnInst& inst); + void S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst); // Scalar Memory void S_LOAD_DWORD(int num_dwords, const GcnInst& inst); From 614a23b369d127f2891ed0f6f955d1016dfa8906 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Thu, 29 Aug 2024 01:18:50 -0300 Subject: [PATCH 096/147] Cheats/Patches (#493) * Cheats/Patches Adds the possibility of applying cheats/patches according to the specific game serial+version The logic for adding modifications has not yet been implemented! Interface based on issues/372 https://github.com/shadps4-emu/shadPS4/issues/372 [X]Front-end []Back-end Create a synchronized fork of the cheats/patches repository * Clang Format * separate files The code has been separated into separate files as suggested by georgemoralis. Added the Patch tab, which has not been implemented yet. Added the 'applyCheat' area to apply the modification, not implemented yet... And added LOG_INFO. * reuse * initial implementation of cheat functionality * Update cheats_patches.cpp sets all added buttons to the size of the largest button. and fixes some aesthetic issues. * move eboot_address to module.h fixes the non-qt builds and makes more sense to be there anyway * Patchs menu and fixes adds the possibility to download Patches, it does not modify the memory yet. and some other fixes * MemoryPatcher namespace, activate cheats on start * format * initial patch implementation * format * format again... * convertValueToHex * Fixes Choosing which cheat file to use. And some other fixes * fix bytes16, bytes32, bytes64 type patches If a patch is any of these types we convert it from little endian to big endian * format * format again :( * Implement pattern scanning for mask type patches * add check to stop patches applying to wrong game previously if you added a patch to a game, but closed the window and opened a different game it would still try to apply the patch, this is now fixed * format * Fix 'Hint' 0x400000 | and Author * Management |save checkbox | shadps4 repository MENU - Cheats/Patches Management (implementing Patches) save patches checkbox add shadps4 repository * Load saved patches, miscellaneous fixes * Fix an issue with mask patches not being saved * format + remove debug log * multiple patches | TR translation for cheats/patches * clang * ENABLE_QT_GUI * OK * move memory_patcher to qt_gui * clang * add cheats hu_HU * fix log * Remove the item from the patchesListView if no patches were added (the game has patches, but not for the current version) --------- Co-authored-by: CrazyBloo --- CMakeLists.txt | 9 +- src/common/path_util.cpp | 2 + src/common/path_util.h | 4 + src/core/module.cpp | 13 + src/emulator.cpp | 6 + src/qt_gui/cheats_patches.cpp | 1264 +++++++++++++++++++++++++++ src/qt_gui/cheats_patches.h | 115 +++ src/qt_gui/gui_context_menus.h | 22 + src/qt_gui/main_window.cpp | 131 ++- src/qt_gui/main_window_ui.h | 7 +- src/qt_gui/memory_patcher.cpp | 347 ++++++++ src/qt_gui/memory_patcher.h | 47 + src/qt_gui/translations/da_DK.ts | 427 ++++++++- src/qt_gui/translations/de.ts | 427 ++++++++- src/qt_gui/translations/el.ts | 427 ++++++++- src/qt_gui/translations/en.ts | 427 ++++++++- src/qt_gui/translations/es_ES.ts | 429 ++++++++- src/qt_gui/translations/fi.ts | 427 ++++++++- src/qt_gui/translations/fr.ts | 427 ++++++++- src/qt_gui/translations/hu_HU.ts | 401 +++++++++ src/qt_gui/translations/id.ts | 427 ++++++++- src/qt_gui/translations/it.ts | 429 ++++++++- src/qt_gui/translations/ja_JP.ts | 429 ++++++++- src/qt_gui/translations/ko_KR.ts | 427 ++++++++- src/qt_gui/translations/lt_LT.ts | 429 ++++++++- src/qt_gui/translations/nb.ts | 427 ++++++++- src/qt_gui/translations/nl.ts | 427 ++++++++- src/qt_gui/translations/pl_PL.ts | 1385 +++++++++++++++++++----------- src/qt_gui/translations/pt_BR.ts | 427 ++++++++- src/qt_gui/translations/ro_RO.ts | 427 ++++++++- src/qt_gui/translations/ru_RU.ts | 429 ++++++++- src/qt_gui/translations/tr_TR.ts | 498 ++++++++++- src/qt_gui/translations/vi_VN.ts | 427 ++++++++- src/qt_gui/translations/zh_CN.ts | 427 ++++++++- src/qt_gui/translations/zh_TW.ts | 427 ++++++++- 35 files changed, 12003 insertions(+), 798 deletions(-) create mode 100644 src/qt_gui/cheats_patches.cpp create mode 100644 src/qt_gui/cheats_patches.h create mode 100644 src/qt_gui/memory_patcher.cpp create mode 100644 src/qt_gui/memory_patcher.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 04740784b..dfc6528df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,7 +109,7 @@ add_subdirectory(externals) include_directories(src) if(ENABLE_QT_GUI) - find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools) + find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network) qt_standard_project_setup() set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) @@ -563,6 +563,10 @@ qt_add_resources(RESOURCE_FILES src/shadps4.qrc) set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/about_dialog.h src/qt_gui/about_dialog.ui + src/qt_gui/cheats_patches.cpp + src/qt_gui/cheats_patches.h + src/qt_gui/memory_patcher.cpp + src/qt_gui/memory_patcher.h src/qt_gui/main_window_ui.h src/qt_gui/main_window.cpp src/qt_gui/main_window.h @@ -651,7 +655,8 @@ else() endif() if (ENABLE_QT_GUI) - target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent) + target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network) + add_definitions(-DENABLE_QT_GUI) endif() if (WIN32) diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index d69f72163..5d5c9ebad 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -104,6 +104,8 @@ static auto UserPaths = [] { create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR); create_path(PathType::DownloadDir, user_dir / DOWNLOAD_DIR); create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR); + create_path(PathType::CheatsDir, user_dir / CHEATS_DIR); + create_path(PathType::PatchesDir, user_dir / PATCHES_DIR); return paths; }(); diff --git a/src/common/path_util.h b/src/common/path_util.h index 263edd46e..8922de9f1 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -20,6 +20,8 @@ enum class PathType { SysModuleDir, // Where system modules are stored. DownloadDir, // Where downloads/temp files are stored. CapturesDir, // Where rdoc captures are stored. + CheatsDir, // Where cheats are stored. + PatchesDir, // Where patches are stored. }; constexpr auto PORTABLE_DIR = "user"; @@ -35,6 +37,8 @@ constexpr auto TEMPDATA_DIR = "temp"; constexpr auto SYSMODULES_DIR = "sys_modules"; constexpr auto DOWNLOAD_DIR = "download"; constexpr auto CAPTURES_DIR = "captures"; +constexpr auto CHEATS_DIR = "cheats"; +constexpr auto PATCHES_DIR = "patches"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; diff --git a/src/core/module.cpp b/src/core/module.cpp index 775e1ef19..f48848bbd 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -5,6 +5,9 @@ #include "common/alignment.h" #include "common/assert.h" #include "common/logging/log.h" +#ifdef ENABLE_QT_GUI +#include "qt_gui/memory_patcher.h" +#endif #include "common/string_util.h" #include "core/aerolib/aerolib.h" #include "core/cpu_patches.h" @@ -192,6 +195,16 @@ void Module::LoadModuleToMemory(u32& max_tls_index) { const VAddr entry_addr = base_virtual_addr + elf.GetElfEntry(); LOG_INFO(Core_Linker, "program entry addr ..........: {:#018x}", entry_addr); + +#ifdef ENABLE_QT_GUI + if (MemoryPatcher::g_eboot_address == 0) { + if (name == "eboot") { + MemoryPatcher::g_eboot_address = base_virtual_addr; + MemoryPatcher::g_eboot_image_size = base_size; + MemoryPatcher::OnGameLoaded(); + } + } +#endif } void Module::LoadDynamicInfo() { diff --git a/src/emulator.cpp b/src/emulator.cpp index 836b989e5..b12bb8591 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -7,6 +7,9 @@ #include "common/debug.h" #include "common/logging/backend.h" #include "common/logging/log.h" +#ifdef ENABLE_QT_GUI +#include "qt_gui/memory_patcher.h" +#endif #include "common/ntapi.h" #include "common/path_util.h" #include "common/polyfill_thread.h" @@ -93,6 +96,9 @@ void Emulator::Run(const std::filesystem::path& file) { auto* param_sfo = Common::Singleton::Instance(); param_sfo->open(sce_sys_folder.string() + "/param.sfo", {}); id = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); +#ifdef ENABLE_QT_GUI + MemoryPatcher::g_game_serial = id; +#endif title = param_sfo->GetString("TITLE"); LOG_INFO(Loader, "Game id: {} Title: {}", id, title); u32 fw_version = param_sfo->GetInteger("SYSTEM_VER"); diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp new file mode 100644 index 000000000..662d52cc1 --- /dev/null +++ b/src/qt_gui/cheats_patches.cpp @@ -0,0 +1,1264 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cheats_patches.h" +#include "common/path_util.h" +#include "core/module.h" +#include "qt_gui/memory_patcher.h" + +using namespace Common::FS; + +CheatsPatches::CheatsPatches(const QString& gameName, const QString& gameSerial, + const QString& gameVersion, const QString& gameSize, + const QPixmap& gameImage, QWidget* parent) + : QWidget(parent), m_gameName(gameName), m_gameSerial(gameSerial), m_gameVersion(gameVersion), + m_gameSize(gameSize), m_gameImage(gameImage), manager(new QNetworkAccessManager(this)) { + setupUI(); + resize(500, 400); + setWindowTitle(tr("Cheats / Patches")); +} + +CheatsPatches::~CheatsPatches() {} + +void CheatsPatches::setupUI() { + defaultTextEdit = tr("defaultTextEdit_MSG"); + defaultTextEdit.replace("\\n", "\n"); + + QString CHEATS_DIR_QString = + QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); + QString NameCheatJson = m_gameSerial + "_" + m_gameVersion + ".json"; + m_cheatFilePath = CHEATS_DIR_QString + "/" + NameCheatJson; + + QHBoxLayout* mainLayout = new QHBoxLayout(this); + + // Create the game info group box + QGroupBox* gameInfoGroupBox = new QGroupBox(); + QVBoxLayout* gameInfoLayout = new QVBoxLayout(gameInfoGroupBox); + gameInfoLayout->setAlignment(Qt::AlignTop); + + QLabel* gameImageLabel = new QLabel(); + if (!m_gameImage.isNull()) { + gameImageLabel->setPixmap(m_gameImage.scaled(275, 275, Qt::KeepAspectRatio)); + } else { + gameImageLabel->setText(tr("No Image Available")); + } + gameImageLabel->setAlignment(Qt::AlignCenter); + gameInfoLayout->addWidget(gameImageLabel, 0, Qt::AlignCenter); + + QLabel* gameNameLabel = new QLabel(m_gameName); + gameNameLabel->setAlignment(Qt::AlignLeft); + gameNameLabel->setWordWrap(true); + gameInfoLayout->addWidget(gameNameLabel); + + QLabel* gameSerialLabel = new QLabel(tr("Serial: ") + m_gameSerial); + gameSerialLabel->setAlignment(Qt::AlignLeft); + gameInfoLayout->addWidget(gameSerialLabel); + + QLabel* gameVersionLabel = new QLabel(tr("Version: ") + m_gameVersion); + gameVersionLabel->setAlignment(Qt::AlignLeft); + gameInfoLayout->addWidget(gameVersionLabel); + + 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(); + instructionsTextEdit->setText(defaultTextEdit); + instructionsTextEdit->setReadOnly(true); + instructionsTextEdit->setFixedHeight(290); + gameInfoLayout->addWidget(instructionsTextEdit); + + // Create the tab widget + QTabWidget* tabWidget = new QTabWidget(); + QWidget* cheatsTab = new QWidget(); + QWidget* patchesTab = new QWidget(); + + // Layouts for the tabs + QVBoxLayout* cheatsLayout = new QVBoxLayout(); + QVBoxLayout* patchesLayout = new QVBoxLayout(); + + // Setup the cheats tab + QGroupBox* cheatsGroupBox = new QGroupBox(); + rightLayout = new QVBoxLayout(cheatsGroupBox); + rightLayout->setAlignment(Qt::AlignTop); + + cheatsGroupBox->setLayout(rightLayout); + QScrollArea* scrollArea = new QScrollArea(); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(cheatsGroupBox); + scrollArea->setMinimumHeight(490); + cheatsLayout->addWidget(scrollArea); + + // QListView + listView_selectFile = new QListView(); + listView_selectFile->setSelectionMode(QAbstractItemView::SingleSelection); + listView_selectFile->setEditTriggers(QAbstractItemView::NoEditTriggers); + + // Add QListView to layout + QVBoxLayout* fileListLayout = new QVBoxLayout(); + fileListLayout->addWidget(new QLabel(tr("Select Cheat File:"))); + fileListLayout->addWidget(listView_selectFile); + cheatsLayout->addLayout(fileListLayout, 2); + + // Call the method to fill the list of cheat files + populateFileListCheats(); + + QLabel* repositoryLabel = new QLabel("Repository:"); + repositoryLabel->setAlignment(Qt::AlignLeft); + repositoryLabel->setAlignment(Qt::AlignVCenter); + + // Add a combo box and a download button + QHBoxLayout* controlLayout = new QHBoxLayout(); + controlLayout->addWidget(repositoryLabel); + controlLayout->setAlignment(Qt::AlignLeft); + QComboBox* downloadComboBox = new QComboBox(); + + downloadComboBox->addItem("wolf2022", "wolf2022"); + downloadComboBox->addItem("GoldHEN", "GoldHEN"); + downloadComboBox->addItem("shadPS4", "shadPS4"); + + controlLayout->addWidget(downloadComboBox); + + QPushButton* downloadButton = new QPushButton(tr("Download Cheats")); + connect(downloadButton, &QPushButton::clicked, [=]() { + QString source = downloadComboBox->currentData().toString(); + downloadCheats(source, m_gameSerial, m_gameVersion, true); + }); + + QPushButton* deleteCheatButton = new QPushButton(tr("Delete File")); + connect(deleteCheatButton, &QPushButton::clicked, [=]() { + QStringListModel* model = qobject_cast(listView_selectFile->model()); + if (!model) { + return; + } + QItemSelectionModel* selectionModel = listView_selectFile->selectionModel(); + if (!selectionModel) { + return; + } + QModelIndexList selectedIndexes = selectionModel->selectedIndexes(); + if (selectedIndexes.isEmpty()) { + QMessageBox::warning( + this, tr("Delete File"), + tr("No files selected.") + "\n" + + tr("You can delete the cheats you don't want after downloading them.")); + return; + } + QModelIndex selectedIndex = selectedIndexes.first(); + QString selectedFileName = model->data(selectedIndex).toString(); + + int ret = QMessageBox::warning( + this, tr("Delete File"), + QString(tr("Do you want to delete the selected file?\n%1")).arg(selectedFileName), + QMessageBox::Yes | QMessageBox::No); + + if (ret == QMessageBox::Yes) { + QString filePath = CHEATS_DIR_QString + "/" + selectedFileName; + QFile::remove(filePath); + populateFileListCheats(); + } + }); + + controlLayout->addWidget(downloadButton); + controlLayout->addWidget(deleteCheatButton); + + cheatsLayout->addLayout(controlLayout); + cheatsTab->setLayout(cheatsLayout); + + // Setup the patches tab + QGroupBox* patchesGroupBox = new QGroupBox(); + patchesGroupBoxLayout = new QVBoxLayout(patchesGroupBox); + patchesGroupBoxLayout->setAlignment(Qt::AlignTop); + patchesGroupBox->setLayout(patchesGroupBoxLayout); + + QScrollArea* patchesScrollArea = new QScrollArea(); + patchesScrollArea->setWidgetResizable(true); + patchesScrollArea->setWidget(patchesGroupBox); + patchesScrollArea->setMinimumHeight(490); + patchesLayout->addWidget(patchesScrollArea); + + // List of files in patchesListView + patchesListView = new QListView(); + patchesListView->setSelectionMode(QAbstractItemView::SingleSelection); + patchesListView->setEditTriggers(QAbstractItemView::NoEditTriggers); + + // Add new label "Select Patch File:" above the QListView + QVBoxLayout* patchFileListLayout = new QVBoxLayout(); + patchFileListLayout->addWidget(new QLabel(tr("Select Patch File:"))); + patchFileListLayout->addWidget(patchesListView); + patchesLayout->addLayout(patchFileListLayout, 2); + + QStringListModel* patchesModel = new QStringListModel(); + patchesListView->setModel(patchesModel); + + QHBoxLayout* patchesControlLayout = new QHBoxLayout(); + + QLabel* patchesRepositoryLabel = new QLabel(tr("Repository:")); + patchesRepositoryLabel->setAlignment(Qt::AlignLeft); + patchesRepositoryLabel->setAlignment(Qt::AlignVCenter); + patchesControlLayout->addWidget(patchesRepositoryLabel); + + // Add the combo box with options + patchesComboBox = new QComboBox(); + patchesComboBox->addItem("GoldHEN", "GoldHEN"); + patchesComboBox->addItem("shadPS4", "shadPS4"); + patchesControlLayout->addWidget(patchesComboBox); + + QPushButton* patchesButton = new QPushButton(tr("Download Patches")); + connect(patchesButton, &QPushButton::clicked, [=]() { + QString selectedOption = patchesComboBox->currentData().toString(); + downloadPatches(selectedOption, true); + }); + patchesControlLayout->addWidget(patchesButton); + + QPushButton* saveButton = new QPushButton(tr("Save")); + connect(saveButton, &QPushButton::clicked, this, &CheatsPatches::onSaveButtonClicked); + + patchesControlLayout->addWidget(saveButton); + + patchesLayout->addLayout(patchesControlLayout); + patchesTab->setLayout(patchesLayout); + + tabWidget->addTab(cheatsTab, tr("Cheats")); + tabWidget->addTab(patchesTab, tr("Patches")); + + connect(tabWidget, &QTabWidget::currentChanged, this, [this](int index) { + if (index == 1) { + populateFileListPatches(); + } + }); + + mainLayout->addWidget(gameInfoGroupBox, 1); + mainLayout->addWidget(tabWidget, 3); + + manager = new QNetworkAccessManager(this); + + setLayout(mainLayout); +} + +void CheatsPatches::onSaveButtonClicked() { + // Get the name of the selected folder in the patchesListView + QString selectedPatchName; + QModelIndexList selectedIndexes = patchesListView->selectionModel()->selectedIndexes(); + if (selectedIndexes.isEmpty()) { + QMessageBox::warning(this, tr("Error"), tr("No patch selected.")); + return; + } + selectedPatchName = patchesListView->model()->data(selectedIndexes.first()).toString(); + int separatorIndex = selectedPatchName.indexOf(" | "); + selectedPatchName = selectedPatchName.mid(separatorIndex + 3); + + QString patchDir = + QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()) + + "/" + selectedPatchName; + + QString filesJsonPath = patchDir + "/files.json"; + QFile jsonFile(filesJsonPath); + if (!jsonFile.open(QIODevice::ReadOnly)) { + QMessageBox::critical(this, tr("Error"), tr("Unable to open files.json for reading.")); + return; + } + + QByteArray jsonData = jsonFile.readAll(); + jsonFile.close(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + + QString selectedFileName; + QString serial = m_gameSerial; + + for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) { + QString filePath = it.key(); + QJsonArray idsArray = it.value().toArray(); + + if (idsArray.contains(QJsonValue(serial))) { + selectedFileName = filePath; + break; + } + } + + if (selectedFileName.isEmpty()) { + QMessageBox::critical(this, tr("Error"), tr("No patch file found for the current serial.")); + return; + } + + QString filePath = patchDir + "/" + selectedFileName; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(this, tr("Error"), tr("Unable to open the file for reading.")); + return; + } + + QByteArray xmlData = file.readAll(); + file.close(); + + QString newXmlData; + QXmlStreamWriter xmlWriter(&newXmlData); + xmlWriter.setAutoFormatting(true); + xmlWriter.writeStartDocument(); + + QXmlStreamReader xmlReader(xmlData); + bool insideMetadata = false; + + while (!xmlReader.atEnd()) { + xmlReader.readNext(); + + if (xmlReader.isStartElement()) { + if (xmlReader.name() == QStringLiteral("Metadata")) { + insideMetadata = true; + xmlWriter.writeStartElement(xmlReader.name().toString()); + + QString name = xmlReader.attributes().value("Name").toString(); + bool isEnabled = false; + bool hasIsEnabled = false; + bool foundPatchInfo = false; + + // Check and update the isEnabled attribute + for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { + if (attr.name() == QStringLiteral("isEnabled")) { + hasIsEnabled = true; + auto it = m_patchInfos.find(name); + if (it != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(it->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + xmlWriter.writeAttribute("isEnabled", isEnabled ? "true" : "false"); + } + } + if (!foundPatchInfo) { + auto maskIt = m_patchInfos.find(name + " (any version)"); + if (maskIt != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(maskIt->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + xmlWriter.writeAttribute("isEnabled", + isEnabled ? "true" : "false"); + } + } + } + + } else { + xmlWriter.writeAttribute(attr.name().toString(), attr.value().toString()); + } + } + + if (!hasIsEnabled) { + auto it = m_patchInfos.find(name); + if (it != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(it->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + } + } + if (!foundPatchInfo) { + auto maskIt = m_patchInfos.find(name + " (any version)"); + if (maskIt != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(maskIt->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + } + } + } + xmlWriter.writeAttribute("isEnabled", isEnabled ? "true" : "false"); + } + } else { + xmlWriter.writeStartElement(xmlReader.name().toString()); + for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { + xmlWriter.writeAttribute(attr.name().toString(), attr.value().toString()); + } + } + } else if (xmlReader.isEndElement()) { + if (xmlReader.name() == QStringLiteral("Metadata")) { + insideMetadata = false; + } + xmlWriter.writeEndElement(); + } else if (xmlReader.isCharacters() && !xmlReader.isWhitespace()) { + xmlWriter.writeCharacters(xmlReader.text().toString()); + } + } + + xmlWriter.writeEndDocument(); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(this, tr("Error"), tr("Unable to open the file for writing.")); + return; + } + + QTextStream textStream(&file); + textStream << newXmlData; + file.close(); + + if (xmlReader.hasError()) { + QMessageBox::critical(this, tr("Error"), + tr("Failed to parse XML: ") + "\n" + xmlReader.errorString()); + } else { + QMessageBox::information(this, tr("Success"), tr("Options saved successfully.")); + } +} + +QCheckBox* CheatsPatches::findCheckBoxByName(const QString& name) { + for (int i = 0; i < patchesGroupBoxLayout->count(); ++i) { + QLayoutItem* item = patchesGroupBoxLayout->itemAt(i); + if (item) { + QWidget* widget = item->widget(); + QCheckBox* checkBox = qobject_cast(widget); + if (checkBox) { + if (checkBox->text().toStdString().find(name.toStdString()) != std::string::npos) { + return checkBox; + } + } + } + } + return nullptr; +} + +void CheatsPatches::downloadCheats(const QString& source, const QString& m_gameSerial, + const QString& m_gameVersion, const bool showMessageBox) { + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); + if (!dir.exists()) { + dir.mkpath("."); + } + + QString url; + if (source == "GoldHEN") { + url = "https://raw.githubusercontent.com/GoldHEN/GoldHEN_Cheat_Repository/main/json.txt"; + } else if (source == "wolf2022") { + url = "https://wolf2022.ir/trainer/" + m_gameSerial + "_" + m_gameVersion + ".json"; + } else if (source == "shadPS4") { + url = "https://raw.githubusercontent.com/shadps4-emu/ps4_cheats/main/" + "CHEATS_JSON.txt"; + } else { + QMessageBox::warning(this, tr("Invalid Source"), + QString(tr("The selected source is invalid.") + "\n%1").arg(source)); + return; + } + + QNetworkRequest request(url); + QNetworkReply* reply = manager->get(request); + + connect(reply, &QNetworkReply::finished, [=]() { + if (reply->error() == QNetworkReply::NoError) { + QByteArray jsonData = reply->readAll(); + bool foundFiles = false; + + if (source == "GoldHEN" || source == "shadPS4") { + QString textContent(jsonData); + QRegularExpression regex( + QString("%1_%2[^=]*\.json").arg(m_gameSerial).arg(m_gameVersion)); + QRegularExpressionMatchIterator matches = regex.globalMatch(textContent); + QString baseUrl; + + if (source == "GoldHEN") { + baseUrl = "https://raw.githubusercontent.com/GoldHEN/GoldHEN_Cheat_Repository/" + "main/json/"; + } else { + baseUrl = "https://raw.githubusercontent.com/shadps4-emu/ps4_cheats/" + "main/CHEATS/"; + } + + while (matches.hasNext()) { + QRegularExpressionMatch match = matches.next(); + QString fileName = match.captured(0); + + if (!fileName.isEmpty()) { + QString newFileName = fileName; + int dotIndex = newFileName.lastIndexOf('.'); + if (dotIndex != -1) { + + if (source == "GoldHEN") { + newFileName.insert(dotIndex, "_GoldHEN"); + } else { + newFileName.insert(dotIndex, "_shadPS4"); + } + } + QString fileUrl = baseUrl + fileName; + QString localFilePath = dir.filePath(newFileName); + + if (QFile::exists(localFilePath) && showMessageBox) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, tr("File Exists"), + tr("File already exists. Do you want to replace it?"), + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) { + continue; + } + } + QNetworkRequest fileRequest(fileUrl); + QNetworkReply* fileReply = manager->get(fileRequest); + + connect(fileReply, &QNetworkReply::finished, [=]() { + if (fileReply->error() == QNetworkReply::NoError) { + QByteArray fileData = fileReply->readAll(); + QFile localFile(localFilePath); + if (localFile.open(QIODevice::WriteOnly)) { + localFile.write(fileData); + localFile.close(); + } else { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save file:") + "\n%1") + .arg(localFilePath)); + } + } else { + QMessageBox::warning(this, tr("Error"), + QString(tr("Failed to download file:") + + "%1\n\n" + tr("Error:") + "%2") + .arg(fileUrl) + .arg(fileReply->errorString())); + } + fileReply->deleteLater(); + }); + + foundFiles = true; + } + } + if (!foundFiles && showMessageBox) { + QMessageBox::warning(this, tr("Cheats Not Found"), tr("CheatsNotFound_MSG")); + } + } else if (source == "wolf2022") { + QString fileName = QFileInfo(QUrl(url).path()).fileName(); + QString baseFileName = fileName; + int dotIndex = baseFileName.lastIndexOf('.'); + if (dotIndex != -1) { + baseFileName.insert(dotIndex, "_wolf2022"); + } + QString filePath = + QString::fromStdString( + Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()) + + "/" + baseFileName; + if (QFile::exists(filePath) && showMessageBox) { + QMessageBox::StandardButton reply2; + reply2 = + QMessageBox::question(this, tr("File Exists"), + tr("File already exists. Do you want to replace it?"), + QMessageBox::Yes | QMessageBox::No); + if (reply2 == QMessageBox::No) { + reply->deleteLater(); + return; + } + } + QFile cheatFile(filePath); + if (cheatFile.open(QIODevice::WriteOnly)) { + cheatFile.write(jsonData); + cheatFile.close(); + foundFiles = true; + populateFileListCheats(); + } else { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save file:") + "\n%1").arg(filePath)); + } + } + if (foundFiles && showMessageBox) { + QMessageBox::information(this, tr("Cheats Downloaded Successfully"), + tr("CheatsDownloadedSuccessfully_MSG")); + populateFileListCheats(); + } + + } else { + if (showMessageBox) { + QMessageBox::warning(this, tr("Cheats Not Found"), tr("CheatsNotFound_MSG")); + } + } + reply->deleteLater(); + emit downloadFinished(); + }); + + // connect(reply, &QNetworkReply::errorOccurred, [=](QNetworkReply::NetworkError code) { + // if (showMessageBox) + // QMessageBox::warning(this, "Download Error", + // QString("Error in response: %1").arg(reply->errorString())); + // }); +} + +void CheatsPatches::populateFileListPatches() { + QLayoutItem* item; + while ((item = patchesGroupBoxLayout->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + m_patchInfos.clear(); + + QString patchesDir = + QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()); + QDir dir(patchesDir); + + QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + QStringList matchingFiles; + + foreach (const QString& folder, folders) { + QString folderPath = dir.filePath(folder); + QDir subDir(folderPath); + + QString filesJsonPath = subDir.filePath("files.json"); + QFile file(filesJsonPath); + + if (file.open(QIODevice::ReadOnly)) { + QByteArray fileData = file.readAll(); + file.close(); + + QJsonDocument jsonDoc(QJsonDocument::fromJson(fileData)); + QJsonObject jsonObj = jsonDoc.object(); + + for (auto it = jsonObj.constBegin(); it != jsonObj.constEnd(); ++it) { + QString fileName = it.key(); + QJsonArray serials = it.value().toArray(); + + if (serials.contains(QJsonValue(m_gameSerial))) { + QString fileEntry = fileName + " | " + folder; + if (!matchingFiles.contains(fileEntry)) { + matchingFiles << fileEntry; + } + } + } + } + } + QStringListModel* model = new QStringListModel(matchingFiles, this); + patchesListView->setModel(model); + + connect( + patchesListView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this]() { + QModelIndexList selectedIndexes = patchesListView->selectionModel()->selectedIndexes(); + if (!selectedIndexes.isEmpty()) { + QString selectedText = selectedIndexes.first().data().toString(); + addPatchesToLayout(selectedText); + } + }); + + if (!matchingFiles.isEmpty()) { + QModelIndex firstIndex = model->index(0, 0); + patchesListView->selectionModel()->select(firstIndex, QItemSelectionModel::Select | + QItemSelectionModel::Rows); + patchesListView->setCurrentIndex(firstIndex); + } +} + +void CheatsPatches::downloadPatches(const QString repository, const bool showMessageBox) { + QString url; + if (repository == "GoldHEN") { + url = "https://github.com/GoldHEN/GoldHEN_Patch_Repository/tree/main/" + "patches/xml"; + } + if (repository == "shadPS4") { + url = "https://github.com/shadps4-emu/ps4_cheats/tree/main/" + "PATCHES"; + } + QNetworkAccessManager* manager = new QNetworkAccessManager(this); + QNetworkRequest request(url); + QNetworkReply* reply = manager->get(request); + + connect(reply, &QNetworkReply::finished, [=]() { + if (reply->error() == QNetworkReply::NoError) { + QByteArray htmlData = reply->readAll(); + reply->deleteLater(); + + // Parsear HTML e extrair JSON usando QRegularExpression + QString htmlString = QString::fromUtf8(htmlData); + QRegularExpression jsonRegex( + R"()"); + QRegularExpressionMatch match = jsonRegex.match(htmlString); + + if (match.hasMatch()) { + QByteArray jsonData = match.captured(1).toUtf8(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObj = jsonDoc.object(); + QJsonArray itemsArray = + jsonObj["payload"].toObject()["tree"].toObject()["items"].toArray(); + + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString fullPath = dir.filePath(repository); + if (!dir.exists(fullPath)) { + dir.mkpath(fullPath); + } + dir.setPath(fullPath); + + foreach (const QJsonValue& value, itemsArray) { + QJsonObject fileObj = value.toObject(); + QString fileName = fileObj["name"].toString(); + QString filePath = fileObj["path"].toString(); + + if (fileName.endsWith(".xml")) { + QString fileUrl; + if (repository == "GoldHEN") { + fileUrl = QString("https://raw.githubusercontent.com/GoldHEN/" + "GoldHEN_Patch_Repository/main/%1") + .arg(filePath); + } + if (repository == "shadPS4") { + fileUrl = QString("https://raw.githubusercontent.com/shadps4-emu/" + "ps4_cheats/main/%1") + .arg(filePath); + } + QNetworkRequest fileRequest(fileUrl); + QNetworkReply* fileReply = manager->get(fileRequest); + + connect(fileReply, &QNetworkReply::finished, [=]() { + if (fileReply->error() == QNetworkReply::NoError) { + QByteArray fileData = fileReply->readAll(); + QFile localFile(dir.filePath(fileName)); + if (localFile.open(QIODevice::WriteOnly)) { + localFile.write(fileData); + localFile.close(); + } else { + if (showMessageBox) { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save:") + "\n%1").arg(fileName)); + } + } + } else { + if (showMessageBox) { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to download:") + "\n%1").arg(fileUrl)); + } + } + fileReply->deleteLater(); + }); + } + } + if (showMessageBox) { + QMessageBox::information(this, tr("Download Complete"), + QString(tr("DownloadComplete_MSG"))); + } + + // Create the files.json file with the identification of which file to open + createFilesJson(repository); + populateFileListPatches(); + + } else { + if (showMessageBox) { + QMessageBox::warning(this, tr("Error"), + tr("Failed to parse JSON data from HTML.")); + } + } + } else { + if (showMessageBox) { + QMessageBox::warning(this, tr("Error"), tr("Failed to retrieve HTML page.")); + } + } + emit downloadFinished(); + }); +} + +void CheatsPatches::createFilesJson(const QString& repository) { + + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString fullPath = dir.filePath(repository); + if (!dir.exists(fullPath)) { + dir.mkpath(fullPath); + } + dir.setPath(fullPath); + + QJsonObject filesObject; + QStringList xmlFiles = dir.entryList(QStringList() << "*.xml", QDir::Files); + + foreach (const QString& xmlFile, xmlFiles) { + QFile file(dir.filePath(xmlFile)); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::warning(this, tr("ERROR"), + QString(tr("Failed to open file:") + "\n%1").arg(xmlFile)); + continue; + } + + QXmlStreamReader xmlReader(&file); + QJsonArray titleIdsArray; + + while (!xmlReader.atEnd() && !xmlReader.hasError()) { + QXmlStreamReader::TokenType token = xmlReader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (xmlReader.name() == QStringLiteral("ID")) { + titleIdsArray.append(xmlReader.readElementText()); + } + } + } + + if (xmlReader.hasError()) { + QMessageBox::warning(this, tr("ERROR"), + QString(tr("XML ERROR:") + "\n%1").arg(xmlReader.errorString())); + } + filesObject[xmlFile] = titleIdsArray; + } + + QFile jsonFile(dir.absolutePath() + "/files.json"); + if (!jsonFile.open(QIODevice::WriteOnly)) { + QMessageBox::warning(this, tr("ERROR"), tr("Failed to open files.json for writing")); + return; + } + + QJsonDocument jsonDoc(filesObject); + jsonFile.write(jsonDoc.toJson()); + jsonFile.close(); +} + +void CheatsPatches::addCheatsToLayout(const QJsonArray& modsArray, const QJsonArray& creditsArray) { + QLayoutItem* item; + while ((item = rightLayout->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + m_cheats.clear(); + m_cheatCheckBoxes.clear(); + + int maxWidthButton = 0; + + for (const QJsonValue& modValue : modsArray) { + QJsonObject modObject = modValue.toObject(); + QString modName = modObject["name"].toString(); + QString modType = modObject["type"].toString(); + + Cheat cheat; + cheat.name = modName; + cheat.type = modType; + + QJsonArray memoryArray = modObject["memory"].toArray(); + for (const QJsonValue& memoryValue : memoryArray) { + QJsonObject memoryObject = memoryValue.toObject(); + MemoryMod memoryMod; + memoryMod.offset = memoryObject["offset"].toString(); + memoryMod.on = memoryObject["on"].toString(); + memoryMod.off = memoryObject["off"].toString(); + cheat.memoryMods.append(memoryMod); + } + + // Check for the presence of 'hint' field + cheat.hasHint = modObject.contains("hint"); + + m_cheats[modName] = cheat; + + if (modType == "checkbox") { + QCheckBox* cheatCheckBox = new QCheckBox(modName); + rightLayout->addWidget(cheatCheckBox); + m_cheatCheckBoxes.append(cheatCheckBox); + connect(cheatCheckBox, &QCheckBox::toggled, + [=](bool checked) { applyCheat(modName, checked); }); + } else if (modType == "button") { + QPushButton* cheatButton = new QPushButton(modName); + cheatButton->adjustSize(); + int buttonWidth = cheatButton->sizeHint().width(); + if (buttonWidth > maxWidthButton) { + maxWidthButton = buttonWidth; + } + + // Create a horizontal layout for buttons + QHBoxLayout* buttonLayout = new QHBoxLayout(); + buttonLayout->setContentsMargins(0, 0, 0, 0); + buttonLayout->addWidget(cheatButton); + buttonLayout->addStretch(); + + rightLayout->addLayout(buttonLayout); + connect(cheatButton, &QPushButton::clicked, [=]() { applyCheat(modName, true); }); + } + } + + // Set minimum and fixed size for all buttons + 20 + for (int i = 0; i < rightLayout->count(); ++i) { + QLayoutItem* layoutItem = rightLayout->itemAt(i); + QWidget* widget = layoutItem->widget(); + if (widget) { + QPushButton* button = qobject_cast(widget); + if (button) { + button->setMinimumWidth(maxWidthButton); + button->setFixedWidth(maxWidthButton + 20); + } + } else { + QLayout* layout = layoutItem->layout(); + if (layout) { + for (int j = 0; j < layout->count(); ++j) { + QLayoutItem* innerItem = layout->itemAt(j); + QWidget* innerWidget = innerItem->widget(); + if (innerWidget) { + QPushButton* button = qobject_cast(innerWidget); + if (button) { + button->setMinimumWidth(maxWidthButton); + button->setFixedWidth(maxWidthButton + 20); + } + } + } + } + } + } + + // Set credits label + QLabel* creditsLabel = new QLabel(); + QString creditsText = tr("Author: "); + if (!creditsArray.isEmpty()) { + creditsText += creditsArray[0].toString(); + } + creditsLabel->setText(creditsText); + creditsLabel->setAlignment(Qt::AlignLeft); + rightLayout->addWidget(creditsLabel); +} + +void CheatsPatches::populateFileListCheats() { + QString cheatsDir = + QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); + QString pattern = m_gameSerial + "_" + m_gameVersion + "*.json"; + + QDir dir(cheatsDir); + QStringList filters; + filters << pattern; + dir.setNameFilters(filters); + + QFileInfoList fileList = dir.entryInfoList(QDir::Files); + QStringList fileNames; + + for (const QFileInfo& fileInfo : fileList) { + fileNames << fileInfo.fileName(); + } + + QStringListModel* model = new QStringListModel(fileNames, this); + listView_selectFile->setModel(model); + + connect(listView_selectFile->selectionModel(), &QItemSelectionModel::selectionChanged, this, + [this]() { + QModelIndexList selectedIndexes = + listView_selectFile->selectionModel()->selectedIndexes(); + if (!selectedIndexes.isEmpty()) { + + QString selectedFileName = selectedIndexes.first().data().toString(); + QString cheatsDir = QString::fromStdString( + Common::FS::GetUserPath(Common::FS::PathType::CheatsDir).string()); + + QFile file(cheatsDir + "/" + selectedFileName); + if (file.open(QIODevice::ReadOnly)) { + QByteArray jsonData = file.readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + QJsonArray modsArray = jsonObject["mods"].toArray(); + QJsonArray creditsArray = jsonObject["credits"].toArray(); + addCheatsToLayout(modsArray, creditsArray); + } + } + }); + + if (!fileNames.isEmpty()) { + QModelIndex firstIndex = model->index(0, 0); + listView_selectFile->selectionModel()->select(firstIndex, QItemSelectionModel::Select | + QItemSelectionModel::Rows); + listView_selectFile->setCurrentIndex(firstIndex); + } +} + +void CheatsPatches::addPatchesToLayout(const QString& filePath) { + if (filePath == "") { + return; + } + QString folderPath = filePath.section(" | ", 1, 1); + + // Clear existing layout items + QLayoutItem* item; + while ((item = patchesGroupBoxLayout->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + m_patchInfos.clear(); + + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString fullPath = dir.filePath(folderPath); + + if (!dir.exists(fullPath)) { + QMessageBox::warning(this, tr("ERROR"), + QString(tr("Directory does not exist:") + "\n%1").arg(fullPath)); + return; + } + dir.setPath(fullPath); + + QString filesJsonPath = dir.filePath("files.json"); + + QFile jsonFile(filesJsonPath); + if (!jsonFile.open(QIODevice::ReadOnly)) { + QMessageBox::warning(this, tr("ERROR"), tr("Failed to open files.json for reading.")); + return; + } + + QByteArray jsonData = jsonFile.readAll(); + jsonFile.close(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + + bool patchAdded = false; + + // Iterate over each entry in the JSON file + for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) { + QString xmlFileName = it.key(); + QJsonArray idsArray = it.value().toArray(); + + // Check if the serial is in the ID list + if (idsArray.contains(QJsonValue(m_gameSerial))) { + QString xmlFilePath = dir.filePath(xmlFileName); + QFile xmlFile(xmlFilePath); + + if (!xmlFile.open(QIODevice::ReadOnly)) { + QMessageBox::warning( + this, tr("ERROR"), + QString(tr("Failed to open file:") + "\n%1").arg(xmlFile.fileName())); + continue; + } + QXmlStreamReader xmlReader(&xmlFile); + QString patchName; + QString patchAuthor; + QString patchNote; + QJsonArray patchLines; + bool isEnabled = false; + + while (!xmlReader.atEnd() && !xmlReader.hasError()) { + xmlReader.readNext(); + + if (xmlReader.tokenType() == QXmlStreamReader::StartElement) { + if (xmlReader.name() == QStringLiteral("Metadata")) { + QXmlStreamAttributes attributes = xmlReader.attributes(); + QString appVer = attributes.value("AppVer").toString(); + if (appVer == m_gameVersion) { + patchName = attributes.value("Name").toString(); + patchAuthor = attributes.value("Author").toString(); + patchNote = attributes.value("Note").toString(); + isEnabled = + attributes.value("isEnabled").toString() == QStringLiteral("true"); + } + if (appVer == "mask") { + patchName = attributes.value("Name").toString() + " (any version)"; + patchAuthor = attributes.value("Author").toString(); + patchNote = attributes.value("Note").toString(); + isEnabled = + attributes.value("isEnabled").toString() == QStringLiteral("true"); + } + } else if (xmlReader.name() == QStringLiteral("PatchList")) { + QJsonArray linesArray; + while (!xmlReader.atEnd() && + !(xmlReader.tokenType() == QXmlStreamReader::EndElement && + xmlReader.name() == QStringLiteral("PatchList"))) { + xmlReader.readNext(); + if (xmlReader.tokenType() == QXmlStreamReader::StartElement && + xmlReader.name() == QStringLiteral("Line")) { + QXmlStreamAttributes attributes = xmlReader.attributes(); + QJsonObject lineObject; + lineObject["Type"] = attributes.value("Type").toString(); + lineObject["Address"] = attributes.value("Address").toString(); + lineObject["Value"] = attributes.value("Value").toString(); + linesArray.append(lineObject); + } + } + patchLines = linesArray; + } + } + + if (!patchName.isEmpty() && !patchLines.isEmpty()) { + QCheckBox* patchCheckBox = new QCheckBox(patchName); + patchCheckBox->setChecked(isEnabled); + patchesGroupBoxLayout->addWidget(patchCheckBox); + + PatchInfo patchInfo; + patchInfo.name = patchName; + patchInfo.author = patchAuthor; + patchInfo.note = patchNote; + patchInfo.linesArray = patchLines; + patchInfo.serial = m_gameSerial; + m_patchInfos[patchName] = patchInfo; + + patchCheckBox->installEventFilter(this); + + connect(patchCheckBox, &QCheckBox::toggled, + [=](bool checked) { applyPatch(patchName, checked); }); + + patchName.clear(); + patchAuthor.clear(); + patchNote.clear(); + patchLines = QJsonArray(); + patchAdded = true; + } + } + xmlFile.close(); + } + } + + // Remove the item from the list view if no patches were added (the game has patches, but not + // for the current version) + if (!patchAdded) { + QStringListModel* model = qobject_cast(patchesListView->model()); + if (model) { + QStringList items = model->stringList(); + int index = items.indexOf(filePath); + if (index != -1) { + items.removeAt(index); + model->setStringList(items); + } + } + } +} + +void CheatsPatches::updateNoteTextEdit(const QString& patchName) { + if (m_patchInfos.contains(patchName)) { + const PatchInfo& patchInfo = m_patchInfos[patchName]; + QString text = QString(tr("Name:") + " %1\n" + tr("Author:") + " %2\n\n%3") + .arg(patchInfo.name) + .arg(patchInfo.author) + .arg(patchInfo.note); + + foreach (const QJsonValue& value, patchInfo.linesArray) { + QJsonObject lineObject = value.toObject(); + QString type = lineObject["Type"].toString(); + QString address = lineObject["Address"].toString(); + QString patchValue = lineObject["Value"].toString(); + + // add the values ​​to be modified in instructionsTextEdit + // text.append(QString("\nType: %1\nAddress: %2\n\nValue: %3") + // .arg(type) + // .arg(address) + // .arg(patchValue)); + } + text.replace("\\n", "\n"); + instructionsTextEdit->setText(text); + } +} + +bool showErrorMessage = true; +void CheatsPatches::uncheckAllCheatCheckBoxes() { + for (auto& cheatCheckBox : m_cheatCheckBoxes) { + cheatCheckBox->setChecked(false); + } + showErrorMessage = true; +} + +void CheatsPatches::applyCheat(const QString& modName, bool enabled) { + if (!m_cheats.contains(modName)) + return; + + Cheat cheat = m_cheats[modName]; + + for (const MemoryMod& memoryMod : cheat.memoryMods) { + QString value = enabled ? memoryMod.on : memoryMod.off; + + std::string modNameStr = modName.toStdString(); + std::string offsetStr = memoryMod.offset.toStdString(); + std::string valueStr = value.toStdString(); + + if (MemoryPatcher::g_eboot_address == 0) { + MemoryPatcher::patchInfo addingPatch; + addingPatch.modNameStr = modNameStr; + addingPatch.offsetStr = offsetStr; + addingPatch.valueStr = valueStr; + addingPatch.isOffset = true; + + MemoryPatcher::AddPatchToQueue(addingPatch); + continue; + } + // Determine if the hint field is present + bool isHintPresent = m_cheats[modName].hasHint; + MemoryPatcher::PatchMemory(modNameStr, offsetStr, valueStr, !isHintPresent, false); + } +} + +void CheatsPatches::applyPatch(const QString& patchName, bool enabled) { + if (!enabled) + return; + if (m_patchInfos.contains(patchName)) { + const PatchInfo& patchInfo = m_patchInfos[patchName]; + + foreach (const QJsonValue& value, patchInfo.linesArray) { + QJsonObject lineObject = value.toObject(); + QString type = lineObject["Type"].toString(); + QString address = lineObject["Address"].toString(); + QString patchValue = lineObject["Value"].toString(); + QString maskOffsetStr = lineObject["Offset"].toString(); + + patchValue = MemoryPatcher::convertValueToHex(type, patchValue); + + bool littleEndian = false; + + if (type == "bytes16") { + 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") { + 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 (MemoryPatcher::g_eboot_address == 0) { + MemoryPatcher::patchInfo addingPatch; + addingPatch.gameSerial = patchInfo.serial.toStdString(); + addingPatch.modNameStr = patchName.toStdString(); + addingPatch.offsetStr = address.toStdString(); + addingPatch.valueStr = patchValue.toStdString(); + addingPatch.isOffset = false; + addingPatch.littleEndian = littleEndian; + addingPatch.patchMask = patchMask; + addingPatch.maskOffset = maskOffsetValue; + + MemoryPatcher::AddPatchToQueue(addingPatch); + continue; + } + MemoryPatcher::PatchMemory(patchName.toStdString(), address.toStdString(), + patchValue.toStdString(), false, littleEndian, patchMask); + } + } +} + +bool CheatsPatches::eventFilter(QObject* obj, QEvent* event) { + if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave) { + QCheckBox* checkBox = qobject_cast(obj); + if (checkBox) { + bool hovered = (event->type() == QEvent::HoverEnter); + onPatchCheckBoxHovered(checkBox, hovered); + return true; + } + } + // Pass the event on to base class + return QWidget::eventFilter(obj, event); +} + +void CheatsPatches::onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered) { + if (hovered) { + QString text = checkBox->text(); + updateNoteTextEdit(text); + } else { + instructionsTextEdit->setText(defaultTextEdit); + } +} \ No newline at end of file diff --git a/src/qt_gui/cheats_patches.h b/src/qt_gui/cheats_patches.h new file mode 100644 index 000000000..7a68829cd --- /dev/null +++ b/src/qt_gui/cheats_patches.h @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef CHEATS_PATCHES_H +#define CHEATS_PATCHES_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class CheatsPatches : public QWidget { + Q_OBJECT + +public: + CheatsPatches(const QString& gameName, const QString& gameSerial, const QString& gameVersion, + const QString& gameSize, const QPixmap& gameImage, QWidget* parent = nullptr); + ~CheatsPatches(); + + // Public Methods + void downloadCheats(const QString& source, const QString& m_gameSerial, + const QString& m_gameVersion, bool showMessageBox); + void downloadPatches(const QString repository, const bool showMessageBox); + +signals: + void downloadFinished(); + +private: + // UI Setup and Event Handlers + void setupUI(); + void onSaveButtonClicked(); + QCheckBox* findCheckBoxByName(const QString& name); + bool eventFilter(QObject* obj, QEvent* event); + void onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered); + + // Cheat and Patch Management + void populateFileListCheats(); + void populateFileListPatches(); + + void addCheatsToLayout(const QJsonArray& modsArray, const QJsonArray& creditsArray); + void addPatchesToLayout(const QString& serial); + + void applyCheat(const QString& modName, bool enabled); + void applyPatch(const QString& patchName, bool enabled); + + void createFilesJson(const QString& repository); + void uncheckAllCheatCheckBoxes(); + void updateNoteTextEdit(const QString& patchName); + + // Network Manager + QNetworkAccessManager* manager; + + // Patch Info Structures + struct MemoryMod { + QString offset; + QString on; + QString off; + }; + + struct Cheat { + QString name; + QString type; + bool hasHint; + QVector memoryMods; + }; + + struct PatchInfo { + QString name; + QString author; + QString note; + QJsonArray linesArray; + QString serial; + }; + + // Members + QString m_gameName; + QString m_gameSerial; + QString m_gameVersion; + QString m_gameSize; + QPixmap m_gameImage; + QString m_cheatFilePath; + QMap m_cheats; + QMap m_patchInfos; + QVector m_cheatCheckBoxes; + + // UI Elements + QVBoxLayout* rightLayout; + QVBoxLayout* patchesGroupBoxLayout; + QGroupBox* patchesGroupBox; + QVBoxLayout* patchesLayout; + QTextEdit* instructionsTextEdit; + QListView* listView_selectFile; + QItemSelectionModel* selectionModel; + QComboBox* patchesComboBox; + QListView* patchesListView; + + QString defaultTextEdit; +}; + +#endif // CHEATS_PATCHES_H \ No newline at end of file diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index f4bc519a2..c43ff8f87 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -10,6 +10,7 @@ #include #include +#include "cheats_patches.h" #include "game_info.h" #include "trophy_viewer.h" @@ -20,6 +21,7 @@ #include #include #endif +#include "common/path_util.h" class GuiContextMenus : public QObject { Q_OBJECT @@ -34,15 +36,22 @@ public: itemID = widget->currentRow() * widget->columnCount() + widget->currentColumn(); } + // Do not show the menu if an item is selected + if (itemID == -1) { + return; + } + // Setup menu. QMenu menu(widget); QAction createShortcut(tr("Create Shortcut"), widget); QAction openFolder(tr("Open Game Folder"), widget); + QAction openCheats(tr("Cheats / Patches"), widget); QAction openSfoViewer(tr("SFO Viewer"), widget); QAction openTrophyViewer(tr("Trophy Viewer"), widget); menu.addAction(&openFolder); menu.addAction(&createShortcut); + menu.addAction(&openCheats); menu.addAction(&openSfoViewer); menu.addAction(&openTrophyViewer); @@ -121,6 +130,19 @@ public: } } + if (selected == &openCheats) { + QString gameName = QString::fromStdString(m_games[itemID].name); + QString gameSerial = QString::fromStdString(m_games[itemID].serial); + QString gameVersion = QString::fromStdString(m_games[itemID].version); + QString gameSize = QString::fromStdString(m_games[itemID].size); + QPixmap gameImage(QString::fromStdString(m_games[itemID].icon_path)); + CheatsPatches* cheatsPatches = + new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage); + cheatsPatches->show(); + connect(widget->parent(), &QWidget::destroyed, cheatsPatches, + [widget, cheatsPatches]() { cheatsPatches->deleteLater(); }); + } + if (selected == &openTrophyViewer) { QString trophyPath = QString::fromStdString(m_games[itemID].serial); QString gameTrpPath = QString::fromStdString(m_games[itemID].path); diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 8a4281726..23668ef78 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -5,6 +5,7 @@ #include #include "about_dialog.h" +#include "cheats_patches.h" #include "common/io_file.h" #include "common/version.h" #include "core/file_format/pkg.h" @@ -164,7 +165,7 @@ void MainWindow::GetPhysicalDevices() { auto prop = physical_device.getProperties(); QString name = QString::fromUtf8(prop.deviceName, -1); if (prop.apiVersion < Vulkan::TargetVulkanApiVersion) { - name += " * Unsupported Vulkan Version"; + name += tr(" * Unsupported Vulkan Version"); } m_physical_devices.push_back(name); } @@ -317,6 +318,83 @@ void MainWindow::CreateConnects() { Config::setTableMode(2); }); + // Cheats/Patches Download. + connect(ui->downloadCheatsPatchesAct, &QAction::triggered, this, [this]() { + QDialog* panelDialog = new QDialog(this); + QVBoxLayout* layout = new QVBoxLayout(panelDialog); + QPushButton* downloadAllCheatsButton = + new QPushButton(tr("Download Cheats For All Installed Games"), panelDialog); + QPushButton* downloadAllPatchesButton = + new QPushButton(tr("Download Patches For All Games"), panelDialog); + + layout->addWidget(downloadAllCheatsButton); + layout->addWidget(downloadAllPatchesButton); + + panelDialog->setLayout(layout); + + connect(downloadAllCheatsButton, &QPushButton::clicked, this, [this, panelDialog]() { + QEventLoop eventLoop; + int pendingDownloads = 0; + + auto onDownloadFinished = [&]() { + if (--pendingDownloads <= 0) { + eventLoop.quit(); + } + }; + + for (const GameInfo& game : m_game_info->m_games) { + QString empty = ""; + QString gameSerial = QString::fromStdString(game.serial); + QString gameVersion = QString::fromStdString(game.version); + + CheatsPatches* cheatsPatches = + new CheatsPatches(empty, empty, empty, empty, empty, nullptr); + connect(cheatsPatches, &CheatsPatches::downloadFinished, onDownloadFinished); + + pendingDownloads += 3; + + cheatsPatches->downloadCheats("wolf2022", gameSerial, gameVersion, false); + cheatsPatches->downloadCheats("GoldHEN", gameSerial, gameVersion, false); + cheatsPatches->downloadCheats("shadPS4", gameSerial, gameVersion, false); + } + eventLoop.exec(); + + QMessageBox::information( + nullptr, tr("Download Complete"), + tr("You have downloaded cheats for all the games you have installed.")); + + panelDialog->accept(); + }); + connect(downloadAllPatchesButton, &QPushButton::clicked, this, [this, panelDialog]() { + QEventLoop eventLoop; + int pendingDownloads = 0; + + auto onDownloadFinished = [&]() { + if (--pendingDownloads <= 0) { + eventLoop.quit(); + } + }; + + QString empty = ""; + CheatsPatches* cheatsPatches = + new CheatsPatches(empty, empty, empty, empty, empty, nullptr); + connect(cheatsPatches, &CheatsPatches::downloadFinished, onDownloadFinished); + + pendingDownloads += 2; + + cheatsPatches->downloadPatches("GoldHEN", false); + cheatsPatches->downloadPatches("shadPS4", false); + + eventLoop.exec(); + QMessageBox::information( + nullptr, tr("Download Complete"), + QString(tr("Patches Downloaded Successfully!") + "\n" + + tr("All Patches available for all games have been downloaded."))); + panelDialog->accept(); + }); + panelDialog->exec(); + }); + // Dump game list. connect(ui->dumpGameListAct, &QAction::triggered, this, [&] { QString filePath = qApp->applicationDirPath().append("/GameList.txt"); @@ -468,7 +546,7 @@ void MainWindow::RefreshGameTable() { m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); statusBar->clearMessage(); int numGames = m_game_info->m_games.size(); - QString statusMessage = "Games: " + QString::number(numGames); + QString statusMessage = tr("Games: ") + QString::number(numGames); statusBar->showMessage(statusMessage); } @@ -519,7 +597,8 @@ void MainWindow::BootGame() { int nFiles = fileNames.size(); if (nFiles > 1) { - QMessageBox::critical(nullptr, "Game Boot", QString("Only one file can be selected!")); + QMessageBox::critical(nullptr, tr("Game Boot"), + QString(tr("Only one file can be selected!"))); } else { std::filesystem::path path(fileNames[0].toStdString()); #ifdef _WIN64 @@ -542,7 +621,7 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int QDir game_dir(QString::fromStdString(extract_path.string())); if (game_dir.exists()) { QMessageBox msgBox; - msgBox.setWindowTitle("PKG Extraction"); + msgBox.setWindowTitle(tr("PKG Extraction")); if (pkgType.contains("PATCH")) { psf.open("", pkg.sfo); QString pkg_app_version = QString::fromStdString(psf.GetString("APP_VER")); @@ -551,23 +630,24 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int double appD = game_app_version.toDouble(); double pkgD = pkg_app_version.toDouble(); if (pkgD == appD) { - msgBox.setText( - QString("Patch detected!\nPKG and Game versions match!: %1\nWould you like " - "to overwrite?") - .arg(pkg_app_version)); + msgBox.setText(QString(tr("Patch detected!\nPKG and Game versions match!: " + "%1\nWould you like ") + + tr("to overwrite?")) + .arg(pkg_app_version)); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } else if (pkgD < appD) { - msgBox.setText(QString("Patch detected!\nPKG Version %1 is older " - "than installed version!: %2\nWould you like " - "to overwrite?") + msgBox.setText(QString(tr("Patch detected!\nPKG Version %1 is older ") + + tr("than installed version!: %2\nWould you like ") + + tr("to overwrite?")) .arg(pkg_app_version, game_app_version)); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } else { - msgBox.setText(QString("Patch detected!\nGame is installed: %1\nWould you like " - "to install Patch: %2?") - .arg(game_app_version, pkg_app_version)); + msgBox.setText( + QString(tr("Patch detected!\nGame is installed: %1\nWould you like ") + + tr("to install Patch: %2?")) + .arg(game_app_version, pkg_app_version)); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } @@ -578,8 +658,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int return; } } else { - msgBox.setText(QString("Game already installed\n%1\nWould you like to overwrite?") - .arg(QString::fromStdString(extract_path.string()))); + msgBox.setText( + QString(tr("Game already installed\n%1\nWould you like to overwrite?")) + .arg(QString::fromStdString(extract_path.string()))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int result = msgBox.exec(); @@ -592,15 +673,15 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } else { // Do nothing; if (pkgType.contains("PATCH")) { - QMessageBox::information(this, "PKG Extraction", - "PKG is a patch, please install the game first!"); + QMessageBox::information(this, tr("PKG Extraction"), + tr("PKG is a patch, please install the game first!")); return; } // what else? } if (!pkg.Extract(file, extract_path, failreason)) { - QMessageBox::critical(this, "PKG ERROR", QString::fromStdString(failreason)); + QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason)); } else { int nfiles = pkg.GetNumberOfFiles(); @@ -610,9 +691,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } QProgressDialog dialog; - dialog.setWindowTitle("PKG Extraction"); + dialog.setWindowTitle(tr("PKG Extraction")); dialog.setWindowModality(Qt::WindowModal); - QString extractmsg = QString("Extracting PKG %1/%2").arg(pkgNum).arg(nPkg); + QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg); dialog.setLabelText(extractmsg); dialog.setAutoClose(true); dialog.setRange(0, nfiles); @@ -622,8 +703,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int if (pkgNum == nPkg) { QString path = QString::fromStdString(Config::getGameInstallDir()); QMessageBox extractMsgBox(this); - extractMsgBox.setWindowTitle("Extraction Finished"); - extractMsgBox.setText(QString("Game successfully installed at %1").arg(path)); + extractMsgBox.setWindowTitle(tr("Extraction Finished")); + extractMsgBox.setText( + QString(tr("Game successfully installed at %1")).arg(path)); extractMsgBox.addButton(QMessageBox::Ok); extractMsgBox.setDefaultButton(QMessageBox::Ok); connect(&extractMsgBox, &QMessageBox::buttonClicked, this, @@ -644,7 +726,8 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int dialog.exec(); } } else { - QMessageBox::critical(this, "PKG ERROR", "File doesn't appear to be a valid PKG file"); + QMessageBox::critical(this, tr("PKG ERROR"), + tr("File doesn't appear to be a valid PKG file")); } } diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 1a2a560e0..498cec735 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -25,6 +25,7 @@ public: QAction* setlistModeGridAct; QAction* setlistElfAct; QAction* gameInstallPathAct; + QAction* downloadCheatsPatchesAct; QAction* dumpGameListAct; QAction* pkgViewerAct; QAction* aboutAct; @@ -120,11 +121,12 @@ public: gameInstallPathAct = new QAction(MainWindow); gameInstallPathAct->setObjectName("gameInstallPathAct"); gameInstallPathAct->setIcon(QIcon(":images/folder_icon.png")); + downloadCheatsPatchesAct = new QAction(MainWindow); + downloadCheatsPatchesAct->setObjectName("downloadCheatsPatchesAct"); dumpGameListAct = new QAction(MainWindow); dumpGameListAct->setObjectName("dumpGameList"); pkgViewerAct = new QAction(MainWindow); pkgViewerAct->setObjectName("pkgViewer"); - pkgViewerAct->setObjectName("pkgViewer"); pkgViewerAct->setIcon(QIcon(":images/file_icon.png")); aboutAct = new QAction(MainWindow); aboutAct->setObjectName("aboutAct"); @@ -277,6 +279,7 @@ public: menuSettings->addAction(configureAct); menuSettings->addAction(gameInstallPathAct); menuSettings->addAction(menuUtils->menuAction()); + menuUtils->addAction(downloadCheatsPatchesAct); menuUtils->addAction(dumpGameListAct); menuUtils->addAction(pkgViewerAct); menuAbout->addAction(aboutAct); @@ -323,6 +326,8 @@ public: setlistElfAct->setText(QCoreApplication::translate("MainWindow", "Elf Viewer", nullptr)); gameInstallPathAct->setText( QCoreApplication::translate("MainWindow", "Game Install Directory", nullptr)); + downloadCheatsPatchesAct->setText( + QCoreApplication::translate("MainWindow", "Download Cheats/Patches", nullptr)); dumpGameListAct->setText( QCoreApplication::translate("MainWindow", "Dump Game List", nullptr)); pkgViewerAct->setText(QCoreApplication::translate("MainWindow", "PKG Viewer", nullptr)); diff --git a/src/qt_gui/memory_patcher.cpp b/src/qt_gui/memory_patcher.cpp new file mode 100644 index 000000000..d5ffa1c99 --- /dev/null +++ b/src/qt_gui/memory_patcher.cpp @@ -0,0 +1,347 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common/logging/log.h" +#include "common/path_util.h" +#include "memory_patcher.h" + +namespace MemoryPatcher { + +uintptr_t g_eboot_address; +u64 g_eboot_image_size; +std::string g_game_serial; +std::vector pending_patches; + +QString toHex(unsigned long long value, size_t byteSize) { + std::stringstream ss; + ss << std::hex << std::setfill('0') << std::setw(byteSize * 2) << value; + return QString::fromStdString(ss.str()); +} + +QString convertValueToHex(const QString& type, const QString& valueStr) { + QString result; + std::string typeStr = type.toStdString(); + std::string valueStrStd = valueStr.toStdString(); + + if (typeStr == "byte") { + unsigned int value = std::stoul(valueStrStd, nullptr, 16); + result = toHex(value, 1); + } else if (typeStr == "bytes16") { + unsigned int value = std::stoul(valueStrStd, nullptr, 16); + result = toHex(value, 2); + } else if (typeStr == "bytes32") { + unsigned long value = std::stoul(valueStrStd, nullptr, 16); + result = toHex(value, 4); + } else if (typeStr == "bytes64") { + unsigned long long value = std::stoull(valueStrStd, nullptr, 16); + result = toHex(value, 8); + } else if (typeStr == "float32") { + union { + float f; + uint32_t i; + } floatUnion; + floatUnion.f = std::stof(valueStrStd); + result = toHex(floatUnion.i, sizeof(floatUnion.i)); + } else if (typeStr == "float64") { + union { + double d; + uint64_t i; + } doubleUnion; + doubleUnion.d = std::stod(valueStrStd); + result = toHex(doubleUnion.i, sizeof(doubleUnion.i)); + } else if (typeStr == "utf8") { + QByteArray byteArray = QString::fromStdString(valueStrStd).toUtf8(); + byteArray.append('\0'); + std::stringstream ss; + for (unsigned char c : byteArray) { + ss << std::hex << std::setfill('0') << std::setw(2) << static_cast(c); + } + result = QString::fromStdString(ss.str()); + } else if (typeStr == "utf16") { + QByteArray byteArray( + reinterpret_cast(QString::fromStdString(valueStrStd).utf16()), + QString::fromStdString(valueStrStd).size() * 2); + byteArray.append('\0'); + byteArray.append('\0'); + std::stringstream ss; + for (unsigned char c : byteArray) { + ss << std::hex << std::setfill('0') << std::setw(2) << static_cast(c); + } + result = QString::fromStdString(ss.str()); + } else if (typeStr == "bytes") { + result = valueStr; + } else if (typeStr == "mask" || typeStr == "mask_jump32") { + result = valueStr; + } else { + LOG_INFO(Loader, "Error applying Patch, unknown type: {}", typeStr); + } + return result; +} + +void OnGameLoaded() { + + // We use the QT headers for the xml and json parsing, this define is only true on QT builds + QString patchDir = + QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir).string()); + QString repositories[] = {"GoldHEN", "shadPS4"}; + + for (const QString& repository : repositories) { + QString filesJsonPath = patchDir + "/" + repository + "/files.json"; + + QFile jsonFile(filesJsonPath); + if (!jsonFile.open(QIODevice::ReadOnly)) { + LOG_ERROR(Loader, "Unable to open files.json for reading."); + continue; + } + + QByteArray jsonData = jsonFile.readAll(); + jsonFile.close(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + + QString selectedFileName; + QString serial = QString::fromStdString(g_game_serial); + + for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) { + QString filePath = it.key(); + QJsonArray idsArray = it.value().toArray(); + + if (idsArray.contains(QJsonValue(serial))) { + selectedFileName = filePath; + break; + } + } + + if (selectedFileName.isEmpty()) { + LOG_ERROR(Loader, "No patch file found for the current serial."); + continue; + } + + QString filePath = patchDir + "/" + repository + "/" + selectedFileName; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + LOG_ERROR(Loader, "Unable to open the file for reading."); + continue; + } + + QByteArray xmlData = file.readAll(); + file.close(); + + QString newXmlData; + + QXmlStreamReader xmlReader(xmlData); + bool insideMetadata = false; + + bool isEnabled = false; + std::string currentPatchName; + while (!xmlReader.atEnd()) { + xmlReader.readNext(); + + if (xmlReader.isStartElement()) { + QJsonArray patchLines; + if (xmlReader.name() == QStringLiteral("Metadata")) { + insideMetadata = true; + + QString name = xmlReader.attributes().value("Name").toString(); + currentPatchName = name.toStdString(); + + // Check and update the isEnabled attribute + for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { + if (attr.name() == QStringLiteral("isEnabled")) { + if (attr.value().toString() == "true") { + isEnabled = true; + } else + isEnabled = false; + } + } + } else if (xmlReader.name() == QStringLiteral("PatchList")) { + QJsonArray linesArray; + while (!xmlReader.atEnd() && + !(xmlReader.tokenType() == QXmlStreamReader::EndElement && + xmlReader.name() == QStringLiteral("PatchList"))) { + xmlReader.readNext(); + if (xmlReader.tokenType() == QXmlStreamReader::StartElement && + xmlReader.name() == QStringLiteral("Line")) { + QXmlStreamAttributes attributes = xmlReader.attributes(); + QJsonObject lineObject; + lineObject["Type"] = attributes.value("Type").toString(); + lineObject["Address"] = attributes.value("Address").toString(); + lineObject["Value"] = attributes.value("Value").toString(); + linesArray.append(lineObject); + } + } + + patchLines = linesArray; + if (isEnabled) { + foreach (const QJsonValue& value, patchLines) { + QJsonObject lineObject = value.toObject(); + QString type = lineObject["Type"].toString(); + QString address = lineObject["Address"].toString(); + QString patchValue = lineObject["Value"].toString(); + QString maskOffsetStr = lineObject["Offset"].toString(); + + patchValue = convertValueToHex(type, patchValue); + + bool littleEndian = false; + + if (type == "bytes16") { + 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") { + 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); + } + } + } + } + } + + if (xmlReader.hasError()) { + LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial); + } else { + LOG_INFO(Loader, "Patches loaded successfully"); + } + ApplyPendingPatches(); + } +} + +void AddPatchToQueue(patchInfo patchToAdd) { + pending_patches.push_back(patchToAdd); +} + +void ApplyPendingPatches() { + + for (size_t i = 0; i < pending_patches.size(); ++i) { + patchInfo currentPatch = pending_patches[i]; + + if (currentPatch.gameSerial != g_game_serial) + continue; + + PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, + currentPatch.isOffset, currentPatch.littleEndian, currentPatch.patchMask, + currentPatch.maskOffset); + } + + pending_patches.clear(); +} + +void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset, + bool littleEndian, PatchMask patchMask, int maskOffset) { + // Send a request to modify the process memory. + void* cheatAddress = nullptr; + + if (patchMask == PatchMask::None) { + if (isOffset) { + cheatAddress = reinterpret_cast(g_eboot_address + std::stoi(offsetStr, 0, 16)); + } else { + cheatAddress = + reinterpret_cast(g_eboot_address + (std::stoi(offsetStr, 0, 16) - 0x400000)); + } + } + + if (patchMask == PatchMask::Mask) { + cheatAddress = reinterpret_cast(PatternScan(offsetStr) + maskOffset); + } + + // TODO: implement mask_jump32 + + if (cheatAddress == nullptr) { + LOG_ERROR(Loader, "Failed to get address for patch {}", modNameStr); + return; + } + + std::vector bytePatch; + + for (size_t i = 0; i < valueStr.length(); i += 2) { + unsigned char byte = + static_cast(std::strtol(valueStr.substr(i, 2).c_str(), nullptr, 16)); + + bytePatch.push_back(byte); + } + + if (littleEndian) { + std::reverse(bytePatch.begin(), bytePatch.end()); + } + + std::memcpy(cheatAddress, bytePatch.data(), bytePatch.size()); + + LOG_INFO(Loader, "Applied patch: {}, Offset: {}, Value: {}", modNameStr, + (uintptr_t)cheatAddress, valueStr); +} + +static std::vector PatternToByte(const std::string& pattern) { + std::vector bytes; + const char* start = pattern.data(); + const char* end = start + pattern.size(); + + for (const char* current = start; current < end; ++current) { + if (*current == '?') { + ++current; + if (*current == '?') + ++current; + bytes.push_back(-1); + } else { + bytes.push_back(strtoul(current, const_cast(¤t), 16)); + } + } + + return bytes; +} + +uintptr_t PatternScan(const std::string& signature) { + std::vector patternBytes = PatternToByte(signature); + const auto scanBytes = static_cast((void*)g_eboot_address); + + const int32_t* sigPtr = patternBytes.data(); + const size_t sigSize = patternBytes.size(); + + uint32_t foundResults = 0; + for (uint32_t i = 0; i < g_eboot_image_size - sigSize; ++i) { + bool found = true; + for (uint32_t j = 0; j < sigSize; ++j) { + if (scanBytes[i + j] != sigPtr[j] && sigPtr[j] != -1) { + found = false; + break; + } + } + + if (found) { + foundResults++; + return reinterpret_cast(&scanBytes[i]); + } + } + + return 0; +} + +} // namespace MemoryPatcher \ No newline at end of file diff --git a/src/qt_gui/memory_patcher.h b/src/qt_gui/memory_patcher.h new file mode 100644 index 000000000..821184ade --- /dev/null +++ b/src/qt_gui/memory_patcher.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include +#include +#include +#include + +namespace MemoryPatcher { + +extern uintptr_t g_eboot_address; +extern u64 g_eboot_image_size; +extern std::string g_game_serial; + +enum PatchMask : uint8_t { + None, + Mask, + Mask_Jump32, +}; + +struct patchInfo { + std::string gameSerial; + std::string modNameStr; + std::string offsetStr; + std::string valueStr; + bool isOffset; + bool littleEndian; + PatchMask patchMask; + int maskOffset; +}; + +extern std::vector pending_patches; + +QString convertValueToHex(const QString& type, const QString& valueStr); + +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); + +static std::vector PatternToByte(const std::string& pattern); +uintptr_t PatternScan(const std::string& signature); + +} // namespace MemoryPatcher \ No newline at end of file diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index 0f4489eed..de9097f2b 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Trick / Patches + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Download Tricks / Patches + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging + + + MainWindow + + + * Unsupported Vulkan Version + * Ikke understøttet Vulkan-version + + + + Download Cheats For All Installed Games + Hent snyd til alle installerede spil + + + + Download Patches For All Games + Hent patches til alle spil + + + + Download Complete + Download fuldført + + + + You have downloaded cheats for all the games you have installed. + Du har hentet snyd til alle de spil, du har installeret. + + + + Patches Downloaded Successfully! + Patcher hentet med succes! + + + + All Patches available for all games have been downloaded. + Alle patches til alle spil er blevet hentet. + + + + Games: + Spil: + + + + PKG File (*.PKG) + PKG-fil (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF-filer (*.bin *.elf *.oelf) + + + + Game Boot + Spil-boot + + + + Only one file can be selected! + Kun én fil kan vælges! + + + + PKG Extraction + PKG-udtrækning + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch opdaget!\nPKG- og spilversioner stemmer overens!: %1\nVil du + + + + to overwrite? + overskrive? + + + + Patch detected!\nPKG Version %1 is older + Patch opdaget!\nPKG-version %1 er ældre + + + + than installed version!: %2\nWould you like + end installeret version!: %2\nVil du + + + + to overwrite? + overskrive? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch opdaget!\nSpillet er installeret: %1\nVil du + + + + to install Patch: %2? + installere patch: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Spil allerede installeret\n%1\nVil du overskrive? + + + + PKG is a patch, please install the game first! + PKG er en patch, venligst installer spillet først! + + + + PKG ERROR + PKG FEJL + + + + Extracting PKG %1/%2 + Udvinding af PKG %1/%2 + + + + Extraction Finished + Udvinding afsluttet + + + + Game successfully installed at %1 + Spillet blev installeret succesfuldt på %1 + + + + File doesn't appear to be a valid PKG file + Filen ser ikke ud til at være en gyldig PKG-fil + + + + CheatsPatches + + + Cheats / Patches + Snyd / Patches + + + + defaultTextEdit_MSG + Cheats/Patches er eksperimentelle.\nBrug med forsigtighed.\n\nDownload cheats individuelt ved at vælge lageret og klikke på download-knappen.\nUnder fanen Patches kan du downloade alle patches på én gang, vælge hvilke du vil bruge og gemme valget.\n\nDa vi ikke udvikler cheats/patches,\nvenligst rapporter problemer til cheat-udvikleren.\n\nHar du lavet en ny cheat? Besøg:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Ingen billede tilgængelig + + + + Serial: + Serienummer: + + + + Version: + Version: + + + + Size: + Størrelse: + + + + Select Cheat File: + Vælg snyd-fil: + + + + Repository: + Repository: + + + + Download Cheats + Hent snyd + + + + Delete File + Slet fil + + + + No files selected. + Ingen filer valgt. + + + + You can delete the cheats you don't want after downloading them. + Du kan slette de snyd, du ikke ønsker, efter at have hentet dem. + + + + Do you want to delete the selected file?\n%1 + Ønsker du at slette den valgte fil?\n%1 + + + + Select Patch File: + Vælg patch-fil: + + + + Download Patches + Hent patches + + + + Save + Gem + + + + Cheats + Snyd + + + + Patches + Patches + + + + Error + Fejl + + + + No patch selected. + Ingen patch valgt. + + + + Unable to open files.json for reading. + Kan ikke åbne files.json til læsning. + + + + No patch file found for the current serial. + Ingen patch-fil fundet for det nuværende serienummer. + + + + Unable to open the file for reading. + Kan ikke åbne filen til læsning. + + + + Unable to open the file for writing. + Kan ikke åbne filen til skrivning. + + + + Failed to parse XML: + Kunne ikke analysere XML: + + + + Success + Succes + + + + Options saved successfully. + Indstillinger gemt med succes. + + + + Invalid Source + Ugyldig kilde + + + + The selected source is invalid. + Den valgte kilde er ugyldig. + + + + File Exists + Fil findes + + + + File already exists. Do you want to replace it? + Filen findes allerede. Vil du erstatte den? + + + + Failed to save file: + Kunne ikke gemme fil: + + + + Failed to download file: + Kunne ikke hente fil: + + + + Cheats Not Found + Snyd ikke fundet + + + + CheatsNotFound_MSG + Ingen snyd fundet til dette spil i denne version af det valgte repository, prøv et andet repository eller en anden version af spillet. + + + + Cheats Downloaded Successfully + Snyd hentet med succes + + + + CheatsDownloadedSuccessfully_MSG + Du har succesfuldt hentet snyd for denne version af spillet fra det valgte repository. Du kan prøve at hente fra et andet repository, hvis det er tilgængeligt, vil det også være muligt at bruge det ved at vælge filen fra listen. + + + + Failed to save: + Kunne ikke gemme: + + + + Failed to download: + Kunne ikke hente: + + + + Download Complete + Download fuldført + + + + DownloadComplete_MSG + Patcher hentet med succes! Alle patches til alle spil er blevet hentet, der er ikke behov for at hente dem individuelt for hvert spil, som det sker med snyd. + + + + Failed to parse JSON data from HTML. + Kunne ikke analysere JSON-data fra HTML. + + + + Failed to retrieve HTML page. + Kunne ikke hente HTML-side. + + + + Failed to open file: + Kunne ikke åbne fil: + + + + XML ERROR: + XML FEJL: + + + + Failed to open files.json for writing + Kunne ikke åbne files.json til skrivning + + + + Author: + Forfatter: + + + + Directory does not exist: + Mappe findes ikke: + + + + Failed to open files.json for reading. + Kunne ikke åbne files.json til læsning. + + + + Name: + Navn: + \ No newline at end of file diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index 1ff204df9..6183c812d 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Cheats / Patches + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Cheats / Patches herunterladen + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging + + + MainWindow + + + * Unsupported Vulkan Version + * Nicht unterstützte Vulkan-Version + + + + Download Cheats For All Installed Games + Cheats für alle installierten Spiele herunterladen + + + + Download Patches For All Games + Patches für alle Spiele herunterladen + + + + Download Complete + Download abgeschlossen + + + + You have downloaded cheats for all the games you have installed. + Sie haben Cheats für alle installierten Spiele heruntergeladen. + + + + Patches Downloaded Successfully! + Patches erfolgreich heruntergeladen! + + + + All Patches available for all games have been downloaded. + Alle Patches für alle Spiele wurden heruntergeladen. + + + + Games: + Spiele: + + + + PKG File (*.PKG) + PKG-Datei (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF-Dateien (*.bin *.elf *.oelf) + + + + Game Boot + Spiel-Start + + + + Only one file can be selected! + Es kann nur eine Datei ausgewählt werden! + + + + PKG Extraction + PKG-Extraktion + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch erkannt!\nPKG- und Spielversion stimmen überein!: %1\nMöchten Sie + + + + to overwrite? + überschreiben? + + + + Patch detected!\nPKG Version %1 is older + Patch erkannt!\nPKG-Version %1 ist älter + + + + than installed version!: %2\nWould you like + als die installierte Version!: %2\nMöchten Sie + + + + to overwrite? + überschreiben? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch erkannt!\nSpiel ist installiert: %1\nMöchten Sie + + + + to install Patch: %2? + Patch installieren: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Spiel bereits installiert\n%1\nMöchten Sie überschreiben? + + + + PKG is a patch, please install the game first! + PKG ist ein Patch, bitte installieren Sie zuerst das Spiel! + + + + PKG ERROR + PKG-ERROR + + + + Extracting PKG %1/%2 + Extrahiere PKG %1/%2 + + + + Extraction Finished + Extraktion abgeschlossen + + + + Game successfully installed at %1 + Spiel erfolgreich installiert auf %1 + + + + File doesn't appear to be a valid PKG file + Die Datei scheint keine gültige PKG-Datei zu sein + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches sind experimentell.\nVerwenden Sie sie mit Vorsicht.\n\nLaden Sie Cheats einzeln herunter, indem Sie das Repository auswählen und auf die Download-Schaltfläche klicken.\nAuf der Registerkarte Patches können Sie alle Patches auf einmal herunterladen, auswählen, welche Sie verwenden möchten, und die Auswahl speichern.\n\nDa wir die Cheats/Patches nicht entwickeln,\nbitte melden Sie Probleme an den Cheat-Autor.\n\nHaben Sie einen neuen Cheat erstellt? Besuchen Sie:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Kein Bild verfügbar + + + + Serial: + Seriennummer: + + + + Version: + Version: + + + + Size: + Größe: + + + + Select Cheat File: + Cheat-Datei auswählen: + + + + Repository: + Repository: + + + + Download Cheats + Cheats herunterladen + + + + Delete File + Datei löschen + + + + No files selected. + Keine Dateien ausgewählt. + + + + You can delete the cheats you don't want after downloading them. + Sie können die Cheats, die Sie nicht möchten, nach dem Herunterladen löschen. + + + + Do you want to delete the selected file?\n%1 + Wollen Sie die ausgewählte Datei löschen?\n%1 + + + + Select Patch File: + Patch-Datei auswählen: + + + + Download Patches + Patches herunterladen + + + + Save + Speichern + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Fehler + + + + No patch selected. + Kein Patch ausgewählt. + + + + Unable to open files.json for reading. + Kann files.json nicht zum Lesen öffnen. + + + + No patch file found for the current serial. + Keine Patch-Datei für die aktuelle Seriennummer gefunden. + + + + Unable to open the file for reading. + Kann die Datei nicht zum Lesen öffnen. + + + + Unable to open the file for writing. + Kann die Datei nicht zum Schreiben öffnen. + + + + Failed to parse XML: + Fehler beim Parsen von XML: + + + + Success + Erfolg + + + + Options saved successfully. + Optionen erfolgreich gespeichert. + + + + Invalid Source + Ungültige Quelle + + + + The selected source is invalid. + Die ausgewählte Quelle ist ungültig. + + + + File Exists + Datei existiert + + + + File already exists. Do you want to replace it? + Datei existiert bereits. Möchten Sie sie ersetzen? + + + + Failed to save file: + Fehler beim Speichern der Datei: + + + + Failed to download file: + Fehler beim Herunterladen der Datei: + + + + Cheats Not Found + Cheats nicht gefunden + + + + CheatsNotFound_MSG + Keine Cheats für dieses Spiel in dieser Version des gewählten Repositories gefunden. Versuchen Sie es mit einem anderen Repository oder einer anderen Version des Spiels. + + + + Cheats Downloaded Successfully + Cheats erfolgreich heruntergeladen + + + + CheatsDownloadedSuccessfully_MSG + Sie haben erfolgreich Cheats für diese Version des Spiels aus dem gewählten Repository heruntergeladen. Sie können versuchen, von einem anderen Repository herunterzuladen. Wenn verfügbar, können Sie es auswählen, indem Sie die Datei aus der Liste auswählen. + + + + Failed to save: + Speichern fehlgeschlagen: + + + + Failed to download: + Herunterladen fehlgeschlagen: + + + + Download Complete + Download abgeschlossen + + + + DownloadComplete_MSG + Patches erfolgreich heruntergeladen! Alle Patches für alle Spiele wurden heruntergeladen, es ist nicht notwendig, sie einzeln für jedes Spiel herunterzuladen, wie es bei Cheats der Fall ist. + + + + Failed to parse JSON data from HTML. + Fehler beim Parsen der JSON-Daten aus HTML. + + + + Failed to retrieve HTML page. + Fehler beim Abrufen der HTML-Seite. + + + + Failed to open file: + Fehler beim Öffnen der Datei: + + + + XML ERROR: + XML-Fehler: + + + + Failed to open files.json for writing + Kann files.json nicht zum Schreiben öffnen + + + + Author: + Autor: + + + + Directory does not exist: + Verzeichnis existiert nicht: + + + + Failed to open files.json for reading. + Kann files.json nicht zum Lesen öffnen. + + + + Name: + Name: + \ No newline at end of file diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts index b015954e6..5d4a15d8a 100644 --- a/src/qt_gui/translations/el.ts +++ b/src/qt_gui/translations/el.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Kodikí / Enimeróseis + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Κατεβάστε Κωδικούς / Ενημερώσεις + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging + + + MainWindow + + + * Unsupported Vulkan Version + * Μη υποστηριζόμενη έκδοση Vulkan + + + + Download Cheats For All Installed Games + Λήψη Cheats για όλα τα εγκατεστημένα παιχνίδια + + + + Download Patches For All Games + Λήψη Patches για όλα τα παιχνίδια + + + + Download Complete + Η λήψη ολοκληρώθηκε + + + + You have downloaded cheats for all the games you have installed. + Έχετε κατεβάσει cheats για όλα τα εγκατεστημένα παιχνίδια. + + + + Patches Downloaded Successfully! + Τα Patches κατέβηκαν επιτυχώς! + + + + All Patches available for all games have been downloaded. + Όλα τα διαθέσιμα Patches για όλα τα παιχνίδια έχουν κατέβει. + + + + Games: + Παιχνίδια: + + + + PKG File (*.PKG) + Αρχείο PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Αρχεία ELF (*.bin *.elf *.oelf) + + + + Game Boot + Εκκίνηση παιχνιδιού + + + + Only one file can be selected! + Μπορεί να επιλεγεί μόνο ένα αρχείο! + + + + PKG Extraction + Εξαγωγή PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Ανίχνευση Patch!\nΟι εκδόσεις PKG και παιχνιδιού ταιριάζουν!: %1\nΘέλετε + + + + to overwrite? + να αντικαταστήσετε; + + + + Patch detected!\nPKG Version %1 is older + Ανίχνευση Patch!\nΗ έκδοση PKG %1 είναι παλαιότερη + + + + than installed version!: %2\nWould you like + από την εγκατεστημένη έκδοση!: %2\nΘέλετε + + + + to overwrite? + να αντικαταστήσετε; + + + + Patch detected!\nGame is installed: %1\nWould you like + Ανίχνευση Patch!\nΤο παιχνίδι είναι εγκατεστημένο: %1\nΘέλετε + + + + to install Patch: %2? + να εγκαταστήσετε το Patch: %2; + + + + Game already installed\n%1\nWould you like to overwrite? + Το παιχνίδι είναι ήδη εγκατεστημένο\n%1\nΘέλετε να αντικαταστήσετε; + + + + PKG is a patch, please install the game first! + Το PKG είναι patch, παρακαλώ εγκαταστήστε πρώτα το παιχνίδι! + + + + PKG ERROR + ΣΦΑΛΜΑ PKG + + + + Extracting PKG %1/%2 + Εξαγωγή PKG %1/%2 + + + + Extraction Finished + Η εξαγωγή ολοκληρώθηκε + + + + Game successfully installed at %1 + Το παιχνίδι εγκαταστάθηκε επιτυχώς στο %1 + + + + File doesn't appear to be a valid PKG file + Η αρχείο δεν φαίνεται να είναι έγκυρο αρχείο PKG + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Οι cheats/patches είναι πειραματικά.\nΧρησιμοποιήστε τα με προσοχή.\n\nΚατεβάστε τους cheats μεμονωμένα επιλέγοντας το αποθετήριο και κάνοντας κλικ στο κουμπί λήψης.\nΣτην καρτέλα Patches, μπορείτε να κατεβάσετε όλα τα patches ταυτόχρονα, να επιλέξετε ποια θέλετε να χρησιμοποιήσετε και να αποθηκεύσετε την επιλογή.\n\nΔεδομένου ότι δεν αναπτύσσουμε τους cheats/patches,\nπαρακαλώ αναφέρετε προβλήματα στον δημιουργό του cheat.\n\nΔημιουργήσατε ένα νέο cheat; Επισκεφθείτε:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Δεν διατίθεται εικόνα + + + + Serial: + Σειριακός αριθμός: + + + + Version: + Έκδοση: + + + + Size: + Μέγεθος: + + + + Select Cheat File: + Επιλέξτε αρχείο Cheat: + + + + Repository: + Αποθετήριο: + + + + Download Cheats + Λήψη Cheats + + + + Delete File + Διαγραφή αρχείου + + + + No files selected. + Δεν έχουν επιλεγεί αρχεία. + + + + You can delete the cheats you don't want after downloading them. + Μπορείτε να διαγράψετε τα cheats που δεν θέλετε μετά τη λήψη τους. + + + + Do you want to delete the selected file?\n%1 + Θέλετε να διαγράψετε το επιλεγμένο αρχείο;\n%1 + + + + Select Patch File: + Επιλέξτε αρχείο Patch: + + + + Download Patches + Λήψη Patches + + + + Save + Αποθήκευση + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Σφάλμα + + + + No patch selected. + Δεν έχει επιλεγεί κανένα patch. + + + + Unable to open files.json for reading. + Αδυναμία ανοίγματος του files.json για ανάγνωση. + + + + No patch file found for the current serial. + Δεν βρέθηκε αρχείο patch για τον τρέχοντα σειριακό αριθμό. + + + + Unable to open the file for reading. + Αδυναμία ανοίγματος του αρχείου για ανάγνωση. + + + + Unable to open the file for writing. + Αδυναμία ανοίγματος του αρχείου για εγγραφή. + + + + Failed to parse XML: + Αποτυχία ανάλυσης XML: + + + + Success + Επιτυχία + + + + Options saved successfully. + Οι ρυθμίσεις αποθηκεύτηκαν επιτυχώς. + + + + Invalid Source + Μη έγκυρη Πηγή + + + + The selected source is invalid. + Η επιλεγμένη πηγή είναι μη έγκυρη. + + + + File Exists + Η αρχείο υπάρχει + + + + File already exists. Do you want to replace it? + Η αρχείο υπάρχει ήδη. Θέλετε να την αντικαταστήσετε; + + + + Failed to save file: + Αποτυχία αποθήκευσης αρχείου: + + + + Failed to download file: + Αποτυχία λήψης αρχείου: + + + + Cheats Not Found + Δεν βρέθηκαν Cheats + + + + CheatsNotFound_MSG + Δεν βρέθηκαν cheats για αυτό το παιχνίδι στην τρέχουσα έκδοση του επιλεγμένου αποθετηρίου. Δοκιμάστε να κατεβάσετε από άλλο αποθετήριο ή άλλη έκδοση του παιχνιδιού. + + + + Cheats Downloaded Successfully + Cheats κατεβάστηκαν επιτυχώς + + + + CheatsDownloadedSuccessfully_MSG + Κατεβάσατε επιτυχώς cheats για αυτή την έκδοση του παιχνιδιού από το επιλεγμένο αποθετήριο. Μπορείτε να δοκιμάσετε να κατεβάσετε από άλλο αποθετήριο. Αν είναι διαθέσιμο, μπορείτε να το επιλέξετε επιλέγοντας το αρχείο από τη λίστα. + + + + Failed to save: + Αποτυχία αποθήκευσης: + + + + Failed to download: + Αποτυχία λήψης: + + + + Download Complete + Η λήψη ολοκληρώθηκε + + + + DownloadComplete_MSG + Τα Patches κατεβάστηκαν επιτυχώς! Όλα τα Patches για όλα τα παιχνίδια έχουν κατέβει, δεν είναι απαραίτητο να τα κατεβάσετε ένα-ένα για κάθε παιχνίδι, όπως με τα Cheats. + + + + Failed to parse JSON data from HTML. + Αποτυχία ανάλυσης δεδομένων JSON από HTML. + + + + Failed to retrieve HTML page. + Αποτυχία ανάκτησης σελίδας HTML. + + + + Failed to open file: + Αποτυχία ανοίγματος αρχείου: + + + + XML ERROR: + ΣΦΑΛΜΑ XML: + + + + Failed to open files.json for writing + Αποτυχία ανοίγματος του files.json για εγγραφή + + + + Author: + Συγγραφέας: + + + + Directory does not exist: + Ο φάκελος δεν υπάρχει: + + + + Failed to open files.json for reading. + Αποτυχία ανοίγματος του files.json για ανάγνωση. + + + + Name: + Όνομα: + \ No newline at end of file diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts index 5ceb11884..aa8a1a5d8 100644 --- a/src/qt_gui/translations/en.ts +++ b/src/qt_gui/translations/en.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Cheats / Patches + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Download Cheats / Patches + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * 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: + + + + PKG File (*.PKG) + PKG File (*.PKG) + + + + 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!\nPKG and Game versions match!: %1\nWould you like + Patch detected!\nPKG and Game versions match!: %1\nWould you like + + + + to overwrite? + to overwrite? + + + + Patch detected!\nPKG Version %1 is older + Patch detected!\nPKG Version %1 is older + + + + than installed version!: %2\nWould you like + than installed version!: %2\nWould you like + + + + to overwrite? + to overwrite? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch detected!\nGame is installed: %1\nWould you like + + + + to install Patch: %2? + to install Patch: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Game already installed\n%1\nWould you like to overwrite? + + + + PKG is a patch, please install the game first! + PKG is a patch, please install the game first! + + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + 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:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + 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 + + + + CheatsNotFound_MSG + 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 + + + + CheatsDownloadedSuccessfully_MSG + 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 + + + + DownloadComplete_MSG + 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. + + + + Failed to parse JSON data from HTML. + Failed to parse JSON data from HTML. + + + + Failed to retrieve HTML page. + Failed to retrieve HTML page. + + + + 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: + + \ No newline at end of file diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index 1b42b18e6..5b7ad4b6d 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Crear acceso directo - + Open Game Folder Abrir carpeta del juego - + + Cheats / Patches + Trucos / Parches + + + SFO Viewer Vista SFO - + Trophy Viewer Ver trofeos - + Copy info Copiar información - + Copy Name Copiar nombre - + Copy Serial Copiar serial - + Copy All Copiar todo - + Shortcut creation Acceso directo creado - + Shortcut created successfully!\n %1 ¡Acceso directo creado con éxito!\n %1 - + Error Error - + Error creating shortcut!\n %1 ¡Error al crear el acceso directo!\n %1 - + Install PKG Instalar PKG @@ -248,6 +253,11 @@ Game Install Directory Carpeta de instalación de los juegos + + + Download Cheats/Patches + Descargar Trucos / Parches + Dump Game List @@ -488,4 +498,395 @@ Habilitar depuración de RenderDoc - + + MainWindow + + + * Unsupported Vulkan Version + * Versión de Vulkan no soportada + + + + Download Cheats For All Installed Games + Descargar trucos para todos los juegos instalados + + + + Download Patches For All Games + Descargar parches para todos los juegos + + + + Download Complete + Descarga completa + + + + You have downloaded cheats for all the games you have installed. + Has descargado trucos para todos los juegos que tienes instalados. + + + + Patches Downloaded Successfully! + ¡Parches descargados exitosamente! + + + + All Patches available for all games have been downloaded. + Todos los parches disponibles para todos los juegos han sido descargados. + + + + Games: + Juegos: + + + + PKG File (*.PKG) + Archivo PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Archivos ELF (*.bin *.elf *.oelf) + + + + Game Boot + Inicio del juego + + + + Only one file can be selected! + ¡Solo se puede seleccionar un archivo! + + + + PKG Extraction + Extracción de PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + ¡Parche detectado!\n¡La versión de PKG y del juego coinciden!: %1\n¿Te gustaría + + + + to overwrite? + ¿sobrescribir? + + + + Patch detected!\nPKG Version %1 is older + ¡Parche detectado!\nLa versión de PKG %1 es más antigua + + + + than installed version!: %2\nWould you like + que la versión instalada!: %2\n¿Te gustaría + + + + to overwrite? + ¿sobrescribir? + + + + Patch detected!\nGame is installed: %1\nWould you like + ¡Parche detectado!\nJuego está instalado: %1\n¿Te gustaría + + + + to install Patch: %2? + ¿instalar el parche: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Juego ya instalado\n%1\n¿Te gustaría sobrescribirlo? + + + + PKG is a patch, please install the game first! + PKG es un parche, ¡por favor instala el juego primero! + + + + PKG ERROR + ERROR PKG + + + + Extracting PKG %1/%2 + Extrayendo PKG %1/%2 + + + + Extraction Finished + Extracción terminada + + + + Game successfully installed at %1 + Juego instalado exitosamente en %1 + + + + File doesn't appear to be a valid PKG file + El archivo no parece ser un archivo PKG válido + + + + CheatsPatches + + + Cheats / Patches + Trucos / Parches + + + + defaultTextEdit_MSG + Los cheats/patches son experimentales.\nÚselos con precaución.\n\nDescargue los cheats individualmente seleccionando el repositorio y haciendo clic en el botón de descarga.\nEn la pestaña Patches, puede descargar todos los patches a la vez, elegir cuáles desea usar y guardar la selección.\n\nComo no desarrollamos los Cheats/Patches,\npor favor informe los problemas al autor del cheat.\n\n¿Creaste un nuevo cheat? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + No hay imagen disponible + + + + Serial: + Serie: + + + + Version: + Versión: + + + + Size: + Tamaño: + + + + Select Cheat File: + Seleccionar archivo de trucos: + + + + Repository: + Repositorio: + + + + Download Cheats + Descargar trucos + + + + Delete File + Eliminar archivo + + + + No files selected. + No se han seleccionado archivos. + + + + You can delete the cheats you don't want after downloading them. + Puedes eliminar los trucos que no quieras después de descargarlos. + + + + Do you want to delete the selected file?\n%1 + ¿Deseas eliminar el archivo seleccionado?\n%1 + + + + Select Patch File: + Seleccionar archivo de parche: + + + + Download Patches + Descargar parches + + + + Save + Guardar + + + + Cheats + Trucos + + + + Patches + Parche + + + + Error + Error + + + + No patch selected. + No se ha seleccionado ningún parche. + + + + Unable to open files.json for reading. + No se puede abrir files.json para lectura. + + + + No patch file found for the current serial. + No se encontró ningún archivo de parche para la serie actual. + + + + Unable to open the file for reading. + No se puede abrir el archivo para lectura. + + + + Unable to open the file for writing. + No se puede abrir el archivo para escritura. + + + + Failed to parse XML: + Error al analizar XML: + + + + Success + Éxito + + + + Options saved successfully. + Opciones guardadas exitosamente. + + + + Invalid Source + Fuente inválida + + + + The selected source is invalid. + La fuente seleccionada es inválida. + + + + File Exists + El archivo ya existe + + + + File already exists. Do you want to replace it? + El archivo ya existe. ¿Deseas reemplazarlo? + + + + Failed to save file: + Error al guardar el archivo: + + + + Failed to download file: + Error al descargar el archivo: + + + + Cheats Not Found + Trucos no encontrados + + + + CheatsNotFound_MSG + No se encontraron trucos para este juego en esta versión del repositorio seleccionado,intenta con otro repositorio o con una versión diferente del juego. + + + + Cheats Downloaded Successfully + Trucos descargados exitosamente + + + + CheatsDownloadedSuccessfully_MSG + Has descargado exitosamente los trucos para esta versión del juego desde el repositorio seleccionado. Puedes intentar descargar desde otro repositorio; si está disponible, también será posible usarlo seleccionando el archivo de la lista. + + + + Failed to save: + Error al guardar: + + + + Failed to download: + Error al descargar: + + + + Download Complete + Descarga completa + + + + DownloadComplete_MSG + ¡Parches descargados exitosamente! Todos los parches disponibles para todos los juegos han sido descargados, no es necesario descargarlos individualmente para cada juego como ocurre con los trucos. + + + + Failed to parse JSON data from HTML. + Error al analizar los datos JSON del HTML. + + + + Failed to retrieve HTML page. + Error al recuperar la página HTML. + + + + Failed to open file: + Error al abrir el archivo: + + + + XML ERROR: + ERROR XML: + + + + Failed to open files.json for writing + Error al abrir files.json para escritura + + + + Author: + Autor: + + + + Directory does not exist: + El directorio no existe: + + + + Failed to open files.json for reading. + Error al abrir files.json para lectura. + + + + Name: + Nombre: + + + \ No newline at end of file diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts index af605d641..70345efbe 100644 --- a/src/qt_gui/translations/fi.ts +++ b/src/qt_gui/translations/fi.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Huijaukset / Korjaukset + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Lataa Huijaukset / Korjaukset + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * Unsupported Vulkan Version + * Tuettu Vulkan-versio + + + + Download Cheats For All Installed Games + Lataa huijaukset kaikille asennetuille peleille + + + + Download Patches For All Games + Lataa korjaukset kaikille peleille + + + + Download Complete + Lataus valmis + + + + You have downloaded cheats for all the games you have installed. + Olet ladannut huijaukset kaikkiin asennettuihin peleihin. + + + + Patches Downloaded Successfully! + Korjaukset ladattu onnistuneesti! + + + + All Patches available for all games have been downloaded. + Kaikki saatavilla olevat korjaukset kaikille peleille on ladattu. + + + + Games: + Pelit: + + + + PKG File (*.PKG) + PKG-tiedosto (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF-tiedostot (*.bin *.elf *.oelf) + + + + Game Boot + Pelin käynnistys + + + + Only one file can be selected! + Vain yksi tiedosto voidaan valita! + + + + PKG Extraction + PKG:n purku + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Korjaus havaittu!\nPKG:n ja pelin versiot vastaavat!: %1\nHaluatko + + + + to overwrite? + korvata? + + + + Patch detected!\nPKG Version %1 is older + Korjaus havaittu!\nPKG Version %1 on vanhempi + + + + than installed version!: %2\nWould you like + kuin asennettu versio!: %2\nHaluatko + + + + to overwrite? + korvata? + + + + Patch detected!\nGame is installed: %1\nWould you like + Korjaus havaittu!\nPeli on asennettu: %1\nHaluatko + + + + to install Patch: %2? + asentaa korjaus: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Peli on jo asennettu\n%1\nHaluatko korvata sen? + + + + PKG is a patch, please install the game first! + PKG on korjaus, asenna peli ensin! + + + + PKG ERROR + PKG VIRHE + + + + Extracting PKG %1/%2 + Purkaminen PKG %1/%2 + + + + Extraction Finished + Purku valmis + + + + Game successfully installed at %1 + Peli asennettu onnistuneesti kohtaan %1 + + + + File doesn't appear to be a valid PKG file + Tiedosto ei vaikuta olevan kelvollinen PKG-tiedosto + + + + CheatsPatches + + + Cheats / Patches + Huijaukset / Korjaukset + + + + defaultTextEdit_MSG + Cheats/Patches ovat kokeellisia.\nKäytä varoen.\n\nLataa cheats yksitellen valitsemalla repositorio ja napsauttamalla latauspainiketta.\nPatches-välilehdellä voit ladata kaikki patchit kerralla, valita, mitä haluat käyttää, ja tallentaa valinnan.\n\nKoska emme kehitä Cheats/Patches,\nilmoita ongelmista cheatin tekijälle.\n\nLuo uusi cheat? Käy osoitteessa:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Kuvaa ei saatavilla + + + + Serial: + Sarjanumero: + + + + Version: + Versio: + + + + Size: + Koko: + + + + Select Cheat File: + Valitse huijaustiedosto: + + + + Repository: + Repo: + + + + Download Cheats + Lataa huijaukset + + + + Delete File + Poista tiedosto + + + + No files selected. + Ei tiedostoja valittu. + + + + You can delete the cheats you don't want after downloading them. + Voit poistaa ei-toivomasi huijaukset lataamisen jälkeen. + + + + Do you want to delete the selected file?\n%1 + Haluatko poistaa valitun tiedoston?\n%1 + + + + Select Patch File: + Valitse korjaustiedosto: + + + + Download Patches + Lataa korjaukset + + + + Save + Tallenna + + + + Cheats + Huijaukset + + + + Patches + Korjaukset + + + + Error + Virhe + + + + No patch selected. + Ei korjausta valittu. + + + + Unable to open files.json for reading. + Tiedostoa files.json ei voitu avata lukemista varten. + + + + No patch file found for the current serial. + Nykyiselle sarjanumerolle ei löytynyt korjaustiedostoa. + + + + Unable to open the file for reading. + Tiedostoa ei voitu avata lukemista varten. + + + + Unable to open the file for writing. + Tiedostoa ei voitu avata kirjoittamista varten. + + + + Failed to parse XML: + XML:n jäsentäminen epäonnistui: + + + + Success + Onnistui + + + + Options saved successfully. + Vaihtoehdot tallennettu onnistuneesti. + + + + Invalid Source + Virheellinen lähde + + + + The selected source is invalid. + Valittu lähde on virheellinen. + + + + File Exists + Tiedosto on olemassa + + + + File already exists. Do you want to replace it? + Tiedosto on jo olemassa. Haluatko korvata sen? + + + + Failed to save file: + Tiedoston tallentaminen epäonnistui: + + + + Failed to download file: + Tiedoston lataaminen epäonnistui: + + + + Cheats Not Found + Huijauksia ei löytynyt + + + + CheatsNotFound_MSG + Huijauksia ei löytynyt tälle pelille tämän version valitusta repositoriosta, yritä toista repositoriota tai pelin eri versiota. + + + + Cheats Downloaded Successfully + Huijaukset ladattu onnistuneesti + + + + CheatsDownloadedSuccessfully_MSG + Olet ladannut huijaukset onnistuneesti valitusta repositoriosta tälle pelin versiolle. Voit yrittää ladata toisesta repositoriosta, jos se on saatavilla, voit myös käyttää sitä valitsemalla tiedoston luettelosta. + + + + Failed to save: + Tallentaminen epäonnistui: + + + + Failed to download: + Lataaminen epäonnistui: + + + + Download Complete + Lataus valmis + + + + DownloadComplete_MSG + Korjaukset ladattu onnistuneesti! Kaikki saatavilla olevat korjaukset kaikille peleille on ladattu, eikä niitä tarvitse ladata yksittäin jokaiselle pelille kuten huijauksissa. + + + + Failed to parse JSON data from HTML. + JSON-tietojen jäsentäminen HTML:stä epäonnistui. + + + + Failed to retrieve HTML page. + HTML-sivun hakeminen epäonnistui. + + + + Failed to open file: + Tiedoston avaaminen epäonnistui: + + + + XML ERROR: + XML VIRHE: + + + + Failed to open files.json for writing + Tiedostoa files.json ei voitu avata kirjoittamista varten + + + + Author: + Tekijä: + + + + Directory does not exist: + Kansiota ei ole olemassa: + + + + Failed to open files.json for reading. + Tiedostoa files.json ei voitu avata lukemista varten. + + + + Name: + Nimi: + + \ No newline at end of file diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 3f3b38baf..56d316092 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Créer un raccourci - + Open Game Folder Ouvrir le dossier du jeu - + + Cheats / Patches + Trucs / Patchs + + + SFO Viewer Visionneuse SFO - + Trophy Viewer Visionneuse de trophées - + Copy info Copier les informations - + Copy Name Copier le nom - + Copy Serial Copier le numéro de série - + Copy All Copier tout - + Shortcut creation Création du raccourci - + Shortcut created successfully!\n %1 Raccourci créé avec succès!\n %1 - + Error Erreur - + Error creating shortcut!\n %1 Erreur lors de la création du raccourci!\n %1 - + Install PKG Installer un PKG @@ -248,6 +253,11 @@ Game Install Directory Répertoire des jeux + + + Download Cheats/Patches + Télécharger Trucs / Patchs + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Activer le débogage RenderDoc + + + MainWindow + + + * Unsupported Vulkan Version + * Version Vulkan non prise en charge + + + + Download Cheats For All Installed Games + Télécharger les cheats pour tous les jeux installés + + + + Download Patches For All Games + Télécharger les patches pour tous les jeux + + + + Download Complete + Téléchargement terminé + + + + You have downloaded cheats for all the games you have installed. + Vous avez téléchargé des cheats pour tous les jeux que vous avez installés. + + + + Patches Downloaded Successfully! + Patches téléchargés avec succès ! + + + + All Patches available for all games have been downloaded. + Tous les patches disponibles pour tous les jeux ont été téléchargés. + + + + Games: + Jeux : + + + + PKG File (*.PKG) + Fichier PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Fichiers ELF (*.bin *.elf *.oelf) + + + + Game Boot + Boot du jeu + + + + Only one file can be selected! + Un seul fichier peut être sélectionné ! + + + + PKG Extraction + Extraction PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch détecté !\nLes versions PKG et Jeu correspondent : %1\nSouhaitez-vous + + + + to overwrite? + écraser ? + + + + Patch detected!\nPKG Version %1 is older + Patch détecté !\nVersion PKG %1 est plus ancienne + + + + than installed version!: %2\nWould you like + que la version installée ! : %2\nSouhaitez-vous + + + + to overwrite? + écraser ? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch détecté !\nJeu est installé : %1\nSouhaitez-vous + + + + to install Patch: %2? + installer le patch : %2 ? + + + + Game already installed\n%1\nWould you like to overwrite? + Jeu déjà installé\n%1\nSouhaitez-vous écraser ? + + + + PKG is a patch, please install the game first! + PKG est un patch, veuillez d'abord installer le jeu ! + + + + PKG ERROR + ERREUR PKG + + + + Extracting PKG %1/%2 + Extraction PKG %1/%2 + + + + Extraction Finished + Extraction terminée + + + + Game successfully installed at %1 + Jeu installé avec succès à %1 + + + + File doesn't appear to be a valid PKG file + Le fichier ne semble pas être un fichier PKG valide + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Les cheats/patches sont expérimentaux.\nUtilisez-les avec précaution.\n\nTéléchargez les cheats individuellement en sélectionnant le dépôt et en cliquant sur le bouton de téléchargement.\nDans l'onglet Patches, vous pouvez télécharger tous les patches en une seule fois, choisir lesquels vous souhaitez utiliser et enregistrer votre sélection.\n\nComme nous ne développons pas les Cheats/Patches,\nmerci de signaler les problèmes à l'auteur du cheat.\n\nVous avez créé un nouveau cheat ? Visitez :\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Aucune image disponible + + + + Serial: + Série : + + + + Version: + Version : + + + + Size: + Taille : + + + + Select Cheat File: + Sélectionner le fichier de cheat : + + + + Repository: + Dépôt : + + + + Download Cheats + Télécharger les cheats + + + + Delete File + Supprimer le fichier + + + + No files selected. + Aucun fichier sélectionné. + + + + You can delete the cheats you don't want after downloading them. + Vous pouvez supprimer les cheats que vous ne souhaitez pas après les avoir téléchargés. + + + + Do you want to delete the selected file?\n%1 + Voulez-vous supprimer le fichier sélectionné ?\n%1 + + + + Select Patch File: + Sélectionner le fichier de patch : + + + + Download Patches + Télécharger les patches + + + + Save + Enregistrer + + + + Cheats + Cheats + + + + Patches + Patchs + + + + Error + Erreur + + + + No patch selected. + Aucun patch sélectionné. + + + + Unable to open files.json for reading. + Impossible d'ouvrir files.json pour la lecture. + + + + No patch file found for the current serial. + Aucun fichier de patch trouvé pour la série actuelle. + + + + Unable to open the file for reading. + Impossible d'ouvrir le fichier pour la lecture. + + + + Unable to open the file for writing. + Impossible d'ouvrir le fichier pour l'écriture. + + + + Failed to parse XML: + Échec de l'analyse XML : + + + + Success + Succès + + + + Options saved successfully. + Options enregistrées avec succès. + + + + Invalid Source + Source invalide + + + + The selected source is invalid. + La source sélectionnée est invalide. + + + + File Exists + Le fichier existe + + + + File already exists. Do you want to replace it? + Le fichier existe déjà. Voulez-vous le remplacer ? + + + + Failed to save file: + Échec de l'enregistrement du fichier : + + + + Failed to download file: + Échec du téléchargement du fichier : + + + + Cheats Not Found + Cheats non trouvés + + + + CheatsNotFound_MSG + Aucun cheat trouvé pour ce jeu dans cette version du dépôt sélectionné,essayez un autre dépôt ou une version différente du jeu. + + + + Cheats Downloaded Successfully + Cheats téléchargés avec succès + + + + CheatsDownloadedSuccessfully_MSG + Vous avez téléchargé les cheats avec succès pour cette version du jeu depuis le dépôt sélectionné. Vous pouvez essayer de télécharger depuis un autre dépôt, si disponible, il sera également possible de l'utiliser en sélectionnant le fichier dans la liste. + + + + Failed to save: + Échec de l'enregistrement : + + + + Failed to download: + Échec du téléchargement : + + + + Download Complete + Téléchargement terminé + + + + DownloadComplete_MSG + Patchs téléchargés avec succès ! Tous les patches disponibles pour tous les jeux ont été téléchargés, il n'est pas nécessaire de les télécharger individuellement pour chaque jeu comme c'est le cas pour les cheats. + + + + Failed to parse JSON data from HTML. + Échec de l'analyse des données JSON à partir du HTML. + + + + Failed to retrieve HTML page. + Échec de la récupération de la page HTML. + + + + Failed to open file: + Échec de l'ouverture du fichier : + + + + XML ERROR: + ERREUR XML : + + + + Failed to open files.json for writing + Échec de l'ouverture de files.json pour l'écriture + + + + Author: + Auteur : + + + + Directory does not exist: + Répertoire n'existe pas : + + + + Failed to open files.json for reading. + Échec de l'ouverture de files.json pour la lecture. + + + + Name: + Nom : + + \ No newline at end of file diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index c6cc0bce2..e531df45c 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -89,6 +89,11 @@ Open Game Folder Játék Mappa Megnyitása + + + + Cheats / Patches + Csalások / Javítások @@ -247,6 +252,11 @@ Game Install Directory Játék Telepítési Mappa + + + + Download Cheats/Patches + Csalások / Javítások letöltése @@ -488,4 +498,395 @@ RenderDoc Debugolás Engedélyezése + + MainWindow + + + * Unsupported Vulkan Version + * Támogatott Vulkan verzió hiányzik + + + + Download Cheats For All Installed Games + Letöltés csalások minden telepített játékhoz + + + + Download Patches For All Games + Frissítések letöltése minden játékhoz + + + + Download Complete + Letöltés befejezve + + + + You have downloaded cheats for all the games you have installed. + Csalásokat töltöttél le az összes telepített játékhoz. + + + + Patches Downloaded Successfully! + Frissítések sikeresen letöltve! + + + + All Patches available for all games have been downloaded. + Az összes játékhoz elérhető frissítés letöltésre került. + + + + Games: + Játékok: + + + + PKG File (*.PKG) + PKG fájl (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF fájlok (*.bin *.elf *.oelf) + + + + Game Boot + Játék indító + + + + Only one file can be selected! + Csak egy fájl választható ki! + + + + PKG Extraction + PKG kicsomagolás + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Javítás észlelve!\nA PKG és a játék verziók egyeznek: %1\nSzeretnéd + + + + to overwrite? + felülírni? + + + + Patch detected!\nPKG Version %1 is older + Javítás észlelve!\nA PKG verzió %1 régebbi + + + + than installed version!: %2\nWould you like + mint a telepített verzió: %2\nSzeretnéd + + + + to overwrite? + felülírni? + + + + Patch detected!\nGame is installed: %1\nWould you like + Javítás észlelve!\nA játék telepítve van: %1\nSzeretnéd + + + + to install Patch: %2? + a javítást telepíteni: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + A játék már telepítve van\n%1\nSzeretnéd felülírni? + + + + PKG is a patch, please install the game first! + A PKG egy javítás, először telepítsd a játékot! + + + + PKG ERROR + PKG HIBA + + + + Extracting PKG %1/%2 + PKG kicsomagolása %1/%2 + + + + Extraction Finished + Kicsomagolás befejezve + + + + Game successfully installed at %1 + A játék sikeresen telepítve itt: %1 + + + + File doesn't appear to be a valid PKG file + A fájl nem tűnik érvényes PKG fájlnak + + + + CheatsPatches + + + Cheats / Patches + Csalások / Javítások + + + + defaultTextEdit_MSG + A csalások/patchek kísérleti jellegűek.\nHasználja őket óvatosan.\n\nTöltse le a csalásokat egyesével a repository kiválasztásával és a letöltés gombra kattintással.\nA Patches fül alatt egyszerre letöltheti az összes patchet, választhat, melyeket szeretné használni, és elmentheti a választását.\n\nMivel nem fejlesztjük a csalásokat/patch-eket,\nkérjük, jelentse a problémákat a csalás szerzőjének.\n\nKészített egy új csalást? Látogasson el ide:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Nincs elérhető kép + + + + Serial: + Sorozatszám: + + + + Version: + Verzió: + + + + Size: + Méret: + + + + Select Cheat File: + Válaszd ki a csalás fájlt: + + + + Repository: + Tároló: + + + + Download Cheats + Csalások letöltése + + + + Delete File + Fájl törlése + + + + No files selected. + Nincsenek kiválasztott fájlok. + + + + You can delete the cheats you don't want after downloading them. + Törölheted a nem kívánt csalásokat a letöltés után. + + + + Do you want to delete the selected file?\n%1 + Szeretnéd törölni a kiválasztott fájlt?\n%1 + + + + Select Patch File: + Válaszd ki a javítás fájlt: + + + + Download Patches + Javítások letöltése + + + + Save + Mentés + + + + Cheats + Csalások + + + + Patches + Javítások + + + + Error + Hiba + + + + No patch selected. + Nincs kiválasztva javítás. + + + + Unable to open files.json for reading. + Nem sikerült megnyitni a files.json fájlt olvasásra. + + + + No patch file found for the current serial. + Nincs található javítási fájl a jelenlegi sorozatszámhoz. + + + + Unable to open the file for reading. + Nem sikerült megnyitni a fájlt olvasásra. + + + + Unable to open the file for writing. + Nem sikerült megnyitni a fájlt írásra. + + + + Failed to parse XML: + XML elemzési hiba: + + + + Success + Siker + + + + Options saved successfully. + A beállítások sikeresen elmentve. + + + + Invalid Source + Érvénytelen forrás + + + + The selected source is invalid. + A kiválasztott forrás érvénytelen. + + + + File Exists + A fájl létezik + + + + File already exists. Do you want to replace it? + A fájl már létezik. Szeretnéd helyettesíteni? + + + + Failed to save file: + Nem sikerült elmenteni a fájlt: + + + + Failed to download file: + Nem sikerült letölteni a fájlt: + + + + Cheats Not Found + Csalások nem találhatóak + + + + CheatsNotFound_MSG + Nincs található csalás ezen a játékverzión ebben a kiválasztott tárolóban,próbálj meg egy másik tárolót vagy a játék egy másik verzióját. + + + + Cheats Downloaded Successfully + Csalások sikeresen letöltve + + + + CheatsDownloadedSuccessfully_MSG + Sikeresen letöltötted a csalásokat ennek a játéknak a verziójához a kiválasztott tárolóból. Próbálhatsz letölteni egy másik tárolóból is, ha az elérhető, akkor a fájl kiválasztásával az is használható lesz. + + + + Failed to save: + Nem sikerült menteni: + + + + Failed to download: + Nem sikerült letölteni: + + + + Download Complete + Letöltés befejezve + + + + DownloadComplete_MSG + Frissítések sikeresen letöltve! Minden elérhető frissítés letöltésre került, nem szükséges egyesével letölteni őket minden játékhoz, mint a csalások esetében. + + + + Failed to parse JSON data from HTML. + Nem sikerült az JSON adatok elemzése HTML-ből. + + + + Failed to retrieve HTML page. + Nem sikerült HTML oldal lekérése. + + + + Failed to open file: + Nem sikerült megnyitni a fájlt: + + + + XML ERROR: + XML HIBA: + + + + Failed to open files.json for writing + Nem sikerült megnyitni a files.json fájlt írásra + + + + Author: + Szerző: + + + + Directory does not exist: + A könyvtár nem létezik: + + + + Failed to open files.json for reading. + Nem sikerült megnyitni a files.json fájlt olvasásra. + + + + Name: + Név: + + diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts index 502be21e6..dde590469 100644 --- a/src/qt_gui/translations/id.ts +++ b/src/qt_gui/translations/id.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Cheat / Patch + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Unduh Cheat / Patch + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * Unsupported Vulkan Version + * Versi Vulkan Tidak Didukung + + + + Download Cheats For All Installed Games + Unduh Cheat Untuk Semua Game Yang Terpasang + + + + Download Patches For All Games + Unduh Patch Untuk Semua Game + + + + Download Complete + Unduhan Selesai + + + + You have downloaded cheats for all the games you have installed. + Anda telah mengunduh cheat untuk semua game yang terpasang. + + + + Patches Downloaded Successfully! + Patch Berhasil Diunduh! + + + + All Patches available for all games have been downloaded. + Semua Patch yang tersedia untuk semua game telah diunduh. + + + + Games: + Game: + + + + PKG File (*.PKG) + File PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + File ELF (*.bin *.elf *.oelf) + + + + Game Boot + Boot Game + + + + Only one file can be selected! + Hanya satu file yang bisa dipilih! + + + + PKG Extraction + Ekstraksi PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch terdeteksi!\nVersi PKG dan Game cocok!: %1\nApakah Anda ingin + + + + to overwrite? + menimpa? + + + + Patch detected!\nPKG Version %1 is older + Patch terdeteksi!\nVersi PKG %1 lebih lama + + + + than installed version!: %2\nWould you like + daripada versi yang terpasang!: %2\nApakah Anda ingin + + + + to overwrite? + menimpa? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch terdeteksi!\nGame terpasang: %1\nApakah Anda ingin + + + + to install Patch: %2? + memasang Patch: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Game sudah terpasang\n%1\nApakah Anda ingin menimpa? + + + + PKG is a patch, please install the game first! + PKG adalah patch, harap pasang game terlebih dahulu! + + + + PKG ERROR + KESALAHAN PKG + + + + Extracting PKG %1/%2 + Mengekstrak PKG %1/%2 + + + + Extraction Finished + Ekstraksi Selesai + + + + Game successfully installed at %1 + Game berhasil dipasang di %1 + + + + File doesn't appear to be a valid PKG file + File tampaknya bukan file PKG yang valid + + + + CheatsPatches + + + Cheats / Patches + Cheat / Patch + + + + defaultTextEdit_MSG + Cheats/Patches bersifat eksperimental.\nGunakan dengan hati-hati.\n\nUnduh cheats satu per satu dengan memilih repositori dan mengklik tombol unduh.\nDi tab Patches, Anda dapat mengunduh semua patch sekaligus, memilih yang ingin digunakan, dan menyimpan pilihan Anda.\n\nKarena kami tidak mengembangkan Cheats/Patches,\nharap laporkan masalah kepada pembuat cheat.\n\nMembuat cheat baru? Kunjungi:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Tidak Ada Gambar Tersedia + + + + Serial: + Serial: + + + + Version: + Versi: + + + + Size: + Ukuran: + + + + Select Cheat File: + Pilih File Cheat: + + + + Repository: + Repositori: + + + + Download Cheats + Unduh Cheat + + + + Delete File + Hapus File + + + + No files selected. + Tidak ada file yang dipilih. + + + + You can delete the cheats you don't want after downloading them. + Anda dapat menghapus cheat yang tidak Anda inginkan setelah mengunduhnya. + + + + Do you want to delete the selected file?\n%1 + Apakah Anda ingin menghapus berkas yang dipilih?\n%1 + + + + Select Patch File: + Pilih File Patch: + + + + Download Patches + Unduh Patch + + + + Save + Simpan + + + + Cheats + Cheat + + + + Patches + Patch + + + + Error + Kesalahan + + + + No patch selected. + Tidak ada patch yang dipilih. + + + + Unable to open files.json for reading. + Tidak dapat membuka files.json untuk dibaca. + + + + No patch file found for the current serial. + Tidak ada file patch ditemukan untuk serial saat ini. + + + + Unable to open the file for reading. + Tidak dapat membuka file untuk dibaca. + + + + Unable to open the file for writing. + Tidak dapat membuka file untuk menulis. + + + + Failed to parse XML: + Gagal menganalisis XML: + + + + Success + Sukses + + + + Options saved successfully. + Opsi berhasil disimpan. + + + + Invalid Source + Sumber Tidak Valid + + + + The selected source is invalid. + Sumber yang dipilih tidak valid. + + + + File Exists + File Ada + + + + File already exists. Do you want to replace it? + File sudah ada. Apakah Anda ingin menggantinya? + + + + Failed to save file: + Gagal menyimpan file: + + + + Failed to download file: + Gagal mengunduh file: + + + + Cheats Not Found + Cheat Tidak Ditemukan + + + + CheatsNotFound_MSG + Cheat tidak ditemukan untuk game ini dalam versi repositori yang dipilih,cobalah repositori lain atau versi game yang berbeda. + + + + Cheats Downloaded Successfully + Cheat Berhasil Diunduh + + + + CheatsDownloadedSuccessfully_MSG + Anda telah berhasil mengunduh cheat untuk versi game ini dari repositori yang dipilih. Anda bisa mencoba mengunduh dari repositori lain, jika tersedia akan juga memungkinkan untuk menggunakannya dengan memilih file dari daftar. + + + + Failed to save: + Gagal menyimpan: + + + + Failed to download: + Gagal mengunduh: + + + + Download Complete + Unduhan Selesai + + + + DownloadComplete_MSG + Patch Berhasil Diunduh! Semua Patch yang tersedia untuk semua game telah diunduh, tidak perlu mengunduhnya satu per satu seperti yang terjadi pada Cheat. + + + + Failed to parse JSON data from HTML. + Gagal menganalisis data JSON dari HTML. + + + + Failed to retrieve HTML page. + Gagal mengambil halaman HTML. + + + + Failed to open file: + Gagal membuka file: + + + + XML ERROR: + KESALAHAN XML: + + + + Failed to open files.json for writing + Gagal membuka files.json untuk menulis + + + + Author: + Penulis: + + + + Directory does not exist: + Direktori tidak ada: + + + + Failed to open files.json for reading. + Gagal membuka files.json untuk dibaca. + + + + Name: + Nama: + + \ No newline at end of file diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index a47d36823..4cb050b70 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Crea scorciatoia - + Open Game Folder Apri cartella del gioco - + + Cheats / Patches + Trucchi / Patch + + + SFO Viewer Visualizzatore SFO - + Trophy Viewer Visualizzatore Trofei - + Copy info Copia informazioni - + Copy Name Copia Nome - + Copy Serial Copia Seriale - + Copy All Copia Tutto - + Shortcut creation Creazione scorciatoia - + Shortcut created successfully!\n %1 Scorciatoia creata con successo!\n %1 - + Error Errore - + Error creating shortcut!\n %1 Errore nella creazione della scorciatoia!\n %1 - + Install PKG Installa PKG @@ -248,6 +253,11 @@ Game Install Directory Cartella Installazione Giochi + + + Download Cheats/Patches + Scarica Trucchi / Patch + Dump Game List @@ -488,4 +498,395 @@ Abilita Debugging RenderDoc - + + MainWindow + + + * Unsupported Vulkan Version + * Versi Vulkan Tidak Didukung + + + + Download Cheats For All Installed Games + Unduh Cheat Untuk Semua Game yang Terinstal + + + + Download Patches For All Games + Unduh Patch Untuk Semua Game + + + + Download Complete + Unduhan Selesai + + + + You have downloaded cheats for all the games you have installed. + Anda telah mengunduh cheat untuk semua game yang telah Anda instal. + + + + Patches Downloaded Successfully! + Patch Berhasil Diunduh! + + + + All Patches available for all games have been downloaded. + Semua patch yang tersedia untuk semua game telah diunduh. + + + + Games: + Game: + + + + PKG File (*.PKG) + File PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + File ELF (*.bin *.elf *.oelf) + + + + Game Boot + Boot Game + + + + Only one file can be selected! + Hanya satu file yang dapat dipilih! + + + + PKG Extraction + Ekstraksi PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch terdeteksi!\nVersi PKG dan Game cocok!: %1\nApakah Anda ingin + + + + to overwrite? + menimpa? + + + + Patch detected!\nPKG Version %1 is older + Patch terdeteksi!\nVersi PKG %1 lebih lama + + + + than installed version!: %2\nWould you like + daripada versi yang terinstal!: %2\nApakah Anda ingin + + + + to overwrite? + menimpa? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch terdeteksi!\nGame terinstal: %1\nApakah Anda ingin + + + + to install Patch: %2? + menginstal Patch: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Game sudah terinstal\n%1\nApakah Anda ingin menimpa? + + + + PKG is a patch, please install the game first! + PKG adalah patch, silakan instal game terlebih dahulu! + + + + PKG ERROR + ERROR PKG + + + + Extracting PKG %1/%2 + Estrazione PKG %1/%2 + + + + Extraction Finished + Ekstraksi Selesai + + + + Game successfully installed at %1 + Game berhasil diinstal di %1 + + + + File doesn't appear to be a valid PKG file + File tidak tampak sebagai file PKG yang valid + + + + CheatsPatches + + + Cheats / Patches + Cheat / Patch + + + + defaultTextEdit_MSG + I cheats/patches sono sperimentali.\nUtilizzali con cautela.\n\nScarica i cheats singolarmente selezionando il repository e cliccando sul pulsante di download.\nNella scheda Patches, puoi scaricare tutti i patch in una volta sola, scegliere quali vuoi utilizzare e salvare la tua selezione.\n\nPoiché non sviluppiamo i Cheats/Patches,\nper favore segnala i problemi all'autore del cheat.\n\nHai creato un nuovo cheat? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Tidak Ada Gambar + + + + Serial: + Serial: + + + + Version: + Versi: + + + + Size: + Ukuran: + + + + Select Cheat File: + Pilih File Cheat: + + + + Repository: + Repositori: + + + + Download Cheats + Unduh Cheat + + + + Delete File + Hapus File + + + + No files selected. + Tidak ada file yang dipilih. + + + + You can delete the cheats you don't want after downloading them. + Anda dapat menghapus cheat yang tidak diinginkan setelah mengunduhnya. + + + + Do you want to delete the selected file?\n%1 + Apakah Anda ingin menghapus file yang dipilih?\n%1 + + + + Select Patch File: + Pilih File Patch: + + + + Download Patches + Unduh Patch + + + + Save + Simpan + + + + Cheats + Cheat + + + + Patches + Patch + + + + Error + Kesalahan + + + + No patch selected. + Tidak ada patch yang dipilih. + + + + Unable to open files.json for reading. + Gagal membuka files.json untuk dibaca. + + + + No patch file found for the current serial. + Tidak ada file patch ditemukan untuk serial saat ini. + + + + Unable to open the file for reading. + Gagal membuka file untuk dibaca. + + + + Unable to open the file for writing. + Gagal membuka file untuk ditulis. + + + + Failed to parse XML: + Gagal mengurai XML: + + + + Success + Berhasil + + + + Options saved successfully. + Opsi berhasil disimpan. + + + + Invalid Source + Sumber Tidak Valid + + + + The selected source is invalid. + Sumber yang dipilih tidak valid. + + + + File Exists + File Ada + + + + File already exists. Do you want to replace it? + File sudah ada. Apakah Anda ingin menggantinya? + + + + Failed to save file: + Gagal menyimpan file: + + + + Failed to download file: + Gagal mengunduh file: + + + + Cheats Not Found + Cheat Tidak Ditemukan + + + + CheatsNotFound_MSG + Cheat tidak ditemukan untuk game ini dalam versi repositori yang dipilih, coba repositori lain atau versi game yang berbeda. + + + + Cheats Downloaded Successfully + Cheat Berhasil Diunduh + + + + CheatsDownloadedSuccessfully_MSG + Anda telah berhasil mengunduh cheat untuk versi game ini dari repositori yang dipilih. Anda dapat mencoba mengunduh dari repositori lain, jika tersedia, Anda juga dapat menggunakannya dengan memilih file dari daftar. + + + + Failed to save: + Gagal menyimpan: + + + + Failed to download: + Gagal mengunduh: + + + + Download Complete + Unduhan Selesai + + + + DownloadComplete_MSG + Patch Berhasil Diunduh! Semua patch yang tersedia untuk semua game telah diunduh, tidak perlu mengunduhnya secara individu untuk setiap game seperti yang terjadi pada Cheat. + + + + Failed to parse JSON data from HTML. + Gagal mengurai data JSON dari HTML. + + + + Failed to retrieve HTML page. + Gagal mengambil halaman HTML. + + + + Failed to open file: + Gagal membuka file: + + + + XML ERROR: + KESALAHAN XML: + + + + Failed to open files.json for writing + Gagal membuka files.json untuk menulis + + + + Author: + Penulis: + + + + Directory does not exist: + Direktori tidak ada: + + + + Failed to open files.json for reading. + Gagal membuka files.json untuk dibaca. + + + + Name: + Nama: + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index 557b0760b..c3eaaba19 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut ショートカットを作成 - + Open Game Folder ゲームフォルダを開く - + + Cheats / Patches + チート / パッチ + + + SFO Viewer SFOビューワー - + Trophy Viewer トロフィービューワー - + Copy info 情報をコピー - + Copy Name 名前をコピー - + Copy Serial シリアルをコピー - + Copy All すべてコピー - + Shortcut creation ショートカットの作成 - + Shortcut created successfully!\n %1 ショートカットが正常に作成されました!\n %1 - + Error エラー - + Error creating shortcut!\n %1 ショートカットの作成に失敗しました!\n %1 - + Install PKG PKGをインストール @@ -248,6 +253,11 @@ Game Install Directory ゲームインストールディレクトリ + + + Download Cheats/Patches + チート / パッチをダウンロード + Dump Game List @@ -488,4 +498,395 @@ RenderDocデバッグを有効にする - + + MainWindow + + + * Unsupported Vulkan Version + * サポートされていないVulkanバージョン + + + + Download Cheats For All Installed Games + すべてのインストール済みゲームのチートをダウンロード + + + + Download Patches For All Games + すべてのゲームのパッチをダウンロード + + + + Download Complete + ダウンロード完了 + + + + You have downloaded cheats for all the games you have installed. + インストールしたすべてのゲームのチートをダウンロードしました。 + + + + Patches Downloaded Successfully! + パッチが正常にダウンロードされました! + + + + All Patches available for all games have been downloaded. + すべてのゲームに利用可能なパッチがダウンロードされました。 + + + + Games: + ゲーム: + + + + PKG File (*.PKG) + PKGファイル (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELFファイル (*.bin *.elf *.oelf) + + + + Game Boot + ゲームブート + + + + Only one file can be selected! + 1つのファイルしか選択できません! + + + + PKG Extraction + PKG抽出 + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + パッチが検出されました!\nPKGとゲームバージョンが一致しています!: %1\n上書きしますか + + + + to overwrite? + 上書きしますか? + + + + Patch detected!\nPKG Version %1 is older + パッチが検出されました!\nPKGバージョン %1 は古い + + + + than installed version!: %2\nWould you like + インストールされているバージョンよりも古いです!: %2\n上書きしますか + + + + to overwrite? + 上書きしますか? + + + + Patch detected!\nGame is installed: %1\nWould you like + パッチが検出されました!\nゲームがインストールされています: %1\nインストールしますか + + + + to install Patch: %2? + パッチをインストールしますか: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + ゲームはすでにインストールされています\n%1\n上書きしますか? + + + + PKG is a patch, please install the game first! + PKGはパッチです。ゲームを先にインストールしてください! + + + + PKG ERROR + PKGエラー + + + + Extracting PKG %1/%2 + PKGを抽出中 %1/%2 + + + + Extraction Finished + 抽出完了 + + + + Game successfully installed at %1 + ゲームが %1 に正常にインストールされました + + + + File doesn't appear to be a valid PKG file + ファイルが有効なPKGファイルでないようです + + + + CheatsPatches + + + Cheats / Patches + チート / パッチ + + + + defaultTextEdit_MSG + チート/パッチは実験的です。\n使用には注意してください。\n\nリポジトリを選択し、ダウンロードボタンをクリックしてチートを個別にダウンロードします。\n「Patches」タブでは、すべてのパッチを一度にダウンロードし、使用したいものを選択して選択を保存できます。\n\nチート/パッチを開発していないため、\n問題があればチートの作者に報告してください。\n\n新しいチートを作成しましたか?\nhttps://github.com/shadps4-emu/ps4_cheats を訪問してください。 + + + + No Image Available + 画像は利用できません + + + + Serial: + シリアル: + + + + Version: + バージョン: + + + + Size: + サイズ: + + + + Select Cheat File: + チートファイルを選択: + + + + Repository: + リポジトリ: + + + + Download Cheats + チートをダウンロード + + + + Delete File + ファイルを削除 + + + + No files selected. + ファイルが選択されていません。 + + + + You can delete the cheats you don't want after downloading them. + ダウンロード後に不要なチートを削除できます。 + + + + Do you want to delete the selected file?\n%1 + 選択したファイルを削除しますか?\n%1 + + + + Select Patch File: + パッチファイルを選択: + + + + Download Patches + パッチをダウンロード + + + + Save + 保存 + + + + Cheats + チート + + + + Patches + パッチ + + + + Error + エラー + + + + No patch selected. + パッチが選択されていません。 + + + + Unable to open files.json for reading. + files.jsonを読み込み用に開けません。 + + + + No patch file found for the current serial. + 現在のシリアルに対するパッチファイルが見つかりません。 + + + + Unable to open the file for reading. + ファイルを読み込み用に開けません。 + + + + Unable to open the file for writing. + ファイルを記録用に開けません。 + + + + Failed to parse XML: + XMLの解析に失敗しました: + + + + Success + 成功 + + + + Options saved successfully. + オプションが正常に保存されました。 + + + + Invalid Source + 無効なソース + + + + The selected source is invalid. + 選択したソースは無効です。 + + + + File Exists + ファイルが存在します + + + + File already exists. Do you want to replace it? + ファイルはすでに存在します。置き換えますか? + + + + Failed to save file: + ファイルの保存に失敗しました: + + + + Failed to download file: + ファイルのダウンロードに失敗しました: + + + + Cheats Not Found + チートが見つかりません + + + + CheatsNotFound_MSG + このゲームのこのバージョンのチートが選択されたリポジトリに見つかりませんでした。別のリポジトリまたはゲームの別のバージョンを試してください。 + + + + Cheats Downloaded Successfully + チートが正常にダウンロードされました + + + + CheatsDownloadedSuccessfully_MSG + このゲームのこのバージョンのチートをリポジトリから正常にダウンロードしました。 別のリポジトリからのダウンロードも試せます。利用可能であれば、リストからファイルを選択して使用することも可能です。 + + + + Failed to save: + 保存に失敗しました: + + + + Failed to download: + ダウンロードに失敗しました: + + + + Download Complete + ダウンロード完了 + + + + DownloadComplete_MSG + パッチが正常にダウンロードされました! すべてのゲームに利用可能なパッチがダウンロードされました。チートとは異なり、各ゲームごとに個別にダウンロードする必要はありません。 + + + + Failed to parse JSON data from HTML. + HTMLからJSONデータの解析に失敗しました。 + + + + Failed to retrieve HTML page. + HTMLページの取得に失敗しました。 + + + + Failed to open file: + ファイルを開くのに失敗しました: + + + + XML ERROR: + XMLエラー: + + + + Failed to open files.json for writing + files.jsonを記録用に開けません + + + + Author: + 著者: + + + + Directory does not exist: + ディレクトリが存在しません: + + + + Failed to open files.json for reading. + files.jsonを読み込み用に開けません。 + + + + Name: + 名前: + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index b33b5d927..579c6ca79 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + 치트 / 패치 + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + 치트 / 패치 다운로드 + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * 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: + + + + PKG File (*.PKG) + PKG File (*.PKG) + + + + 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!\nPKG and Game versions match!: %1\nWould you like + Patch detected!\nPKG and Game versions match!: %1\nWould you like + + + + to overwrite? + to overwrite? + + + + Patch detected!\nPKG Version %1 is older + Patch detected!\nPKG Version %1 is older + + + + than installed version!: %2\nWould you like + than installed version!: %2\nWould you like + + + + to overwrite? + to overwrite? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch detected!\nGame is installed: %1\nWould you like + + + + to install Patch: %2? + to install Patch: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Game already installed\n%1\nWould you like to overwrite? + + + + PKG is a patch, please install the game first! + PKG is a patch, please install the game first! + + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + 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:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + 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 + + + + CheatsNotFound_MSG + 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 + + + + CheatsDownloadedSuccessfully_MSG + 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 + + + + DownloadComplete_MSG + 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. + + + + Failed to parse JSON data from HTML. + Failed to parse JSON data from HTML. + + + + Failed to retrieve HTML page. + Failed to retrieve HTML page. + + + + 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: + + \ No newline at end of file diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index 286ec3f43..c94edb745 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Apgaulės / Pleistrai + Cheats / Patches + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Atsisiųsti Apgaules / Pleistrus + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging - + + + MainWindow + + + * Unsupported Vulkan Version + * Nepalaikoma Vulkan versija + + + + Download Cheats For All Installed Games + Atsisiųsti sukčiavimus visiems įdiegtiems žaidimams + + + + Download Patches For All Games + Atsisiųsti pataisas visiems žaidimams + + + + Download Complete + Atsisiuntimas baigtas + + + + You have downloaded cheats for all the games you have installed. + Jūs atsisiuntėte sukčiavimus visiems jūsų įdiegtiesiems žaidimams. + + + + Patches Downloaded Successfully! + Pataisos sėkmingai atsisiųstos! + + + + All Patches available for all games have been downloaded. + Visos pataisos visiems žaidimams buvo atsisiųstos. + + + + Games: + Žaidimai: + + + + PKG File (*.PKG) + PKG failas (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF failai (*.bin *.elf *.oelf) + + + + Game Boot + Žaidimo paleidimas + + + + Only one file can be selected! + Galite pasirinkti tik vieną failą! + + + + PKG Extraction + PKG ištraukimas + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Pataisa aptikta!\nPKG ir žaidimo versijos atitinka!: %1\nAr norėtumėte + + + + to overwrite? + perrašyti? + + + + Patch detected!\nPKG Version %1 is older + Pataisa aptikta!\nPKG versija %1 yra senesnė + + + + than installed version!: %2\nWould you like + nei įdiegta versija!: %2\nAr norėtumėte + + + + to overwrite? + perrašyti? + + + + Patch detected!\nGame is installed: %1\nWould you like + Pataisa aptikta!\nŽaidimas įdiegtas: %1\nAr norėtumėte + + + + to install Patch: %2? + įdiegti pataisą: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Žaidimas jau įdiegtas\n%1\nAr norėtumėte perrašyti? + + + + PKG is a patch, please install the game first! + PKG yra pataisa, prašome pirmiausia įdiegti žaidimą! + + + + PKG ERROR + PKG KLAIDA + + + + Extracting PKG %1/%2 + Ekstrakcinis PKG %1/%2 + + + + Extraction Finished + Ekstrakcija baigta + + + + Game successfully installed at %1 + Žaidimas sėkmingai įdiegtas %1 + + + + File doesn't appear to be a valid PKG file + Failas atrodo, kad nėra galiojantis PKG failas + + + + CheatsPatches + + + Cheats / Patches + Sukčiavimai / Pataisos + + + + defaultTextEdit_MSG + Cheats/Patches yra eksperimentiniai.\nNaudokite atsargiai.\n\nAtsisiųskite cheats atskirai pasirinkdami saugyklą ir paspausdami atsisiuntimo mygtuką.\nPatches skirtuke galite atsisiųsti visus patch’us vienu metu, pasirinkti, kuriuos norite naudoti, ir išsaugoti pasirinkimą.\n\nKadangi mes nekurime Cheats/Patches,\npraneškite problemas cheat autoriui.\n\nSukūrėte naują cheat? Apsilankykite:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Nuotrauka neprieinama + + + + Serial: + Seriinis numeris: + + + + Version: + Versija: + + + + Size: + Dydis: + + + + Select Cheat File: + Pasirinkite sukčiavimo failą: + + + + Repository: + Saugykla: + + + + Download Cheats + Atsisiųsti sukčiavimus + + + + Delete File + Pašalinti failą + + + + No files selected. + Failai nepasirinkti. + + + + You can delete the cheats you don't want after downloading them. + Galite pašalinti sukčiavimus, kurių nenorite, juos atsisiuntę. + + + + Do you want to delete the selected file?\n%1 + Ar norite ištrinti pasirinktą failą?\n%1 + + + + Select Patch File: + Pasirinkite pataisos failą: + + + + Download Patches + Atsisiųsti pataisas + + + + Save + Įrašyti + + + + Cheats + Sukčiavimai + + + + Patches + Pataisos + + + + Error + Klaida + + + + No patch selected. + Nieko nepataisyta. + + + + Unable to open files.json for reading. + Neįmanoma atidaryti files.json skaitymui. + + + + No patch file found for the current serial. + Nepavyko rasti pataisos failo dabartiniam serijiniam numeriui. + + + + Unable to open the file for reading. + Neįmanoma atidaryti failo skaitymui. + + + + Unable to open the file for writing. + Neįmanoma atidaryti failo rašymui. + + + + Failed to parse XML: + Nepavyko išanalizuoti XML: + + + + Success + Sėkmė + + + + Options saved successfully. + Nustatymai sėkmingai išsaugoti. + + + + Invalid Source + Netinkamas šaltinis + + + + The selected source is invalid. + Pasirinktas šaltinis yra netinkamas. + + + + File Exists + Failas egzistuoja + + + + File already exists. Do you want to replace it? + Failas jau egzistuoja. Ar norite jį pakeisti? + + + + Failed to save file: + Nepavyko išsaugoti failo: + + + + Failed to download file: + Nepavyko atsisiųsti failo: + + + + Cheats Not Found + Sukčiavimai nerasti + + + + CheatsNotFound_MSG + Nerasta sukčiavimų šiam žaidimui šioje pasirinktos saugyklos versijoje,bandykite kitą saugyklą arba skirtingą žaidimo versiją. + + + + Cheats Downloaded Successfully + Sukčiavimai sėkmingai atsisiųsti + + + + CheatsDownloadedSuccessfully_MSG + Sėkmingai atsisiuntėte sukčiavimus šios žaidimo versijos iš pasirinktos saugyklos. Galite pabandyti atsisiųsti iš kitos saugyklos, jei ji yra prieinama, taip pat bus galima ją naudoti pasirinkus failą iš sąrašo. + + + + Failed to save: + Nepavyko išsaugoti: + + + + Failed to download: + Nepavyko atsisiųsti: + + + + Download Complete + Atsisiuntimas baigtas + + + + DownloadComplete_MSG + Pataisos sėkmingai atsisiųstos! Visos pataisos visiems žaidimams buvo atsisiųstos, nebėra reikalo jas atsisiųsti atskirai kiekvienam žaidimui, kaip tai vyksta su sukčiavimais. + + + + Failed to parse JSON data from HTML. + Nepavyko išanalizuoti JSON duomenų iš HTML. + + + + Failed to retrieve HTML page. + Nepavyko gauti HTML puslapio. + + + + Failed to open file: + Nepavyko atidaryti failo: + + + + XML ERROR: + XML KLAIDA: + + + + Failed to open files.json for writing + Nepavyko atidaryti files.json rašymui + + + + Author: + Autorius: + + + + Directory does not exist: + Katalogas neegzistuoja: + + + + Failed to open files.json for reading. + Nepavyko atidaryti files.json skaitymui. + + + + Name: + Pavadinimas: + + \ No newline at end of file diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts index 27fc540c1..3c5401a2b 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Juks / Oppdateringer + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Last ned Juks / Oppdateringer + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging + + + MainWindow + + + * Unsupported Vulkan Version + * Ikke støttet Vulkan-versjon + + + + Download Cheats For All Installed Games + Last ned jukser for alle installerte spill + + + + Download Patches For All Games + Last ned oppdateringer for alle spill + + + + Download Complete + Nedlasting fullført + + + + You have downloaded cheats for all the games you have installed. + Du har lastet ned jukser for alle spillene du har installert. + + + + Patches Downloaded Successfully! + Oppdateringer lastet ned vellykket! + + + + All Patches available for all games have been downloaded. + Alle oppdateringer tilgjengelige for alle spillene har blitt lastet ned. + + + + Games: + Spill: + + + + PKG File (*.PKG) + PKG-fil (*.PKG) + + + + 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-ekstraksjon + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Oppdatering oppdaget!\nPKG og spillversjoner stemmer!: %1\nØnsker du å + + + + to overwrite? + overskrive? + + + + Patch detected!\nPKG Version %1 is older + Oppdatering oppdaget!\nPKG-versjon %1 er eldre + + + + than installed version!: %2\nWould you like + enn installert versjon!: %2\nØnsker du å + + + + to overwrite? + overskrive? + + + + Patch detected!\nGame is installed: %1\nWould you like + Oppdatering oppdaget!\nSpillet er installert: %1\nØnsker du å + + + + to install Patch: %2? + installere oppdateringen: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Spill allerede installert\n%1\nØnsker du å overskrive? + + + + PKG is a patch, please install the game first! + PKG er en oppdatering, vennligst installer spillet først! + + + + PKG ERROR + PKG FEIL + + + + Extracting PKG %1/%2 + Ekstraherer PKG %1/%2 + + + + Extraction Finished + Ekstrahering fullført + + + + Game successfully installed at %1 + Spillet ble installert vellykket på %1 + + + + File doesn't appear to be a valid PKG file + Fil ser ikke ut til å være en gyldig PKG-fil + + + CheatsPatches + + + Cheats / Patches + Jukser / Oppdateringer + + + + defaultTextEdit_MSG + Cheats/Patches er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned cheats individuelt ved å velge depotet og klikke på nedlastingsknappen.\nPå fanen Patches kan du laste ned alle patches samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Cheats/Patches,\nvær vennlig å rapportere problemer til cheat-utvikleren.\n\nHar du laget en ny cheat? Besøk:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Ingen bilde tilgjengelig + + + + Serial: + Serienummer: + + + + Version: + Versjon: + + + + Size: + Størrelse: + + + + Select Cheat File: + Velg juksfil: + + + + Repository: + Depot: + + + + Download Cheats + Last ned jukser + + + + 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 jukser 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 oppdateringsfil: + + + + Download Patches + Last ned oppdateringer + + + + Save + Lagre + + + + Cheats + Jukser + + + + Patches + Oppdateringer + + + + Error + Feil + + + + No patch selected. + Ingen oppdatering valgt. + + + + Unable to open files.json for reading. + Kan ikke åpne files.json for lesing. + + + + No patch file found for the current serial. + Ingen oppdateringsfil 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 parsing av XML: + + + + Success + Vellykket + + + + Options saved successfully. + Alternativer lagret vellykket. + + + + Invalid Source + Ugyldig kilde + + + + The selected source is invalid. + Den valgte kilden er ugyldig. + + + + File Exists + Fil eksisterer + + + + File already exists. Do you want to replace it? + Fil eksisterer allerede. Ønsker du å erstatte den? + + + + Failed to save file: + Kunne ikke lagre fil: + + + + Failed to download file: + Kunne ikke laste ned fil: + + + + Cheats Not Found + Jukser ikke funnet + + + + CheatsNotFound_MSG + Ingen jukser funnet for dette spillet i denne versjonen av det valgte depotet,prøv et annet depot eller en annen versjon av spillet. + + + + Cheats Downloaded Successfully + Jukser lastet ned vellykket + + + + CheatsDownloadedSuccessfully_MSG + Du har lastet ned jukser vellykket for denne versjonen av spillet fra det valgte depotet. Du kan prøve å laste ned fra et annet depot, 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 + + + + DownloadComplete_MSG + Oppdateringer lastet ned vellykket! Alle oppdateringer tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med jukser. + + + + Failed to parse JSON data from HTML. + Kunne ikke analysere JSON-data fra HTML. + + + + Failed to retrieve HTML page. + Kunne ikke hente HTML-side. + + + + Failed to open file: + Kunne ikke åpne fil: + + + + XML ERROR: + XML FEIL: + + + + Failed to open files.json for writing + Kunne ikke åpne files.json for skriving + + + + Author: + Forfatter: + + + + Directory does not exist: + Direktory eksisterer ikke: + + + + Failed to open files.json for reading. + Kunne ikke åpne files.json for lesing. + + + + Name: + Navn: + + \ No newline at end of file diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts index 2f4f5f9b2..8b55b0e2a 100644 --- a/src/qt_gui/translations/nl.ts +++ b/src/qt_gui/translations/nl.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Cheats / Patches + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Download Cheats/Patches + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging + + + MainWindow + + + * Unsupported Vulkan Version + * Niet ondersteunde Vulkan-versie + + + + Download Cheats For All Installed Games + Download cheats voor alle geïnstalleerde spellen + + + + Download Patches For All Games + Download patches voor alle spellen + + + + Download Complete + Download voltooid + + + + You have downloaded cheats for all the games you have installed. + Je hebt cheats gedownload voor alle spellen die je hebt geïnstalleerd. + + + + Patches Downloaded Successfully! + Patches succesvol gedownload! + + + + All Patches available for all games have been downloaded. + Alle patches voor alle spellen zijn gedownload. + + + + Games: + Spellen: + + + + PKG File (*.PKG) + PKG-bestand (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF-bestanden (*.bin *.elf *.oelf) + + + + Game Boot + Spelopstart + + + + Only one file can be selected! + Je kunt slechts één bestand selecteren! + + + + PKG Extraction + PKG-extractie + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch gedetecteerd!\nPKG en spelversies komen overeen!: %1\nWil je + + + + to overwrite? + overschrijven? + + + + Patch detected!\nPKG Version %1 is older + Patch gedetecteerd!\nPKG-versie %1 is ouder + + + + than installed version!: %2\nWould you like + dan de geïnstalleerde versie!: %2\nWil je + + + + to overwrite? + overschrijven? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch gedetecteerd!\nSpel is geïnstalleerd: %1\nWil je + + + + to install Patch: %2? + de patch installeren: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Spel al geïnstalleerd\n%1\nWil je het overschrijven? + + + + PKG is a patch, please install the game first! + PKG is een patch, installeer eerst het spel! + + + + PKG ERROR + PKG FOUT + + + + Extracting PKG %1/%2 + PKG %1/%2 aan het extraheren + + + + Extraction Finished + Extractie voltooid + + + + Game successfully installed at %1 + Spel succesvol geïnstalleerd op %1 + + + + File doesn't appear to be a valid PKG file + Het bestand lijkt geen geldig PKG-bestand te zijn + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches zijn experimenteel.\nGebruik met voorzichtigheid.\n\nDownload cheats afzonderlijk door het repository te selecteren en op de downloadknop te klikken.\nOp het tabblad Patches kun je alle patches tegelijk downloaden, kiezen welke je wilt gebruiken en je selectie opslaan.\n\nAangezien wij de Cheats/Patches niet ontwikkelen,\nmeld problemen bij de auteur van de cheat.\n\nHeb je een nieuwe cheat gemaakt? Bezoek:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Geen afbeelding beschikbaar + + + + Serial: + Serie: + + + + Version: + Versie: + + + + Size: + Grootte: + + + + Select Cheat File: + Selecteer cheatbestand: + + + + Repository: + Repository: + + + + Download Cheats + Download cheats + + + + Delete File + Bestand verwijderen + + + + No files selected. + Geen bestanden geselecteerd. + + + + You can delete the cheats you don't want after downloading them. + Je kunt de cheats die je niet wilt verwijderen nadat je ze hebt gedownload. + + + + Do you want to delete the selected file?\n%1 + Wil je het geselecteerde bestand verwijderen?\n%1 + + + + Select Patch File: + Selecteer patchbestand: + + + + Download Patches + Download patches + + + + Save + Opslaan + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Fout + + + + No patch selected. + Geen patch geselecteerd. + + + + Unable to open files.json for reading. + Kan files.json niet openen voor lezen. + + + + No patch file found for the current serial. + Geen patchbestand gevonden voor het huidige serienummer. + + + + Unable to open the file for reading. + Kan het bestand niet openen voor lezen. + + + + Unable to open the file for writing. + Kan het bestand niet openen voor schrijven. + + + + Failed to parse XML: + XML parsing mislukt: + + + + Success + Succes + + + + Options saved successfully. + Opties succesvol opgeslagen. + + + + Invalid Source + Ongeldige bron + + + + The selected source is invalid. + De geselecteerde bron is ongeldig. + + + + File Exists + Bestand bestaat + + + + File already exists. Do you want to replace it? + Bestand bestaat al. Wil je het vervangen? + + + + Failed to save file: + Kan bestand niet opslaan: + + + + Failed to download file: + Kan bestand niet downloaden: + + + + Cheats Not Found + Cheats niet gevonden + + + + CheatsNotFound_MSG + Geen cheats gevonden voor deze game in deze versie van de geselecteerde repository.Probeer een andere repository of een andere versie van het spel. + + + + Cheats Downloaded Successfully + Cheats succesvol gedownload + + + + CheatsDownloadedSuccessfully_MSG + Je hebt cheats succesvol gedownload voor deze versie van het spel uit de geselecteerde repository. Je kunt proberen te downloaden van een andere repository. Als deze beschikbaar is, kan het ook worden gebruikt door het bestand uit de lijst te selecteren. + + + + Failed to save: + Opslaan mislukt: + + + + Failed to download: + Downloaden mislukt: + + + + Download Complete + Download voltooid + + + + DownloadComplete_MSG + Patches succesvol gedownload! Alle beschikbare patches voor alle spellen zijn gedownload. Het is niet nodig om ze afzonderlijk te downloaden voor elk spel dat cheats heeft. + + + + Failed to parse JSON data from HTML. + Kan JSON-gegevens uit HTML niet parseren. + + + + Failed to retrieve HTML page. + Kan HTML-pagina niet ophalen. + + + + Failed to open file: + Kan bestand niet openen: + + + + XML ERROR: + XML FOUT: + + + + Failed to open files.json for writing + Kan files.json niet openen voor schrijven + + + + Author: + Auteur: + + + + Directory does not exist: + Map bestaat niet: + + + + Failed to open files.json for reading. + Kan files.json niet openen voor lezen. + + + + Name: + Naam: + \ No newline at end of file diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index 7d18f203d..41c06f89f 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -1,493 +1,892 @@ - - - - - - - AboutDialog - - - 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. - - - - This software should not be used to play games you have not legally obtained. - To oprogramowanie nie służy do grania w gry pochodzące z nielegalnego źródła. - - - - ElfViewer - - - Open Folder - Otwórz folder - - - - GameInfoClass - - - Loading game list, please wait :3 - Ładowanie listy gier, proszę poczekaj :3 - - - - Cancel - Anuluj - - - - Loading... - Ładowanie... - - - - GameInstallDialog - - - shadPS4 - Choose directory - shadPS4 - Wybierz katalog - - - - Directory to install games - Katalog do instalacji gier - - - - Browse - Przeglądaj - - - - Error - Błąd - - - - The value for location to install games is not valid. - Podana ścieżka do instalacji gier nie jest prawidłowa. - - - - GuiContextMenus - - - Create Shortcut - Utwórz skrót - - - - Open Game Folder - Otwórz katalog gry - - - - SFO Viewer - Menedżer plików SFO - - - - Trophy Viewer - Menedżer trofeów - - - - Copy info - Kopiuj informacje - - - - Copy Name - Kopiuj nazwę - - - - Copy Serial - Kopiuj numer seryjny - - - - Copy All - Kopiuj wszystko - - - - Shortcut creation - Tworzenie skrótu - - - - Shortcut created successfully!\n %1 - Utworzenie skrótu zakończone pomyślnie!\n %1 - - - - Error - Błąd - - - - Error creating shortcut!\n %1 - Utworzenie skrótu zakończone niepowodzeniem!\n %1 - - - - Install PKG - Zainstaluj PKG - - - - MainWindow - - - Open/Add Elf Folder - Otwórz/Dodaj folder Elf - - - - Install Packages (PKG) - Zainstaluj paczkę (PKG) - - - - Boot Game - Uruchom grę - - - - About shadPS4 - O programie - - - - Configure... - Konfiguruj... - - - - Install application from a .pkg file - Zainstaluj aplikacje z pliku .pkg - - - - Recent Games - Ostatnie gry - - - - Exit - Wyjdź - - - - Exit shadPS4 - Wyjdź z shadPS4 - - - - Exit the application. - Wyjdź z aplikacji. - - - - Show Game List - Pokaż listę gier - - - - Game List Refresh - Odśwież listę gier - - - - Tiny - Malutkie - - - - Small - Małe - - - - Medium - Średnie - - - - Large - Wielkie - - - - List View - Widok listy - - - - Grid View - Widok siatki - - - - Elf Viewer - Menedżer plików ELF - - - - Game Install Directory - Katalog zainstalowanej gry - - - - Dump Game List - Zgraj listę gier - - - - PKG Viewer - Menedżer plików PKG - - - - Search... - Szukaj... - - - - File - Plik - - - - View - Widok - - - - Game List Icons - Ikony w widoku listy - - - - Game List Mode - Tryb listy gier - - - - Settings - Ustawienia - - - - Utils - Narzędzia - - - - Themes - Motywy - - - - About - O programie - - - - Dark - Ciemny - - - - Light - Jasny - - - - Green - Zielony - - - - Blue - Niebieski - - - - Violet - Fioletowy - - - - toolBar - Pasek narzędzi - - - - PKGViewer - - - Open Folder - Open Folder - - - - TrophyViewer - - - Trophy Viewer - Menedżer trofeów - - - - SettingsDialog - - - Settings - Ustawienia - - - - General - Ogólne - - - - System - System - - - - Console Language - Język konsoli - - - - Emulator Language - Język emulatora - - - - Emulator - Emulator - - - - Enable Fullscreen - Włącz pełny ekran - - - - Show Splash - Pokaż ekran powitania - - - - Is PS4 Pro - Emulacja PS4 Pro - - - - Username - Nazwa użytkownika - - - - Logger - Dziennik zdarzeń - - - - Log Type - Typ dziennika - - - - Log Filter - Filtrowanie dziennika - - - - Graphics - Grafika - - - - Graphics Device - Karta graficzna - - - - Width - Szerokość - - - - Height - Wysokość - - - - Vblank Divider - Dzielnik pionowego blankingu (Vblank) - - - - Advanced - Zaawansowane - - - - Enable Shaders Dumping - Włącz zgrywanie cieni - - - - Enable NULL GPU - Wyłącz kartę graficzną - - - - Enable PM4 Dumping - Włącz zgrywanie PM4 - - - - Debug - Debugowanie - - - - Enable Debug Dumping - Włącz zgrywanie debugowania - - - - Enable Vulkan Validation Layers - Włącz warstwy walidacji Vulkan - - - - Enable Vulkan Synchronization Validation - Włącz walidację synchronizacji Vulkan - - - - Enable RenderDoc Debugging - Włącz debugowanie RenderDoc - - - + + + + AboutDialog + + + 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. + + + + This software should not be used to play games you have not legally obtained. + To oprogramowanie nie służy do grania w gry pochodzące z nielegalnego źródła. + + + + ElfViewer + + + Open Folder + Otwórz folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Ładowanie listy gier, proszę poczekaj :3 + + + + Cancel + Anuluj + + + + Loading... + Ładowanie... + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Wybierz katalog + + + + Directory to install games + Katalog do instalacji gier + + + + Browse + Przeglądaj + + + + Error + Błąd + + + + The value for location to install games is not valid. + Podana ścieżka do instalacji gier nie jest prawidłowa. + + + + GuiContextMenus + + + Create Shortcut + Utwórz skrót + + + + Open Game Folder + Otwórz katalog gry + + + + Cheats / Patches + Kody / Patche + + + + SFO Viewer + Menedżer plików SFO + + + + Trophy Viewer + Menedżer trofeów + + + + Copy info + Kopiuj informacje + + + + Copy Name + Kopiuj nazwę + + + + Copy Serial + Kopiuj numer seryjny + + + + Copy All + Kopiuj wszystko + + + + Shortcut creation + Tworzenie skrótu + + + + Shortcut created successfully!\n %1 + Utworzenie skrótu zakończone pomyślnie!\n %1 + + + + Error + Błąd + + + + Error creating shortcut!\n %1 + Utworzenie skrótu zakończone niepowodzeniem!\n %1 + + + + Install PKG + Zainstaluj PKG + + + + MainWindow + + + Open/Add Elf Folder + Otwórz/Dodaj folder Elf + + + + Install Packages (PKG) + Zainstaluj paczkę (PKG) + + + + Boot Game + Uruchom grę + + + + About shadPS4 + O programie + + + + Configure... + Konfiguruj... + + + + Install application from a .pkg file + Zainstaluj aplikacje z pliku .pkg + + + + Recent Games + Ostatnie gry + + + + Exit + Wyjdź + + + + Exit shadPS4 + Wyjdź z shadPS4 + + + + Exit the application. + Wyjdź z aplikacji. + + + + Show Game List + Pokaż listę gier + + + + Game List Refresh + Odśwież listę gier + + + + Tiny + Malutkie + + + + Small + Małe + + + + Medium + Średnie + + + + Large + Wielkie + + + + List View + Widok listy + + + + Grid View + Widok siatki + + + + Elf Viewer + Menedżer plików ELF + + + + Game Install Directory + Katalog zainstalowanej gry + + + + Download Cheats/Patches + Pobierz Kody / Patche + + + + Dump Game List + Zgraj listę gier + + + + PKG Viewer + Menedżer plików PKG + + + + Search... + Szukaj... + + + + File + Plik + + + + View + Widok + + + + Game List Icons + Ikony w widoku listy + + + + Game List Mode + Tryb listy gier + + + + Settings + Ustawienia + + + + Utils + Narzędzia + + + + Themes + Motywy + + + + About + O programie + + + + Dark + Ciemny + + + + Light + Jasny + + + + Green + Zielony + + + + Blue + Niebieski + + + + Violet + Fioletowy + + + + toolBar + Pasek narzędzi + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Menedżer trofeów + + + + SettingsDialog + + + Settings + Ustawienia + + + + General + Ogólne + + + + System + System + + + + Console Language + Język konsoli + + + + Emulator Language + Język emulatora + + + + Emulator + Emulator + + + + Enable Fullscreen + Włącz pełny ekran + + + + Show Splash + Pokaż ekran powitania + + + + Is PS4 Pro + Emulacja PS4 Pro + + + + Username + Nazwa użytkownika + + + + Logger + Dziennik zdarzeń + + + + Log Type + Typ dziennika + + + + Log Filter + Filtrowanie dziennika + + + + Graphics + Grafika + + + + Graphics Device + Karta graficzna + + + + Width + Szerokość + + + + Height + Wysokość + + + + Vblank Divider + Dzielnik pionowego blankingu (Vblank) + + + + Advanced + Zaawansowane + + + + Enable Shaders Dumping + Włącz zgrywanie cieni + + + + Enable NULL GPU + Wyłącz kartę graficzną + + + + Enable PM4 Dumping + Włącz zgrywanie PM4 + + + + Debug + Debugowanie + + + + Enable Debug Dumping + Włącz zgrywanie debugowania + + + + Enable Vulkan Validation Layers + Włącz warstwy walidacji Vulkan + + + + Enable Vulkan Synchronization Validation + Włącz walidację synchronizacji Vulkan + + + + Enable RenderDoc Debugging + Włącz debugowanie RenderDoc + + + + MainWindow + + + * Unsupported Vulkan Version + * Nieobsługiwana wersja Vulkan + + + + Download Cheats For All Installed Games + Pobierz kody do wszystkich zainstalowanych gier + + + + Download Patches For All Games + Pobierz poprawki do wszystkich gier + + + + Download Complete + Pobieranie zakończone + + + + You have downloaded cheats for all the games you have installed. + Pobrałeś kody do wszystkich zainstalowanych gier. + + + + Patches Downloaded Successfully! + Poprawki pobrane pomyślnie! + + + + All Patches available for all games have been downloaded. + Wszystkie poprawki dostępne dla wszystkich gier zostały pobrane. + + + + Games: + Gry: + + + + PKG File (*.PKG) + Plik PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Pliki ELF (*.bin *.elf *.oelf) + + + + Game Boot + Uruchomienie gry + + + + Only one file can be selected! + Można wybrać tylko jeden plik! + + + + PKG Extraction + Ekstrakcja PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Wykryto poprawkę!\nWersje PKG i gry pasują do siebie!: %1\nCzy chcesz + + + + to overwrite? + nadpisać? + + + + Patch detected!\nPKG Version %1 is older + Wykryto poprawkę!\nWersja PKG %1 jest starsza + + + + than installed version!: %2\nWould you like + niż zainstalowana wersja!: %2\nCzy chcesz + + + + to overwrite? + nadpisać? + + + + Patch detected!\nGame is installed: %1\nWould you like + Wykryto poprawkę!\nGra jest zainstalowana: %1\nCzy chcesz + + + + to install Patch: %2? + zainstalować poprawkę: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Gra już zainstalowana\n%1\nCzy chcesz ją nadpisać? + + + + PKG is a patch, please install the game first! + PKG jest poprawką, proszę najpierw zainstalować grę! + + + + PKG ERROR + BŁĄD PKG + + + + Extracting PKG %1/%2 + Ekstrakcja PKG %1/%2 + + + + Extraction Finished + Ekstrakcja zakończona + + + + Game successfully installed at %1 + Gra pomyślnie zainstalowana w %1 + + + + File doesn't appear to be a valid PKG file + Plik nie wydaje się być prawidłowym plikiem PKG + + + + CheatsPatches + + + Cheats / Patches + Kody / Poprawki + + + + defaultTextEdit_MSG + Cheaty/Patche są eksperymentalne.\nUżywaj ich ostrożnie.\n\nPobierz cheaty pojedynczo, wybierając repozytorium i klikając przycisk pobierania.\nNa zakładce Patches możesz pobrać wszystkie patche jednocześnie, wybrać, które chcesz używać, i zapisać wybór.\n\nPonieważ nie rozwijamy Cheats/Patches,\nproszę zgłosić problemy do autora cheatu.\n\nStworzyłeś nowy cheat? Odwiedź:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Brak dostępnego obrazu + + + + Serial: + Numer seryjny: + + + + Version: + Wersja: + + + + Size: + Rozmiar: + + + + Select Cheat File: + Wybierz plik kodu: + + + + Repository: + Repozytorium: + + + + Download Cheats + Pobierz kody + + + + Remove Old Files + Usuń stare pliki + + + + Do you want to delete the files after downloading them? + Czy chcesz usunąć pliki po ich pobraniu? + + + + Do you want to delete the files after downloading them?\n%1 + Czy chcesz usunąć pliki po ich pobraniu?\n%1 + + + + Do you want to delete the selected file?\n%1 + Czy chcesz usunąć wybrany plik?\n%1 + + + + Select Patch File: + Wybierz plik poprawki: + + + + Download Patches + Pobierz poprawki + + + + Save + Zapisz + + + + Cheats + Kody + + + + Patches + Poprawki + + + + Error + Błąd + + + + No patch selected. + Nie wybrano poprawki. + + + + Unable to open files.json for reading. + Nie można otworzyć pliku files.json do odczytu. + + + + No patch file found for the current serial. + Nie znaleziono pliku poprawki dla bieżącego numeru seryjnego. + + + + Unable to open the file for reading. + Nie można otworzyć pliku do odczytu. + + + + Unable to open the file for writing. + Nie można otworzyć pliku do zapisu. + + + + Failed to parse XML: + Nie udało się sparsować XML: + + + + Success + Sukces + + + + Options saved successfully. + Opcje zostały pomyślnie zapisane. + + + + Invalid Source + Nieprawidłowe źródło + + + + The selected source is invalid. + Wybrane źródło jest nieprawidłowe. + + + + File Exists + Plik istnieje + + + + File already exists. Do you want to replace it? + Plik już istnieje. Czy chcesz go zastąpić? + + + + Failed to save file: + Nie udało się zapisać pliku: + + + + Failed to download file: + Nie udało się pobrać pliku: + + + + Cheats Not Found + Nie znaleziono kodów + + + + CheatsNotFound_MSG + Nie znaleziono kodów do tej gry w tej wersji wybranego repozytorium.Spróbuj innego repozytorium lub innej wersji gry. + + + + Cheats Downloaded Successfully + Kody pobrane pomyślnie + + + + CheatsDownloadedSuccessfully_MSG + Pomyślnie pobrano kody dla tej wersji gry z wybranego repozytorium. Możesz spróbować pobrać z innego repozytorium. Jeśli jest dostępne, możesz również użyć go, wybierając plik z listy. + + + + Failed to save: + Nie udało się zapisać: + + + + Failed to download: + Nie udało się pobrać: + + + + Download Complete + Pobieranie zakończone + + + + DownloadComplete_MSG + Poprawki zostały pomyślnie pobrane! Wszystkie dostępne poprawki dla wszystkich gier zostały pobrane. Nie ma potrzeby pobierania ich osobno dla każdej gry, która ma kody. + + + + Failed to parse JSON data from HTML. + Nie udało się sparsować danych JSON z HTML. + + + + Failed to retrieve HTML page. + Nie udało się pobrać strony HTML. + + + + Failed to open file: + Nie udało się otworzyć pliku: + + + + XML ERROR: + BŁĄD XML: + + + + Failed to open files.json for writing + Nie udało się otworzyć pliku files.json do zapisu + + + + Author: + Autor: + + + + Directory does not exist: + Katalog nie istnieje: + + + + Directory does not exist: %1 + Katalog nie istnieje: %1 + + + + Failed to parse JSON: + Nie udało się sparsować JSON: + + + \ No newline at end of file diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index c98d84410..c198d1fd3 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Criar Atalho - + Open Game Folder Abrir Pasta do Jogo - + + Cheats / Patches + Cheats / Patches + + + SFO Viewer Visualizador de SFO - + Trophy Viewer Visualizador de Troféu - + Copy info Copiar informação - + Copy Name Copiar Nome - + Copy Serial Copiar Serial - + Copy All Copiar Tudo - + Shortcut creation Criação de atalho - + Shortcut created successfully!\n %1 Atalho criado com sucesso!\n %1 - + Error Erro - + Error creating shortcut!\n %1 Erro ao criar atalho!\n %1 - + Install PKG Instalar PKG @@ -248,6 +253,11 @@ Game Install Directory Diretório de Instalação de Jogos + + + Download Cheats/Patches + Baixar Trapaças / Patches + Dump Game List @@ -488,4 +498,395 @@ Ativar Depuração por RenderDoc + + MainWindow + + + * Unsupported Vulkan Version + * Versão Vulkan não suportada + + + + Download Cheats For All Installed Games + Baixar Trapaças para todos os jogos instalados + + + + Download Patches For All Games + Baixar Patches para todos os jogos + + + + Download Complete + Download Completo + + + + You have downloaded cheats for all the games you have installed. + Você baixou trapaças para todos os jogos que instalou. + + + + Patches Downloaded Successfully! + Patches Baixados com Sucesso! + + + + All Patches available for all games have been downloaded. + Todos os patches disponíveis para todos os jogos foram baixados. + + + + Games: + Jogos: + + + + PKG File (*.PKG) + Arquivo PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Arquivos ELF (*.bin *.elf *.oelf) + + + + Game Boot + Inicialização do Jogo + + + + Only one file can be selected! + Apenas um arquivo pode ser selecionado! + + + + PKG Extraction + Extração de PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch detectado!\nVersões PKG e do Jogo correspondem!: %1\nGostaria de + + + + to overwrite? + substituir? + + + + Patch detected!\nPKG Version %1 is older + Patch detectado!\nVersão PKG %1 é mais antiga + + + + than installed version!: %2\nWould you like + do que a versão instalada!: %2\nGostaria de + + + + to overwrite? + substituir? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch detectado!\nJogo está instalado: %1\nGostaria de + + + + to install Patch: %2? + instalar o Patch: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Jogo já instalado\n%1\nGostaria de substituir? + + + + PKG is a patch, please install the game first! + PKG é um patch, por favor, instale o jogo primeiro! + + + + PKG ERROR + ERRO PKG + + + + Extracting PKG %1/%2 + Extraindo PKG %1/%2 + + + + Extraction Finished + Extração Concluída + + + + Game successfully installed at %1 + Jogo instalado com sucesso em %1 + + + + File doesn't appear to be a valid PKG file + O arquivo não parece ser um arquivo PKG válido + + + + CheatsPatches + + + Cheats / Patches + Trapaças / Patches + + + + defaultTextEdit_MSG + Trapaças/Patches são experimentais.\nUse com cautela.\n\nBaixe as trapaças individualmente selecionando o repositório e clicando no botão de download.\nNa aba Patches, você pode baixar todos os Patches de uma vez, escolher qual deseja usar e salvar a opção.\n\nComo não desenvolvemos as Trapaças/Patches,\npor favor, reporte problemas relacionados ao autor da trapaça.\n\nCriou uma nova trapaça? Visite:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Imagem Não Disponível + + + + Serial: + Série: + + + + Version: + Versão: + + + + Size: + Tamanho: + + + + Select Cheat File: + Selecione o Arquivo de Trapaça: + + + + Repository: + Repositório: + + + + Download Cheats + Baixar Trapaças + + + + Delete File + Excluir Arquivo + + + + No files selected. + Nenhum arquivo selecionado. + + + + You can delete the cheats you don't want after downloading them. + Você pode excluir as trapaças que não deseja após baixá-las. + + + + Do you want to delete the selected file?\n%1 + Deseja excluir o arquivo selecionado?\n%1 + + + + Select Patch File: + Selecione o Arquivo de Patch: + + + + Download Patches + Baixar Patches + + + + Save + Salvar + + + + Cheats + Trapaças + + + + Patches + Patches + + + + Error + Erro + + + + No patch selected. + Nenhum patch selecionado. + + + + 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. + Nenhum arquivo de patch encontrado para a série atual. + + + + Unable to open the file for reading. + Não foi possível abrir o arquivo para leitura. + + + + Unable to open the file for writing. + Não foi possível abrir o arquivo para gravação. + + + + Failed to parse XML: + Falha ao analisar XML: + + + + Success + Sucesso + + + + Options saved successfully. + Opções salvas com sucesso. + + + + Invalid Source + Fonte Inválida + + + + The selected source is invalid. + A fonte selecionada é inválida. + + + + File Exists + Arquivo Existe + + + + File already exists. Do you want to replace it? + O arquivo já existe. Deseja substituí-lo? + + + + Failed to save file: + Falha ao salvar o arquivo: + + + + Failed to download file: + Falha ao baixar o arquivo: + + + + Cheats Not Found + Trapaças Não Encontradas + + + + CheatsNotFound_MSG + Nenhuma trapaça encontrada para este jogo nesta versão do repositório selecionado, tente outro repositório ou uma versão diferente do jogo. + + + + Cheats Downloaded Successfully + Trapaças Baixadas com Sucesso + + + + CheatsDownloadedSuccessfully_MSG + Você baixou as trapaças com sucesso. Para esta versão do jogo a partir do repositório selecionado.Você pode tentar baixar de outro repositório, se estiver disponível, também será possível usá-lo selecionando o arquivo da lista. + + + + Failed to save: + Falha ao salvar: + + + + Failed to download: + Falha ao baixar: + + + + Download Complete + Download Completo + + + + DownloadComplete_MSG + Patches Baixados com Sucesso! Todos os patches disponíveis para todos os jogos foram baixados, não é necessário baixá-los individualmente para cada jogo como acontece com as Trapaças. + + + + Failed to parse JSON data from HTML. + Falha ao analisar dados JSON do HTML. + + + + Failed to retrieve HTML page. + Falha ao recuperar a página HTML. + + + + Failed to open file: + Falha ao abrir o arquivo: + + + + XML ERROR: + ERRO XML: + + + + Failed to open files.json for writing + Falha ao abrir files.json para gravação + + + + Author: + Autor: + + + + Directory does not exist: + Diretório não existe: + + + + Failed to open files.json for reading. + Falha ao abrir files.json para leitura. + + + + Name: + Nome: + + \ No newline at end of file diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index c7dfae1b4..3463182f5 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Trapaças / Patches + Coduri / Patch-uri + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Descarcă Coduri / Patch-uri + Dump Game List @@ -487,5 +497,396 @@ Enable RenderDoc Debugging Enable RenderDoc Debugging + + + MainWindow + + + * Unsupported Vulkan Version + * Versiune Vulkan nesuportată + + + + Download Cheats For All Installed Games + Descarcă Cheats pentru toate jocurile instalate + + + + Download Patches For All Games + Descarcă Patches pentru toate jocurile + + + + Download Complete + Descărcare completă + + + + You have downloaded cheats for all the games you have installed. + Ai descărcat cheats pentru toate jocurile instalate. + + + + Patches Downloaded Successfully! + Patches descărcate cu succes! + + + + All Patches available for all games have been downloaded. + Toate Patches disponibile pentru toate jocurile au fost descărcate. + + + + Games: + Jocuri: + + + + PKG File (*.PKG) + Fișier PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Fișiere ELF (*.bin *.elf *.oelf) + + + + Game Boot + Boot Joc + + + + Only one file can be selected! + Numai un fișier poate fi selectat! + + + + PKG Extraction + Extracție PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Patch detectat!\nVersiunile PKG și Joc se potrivesc!: %1\nAi dori să + + + + to overwrite? + să suprascrii? + + + + Patch detected!\nPKG Version %1 is older + Patch detectat!\nVersiunea PKG %1 este mai veche + + + + than installed version!: %2\nWould you like + decât versiunea instalată!: %2\nAi dori să + + + + to overwrite? + să suprascrii? + + + + Patch detected!\nGame is installed: %1\nWould you like + Patch detectat!\nJocul este instalat: %1\nAi dori să + + + + to install Patch: %2? + să instalezi Patch-ul: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Jocul este deja instalat\n%1\nAi dori să suprascrii? + + + + PKG is a patch, please install the game first! + PKG este un patch, te rugăm să instalezi mai întâi jocul! + + + + PKG ERROR + EROARE PKG + + + + Extracting PKG %1/%2 + Extracție PKG %1/%2 + + + + Extraction Finished + Extracție terminată + + + + Game successfully installed at %1 + Jocul a fost instalat cu succes la %1 + + + + File doesn't appear to be a valid PKG file + Fișierul nu pare să fie un fișier PKG valid + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches sunt experimentale.\nUtilizați cu prudență.\n\nDescărcați cheats individual prin selectarea depozitului și făcând clic pe butonul de descărcare.\nÎn fila Patches, puteți descărca toate patch-urile deodată, alege pe cele pe care doriți să le utilizați și salvați selecția.\n\nDeoarece nu dezvoltăm Cheats/Patches,\nte rugăm să raportezi problemele autorului cheat-ului.\n\nAi creat un nou cheat? Vizitează:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Nu este disponibilă imaginea + + + + Serial: + Serial: + + + + Version: + Versiune: + + + + Size: + Dimensiune: + + + + Select Cheat File: + Selectează fișierul Cheat: + + + + Repository: + Repository: + + + + Download Cheats + Descarcă Cheats + + + + Delete File + Șterge Fișierul + + + + No files selected. + Nu sunt fișiere selectate. + + + + You can delete the cheats you don't want after downloading them. + Poti șterge cheats-urile pe care nu le dorești după ce le-ai descărcat. + + + + Do you want to delete the selected file?\n%1 + Vrei să ștergi fișierul selectat?\n%1 + + + + Select Patch File: + Selectează fișierul Patch: + + + + Download Patches + Descarcă Patches + + + + Save + Salvează + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Eroare + + + + No patch selected. + Nu este selectat niciun patch. + + + + Unable to open files.json for reading. + Imposibil de deschis files.json pentru citire. + + + + No patch file found for the current serial. + Nu s-a găsit niciun fișier patch pentru serialul curent. + + + + Unable to open the file for reading. + Imposibil de deschis fișierul pentru citire. + + + + Unable to open the file for writing. + Imposibil de deschis fișierul pentru scriere. + + + + Failed to parse XML: + Nu s-a reușit pararea XML: + + + + Success + Succes + + + + Options saved successfully. + Opțiunile au fost salvate cu succes. + + + + Invalid Source + Sursă invalidă + + + + The selected source is invalid. + Sursa selectată este invalidă. + + + + File Exists + Fișier existent + + + + File already exists. Do you want to replace it? + Fișierul există deja. Vrei să-l înlocuiești? + + + + Failed to save file: + Nu s-a reușit salvarea fișierului: + + + + Failed to download file: + Nu s-a reușit descărcarea fișierului: + + + + Cheats Not Found + Cheats Nu au fost găsite + + + + CheatsNotFound_MSG + Nu au fost găsite cheats pentru acest joc în această versiune a repository-ului selectat, încearcă un alt repository sau o versiune diferită a jocului. + + + + Cheats Downloaded Successfully + Cheats descărcate cu succes + + + + CheatsDownloadedSuccessfully_MSG + Ai descărcat cu succes cheats-urile pentru această versiune a jocului din repository-ul selectat. Poți încerca descărcarea din alt repository; dacă este disponibil, va fi posibil să-l folosești selectând fișierul din listă. + + + + Failed to save: + Nu s-a reușit salvarea: + + + + Failed to download: + Nu s-a reușit descărcarea: + + + + Download Complete + Descărcare completă + + + + DownloadComplete_MSG + Patches descărcate cu succes! Toate Patches disponibile pentru toate jocurile au fost descărcate; nu este nevoie să le descarci individual pentru fiecare joc, așa cum se întâmplă cu Cheats. + + + + Failed to parse JSON data from HTML. + Nu s-a reușit pararea datelor JSON din HTML. + + + + Failed to retrieve HTML page. + Nu s-a reușit obținerea paginii HTML. + + + + Failed to open file: + Nu s-a reușit deschiderea fișierului: + + + + XML ERROR: + EROARE XML: + + + + Failed to open files.json for writing + Nu s-a reușit deschiderea files.json pentru scriere + + + + Author: + Autor: + + + + Directory does not exist: + Directorul nu există: + + + + Failed to open files.json for reading. + Nu s-a reușit deschiderea files.json pentru citire. + + + + Name: + Nume: + \ No newline at end of file diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 46a30cdeb..a71533a35 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Создать ярлык - + Open Game Folder Открыть папку с игрой - + + Cheats / Patches + Читы / Патчи + + + SFO Viewer Просмотр SFO - + Trophy Viewer Просмотр трофеев - + Copy info Копировать информацию - + Copy Name Копировать имя - + Copy Serial Копировать серийный номер - + Copy All Копировать все - + Shortcut creation Создание ярлыка - + Shortcut created successfully!\n %1 Ярлык создан успешно!\n %1 - + Error Ошибка - + Error creating shortcut!\n %1 Ошибка создания ярлыка!\n %1 - + Install PKG Установить PKG @@ -248,6 +253,11 @@ Game Install Directory Каталог установки игры + + + Download Cheats/Patches + Скачать Читы / Патчи + Dump Game List @@ -488,4 +498,395 @@ Включить отладку RenderDoc - + + MainWindow + + + * Unsupported Vulkan Version + * Неподдерживаемая версия Vulkan + + + + Download Cheats For All Installed Games + Скачать читы для всех установленных игр + + + + Download Patches For All Games + Скачать патчи для всех игр + + + + Download Complete + Скачивание завершено + + + + You have downloaded cheats for all the games you have installed. + Вы скачали читы для всех установленных игр. + + + + Patches Downloaded Successfully! + Патчи успешно скачаны! + + + + All Patches available for all games have been downloaded. + Все доступные патчи для всех игр были скачаны. + + + + Games: + Игры: + + + + PKG File (*.PKG) + Файл PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Файл ELF (*.bin *.elf *.oelf) + + + + Game Boot + Запуск игры + + + + Only one file can be selected! + Можно выбрать только один файл! + + + + PKG Extraction + Извлечение PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Обнаружен патч!\nВерсии PKG и игры совпадают!: %1\nХотите + + + + to overwrite? + перезаписать? + + + + Patch detected!\nPKG Version %1 is older + Обнаружен патч!\nВерсия PKG %1 устарела + + + + than installed version!: %2\nWould you like + по сравнению с установленной версией!: %2\nХотите + + + + to overwrite? + перезаписать? + + + + Patch detected!\nGame is installed: %1\nWould you like + Обнаружен патч!\nИгра установлена: %1\nХотите + + + + to install Patch: %2? + установить патч: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Игра уже установлена\n%1\nХотите перезаписать? + + + + PKG is a patch, please install the game first! + PKG - это патч, сначала установите игру! + + + + PKG ERROR + ОШИБКА PKG + + + + Extracting PKG %1/%2 + Извлечение PKG %1/%2 + + + + Extraction Finished + Извлечение завершено + + + + Game successfully installed at %1 + Игра успешно установлена по адресу %1 + + + + File doesn't appear to be a valid PKG file + Файл не является допустимым файлом PKG + + + + CheatsPatches + + + Cheats / Patches + Читы / Патчи + + + + defaultTextEdit_MSG + Cheats/Patches sunt experimentale.\nUtilizați cu prudență.\n\nDescărcați cheats individual prin selectarea depozitului și făcând clic pe butonul de descărcare.\nÎn fila Patches, puteți descărca toate patch-urile deodată, alege pe cele pe care doriți să le utilizați și salvați selecția.\n\nDeoarece nu dezvoltăm Cheats/Patches,\nte rugăm să raportezi problemele autorului cheat-ului.\n\nAi creat un nou cheat? Vizitează:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Изображение недоступно + + + + Serial: + Серийный номер: + + + + Version: + Версия: + + + + Size: + Размер: + + + + Select Cheat File: + Выберите файл чита: + + + + Repository: + Репозиторий: + + + + Download Cheats + Скачать читы + + + + Delete File + Удалить файл + + + + No files selected. + Файлы не выбраны. + + + + You can delete the cheats you don't want after downloading them. + Вы можете удалить ненужные читы после их скачивания. + + + + Do you want to delete the selected file?\n%1 + Вы хотите удалить выбранный файл?\n%1 + + + + Select Patch File: + Выберите файл патча: + + + + Download Patches + Скачать патчи + + + + Save + Сохранить + + + + Cheats + Читы + + + + Patches + Патчи + + + + Error + Ошибка + + + + No patch selected. + Патч не выбран. + + + + Unable to open files.json for reading. + Не удалось открыть файл files.json для чтения. + + + + No patch file found for the current serial. + Не найден файл патча для текущего серийного номера. + + + + Unable to open the file for reading. + Не удалось открыть файл для чтения. + + + + Unable to open the file for writing. + Не удалось открыть файл для записи. + + + + Failed to parse XML: + Не удалось разобрать XML: + + + + Success + Успех + + + + Options saved successfully. + Опции успешно сохранены. + + + + Invalid Source + Неверный источник + + + + The selected source is invalid. + Выбранный источник недействителен. + + + + File Exists + Файл существует + + + + File already exists. Do you want to replace it? + Файл уже существует. Хотите заменить его? + + + + Failed to save file: + Не удалось сохранить файл: + + + + Failed to download file: + Не удалось скачать файл: + + + + Cheats Not Found + Читы не найдены + + + + CheatsNotFound_MSG + Читы не найдены для этой игры в выбранном репозитории. Попробуйте другой репозиторий или другую версию игры. + + + + Cheats Downloaded Successfully + Читы успешно скачаны + + + + CheatsDownloadedSuccessfully_MSG + Вы успешно скачали читы для этой версии игры из выбранного репозитория. Вы можете попробовать скачать из другого репозитория. Если он доступен, его также можно будет использовать, выбрав файл из списка. + + + + Failed to save: + Не удалось сохранить: + + + + Failed to download: + Не удалось скачать: + + + + Download Complete + Скачивание завершено + + + + DownloadComplete_MSG + Патчи успешно скачаны! Все доступные патчи для всех игр были скачаны, нет необходимости скачивать их по отдельности для каждой игры, как это происходит с читами. + + + + Failed to parse JSON data from HTML. + Не удалось разобрать данные JSON из HTML. + + + + Failed to retrieve HTML page. + Не удалось получить HTML-страницу. + + + + Failed to open file: + Не удалось открыть файл: + + + + XML ERROR: + ОШИБКА XML: + + + + Failed to open files.json for writing + Не удалось открыть файл files.json для записи + + + + Author: + Автор: + + + + Directory does not exist: + Каталог не существует: + + + + Failed to open files.json for reading. + Не удалось открыть файл files.json для чтения. + + + + Name: + Имя: + + + \ No newline at end of file diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index ea5d0765f..514b9af7e 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Kısayol Oluştur - + Open Game Folder Oyun Klasörünü Aç - + + Cheats / Patches + Hileler / Yamanlar + + + SFO Viewer SFO Görüntüleyici - + Trophy Viewer Kupa Görüntüleyici - + Copy info Bilgiyi Kopyala - + Copy Name Adı Kopyala - + Copy Serial Seri Numarasını Kopyala - + Copy All Tümünü Kopyala - + Shortcut creation Kısayol oluşturma - + Shortcut created successfully!\n %1 Kısayol başarıyla oluşturuldu!\n %1 - + Error Hata - + Error creating shortcut!\n %1 Kısayol oluşturulurken hata oluştu!\n %1 - + Install PKG PKG Yükle @@ -248,6 +253,11 @@ Game Install Directory Oyun Kurulum Klasörü + + + Download Cheats/Patches + Hileler / Yamanlar İndir + Dump Game List @@ -488,4 +498,466 @@ RenderDoc Hata Ayıklamayı Etkinleştir + + MainWindow + + + * Unsupported Vulkan Version + * Desteklenmeyen Vulkan Sürümü + + + + Download Cheats For All Installed Games + Tüm Yüklenmiş Oyunlar İçin Hileleri İndir + + + + Download Patches For All Games + Tüm Oyunlar İçin Yamanları İndir + + + + Download Complete + İndirme Tamamlandı + + + + You have downloaded cheats for all the games you have installed. + Yüklediğiniz tüm oyunlar için hileleri indirdiniz. + + + + Patches Downloaded Successfully! + Yamalar Başarıyla İndirildi! + + + + All Patches available for all games have been downloaded. + Tüm oyunlar için mevcut tüm yamalar indirildi. + + + + Games: + Oyunlar: + + + + PKG File (*.PKG) + PKG Dosyası (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF Dosyaları (*.bin *.elf *.oelf) + + + + Game Boot + Oyun Başlatma + + + + Only one file can be selected! + Sadece bir dosya seçilebilir! + + + + PKG Extraction + PKG Çıkartma + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Yama tespit edildi!\nPKG ve Oyun sürümleri uyuyor!: %1\nÜzerine yazmak ister misiniz? + + + + to overwrite? + üzerine yazmak? + + + + Patch detected!\nPKG Version %1 is older + Yama tespit edildi!\nPKG Sürümü %1 daha eski + + + + than installed version!: %2\nWould you like + yüklü sürümden!: %2\nÜzerine yazmak ister misiniz? + + + + to overwrite? + üzerine yazmak? + + + + Patch detected!\nGame is installed: %1\nWould you like + Yama tespit edildi!\nOyun yüklü: %1\nÜzerine yazmak ister misiniz? + + + + to install Patch: %2? + Yamayı kurmak ister misiniz: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Oyun zaten yüklü\n%1\nÜzerine yazmak ister misiniz? + + + + PKG is a patch, please install the game first! + PKG bir yama, lütfen önce oyunu yükleyin! + + + + PKG ERROR + PKG HATASI + + + + Extracting PKG %1/%2 + PKG Çıkarılıyor %1/%2 + + + + Extraction Finished + Çıkarma Tamamlandı + + + + Game successfully installed at %1 + Oyun başarıyla %1 konumuna yüklendi + + + + File doesn't appear to be a valid PKG file + Dosya geçerli bir PKG dosyası gibi görünmüyor + + + + CheatsPatches + + + Cheats / Patches + Hileler / Yamalar + + + + defaultTextEdit_MSG + Cheats/Patches deneysel niteliktedir.\nDikkatli kullanın.\n\nCheat'leri ayrı ayrı indirerek, depo seçerek ve indirme düğmesine tıklayarak indirin.\nPatches sekmesinde tüm patch'leri bir kerede indirebilir, hangi patch'leri kullanmak istediğinizi seçebilir ve seçiminizi kaydedebilirsiniz.\n\nCheats/Patches'i geliştirmediğimiz için,\nproblemleri cheat yazarına bildirin.\n\nYeni bir cheat mi oluşturduğunuz? Şu adresi ziyaret edin:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Görüntü Mevcut Değil + + + + Serial: + Seri Numarası: + + + + Version: + Sürüm: + + + + Size: + Boyut: + + + + Select Cheat File: + Hile Dosyasını Seçin: + + + + Repository: + Depo: + + + + Download Cheats + Hileleri İndir + + + + Confirm Delete + Silme Onayı + + + + Are you sure you want to delete the selected cheat?\n%1 + Seçilen hileyi silmek istediğinizden emin misiniz?\n%1 + + + + You can delete the cheats you don't want after downloading them. + İndirdikten sonra istemediğiniz hileleri silebilirsiniz. + + + + Do you want to delete the selected file?\n%1 + Seçilen dosyayı silmek istiyor musunuz?\n%1 + + + + Select Patch File: + Yama Dosyasını Seçin: + + + + Download Patches + Yamaları İndir + + + + Save + Kaydet + + + + Cheats + Hileler + + + + Patches + Yamalar + + + + Error + Hata + + + + No patch selected. + Hiç yama seçilmedi. + + + + Unable to open files.json for reading. + files.json dosyasını okumak için açılamadı. + + + + No patch file found for the current serial. + Mevcut seri numarası için hiç yama dosyası bulunamadı. + + + + Unable to open the file for reading. + Dosya okumak için açılamadı. + + + + Unable to open the file for writing. + Dosya yazmak için açılamadı. + + + + Failed to parse XML: + XML ayrıştırılamadı: + + + + Success + Başarı + + + + Options saved successfully. + Ayarlar başarıyla kaydedildi. + + + + Invalid Source + Geçersiz Kaynak + + + + The selected source is invalid. + Seçilen kaynak geçersiz. + + + + File Exists + Dosya Var + + + + File already exists. Do you want to replace it? + Dosya zaten var. Üzerine yazmak ister misiniz? + + + + Failed to save file: + Dosya kaydedilemedi: + + + + Failed to download file: + Dosya indirilemedi: + + + + Cheats Not Found + Hileler Bulunamadı + + + + CheatsNotFound_MSG + Bu oyun için seçilen depoda hile bulunamadı.Başka bir depo veya oyun sürümü deneyin. + + + + Cheats Downloaded Successfully + Hileler Başarıyla İndirildi + + + + CheatsDownloadedSuccessfully_MSG + Bu oyun sürümü için hileleri başarıyla indirdiniz. Başka bir depodan indirmeyi deneyebilirsiniz. Eğer mevcutsa, listeden dosyayı seçerek de kullanılabilir. + + + + Failed to save: + Kaydedilemedi: + + + + Failed to download: + İndirilemedi: + + + + Download Complete + İndirme Tamamlandı + + + + DownloadComplete_MSG + Yamalar başarıyla indirildi! Tüm oyunlar için mevcut tüm yamalar indirildi, her oyun için ayrı ayrı indirme yapmanız gerekmez, hilelerle olduğu gibi. + + + + Failed to parse JSON data from HTML. + HTML'den JSON verileri ayrıştırılamadı. + + + + Failed to retrieve HTML page. + HTML sayfası alınamadı. + + + + Failed to open file: + Dosya açılamadı: + + + + XML ERROR: + XML HATASI: + + + + Failed to open files.json for writing + files.json dosyası yazmak için açılamadı + + + + Author: + Yazar: + + + + Directory does not exist: + Klasör mevcut değil: + + + + Failed to open files.json for reading. + files.json dosyası okumak için açılamadı. + + + + Name: + İsim: + + + + Version: + Sürüm: + + + + Size: + Boyut: + + + + LangDialog + + + Language Settings + Dil Ayarları + + + + Select Language: + Dil Seçin: + + + + Restart Required + Yeniden Başlatma Gerekiyor + + + + Changes will take effect after restarting the application. + Değişiklikler uygulama yeniden başlatıldığında geçerli olacaktır. + + + + SettingsDialog + + + Settings + Ayarlar + + + + General + Genel + + + + Cheats + Hileler + + + + Update + Güncelleme + + + + Save + Kaydet + + + + Reset to Default + Varsayılana Sıfırla + + + + Apply Changes + Değişiklikleri Uygula + + \ No newline at end of file diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 08af9b351..977b6760c 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Mẹo / Bản vá + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Tải Mẹo / Bản vá + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * Unsupported Vulkan Version + * Phiên bản Vulkan không được hỗ trợ + + + + Download Cheats For All Installed Games + Tải xuống cheat cho tất cả các trò chơi đã cài đặt + + + + Download Patches For All Games + Tải xuống bản vá cho tất cả các trò chơi + + + + Download Complete + Tải xuống hoàn tất + + + + You have downloaded cheats for all the games you have installed. + Bạn đã tải xuống cheat cho tất cả các trò chơi mà bạn đã cài đặt. + + + + Patches Downloaded Successfully! + Bản vá đã tải xuống thành công! + + + + All Patches available for all games have been downloaded. + Tất cả các bản vá có sẵn cho tất cả các trò chơi đã được tải xuống. + + + + Games: + Trò chơi: + + + + PKG File (*.PKG) + Tệp PKG (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + Tệp ELF (*.bin *.elf *.oelf) + + + + Game Boot + Khởi động trò chơi + + + + Only one file can be selected! + Chỉ có thể chọn một tệp duy nhất! + + + + PKG Extraction + Giải nén PKG + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + Đã phát hiện bản vá!\nPhiên bản PKG và trò chơi khớp!: %1\nBạn có muốn + + + + to overwrite? + ghi đè không? + + + + Patch detected!\nPKG Version %1 is older + Đã phát hiện bản vá!\nPhiên bản PKG %1 cũ hơn + + + + than installed version!: %2\nWould you like + so với phiên bản đã cài đặt!: %2\nBạn có muốn + + + + to overwrite? + ghi đè không? + + + + Patch detected!\nGame is installed: %1\nWould you like + Đã phát hiện bản vá!\nTrò chơi đã được cài đặt: %1\nBạn có muốn + + + + to install Patch: %2? + cài đặt bản vá: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + Trò chơi đã được cài đặt\n%1\nBạn có muốn ghi đè không? + + + + PKG is a patch, please install the game first! + PKG là bản vá, vui lòng cài đặt trò chơi trước! + + + + PKG ERROR + LOI PKG + + + + Extracting PKG %1/%2 + Đang giải nén PKG %1/%2 + + + + Extraction Finished + Giải nén hoàn tất + + + + Game successfully installed at %1 + Trò chơi đã được cài đặt thành công tại %1 + + + + File doesn't appear to be a valid PKG file + Tệp không có vẻ là tệp PKG hợp lệ + + + + CheatsPatches + + + Cheats / Patches + Cheat / Bản vá + + + + defaultTextEdit_MSG + Cheats/Patches là các tính năng thử nghiệm.\nHãy sử dụng cẩn thận.\n\nTải xuống các cheat riêng lẻ bằng cách chọn kho lưu trữ và nhấp vào nút tải xuống.\nTại tab Patches, bạn có thể tải xuống tất cả các patch cùng một lúc, chọn cái nào bạn muốn sử dụng và lưu lựa chọn của mình.\n\nVì chúng tôi không phát triển Cheats/Patches,\nxin vui lòng báo cáo các vấn đề cho tác giả cheat.\n\nBạn đã tạo ra một cheat mới? Truy cập:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Không có hình ảnh + + + + Serial: + Số seri: + + + + Version: + Phiên bản: + + + + Size: + Kích thước: + + + + Select Cheat File: + Chọn tệp Cheat: + + + + Repository: + Kho lưu trữ: + + + + Download Cheats + Tải xuống Cheat + + + + Delete File + Xóa tệp + + + + No files selected. + Không có tệp nào được chọn. + + + + You can delete the cheats you don't want after downloading them. + Bạn có thể xóa các cheat không muốn sau khi tải xuống. + + + + Do you want to delete the selected file?\n%1 + Bạn có muốn xóa tệp đã chọn?\n%1 + + + + Select Patch File: + Chọn tệp Bản vá: + + + + Download Patches + Tải xuống Bản vá + + + + Save + Lưu + + + + Cheats + Cheat + + + + Patches + Bản vá + + + + Error + Lỗi + + + + No patch selected. + Không có bản vá nào được chọn. + + + + Unable to open files.json for reading. + Không thể mở files.json để đọc. + + + + No patch file found for the current serial. + Không tìm thấy tệp bản vá cho số seri hiện tại. + + + + Unable to open the file for reading. + Không thể mở tệp để đọc. + + + + Unable to open the file for writing. + Không thể mở tệp để ghi. + + + + Failed to parse XML: + Không thể phân tích XML: + + + + Success + Thành công + + + + Options saved successfully. + Các tùy chọn đã được lưu thành công. + + + + Invalid Source + Nguồn không hợp lệ + + + + The selected source is invalid. + Nguồn đã chọn không hợp lệ. + + + + File Exists + Tệp đã tồn tại + + + + File already exists. Do you want to replace it? + Tệp đã tồn tại. Bạn có muốn thay thế nó không? + + + + Failed to save file: + Không thể lưu tệp: + + + + Failed to download file: + Không thể tải xuống tệp: + + + + Cheats Not Found + Không tìm thấy Cheat + + + + CheatsNotFound_MSG + Không tìm thấy Cheat cho trò chơi này trong phiên bản kho lưu trữ đã chọn,hãy thử kho lưu trữ khác hoặc phiên bản khác của trò chơi. + + + + Cheats Downloaded Successfully + Cheat đã tải xuống thành công + + + + CheatsDownloadedSuccessfully_MSG + Bạn đã tải xuống các cheat thành công. Cho phiên bản trò chơi này từ kho lưu trữ đã chọn. Bạn có thể thử tải xuống từ kho lưu trữ khác, nếu có, bạn cũng có thể sử dụng bằng cách chọn tệp từ danh sách. + + + + Failed to save: + Không thể lưu: + + + + Failed to download: + Không thể tải xuống: + + + + Download Complete + Tải xuống hoàn tất + + + + DownloadComplete_MSG + Bản vá đã tải xuống thành công! Tất cả các bản vá có sẵn cho tất cả các trò chơi đã được tải xuống, không cần tải xuống riêng lẻ cho mỗi trò chơi như trong Cheat. + + + + Failed to parse JSON data from HTML. + Không thể phân tích dữ liệu JSON từ HTML. + + + + Failed to retrieve HTML page. + Không thể lấy trang HTML. + + + + Failed to open file: + Không thể mở tệp: + + + + XML ERROR: + LỖI XML: + + + + Failed to open files.json for writing + Không thể mở files.json để ghi + + + + Author: + Tác giả: + + + + Directory does not exist: + Thư mục không tồn tại: + + + + Failed to open files.json for reading. + Không thể mở files.json để đọc. + + + + Name: + Tên: + + \ No newline at end of file diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 6f6392237..d5ace320d 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Zuòbì / Bǔdīng + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Xiàzài Zuòbì / Bǔdīng + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * Unsupported Vulkan Version + * 不支持的 Vulkan 版本 + + + + Download Cheats For All Installed Games + 下载所有已安装游戏的作弊码 + + + + Download Patches For All Games + 下载所有游戏的补丁 + + + + Download Complete + 下载完成 + + + + You have downloaded cheats for all the games you have installed. + 您已下载了所有已安装游戏的作弊码。 + + + + Patches Downloaded Successfully! + 补丁下载成功! + + + + All Patches available for all games have been downloaded. + 所有游戏的所有补丁都已下载。 + + + + Games: + 游戏: + + + + PKG File (*.PKG) + PKG 文件 (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF 文件 (*.bin *.elf *.oelf) + + + + Game Boot + 游戏启动 + + + + Only one file can be selected! + 只能选择一个文件! + + + + PKG Extraction + PKG 解压 + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + 检测到补丁!\nPKG 和游戏版本匹配:%1\n您想要 + + + + to overwrite? + 覆盖吗? + + + + Patch detected!\nPKG Version %1 is older + 检测到补丁!\nPKG 版本 %1 较旧 + + + + than installed version!: %2\nWould you like + 与已安装版本相比:%2\n您想要 + + + + to overwrite? + 覆盖吗? + + + + Patch detected!\nGame is installed: %1\nWould you like + 检测到补丁!\n游戏已安装:%1\n您想要 + + + + to install Patch: %2? + 安装补丁:%2? + + + + Game already installed\n%1\nWould you like to overwrite? + 游戏已安装\n%1\n您想要覆盖吗? + + + + PKG is a patch, please install the game first! + PKG 是一个补丁,请先安装游戏! + + + + PKG ERROR + PKG 错误 + + + + Extracting PKG %1/%2 + 正在解压 PKG %1/%2 + + + + Extraction Finished + 解压完成 + + + + Game successfully installed at %1 + 游戏成功安装在 %1 + + + + File doesn't appear to be a valid PKG file + 文件似乎不是有效的 PKG 文件 + + + + CheatsPatches + + + Cheats / Patches + 作弊码 / 补丁 + + + + defaultTextEdit_MSG + 作弊/补丁是实验性的。\n请小心使用。\n\n通过选择存储库并点击下载按钮,单独下载作弊程序。\n在“补丁”选项卡中,您可以一次性下载所有补丁,选择要使用的补丁并保存选择。\n\n由于我们不开发作弊程序/补丁,\n请将问题报告给作弊程序的作者。\n\n创建了新的作弊程序?访问:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + 没有可用的图像 + + + + Serial: + 序列号: + + + + Version: + 版本: + + + + Size: + 大小: + + + + Select Cheat File: + 选择作弊码文件: + + + + Repository: + 存储库: + + + + Download Cheats + 下载作弊码 + + + + Delete File + 删除文件 + + + + No files selected. + 没有选择文件。 + + + + You can delete the cheats you don't want after downloading them. + 您可以在下载后删除不想要的作弊码。 + + + + Do you want to delete the selected file?\n%1 + 您要删除选中的文件吗?\n%1 + + + + Select Patch File: + 选择补丁文件: + + + + Download Patches + 下载补丁 + + + + Save + 保存 + + + + Cheats + 作弊码 + + + + Patches + 补丁 + + + + Error + 错误 + + + + No patch selected. + 没有选择补丁。 + + + + Unable to open files.json for reading. + 无法打开 files.json 进行读取。 + + + + No patch file found for the current serial. + 未找到当前序列号的补丁文件。 + + + + Unable to open the file for reading. + 无法打开文件进行读取。 + + + + Unable to open the file for writing. + 无法打开文件进行写入。 + + + + Failed to parse XML: + 解析 XML 失败: + + + + Success + 成功 + + + + Options saved successfully. + 选项已成功保存。 + + + + Invalid Source + 无效的来源 + + + + The selected source is invalid. + 选择的来源无效。 + + + + File Exists + 文件已存在 + + + + File already exists. Do you want to replace it? + 文件已存在。您要替换它吗? + + + + Failed to save file: + 保存文件失败: + + + + Failed to download file: + 下载文件失败: + + + + Cheats Not Found + 未找到作弊码 + + + + CheatsNotFound_MSG + 在所选存储库的版本中找不到该游戏的作弊码,请尝试其他存储库或游戏版本。 + + + + Cheats Downloaded Successfully + 作弊码下载成功 + + + + CheatsDownloadedSuccessfully_MSG + 您已成功下载了该游戏版本的作弊码 从所选存储库中。如果有,您还可以尝试从其他存储库下载,或通过从列表中选择文件来使用它们。 + + + + Failed to save: + 保存失败: + + + + Failed to download: + 下载失败: + + + + Download Complete + 下载完成 + + + + DownloadComplete_MSG + 补丁下载成功!所有可用的补丁已下载完成,无需像作弊码那样单独下载每个游戏的补丁。 + + + + Failed to parse JSON data from HTML. + 无法解析 HTML 中的 JSON 数据。 + + + + Failed to retrieve HTML page. + 无法获取 HTML 页面。 + + + + Failed to open file: + 无法打开文件: + + + + XML ERROR: + XML 错误: + + + + Failed to open files.json for writing + 无法打开 files.json 进行写入 + + + + Author: + 作者: + + + + Directory does not exist: + 目录不存在: + + + + Failed to open files.json for reading. + 无法打开 files.json 进行读取。 + + + + Name: + 名称: + + \ No newline at end of file diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 1ddeaa43f..4a9da9f37 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -81,67 +81,72 @@ GuiContextMenus - + Create Shortcut Create Shortcut - + Open Game Folder Open Game Folder - + + Cheats / Patches + Zuòbì / Xiūbǔ chéngshì + + + SFO Viewer SFO Viewer - + Trophy Viewer Trophy Viewer - + Copy info Copy info - + Copy Name Copy Name - + Copy Serial Copy Serial - + Copy All Copy All - + Shortcut creation Shortcut creation - + Shortcut created successfully!\n %1 Shortcut created successfully!\n %1 - + Error Error - + Error creating shortcut!\n %1 Error creating shortcut!\n %1 - + Install PKG Install PKG @@ -248,6 +253,11 @@ Game Install Directory Game Install Directory + + + Download Cheats/Patches + Xiàzài Zuòbì / Xiūbǔ chéngshì + Dump Game List @@ -488,4 +498,395 @@ Enable RenderDoc Debugging + + MainWindow + + + * Unsupported Vulkan Version + * 不支援的 Vulkan 版本 + + + + Download Cheats For All Installed Games + 下載所有已安裝遊戲的作弊碼 + + + + Download Patches For All Games + 下載所有遊戲的修補檔 + + + + Download Complete + 下載完成 + + + + You have downloaded cheats for all the games you have installed. + 您已經下載了所有已安裝遊戲的作弊碼。 + + + + Patches Downloaded Successfully! + 修補檔下載成功! + + + + All Patches available for all games have been downloaded. + 所有遊戲的修補檔已經下載完成。 + + + + Games: + 遊戲: + + + + PKG File (*.PKG) + PKG 檔案 (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF 檔案 (*.bin *.elf *.oelf) + + + + Game Boot + 遊戲啟動 + + + + Only one file can be selected! + 只能選擇一個檔案! + + + + PKG Extraction + PKG 解壓縮 + + + + Patch detected!\nPKG and Game versions match!: %1\nWould you like + 偵測到修補檔!\nPKG 和遊戲版本匹配!: %1\n您是否希望 + + + + to overwrite? + 覆蓋嗎? + + + + Patch detected!\nPKG Version %1 is older + 偵測到修補檔!\nPKG 版本 %1 較舊 + + + + than installed version!: %2\nWould you like + 比安裝的版本舊!: %2\n您是否希望 + + + + to overwrite? + 覆蓋嗎? + + + + Patch detected!\nGame is installed: %1\nWould you like + 偵測到修補檔!\n遊戲已安裝: %1\n您是否希望 + + + + to install Patch: %2? + 安裝修補檔: %2? + + + + Game already installed\n%1\nWould you like to overwrite? + 遊戲已經安裝\n%1\n您是否希望覆蓋? + + + + PKG is a patch, please install the game first! + PKG 是修補檔,請先安裝遊戲! + + + + PKG ERROR + PKG 錯誤 + + + + Extracting PKG %1/%2 + 正在解壓縮 PKG %1/%2 + + + + Extraction Finished + 解壓縮完成 + + + + Game successfully installed at %1 + 遊戲成功安裝於 %1 + + + + File doesn't appear to be a valid PKG file + 檔案似乎不是有效的 PKG 檔案 + + + + CheatsPatches + + + Cheats / Patches + 作弊碼 / 修補檔 + + + + defaultTextEdit_MSG + 作弊/補丁為實驗性功能。\n請小心使用。\n\n透過選擇儲存庫並點擊下載按鈕來單獨下載作弊程式。\n在“補丁”標籤頁中,您可以一次下載所有補丁,選擇要使用的補丁並保存您的選擇。\n\n由於我們不開發作弊/補丁,\n請將問題報告給作弊程式的作者。\n\n創建了新的作弊程式?請訪問:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + 沒有可用的圖片 + + + + Serial: + 序號: + + + + Version: + 版本: + + + + Size: + 大小: + + + + Select Cheat File: + 選擇作弊檔案: + + + + Repository: + 儲存庫: + + + + Download Cheats + 下載作弊碼 + + + + Delete File + 刪除檔案 + + + + No files selected. + 沒有選擇檔案。 + + + + You can delete the cheats you don't want after downloading them. + 您可以在下載後刪除不需要的作弊碼。 + + + + Do you want to delete the selected file?\n%1 + 您是否要刪除選定的檔案?\n%1 + + + + Select Patch File: + 選擇修補檔案: + + + + Download Patches + 下載修補檔 + + + + Save + 儲存 + + + + Cheats + 作弊碼 + + + + Patches + 修補檔 + + + + Error + 錯誤 + + + + No patch selected. + 未選擇修補檔。 + + + + Unable to open files.json for reading. + 無法打開 files.json 進行讀取。 + + + + No patch file found for the current serial. + 找不到當前序號的修補檔。 + + + + Unable to open the file for reading. + 無法打開檔案進行讀取。 + + + + Unable to open the file for writing. + 無法打開檔案進行寫入。 + + + + Failed to parse XML: + 解析 XML 失敗: + + + + Success + 成功 + + + + Options saved successfully. + 選項已成功儲存。 + + + + Invalid Source + 無效的來源 + + + + The selected source is invalid. + 選擇的來源無效。 + + + + File Exists + 檔案已存在 + + + + File already exists. Do you want to replace it? + 檔案已存在。您是否希望替換它? + + + + Failed to save file: + 無法儲存檔案: + + + + Failed to download file: + 無法下載檔案: + + + + Cheats Not Found + 未找到作弊碼 + + + + CheatsNotFound_MSG + 在此版本的儲存庫中未找到該遊戲的作弊碼,請嘗試另一個儲存庫或不同版本的遊戲。 + + + + Cheats Downloaded Successfully + 作弊碼下載成功 + + + + CheatsDownloadedSuccessfully_MSG + 您已成功下載該遊戲版本的作弊碼 從選定的儲存庫中。 您可以嘗試從其他儲存庫下載,如果可用,您也可以選擇從列表中選擇檔案來使用它。 + + + + Failed to save: + 儲存失敗: + + + + Failed to download: + 下載失敗: + + + + Download Complete + 下載完成 + + + + DownloadComplete_MSG + 修補檔下載成功!所有遊戲的修補檔已下載完成,無需像作弊碼那樣為每個遊戲單獨下載。 + + + + Failed to parse JSON data from HTML. + 無法從 HTML 解析 JSON 數據。 + + + + Failed to retrieve HTML page. + 無法檢索 HTML 頁面。 + + + + Failed to open file: + 無法打開檔案: + + + + XML ERROR: + XML 錯誤: + + + + Failed to open files.json for writing + 無法打開 files.json 進行寫入 + + + + Author: + 作者: + + + + Directory does not exist: + 目錄不存在: + + + + Failed to open files.json for reading. + 無法打開 files.json 進行讀取。 + + + + Name: + 名稱: + + \ No newline at end of file From e1382b43c89ac33febd2cd9629ecf24cc8826546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:02:36 +0200 Subject: [PATCH 097/147] Update French translation (#641) --- src/qt_gui/translations/fr.ts | 60 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 56d316092..371da9616 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -93,7 +93,7 @@ Cheats / Patches - Trucs / Patchs + Cheats/Patchs @@ -108,7 +108,7 @@ Copy info - Copier les informations + Copier infos @@ -133,7 +133,7 @@ Shortcut created successfully!\n %1 - Raccourci créé avec succès!\n %1 + Raccourci créé avec succès !\n %1 @@ -143,7 +143,7 @@ Error creating shortcut!\n %1 - Erreur lors de la création du raccourci!\n %1 + Erreur lors de la création du raccourci !\n %1 @@ -256,7 +256,7 @@ Download Cheats/Patches - Télécharger Trucs / Patchs + Télécharger Cheats/Patchs @@ -485,12 +485,12 @@ Enable Vulkan Validation Layers - Couche de validation Vulkan + Activer la couche de validation Vulkan Enable Vulkan Synchronization Validation - Synchroniser la validation Vulkan + Activer la synchronisation de la validation Vulkan @@ -503,17 +503,17 @@ * Unsupported Vulkan Version - * Version Vulkan non prise en charge + * Version de Vulkan non prise en charge Download Cheats For All Installed Games - Télécharger les cheats pour tous les jeux installés + Télécharger les Cheats pour tous les jeux installés Download Patches For All Games - Télécharger les patches pour tous les jeux + Télécharger les patchs pour tous les jeux @@ -523,17 +523,17 @@ You have downloaded cheats for all the games you have installed. - Vous avez téléchargé des cheats pour tous les jeux que vous avez installés. + Vous avez téléchargé des Cheats pour tous les jeux installés. Patches Downloaded Successfully! - Patches téléchargés avec succès ! + Patchs téléchargés avec succès ! All Patches available for all games have been downloaded. - Tous les patches disponibles pour tous les jeux ont été téléchargés. + Tous les patchs disponibles pour les jeux ont été téléchargés. @@ -543,7 +543,7 @@ PKG File (*.PKG) - Fichier PKG (*.PKG) + Fichiers PKG (*.PKG) @@ -553,7 +553,7 @@ Game Boot - Boot du jeu + Démarrer un jeu @@ -563,12 +563,12 @@ PKG Extraction - Extraction PKG + Extraction du PKG Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch détecté !\nLes versions PKG et Jeu correspondent : %1\nSouhaitez-vous + Patch détecté !\nLa version du PKG et du jeu correspondent : %1\nSouhaitez-vous @@ -608,12 +608,12 @@ PKG is a patch, please install the game first! - PKG est un patch, veuillez d'abord installer le jeu ! + Le PKG est un patch, veuillez d'abord installer le jeu ! PKG ERROR - ERREUR PKG + Erreur PKG @@ -633,7 +633,7 @@ File doesn't appear to be a valid PKG file - Le fichier ne semble pas être un fichier PKG valide + Le fichier ne semble pas être un PKG valide @@ -641,12 +641,12 @@ Cheats / Patches - Cheats / Patches + Cheats/Patches defaultTextEdit_MSG - Les cheats/patches sont expérimentaux.\nUtilisez-les avec précaution.\n\nTéléchargez les cheats individuellement en sélectionnant le dépôt et en cliquant sur le bouton de téléchargement.\nDans l'onglet Patches, vous pouvez télécharger tous les patches en une seule fois, choisir lesquels vous souhaitez utiliser et enregistrer votre sélection.\n\nComme nous ne développons pas les Cheats/Patches,\nmerci de signaler les problèmes à l'auteur du cheat.\n\nVous avez créé un nouveau cheat ? Visitez :\nhttps://github.com/shadps4-emu/ps4_cheats + Les Cheats/Patchs sont expérimentaux.\nUtilisez-les avec précaution.\n\nTéléchargez les Cheats individuellement en sélectionnant le dépôt et en cliquant sur le bouton de téléchargement.\nDans l'onglet Patchs, vous pouvez télécharger tous les patchs en une seule fois, choisir lesquels vous souhaitez utiliser et enregistrer votre sélection.\n\nComme nous ne développons pas les Cheats/Patches,\nmerci de signaler les problèmes à l'auteur du Cheat.\n\nVous avez créé un nouveau cheat ? Visitez :\nhttps://github.com/shadps4-emu/ps4_cheats @@ -671,7 +671,7 @@ Select Cheat File: - Sélectionner le fichier de cheat : + Sélectionner le fichier de Cheat : @@ -681,7 +681,7 @@ Download Cheats - Télécharger les cheats + Télécharger les Cheats @@ -696,7 +696,7 @@ You can delete the cheats you don't want after downloading them. - Vous pouvez supprimer les cheats que vous ne souhaitez pas après les avoir téléchargés. + Vous pouvez supprimer les Cheats que vous ne souhaitez pas après les avoir téléchargés. @@ -711,7 +711,7 @@ Download Patches - Télécharger les patches + Télécharger les patchs @@ -811,7 +811,7 @@ CheatsNotFound_MSG - Aucun cheat trouvé pour ce jeu dans cette version du dépôt sélectionné,essayez un autre dépôt ou une version différente du jeu. + Aucun Cheat trouvé pour ce jeu dans cette version du dépôt sélectionné, essayez un autre dépôt ou une version différente du jeu. @@ -841,7 +841,7 @@ DownloadComplete_MSG - Patchs téléchargés avec succès ! Tous les patches disponibles pour tous les jeux ont été téléchargés, il n'est pas nécessaire de les télécharger individuellement pour chaque jeu comme c'est le cas pour les cheats. + Patchs téléchargés avec succès ! Tous les patches disponibles pour tous les jeux ont été téléchargés, il n'est pas nécessaire de les télécharger individuellement pour chaque jeu comme c'est le cas pour les Cheats. @@ -861,7 +861,7 @@ XML ERROR: - ERREUR XML : + Erreur XML : @@ -889,4 +889,4 @@ Nom : - \ No newline at end of file + From 8827c72a1c7703e73ffb6e0d35726461fcc8bffd Mon Sep 17 00:00:00 2001 From: Dzmitry Dubrova Date: Thu, 29 Aug 2024 12:55:40 +0300 Subject: [PATCH 098/147] Add DLC support (#596) * fs/core: Add DLC support * fs/core: Fix extraction paths * Fix DLC mounting * gui: Add translations --- src/common/path_util.cpp | 1 + src/common/path_util.h | 2 + src/core/file_format/pkg.cpp | 107 +++++++++---- src/core/file_format/pkg.h | 1 - .../libraries/app_content/app_content.cpp | 143 ++++++++++++++++-- src/core/libraries/app_content/app_content.h | 26 +++- src/core/libraries/error_codes.h | 4 +- src/qt_gui/main_window.cpp | 122 ++++++++++----- src/qt_gui/translations/da_DK.ts | 10 ++ src/qt_gui/translations/de.ts | 10 ++ src/qt_gui/translations/el.ts | 10 ++ src/qt_gui/translations/en.ts | 10 ++ src/qt_gui/translations/es_ES.ts | 10 ++ src/qt_gui/translations/fi.ts | 10 ++ src/qt_gui/translations/fr.ts | 10 ++ src/qt_gui/translations/hu_HU.ts | 10 ++ src/qt_gui/translations/id.ts | 10 ++ src/qt_gui/translations/it.ts | 10 ++ src/qt_gui/translations/ja_JP.ts | 10 ++ src/qt_gui/translations/ko_KR.ts | 10 ++ src/qt_gui/translations/lt_LT.ts | 10 ++ src/qt_gui/translations/nb.ts | 10 ++ src/qt_gui/translations/nl.ts | 10 ++ src/qt_gui/translations/pl_PL.ts | 10 ++ src/qt_gui/translations/pt_BR.ts | 10 ++ src/qt_gui/translations/ro_RO.ts | 10 ++ src/qt_gui/translations/ru_RU.ts | 10 ++ src/qt_gui/translations/tr_TR.ts | 10 ++ src/qt_gui/translations/vi_VN.ts | 10 ++ src/qt_gui/translations/zh_CN.ts | 10 ++ src/qt_gui/translations/zh_TW.ts | 10 ++ 31 files changed, 544 insertions(+), 92 deletions(-) diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 5d5c9ebad..8d369fc7b 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -106,6 +106,7 @@ static auto UserPaths = [] { create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR); create_path(PathType::CheatsDir, user_dir / CHEATS_DIR); create_path(PathType::PatchesDir, user_dir / PATCHES_DIR); + create_path(PathType::AddonsDir, user_dir / ADDONS_DIR); return paths; }(); diff --git a/src/common/path_util.h b/src/common/path_util.h index 8922de9f1..bee93c1b9 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -22,6 +22,7 @@ enum class PathType { CapturesDir, // Where rdoc captures are stored. CheatsDir, // Where cheats are stored. PatchesDir, // Where patches are stored. + AddonsDir, // Where additional content is stored. }; constexpr auto PORTABLE_DIR = "user"; @@ -39,6 +40,7 @@ constexpr auto DOWNLOAD_DIR = "download"; constexpr auto CAPTURES_DIR = "captures"; constexpr auto CHEATS_DIR = "cheats"; constexpr auto PATCHES_DIR = "patches"; +constexpr auto ADDONS_DIR = "addcont"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp index fe3c34547..d86f3b28d 100644 --- a/src/core/file_format/pkg.cpp +++ b/src/core/file_format/pkg.cpp @@ -67,15 +67,19 @@ bool PKG::Open(const std::filesystem::path& filepath) { file.Seek(0x47); // skip first 7 characters of content_id file.Read(pkgTitleID); - file.Seek(0); - pkg.resize(pkgheader.pkg_promote_size); - file.Read(pkg); - u32 offset = pkgheader.pkg_table_entry_offset; u32 n_files = pkgheader.pkg_table_entry_count; + + file.Seek(offset); for (int i = 0; i < n_files; i++) { - PKGEntry entry; - std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry)); + PKGEntry entry{}; + file.Read(entry.id); + file.Read(entry.filename_offset); + file.Read(entry.flags1); + file.Read(entry.flags2); + file.Read(entry.offset); + file.Read(entry.size); + file.Seek(8, Common::FS::SeekOrigin::CurrentPosition); // Try to figure out the name const auto name = GetEntryNameByType(entry.id); @@ -113,9 +117,6 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: failreason = "Content size is bigger than pkg size"; return false; } - file.Seek(0); - pkg.resize(pkgheader.pkg_promote_size); - file.Read(pkg); u32 offset = pkgheader.pkg_table_entry_offset; u32 n_files = pkgheader.pkg_table_entry_count; @@ -126,9 +127,18 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: std::array, 7> key1; std::array imgkeydata; + file.Seek(offset); for (int i = 0; i < n_files; i++) { - PKGEntry entry; - std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry)); + PKGEntry entry{}; + file.Read(entry.id); + file.Read(entry.filename_offset); + file.Read(entry.flags1); + file.Read(entry.flags2); + file.Read(entry.offset); + file.Read(entry.size); + file.Seek(8, Common::FS::SeekOrigin::CurrentPosition); + + auto currentPos = file.Tell(); // Try to figure out the name const auto name = GetEntryNameByType(entry.id); @@ -139,8 +149,15 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: // Just print with id Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id), Common::FS::FileAccessMode::Write); - out.WriteRaw(pkg.data() + entry.offset, entry.size); + file.Seek(entry.offset); + + std::vector data; + data.resize(entry.size); + file.ReadRaw(data.data(), entry.size); + out.WriteRaw(data.data(), entry.size); out.Close(); + + file.Seek(currentPos); continue; } @@ -178,14 +195,25 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: } Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write); - out.WriteRaw(pkg.data() + entry.offset, entry.size); + file.Seek(entry.offset); + + std::vector data; + data.resize(entry.size); + file.ReadRaw(data.data(), entry.size); + out.WriteRaw(data.data(), entry.size); out.Close(); // Decrypt Np stuff and overwrite. if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 || entry.id == 0x403) { // somehow 0x401 is not decrypting decNp.resize(entry.size); - std::span cipherNp(pkg.data() + entry.offset, entry.size); + file.Seek(entry.offset); + + std::vector data; + data.resize(entry.size); + file.ReadRaw(data.data(), entry.size); + + std::span cipherNp(data.data(), entry.size); std::array concatenated_ivkey_dk3_; std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry)); std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_)); @@ -197,6 +225,8 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: out.Write(decNp); out.Close(); } + + file.Seek(currentPos); } // Extract trophy files @@ -214,28 +244,31 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey); const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok. - // Read encrypted pfs_image - std::vector pfs_encrypted(length); - file.Seek(pkgheader.pfs_image_offset); - file.Read(pfs_encrypted); - file.Close(); - // Decrypt the pfs_image. - std::vector pfs_decrypted(length); - PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0); - - // Retrieve PFSC from decrypted pfs_image. - pfsc_offset = GetPFSCOffset(pfs_decrypted); + int num_blocks = 0; std::vector pfsc(length); - std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset); + if (length != 0) { + // Read encrypted pfs_image + std::vector pfs_encrypted(length); + file.Seek(pkgheader.pfs_image_offset); + file.Read(pfs_encrypted); + file.Close(); + // Decrypt the pfs_image. + std::vector pfs_decrypted(length); + PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0); - PFSCHdr pfsChdr; - std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr)); + // Retrieve PFSC from decrypted pfs_image. + pfsc_offset = GetPFSCOffset(pfs_decrypted); + std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset); - const int num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2); - sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset. + PFSCHdr pfsChdr; + std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr)); - for (int i = 0; i < num_blocks + 1; i++) { - std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8); + num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2); + sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset. + + for (int i = 0; i < num_blocks + 1; i++) { + std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8); + } } u32 ent_size = 0; @@ -296,7 +329,15 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: } else { // Set the the folder according to the current inode. // Can be 2 or more (rarely) - extractPaths[ndinode_counter] = extract_path.parent_path() / GetTitleID(); + auto parent_path = extract_path.parent_path(); + auto title_id = GetTitleID(); + + if (parent_path.filename() != title_id) { + extractPaths[ndinode_counter] = parent_path / title_id; + } else { + // DLCs path has different structure + extractPaths[ndinode_counter] = extract_path; + } uroot_reached = false; break; } diff --git a/src/core/file_format/pkg.h b/src/core/file_format/pkg.h index b6b09a191..d30d50b44 100644 --- a/src/core/file_format/pkg.h +++ b/src/core/file_format/pkg.h @@ -149,7 +149,6 @@ public: private: Crypto crypto; TRP trp; - std::vector pkg; u64 pkgSize = 0; char pkgTitleID[9]; PKGHeader pkgheader; diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index ab3c901aa..c2523124a 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -7,14 +7,33 @@ #include #include #include + #include "app_content.h" #include "common/io_file.h" #include "common/logging/log.h" +#include "common/string_util.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" namespace Libraries::AppContent { +int32_t addcont_count = 0; + +struct AddContInfo { + char entitlementLabel[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE]; + OrbisAppContentAddcontDownloadStatus status; + OrbisAppContentGetEntitlementKey key; +}; + +std::array addcont_info = {{ + {"0000000000000000", + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}}, +}}; + +std::string title_id; + int PS4_SYSV_ABI _Z5dummyv() { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); return ORBIS_OK; @@ -35,9 +54,31 @@ int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAddcontMount() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentMountPoint* mount_point) { + LOG_INFO(Lib_AppContent, "called"); + + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / title_id / + entitlement_label->data; + auto* mnt = Common::Singleton::Instance(); + + for (int i = 0; i < addcont_count; i++) { + if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) { + continue; + } + + if (addcont_info[i].status != ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED) { + return ORBIS_APP_CONTENT_ERROR_NOT_FOUND; + } + + snprintf(mount_point->data, ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE, "/addcont%d", i); + mnt->Mount(mount_dir, mount_point->data); + return ORBIS_OK; + } + + return ORBIS_APP_CONTENT_ERROR_NOT_FOUND; } int PS4_SYSV_ABI sceAppContentAddcontShrink() { @@ -124,22 +165,80 @@ int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentGetAddcontInfo() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlementLabel, + OrbisAppContentAddcontInfo* info) { + LOG_INFO(Lib_AppContent, "called"); + + if (entitlementLabel == nullptr || info == nullptr) { + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + + for (auto i = 0; i < addcont_count; i++) { + if (strncmp(entitlementLabel->data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) { + continue; + } + + LOG_INFO(Lib_AppContent, "found DLC {}", entitlementLabel->data); + + strncpy(info->entitlement_label.data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE); + info->status = addcont_info[i].status; + return ORBIS_OK; + } + + return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT; } int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, OrbisAppContentAddcontInfo* list, u32 list_num, u32* hit_num) { - *hit_num = 0; - LOG_ERROR(Lib_AppContent, "(DUMMY) called"); + LOG_INFO(Lib_AppContent, "called"); + + if (list_num == 0 || list == nullptr) { + if (hit_num == nullptr) { + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + + *hit_num = addcont_count; + return ORBIS_OK; + } + + int dlcs_to_list = addcont_count < list_num ? addcont_count : list_num; + for (int i = 0; i < dlcs_to_list; i++) { + strncpy(list[i].entitlement_label.data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE); + list[i].status = addcont_info[i].status; + } + + if (hit_num != nullptr) { + *hit_num = dlcs_to_list; + } + return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentGetEntitlementKey() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAppContentGetEntitlementKey( + u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentGetEntitlementKey* key) { + LOG_ERROR(Lib_AppContent, "called"); + + if (entitlement_label == nullptr || key == nullptr) { + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + + for (int i = 0; i < addcont_count; i++) { + if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) { + continue; + } + + memcpy(key->data, addcont_info[i].key.data, ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE); + return ORBIS_OK; + } + + return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT; } int PS4_SYSV_ABI sceAppContentGetRegion() { @@ -150,7 +249,25 @@ int PS4_SYSV_ABI sceAppContentGetRegion() { int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, OrbisAppContentBootParam* bootParam) { LOG_ERROR(Lib_AppContent, "(DUMMY) called"); - bootParam->attr = 0; // always 0 + auto* param_sfo = Common::Singleton::Instance(); + + const auto addons_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir); + title_id = param_sfo->GetString("TITLE_ID"); + auto addon_path = addons_dir / title_id; + if (std::filesystem::exists(addon_path)) { + for (const auto& entry : std::filesystem::directory_iterator(addon_path)) { + if (entry.is_directory()) { + auto entitlement_label = entry.path().filename().string(); + + AddContInfo info{}; + info.status = ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED; + strcpy(info.entitlementLabel, entitlement_label.c_str()); + + addcont_info[addcont_count++] = info; + } + } + } + return ORBIS_OK; } @@ -324,4 +441,4 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) { sceAppContentGetDownloadedStoreCountry); }; -} // namespace Libraries::AppContent \ No newline at end of file +} // namespace Libraries::AppContent diff --git a/src/core/libraries/app_content/app_content.h b/src/core/libraries/app_content/app_content.h index 3e6f9b540..a16da5b40 100644 --- a/src/core/libraries/app_content/app_content.h +++ b/src/core/libraries/app_content/app_content.h @@ -41,6 +41,16 @@ struct OrbisAppContentMountPoint { constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_NONE = 0; constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_FORMAT = (1 << 0); constexpr int ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE = 17; +constexpr int ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE = 16; +constexpr int ORBIS_APP_CONTENT_INFO_LIST_MAX_SIZE = 2500; + +enum OrbisAppContentAddcontDownloadStatus : u32 { + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_EXTRA_DATA = 0, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_IN_QUEUE = 1, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOADING = 2, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOAD_SUSPENDED = 3, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED = 4 +}; struct OrbisNpUnifiedEntitlementLabel { char data[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE]; @@ -54,11 +64,17 @@ struct OrbisAppContentAddcontInfo { u32 status; }; +struct OrbisAppContentGetEntitlementKey { + char data[ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE]; +}; + int PS4_SYSV_ABI _Z5dummyv(); int PS4_SYSV_ABI sceAppContentAddcontDelete(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownload(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp(); -int PS4_SYSV_ABI sceAppContentAddcontMount(); +int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentMountPoint* mount_point); int PS4_SYSV_ABI sceAppContentAddcontShrink(); int PS4_SYSV_ABI sceAppContentAddcontUnmount(); int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value); @@ -70,11 +86,15 @@ int PS4_SYSV_ABI sceAppContentDownload1Shrink(); int PS4_SYSV_ABI sceAppContentDownloadDataFormat(); int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(); int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress(); -int PS4_SYSV_ABI sceAppContentGetAddcontInfo(); +int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlementLabel, + OrbisAppContentAddcontInfo* info); int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, OrbisAppContentAddcontInfo* list, u32 list_num, u32* hit_num); -int PS4_SYSV_ABI sceAppContentGetEntitlementKey(); +int PS4_SYSV_ABI sceAppContentGetEntitlementKey( + u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentGetEntitlementKey* key); int PS4_SYSV_ABI sceAppContentGetRegion(); int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, OrbisAppContentBootParam* bootParam); diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index 1453b0a8f..094ea6603 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -460,4 +460,6 @@ constexpr int ORBIS_AVPLAYER_ERROR_INFO_AES_ENCRY = 0x806A00B5; constexpr int ORBIS_AVPLAYER_ERROR_INFO_OTHER_ENCRY = 0x806A00BF; // AppContent library -constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; \ No newline at end of file +constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; +constexpr int ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = 0x80D90007; +constexpr int ORBIS_APP_CONTENT_ERROR_NOT_FOUND = 0x80D90005; \ No newline at end of file diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 23668ef78..412a53c2f 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -7,6 +7,7 @@ #include "about_dialog.h" #include "cheats_patches.h" #include "common/io_file.h" +#include "common/string_util.h" #include "common/version.h" #include "core/file_format/pkg.h" #include "core/loader.h" @@ -615,15 +616,24 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int pkg = PKG(); pkg.Open(file); std::string failreason; - const auto extract_path = - std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID(); + auto extract_path = std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID(); QString pkgType = QString::fromStdString(pkg.GetPkgFlags()); QDir game_dir(QString::fromStdString(extract_path.string())); if (game_dir.exists()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("PKG Extraction")); + + psf.open("", pkg.sfo); + + std::string content_id = psf.GetString("CONTENT_ID"); + std::string entitlement_label = Common::SplitString(content_id, '-')[2]; + + auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / + pkg.GetTitleID() / entitlement_label; + QDir addon_dir(QString::fromStdString(addon_extract_path.string())); + auto category = psf.GetString("CATEGORY"); + if (pkgType.contains("PATCH")) { - psf.open("", pkg.sfo); QString pkg_app_version = QString::fromStdString(psf.GetString("APP_VER")); psf.open(extract_path.string() + "/sce_sys/param.sfo", {}); QString game_app_version = QString::fromStdString(psf.GetString("APP_VER")); @@ -657,6 +667,34 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } else { return; } + } else if (category == "ac") { + if (!addon_dir.exists()) { + QMessageBox addonMsgBox; + addonMsgBox.setWindowTitle(tr("DLC Installation")); + addonMsgBox.setText(QString(tr("Would you like to install DLC: %1?")) + .arg(QString::fromStdString(entitlement_label))); + + addonMsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + addonMsgBox.setDefaultButton(QMessageBox::No); + int result = addonMsgBox.exec(); + if (result == QMessageBox::Yes) { + extract_path = addon_extract_path; + } else { + return; + } + } else { + msgBox.setText( + QString("DLC already installed\n%1\nWould you like to overwrite?") + .arg(QString::fromStdString(addon_extract_path.string()))); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int result = msgBox.exec(); + if (result == QMessageBox::Yes) { + extract_path = addon_extract_path; + } else { + return; + } + } } else { msgBox.setText( QString(tr("Game already installed\n%1\nWould you like to overwrite?")) @@ -685,45 +723,47 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } else { int nfiles = pkg.GetNumberOfFiles(); - QVector indices; - for (int i = 0; i < nfiles; i++) { - indices.append(i); - } - - QProgressDialog dialog; - dialog.setWindowTitle(tr("PKG Extraction")); - dialog.setWindowModality(Qt::WindowModal); - QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg); - dialog.setLabelText(extractmsg); - dialog.setAutoClose(true); - dialog.setRange(0, nfiles); - - QFutureWatcher futureWatcher; - connect(&futureWatcher, &QFutureWatcher::finished, this, [=, this]() { - if (pkgNum == nPkg) { - QString path = QString::fromStdString(Config::getGameInstallDir()); - QMessageBox extractMsgBox(this); - extractMsgBox.setWindowTitle(tr("Extraction Finished")); - extractMsgBox.setText( - QString(tr("Game successfully installed at %1")).arg(path)); - extractMsgBox.addButton(QMessageBox::Ok); - extractMsgBox.setDefaultButton(QMessageBox::Ok); - connect(&extractMsgBox, &QMessageBox::buttonClicked, this, - [&](QAbstractButton* button) { - if (extractMsgBox.button(QMessageBox::Ok) == button) { - extractMsgBox.close(); - emit ExtractionFinished(); - } - }); - extractMsgBox.exec(); + if (nfiles > 0) { + QVector indices; + for (int i = 0; i < nfiles; i++) { + indices.append(i); } - }); - connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); }); - connect(&futureWatcher, &QFutureWatcher::progressValueChanged, &dialog, - &QProgressDialog::setValue); - futureWatcher.setFuture( - QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); })); - dialog.exec(); + + QProgressDialog dialog; + dialog.setWindowTitle(tr("PKG Extraction")); + dialog.setWindowModality(Qt::WindowModal); + QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg); + dialog.setLabelText(extractmsg); + dialog.setAutoClose(true); + dialog.setRange(0, nfiles); + + QFutureWatcher futureWatcher; + connect(&futureWatcher, &QFutureWatcher::finished, this, [=, this]() { + if (pkgNum == nPkg) { + QString path = QString::fromStdString(Config::getGameInstallDir()); + QMessageBox extractMsgBox(this); + extractMsgBox.setWindowTitle(tr("Extraction Finished")); + extractMsgBox.setText( + QString(tr("Game successfully installed at %1")).arg(path)); + extractMsgBox.addButton(QMessageBox::Ok); + extractMsgBox.setDefaultButton(QMessageBox::Ok); + connect(&extractMsgBox, &QMessageBox::buttonClicked, this, + [&](QAbstractButton* button) { + if (extractMsgBox.button(QMessageBox::Ok) == button) { + extractMsgBox.close(); + emit ExtractionFinished(); + } + }); + extractMsgBox.exec(); + } + }); + connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); }); + connect(&futureWatcher, &QFutureWatcher::progressValueChanged, &dialog, + &QProgressDialog::setValue); + futureWatcher.setFuture( + QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); })); + dialog.exec(); + } } } else { QMessageBox::critical(this, tr("PKG ERROR"), diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index de9097f2b..c5a65b5c4 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Spil allerede installeret\n%1\nVil du overskrive? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index 6183c812d..1819ef0cb 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Spiel bereits installiert\n%1\nMöchten Sie überschreiben? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts index 5d4a15d8a..a5b8e9ebd 100644 --- a/src/qt_gui/translations/el.ts +++ b/src/qt_gui/translations/el.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Το παιχνίδι είναι ήδη εγκατεστημένο\n%1\nΘέλετε να αντικαταστήσετε; + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts index aa8a1a5d8..97da0a786 100644 --- a/src/qt_gui/translations/en.ts +++ b/src/qt_gui/translations/en.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Game already installed\n%1\nWould you like to overwrite? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index 5b7ad4b6d..b60595a9e 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Juego ya instalado\n%1\n¿Te gustaría sobrescribirlo? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts index 70345efbe..c998d89e5 100644 --- a/src/qt_gui/translations/fi.ts +++ b/src/qt_gui/translations/fi.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Peli on jo asennettu\n%1\nHaluatko korvata sen? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 371da9616..cf64d760d 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Jeu déjà installé\n%1\nSouhaitez-vous écraser ? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index e531df45c..53c9d46e6 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? A játék már telepítve van\n%1\nSzeretnéd felülírni? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts index dde590469..9f31bd779 100644 --- a/src/qt_gui/translations/id.ts +++ b/src/qt_gui/translations/id.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Game sudah terpasang\n%1\nApakah Anda ingin menimpa? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 4cb050b70..5f194c9aa 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Game sudah terinstal\n%1\nApakah Anda ingin menimpa? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index c3eaaba19..acf0e613e 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? ゲームはすでにインストールされています\n%1\n上書きしますか? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index 579c6ca79..cb15c24b8 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Game already installed\n%1\nWould you like to overwrite? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index c94edb745..5f1276bca 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Žaidimas jau įdiegtas\n%1\nAr norėtumėte perrašyti? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts index 3c5401a2b..01dc32f1d 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Spill allerede installert\n%1\nØnsker du å overskrive? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts index 8b55b0e2a..682321b9e 100644 --- a/src/qt_gui/translations/nl.ts +++ b/src/qt_gui/translations/nl.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Spel al geïnstalleerd\n%1\nWil je het overschrijven? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index 41c06f89f..c92f49475 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Gra już zainstalowana\n%1\nCzy chcesz ją nadpisać? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index c198d1fd3..08c8fa47d 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Jogo já instalado\n%1\nGostaria de substituir? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index 3463182f5..af5c57630 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Jocul este deja instalat\n%1\nAi dori să suprascrii? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index a71533a35..538628dc2 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Игра уже установлена\n%1\nХотите перезаписать? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 514b9af7e..2393b654d 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Oyun zaten yüklü\n%1\nÜzerine yazmak ister misiniz? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 977b6760c..8e28afb64 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? Trò chơi đã được cài đặt\n%1\nBạn có muốn ghi đè không? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index d5ace320d..3e01df031 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? 游戏已安装\n%1\n您想要覆盖吗? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 4a9da9f37..1fb74c695 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -605,6 +605,16 @@ Game already installed\n%1\nWould you like to overwrite? 遊戲已經安裝\n%1\n您是否希望覆蓋? + + + DLC Installation + DLC Installation + + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + PKG is a patch, please install the game first! From 600c5079ceba65a5359596fdce58a188bfff7bdf Mon Sep 17 00:00:00 2001 From: bigol83 <38129260+bigol83@users.noreply.github.com> Date: Thu, 29 Aug 2024 12:11:17 +0200 Subject: [PATCH 099/147] Cheats/patches Italian translation (#642) * Update it.ts * Update it.ts --- src/qt_gui/translations/it.ts | 146 +++++++++++++++++----------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 5f194c9aa..560e76ce0 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -503,42 +503,42 @@ * Unsupported Vulkan Version - * Versi Vulkan Tidak Didukung + * Versione Vulkan non supportata Download Cheats For All Installed Games - Unduh Cheat Untuk Semua Game yang Terinstal + Scarica Trucchi per tutti i giochi installati Download Patches For All Games - Unduh Patch Untuk Semua Game + Scarica Patch per tutti i giochi Download Complete - Unduhan Selesai + Scaricamento completato You have downloaded cheats for all the games you have installed. - Anda telah mengunduh cheat untuk semua game yang telah Anda instal. + Hai scaricato trucchi per tutti i giochi installati. Patches Downloaded Successfully! - Patch Berhasil Diunduh! + Patch scaricate con successo! All Patches available for all games have been downloaded. - Semua patch yang tersedia untuk semua game telah diunduh. + Tutte le patch disponibili per tutti i giochi sono state scaricate. Games: - Game: + Giochi: @@ -553,57 +553,57 @@ Game Boot - Boot Game + Avvia Gioco Only one file can be selected! - Hanya satu file yang dapat dipilih! + Si può selezionare solo un file! PKG Extraction - Ekstraksi PKG + Estrazione file PKG Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch terdeteksi!\nVersi PKG dan Game cocok!: %1\nApakah Anda ingin + Patch rilevata! Il\nPKG e la versione del gioco coincidono!: %1\nVuoi to overwrite? - menimpa? + sovrascrivere? Patch detected!\nPKG Version %1 is older - Patch terdeteksi!\nVersi PKG %1 lebih lama + Patch rilevata! La \nPKG Versione %1 è più vecchia than installed version!: %2\nWould you like - daripada versi yang terinstal!: %2\nApakah Anda ingin + della versione installata!: %2\nVuoi to overwrite? - menimpa? + sovrascrivere? Patch detected!\nGame is installed: %1\nWould you like - Patch terdeteksi!\nGame terinstal: %1\nApakah Anda ingin + Patch rilevata!\nGioco installato: %1\Vuoi to install Patch: %2? - menginstal Patch: %2? + installare la Patch: %2? Game already installed\n%1\nWould you like to overwrite? - Game sudah terinstal\n%1\nApakah Anda ingin menimpa? + Gioco già installato\n%1\nVuoi sovrascrivere?? @@ -618,32 +618,32 @@ PKG is a patch, please install the game first! - PKG adalah patch, silakan instal game terlebih dahulu! + Questo file PKG contiene una patch. Per favore, installa prima il gioco! PKG ERROR - ERROR PKG + ERRORE PKG Extracting PKG %1/%2 - Estrazione PKG %1/%2 + Estrazione file PKG %1/%2 Extraction Finished - Ekstraksi Selesai + Estrazione Completata Game successfully installed at %1 - Game berhasil diinstal di %1 + Gioco installato correttamente in %1 File doesn't appear to be a valid PKG file - File tidak tampak sebagai file PKG yang valid + Il file sembra non essere un file PKG valido @@ -661,77 +661,77 @@ No Image Available - Tidak Ada Gambar + Nessuna immagine disponibile Serial: - Serial: + Seriale: Version: - Versi: + Versione: Size: - Ukuran: + Dimensione: Select Cheat File: - Pilih File Cheat: + Seleziona File Trucchi: Repository: - Repositori: + Archivio: Download Cheats - Unduh Cheat + Scarica trucchi Delete File - Hapus File + Cancella File No files selected. - Tidak ada file yang dipilih. + Nessun file selezionato. You can delete the cheats you don't want after downloading them. - Anda dapat menghapus cheat yang tidak diinginkan setelah mengunduhnya. + Puoi cancellare i trucchi che non vuoi utilizzare dopo averli scaricati. Do you want to delete the selected file?\n%1 - Apakah Anda ingin menghapus file yang dipilih?\n%1 + Vuoi cancellare il file selezionato?\n%1 Select Patch File: - Pilih File Patch: + Seleziona File Patch: Download Patches - Unduh Patch + Scarica Patch Save - Simpan + Salva Cheats - Cheat + Trucchi @@ -741,162 +741,162 @@ Error - Kesalahan + Errore No patch selected. - Tidak ada patch yang dipilih. + Nessuna patch selezionata. Unable to open files.json for reading. - Gagal membuka files.json untuk dibaca. + Impossibile aprire il file .json per la lettura. No patch file found for the current serial. - Tidak ada file patch ditemukan untuk serial saat ini. + Nessun file patch trovato per il seriale selezionato. Unable to open the file for reading. - Gagal membuka file untuk dibaca. + Impossibile aprire il file per la lettura. Unable to open the file for writing. - Gagal membuka file untuk ditulis. + Impossibile aprire il file per la scrittura. Failed to parse XML: - Gagal mengurai XML: + Analisi XML fallita: Success - Berhasil + Successo Options saved successfully. - Opsi berhasil disimpan. + Opzioni salvate con successo. Invalid Source - Sumber Tidak Valid + Fonte non valida The selected source is invalid. - Sumber yang dipilih tidak valid. + La fonte selezionata non è valida. File Exists - File Ada + Il file è presente File already exists. Do you want to replace it? - File sudah ada. Apakah Anda ingin menggantinya? + Il file è già presente. Vuoi sostituirlo? Failed to save file: - Gagal menyimpan file: + Salvataggio file fallito: Failed to download file: - Gagal mengunduh file: + Scaricamento file fallito: Cheats Not Found - Cheat Tidak Ditemukan + Trucchi non trovati CheatsNotFound_MSG - Cheat tidak ditemukan untuk game ini dalam versi repositori yang dipilih, coba repositori lain atau versi game yang berbeda. + Non sono stati trovati trucchi per questa versione del gioco nell'archivio selezionato, prova un altro archivio o una versione diversa del gioco. Cheats Downloaded Successfully - Cheat Berhasil Diunduh + Trucchi scaricati con successo! CheatsDownloadedSuccessfully_MSG - Anda telah berhasil mengunduh cheat untuk versi game ini dari repositori yang dipilih. Anda dapat mencoba mengunduh dari repositori lain, jika tersedia, Anda juga dapat menggunakannya dengan memilih file dari daftar. + Hai scaricato con successo i trucchi per questa versione del gioco dall'archivio selezionato. Puoi provare a scaricare da un altro archivio, se disponibile, puoi anche utilizzarlo selezionando il file dall'elenco. Failed to save: - Gagal menyimpan: + Salvataggio fallito: Failed to download: - Gagal mengunduh: + Impossibile scaricare: Download Complete - Unduhan Selesai + Scaricamento completo DownloadComplete_MSG - Patch Berhasil Diunduh! Semua patch yang tersedia untuk semua game telah diunduh, tidak perlu mengunduhnya secara individu untuk setiap game seperti yang terjadi pada Cheat. + Patch scaricata con successo! Vengono scaricate tutte le patch disponibili per tutti i giochi, non è necessario scaricarle singolarmente per ogni gioco come nel caso dei trucchi. Failed to parse JSON data from HTML. - Gagal mengurai data JSON dari HTML. + Impossibile analizzare i dati JSON dall'HTML. Failed to retrieve HTML page. - Gagal mengambil halaman HTML. + Impossibile recuperare la pagina HTML. Failed to open file: - Gagal membuka file: + Impossibile aprire file: XML ERROR: - KESALAHAN XML: + ERRORE XML: Failed to open files.json for writing - Gagal membuka files.json untuk menulis + Impossibile aprire i file .json per la scrittura Author: - Penulis: + Autore: Directory does not exist: - Direktori tidak ada: + La cartella non esiste: Failed to open files.json for reading. - Gagal membuka files.json untuk dibaca. + Impossibile aprire i file .json per la lettura. Name: - Nama: + Nome: - \ No newline at end of file + From c997490645c18f6ad1a244072b73f6a6ec7cba52 Mon Sep 17 00:00:00 2001 From: bigol83 <38129260+bigol83@users.noreply.github.com> Date: Thu, 29 Aug 2024 12:31:48 +0200 Subject: [PATCH 100/147] DLC Italian translation (#644) --- src/qt_gui/translations/it.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 560e76ce0..846d27d14 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -356,8 +356,8 @@ TrophyViewer - Visualizzatore Trofei - Trophy Viewer + Trophy Viewer + Visualizzatore Trofei @@ -608,12 +608,12 @@ DLC Installation - DLC Installation + Installazione DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Vuoi installare il DLC: %1? From 9d349a1308bcabeb62572acb31992a48373354ad Mon Sep 17 00:00:00 2001 From: psucien Date: Wed, 28 Aug 2024 23:25:58 +0200 Subject: [PATCH 101/147] video_core: added support for indirect dispatches (gfx only) --- src/video_core/amdgpu/liverpool.cpp | 22 +++++++++++ src/video_core/amdgpu/liverpool.h | 1 + src/video_core/amdgpu/pm4_cmds.h | 36 +++++++++++++++++ src/video_core/buffer_cache/buffer.cpp | 3 +- .../renderer_vulkan/vk_rasterizer.cpp | 39 +++++++++++++++++++ .../renderer_vulkan/vk_rasterizer.h | 1 + 6 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 8570a2908..e61f8cec0 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -383,6 +383,22 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); + const auto offset = dispatch_indirect->data_offset; + const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; + const auto size = sizeof(PM4CmdDispatchIndirect::GroupDimensions); + if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin( + fmt::format("dcb:{}:DispatchIndirect", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->DispatchIndirect(ib_address, offset, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } case PM4ItOpcode::NumInstances: { const auto* num_instances = reinterpret_cast(header); regs.num_instances.num_instances = num_instances->num_instances; @@ -399,6 +415,12 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::spannum_indices; break; } + case PM4ItOpcode::SetBase: { + const auto* set_base = reinterpret_cast(header); + ASSERT(set_base->base_index == PM4CmdSetBase::BaseIndex::DrawIndexIndirPatchTable); + mapped_queues[GfxQueueId].indirect_args_addr = set_base->Address(); + break; + } case PM4ItOpcode::EventWrite: { // const auto* event = reinterpret_cast(header); break; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 14284bbc6..7b38ca79f 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -1127,6 +1127,7 @@ private: std::vector ccb_buffer; std::queue submits{}; ComputeProgram cs_state{}; + VAddr indirect_args_addr{}; }; std::array mapped_queues{}; diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 5ab233fdc..50e4c93a1 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -704,4 +704,40 @@ struct PM4CmdReleaseMem { } }; +struct PM4CmdSetBase { + enum class BaseIndex : u32 { + DisplayListPatchTable = 0b0000, + DrawIndexIndirPatchTable = 0b0001, + GdsPartition = 0b0010, + CePartition = 0b0011, + }; + + PM4Type3Header header; + union { + BitField<0, 4, BaseIndex> base_index; + u32 dw1; + }; + u32 address0; + u32 address1; + + template + T Address() const { + ASSERT(base_index == BaseIndex::DisplayListPatchTable || + base_index == BaseIndex::DrawIndexIndirPatchTable); + return reinterpret_cast(address0 | (u64(address1 & 0xffff) << 32u)); + } +}; + +struct PM4CmdDispatchIndirect { + struct GroupDimensions { + u32 dim_x; + u32 dim_y; + u32 dim_z; + }; + + PM4Type3Header header; + u32 data_offset; ///< Byte aligned offset where the required data structure starts + u32 dispatch_initiator; ///< Dispatch Initiator Register +}; + } // namespace AmdGpu diff --git a/src/video_core/buffer_cache/buffer.cpp b/src/video_core/buffer_cache/buffer.cpp index d112864d5..e9dceb624 100644 --- a/src/video_core/buffer_cache/buffer.cpp +++ b/src/video_core/buffer_cache/buffer.cpp @@ -17,7 +17,8 @@ constexpr vk::BufferUsageFlags AllFlags = vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eUniformTexelBuffer | vk::BufferUsageFlagBits::eStorageTexelBuffer | vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eStorageBuffer | - vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eVertexBuffer; + vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eVertexBuffer | + vk::BufferUsageFlagBits::eIndirectBuffer; std::string_view BufferTypeName(MemoryUsage type) { switch (type) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f22f19eaf..9231c5104 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -90,6 +90,45 @@ void Rasterizer::DispatchDirect() { cmdbuf.dispatch(cs_program.dim_x, cs_program.dim_y, cs_program.dim_z); } +void Rasterizer::DispatchIndirect(VAddr address, u32 offset, u32 size) { + RENDERER_TRACE; + + const auto cmdbuf = scheduler.CommandBuffer(); + const auto& cs_program = liverpool->regs.cs_program; + const ComputePipeline* pipeline = pipeline_cache.GetComputePipeline(); + if (!pipeline) { + return; + } + + try { + const auto has_resources = pipeline->BindResources(buffer_cache, texture_cache); + if (!has_resources) { + return; + } + } catch (...) { + UNREACHABLE(); + } + + scheduler.EndRendering(); + cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle()); + const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true); + const auto total_offset = base + offset; + + // Emulate PFP-to-ME sync packet + const vk::BufferMemoryBarrier ib_barrier{ + .srcAccessMask = vk::AccessFlagBits::eShaderWrite, + .dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead, + .buffer = buffer->Handle(), + .offset = total_offset, + .size = size, + }; + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, + vk::PipelineStageFlagBits::eDrawIndirect, + vk::DependencyFlagBits::eByRegion, {}, ib_barrier, {}); + + cmdbuf.dispatchIndirect(buffer->Handle(), total_offset); +} + u64 Rasterizer::Flush() { const u64 current_tick = scheduler.CurrentTick(); SubmitInfo info{}; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index a151ebc27..34f6ae726 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -34,6 +34,7 @@ public: void Draw(bool is_indexed, u32 index_offset = 0); void DispatchDirect(); + void DispatchIndirect(VAddr address, u32 offset, u32 size); void ScopeMarkerBegin(const std::string_view& str); void ScopeMarkerEnd(); From 37786e06c2c3c607347b1e46ded9a49110bf9793 Mon Sep 17 00:00:00 2001 From: Marcin Mitura Date: Thu, 29 Aug 2024 13:27:11 +0200 Subject: [PATCH 102/147] DLCs - Polish localization Translates strings introduced in #596. --- src/qt_gui/translations/pl_PL.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index c92f49475..40f8933e1 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -608,12 +608,12 @@ DLC Installation - DLC Installation + Instalacja dodadkowej zawartości (DLC) Would you like to install DLC: %1? - Would you like to install DLC: %1? + Czy na pewno chcesz zainstalować dodatkową zawartość (DLC): %1? From 81eb3a4d14f0ff01eb4e15b44634f439355a3df7 Mon Sep 17 00:00:00 2001 From: kiwipuppeh Date: Thu, 29 Aug 2024 08:22:19 -0400 Subject: [PATCH 103/147] Add /hostapp support In the case of certain games, such as Battlefield 4 (CUSA00110), the local pathing will resolve to /hostapp instead of /app0, which works fine on PS4, but was failing to resolve to any meaningful mount in shadPS4, this corrects this issue when running from eboot.bin directly. --- src/emulator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/emulator.cpp b/src/emulator.cpp index b12bb8591..85a4d745a 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -84,6 +84,8 @@ void Emulator::Run(const std::filesystem::path& file) { // Applications expect to be run from /app0 so mount the file's parent path as app0. auto* mnt = Common::Singleton::Instance(); mnt->Mount(file.parent_path(), "/app0"); + // Certain games may use /hostapp as well such as CUSA001100 + mnt->Mount(file.parent_path(), "/hostapp"); // Loading param.sfo file if exists std::string id; From aef7498c49be3a0ee5718e69111e506be0e2dff3 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Thu, 29 Aug 2024 13:21:58 -0300 Subject: [PATCH 104/147] fix tr cheats_patches.cpp the 2 words were not being translated --- src/qt_gui/cheats_patches.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index 662d52cc1..47acf068c 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -130,7 +130,7 @@ void CheatsPatches::setupUI() { // Call the method to fill the list of cheat files populateFileListCheats(); - QLabel* repositoryLabel = new QLabel("Repository:"); + QLabel* repositoryLabel = new QLabel(tr("Repository:")); repositoryLabel->setAlignment(Qt::AlignLeft); repositoryLabel->setAlignment(Qt::AlignVCenter); @@ -1123,7 +1123,7 @@ void CheatsPatches::addPatchesToLayout(const QString& filePath) { void CheatsPatches::updateNoteTextEdit(const QString& patchName) { if (m_patchInfos.contains(patchName)) { const PatchInfo& patchInfo = m_patchInfos[patchName]; - QString text = QString(tr("Name:") + " %1\n" + tr("Author:") + " %2\n\n%3") + QString text = QString(tr("Name:") + " %1\n" + tr("Author: ") + "%2\n\n%3") .arg(patchInfo.name) .arg(patchInfo.author) .arg(patchInfo.note); @@ -1261,4 +1261,4 @@ void CheatsPatches::onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered) { } else { instructionsTextEdit->setText(defaultTextEdit); } -} \ No newline at end of file +} From 66e96dd94439be3dd4684d7a983a7b10745d7bc7 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:29:54 +0300 Subject: [PATCH 105/147] video_core: Account of runtime state changes when compiling shaders (#575) * video_core: Compile shader permutations * spirv: Only specific storage image format for atomics * ir: Avoid cube coord patching for storage image * spirv: Fix default attributes * data_share: Add more instructions * video_core: Query storage flag with runtime state * kernel: Use std::list for semaphore * video_core: Use texture buffers for untyped format load/store * buffer_cache: Limit view usage * vk_pipeline_cache: Fix invalid iterator * image_view: Reduce log spam when alpha=1 in storage swizzle * video_core: More features and proper spirv feature detection * video_core: Attempt no2 for specialization * spirv: Remove conflict * vk_shader_cache: Small cleanup --- CMakeLists.txt | 2 + src/core/libraries/avplayer/avplayer.cpp | 2 +- .../libraries/kernel/threads/semaphore.cpp | 33 +- .../backend/spirv/emit_spirv.cpp | 41 ++- .../backend/spirv/emit_spirv.h | 2 +- .../spirv/emit_spirv_context_get_set.cpp | 269 +---------------- .../backend/spirv/spirv_emit_context.cpp | 156 ++++++---- .../backend/spirv/spirv_emit_context.h | 17 +- .../frontend/translate/data_share.cpp | 35 ++- .../frontend/translate/export.cpp | 2 - .../frontend/translate/translate.cpp | 4 +- .../frontend/translate/translate.h | 12 +- .../frontend/translate/vector_alu.cpp | 14 +- .../frontend/translate/vector_memory.cpp | 165 ++++++---- src/shader_recompiler/ir/ir_emitter.cpp | 37 +-- src/shader_recompiler/ir/ir_emitter.h | 6 +- src/shader_recompiler/ir/microinstruction.cpp | 3 - src/shader_recompiler/ir/opcodes.inc | 10 +- .../ir/passes/resource_tracking_pass.cpp | 190 +++++------- .../ir/passes/shader_info_collection_pass.cpp | 9 + src/shader_recompiler/ir/program.h | 4 +- src/shader_recompiler/ir/reg.h | 3 - src/shader_recompiler/recompiler.cpp | 5 +- src/shader_recompiler/recompiler.h | 2 +- src/shader_recompiler/runtime_info.h | 53 +++- src/video_core/amdgpu/liverpool.h | 2 +- src/video_core/amdgpu/pixel_format.h | 4 + src/video_core/amdgpu/resource.h | 5 + src/video_core/buffer_cache/buffer.cpp | 39 +-- src/video_core/buffer_cache/buffer.h | 15 +- src/video_core/buffer_cache/buffer_cache.cpp | 7 +- .../renderer_vulkan/vk_compute_pipeline.cpp | 106 +++++-- .../renderer_vulkan/vk_compute_pipeline.h | 11 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 91 ++++-- .../renderer_vulkan/vk_graphics_pipeline.h | 3 +- .../renderer_vulkan/vk_instance.cpp | 10 +- src/video_core/renderer_vulkan/vk_instance.h | 5 + .../renderer_vulkan/vk_pipeline_cache.cpp | 285 +++--------------- .../renderer_vulkan/vk_pipeline_cache.h | 19 +- .../renderer_vulkan/vk_shader_cache.cpp | 192 ++++++++++++ .../renderer_vulkan/vk_shader_cache.h | 156 ++++++++++ src/video_core/texture_cache/image_view.cpp | 6 +- src/video_core/texture_cache/tile_manager.cpp | 2 + 43 files changed, 1058 insertions(+), 976 deletions(-) create mode 100644 src/video_core/renderer_vulkan/vk_shader_cache.cpp create mode 100644 src/video_core/renderer_vulkan/vk_shader_cache.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dfc6528df..d2d1c170a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -521,6 +521,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/renderer_vulkan/vk_resource_pool.h src/video_core/renderer_vulkan/vk_scheduler.cpp src/video_core/renderer_vulkan/vk_scheduler.h + src/video_core/renderer_vulkan/vk_shader_cache.cpp + src/video_core/renderer_vulkan/vk_shader_cache.h src/video_core/renderer_vulkan/vk_shader_util.cpp src/video_core/renderer_vulkan/vk_shader_util.h src/video_core/renderer_vulkan/vk_swapchain.cpp diff --git a/src/core/libraries/avplayer/avplayer.cpp b/src/core/libraries/avplayer/avplayer.cpp index 406583a8c..23e1e987a 100644 --- a/src/core/libraries/avplayer/avplayer.cpp +++ b/src/core/libraries/avplayer/avplayer.cpp @@ -325,4 +325,4 @@ void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("yN7Jhuv8g24", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerVprintf); }; -} // namespace Libraries::AvPlayer \ No newline at end of file +} // namespace Libraries::AvPlayer diff --git a/src/core/libraries/kernel/threads/semaphore.cpp b/src/core/libraries/kernel/threads/semaphore.cpp index 5304dc57b..e2f438037 100644 --- a/src/core/libraries/kernel/threads/semaphore.cpp +++ b/src/core/libraries/kernel/threads/semaphore.cpp @@ -2,9 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include -#include -#include #include #include "common/assert.h" #include "common/logging/log.h" @@ -13,9 +12,6 @@ namespace Libraries::Kernel { -using ListBaseHook = - boost::intrusive::list_base_hook>; - class Semaphore { public: Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo) @@ -37,7 +33,7 @@ public: // Create waiting thread object and add it into the list of waiters. WaitingThread waiter{need_count, is_fifo}; - AddWaiter(waiter); + AddWaiter(&waiter); // Perform the wait. return waiter.Wait(lk, timeout); @@ -52,14 +48,14 @@ public: // Wake up threads in order of priority. for (auto it = wait_list.begin(); it != wait_list.end();) { - auto& waiter = *it; - if (waiter.need_count > token_count) { + auto* waiter = *it; + if (waiter->need_count > token_count) { it++; continue; } it = wait_list.erase(it); - token_count -= waiter.need_count; - waiter.cv.notify_one(); + token_count -= waiter->need_count; + waiter->cv.notify_one(); } return true; @@ -70,9 +66,9 @@ public: if (num_waiters) { *num_waiters = wait_list.size(); } - for (auto& waiter : wait_list) { - waiter.was_cancled = true; - waiter.cv.notify_one(); + for (auto* waiter : wait_list) { + waiter->was_cancled = true; + waiter->cv.notify_one(); } wait_list.clear(); token_count = set_count < 0 ? init_count : set_count; @@ -80,7 +76,7 @@ public: } public: - struct WaitingThread : public ListBaseHook { + struct WaitingThread { std::condition_variable cv; u32 priority; s32 need_count; @@ -132,7 +128,7 @@ public: } }; - void AddWaiter(WaitingThread& waiter) { + void AddWaiter(WaitingThread* waiter) { // Insert at the end of the list for FIFO order. if (is_fifo) { wait_list.push_back(waiter); @@ -140,16 +136,13 @@ public: } // Find the first with priority less then us and insert right before it. auto it = wait_list.begin(); - while (it != wait_list.end() && it->priority > waiter.priority) { + while (it != wait_list.end() && (*it)->priority > waiter->priority) { it++; } wait_list.insert(it, waiter); } - using WaitingThreads = - boost::intrusive::list, - boost::intrusive::constant_time_size>; - WaitingThreads wait_list; + std::list wait_list; std::string name; std::atomic token_count; std::mutex mutex; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 09a9fd629..161d4ec9e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -99,7 +99,7 @@ Id TypeId(const EmitContext& ctx, IR::Type type) { } } -void Traverse(EmitContext& ctx, IR::Program& program) { +void Traverse(EmitContext& ctx, const IR::Program& program) { IR::Block* current_block{}; for (const IR::AbstractSyntaxNode& node : program.syntax_list) { switch (node.type) { @@ -162,7 +162,7 @@ void Traverse(EmitContext& ctx, IR::Program& program) { } } -Id DefineMain(EmitContext& ctx, IR::Program& program) { +Id DefineMain(EmitContext& ctx, const IR::Program& program) { const Id void_function{ctx.TypeFunction(ctx.void_id)}; const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; for (IR::Block* const block : program.blocks) { @@ -185,8 +185,27 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { ctx.AddCapability(spv::Capability::Int16); } ctx.AddCapability(spv::Capability::Int64); - if (info.has_storage_images) { + if (info.has_storage_images || info.has_image_buffers) { ctx.AddCapability(spv::Capability::StorageImageExtendedFormats); + ctx.AddCapability(spv::Capability::StorageImageWriteWithoutFormat); + } + if (info.has_texel_buffers) { + ctx.AddCapability(spv::Capability::SampledBuffer); + } + if (info.has_image_buffers) { + ctx.AddCapability(spv::Capability::ImageBuffer); + } + if (info.has_image_gather) { + ctx.AddCapability(spv::Capability::ImageGatherExtended); + } + if (info.has_image_query) { + ctx.AddCapability(spv::Capability::ImageQuery); + } + if (info.uses_lane_id) { + ctx.AddCapability(spv::Capability::GroupNonUniform); + } + if (info.uses_group_quad) { + ctx.AddCapability(spv::Capability::GroupNonUniformQuad); } switch (program.info.stage) { case Stage::Compute: { @@ -206,19 +225,9 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { } else { ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft); } - ctx.AddCapability(spv::Capability::GroupNonUniform); - if (info.uses_group_quad) { - ctx.AddCapability(spv::Capability::GroupNonUniformQuad); - } if (info.has_discard) { ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); } - if (info.has_image_gather) { - ctx.AddCapability(spv::Capability::ImageGatherExtended); - } - if (info.has_image_query) { - ctx.AddCapability(spv::Capability::ImageQuery); - } if (info.stores.Get(IR::Attribute::Depth)) { ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); } @@ -229,7 +238,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { ctx.AddEntryPoint(execution_model, main, "main", interfaces); } -void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { +void PatchPhiNodes(const IR::Program& program, EmitContext& ctx) { auto inst{program.blocks.front()->begin()}; size_t block_index{0}; ctx.PatchDeferredPhi([&](size_t phi_arg) { @@ -248,8 +257,8 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { } } // Anonymous namespace -std::vector EmitSPIRV(const Profile& profile, IR::Program& program, u32& binding) { - EmitContext ctx{profile, program, binding}; +std::vector EmitSPIRV(const Profile& profile, const IR::Program& program, u32& binding) { + EmitContext ctx{profile, program.info, binding}; const Id main{DefineMain(ctx, program)}; DefineEntryPoint(program, ctx, main); if (program.info.stage == Stage::Vertex) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index e513975b3..4c862185f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h @@ -9,7 +9,7 @@ namespace Shader::Backend::SPIRV { -[[nodiscard]] std::vector EmitSPIRV(const Profile& profile, IR::Program& program, +[[nodiscard]] std::vector EmitSPIRV(const Profile& profile, const IR::Program& program, u32& binding); } // namespace Shader::Backend::SPIRV 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 03fc52ff4..4566439c6 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 @@ -262,171 +262,15 @@ Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { return EmitLoadBufferF32xN<4>(ctx, handle, address); } -static bool IsSignedInteger(AmdGpu::NumberFormat format) { - switch (format) { - case AmdGpu::NumberFormat::Unorm: - case AmdGpu::NumberFormat::Uscaled: - case AmdGpu::NumberFormat::Uint: - return false; - case AmdGpu::NumberFormat::Snorm: - case AmdGpu::NumberFormat::Sscaled: - case AmdGpu::NumberFormat::Sint: - case AmdGpu::NumberFormat::SnormNz: - return true; - case AmdGpu::NumberFormat::Float: - default: - UNREACHABLE(); - } -} - -static u32 UXBitsMax(u32 bit_width) { - return (1u << bit_width) - 1u; -} - -static u32 SXBitsMax(u32 bit_width) { - return (1u << (bit_width - 1u)) - 1u; -} - -static Id ConvertValue(EmitContext& ctx, Id value, AmdGpu::NumberFormat format, u32 bit_width) { - switch (format) { - case AmdGpu::NumberFormat::Unorm: - return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(UXBitsMax(bit_width)))); - case AmdGpu::NumberFormat::Snorm: - return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(SXBitsMax(bit_width)))); - case AmdGpu::NumberFormat::SnormNz: - // (x * 2 + 1) / (Format::SMAX * 2) - value = ctx.OpFMul(ctx.F32[1], value, ctx.ConstF32(2.f)); - value = ctx.OpFAdd(ctx.F32[1], value, ctx.ConstF32(1.f)); - return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(SXBitsMax(bit_width) * 2))); - case AmdGpu::NumberFormat::Uscaled: - case AmdGpu::NumberFormat::Sscaled: - case AmdGpu::NumberFormat::Uint: - case AmdGpu::NumberFormat::Sint: - case AmdGpu::NumberFormat::Float: - return value; - default: - UNREACHABLE_MSG("Unsupported number format for conversion: {}", - magic_enum::enum_name(format)); - } -} - -static Id ComponentOffset(EmitContext& ctx, Id address, u32 stride, u32 bit_offset) { - Id comp_offset = ctx.ConstU32(bit_offset); - if (stride < 4) { - // comp_offset += (address % 4) * 8; - const Id byte_offset = ctx.OpUMod(ctx.U32[1], address, ctx.ConstU32(4u)); - const Id bit_offset = ctx.OpShiftLeftLogical(ctx.U32[1], byte_offset, ctx.ConstU32(3u)); - comp_offset = ctx.OpIAdd(ctx.U32[1], comp_offset, bit_offset); - } - return comp_offset; -} - -static Id GetBufferFormatValue(EmitContext& ctx, u32 handle, Id address, u32 comp) { - auto& buffer = ctx.buffers[handle]; - const auto format = buffer.dfmt; - switch (format) { - case AmdGpu::DataFormat::FormatInvalid: - return ctx.f32_zero_value; - case AmdGpu::DataFormat::Format8: - case AmdGpu::DataFormat::Format16: - case AmdGpu::DataFormat::Format32: - case AmdGpu::DataFormat::Format8_8: - case AmdGpu::DataFormat::Format16_16: - case AmdGpu::DataFormat::Format10_11_11: - case AmdGpu::DataFormat::Format11_11_10: - case AmdGpu::DataFormat::Format10_10_10_2: - case AmdGpu::DataFormat::Format2_10_10_10: - case AmdGpu::DataFormat::Format8_8_8_8: - case AmdGpu::DataFormat::Format32_32: - case AmdGpu::DataFormat::Format16_16_16_16: - case AmdGpu::DataFormat::Format32_32_32: - case AmdGpu::DataFormat::Format32_32_32_32: { - const u32 num_components = AmdGpu::NumComponents(format); - if (comp >= num_components) { - return ctx.f32_zero_value; - } - - // uint index = address / 4; - Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); - const u32 stride = buffer.stride; - if (stride > 4) { - const u32 index_offset = u32(AmdGpu::ComponentOffset(format, comp) / 32); - if (index_offset > 0) { - // index += index_offset; - index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(index_offset)); - } - } - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index); - - const u32 bit_offset = AmdGpu::ComponentOffset(format, comp) % 32; - const u32 bit_width = AmdGpu::ComponentBits(format, comp); - const auto num_format = buffer.nfmt; - if (num_format == AmdGpu::NumberFormat::Float) { - if (bit_width == 32) { - return ctx.OpLoad(ctx.F32[1], ptr); - } else if (bit_width == 16) { - const Id comp_offset = ComponentOffset(ctx, address, stride, bit_offset); - Id value = ctx.OpLoad(ctx.U32[1], ptr); - value = - ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset, ctx.ConstU32(bit_width)); - value = ctx.OpSConvert(ctx.U16, value); - value = ctx.OpBitcast(ctx.F16[1], value); - return ctx.OpFConvert(ctx.F32[1], value); - } else { - UNREACHABLE_MSG("Invalid float bit width {}", bit_width); - } - } else { - Id value = ctx.OpLoad(ctx.U32[1], ptr); - const bool is_signed = IsSignedInteger(num_format); - if (bit_width < 32) { - const Id comp_offset = ComponentOffset(ctx, address, stride, bit_offset); - if (is_signed) { - value = ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset, - ctx.ConstU32(bit_width)); - } else { - value = ctx.OpBitFieldUExtract(ctx.U32[1], value, comp_offset, - ctx.ConstU32(bit_width)); - } - } - value = ctx.OpBitcast(ctx.F32[1], value); - return ConvertValue(ctx, value, num_format, bit_width); - } - break; - } - default: - UNREACHABLE_MSG("Invalid format for conversion: {}", magic_enum::enum_name(format)); - } -} - -template -static Id EmitLoadBufferFormatF32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - auto& buffer = ctx.buffers[handle]; - address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); - if constexpr (N == 1) { - return GetBufferFormatValue(ctx, handle, address, 0); - } else { - boost::container::static_vector ids; - for (u32 i = 0; i < N; i++) { - ids.push_back(GetBufferFormatValue(ctx, handle, address, i)); - } - return ctx.OpCompositeConstruct(ctx.F32[N], ids); - } -} - Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<1>(ctx, inst, handle, address); -} - -Id EmitLoadBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<2>(ctx, inst, handle, address); -} - -Id EmitLoadBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<3>(ctx, inst, handle, address); -} - -Id EmitLoadBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<4>(ctx, inst, handle, address); + const auto& buffer = ctx.texture_buffers[handle]; + const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id); + const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset); + Id texel = ctx.OpImageFetch(buffer.result_type, tex_buffer, coord); + if (buffer.is_integer) { + texel = ctx.OpBitcast(ctx.F32[4], texel); + } + return texel; } template @@ -467,97 +311,14 @@ void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address EmitStoreBufferF32xN<1>(ctx, handle, address, value); } -static Id ConvertF32ToFormat(EmitContext& ctx, Id value, AmdGpu::NumberFormat format, - u32 bit_width) { - switch (format) { - case AmdGpu::NumberFormat::Unorm: - return ctx.OpConvertFToU( - ctx.U32[1], ctx.OpFMul(ctx.F32[1], value, ctx.ConstF32(float(UXBitsMax(bit_width))))); - case AmdGpu::NumberFormat::Uint: - return ctx.OpBitcast(ctx.U32[1], value); - case AmdGpu::NumberFormat::Float: - return value; - default: - UNREACHABLE_MSG("Unsupported number format for conversion: {}", - magic_enum::enum_name(format)); - } -} - -template -static void EmitStoreBufferFormatF32xN(EmitContext& ctx, u32 handle, Id address, Id value) { - auto& buffer = ctx.buffers[handle]; - const auto format = buffer.dfmt; - const auto num_format = buffer.nfmt; - - switch (format) { - case AmdGpu::DataFormat::FormatInvalid: - return; - case AmdGpu::DataFormat::Format8_8_8_8: - case AmdGpu::DataFormat::Format16: - case AmdGpu::DataFormat::Format32: - case AmdGpu::DataFormat::Format32_32: - case AmdGpu::DataFormat::Format32_32_32_32: { - ASSERT(N == AmdGpu::NumComponents(format)); - - 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); - - Id packed_value{}; - for (u32 i = 0; i < N; i++) { - const u32 bit_width = AmdGpu::ComponentBits(format, i); - const u32 bit_offset = AmdGpu::ComponentOffset(format, i) % 32; - - const Id comp{ConvertF32ToFormat( - ctx, N == 1 ? value : ctx.OpCompositeExtract(ctx.F32[1], value, i), num_format, - bit_width)}; - - if (bit_width == 32) { - if constexpr (N == 1) { - ctx.OpStore(ptr, comp); - } else { - 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, comp); - } - } else { - if (i == 0) { - packed_value = comp; - } else { - packed_value = - ctx.OpBitFieldInsert(ctx.U32[1], packed_value, comp, - ctx.ConstU32(bit_offset), ctx.ConstU32(bit_width)); - } - - if (i == N - 1) { - ctx.OpStore(ptr, packed_value); - } - } - } - } break; - default: - UNREACHABLE_MSG("Invalid format for conversion: {}", magic_enum::enum_name(format)); - } -} - void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferFormatF32xN<1>(ctx, handle, address, value); -} - -void EmitStoreBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, - Id value) { - EmitStoreBufferFormatF32xN<2>(ctx, handle, address, value); -} - -void EmitStoreBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, - Id value) { - EmitStoreBufferFormatF32xN<3>(ctx, handle, address, value); -} - -void EmitStoreBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, - Id value) { - EmitStoreBufferFormatF32xN<4>(ctx, handle, address, value); + const auto& buffer = ctx.texture_buffers[handle]; + const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id); + const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset); + if (buffer.is_integer) { + value = ctx.OpBitcast(ctx.U32[4], value); + } + ctx.OpImageWrite(tex_buffer, coord, value); } } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 994c2847e..e40196047 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -41,13 +41,14 @@ void Name(EmitContext& ctx, Id object, std::string_view format_str, Args&&... ar } // Anonymous namespace -EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& binding_) - : Sirit::Module(profile_.supported_spirv), info{program.info}, profile{profile_}, - stage{program.info.stage}, binding{binding_} { +EmitContext::EmitContext(const Profile& profile_, const Shader::Info& info_, u32& binding_) + : Sirit::Module(profile_.supported_spirv), info{info_}, profile{profile_}, stage{info.stage}, + binding{binding_} { AddCapability(spv::Capability::Shader); DefineArithmeticTypes(); DefineInterfaces(); DefineBuffers(); + DefineTextureBuffers(); DefineImagesAndSamplers(); DefineSharedMemory(); } @@ -123,25 +124,24 @@ void EmitContext::DefineInterfaces() { DefineOutputs(); } -Id GetAttributeType(EmitContext& ctx, AmdGpu::NumberFormat fmt) { +const VectorIds& GetAttributeType(EmitContext& ctx, AmdGpu::NumberFormat fmt) { switch (fmt) { case AmdGpu::NumberFormat::Float: case AmdGpu::NumberFormat::Unorm: case AmdGpu::NumberFormat::Snorm: case AmdGpu::NumberFormat::SnormNz: - return ctx.F32[4]; - case AmdGpu::NumberFormat::Sint: - return ctx.S32[4]; - case AmdGpu::NumberFormat::Uint: - return ctx.U32[4]; case AmdGpu::NumberFormat::Sscaled: - return ctx.F32[4]; case AmdGpu::NumberFormat::Uscaled: - return ctx.F32[4]; + case AmdGpu::NumberFormat::Srgb: + return ctx.F32; + case AmdGpu::NumberFormat::Sint: + return ctx.S32; + case AmdGpu::NumberFormat::Uint: + return ctx.U32; default: break; } - throw InvalidArgument("Invalid attribute type {}", fmt); + UNREACHABLE_MSG("Invalid attribute type {}", fmt); } EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id) { @@ -162,7 +162,7 @@ EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat f default: break; } - throw InvalidArgument("Invalid attribute type {}", fmt); + UNREACHABLE_MSG("Invalid attribute type {}", fmt); } void EmitContext::DefineBufferOffsets() { @@ -177,6 +177,16 @@ void EmitContext::DefineBufferOffsets() { buffer.offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U)); buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U)); } + for (auto& tex_buffer : texture_buffers) { + const u32 binding = tex_buffer.binding; + const u32 half = Shader::PushData::BufOffsetIndex + (binding >> 4); + const u32 comp = (binding & 0xf) >> 2; + const u32 offset = (binding & 0x3) << 3; + const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]), + push_data_block, ConstU32(half), ConstU32(comp))}; + const Id value{OpLoad(U32[1], ptr)}; + tex_buffer.coord_offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U)); + } } Id MakeDefaultValue(EmitContext& ctx, u32 default_value) { @@ -195,6 +205,11 @@ Id MakeDefaultValue(EmitContext& ctx, u32 default_value) { } void EmitContext::DefineInputs() { + if (info.uses_lane_id) { + subgroup_local_invocation_id = DefineVariable( + U32[1], spv::BuiltIn::SubgroupLocalInvocationId, spv::StorageClass::Input); + Decorate(subgroup_local_invocation_id, spv::Decoration::Flat); + } switch (stage) { case Stage::Vertex: { vertex_index = DefineVariable(U32[1], spv::BuiltIn::VertexIndex, spv::StorageClass::Input); @@ -202,7 +217,7 @@ void EmitContext::DefineInputs() { instance_id = DefineVariable(U32[1], spv::BuiltIn::InstanceIndex, spv::StorageClass::Input); for (const auto& input : info.vs_inputs) { - const Id type{GetAttributeType(*this, input.fmt)}; + const Id type{GetAttributeType(*this, input.fmt)[4]}; if (input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate0 || input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate1) { @@ -229,15 +244,12 @@ void EmitContext::DefineInputs() { break; } case Stage::Fragment: - subgroup_local_invocation_id = DefineVariable( - U32[1], spv::BuiltIn::SubgroupLocalInvocationId, spv::StorageClass::Input); - Decorate(subgroup_local_invocation_id, spv::Decoration::Flat); 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); for (const auto& input : info.ps_inputs) { const u32 semantic = input.param_index; - if (input.is_default) { + if (input.is_default && !input.is_flat) { input_params[semantic] = {MakeDefaultValue(*this, input.default_value), F32[1], F32[1], 4, true}; continue; @@ -328,47 +340,74 @@ void EmitContext::DefinePushDataBlock() { void EmitContext::DefineBuffers() { boost::container::small_vector type_ids; - for (u32 i = 0; const auto& buffer : info.buffers) { - const auto* data_types = True(buffer.used_types & IR::Type::F32) ? &F32 : &U32; - const Id data_type = (*data_types)[1]; - const Id record_array_type{buffer.is_storage - ? TypeRuntimeArray(data_type) - : TypeArray(data_type, ConstU32(buffer.length))}; + const auto define_struct = [&](Id record_array_type, bool is_instance_data) { const Id struct_type{TypeStruct(record_array_type)}; - if (std::ranges::find(type_ids, record_array_type.value, &Id::value) == type_ids.end()) { - Decorate(record_array_type, spv::Decoration::ArrayStride, 4); - const auto name = - buffer.is_instance_data - ? fmt::format("{}_instance_data{}_{}{}", stage, i, 'f', - sizeof(float) * CHAR_BIT) - : fmt::format("{}_cbuf_block_{}{}", stage, 'f', sizeof(float) * CHAR_BIT); - Name(struct_type, name); - 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); + 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); + const auto name = is_instance_data ? fmt::format("{}_instance_data_f32", stage) + : fmt::format("{}_cbuf_block_f32", stage); + Name(struct_type, name); + 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; + }; + + for (const auto& desc : info.buffers) { + const auto sharp = desc.GetSharp(info); + const bool is_storage = desc.IsStorage(sharp); + 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(sharp.NumDwords()))}; + const Id struct_type{define_struct(record_array_type, desc.is_instance_data)}; const auto storage_class = - buffer.is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform; + 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); Decorate(id, spv::Decoration::DescriptorSet, 0U); - Name(id, fmt::format("{}_{}", buffer.is_storage ? "ssbo" : "cbuf", buffer.sgpr_base)); + if (is_storage && !desc.is_written) { + Decorate(id, spv::Decoration::NonWritable); + } + Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "cbuf", desc.sgpr_base)); buffers.push_back({ .id = id, .binding = binding++, .data_types = data_types, .pointer_type = pointer_type, - .dfmt = buffer.dfmt, - .nfmt = buffer.nfmt, - .stride = buffer.GetVsharp(info).GetStride(), }); interfaces.push_back(id); - i++; + } +} + +void EmitContext::DefineTextureBuffers() { + for (const auto& desc : info.texture_buffers) { + const bool is_integer = + desc.nfmt == AmdGpu::NumberFormat::Uint || desc.nfmt == AmdGpu::NumberFormat::Sint; + const VectorIds& sampled_type{GetAttributeType(*this, desc.nfmt)}; + const u32 sampled = desc.is_written ? 2 : 1; + const Id image_type{TypeImage(sampled_type[1], spv::Dim::Buffer, false, false, false, + sampled, spv::ImageFormat::Unknown)}; + const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; + const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; + Decorate(id, spv::Decoration::Binding, binding); + Decorate(id, spv::Decoration::DescriptorSet, 0U); + Name(id, fmt::format("{}_{}", desc.is_written ? "imgbuf" : "texbuf", desc.sgpr_base)); + texture_buffers.push_back({ + .id = id, + .binding = binding++, + .image_type = image_type, + .result_type = sampled_type[4], + .is_integer = is_integer, + }); + interfaces.push_back(id); } } @@ -447,7 +486,7 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { const auto image = ctx.info.ReadUd(desc.sgpr_base, desc.dword_offset); - const auto format = desc.is_storage ? GetFormat(image) : spv::ImageFormat::Unknown; + const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown; const u32 sampled = desc.is_storage ? 2 : 1; switch (desc.type) { case AmdGpu::ImageType::Color1D: @@ -470,17 +509,8 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { void EmitContext::DefineImagesAndSamplers() { for (const auto& image_desc : info.images) { - const VectorIds* data_types = [&] { - switch (image_desc.nfmt) { - case AmdGpu::NumberFormat::Uint: - return &U32; - case AmdGpu::NumberFormat::Sint: - return &S32; - default: - return &F32; - } - }(); - const Id sampled_type = data_types->Get(1); + const VectorIds& data_types = GetAttributeType(*this, image_desc.nfmt); + const Id sampled_type = data_types[1]; const Id image_type{ImageType(*this, image_desc, sampled_type)}; const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; @@ -489,7 +519,7 @@ void EmitContext::DefineImagesAndSamplers() { Name(id, fmt::format("{}_{}{}_{:02x}", stage, "img", image_desc.sgpr_base, image_desc.dword_offset)); images.push_back({ - .data_types = data_types, + .data_types = &data_types, .id = id, .sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type), .pointer_type = pointer_type, @@ -498,13 +528,12 @@ void EmitContext::DefineImagesAndSamplers() { interfaces.push_back(id); ++binding; } - - image_u32 = TypePointer(spv::StorageClass::Image, U32[1]); - + if (std::ranges::any_of(info.images, &ImageResource::is_atomic)) { + image_u32 = TypePointer(spv::StorageClass::Image, U32[1]); + } if (info.samplers.empty()) { return; } - sampler_type = TypeSampler(); sampler_pointer_type = TypePointer(spv::StorageClass::UniformConstant, sampler_type); for (const auto& samp_desc : info.samplers) { @@ -520,14 +549,15 @@ void EmitContext::DefineImagesAndSamplers() { } void EmitContext::DefineSharedMemory() { - static constexpr size_t DefaultSharedMemSize = 16_KB; + static constexpr size_t DefaultSharedMemSize = 2_KB; if (!info.uses_shared) { return; } - if (info.shared_memory_size == 0) { - info.shared_memory_size = DefaultSharedMemSize; + u32 shared_memory_size = info.shared_memory_size; + if (shared_memory_size == 0) { + shared_memory_size = DefaultSharedMemSize; } - const u32 num_elements{Common::DivCeil(info.shared_memory_size, 4U)}; + const u32 num_elements{Common::DivCeil(shared_memory_size, 4U)}; const Id type{TypeArray(U32[1], ConstU32(num_elements))}; shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 5a09c4116..5391108f3 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -36,7 +36,7 @@ struct VectorIds { class EmitContext final : public Sirit::Module { public: - explicit EmitContext(const Profile& profile, IR::Program& program, u32& binding); + explicit EmitContext(const Profile& profile, const Shader::Info& info, u32& binding); ~EmitContext(); Id Def(const IR::Value& value); @@ -124,7 +124,7 @@ public: return ConstantComposite(type, constituents); } - Info& info; + const Info& info; const Profile& profile; Stage stage{}; @@ -207,13 +207,19 @@ public: u32 binding; const VectorIds* data_types; Id pointer_type; - AmdGpu::DataFormat dfmt; - AmdGpu::NumberFormat nfmt; - u32 stride; + }; + struct TextureBufferDefinition { + Id id; + Id coord_offset; + u32 binding; + Id image_type; + Id result_type; + bool is_integer; }; u32& binding; boost::container::small_vector buffers; + boost::container::small_vector texture_buffers; boost::container::small_vector images; boost::container::small_vector samplers; @@ -238,6 +244,7 @@ private: void DefineOutputs(); void DefinePushDataBlock(); void DefineBuffers(); + void DefineTextureBuffers(); void DefineImagesAndSamplers(); void DefineSharedMemory(); diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index 7580f7444..aa9b49b63 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -18,25 +18,31 @@ void Translator::EmitDataShare(const GcnInst& inst) { case Opcode::DS_READ2_B64: return DS_READ(64, false, true, inst); case Opcode::DS_WRITE_B32: - return DS_WRITE(32, false, false, inst); + return DS_WRITE(32, false, false, false, inst); + case Opcode::DS_WRITE2ST64_B32: + return DS_WRITE(32, false, true, true, inst); case Opcode::DS_WRITE_B64: - return DS_WRITE(64, false, false, inst); + return DS_WRITE(64, false, false, false, inst); case Opcode::DS_WRITE2_B32: - return DS_WRITE(32, false, true, inst); + return DS_WRITE(32, false, true, false, inst); case Opcode::DS_WRITE2_B64: - return DS_WRITE(64, false, true, inst); + return DS_WRITE(64, false, true, false, inst); case Opcode::DS_ADD_U32: return DS_ADD_U32(inst, false); case Opcode::DS_MIN_U32: - return DS_MIN_U32(inst, false); + return DS_MIN_U32(inst, false, false); + case Opcode::DS_MIN_I32: + return DS_MIN_U32(inst, true, false); case Opcode::DS_MAX_U32: - return DS_MAX_U32(inst, false); + return DS_MAX_U32(inst, false, false); + case Opcode::DS_MAX_I32: + return DS_MAX_U32(inst, true, false); case Opcode::DS_ADD_RTN_U32: return DS_ADD_U32(inst, true); case Opcode::DS_MIN_RTN_U32: - return DS_MIN_U32(inst, true); + return DS_MIN_U32(inst, false, true); case Opcode::DS_MAX_RTN_U32: - return DS_MAX_U32(inst, true); + return DS_MAX_U32(inst, false, true); default: LogMissingOpcode(inst); } @@ -89,12 +95,13 @@ void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnIn } } -void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst) { +void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, + const GcnInst& inst) { 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}; if (is_pair) { - const u32 adj = bit_size == 32 ? 4 : 8; + 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))); if (bit_size == 32) { ir.WriteShared(32, ir.GetVectorReg(data0), addr0); @@ -133,23 +140,23 @@ void Translator::DS_ADD_U32(const GcnInst& inst, bool rtn) { } } -void Translator::DS_MIN_U32(const GcnInst& inst, bool rtn) { +void Translator::DS_MIN_U32(const GcnInst& inst, bool is_signed, bool rtn) { const IR::U32 addr{GetSrc(inst.src[0])}; const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 addr_offset = ir.IAdd(addr, offset); - const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, false); + const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, is_signed); if (rtn) { SetDst(inst.dst[0], IR::U32{original_val}); } } -void Translator::DS_MAX_U32(const GcnInst& inst, bool rtn) { +void Translator::DS_MAX_U32(const GcnInst& inst, bool is_signed, bool rtn) { const IR::U32 addr{GetSrc(inst.src[0])}; const IR::U32 data{GetSrc(inst.src[1])}; const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); const IR::U32 addr_offset = ir.IAdd(addr, offset); - const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, false); + const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, is_signed); if (rtn) { SetDst(inst.dst[0], IR::U32{original_val}); } diff --git a/src/shader_recompiler/frontend/translate/export.cpp b/src/shader_recompiler/frontend/translate/export.cpp index 889de21b7..d80de002c 100644 --- a/src/shader_recompiler/frontend/translate/export.cpp +++ b/src/shader_recompiler/frontend/translate/export.cpp @@ -1,14 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" #include "shader_recompiler/frontend/translate/translate.h" namespace Shader::Gcn { void Translator::EmitExport(const GcnInst& inst) { if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) { - LOG_WARNING(Render_Recompiler, "An ambiguous export appeared in translation"); ir.Discard(ir.LogicalNot(ir.GetExec())); } diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index e59cd5656..e3482546b 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -354,7 +354,7 @@ void Translator::EmitFetch(const GcnInst& inst) { if (!std::filesystem::exists(dump_dir)) { std::filesystem::create_directories(dump_dir); } - const auto filename = fmt::format("vs_fetch_{:#018x}.bin", info.pgm_hash); + const auto filename = fmt::format("vs_{:#018x}_fetch.bin", info.pgm_hash); const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; file.WriteRaw(code, fetch_size); } @@ -399,9 +399,7 @@ void Translator::EmitFetch(const GcnInst& inst) { info.buffers.push_back({ .sgpr_base = attrib.sgpr_base, .dword_offset = attrib.dword_offset, - .length = buffer.num_records, .used_types = IR::Type::F32, - .is_storage = true, // we may not fit into UBO with large meshes .is_instance_data = true, }); instance_buf_handle = s32(info.buffers.size() - 1); diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 8cbf7357e..8d418421c 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -191,8 +191,10 @@ public: void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst); // Vector Memory - void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_format, const GcnInst& inst); - void BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_format, const GcnInst& inst); + void BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst); + void BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst); + void BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst); + void BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst); void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst); // Vector interpolation @@ -202,10 +204,10 @@ public: // Data share void DS_SWIZZLE_B32(const GcnInst& inst); void DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst); - void DS_WRITE(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst); + void DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst); void DS_ADD_U32(const GcnInst& inst, bool rtn); - void DS_MIN_U32(const GcnInst& inst, bool rtn); - void DS_MAX_U32(const GcnInst& inst, bool rtn); + void DS_MIN_U32(const GcnInst& inst, bool is_signed, bool rtn); + void DS_MAX_U32(const GcnInst& inst, bool is_signed, bool rtn); void V_READFIRSTLANE_B32(const GcnInst& inst); void V_READLANE_B32(const GcnInst& inst); void V_WRITELANE_B32(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 274dcff11..13a8342d3 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -415,14 +415,20 @@ void Translator::V_ADDC_U32(const GcnInst& inst) { const auto src0 = GetSrc(inst.src[0]); const auto src1 = GetSrc(inst.src[1]); - IR::U32 scarry; + IR::U1 carry; if (inst.src_count == 3) { // VOP3 - IR::U1 thread_bit{ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[2].code))}; - scarry = IR::U32{ir.Select(thread_bit, ir.Imm32(1), ir.Imm32(0))}; + if (inst.src[2].field == OperandField::VccLo) { + carry = ir.GetVcc(); + } else if (inst.src[2].field == OperandField::ScalarGPR) { + carry = ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[2].code)); + } else { + UNREACHABLE(); + } } else { // VOP2 - scarry = ir.GetVccLo(); + carry = ir.GetVcc(); } + const IR::U32 scarry = IR::U32{ir.Select(carry, ir.Imm32(1), ir.Imm32(0))}; const IR::U32 result = ir.IAdd(ir.IAdd(src0, src1), scarry); const IR::VectorReg dst_reg{inst.dst[0].code}; diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index b88cfc46c..73530dade 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -56,57 +56,57 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { // Buffer load operations case Opcode::TBUFFER_LOAD_FORMAT_X: - return BUFFER_LOAD_FORMAT(1, true, true, inst); + return BUFFER_LOAD(1, true, inst); case Opcode::TBUFFER_LOAD_FORMAT_XY: - return BUFFER_LOAD_FORMAT(2, true, true, inst); + return BUFFER_LOAD(2, true, inst); case Opcode::TBUFFER_LOAD_FORMAT_XYZ: - return BUFFER_LOAD_FORMAT(3, true, true, inst); + return BUFFER_LOAD(3, true, inst); case Opcode::TBUFFER_LOAD_FORMAT_XYZW: - return BUFFER_LOAD_FORMAT(4, true, true, inst); + return BUFFER_LOAD(4, true, inst); case Opcode::BUFFER_LOAD_FORMAT_X: - return BUFFER_LOAD_FORMAT(1, false, true, inst); + return BUFFER_LOAD_FORMAT(1, inst); case Opcode::BUFFER_LOAD_FORMAT_XY: - return BUFFER_LOAD_FORMAT(2, false, true, inst); + return BUFFER_LOAD_FORMAT(2, inst); case Opcode::BUFFER_LOAD_FORMAT_XYZ: - return BUFFER_LOAD_FORMAT(3, false, true, inst); + return BUFFER_LOAD_FORMAT(3, inst); case Opcode::BUFFER_LOAD_FORMAT_XYZW: - return BUFFER_LOAD_FORMAT(4, false, true, inst); + return BUFFER_LOAD_FORMAT(4, inst); case Opcode::BUFFER_LOAD_DWORD: - return BUFFER_LOAD_FORMAT(1, false, false, inst); + return BUFFER_LOAD(1, false, inst); case Opcode::BUFFER_LOAD_DWORDX2: - return BUFFER_LOAD_FORMAT(2, false, false, inst); + return BUFFER_LOAD(2, false, inst); case Opcode::BUFFER_LOAD_DWORDX3: - return BUFFER_LOAD_FORMAT(3, false, false, inst); + return BUFFER_LOAD(3, false, inst); case Opcode::BUFFER_LOAD_DWORDX4: - return BUFFER_LOAD_FORMAT(4, false, false, inst); + return BUFFER_LOAD(4, false, inst); // Buffer store operations case Opcode::BUFFER_STORE_FORMAT_X: - return BUFFER_STORE_FORMAT(1, false, true, inst); + return BUFFER_STORE_FORMAT(1, inst); case Opcode::BUFFER_STORE_FORMAT_XY: - return BUFFER_STORE_FORMAT(2, false, true, inst); + return BUFFER_STORE_FORMAT(2, inst); case Opcode::BUFFER_STORE_FORMAT_XYZ: - return BUFFER_STORE_FORMAT(3, false, true, inst); + return BUFFER_STORE_FORMAT(3, inst); case Opcode::BUFFER_STORE_FORMAT_XYZW: - return BUFFER_STORE_FORMAT(4, false, true, inst); + return BUFFER_STORE_FORMAT(4, inst); case Opcode::TBUFFER_STORE_FORMAT_X: - return BUFFER_STORE_FORMAT(1, true, true, inst); + return BUFFER_STORE(1, true, inst); case Opcode::TBUFFER_STORE_FORMAT_XY: - return BUFFER_STORE_FORMAT(2, true, true, inst); + return BUFFER_STORE(2, true, inst); case Opcode::TBUFFER_STORE_FORMAT_XYZ: - return BUFFER_STORE_FORMAT(3, true, true, inst); + return BUFFER_STORE(3, true, inst); case Opcode::BUFFER_STORE_DWORD: - return BUFFER_STORE_FORMAT(1, false, false, inst); + return BUFFER_STORE(1, false, inst); case Opcode::BUFFER_STORE_DWORDX2: - return BUFFER_STORE_FORMAT(2, false, false, inst); + return BUFFER_STORE(2, false, inst); case Opcode::BUFFER_STORE_DWORDX3: - return BUFFER_STORE_FORMAT(3, false, false, inst); + return BUFFER_STORE(3, false, inst); case Opcode::BUFFER_STORE_DWORDX4: - return BUFFER_STORE_FORMAT(4, false, false, inst); + return BUFFER_STORE(4, false, inst); // Buffer atomic operations case Opcode::BUFFER_ATOMIC_ADD: @@ -349,8 +349,7 @@ void Translator::IMAGE_STORE(const GcnInst& inst) { ir.ImageWrite(handle, body, value, {}); } -void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_format, - const GcnInst& inst) { +void Translator::BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst) { const auto& mtbuf = inst.control.mtbuf; const IR::VectorReg vaddr{inst.src[0].code}; const IR::ScalarReg sharp{inst.src[2].code * 4}; @@ -370,22 +369,19 @@ void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_forma info.index_enable.Assign(mtbuf.idxen); info.offset_enable.Assign(mtbuf.offen); info.inst_offset.Assign(mtbuf.offset); - info.is_typed.Assign(is_typed); if (is_typed) { - info.dmft.Assign(static_cast(mtbuf.dfmt)); - info.nfmt.Assign(static_cast(mtbuf.nfmt)); - ASSERT(info.nfmt == AmdGpu::NumberFormat::Float && - (info.dmft == AmdGpu::DataFormat::Format32_32_32_32 || - info.dmft == AmdGpu::DataFormat::Format32_32_32 || - info.dmft == AmdGpu::DataFormat::Format32_32 || - info.dmft == AmdGpu::DataFormat::Format32)); + const auto dmft = static_cast(mtbuf.dfmt); + const auto nfmt = static_cast(mtbuf.nfmt); + ASSERT(nfmt == AmdGpu::NumberFormat::Float && + (dmft == AmdGpu::DataFormat::Format32_32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32)); } const IR::Value handle = ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); - const IR::Value value = is_format ? ir.LoadBufferFormat(num_dwords, handle, address, info) - : ir.LoadBuffer(num_dwords, handle, address, info); + const IR::Value value = ir.LoadBuffer(num_dwords, handle, address, info); const IR::VectorReg dst_reg{inst.src[1].code}; if (num_dwords == 1) { ir.SetVectorReg(dst_reg, IR::F32{value}); @@ -396,8 +392,34 @@ void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_forma } } -void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_format, - const GcnInst& inst) { +void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst) { + const auto& mubuf = inst.control.mubuf; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::ScalarReg sharp{inst.src[2].code * 4}; + ASSERT_MSG(!mubuf.offen && mubuf.offset == 0, "Offsets for image buffers are not supported"); + const IR::Value address = [&] -> IR::Value { + if (mubuf.idxen) { + return ir.GetVectorReg(vaddr); + } + return {}; + }(); + const IR::Value soffset{GetSrc(inst.src[3])}; + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); + + IR::BufferInstInfo info{}; + info.index_enable.Assign(mubuf.idxen); + + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), + ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); + const IR::Value value = ir.LoadBufferFormat(handle, address, info); + const IR::VectorReg dst_reg{inst.src[1].code}; + for (u32 i = 0; i < num_dwords; i++) { + ir.SetVectorReg(dst_reg + i, IR::F32{ir.CompositeExtract(value, i)}); + } +} + +void Translator::BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst) { const auto& mtbuf = inst.control.mtbuf; const IR::VectorReg vaddr{inst.src[0].code}; const IR::ScalarReg sharp{inst.src[2].code * 4}; @@ -417,45 +439,76 @@ void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_form info.index_enable.Assign(mtbuf.idxen); info.offset_enable.Assign(mtbuf.offen); info.inst_offset.Assign(mtbuf.offset); - info.is_typed.Assign(is_typed); if (is_typed) { - info.dmft.Assign(static_cast(mtbuf.dfmt)); - info.nfmt.Assign(static_cast(mtbuf.nfmt)); + const auto dmft = static_cast(mtbuf.dfmt); + const auto nfmt = static_cast(mtbuf.nfmt); + ASSERT(nfmt == AmdGpu::NumberFormat::Float && + (dmft == AmdGpu::DataFormat::Format32_32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32)); } IR::Value value{}; const IR::VectorReg src_reg{inst.src[1].code}; switch (num_dwords) { case 1: - value = ir.GetVectorReg(src_reg); + value = ir.GetVectorReg(src_reg); break; case 2: - value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), - ir.GetVectorReg(src_reg + 1)); + value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), + ir.GetVectorReg(src_reg + 1)); break; case 3: - value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), - ir.GetVectorReg(src_reg + 1), - ir.GetVectorReg(src_reg + 2)); + value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), + ir.GetVectorReg(src_reg + 1), + ir.GetVectorReg(src_reg + 2)); break; case 4: - value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), - ir.GetVectorReg(src_reg + 1), - ir.GetVectorReg(src_reg + 2), - ir.GetVectorReg(src_reg + 3)); + value = ir.CompositeConstruct( + ir.GetVectorReg(src_reg), ir.GetVectorReg(src_reg + 1), + ir.GetVectorReg(src_reg + 2), ir.GetVectorReg(src_reg + 3)); break; } const IR::Value handle = ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); - if (is_format) { - ir.StoreBufferFormat(num_dwords, handle, address, value, info); - } else { - ir.StoreBuffer(num_dwords, handle, address, value, info); - } + ir.StoreBuffer(num_dwords, handle, address, value, info); +} + +void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst) { + const auto& mubuf = inst.control.mubuf; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::ScalarReg sharp{inst.src[2].code * 4}; + ASSERT_MSG(!mubuf.offen && mubuf.offset == 0, "Offsets for image buffers are not supported"); + const IR::Value address = [&] -> IR::Value { + if (mubuf.idxen) { + return ir.GetVectorReg(vaddr); + } + return {}; + }(); + const IR::Value soffset{GetSrc(inst.src[3])}; + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); + + IR::BufferInstInfo info{}; + info.index_enable.Assign(mubuf.idxen); + + const IR::VectorReg src_reg{inst.src[1].code}; + + std::array comps{}; + for (u32 i = 0; i < num_dwords; i++) { + comps[i] = ir.GetVectorReg(src_reg + i); + } + for (u32 i = num_dwords; i < 4; i++) { + comps[i] = ir.Imm32(0.f); + } + + const IR::Value value = ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]); + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), + ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); + ir.StoreBufferFormat(handle, address, value, info); } -// TODO: U64 void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) { const auto& mubuf = inst.control.mubuf; const IR::VectorReg vaddr{inst.src[0].code}; diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 65de98b7e..473ae4f66 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -325,20 +325,8 @@ Value IREmitter::LoadBuffer(int num_dwords, const Value& handle, const Value& ad } } -Value IREmitter::LoadBufferFormat(int num_dwords, const Value& handle, const Value& address, - BufferInstInfo info) { - switch (num_dwords) { - case 1: - return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address); - case 2: - return Inst(Opcode::LoadBufferFormatF32x2, Flags{info}, handle, address); - case 3: - return Inst(Opcode::LoadBufferFormatF32x3, Flags{info}, handle, address); - case 4: - return Inst(Opcode::LoadBufferFormatF32x4, Flags{info}, handle, address); - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } +Value IREmitter::LoadBufferFormat(const Value& handle, const Value& address, BufferInstInfo info) { + return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address); } void IREmitter::StoreBuffer(int num_dwords, const Value& handle, const Value& address, @@ -409,24 +397,9 @@ Value IREmitter::BufferAtomicSwap(const Value& handle, const Value& address, con return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value); } -void IREmitter::StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info) { - switch (num_dwords) { - case 1: - Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data); - break; - case 2: - Inst(Opcode::StoreBufferFormatF32x2, Flags{info}, handle, address, data); - break; - case 3: - Inst(Opcode::StoreBufferFormatF32x3, Flags{info}, handle, address, data); - break; - case 4: - Inst(Opcode::StoreBufferFormatF32x4, Flags{info}, handle, address, data); - break; - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } +void IREmitter::StoreBufferFormat(const Value& handle, const Value& address, const Value& data, + BufferInstInfo info) { + Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data); } U32 IREmitter::LaneId() { diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index a60f4c288..de8fe450d 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -92,12 +92,12 @@ public: [[nodiscard]] Value LoadBuffer(int num_dwords, const Value& handle, const Value& address, BufferInstInfo info); - [[nodiscard]] Value LoadBufferFormat(int num_dwords, const Value& handle, const Value& address, + [[nodiscard]] Value LoadBufferFormat(const Value& handle, const Value& address, BufferInstInfo info); void StoreBuffer(int num_dwords, const Value& handle, const Value& address, const Value& data, BufferInstInfo info); - void StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info); + void StoreBufferFormat(const Value& handle, const Value& address, const Value& data, + BufferInstInfo info); [[nodiscard]] Value BufferAtomicIAdd(const Value& handle, const Value& address, const Value& value, BufferInstInfo info); diff --git a/src/shader_recompiler/ir/microinstruction.cpp b/src/shader_recompiler/ir/microinstruction.cpp index a8c8b0737..d6ef49cf7 100644 --- a/src/shader_recompiler/ir/microinstruction.cpp +++ b/src/shader_recompiler/ir/microinstruction.cpp @@ -56,9 +56,6 @@ bool Inst::MayHaveSideEffects() const noexcept { case Opcode::StoreBufferF32x3: case Opcode::StoreBufferF32x4: case Opcode::StoreBufferFormatF32: - case Opcode::StoreBufferFormatF32x2: - case Opcode::StoreBufferFormatF32x3: - case Opcode::StoreBufferFormatF32x4: case Opcode::StoreBufferU32: case Opcode::BufferAtomicIAdd32: case Opcode::BufferAtomicSMin32: diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index a49ea1c77..1e33d6d45 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -79,19 +79,13 @@ OPCODE(LoadBufferF32, F32, Opaq OPCODE(LoadBufferF32x2, F32x2, Opaque, Opaque, ) OPCODE(LoadBufferF32x3, F32x3, Opaque, Opaque, ) OPCODE(LoadBufferF32x4, F32x4, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32, F32, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32x2, F32x2, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32x3, F32x3, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32x4, F32x4, Opaque, Opaque, ) +OPCODE(LoadBufferFormatF32, F32x4, Opaque, Opaque, ) OPCODE(LoadBufferU32, U32, Opaque, Opaque, ) OPCODE(StoreBufferF32, Void, Opaque, Opaque, F32, ) OPCODE(StoreBufferF32x2, Void, Opaque, Opaque, F32x2, ) OPCODE(StoreBufferF32x3, Void, Opaque, Opaque, F32x3, ) OPCODE(StoreBufferF32x4, Void, Opaque, Opaque, F32x4, ) -OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32, ) -OPCODE(StoreBufferFormatF32x2, Void, Opaque, Opaque, F32x2, ) -OPCODE(StoreBufferFormatF32x3, Void, Opaque, Opaque, F32x3, ) -OPCODE(StoreBufferFormatF32x4, Void, Opaque, Opaque, F32x4, ) +OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32x4, ) OPCODE(StoreBufferU32, Void, Opaque, Opaque, U32, ) // Buffer atomic operations diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index ace6a37d8..f446ac476 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -3,6 +3,7 @@ #include #include +#include "common/alignment.h" #include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/breadth_first_search.h" #include "shader_recompiler/ir/ir_emitter.h" @@ -45,10 +46,6 @@ bool IsBufferStore(const IR::Inst& inst) { case IR::Opcode::StoreBufferF32x2: case IR::Opcode::StoreBufferF32x3: case IR::Opcode::StoreBufferF32x4: - case IR::Opcode::StoreBufferFormatF32: - case IR::Opcode::StoreBufferFormatF32x2: - case IR::Opcode::StoreBufferFormatF32x3: - case IR::Opcode::StoreBufferFormatF32x4: case IR::Opcode::StoreBufferU32: return true; default: @@ -62,10 +59,6 @@ bool IsBufferInstruction(const IR::Inst& inst) { case IR::Opcode::LoadBufferF32x2: case IR::Opcode::LoadBufferF32x3: case IR::Opcode::LoadBufferF32x4: - case IR::Opcode::LoadBufferFormatF32: - case IR::Opcode::LoadBufferFormatF32x2: - case IR::Opcode::LoadBufferFormatF32x3: - case IR::Opcode::LoadBufferFormatF32x4: case IR::Opcode::LoadBufferU32: case IR::Opcode::ReadConstBuffer: case IR::Opcode::ReadConstBufferU32: @@ -75,6 +68,11 @@ bool IsBufferInstruction(const IR::Inst& inst) { } } +bool IsTextureBufferInstruction(const IR::Inst& inst) { + return inst.GetOpcode() == IR::Opcode::LoadBufferFormatF32 || + inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32; +} + static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { switch (num_format) { case AmdGpu::NumberFormat::Float: @@ -100,28 +98,6 @@ static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_for IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) { switch (inst.GetOpcode()) { - case IR::Opcode::LoadBufferFormatF32: - case IR::Opcode::LoadBufferFormatF32x2: - case IR::Opcode::LoadBufferFormatF32x3: - case IR::Opcode::LoadBufferFormatF32x4: - case IR::Opcode::StoreBufferFormatF32: - case IR::Opcode::StoreBufferFormatF32x2: - case IR::Opcode::StoreBufferFormatF32x3: - case IR::Opcode::StoreBufferFormatF32x4: - switch (num_format) { - case AmdGpu::NumberFormat::Unorm: - case AmdGpu::NumberFormat::Snorm: - case AmdGpu::NumberFormat::Uscaled: - case AmdGpu::NumberFormat::Sscaled: - case AmdGpu::NumberFormat::Uint: - case AmdGpu::NumberFormat::Sint: - case AmdGpu::NumberFormat::SnormNz: - return IR::Type::U32; - case AmdGpu::NumberFormat::Float: - return IR::Type::F32; - default: - UNREACHABLE(); - } case IR::Opcode::LoadBufferF32: case IR::Opcode::LoadBufferF32x2: case IR::Opcode::LoadBufferF32x3: @@ -143,20 +119,8 @@ IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) { } } -bool IsImageInstruction(const IR::Inst& inst) { +bool IsImageAtomicInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { - case IR::Opcode::ImageSampleExplicitLod: - case IR::Opcode::ImageSampleImplicitLod: - case IR::Opcode::ImageSampleDrefExplicitLod: - case IR::Opcode::ImageSampleDrefImplicitLod: - case IR::Opcode::ImageFetch: - case IR::Opcode::ImageGather: - case IR::Opcode::ImageGatherDref: - case IR::Opcode::ImageQueryDimensions: - case IR::Opcode::ImageQueryLod: - case IR::Opcode::ImageGradient: - case IR::Opcode::ImageRead: - case IR::Opcode::ImageWrite: case IR::Opcode::ImageAtomicIAdd32: case IR::Opcode::ImageAtomicSMin32: case IR::Opcode::ImageAtomicUMin32: @@ -178,20 +142,27 @@ bool IsImageStorageInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::ImageWrite: case IR::Opcode::ImageRead: - case IR::Opcode::ImageAtomicIAdd32: - case IR::Opcode::ImageAtomicSMin32: - case IR::Opcode::ImageAtomicUMin32: - case IR::Opcode::ImageAtomicSMax32: - case IR::Opcode::ImageAtomicUMax32: - case IR::Opcode::ImageAtomicInc32: - case IR::Opcode::ImageAtomicDec32: - case IR::Opcode::ImageAtomicAnd32: - case IR::Opcode::ImageAtomicOr32: - case IR::Opcode::ImageAtomicXor32: - case IR::Opcode::ImageAtomicExchange32: return true; default: - return false; + return IsImageAtomicInstruction(inst); + } +} + +bool IsImageInstruction(const IR::Inst& inst) { + switch (inst.GetOpcode()) { + case IR::Opcode::ImageSampleExplicitLod: + case IR::Opcode::ImageSampleImplicitLod: + case IR::Opcode::ImageSampleDrefExplicitLod: + case IR::Opcode::ImageSampleDrefImplicitLod: + case IR::Opcode::ImageFetch: + case IR::Opcode::ImageGather: + case IR::Opcode::ImageGatherDref: + case IR::Opcode::ImageQueryDimensions: + case IR::Opcode::ImageQueryLod: + case IR::Opcode::ImageGradient: + return true; + default: + return IsImageStorageInstruction(inst); } } @@ -214,7 +185,8 @@ u32 ImageOffsetArgumentPosition(const IR::Inst& inst) { class Descriptors { public: explicit Descriptors(Info& info_) - : info{info_}, buffer_resources{info_.buffers}, image_resources{info_.images}, + : info{info_}, buffer_resources{info_.buffers}, + texture_buffer_resources{info_.texture_buffers}, image_resources{info_.images}, sampler_resources{info_.samplers} {} u32 Add(const BufferResource& desc) { @@ -224,13 +196,21 @@ public: desc.inline_cbuf == existing.inline_cbuf; })}; auto& buffer = buffer_resources[index]; - ASSERT(buffer.length == desc.length); - buffer.is_storage |= desc.is_storage; buffer.used_types |= desc.used_types; buffer.is_written |= desc.is_written; return index; } + u32 Add(const TextureBufferResource& desc) { + const u32 index{Add(texture_buffer_resources, desc, [&desc](const auto& existing) { + return desc.sgpr_base == existing.sgpr_base && + desc.dword_offset == existing.dword_offset; + })}; + auto& buffer = texture_buffer_resources[index]; + buffer.is_written |= desc.is_written; + return index; + } + u32 Add(const ImageResource& desc) { const u32 index{Add(image_resources, desc, [&desc](const auto& existing) { return desc.sgpr_base == existing.sgpr_base && @@ -247,7 +227,7 @@ public: return true; } // Samplers with different bindings might still be the same. - return existing.GetSsharp(info) == desc.GetSsharp(info); + return existing.GetSharp(info) == desc.GetSharp(info); })}; return index; } @@ -265,6 +245,7 @@ private: const Info& info; BufferResourceList& buffer_resources; + TextureBufferResourceList& texture_buffer_resources; ImageResourceList& image_resources; SamplerResourceList& sampler_resources; }; @@ -361,33 +342,6 @@ SharpLocation TrackSharp(const IR::Inst* inst) { }; } -static constexpr size_t MaxUboSize = 65536; - -static bool IsLoadBufferFormat(const IR::Inst& inst) { - switch (inst.GetOpcode()) { - case IR::Opcode::LoadBufferFormatF32: - case IR::Opcode::LoadBufferFormatF32x2: - case IR::Opcode::LoadBufferFormatF32x3: - case IR::Opcode::LoadBufferFormatF32x4: - return true; - default: - return false; - } -} - -static u32 BufferLength(const AmdGpu::Buffer& buffer) { - const auto stride = buffer.GetStride(); - if (stride < sizeof(f32)) { - ASSERT(sizeof(f32) % stride == 0); - return (((buffer.num_records - 1) / sizeof(f32)) + 1) * stride; - } else if (stride == sizeof(f32)) { - return buffer.num_records; - } else { - ASSERT(stride % sizeof(f32) == 0); - return buffer.num_records * (stride / sizeof(f32)); - } -} - s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, AmdGpu::Buffer& cbuf) { @@ -414,10 +368,8 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, return descriptors.Add(BufferResource{ .sgpr_base = std::numeric_limits::max(), .dword_offset = 0, - .length = BufferLength(cbuf), .used_types = BufferDataType(inst, cbuf.GetNumberFmt()), .inline_cbuf = cbuf, - .is_storage = IsBufferStore(inst) || cbuf.GetSize() > MaxUboSize, }); } @@ -429,28 +381,17 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, IR::Inst* handle = inst.Arg(0).InstRecursive(); IR::Inst* producer = handle->Arg(0).InstRecursive(); const auto sharp = TrackSharp(producer); - const bool is_store = IsBufferStore(inst); buffer = info.ReadUd(sharp.sgpr_base, sharp.dword_offset); binding = descriptors.Add(BufferResource{ .sgpr_base = sharp.sgpr_base, .dword_offset = sharp.dword_offset, - .length = BufferLength(buffer), .used_types = BufferDataType(inst, buffer.GetNumberFmt()), - .is_storage = is_store || buffer.GetSize() > MaxUboSize, - .is_written = is_store, + .is_written = IsBufferStore(inst), }); } // Update buffer descriptor format. const auto inst_info = inst.Flags(); - auto& buffer_desc = info.buffers[binding]; - if (inst_info.is_typed) { - buffer_desc.dfmt = inst_info.dmft; - buffer_desc.nfmt = inst_info.nfmt; - } else { - buffer_desc.dfmt = buffer.GetDataFmt(); - buffer_desc.nfmt = buffer.GetNumberFmt(); - } // Replace handle with binding index in buffer resource list. IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; @@ -463,20 +404,7 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, return; } - if (IsLoadBufferFormat(inst)) { - if (UseFP16(buffer.GetDataFmt(), buffer.GetNumberFmt())) { - info.uses_fp16 = true; - } - } else { - const u32 stride = buffer.GetStride(); - if (stride < 4) { - LOG_WARNING(Render_Vulkan, - "non-formatting load_buffer_* is not implemented for stride {}", stride); - } - } - // Compute address of the buffer using the stride. - // Todo: What if buffer is rebound with different stride? IR::U32 address = ir.Imm32(inst_info.inst_offset.Value()); if (inst_info.index_enable) { const IR::U32 index = inst_info.offset_enable ? IR::U32{ir.CompositeExtract(inst.Arg(1), 0)} @@ -491,8 +419,31 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, inst.SetArg(1, address); } +void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, + Descriptors& descriptors) { + const IR::Inst* handle = inst.Arg(0).InstRecursive(); + const IR::Inst* producer = handle->Arg(0).InstRecursive(); + const auto sharp = TrackSharp(producer); + const auto buffer = info.ReadUd(sharp.sgpr_base, sharp.dword_offset); + const s32 binding = descriptors.Add(TextureBufferResource{ + .sgpr_base = sharp.sgpr_base, + .dword_offset = sharp.dword_offset, + .nfmt = buffer.GetNumberFmt(), + .is_written = inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32, + }); + + // Replace handle with binding index in texture buffer resource list. + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + inst.SetArg(0, ir.Imm32(binding)); + ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable); +} + IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t, - const IR::Value& z) { + const IR::Value& z, bool is_storage) { + // When cubemap is written with imageStore it is treated like 2DArray. + if (is_storage) { + return ir.CompositeConstruct(s, t, z); + } // We need to fix x and y coordinate, // because the s and t coordinate will be scaled and plus 1.5 by v_madak_f32. // We already force the scale value to be 1.0 when handling v_cubema_f32, @@ -530,13 +481,15 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip return; } ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); + const bool is_storage = IsImageStorageInstruction(inst); u32 image_binding = descriptors.Add(ImageResource{ .sgpr_base = tsharp.sgpr_base, .dword_offset = tsharp.dword_offset, .type = image.GetType(), .nfmt = static_cast(image.GetNumberFmt()), - .is_storage = IsImageStorageInstruction(inst), + .is_storage = is_storage, .is_depth = bool(inst_info.is_depth), + .is_atomic = IsImageAtomicInstruction(inst), }); // Read sampler sharp. This doesn't exist for IMAGE_LOAD/IMAGE_STORE instructions @@ -593,7 +546,8 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip case AmdGpu::ImageType::Color3D: // x, y, z return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; case AmdGpu::ImageType::Cube: // x, y, face - return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; + return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_storage), + body->Arg(3)}; default: UNREACHABLE_MSG("Unknown image type {}", image.GetType()); } @@ -668,6 +622,10 @@ void ResourceTrackingPass(IR::Program& program) { PatchBufferInstruction(*block, inst, info, descriptors); continue; } + if (IsTextureBufferInstruction(inst)) { + PatchTextureBufferInstruction(*block, inst, info, descriptors); + continue; + } if (IsImageInstruction(inst)) { PatchImageInstruction(*block, inst, info, descriptors); } 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 52087a653..7105f01f1 100644 --- a/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp +++ b/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp @@ -29,6 +29,12 @@ void Visit(Info& info, IR::Inst& inst) { case IR::Opcode::ImageWrite: info.has_storage_images = true; break; + case IR::Opcode::LoadBufferFormatF32: + info.has_texel_buffers = true; + break; + case IR::Opcode::StoreBufferFormatF32: + info.has_image_buffers = true; + break; case IR::Opcode::QuadShuffle: info.uses_group_quad = true; break; @@ -44,6 +50,9 @@ void Visit(Info& info, IR::Inst& inst) { case IR::Opcode::ImageQueryLod: info.has_image_query = true; break; + case IR::Opcode::LaneId: + info.uses_lane_id = true; + break; default: break; } diff --git a/src/shader_recompiler/ir/program.h b/src/shader_recompiler/ir/program.h index eff933f28..f7abba641 100644 --- a/src/shader_recompiler/ir/program.h +++ b/src/shader_recompiler/ir/program.h @@ -12,11 +12,13 @@ namespace Shader::IR { struct Program { + explicit Program(Info& info_) : info{info_} {} + AbstractSyntaxList syntax_list; BlockList blocks; BlockList post_order_blocks; std::vector ins_list; - Info info; + Info& info; }; [[nodiscard]] std::string DumpProgram(const Program& program); diff --git a/src/shader_recompiler/ir/reg.h b/src/shader_recompiler/ir/reg.h index 7868a5a3b..fba04f33e 100644 --- a/src/shader_recompiler/ir/reg.h +++ b/src/shader_recompiler/ir/reg.h @@ -66,9 +66,6 @@ union BufferInstInfo { BitField<0, 1, u32> index_enable; BitField<1, 1, u32> offset_enable; BitField<2, 12, u32> inst_offset; - BitField<14, 4, AmdGpu::DataFormat> dmft; - BitField<18, 3, AmdGpu::NumberFormat> nfmt; - BitField<21, 1, u32> is_typed; }; enum class ScalarReg : u32 { diff --git a/src/shader_recompiler/recompiler.cpp b/src/shader_recompiler/recompiler.cpp index 0efac4ff1..dfcf9ed1b 100644 --- a/src/shader_recompiler/recompiler.cpp +++ b/src/shader_recompiler/recompiler.cpp @@ -29,7 +29,7 @@ IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { IR::Program TranslateProgram(Common::ObjectPool& inst_pool, Common::ObjectPool& block_pool, std::span token, - const Info&& info, const Profile& profile) { + Info& info, const Profile& profile) { // Ensure first instruction is expected. constexpr u32 token_mov_vcchi = 0xBEEB03FF; ASSERT_MSG(token[0] == token_mov_vcchi, "First instruction is not s_mov_b32 vcc_hi, #imm"); @@ -38,7 +38,7 @@ IR::Program TranslateProgram(Common::ObjectPool& inst_pool, Gcn::GcnDecodeContext decoder; // Decode and save instructions - IR::Program program; + IR::Program program{info}; program.ins_list.reserve(token.size()); while (!slice.atEnd()) { program.ins_list.emplace_back(decoder.decodeInstruction(slice)); @@ -49,7 +49,6 @@ IR::Program TranslateProgram(Common::ObjectPool& inst_pool, Gcn::CFG cfg{gcn_block_pool, program.ins_list}; // Structurize control flow graph and create program. - program.info = std::move(info); program.syntax_list = Shader::Gcn::BuildASL(inst_pool, block_pool, cfg, program.info, profile); program.blocks = GenerateBlocks(program.syntax_list); program.post_order_blocks = Shader::IR::PostOrder(program.syntax_list.front()); diff --git a/src/shader_recompiler/recompiler.h b/src/shader_recompiler/recompiler.h index 34e958a15..3a2295189 100644 --- a/src/shader_recompiler/recompiler.h +++ b/src/shader_recompiler/recompiler.h @@ -13,7 +13,7 @@ struct Profile; [[nodiscard]] IR::Program TranslateProgram(Common::ObjectPool& inst_pool, Common::ObjectPool& block_pool, - std::span code, const Info&& info, + std::span code, Info& info, const Profile& profile); } // namespace Shader diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 7d36dbe1b..77c57e947 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "common/assert.h" #include "common/types.h" @@ -74,18 +75,29 @@ struct Info; struct BufferResource { u32 sgpr_base; u32 dword_offset; - u32 length; IR::Type used_types; AmdGpu::Buffer inline_cbuf; - AmdGpu::DataFormat dfmt; - AmdGpu::NumberFormat nfmt; - bool is_storage{}; bool is_instance_data{}; bool is_written{}; - constexpr AmdGpu::Buffer GetVsharp(const Info& info) const noexcept; + bool IsStorage(AmdGpu::Buffer buffer) const noexcept { + static constexpr size_t MaxUboSize = 65536; + return buffer.GetSize() > MaxUboSize || is_written; + } + + constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; }; -using BufferResourceList = boost::container::static_vector; +using BufferResourceList = boost::container::small_vector; + +struct TextureBufferResource { + u32 sgpr_base; + u32 dword_offset; + AmdGpu::NumberFormat nfmt; + bool is_written{}; + + constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; +}; +using TextureBufferResourceList = boost::container::small_vector; struct ImageResource { u32 sgpr_base; @@ -94,8 +106,11 @@ struct ImageResource { AmdGpu::NumberFormat nfmt; bool is_storage; bool is_depth; + bool is_atomic{}; + + constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; }; -using ImageResourceList = boost::container::static_vector; +using ImageResourceList = boost::container::small_vector; struct SamplerResource { u32 sgpr_base; @@ -104,9 +119,9 @@ struct SamplerResource { u32 associated_image : 4; u32 disable_aniso : 1; - constexpr AmdGpu::Sampler GetSsharp(const Info& info) const noexcept; + constexpr AmdGpu::Sampler GetSharp(const Info& info) const noexcept; }; -using SamplerResourceList = boost::container::static_vector; +using SamplerResourceList = boost::container::small_vector; struct PushData { static constexpr size_t BufOffsetIndex = 2; @@ -179,6 +194,7 @@ struct Info { s8 instance_offset_sgpr = -1; BufferResourceList buffers; + TextureBufferResourceList texture_buffers; ImageResourceList images; SamplerResourceList samplers; @@ -194,9 +210,12 @@ struct Info { u64 pgm_hash{}; u32 shared_memory_size{}; bool has_storage_images{}; + bool has_image_buffers{}; + bool has_texel_buffers{}; bool has_discard{}; bool has_image_gather{}; bool has_image_query{}; + bool uses_lane_id{}; bool uses_group_quad{}; bool uses_shared{}; bool uses_fp16{}; @@ -214,6 +233,10 @@ struct Info { return data; } + size_t NumBindings() const noexcept { + return buffers.size() + texture_buffers.size() + images.size() + samplers.size(); + } + [[nodiscard]] std::pair GetDrawOffsets() const noexcept { u32 vertex_offset = 0; u32 instance_offset = 0; @@ -227,11 +250,19 @@ struct Info { } }; -constexpr AmdGpu::Buffer BufferResource::GetVsharp(const Info& info) const noexcept { +constexpr AmdGpu::Buffer BufferResource::GetSharp(const Info& info) const noexcept { return inline_cbuf ? inline_cbuf : info.ReadUd(sgpr_base, dword_offset); } -constexpr AmdGpu::Sampler SamplerResource::GetSsharp(const Info& info) const noexcept { +constexpr AmdGpu::Buffer TextureBufferResource::GetSharp(const Info& info) const noexcept { + return info.ReadUd(sgpr_base, dword_offset); +} + +constexpr AmdGpu::Image ImageResource::GetSharp(const Info& info) const noexcept { + return info.ReadUd(sgpr_base, dword_offset); +} + +constexpr AmdGpu::Sampler SamplerResource::GetSharp(const Info& info) const noexcept { return inline_sampler ? inline_sampler : info.ReadUd(sgpr_base, dword_offset); } diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 7b38ca79f..7f262e1f4 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -167,7 +167,7 @@ struct Liverpool { static constexpr auto* GetBinaryInfo(const Shader& sh) { const auto* code = sh.template Address(); const auto* bininfo = std::bit_cast(code + (code[1] + 1) * 2); - ASSERT_MSG(bininfo->Valid(), "Invalid shader binary header"); + // ASSERT_MSG(bininfo->Valid(), "Invalid shader binary header"); return bininfo; } diff --git a/src/video_core/amdgpu/pixel_format.h b/src/video_core/amdgpu/pixel_format.h index 1004ed7d2..53d30a7fd 100644 --- a/src/video_core/amdgpu/pixel_format.h +++ b/src/video_core/amdgpu/pixel_format.h @@ -61,6 +61,10 @@ enum class NumberFormat : u32 { Ubscaled = 13, }; +[[nodiscard]] constexpr bool IsInteger(NumberFormat nfmt) { + return nfmt == AmdGpu::NumberFormat::Sint || nfmt == AmdGpu::NumberFormat::Uint; +} + [[nodiscard]] std::string_view NameOf(DataFormat fmt); [[nodiscard]] std::string_view NameOf(NumberFormat fmt); diff --git a/src/video_core/amdgpu/resource.h b/src/video_core/amdgpu/resource.h index 8c3b675ea..b85a3788b 100644 --- a/src/video_core/amdgpu/resource.h +++ b/src/video_core/amdgpu/resource.h @@ -3,6 +3,7 @@ #pragma once +#include "common/alignment.h" #include "common/assert.h" #include "common/bit_field.h" #include "common/types.h" @@ -68,6 +69,10 @@ struct Buffer { return stride == 0 ? 1U : stride; } + u32 NumDwords() const noexcept { + return Common::AlignUp(GetSize(), sizeof(u32)) >> 2; + } + u32 GetSize() const noexcept { return GetStride() * num_records; } diff --git a/src/video_core/buffer_cache/buffer.cpp b/src/video_core/buffer_cache/buffer.cpp index e9dceb624..68a4aa52f 100644 --- a/src/video_core/buffer_cache/buffer.cpp +++ b/src/video_core/buffer_cache/buffer.cpp @@ -13,13 +13,6 @@ namespace VideoCore { -constexpr vk::BufferUsageFlags AllFlags = - vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst | - vk::BufferUsageFlagBits::eUniformTexelBuffer | vk::BufferUsageFlagBits::eStorageTexelBuffer | - vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eStorageBuffer | - vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eVertexBuffer | - vk::BufferUsageFlagBits::eIndirectBuffer; - std::string_view BufferTypeName(MemoryUsage type) { switch (type) { case MemoryUsage::Upload: @@ -96,13 +89,13 @@ void UniqueBuffer::Create(const vk::BufferCreateInfo& buffer_ci, MemoryUsage usa } Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_addr_, - u64 size_bytes_) + vk::BufferUsageFlags flags, u64 size_bytes_) : cpu_addr{cpu_addr_}, size_bytes{size_bytes_}, instance{&instance_}, usage{usage_}, buffer{instance->GetDevice(), instance->GetAllocator()} { // Create buffer object. const vk::BufferCreateInfo buffer_ci = { .size = size_bytes, - .usage = AllFlags, + .usage = flags, }; VmaAllocationInfo alloc_info{}; buffer.Create(buffer_ci, usage, &alloc_info); @@ -119,25 +112,33 @@ Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_ is_coherent = property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; } -vk::BufferView Buffer::View(u32 offset, u32 size, AmdGpu::DataFormat dfmt, +vk::BufferView Buffer::View(u32 offset, u32 size, bool is_written, AmdGpu::DataFormat dfmt, AmdGpu::NumberFormat nfmt) { - const auto it{std::ranges::find_if(views, [offset, size, dfmt, nfmt](const BufferView& view) { - return offset == view.offset && size == view.size && dfmt == view.dfmt && nfmt == view.nfmt; + const auto it{std::ranges::find_if(views, [=](const BufferView& view) { + return offset == view.offset && size == view.size && is_written == view.is_written && + dfmt == view.dfmt && nfmt == view.nfmt; })}; if (it != views.end()) { return it->handle; } + const vk::BufferUsageFlags2CreateInfoKHR usage_flags = { + .usage = is_written ? vk::BufferUsageFlagBits2KHR::eStorageTexelBuffer + : vk::BufferUsageFlagBits2KHR::eUniformTexelBuffer, + }; + const vk::BufferViewCreateInfo view_ci = { + .pNext = &usage_flags, + .buffer = buffer.buffer, + .format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt), + .offset = offset, + .range = size, + }; views.push_back({ .offset = offset, .size = size, + .is_written = is_written, .dfmt = dfmt, .nfmt = nfmt, - .handle = instance->GetDevice().createBufferView({ - .buffer = buffer.buffer, - .format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt), - .offset = offset, - .range = size, - }), + .handle = instance->GetDevice().createBufferView(view_ci), }); return views.back().handle; } @@ -147,7 +148,7 @@ constexpr u64 WATCHES_RESERVE_CHUNK = 0x1000; StreamBuffer::StreamBuffer(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler_, MemoryUsage usage, u64 size_bytes) - : Buffer{instance, usage, 0, size_bytes}, scheduler{scheduler_} { + : Buffer{instance, usage, 0, AllFlags, size_bytes}, scheduler{scheduler_} { ReserveWatches(current_watches, WATCHES_INITIAL_RESERVE); ReserveWatches(previous_watches, WATCHES_INITIAL_RESERVE); const auto device = instance.GetDevice(); diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index 87293c768..7bcd06094 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -31,6 +31,15 @@ enum class MemoryUsage { Stream, ///< Requests device local host visible buffer, falling back host memory. }; +constexpr vk::BufferUsageFlags ReadFlags = + vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eUniformTexelBuffer | + vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eIndexBuffer | + vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eIndirectBuffer; + +constexpr vk::BufferUsageFlags AllFlags = ReadFlags | vk::BufferUsageFlagBits::eTransferDst | + vk::BufferUsageFlagBits::eStorageTexelBuffer | + vk::BufferUsageFlagBits::eStorageBuffer; + struct UniqueBuffer { explicit UniqueBuffer(vk::Device device, VmaAllocator allocator); ~UniqueBuffer(); @@ -65,7 +74,7 @@ struct UniqueBuffer { class Buffer { public: explicit Buffer(const Vulkan::Instance& instance, MemoryUsage usage, VAddr cpu_addr_, - u64 size_bytes_); + vk::BufferUsageFlags flags, u64 size_bytes_); Buffer& operator=(const Buffer&) = delete; Buffer(const Buffer&) = delete; @@ -73,7 +82,8 @@ public: Buffer& operator=(Buffer&&) = default; Buffer(Buffer&&) = default; - vk::BufferView View(u32 offset, u32 size, AmdGpu::DataFormat dfmt, AmdGpu::NumberFormat nfmt); + vk::BufferView View(u32 offset, u32 size, bool is_written, AmdGpu::DataFormat dfmt, + AmdGpu::NumberFormat nfmt); /// Increases the likeliness of this being a stream buffer void IncreaseStreamScore(int score) noexcept { @@ -121,6 +131,7 @@ public: struct BufferView { u32 offset; u32 size; + bool is_written; AmdGpu::DataFormat dfmt; AmdGpu::NumberFormat nfmt; vk::BufferView handle; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 02d6b2ce4..b838989fd 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -23,7 +23,7 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s stream_buffer{instance, scheduler, MemoryUsage::Stream, UboStreamBufferSize}, memory_tracker{&tracker} { // Ensure the first slot is used for the null buffer - void(slot_buffers.insert(instance, MemoryUsage::DeviceLocal, 0, 1)); + void(slot_buffers.insert(instance, MemoryUsage::DeviceLocal, 0, ReadFlags, 1)); } BufferCache::~BufferCache() = default; @@ -421,7 +421,7 @@ BufferId BufferCache::CreateBuffer(VAddr device_addr, u32 wanted_size) { const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size); const u32 size = static_cast(overlap.end - overlap.begin); const BufferId new_buffer_id = - slot_buffers.insert(instance, MemoryUsage::DeviceLocal, overlap.begin, size); + slot_buffers.insert(instance, MemoryUsage::DeviceLocal, overlap.begin, AllFlags, size); auto& new_buffer = slot_buffers[new_buffer_id]; const size_t size_bytes = new_buffer.SizeBytes(); const auto cmdbuf = scheduler.CommandBuffer(); @@ -495,7 +495,8 @@ bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size) } else { // For large one time transfers use a temporary host buffer. // RenderDoc can lag quite a bit if the stream buffer is too large. - Buffer temp_buffer{instance, MemoryUsage::Upload, 0, total_size_bytes}; + Buffer temp_buffer{instance, MemoryUsage::Upload, 0, vk::BufferUsageFlagBits::eTransferSrc, + total_size_bytes}; src_buffer = temp_buffer.Handle(); u8* const staging = temp_buffer.mapped_data.data(); for (auto& copy : copies) { diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 81cf9c02a..e62c1040f 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -13,22 +13,31 @@ namespace Vulkan { ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler_, vk::PipelineCache pipeline_cache, u64 compute_key_, - const Program* program) - : instance{instance_}, scheduler{scheduler_}, compute_key{compute_key_}, - info{&program->pgm.info} { + const Shader::Info& info_, vk::ShaderModule module) + : instance{instance_}, scheduler{scheduler_}, compute_key{compute_key_}, info{&info_} { const vk::PipelineShaderStageCreateInfo shader_ci = { .stage = vk::ShaderStageFlagBits::eCompute, - .module = program->module, + .module = module, .pName = "main", }; u32 binding{}; boost::container::small_vector bindings; for (const auto& buffer : info->buffers) { + const auto sharp = buffer.GetSharp(*info); bindings.push_back({ .binding = binding++, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = buffer.IsStorage(sharp) ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, + .descriptorCount = 1, + .stageFlags = vk::ShaderStageFlagBits::eCompute, + }); + } + for (const auto& tex_buffer : info->texture_buffers) { + bindings.push_back({ + .binding = binding++, + .descriptorType = tex_buffer.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, .descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute, }); @@ -91,22 +100,24 @@ ComputePipeline::~ComputePipeline() = default; bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, VideoCore::TextureCache& texture_cache) const { // Bind resource buffers and textures. + boost::container::static_vector buffer_views; boost::container::static_vector buffer_infos; boost::container::static_vector image_infos; boost::container::small_vector set_writes; Shader::PushData push_data{}; u32 binding{}; - for (const auto& buffer : info->buffers) { - const auto vsharp = buffer.GetVsharp(*info); + for (const auto& desc : info->buffers) { + const auto vsharp = desc.GetSharp(*info); + const bool is_storage = desc.IsStorage(vsharp); const VAddr address = vsharp.base_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 (buffer.is_storage) { + if (desc.is_written) { if (texture_cache.TouchMeta(address, true)) { - LOG_WARNING(Render_Vulkan, "Metadata update skipped"); + LOG_TRACE(Render_Vulkan, "Metadata update skipped"); return false; } } else { @@ -115,13 +126,12 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } } const u32 size = vsharp.GetSize(); - if (buffer.is_written) { + if (desc.is_written) { texture_cache.InvalidateMemory(address, size, true); } const u32 alignment = - buffer.is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); - const auto [vk_buffer, offset] = - buffer_cache.ObtainBuffer(address, size, buffer.is_written); + is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); + const auto [vk_buffer, offset] = buffer_cache.ObtainBuffer(address, size, desc.is_written); const u32 offset_aligned = Common::AlignDown(offset, alignment); const u32 adjust = offset - offset_aligned; if (adjust != 0) { @@ -134,20 +144,68 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, .dstBinding = binding++, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, .pBufferInfo = &buffer_infos.back(), }); } + for (const auto& desc : info->texture_buffers) { + const auto vsharp = desc.GetSharp(*info); + vk::BufferView& buffer_view = buffer_views.emplace_back(VK_NULL_HANDLE); + if (vsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) { + const VAddr address = vsharp.base_address; + const u32 size = vsharp.GetSize(); + if (desc.is_written) { + if (texture_cache.TouchMeta(address, true)) { + 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 (desc.is_written) { + texture_cache.InvalidateMemory(address, size, true); + } + const u32 alignment = instance.TexelBufferMinAlignment(); + const auto [vk_buffer, offset] = + buffer_cache.ObtainBuffer(address, size, desc.is_written); + const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; + ASSERT_MSG(fmt_stride == vsharp.GetStride(), + "Texel buffer stride must match format stride"); + const u32 offset_aligned = Common::AlignDown(offset, alignment); + const u32 adjust = offset - offset_aligned; + if (adjust != 0) { + ASSERT(adjust % fmt_stride == 0); + push_data.AddOffset(binding, adjust / fmt_stride); + } + buffer_view = vk_buffer->View(offset_aligned, size + adjust, desc.is_written, + vsharp.GetDataFmt(), vsharp.GetNumberFmt()); + } + set_writes.push_back({ + .dstSet = VK_NULL_HANDLE, + .dstBinding = binding++, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = desc.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, + .pTexelBufferView = &buffer_view, + }); + } + for (const auto& image_desc : info->images) { - const auto tsharp = - info->ReadUd(image_desc.sgpr_base, image_desc.dword_offset); - VideoCore::ImageInfo image_info{tsharp}; - VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; - const auto& image_view = texture_cache.FindTexture(image_info, view_info); - const auto& image = texture_cache.GetImage(image_view.image_id); - image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); + const auto tsharp = image_desc.GetSharp(*info); + if (tsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) { + VideoCore::ImageInfo image_info{tsharp}; + VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; + const auto& image_view = texture_cache.FindTexture(image_info, view_info); + const auto& image = texture_cache.GetImage(image_view.image_id); + image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); + } else { + image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); + } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, .dstBinding = binding++, @@ -163,7 +221,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } } for (const auto& sampler : info->samplers) { - const auto ssharp = sampler.GetSsharp(*info); + const auto ssharp = sampler.GetSharp(*info); const auto vk_sampler = texture_cache.GetSampler(ssharp); image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); set_writes.push_back({ diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 5da9dc7e7..0132066c5 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h @@ -3,7 +3,7 @@ #pragma once -#include "shader_recompiler/ir/program.h" +#include #include "shader_recompiler/runtime_info.h" #include "video_core/renderer_vulkan/vk_common.h" @@ -17,18 +17,11 @@ namespace Vulkan { class Instance; class Scheduler; -struct Program { - Shader::IR::Program pgm; - std::vector spv; - vk::ShaderModule module; - u32 end_binding; -}; - class ComputePipeline { public: explicit ComputePipeline(const Instance& instance, Scheduler& scheduler, vk::PipelineCache pipeline_cache, u64 compute_key, - const Program* program); + const Shader::Info& info, vk::ShaderModule module); ~ComputePipeline(); [[nodiscard]] vk::Pipeline Handle() const noexcept { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 5623e431c..719a911a4 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -19,15 +19,11 @@ namespace Vulkan { GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& scheduler_, const GraphicsPipelineKey& key_, vk::PipelineCache pipeline_cache, - std::span programs) + std::span infos, + std::span modules) : instance{instance_}, scheduler{scheduler_}, key{key_} { const vk::Device device = instance.GetDevice(); - for (u32 i = 0; i < MaxShaderStages; i++) { - if (!programs[i]) { - continue; - } - stages[i] = &programs[i]->pgm.info; - } + std::ranges::copy(infos, stages.begin()); BuildDescSetLayout(); const vk::PushConstantRange push_constants = { @@ -194,16 +190,18 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul auto stage = u32(Shader::Stage::Vertex); boost::container::static_vector shader_stages; - shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ - .stage = vk::ShaderStageFlagBits::eVertex, - .module = programs[stage]->module, - .pName = "main", - }); + if (infos[stage]) { + shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ + .stage = vk::ShaderStageFlagBits::eVertex, + .module = modules[stage], + .pName = "main", + }); + } stage = u32(Shader::Stage::Fragment); - if (programs[stage]) { + if (infos[stage]) { shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ .stage = vk::ShaderStageFlagBits::eFragment, - .module = programs[stage]->module, + .module = modules[stage], .pName = "main", }); } @@ -309,14 +307,24 @@ void GraphicsPipeline::BuildDescSetLayout() { continue; } for (const auto& buffer : stage->buffers) { + const auto sharp = buffer.GetSharp(*stage); bindings.push_back({ .binding = binding++, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = buffer.IsStorage(sharp) ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, .descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, }); } + for (const auto& tex_buffer : stage->texture_buffers) { + bindings.push_back({ + .binding = binding++, + .descriptorType = tex_buffer.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, + .descriptorCount = 1, + .stageFlags = vk::ShaderStageFlagBits::eCompute, + }); + } for (const auto& image : stage->images) { bindings.push_back({ .binding = binding++, @@ -347,7 +355,8 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, VideoCore::BufferCache& buffer_cache, VideoCore::TextureCache& texture_cache) const { // Bind resource buffers and textures. - boost::container::static_vector buffer_infos; + boost::container::static_vector buffer_views; + boost::container::static_vector buffer_infos; boost::container::static_vector image_infos; boost::container::small_vector set_writes; Shader::PushData push_data{}; @@ -362,15 +371,16 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, push_data.step1 = regs.vgt_instance_step_rate_1; } for (const auto& buffer : stage->buffers) { - const auto vsharp = buffer.GetVsharp(*stage); + const auto vsharp = buffer.GetSharp(*stage); + const bool is_storage = buffer.IsStorage(vsharp); if (vsharp) { const VAddr address = vsharp.base_address; if (texture_cache.IsMeta(address)) { LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (buffer)"); } const u32 size = vsharp.GetSize(); - const u32 alignment = buffer.is_storage ? instance.StorageMinAlignment() - : instance.UniformMinAlignment(); + const u32 alignment = + is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); const auto [vk_buffer, offset] = buffer_cache.ObtainBuffer(address, size, buffer.is_written); const u32 offset_aligned = Common::AlignDown(offset, alignment); @@ -388,16 +398,47 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, .dstBinding = binding++, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, .pBufferInfo = &buffer_infos.back(), }); } + for (const auto& tex_buffer : stage->texture_buffers) { + const auto vsharp = tex_buffer.GetSharp(*stage); + vk::BufferView& buffer_view = buffer_views.emplace_back(VK_NULL_HANDLE); + if (vsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) { + const VAddr address = vsharp.base_address; + const u32 size = vsharp.GetSize(); + const u32 alignment = instance.TexelBufferMinAlignment(); + const auto [vk_buffer, offset] = + buffer_cache.ObtainBuffer(address, size, tex_buffer.is_written); + const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; + ASSERT_MSG(fmt_stride == vsharp.GetStride(), + "Texel buffer stride must match format stride"); + const u32 offset_aligned = Common::AlignDown(offset, alignment); + const u32 adjust = offset - offset_aligned; + if (adjust != 0) { + ASSERT(adjust % fmt_stride == 0); + push_data.AddOffset(binding, adjust / fmt_stride); + } + buffer_view = vk_buffer->View(offset, size + adjust, tex_buffer.is_written, + vsharp.GetDataFmt(), vsharp.GetNumberFmt()); + } + set_writes.push_back({ + .dstSet = VK_NULL_HANDLE, + .dstBinding = binding++, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = tex_buffer.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, + .pTexelBufferView = &buffer_view, + }); + } + boost::container::static_vector tsharps; for (const auto& image_desc : stage->images) { - const auto tsharp = - stage->ReadUd(image_desc.sgpr_base, image_desc.dword_offset); + const auto tsharp = image_desc.GetSharp(*stage); if (tsharp) { tsharps.emplace_back(tsharp); VideoCore::ImageInfo image_info{tsharp}; @@ -423,7 +464,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, } } for (const auto& sampler : stage->samplers) { - auto ssharp = sampler.GetSsharp(*stage); + auto ssharp = sampler.GetSharp(*stage); if (sampler.disable_aniso) { const auto& tsharp = tsharps[sampler.associated_image]; if (tsharp.base_level == 0 && tsharp.last_level == 0) { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 548e7d451..3e51e6529 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -59,7 +59,8 @@ class GraphicsPipeline { public: explicit GraphicsPipeline(const Instance& instance, Scheduler& scheduler, const GraphicsPipelineKey& key, vk::PipelineCache pipeline_cache, - std::span programs); + std::span stages, + std::span modules); ~GraphicsPipeline(); void BindResources(const Liverpool::Regs& regs, VideoCore::BufferCache& buffer_cache, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 19939a329..e1a5cb414 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -178,7 +178,7 @@ bool Instance::CreateDevice() { return false; } - boost::container::static_vector enabled_extensions; + boost::container::static_vector enabled_extensions; const auto add_extension = [&](std::string_view extension) -> bool { const auto result = std::find_if(available_extensions.begin(), available_extensions.end(), @@ -217,6 +217,7 @@ bool Instance::CreateDevice() { // with extensions. tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); + const bool maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); const bool has_sync2 = add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); @@ -277,6 +278,7 @@ bool Instance::CreateDevice() { .depthBiasClamp = features.depthBiasClamp, .multiViewport = features.multiViewport, .samplerAnisotropy = features.samplerAnisotropy, + .vertexPipelineStoresAndAtomics = features.vertexPipelineStoresAndAtomics, .fragmentStoresAndAtomics = features.fragmentStoresAndAtomics, .shaderImageGatherExtended = features.shaderImageGatherExtended, .shaderStorageImageExtendedFormats = features.shaderStorageImageExtendedFormats, @@ -299,6 +301,9 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceMaintenance4FeaturesKHR{ .maintenance4 = true, }, + vk::PhysicalDeviceMaintenance5FeaturesKHR{ + .maintenance5 = true, + }, vk::PhysicalDeviceDynamicRenderingFeaturesKHR{ .dynamicRendering = true, }, @@ -344,6 +349,9 @@ bool Instance::CreateDevice() { if (!maintenance4) { device_chain.unlink(); } + if (!maintenance5) { + device_chain.unlink(); + } if (!custom_border_color) { device_chain.unlink(); } diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 4cb4741a5..5f985d4ae 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -192,6 +192,11 @@ public: return properties.limits.minStorageBufferOffsetAlignment; } + /// Returns the minimum required alignment for texel buffers + vk::DeviceSize TexelBufferMinAlignment() const { + return properties.limits.minTexelBufferOffsetAlignment; + } + /// Returns the minimum alignemt required for accessing host-mapped device memory vk::DeviceSize NonCoherentAtomSize() const { return properties.limits.nonCoherentAtomSize; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 139edcf7c..7e880657e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -1,147 +1,59 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/config.h" -#include "common/io_file.h" -#include "common/path_util.h" -#include "shader_recompiler/backend/spirv/emit_spirv.h" -#include "shader_recompiler/exception.h" -#include "shader_recompiler/recompiler.h" #include "shader_recompiler/runtime_info.h" #include "video_core/renderer_vulkan/renderer_vulkan.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/renderer_vulkan/vk_shader_cache.h" extern std::unique_ptr renderer; namespace Vulkan { -using Shader::VsOutput; - -[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) { - return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)); -} - -void BuildVsOutputs(Shader::Info& info, const AmdGpu::Liverpool::VsOutputControl& ctl) { - const auto add_output = [&](VsOutput x, VsOutput y, VsOutput z, VsOutput w) { - if (x != VsOutput::None || y != VsOutput::None || z != VsOutput::None || - w != VsOutput::None) { - info.vs_outputs.emplace_back(Shader::VsOutputMap{x, y, z, w}); - } - }; - // VS_OUT_MISC_VEC - add_output(ctl.use_vtx_point_size ? VsOutput::PointSprite : VsOutput::None, - ctl.use_vtx_edge_flag - ? VsOutput::EdgeFlag - : (ctl.use_vtx_gs_cut_flag ? VsOutput::GsCutFlag : VsOutput::None), - ctl.use_vtx_kill_flag - ? VsOutput::KillFlag - : (ctl.use_vtx_render_target_idx ? VsOutput::GsMrtIndex : VsOutput::None), - ctl.use_vtx_viewport_idx ? VsOutput::GsVpIndex : VsOutput::None); - // VS_OUT_CCDIST0 - add_output(ctl.IsClipDistEnabled(0) - ? VsOutput::ClipDist0 - : (ctl.IsCullDistEnabled(0) ? VsOutput::CullDist0 : VsOutput::None), - ctl.IsClipDistEnabled(1) - ? VsOutput::ClipDist1 - : (ctl.IsCullDistEnabled(1) ? VsOutput::CullDist1 : VsOutput::None), - ctl.IsClipDistEnabled(2) - ? VsOutput::ClipDist2 - : (ctl.IsCullDistEnabled(2) ? VsOutput::CullDist2 : VsOutput::None), - ctl.IsClipDistEnabled(3) - ? VsOutput::ClipDist3 - : (ctl.IsCullDistEnabled(3) ? VsOutput::CullDist3 : VsOutput::None)); - // VS_OUT_CCDIST1 - add_output(ctl.IsClipDistEnabled(4) - ? VsOutput::ClipDist4 - : (ctl.IsCullDistEnabled(4) ? VsOutput::CullDist4 : VsOutput::None), - ctl.IsClipDistEnabled(5) - ? VsOutput::ClipDist5 - : (ctl.IsCullDistEnabled(5) ? VsOutput::CullDist5 : VsOutput::None), - ctl.IsClipDistEnabled(6) - ? VsOutput::ClipDist6 - : (ctl.IsCullDistEnabled(6) ? VsOutput::CullDist6 : VsOutput::None), - ctl.IsClipDistEnabled(7) - ? VsOutput::ClipDist7 - : (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None)); -} - -Shader::Info MakeShaderInfo(Shader::Stage stage, std::span user_data, - const AmdGpu::Liverpool::Regs& regs) { - Shader::Info info{}; - info.user_data = user_data; - info.stage = stage; - switch (stage) { - case Shader::Stage::Vertex: { - info.num_user_data = regs.vs_program.settings.num_user_regs; - info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt; - BuildVsOutputs(info, regs.vs_output_control); - break; - } - case Shader::Stage::Fragment: { - info.num_user_data = regs.ps_program.settings.num_user_regs; - for (u32 i = 0; i < regs.num_interp; i++) { - info.ps_inputs.push_back({ - .param_index = regs.ps_inputs[i].input_offset.Value(), - .is_default = bool(regs.ps_inputs[i].use_default), - .is_flat = bool(regs.ps_inputs[i].flat_shade), - .default_value = regs.ps_inputs[i].default_value, - }); - } - break; - } - case Shader::Stage::Compute: { - const auto& cs_pgm = regs.cs_program; - info.num_user_data = cs_pgm.settings.num_user_regs; - info.workgroup_size = {cs_pgm.num_thread_x.full, cs_pgm.num_thread_y.full, - cs_pgm.num_thread_z.full}; - info.tgid_enable = {cs_pgm.IsTgidEnabled(0), cs_pgm.IsTgidEnabled(1), - cs_pgm.IsTgidEnabled(2)}; - info.shared_memory_size = cs_pgm.SharedMemSize(); - break; - } - default: - break; - } - return info; -} - PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, AmdGpu::Liverpool* liverpool_) - : instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, inst_pool{8192}, - block_pool{512} { + : instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, + shader_cache{std::make_unique(instance, liverpool)} { pipeline_cache = instance.GetDevice().createPipelineCacheUnique({}); - profile = Shader::Profile{ - .supported_spirv = 0x00010600U, - .subgroup_size = instance.SubgroupSize(), - .support_explicit_workgroup_layout = true, - }; } +PipelineCache::~PipelineCache() = default; + const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() { + const auto& regs = liverpool->regs; // Tessellation is unsupported so skip the draw to avoid locking up the driver. - if (liverpool->regs.primitive_type == Liverpool::PrimitiveType::PatchPrimitive) { + if (regs.primitive_type == Liverpool::PrimitiveType::PatchPrimitive) { + return nullptr; + } + // There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an + // actual draw hence can skip pipeline creation. + if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) { + LOG_TRACE(Render_Vulkan, "FCE pass skipped"); + return nullptr; + } + if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) { + // TODO: check for a valid MRT1 to promote the draw to the resolve pass. + LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped"); return nullptr; } RefreshGraphicsKey(); const auto [it, is_new] = graphics_pipelines.try_emplace(graphics_key); if (is_new) { - it.value() = CreateGraphicsPipeline(); + it.value() = std::make_unique(instance, scheduler, graphics_key, + *pipeline_cache, infos, modules); } const GraphicsPipeline* pipeline = it->second.get(); return pipeline; } const ComputePipeline* PipelineCache::GetComputePipeline() { - const auto& cs_pgm = liverpool->regs.cs_program; - ASSERT(cs_pgm.Address() != nullptr); - const auto* bininfo = Liverpool::GetBinaryInfo(cs_pgm); - compute_key = bininfo->shader_hash; + RefreshComputeKey(); const auto [it, is_new] = compute_pipelines.try_emplace(compute_key); if (is_new) { - it.value() = CreateComputePipeline(); + it.value() = std::make_unique(instance, scheduler, *pipeline_cache, + compute_key, *infos[0], modules[0]); } const ComputePipeline* pipeline = it->second.get(); return pipeline; @@ -229,164 +141,37 @@ void PipelineCache::RefreshGraphicsKey() { ++remapped_cb; } + u32 binding{}; for (u32 i = 0; i < MaxShaderStages; i++) { if (!regs.stage_enable.IsStageEnabled(i)) { key.stage_hashes[i] = 0; + infos[i] = nullptr; continue; } auto* pgm = regs.ProgramForStage(i); if (!pgm || !pgm->Address()) { key.stage_hashes[i] = 0; + infos[i] = nullptr; continue; } const auto* bininfo = Liverpool::GetBinaryInfo(*pgm); if (!bininfo->Valid()) { key.stage_hashes[i] = 0; + infos[i] = nullptr; continue; } - key.stage_hashes[i] = bininfo->shader_hash; - } -} - -std::unique_ptr PipelineCache::CreateGraphicsPipeline() { - const auto& regs = liverpool->regs; - - // There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an - // actual draw hence can skip pipeline creation. - if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) { - LOG_TRACE(Render_Vulkan, "FCE pass skipped"); - return {}; - } - - if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) { - // TODO: check for a valid MRT1 to promote the draw to the resolve pass. - LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped"); - return {}; - } - - u32 binding{}; - for (u32 i = 0; i < MaxShaderStages; i++) { - if (!graphics_key.stage_hashes[i]) { - programs[i] = nullptr; - continue; - } - auto* pgm = regs.ProgramForStage(i); - const auto code = pgm->Code(); - - // Dump shader code if requested. const auto stage = Shader::Stage{i}; - const u64 hash = graphics_key.stage_hashes[i]; - if (Config::dumpShaders()) { - DumpShader(code, hash, stage, "bin"); - } - - if (stage != Shader::Stage::Fragment && stage != Shader::Stage::Vertex) { - LOG_ERROR(Render_Vulkan, "Unsupported shader stage {}. PL creation skipped.", stage); - return {}; - } - - const u64 lookup_hash = HashCombine(hash, binding); - auto it = program_cache.find(lookup_hash); - if (it != program_cache.end()) { - const Program* program = it.value().get(); - ASSERT(program->pgm.info.stage == stage); - programs[i] = program; - binding = program->end_binding; - continue; - } - - // Recompile shader to IR. - try { - auto program = std::make_unique(); - block_pool.ReleaseContents(); - inst_pool.ReleaseContents(); - - LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x}", stage, hash); - Shader::Info info = MakeShaderInfo(stage, pgm->user_data, regs); - info.pgm_base = pgm->Address(); - info.pgm_hash = hash; - program->pgm = - Shader::TranslateProgram(inst_pool, block_pool, code, std::move(info), profile); - - // Compile IR to SPIR-V - program->spv = Shader::Backend::SPIRV::EmitSPIRV(profile, program->pgm, binding); - if (Config::dumpShaders()) { - DumpShader(program->spv, hash, stage, "spv"); - } - - // Compile module and set name to hash in renderdoc - program->end_binding = binding; - program->module = CompileSPV(program->spv, instance.GetDevice()); - const auto name = fmt::format("{}_{:#x}", stage, hash); - Vulkan::SetObjectName(instance.GetDevice(), program->module, name); - - // Cache program - const auto [it, _] = program_cache.emplace(lookup_hash, std::move(program)); - programs[i] = it.value().get(); - } catch (const Shader::Exception& e) { - UNREACHABLE_MSG("{}", e.what()); - } - } - - return std::make_unique(instance, scheduler, graphics_key, *pipeline_cache, - programs); -} - -std::unique_ptr PipelineCache::CreateComputePipeline() { - const auto& cs_pgm = liverpool->regs.cs_program; - const auto code = cs_pgm.Code(); - - // Dump shader code if requested. - if (Config::dumpShaders()) { - DumpShader(code, compute_key, Shader::Stage::Compute, "bin"); - } - - block_pool.ReleaseContents(); - inst_pool.ReleaseContents(); - - // Recompile shader to IR. - try { - auto program = std::make_unique(); - LOG_INFO(Render_Vulkan, "Compiling cs shader {:#x}", compute_key); - Shader::Info info = - MakeShaderInfo(Shader::Stage::Compute, cs_pgm.user_data, liverpool->regs); - info.pgm_base = cs_pgm.Address(); - info.pgm_hash = compute_key; - program->pgm = - Shader::TranslateProgram(inst_pool, block_pool, code, std::move(info), profile); - - // Compile IR to SPIR-V - u32 binding{}; - program->spv = Shader::Backend::SPIRV::EmitSPIRV(profile, program->pgm, binding); - if (Config::dumpShaders()) { - DumpShader(program->spv, compute_key, Shader::Stage::Compute, "spv"); - } - - // Compile module and set name to hash in renderdoc - program->module = CompileSPV(program->spv, instance.GetDevice()); - const auto name = fmt::format("cs_{:#x}", compute_key); - Vulkan::SetObjectName(instance.GetDevice(), program->module, name); - - // Cache program - const auto [it, _] = program_cache.emplace(compute_key, std::move(program)); - return std::make_unique(instance, scheduler, *pipeline_cache, compute_key, - it.value().get()); - } catch (const Shader::Exception& e) { - UNREACHABLE_MSG("{}", e.what()); - return nullptr; + const GuestProgram guest_pgm{pgm, stage}; + std::tie(infos[i], modules[i], key.stage_hashes[i]) = + shader_cache->GetProgram(guest_pgm, binding); } } -void PipelineCache::DumpShader(std::span code, u64 hash, Shader::Stage stage, - std::string_view ext) { - using namespace Common::FS; - const auto dump_dir = GetUserPath(PathType::ShaderDir) / "dumps"; - if (!std::filesystem::exists(dump_dir)) { - std::filesystem::create_directories(dump_dir); - } - const auto filename = fmt::format("{}_{:#018x}.{}", stage, hash, ext); - const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; - file.WriteSpan(code); +void PipelineCache::RefreshComputeKey() { + u32 binding{}; + const auto* cs_pgm = &liverpool->regs.cs_program; + const GuestProgram guest_pgm{cs_pgm, Shader::Stage::Compute}; + std::tie(infos[0], modules[0], compute_key) = shader_cache->GetProgram(guest_pgm, binding); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 8f3b806cb..d0eb0c660 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -4,9 +4,6 @@ #pragma once #include -#include "shader_recompiler/ir/basic_block.h" -#include "shader_recompiler/ir/program.h" -#include "shader_recompiler/profile.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" @@ -18,6 +15,7 @@ namespace Vulkan { class Instance; class Scheduler; +class ShaderCache; class PipelineCache { static constexpr size_t MaxShaderStages = 5; @@ -25,7 +23,7 @@ class PipelineCache { public: explicit PipelineCache(const Instance& instance, Scheduler& scheduler, AmdGpu::Liverpool* liverpool); - ~PipelineCache() = default; + ~PipelineCache(); const GraphicsPipeline* GetGraphicsPipeline(); @@ -33,10 +31,7 @@ public: private: void RefreshGraphicsKey(); - void DumpShader(std::span code, u64 hash, Shader::Stage stage, std::string_view ext); - - std::unique_ptr CreateGraphicsPipeline(); - std::unique_ptr CreateComputePipeline(); + void RefreshComputeKey(); private: const Instance& instance; @@ -44,15 +39,13 @@ private: AmdGpu::Liverpool* liverpool; vk::UniquePipelineCache pipeline_cache; vk::UniquePipelineLayout pipeline_layout; - tsl::robin_map> program_cache; + std::unique_ptr shader_cache; tsl::robin_map> compute_pipelines; tsl::robin_map> graphics_pipelines; - std::array programs{}; - Shader::Profile profile{}; + std::array infos{}; + std::array modules{}; GraphicsPipelineKey graphics_key{}; u64 compute_key{}; - Common::ObjectPool inst_pool; - Common::ObjectPool block_pool; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_shader_cache.cpp b/src/video_core/renderer_vulkan/vk_shader_cache.cpp new file mode 100644 index 000000000..762557125 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_shader_cache.cpp @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/config.h" +#include "common/io_file.h" +#include "common/path_util.h" +#include "shader_recompiler/backend/spirv/emit_spirv.h" +#include "shader_recompiler/recompiler.h" +#include "video_core/renderer_vulkan/vk_instance.h" +#include "video_core/renderer_vulkan/vk_platform.h" +#include "video_core/renderer_vulkan/vk_shader_cache.h" +#include "video_core/renderer_vulkan/vk_shader_util.h" + +namespace Vulkan { + +using Shader::VsOutput; + +void BuildVsOutputs(Shader::Info& info, const AmdGpu::Liverpool::VsOutputControl& ctl) { + const auto add_output = [&](VsOutput x, VsOutput y, VsOutput z, VsOutput w) { + if (x != VsOutput::None || y != VsOutput::None || z != VsOutput::None || + w != VsOutput::None) { + info.vs_outputs.emplace_back(Shader::VsOutputMap{x, y, z, w}); + } + }; + // VS_OUT_MISC_VEC + add_output(ctl.use_vtx_point_size ? VsOutput::PointSprite : VsOutput::None, + ctl.use_vtx_edge_flag + ? VsOutput::EdgeFlag + : (ctl.use_vtx_gs_cut_flag ? VsOutput::GsCutFlag : VsOutput::None), + ctl.use_vtx_kill_flag + ? VsOutput::KillFlag + : (ctl.use_vtx_render_target_idx ? VsOutput::GsMrtIndex : VsOutput::None), + ctl.use_vtx_viewport_idx ? VsOutput::GsVpIndex : VsOutput::None); + // VS_OUT_CCDIST0 + add_output(ctl.IsClipDistEnabled(0) + ? VsOutput::ClipDist0 + : (ctl.IsCullDistEnabled(0) ? VsOutput::CullDist0 : VsOutput::None), + ctl.IsClipDistEnabled(1) + ? VsOutput::ClipDist1 + : (ctl.IsCullDistEnabled(1) ? VsOutput::CullDist1 : VsOutput::None), + ctl.IsClipDistEnabled(2) + ? VsOutput::ClipDist2 + : (ctl.IsCullDistEnabled(2) ? VsOutput::CullDist2 : VsOutput::None), + ctl.IsClipDistEnabled(3) + ? VsOutput::ClipDist3 + : (ctl.IsCullDistEnabled(3) ? VsOutput::CullDist3 : VsOutput::None)); + // VS_OUT_CCDIST1 + add_output(ctl.IsClipDistEnabled(4) + ? VsOutput::ClipDist4 + : (ctl.IsCullDistEnabled(4) ? VsOutput::CullDist4 : VsOutput::None), + ctl.IsClipDistEnabled(5) + ? VsOutput::ClipDist5 + : (ctl.IsCullDistEnabled(5) ? VsOutput::CullDist5 : VsOutput::None), + ctl.IsClipDistEnabled(6) + ? VsOutput::ClipDist6 + : (ctl.IsCullDistEnabled(6) ? VsOutput::CullDist6 : VsOutput::None), + ctl.IsClipDistEnabled(7) + ? VsOutput::ClipDist7 + : (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None)); +} + +Shader::Info MakeShaderInfo(const GuestProgram& pgm, const AmdGpu::Liverpool::Regs& regs) { + Shader::Info info{}; + info.user_data = pgm.user_data; + info.pgm_base = VAddr(pgm.code.data()); + info.pgm_hash = pgm.hash; + info.stage = pgm.stage; + switch (pgm.stage) { + case Shader::Stage::Vertex: { + info.num_user_data = regs.vs_program.settings.num_user_regs; + info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt; + BuildVsOutputs(info, regs.vs_output_control); + break; + } + case Shader::Stage::Fragment: { + info.num_user_data = regs.ps_program.settings.num_user_regs; + for (u32 i = 0; i < regs.num_interp; i++) { + info.ps_inputs.push_back({ + .param_index = regs.ps_inputs[i].input_offset.Value(), + .is_default = bool(regs.ps_inputs[i].use_default), + .is_flat = bool(regs.ps_inputs[i].flat_shade), + .default_value = regs.ps_inputs[i].default_value, + }); + } + break; + } + case Shader::Stage::Compute: { + const auto& cs_pgm = regs.cs_program; + info.num_user_data = cs_pgm.settings.num_user_regs; + info.workgroup_size = {cs_pgm.num_thread_x.full, cs_pgm.num_thread_y.full, + cs_pgm.num_thread_z.full}; + info.tgid_enable = {cs_pgm.IsTgidEnabled(0), cs_pgm.IsTgidEnabled(1), + cs_pgm.IsTgidEnabled(2)}; + info.shared_memory_size = cs_pgm.SharedMemSize(); + break; + } + default: + break; + } + return info; +} + +[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) { + return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)); +} + +ShaderCache::ShaderCache(const Instance& instance_, AmdGpu::Liverpool* liverpool_) + : instance{instance_}, liverpool{liverpool_}, inst_pool{8192}, block_pool{512} { + profile = Shader::Profile{ + .supported_spirv = 0x00010600U, + .subgroup_size = instance.SubgroupSize(), + .support_explicit_workgroup_layout = true, + }; +} + +vk::ShaderModule ShaderCache::CompileModule(Shader::Info& info, std::span code, + size_t perm_idx, u32& binding) { + LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x} {}", info.stage, info.pgm_hash, + perm_idx != 0 ? "(permutation)" : ""); + + if (Config::dumpShaders()) { + DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); + } + + block_pool.ReleaseContents(); + inst_pool.ReleaseContents(); + const auto ir_program = Shader::TranslateProgram(inst_pool, block_pool, code, info, profile); + + // Compile IR to SPIR-V + const auto spv = Shader::Backend::SPIRV::EmitSPIRV(profile, ir_program, binding); + if (Config::dumpShaders()) { + DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); + } + + // Create module and set name to hash in renderdoc + const auto module = CompileSPV(spv, instance.GetDevice()); + ASSERT(module != VK_NULL_HANDLE); + const auto name = fmt::format("{}_{:#x}_{}", info.stage, info.pgm_hash, perm_idx); + Vulkan::SetObjectName(instance.GetDevice(), module, name); + return module; +} + +Program* ShaderCache::CreateProgram(const GuestProgram& pgm, u32& binding) { + Program* program = program_pool.Create(MakeShaderInfo(pgm, liverpool->regs)); + u32 start_binding = binding; + const auto module = CompileModule(program->info, pgm.code, 0, binding); + program->modules.emplace_back(module, StageSpecialization{program->info, start_binding}); + return program; +} + +std::tuple ShaderCache::GetProgram( + const GuestProgram& pgm, u32& binding) { + auto [it_pgm, new_program] = program_cache.try_emplace(pgm.hash); + if (new_program) { + auto program = CreateProgram(pgm, binding); + const auto module = program->modules.back().module; + it_pgm.value() = program; + return std::make_tuple(&program->info, module, HashCombine(pgm.hash, 0)); + } + + Program* program = it_pgm->second; + const auto& info = program->info; + size_t perm_idx = program->modules.size(); + StageSpecialization spec{info, binding}; + vk::ShaderModule module{}; + + const auto it = std::ranges::find(program->modules, spec, &Program::Module::spec); + if (it == program->modules.end()) { + auto new_info = MakeShaderInfo(pgm, liverpool->regs); + module = CompileModule(new_info, pgm.code, perm_idx, binding); + program->modules.emplace_back(module, std::move(spec)); + } else { + binding += info.NumBindings(); + module = it->module; + perm_idx = std::distance(program->modules.begin(), it); + } + return std::make_tuple(&info, module, HashCombine(pgm.hash, perm_idx)); +} + +void ShaderCache::DumpShader(std::span code, u64 hash, Shader::Stage stage, + size_t perm_idx, std::string_view ext) { + using namespace Common::FS; + const auto dump_dir = GetUserPath(PathType::ShaderDir) / "dumps"; + if (!std::filesystem::exists(dump_dir)) { + std::filesystem::create_directories(dump_dir); + } + const auto filename = fmt::format("{}_{:#018x}_{}.{}", stage, hash, perm_idx, ext); + const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; + file.WriteSpan(code); +} + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_shader_cache.h b/src/video_core/renderer_vulkan/vk_shader_cache.h new file mode 100644 index 000000000..191e1b08c --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_shader_cache.h @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include "common/object_pool.h" +#include "shader_recompiler/ir/basic_block.h" +#include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" +#include "video_core/amdgpu/liverpool.h" +#include "video_core/renderer_vulkan/vk_common.h" + +namespace Vulkan { + +class Instance; + +struct BufferSpecialization { + u16 stride : 14; + u16 is_storage : 1; + + auto operator<=>(const BufferSpecialization&) const = default; +}; + +struct TextureBufferSpecialization { + bool is_integer; + + auto operator<=>(const TextureBufferSpecialization&) const = default; +}; + +struct ImageSpecialization { + AmdGpu::ImageType type; + bool is_integer; + + auto operator<=>(const ImageSpecialization&) const = default; +}; + +struct StageSpecialization { + static constexpr size_t MaxStageResources = 32; + + const Shader::Info* info; + std::bitset bitset{}; + boost::container::small_vector buffers; + boost::container::small_vector tex_buffers; + boost::container::small_vector images; + u32 start_binding{}; + + void ForEachSharp(u32& binding, auto& spec_list, auto& desc_list, auto&& func) { + for (const auto& desc : desc_list) { + auto& spec = spec_list.emplace_back(); + const auto sharp = desc.GetSharp(*info); + if (!sharp) { + binding++; + continue; + } + bitset.set(binding++); + func(spec, desc, sharp); + } + } + + StageSpecialization(const Shader::Info& info_, u32 start_binding_) + : info{&info_}, start_binding{start_binding_} { + u32 binding{}; + ForEachSharp(binding, buffers, info->buffers, + [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { + spec.stride = sharp.GetStride(); + spec.is_storage = desc.IsStorage(sharp); + }); + ForEachSharp(binding, tex_buffers, info->texture_buffers, + [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { + spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); + }); + ForEachSharp(binding, images, info->images, + [](auto& spec, const auto& desc, AmdGpu::Image sharp) { + spec.type = sharp.GetType(); + spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); + }); + } + + bool operator==(const StageSpecialization& other) const { + if (start_binding != other.start_binding) { + return false; + } + u32 binding{}; + for (u32 i = 0; i < buffers.size(); i++) { + if (other.bitset[binding++] && buffers[i] != other.buffers[i]) { + return false; + } + } + for (u32 i = 0; i < tex_buffers.size(); i++) { + if (other.bitset[binding++] && tex_buffers[i] != other.tex_buffers[i]) { + return false; + } + } + for (u32 i = 0; i < images.size(); i++) { + if (other.bitset[binding++] && images[i] != other.images[i]) { + return false; + } + } + return true; + } +}; + +struct Program { + struct Module { + vk::ShaderModule module; + StageSpecialization spec; + }; + + Shader::Info info; + boost::container::small_vector modules; + + explicit Program(const Shader::Info& info_) : info{info_} {} +}; + +struct GuestProgram { + Shader::Stage stage; + std::span user_data; + std::span code; + u64 hash; + + explicit GuestProgram(const auto* pgm, Shader::Stage stage_) + : stage{stage_}, user_data{pgm->user_data}, code{pgm->Code()} { + const auto* bininfo = AmdGpu::Liverpool::GetBinaryInfo(*pgm); + hash = bininfo->shader_hash; + } +}; + +class ShaderCache { +public: + explicit ShaderCache(const Instance& instance, AmdGpu::Liverpool* liverpool); + ~ShaderCache() = default; + + std::tuple GetProgram(const GuestProgram& pgm, + u32& binding); + +private: + void DumpShader(std::span code, u64 hash, Shader::Stage stage, size_t perm_idx, + std::string_view ext); + vk::ShaderModule CompileModule(Shader::Info& info, std::span code, size_t perm_idx, + u32& binding); + Program* CreateProgram(const GuestProgram& pgm, u32& binding); + +private: + const Instance& instance; + AmdGpu::Liverpool* liverpool; + Shader::Profile profile{}; + tsl::robin_map program_cache; + Common::ObjectPool inst_pool; + Common::ObjectPool block_pool; + Common::ObjectPool program_pool; +}; + +} // namespace Vulkan diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 00c3833fe..bcdc11ad9 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -50,9 +50,9 @@ vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) { } bool IsIdentityMapping(u32 dst_sel, u32 num_components) { - return (num_components == 1 && dst_sel == 0b100) || - (num_components == 2 && dst_sel == 0b101'100) || - (num_components == 3 && dst_sel == 0b110'101'100) || + return (num_components == 1 && dst_sel == 0b001'000'000'100) || + (num_components == 2 && dst_sel == 0b001'000'101'100) || + (num_components == 3 && dst_sel == 0b001'110'101'100) || (num_components == 4 && dst_sel == 0b111'110'101'100); } diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index 0bed5adc2..8b0227624 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -187,6 +187,7 @@ vk::Format DemoteImageFormatForDetiling(vk::Format format) { case vk::Format::eR32Uint: case vk::Format::eR16G16Sfloat: case vk::Format::eR16G16Unorm: + case vk::Format::eB10G11R11UfloatPack32: return vk::Format::eR32Uint; case vk::Format::eBc1RgbaSrgbBlock: case vk::Format::eBc1RgbaUnormBlock: @@ -202,6 +203,7 @@ vk::Format DemoteImageFormatForDetiling(vk::Format format) { case vk::Format::eBc3SrgbBlock: case vk::Format::eBc3UnormBlock: case vk::Format::eBc5UnormBlock: + case vk::Format::eBc5SnormBlock: case vk::Format::eBc7SrgbBlock: case vk::Format::eBc7UnormBlock: case vk::Format::eBc6HUfloatBlock: From 1c835a1aa49c5807c2f8ed40a52b825304bd3373 Mon Sep 17 00:00:00 2001 From: Flamy <27062841+f1amy@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:59:52 +0500 Subject: [PATCH 106/147] ru DLC translation and translation fixes --- src/qt_gui/translations/ru_RU.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 538628dc2..f4e8fbfdd 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -93,7 +93,7 @@ Cheats / Patches - Читы / Патчи + Читы и патчи @@ -256,7 +256,7 @@ Download Cheats/Patches - Скачать Читы / Патчи + Скачать читы или патчи @@ -608,12 +608,12 @@ DLC Installation - DLC Installation + Установка DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Вы хотите установить DLC: %1? @@ -638,7 +638,7 @@ Game successfully installed at %1 - Игра успешно установлена по адресу %1 + Игра успешно установлена в %1 @@ -651,13 +651,13 @@ Cheats / Patches - Читы / Патчи + Читы и патчи defaultTextEdit_MSG - Cheats/Patches sunt experimentale.\nUtilizați cu prudență.\n\nDescărcați cheats individual prin selectarea depozitului și făcând clic pe butonul de descărcare.\nÎn fila Patches, puteți descărca toate patch-urile deodată, alege pe cele pe care doriți să le utilizați și salvați selecția.\n\nDeoarece nu dezvoltăm Cheats/Patches,\nte rugăm să raportezi problemele autorului cheat-ului.\n\nAi creat un nou cheat? Vizitează:\nhttps://github.com/shadps4-emu/ps4_cheats - + Читы и патчи экспериментальны.\nИспользуйте с осторожностью.\n\nСкачивайте читы, выбрав репозиторий и нажав на кнопку загрузки.\nВо вкладке "Патчи" вы можете скачать все патчи сразу, выбирать какие вы хотите использовать, и сохранять выбор.\n\nПоскольку мы не разрабатываем читы/патчи,\nпожалуйста сообщайте о проблемах автору чита/патча.\n\nСоздали новый чит? Посетите:\nhttps://github.com/shadps4-emu/ps4_cheats + No Image Available From 751f6f9babf6a47884379fe48c6500f398aca29f Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Thu, 29 Aug 2024 17:26:06 -0300 Subject: [PATCH 107/147] Fix creation files.json in 'Download ALL' --- src/qt_gui/cheats_patches.h | 2 +- src/qt_gui/main_window.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt_gui/cheats_patches.h b/src/qt_gui/cheats_patches.h index 7a68829cd..a9932886c 100644 --- a/src/qt_gui/cheats_patches.h +++ b/src/qt_gui/cheats_patches.h @@ -36,6 +36,7 @@ public: void downloadCheats(const QString& source, const QString& m_gameSerial, const QString& m_gameVersion, bool showMessageBox); void downloadPatches(const QString repository, const bool showMessageBox); + void createFilesJson(const QString& repository); signals: void downloadFinished(); @@ -58,7 +59,6 @@ private: void applyCheat(const QString& modName, bool enabled); void applyPatch(const QString& patchName, bool enabled); - void createFilesJson(const QString& repository); void uncheckAllCheatCheckBoxes(); void updateNoteTextEdit(const QString& patchName); diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 412a53c2f..9571f5d7b 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -391,6 +391,8 @@ void MainWindow::CreateConnects() { nullptr, tr("Download Complete"), QString(tr("Patches Downloaded Successfully!") + "\n" + tr("All Patches available for all games have been downloaded."))); + cheatsPatches->createFilesJson("GoldHEN"); + cheatsPatches->createFilesJson("shadPS4"); panelDialog->accept(); }); panelDialog->exec(); From 5a96ac1a4fbbd6285950e91845f3ae4df18d9a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pl=C3=ADnio=20Larrubia?= Date: Thu, 29 Aug 2024 18:22:36 -0300 Subject: [PATCH 108/147] =?UTF-8?q?Update=20PT-BR=20translation=20-=20Supp?= =?UTF-8?q?ort=20DLC=20texts=20-=20Fixed=20some=20errors=20on=20Cheats=20(?= =?UTF-8?q?Trapa=C3=A7as)=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/qt_gui/translations/pt_BR.ts | 56 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 08c8fa47d..96fb78f86 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -37,7 +37,7 @@ Loading game list, please wait :3 - Carregando lista de jogos, por favor aguarde :3 + Carregando a lista de jogos, por favor aguarde :3 @@ -256,7 +256,7 @@ Download Cheats/Patches - Baixar Trapaças / Patches + Baixar Cheats/Patches @@ -291,7 +291,7 @@ Game List Mode - Modo de Lista de Jogos + Modo da Lista de Jogos @@ -425,7 +425,7 @@ Log Filter - Filtro + Filtro do Registro @@ -508,12 +508,12 @@ Download Cheats For All Installed Games - Baixar Trapaças para todos os jogos instalados + Baixar Cheats para Todos os Jogos Instalados Download Patches For All Games - Baixar Patches para todos os jogos + Baixar Patches para Todos os Jogos @@ -523,7 +523,7 @@ You have downloaded cheats for all the games you have installed. - Você baixou trapaças para todos os jogos que instalou. + Você baixou cheats para todos os jogos que instalou. @@ -578,7 +578,7 @@ Patch detected!\nPKG Version %1 is older - Patch detectado!\nVersão PKG %1 é mais antiga + Patch detectado!\nVersão do PKG %1 é mais antiga @@ -593,7 +593,7 @@ Patch detected!\nGame is installed: %1\nWould you like - Patch detectado!\nJogo está instalado: %1\nGostaria de + Patch detectado!\nO Jogo está instalado: %1\nGostaria de @@ -608,22 +608,22 @@ DLC Installation - DLC Installation + Instalação de DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Gostaria de instalar a DLC: %1? PKG is a patch, please install the game first! - PKG é um patch, por favor, instale o jogo primeiro! + O PKG é um patch, por favor, instale o jogo primeiro! PKG ERROR - ERRO PKG + ERRO de PKG @@ -651,12 +651,12 @@ Cheats / Patches - Trapaças / Patches + Cheats / Patches defaultTextEdit_MSG - Trapaças/Patches são experimentais.\nUse com cautela.\n\nBaixe as trapaças individualmente selecionando o repositório e clicando no botão de download.\nNa aba Patches, você pode baixar todos os Patches de uma vez, escolher qual deseja usar e salvar a opção.\n\nComo não desenvolvemos as Trapaças/Patches,\npor favor, reporte problemas relacionados ao autor da trapaça.\n\nCriou uma nova trapaça? Visite:\nhttps://github.com/shadps4-emu/ps4_cheats + Cheats/Patches são experimentais.\nUse com cautela.\n\nBaixe os cheats individualmente selecionando o repositório e clicando no botão de download.\nNa aba Patches, você pode baixar todos os Patches de uma vez, escolha qual deseja usar e salve a opção.\n\nComo não desenvolvemos os Cheats/Patches,\npor favor, reporte problemas relacionados ao autor do cheat.\n\nCriou um novo cheat? Visite:\nhttps://github.com/shadps4-emu/ps4_cheats @@ -666,7 +666,7 @@ Serial: - Série: + Serial: @@ -681,7 +681,7 @@ Select Cheat File: - Selecione o Arquivo de Trapaça: + Selecione o Arquivo de Cheat: @@ -691,7 +691,7 @@ Download Cheats - Baixar Trapaças + Baixar Cheats @@ -706,7 +706,7 @@ You can delete the cheats you don't want after downloading them. - Você pode excluir as trapaças que não deseja após baixá-las. + Você pode excluir os cheats que não deseja após baixá-las. @@ -731,7 +731,7 @@ Cheats - Trapaças + Cheats @@ -756,7 +756,7 @@ No patch file found for the current serial. - Nenhum arquivo de patch encontrado para a série atual. + Nenhum arquivo de patch encontrado para o serial atual. @@ -816,22 +816,22 @@ Cheats Not Found - Trapaças Não Encontradas + Cheats Não Encontrados CheatsNotFound_MSG - Nenhuma trapaça encontrada para este jogo nesta versão do repositório selecionado, tente outro repositório ou uma versão diferente do jogo. + Nenhum cheat encontrado para este jogo nesta versão do repositório selecionado, tente outro repositório ou uma versão diferente do jogo. Cheats Downloaded Successfully - Trapaças Baixadas com Sucesso + Cheats Baixados com Sucesso CheatsDownloadedSuccessfully_MSG - Você baixou as trapaças com sucesso. Para esta versão do jogo a partir do repositório selecionado.Você pode tentar baixar de outro repositório, se estiver disponível, também será possível usá-lo selecionando o arquivo da lista. + Você baixou os cheats com sucesso. Para esta versão do jogo a partir do repositório selecionado. Você pode tentar baixar de outro repositório, se estiver disponível, também será possível usá-lo selecionando o arquivo da lista. @@ -851,7 +851,7 @@ DownloadComplete_MSG - Patches Baixados com Sucesso! Todos os patches disponíveis para todos os jogos foram baixados, não é necessário baixá-los individualmente para cada jogo como acontece com as Trapaças. + Patches Baixados com Sucesso! Todos os patches disponíveis para todos os jogos foram baixados, não é necessário baixá-los individualmente para cada jogo como acontece com os Cheats. @@ -871,7 +871,7 @@ XML ERROR: - ERRO XML: + ERRO de XML: @@ -886,7 +886,7 @@ Directory does not exist: - Diretório não existe: + O Diretório não existe: From fab390b8608d844ebe644d7ca1cebc6b356d5112 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Fri, 30 Aug 2024 00:20:47 +0300 Subject: [PATCH 109/147] spirv: More correct texel buffer usage --- src/shader_recompiler/backend/spirv/emit_spirv.cpp | 1 + .../backend/spirv/emit_spirv_context_get_set.cpp | 3 ++- src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | 1 + src/shader_recompiler/backend/spirv/spirv_emit_context.h | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 161d4ec9e..98eac0819 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -187,6 +187,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { ctx.AddCapability(spv::Capability::Int64); if (info.has_storage_images || info.has_image_buffers) { ctx.AddCapability(spv::Capability::StorageImageExtendedFormats); + ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); ctx.AddCapability(spv::Capability::StorageImageWriteWithoutFormat); } if (info.has_texel_buffers) { 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 4566439c6..7bdc98de9 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 @@ -266,7 +266,8 @@ Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addr const auto& buffer = ctx.texture_buffers[handle]; const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id); const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset); - Id texel = ctx.OpImageFetch(buffer.result_type, tex_buffer, coord); + Id texel = buffer.is_storage ? ctx.OpImageRead(buffer.result_type, tex_buffer, coord) + : ctx.OpImageFetch(buffer.result_type, tex_buffer, coord); if (buffer.is_integer) { texel = ctx.OpBitcast(ctx.F32[4], texel); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index e40196047..51315139f 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -406,6 +406,7 @@ void EmitContext::DefineTextureBuffers() { .image_type = image_type, .result_type = sampled_type[4], .is_integer = is_integer, + .is_storage = desc.is_written, }); interfaces.push_back(id); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 5391108f3..d3646382f 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -215,6 +215,7 @@ public: Id image_type; Id result_type; bool is_integer; + bool is_storage; }; u32& binding; From 6fbbe3d79b8f8e359b47e1f5b42030b20f82b9a3 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Fri, 30 Aug 2024 00:21:25 +0300 Subject: [PATCH 110/147] translator: Add missed flow instruction --- src/shader_recompiler/frontend/translate/translate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index e3482546b..eb86310b8 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -436,6 +436,7 @@ void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) { case Opcode::S_CBRANCH_SCC1: case Opcode::S_CBRANCH_VCCNZ: case Opcode::S_CBRANCH_VCCZ: + case Opcode::S_CBRANCH_EXECNZ: case Opcode::S_BRANCH: return; default: From cf706f8cc7fb2e1606182b676ac50510211ec88b Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Fri, 30 Aug 2024 00:25:04 +0300 Subject: [PATCH 111/147] buffer: Don't leak texel buffers, blacklist stream buffer with texel buffers --- src/video_core/buffer_cache/buffer.cpp | 6 +++--- src/video_core/buffer_cache/buffer.h | 2 +- src/video_core/buffer_cache/buffer_cache.cpp | 5 +++-- src/video_core/buffer_cache/buffer_cache.h | 3 ++- src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 2 +- src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/video_core/buffer_cache/buffer.cpp b/src/video_core/buffer_cache/buffer.cpp index 68a4aa52f..372b6f745 100644 --- a/src/video_core/buffer_cache/buffer.cpp +++ b/src/video_core/buffer_cache/buffer.cpp @@ -119,7 +119,7 @@ vk::BufferView Buffer::View(u32 offset, u32 size, bool is_written, AmdGpu::DataF dfmt == view.dfmt && nfmt == view.nfmt; })}; if (it != views.end()) { - return it->handle; + return *it->handle; } const vk::BufferUsageFlags2CreateInfoKHR usage_flags = { .usage = is_written ? vk::BufferUsageFlagBits2KHR::eStorageTexelBuffer @@ -138,9 +138,9 @@ vk::BufferView Buffer::View(u32 offset, u32 size, bool is_written, AmdGpu::DataF .is_written = is_written, .dfmt = dfmt, .nfmt = nfmt, - .handle = instance->GetDevice().createBufferView(view_ci), + .handle = instance->GetDevice().createBufferViewUnique(view_ci), }); - return views.back().handle; + return *views.back().handle; } constexpr u64 WATCHES_INITIAL_RESERVE = 0x4000; diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index 7bcd06094..26d48eaef 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -134,7 +134,7 @@ public: bool is_written; AmdGpu::DataFormat dfmt; AmdGpu::NumberFormat nfmt; - vk::BufferView handle; + vk::UniqueBufferView handle; }; std::vector views; }; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index b838989fd..0151f2c13 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -228,11 +228,12 @@ u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { return regs.num_indices; } -std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, bool is_written) { +std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, bool is_written, + bool is_texel_buffer) { std::scoped_lock lk{mutex}; static constexpr u64 StreamThreshold = CACHING_PAGESIZE; const bool is_gpu_dirty = memory_tracker.IsRegionGpuModified(device_addr, size); - if (!is_written && size < StreamThreshold && !is_gpu_dirty) { + if (!is_written && !is_texel_buffer && size <= StreamThreshold && !is_gpu_dirty) { // For small uniform buffers that have not been modified by gpu // use device local stream buffer to reduce renderpass breaks. const u64 offset = stream_buffer.Copy(device_addr, size, instance.UniformMinAlignment()); diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 2bcc4f0e8..a07470b8e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -66,7 +66,8 @@ public: u32 BindIndexBuffer(bool& is_indexed, u32 index_offset); /// Obtains a buffer for the specified region. - [[nodiscard]] std::pair ObtainBuffer(VAddr gpu_addr, u32 size, bool is_written); + [[nodiscard]] std::pair ObtainBuffer(VAddr gpu_addr, u32 size, bool is_written, + bool is_texel_buffer = false); /// Obtains a temporary buffer for usage in texture cache. [[nodiscard]] std::pair ObtainTempBuffer(VAddr gpu_addr, u32 size); diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index e62c1040f..dd22bfbc6 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -171,7 +171,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } const u32 alignment = instance.TexelBufferMinAlignment(); const auto [vk_buffer, offset] = - buffer_cache.ObtainBuffer(address, size, desc.is_written); + buffer_cache.ObtainBuffer(address, size, desc.is_written, true); const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; ASSERT_MSG(fmt_stride == vsharp.GetStride(), "Texel buffer stride must match format stride"); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 719a911a4..386ae62f8 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -412,7 +412,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, const u32 size = vsharp.GetSize(); const u32 alignment = instance.TexelBufferMinAlignment(); const auto [vk_buffer, offset] = - buffer_cache.ObtainBuffer(address, size, tex_buffer.is_written); + buffer_cache.ObtainBuffer(address, size, tex_buffer.is_written, true); const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; ASSERT_MSG(fmt_stride == vsharp.GetStride(), "Texel buffer stride must match format stride"); From cb5190e31acd6dcd79dedc435c4ed82314ebf04b Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Fri, 30 Aug 2024 00:59:12 +0300 Subject: [PATCH 112/147] vk_graphics_pipeline: Fix copy paste error --- src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 386ae62f8..926b7d7cc 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -322,7 +322,7 @@ void GraphicsPipeline::BuildDescSetLayout() { .descriptorType = tex_buffer.is_written ? vk::DescriptorType::eStorageTexelBuffer : vk::DescriptorType::eUniformTexelBuffer, .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eCompute, + .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, }); } for (const auto& image : stage->images) { From 6bf42aa9859c6af758190f23c08d05f1a96ad210 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:08:43 +0300 Subject: [PATCH 113/147] vk_graphics_pipeline: Fix texel buffer offset --- src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 926b7d7cc..1ab65737c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -422,7 +422,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, ASSERT(adjust % fmt_stride == 0); push_data.AddOffset(binding, adjust / fmt_stride); } - buffer_view = vk_buffer->View(offset, size + adjust, tex_buffer.is_written, + buffer_view = vk_buffer->View(offset_aligned, size + adjust, tex_buffer.is_written, vsharp.GetDataFmt(), vsharp.GetNumberFmt()); } set_writes.push_back({ From 1651db24fe6f972ecad611f4f55404574b68e86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hage?= <33609333+greggameplayer@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:43:12 +0200 Subject: [PATCH 114/147] Implement S_XNOR_B64 (#654) --- src/shader_recompiler/frontend/translate/scalar_alu.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index da74f9018..af258cd19 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -31,6 +31,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) { return S_OR_B64(NegateMode::Result, false, inst); case Opcode::S_XOR_B64: return S_OR_B64(NegateMode::None, true, inst); + case Opcode::S_XNOR_B64: + return S_OR_B64(NegateMode::Result, true, inst); case Opcode::S_ORN2_B64: return S_OR_B64(NegateMode::Src1, false, inst); case Opcode::S_AND_B64: From a17150960f01b728d17522791c714d2d5ff10c79 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 19 Jul 2024 01:09:07 -0700 Subject: [PATCH 115/147] Add patches for F16C instructions under Rosetta 2. --- .gitmodules | 5 +- CMakeLists.txt | 3 + externals/CMakeLists.txt | 16 +- externals/half | 1 + src/core/cpu_patches.cpp | 291 ++++++++++++++++-- src/core/cpu_patches.h | 6 + .../libraries/kernel/thread_management.cpp | 3 + src/core/linker.cpp | 4 + 8 files changed, 292 insertions(+), 37 deletions(-) create mode 160000 externals/half diff --git a/.gitmodules b/.gitmodules index 949965866..95b0fc0bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -81,4 +81,7 @@ [submodule "externals/ffmpeg-core"] path = externals/ffmpeg-core url = https://github.com/shadps4-emu/ext-ffmpeg-core.git - shallow = true \ No newline at end of file + shallow = true +[submodule "externals/half"] + path = externals/half + url = https://github.com/ROCm/half.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 04740784b..5601556dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -638,6 +638,9 @@ if (APPLE) # Replacement for std::chrono::time_zone target_link_libraries(shadps4 PRIVATE date::date-tz) + + # Half float conversions for F16C patches + target_link_libraries(shadps4 PRIVATE half) endif() if (NOT ENABLE_QT_GUI) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 6fe73a29a..de0317ff9 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -142,11 +142,17 @@ if (WIN32) target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument") endif() -# date -if (APPLE AND NOT TARGET date::date-tz) - option(BUILD_TZ_LIB "" ON) - option(USE_SYSTEM_TZ_DB "" ON) - add_subdirectory(date) +if (APPLE) + # half + add_library(half INTERFACE) + target_include_directories(half INTERFACE half/include) + + # date + if (NOT TARGET date::date-tz) + option(BUILD_TZ_LIB "" ON) + option(USE_SYSTEM_TZ_DB "" ON) + add_subdirectory(date) + endif() endif() # Tracy diff --git a/externals/half b/externals/half new file mode 160000 index 000000000..1ddada225 --- /dev/null +++ b/externals/half @@ -0,0 +1 @@ +Subproject commit 1ddada225144cac0de8f6b5c0dd9acffd99a2e68 diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp index 42318822b..55bbf23b1 100644 --- a/src/core/cpu_patches.cpp +++ b/src/core/cpu_patches.cpp @@ -15,6 +15,7 @@ #else #include #ifdef __APPLE__ +#include #include #endif #endif @@ -30,6 +31,12 @@ static Xbyak::Reg ZydisToXbyakRegister(const ZydisRegister reg) { if (reg >= ZYDIS_REGISTER_RAX && reg <= ZYDIS_REGISTER_R15) { return Xbyak::Reg64(reg - ZYDIS_REGISTER_RAX + Xbyak::Operand::RAX); } + if (reg >= ZYDIS_REGISTER_XMM0 && reg <= ZYDIS_REGISTER_XMM31) { + return Xbyak::Xmm(reg - ZYDIS_REGISTER_XMM0 + xmm0.getIdx()); + } + if (reg >= ZYDIS_REGISTER_YMM0 && reg <= ZYDIS_REGISTER_YMM31) { + return Xbyak::Ymm(reg - ZYDIS_REGISTER_YMM0 + ymm0.getIdx()); + } UNREACHABLE_MSG("Unsupported register: {}", static_cast(reg)); } @@ -66,6 +73,12 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera return ptr[expression]; } +static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) { + ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE, + "Expected immediate operand, got type: {}", static_cast(operand.type)); + return operand.imm.value.u; +} + static std::unique_ptr ZydisToXbyakOperand(const ZydisDecodedOperand& operand) { switch (operand.type) { case ZYDIS_OPERAND_TYPE_REGISTER: { @@ -110,51 +123,135 @@ static Xbyak::Reg AllocateScratchRegister( #ifdef __APPLE__ -static constexpr u32 MaxSavedRegisters = 3; -static pthread_key_t register_save_slots[MaxSavedRegisters]; -static std::once_flag register_save_init_flag; +static pthread_key_t stack_pointer_slot; +static pthread_key_t patch_stack_slot; +static std::once_flag patch_context_slots_init_flag; static_assert(sizeof(void*) == sizeof(u64), "Cannot fit a register inside a thread local storage slot."); -static void InitializeRegisterSaveSlots() { - for (u32 i = 0; i < MaxSavedRegisters; i++) { - ASSERT_MSG(pthread_key_create(®ister_save_slots[i], nullptr) == 0, - "Unable to allocate thread-local register save slot {}", i); +static void InitializePatchContextSlots() { + ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0, + "Unable to allocate thread-local register for stack pointer."); + ASSERT_MSG(pthread_key_create(&patch_stack_slot, nullptr) == 0, + "Unable to allocate thread-local register for patch stack."); +} + +void InitializeThreadPatchStack() { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + const auto* patch_stack = std::malloc(0x1000); + pthread_setspecific(patch_stack_slot, patch_stack); +} + +void CleanupThreadPatchStack() { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + auto* patch_stack = pthread_getspecific(patch_stack_slot); + if (patch_stack != nullptr) { + std::free(patch_stack); + pthread_setspecific(patch_stack_slot, nullptr); } } +/// Saves the stack pointer to thread local storage and loads the patch stack. +static void SaveStack(Xbyak::CodeGenerator& c) { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + // Save stack pointer and load patch stack. + c.putSeg(gs); + c.mov(qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))], rsp); + c.putSeg(gs); + c.mov(rsp, qword[reinterpret_cast(patch_stack_slot * sizeof(void*))]); +} + +/// Restores the stack pointer from thread local storage. +static void RestoreStack(Xbyak::CodeGenerator& c) { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + // Save patch stack pointer and load original stack. + c.putSeg(gs); + c.mov(qword[reinterpret_cast(patch_stack_slot * sizeof(void*))], rsp); + c.putSeg(gs); + c.mov(rsp, qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))]); +} + +#else + +// These utilities are not implemented as we can't save anything to thread local storage without +// temporary registers. +void InitializeThreadPatchStack() { + // No-op +} + +void CleanupThreadPatchStack() { + // No-op +} + +/// Saves the stack pointer to thread local storage and loads the patch stack. +static void SaveStack(Xbyak::CodeGenerator& c) { + UNIMPLEMENTED(); +} + +/// Restores the stack pointer from thread local storage. +static void RestoreStack(Xbyak::CodeGenerator& c) { + UNIMPLEMENTED(); +} + +#endif + +/// Switches to the patch stack, saves registers, and restores the original stack. static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list regs) { - ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to save {} registers.", - regs.size()); - - std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots); - - u32 index = 0; + SaveStack(c); for (const auto& reg : regs) { - const auto offset = reinterpret_cast(register_save_slots[index++] * sizeof(void*)); - - c.putSeg(gs); - c.mov(qword[offset], reg.cvt64()); + c.push(reg.cvt64()); } + RestoreStack(c); } +/// Switches to the patch stack, restores registers, and restores the original stack. static void RestoreRegisters(Xbyak::CodeGenerator& c, const std::initializer_list regs) { - ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to restore {} registers.", - regs.size()); - - std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots); - - u32 index = 0; + SaveStack(c); for (const auto& reg : regs) { - const auto offset = reinterpret_cast(register_save_slots[index++] * sizeof(void*)); + c.pop(reg.cvt64()); + } + RestoreStack(c); +} - c.putSeg(gs); - c.mov(reg.cvt64(), qword[offset]); +/// Switches to the patch stack and stores all registers. +static void SaveContext(Xbyak::CodeGenerator& c) { + SaveStack(c); + for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) { + c.push(Xbyak::Reg64(reg)); + } + for (int reg = 0; reg <= 7; reg++) { + c.sub(rsp, 32); + c.vmovdqu(ptr[rsp], Xbyak::Ymm(reg)); } } +/// Restores all registers and restores the original stack. +/// If the destination is a register, it is not restored to preserve the output. +static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst) { + for (int reg = 7; reg >= 0; reg--) { + if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) { + c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp]); + } + c.add(rsp, 32); + } + for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) { + if (!dst.isREG() || dst.getIdx() != reg) { + c.pop(Xbyak::Reg64(reg)); + } else { + c.add(rsp, 4); + } + } + RestoreStack(c); +} + +#ifdef __APPLE__ + static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { const auto dst = ZydisToXbyakRegisterOperand(operands[0]); const auto src1 = ZydisToXbyakRegisterOperand(operands[1]); @@ -204,9 +301,9 @@ static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenera c.and_(dst, scratch2); if (dst.getIdx() == shift.getIdx()) { - RestoreRegisters(c, {scratch1, scratch2}); + RestoreRegisters(c, {scratch2, scratch1}); } else { - RestoreRegisters(c, {scratch1, scratch2, shift}); + RestoreRegisters(c, {shift, scratch2, scratch1}); } } @@ -258,10 +355,138 @@ static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat RestoreRegisters(c, {scratch}); } -bool FilterRosetta2Only(const ZydisDecodedOperand*) { +static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in, + const u32 count) { + for (u32 i = 0; i < count; i++) { + out[i] = half_float::half_cast(in[i]); + } +} + +static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { + const auto dst = ZydisToXbyakRegisterOperand(operands[0]); + const auto src = ZydisToXbyakOperand(operands[1]); + + const auto float_count = dst.getBit() / 32; + const auto byte_count = float_count * 4; + + SaveContext(c); + + // Allocate stack space for outputs and load into first parameter. + c.sub(rsp, byte_count); + c.mov(rdi, rsp); + + if (src->isXMM()) { + // Allocate stack space for inputs and load into second parameter. + c.sub(rsp, byte_count); + c.mov(rsi, rsp); + + // Move input to the allocated space. + c.movdqu(ptr[rsp], *reinterpret_cast(src.get())); + } else { + c.lea(rsi, src->getAddress()); + } + + // Load float count into third parameter. + c.mov(rdx, float_count); + + c.mov(rax, reinterpret_cast(PerformVCVTPH2PS)); + c.call(rax); + + if (src->isXMM()) { + // Clean up after inputs space. + c.add(rsp, byte_count); + } + + // Load outputs into destination register and clean up space. + if (dst.isYMM()) { + c.vmovdqu(*reinterpret_cast(&dst), ptr[rsp]); + } else { + c.movdqu(*reinterpret_cast(&dst), ptr[rsp]); + } + c.add(rsp, byte_count); + + RestoreContext(c, dst); +} + +using SingleToHalfFloatConverter = half_float::half (*)(float); +static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = { + half_float::half_cast, + half_float::half_cast, + half_float::half_cast, + half_float::half_cast, +}; + +static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in, + const u32 count, const u8 rounding_mode) { + const auto conversion_func = SingleToHalfFloatConverters[rounding_mode]; + + for (u32 i = 0; i < count; i++) { + out[i] = conversion_func(in[i]); + } +} + +static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { + const auto dst = ZydisToXbyakOperand(operands[0]); + const auto src = ZydisToXbyakRegisterOperand(operands[1]); + const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]); + + const auto float_count = src.getBit() / 32; + const auto byte_count = float_count * 4; + + SaveContext(c); + + if (dst->isXMM()) { + // Allocate stack space for outputs and load into first parameter. + c.sub(rsp, byte_count); + c.mov(rdi, rsp); + } else { + c.lea(rdi, dst->getAddress()); + } + + // Allocate stack space for inputs and load into second parameter. + c.sub(rsp, byte_count); + c.mov(rsi, rsp); + + // Move input to the allocated space. + if (src.isYMM()) { + c.vmovdqu(ptr[rsp], *reinterpret_cast(&src)); + } else { + c.movdqu(ptr[rsp], *reinterpret_cast(&src)); + } + + // Load float count into third parameter. + c.mov(rdx, float_count); + + // Load rounding mode into fourth parameter. + if (ctrl & 4) { + // Load from MXCSR.RC. + c.stmxcsr(ptr[rsp - 4]); + c.mov(rcx, ptr[rsp - 4]); + c.shr(rcx, 13); + c.and_(rcx, 3); + } else { + c.mov(rcx, ctrl & 3); + } + + c.mov(rax, reinterpret_cast(PerformVCVTPS2PH)); + c.call(rax); + + // Clean up after inputs space. + c.add(rsp, byte_count); + + if (dst->isXMM()) { + // Load outputs into destination register and clean up space. + c.movdqu(*reinterpret_cast(dst.get()), ptr[rsp]); + c.add(rsp, byte_count); + } + + RestoreContext(c, *dst); +} + +static bool FilterRosetta2Only(const ZydisDecodedOperand*) { int ret = 0; size_t size = sizeof(ret); - if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) != 0) { + if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) { return false; } return ret; @@ -339,12 +564,16 @@ static const std::unordered_map Patches = { #endif #ifdef __APPLE__ - // BMI1 instructions that are not supported by Rosetta 2 on Apple Silicon. + // Patches for instruction sets not supported by Rosetta 2. + // BMI1 {ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}}, {ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}}, {ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}}, {ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}}, {ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}}, + // F16C + {ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}}, + {ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}}, #endif }; diff --git a/src/core/cpu_patches.h b/src/core/cpu_patches.h index 45adbeda3..9126074ed 100644 --- a/src/core/cpu_patches.h +++ b/src/core/cpu_patches.h @@ -9,6 +9,12 @@ class CodeGenerator; namespace Core { +/// Initializes a stack for the current thread for use by patch implementations. +void InitializeThreadPatchStack(); + +/// Cleans up the patch stack for the current thread. +void CleanupThreadPatchStack(); + /// Patches CPU instructions that cannot run as-is on the host. void PatchInstructions(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c); diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 605d0d29f..ac7c8da83 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -10,6 +10,7 @@ #include "common/logging/log.h" #include "common/singleton.h" #include "common/thread.h" +#include "core/cpu_patches.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/kernel/thread_management.h" @@ -985,6 +986,7 @@ static void cleanup_thread(void* arg) { destructor(value); } } + Core::CleanupThreadPatchStack(); thread->is_almost_done = true; } @@ -993,6 +995,7 @@ static void* run_thread(void* arg) { Common::SetCurrentThreadName(thread->name.c_str()); auto* linker = Common::Singleton::Instance(); linker->InitTlsForThread(false); + Core::InitializeThreadPatchStack(); void* ret = nullptr; g_pthread_self = thread; pthread_cleanup_push(cleanup_thread, thread); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 9783ad96f..2e242129a 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -10,6 +10,7 @@ #include "common/thread.h" #include "core/aerolib/aerolib.h" #include "core/aerolib/stubs.h" +#include "core/cpu_patches.h" #include "core/libraries/kernel/memory_management.h" #include "core/libraries/kernel/thread_management.h" #include "core/linker.h" @@ -86,6 +87,7 @@ void Linker::Execute() { Common::SetCurrentThreadName("GAME_MainThread"); Libraries::Kernel::pthreadInitSelfMainThread(); InitTlsForThread(true); + InitializeThreadPatchStack(); // Start shared library modules for (auto& m : m_modules) { @@ -104,6 +106,8 @@ void Linker::Execute() { RunMainEntry(m->GetEntryAddress(), &p, ProgramExitFunc); } } + + CleanupThreadPatchStack(); } s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { From f2b6843f9d9024978870da02fba41ca267bee119 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Thu, 29 Aug 2024 23:11:20 -0300 Subject: [PATCH 116/147] fix tr --- src/qt_gui/cheats_patches.cpp | 3 +- src/qt_gui/main_window.cpp | 36 +++++++++--------- src/qt_gui/translations/da_DK.ts | 58 ++++++++++++++--------------- src/qt_gui/translations/de.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/el.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/en.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/es_ES.ts | 64 ++++++++++++++++---------------- src/qt_gui/translations/fi.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/fr.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/hu_HU.ts | 64 ++++++++++++++++---------------- src/qt_gui/translations/id.ts | 64 ++++++++++++++++---------------- src/qt_gui/translations/it.ts | 56 ++++++++++++++-------------- src/qt_gui/translations/ja_JP.ts | 64 ++++++++++++++++---------------- src/qt_gui/translations/ko_KR.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/lt_LT.ts | 64 ++++++++++++++++---------------- src/qt_gui/translations/nb.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/nl.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/pl_PL.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/pt_BR.ts | 62 +++++++++++++++---------------- src/qt_gui/translations/ro_RO.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/ru_RU.ts | 62 +++++++++++++++---------------- src/qt_gui/translations/tr_TR.ts | 64 ++++++++++++++++---------------- src/qt_gui/translations/vi_VN.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/zh_CN.ts | 60 +++++++++++++++--------------- src/qt_gui/translations/zh_TW.ts | 60 +++++++++++++++--------------- 25 files changed, 721 insertions(+), 720 deletions(-) diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index 47acf068c..fd0bc4e14 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -175,7 +175,8 @@ void CheatsPatches::setupUI() { int ret = QMessageBox::warning( this, tr("Delete File"), - QString(tr("Do you want to delete the selected file?\n%1")).arg(selectedFileName), + QString(tr("Do you want to delete the selected file?\\n%1").replace("\\n", "\n")) + .arg(selectedFileName), QMessageBox::Yes | QMessageBox::No); if (ret == QMessageBox::Yes) { diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 9571f5d7b..944ff4a6b 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -642,24 +642,24 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int double appD = game_app_version.toDouble(); double pkgD = pkg_app_version.toDouble(); if (pkgD == appD) { - msgBox.setText(QString(tr("Patch detected!\nPKG and Game versions match!: " - "%1\nWould you like ") + - tr("to overwrite?")) - .arg(pkg_app_version)); + msgBox.setText(QString(tr("Patch detected!") + "\n" + + tr("PKG and Game versions match: ") + pkg_app_version + + "\n" + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } else if (pkgD < appD) { - msgBox.setText(QString(tr("Patch detected!\nPKG Version %1 is older ") + - tr("than installed version!: %2\nWould you like ") + - tr("to overwrite?")) - .arg(pkg_app_version, game_app_version)); + msgBox.setText(QString(tr("Patch detected!") + "\n" + + tr("PKG Version %1 is older than installed version: ") + .arg(pkg_app_version) + + game_app_version + "\n" + + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } else { - msgBox.setText( - QString(tr("Patch detected!\nGame is installed: %1\nWould you like ") + - tr("to install Patch: %2?")) - .arg(game_app_version, pkg_app_version)); + msgBox.setText(QString(tr("Patch detected!") + "\n" + + tr("Game is installed: ") + game_app_version + "\n" + + tr("Would you like to install Patch: ") + + pkg_app_version + " ?")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } @@ -685,9 +685,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int return; } } else { - msgBox.setText( - QString("DLC already installed\n%1\nWould you like to overwrite?") - .arg(QString::fromStdString(addon_extract_path.string()))); + msgBox.setText(QString(tr("DLC already installed:") + "\n" + + QString::fromStdString(addon_extract_path.string()) + + "\n\n" + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int result = msgBox.exec(); @@ -698,9 +698,9 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } } } else { - msgBox.setText( - QString(tr("Game already installed\n%1\nWould you like to overwrite?")) - .arg(QString::fromStdString(extract_path.string()))); + msgBox.setText(QString(tr("Game already installed") + "\n" + + QString::fromStdString(extract_path.string()) + "\n" + + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int result = msgBox.exec(); diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index c5a65b5c4..c67d29b1d 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -566,44 +566,34 @@ PKG-udtrækning - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch opdaget!\nPKG- og spilversioner stemmer overens!: %1\nVil du + + Patch detected! + Opdatering detekteret! - - to overwrite? - overskrive? + + PKG and Game versions match: + PKG og spilversioner matcher: - - Patch detected!\nPKG Version %1 is older - Patch opdaget!\nPKG-version %1 er ældre + + Would you like to overwrite? + Vil du overskrive? - - than installed version!: %2\nWould you like - end installeret version!: %2\nVil du + + PKG Version %1 is older than installed version: + PKG Version %1 er ældre end den installerede version: - - to overwrite? - overskrive? + + Game is installed: + Spillet er installeret: - - Patch detected!\nGame is installed: %1\nWould you like - Patch opdaget!\nSpillet er installeret: %1\nVil du - - - - to install Patch: %2? - installere patch: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Spil allerede installeret\n%1\nVil du overskrive? + + Would you like to install Patch: + Vil du installere opdateringen: @@ -613,7 +603,17 @@ Would you like to install DLC: %1? - Would you like to install DLC: %1? + Vil du installere DLC: %1? + + + + DLC already installed: + DLC allerede installeret: + + + + Game already installed + Spillet er allerede installeret diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index 1819ef0cb..c833f2e28 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -566,54 +566,54 @@ PKG-Extraktion - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch erkannt!\nPKG- und Spielversion stimmen überein!: %1\nMöchten Sie + + Patch detected! + Patch erkannt! - - to overwrite? - überschreiben? + + PKG and Game versions match: + PKG- und Spielversionen stimmen überein: - - Patch detected!\nPKG Version %1 is older - Patch erkannt!\nPKG-Version %1 ist älter + + Would you like to overwrite? + Würden Sie gerne überschreiben? - - than installed version!: %2\nWould you like - als die installierte Version!: %2\nMöchten Sie + + PKG Version %1 is older than installed version: + PKG-Version %1 ist älter als die installierte Version: - - to overwrite? - überschreiben? + + Game is installed: + Spiel ist installiert: - - Patch detected!\nGame is installed: %1\nWould you like - Patch erkannt!\nSpiel ist installiert: %1\nMöchten Sie - - - - to install Patch: %2? - Patch installieren: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Spiel bereits installiert\n%1\nMöchten Sie überschreiben? + + Would you like to install Patch: + Möchten Sie den Patch installieren: DLC Installation - DLC Installation + DLC-Installation Would you like to install DLC: %1? - Would you like to install DLC: %1? + Würden Sie gerne DLC installieren: %1? + + + + DLC already installed: + DLC bereits installiert: + + + + Game already installed + Spiel bereits installiert diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts index a5b8e9ebd..ef831fb09 100644 --- a/src/qt_gui/translations/el.ts +++ b/src/qt_gui/translations/el.ts @@ -566,54 +566,54 @@ Εξαγωγή PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Ανίχνευση Patch!\nΟι εκδόσεις PKG και παιχνιδιού ταιριάζουν!: %1\nΘέλετε + + Patch detected! + Αναγνώριση ενημέρωσης! - - to overwrite? - να αντικαταστήσετε; + + PKG and Game versions match: + Οι εκδόσεις PKG και παιχνιδιού ταιριάζουν: - - Patch detected!\nPKG Version %1 is older - Ανίχνευση Patch!\nΗ έκδοση PKG %1 είναι παλαιότερη + + Would you like to overwrite? + Θέλετε να αντικαταστήσετε; - - than installed version!: %2\nWould you like - από την εγκατεστημένη έκδοση!: %2\nΘέλετε + + PKG Version %1 is older than installed version: + Η έκδοση PKG %1 είναι παλαιότερη από την εγκατεστημένη έκδοση: - - to overwrite? - να αντικαταστήσετε; + + Game is installed: + Το παιχνίδι είναι εγκατεστημένο: - - Patch detected!\nGame is installed: %1\nWould you like - Ανίχνευση Patch!\nΤο παιχνίδι είναι εγκατεστημένο: %1\nΘέλετε - - - - to install Patch: %2? - να εγκαταστήσετε το Patch: %2; - - - - Game already installed\n%1\nWould you like to overwrite? - Το παιχνίδι είναι ήδη εγκατεστημένο\n%1\nΘέλετε να αντικαταστήσετε; + + Would you like to install Patch: + Θέλετε να εγκαταστήσετε την ενημέρωση: DLC Installation - DLC Installation + Εγκατάσταση DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Θέλετε να εγκαταστήσετε το DLC: %1; + + + + DLC already installed: + DLC ήδη εγκατεστημένο: + + + + Game already installed + Παιχνίδι ήδη εγκατεστημένο diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts index 97da0a786..b3c3b699b 100644 --- a/src/qt_gui/translations/en.ts +++ b/src/qt_gui/translations/en.ts @@ -566,44 +566,34 @@ PKG Extraction - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch detected!\nPKG and Game versions match!: %1\nWould you like - - - - to overwrite? - to overwrite? - - - - Patch detected!\nPKG Version %1 is older - Patch detected!\nPKG Version %1 is older - - - - than installed version!: %2\nWould you like - than installed version!: %2\nWould you like - - - - to overwrite? - to overwrite? + + Patch detected! + Patch detected! - Patch detected!\nGame is installed: %1\nWould you like - Patch detected!\nGame is installed: %1\nWould you like + PKG and Game versions match: + PKG and Game versions match: - to install Patch: %2? - to install Patch: %2? + Would you like to overwrite? + Would you like to overwrite? - - Game already installed\n%1\nWould you like to overwrite? - Game already installed\n%1\nWould 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: @@ -615,6 +605,16 @@ 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 is a patch, please install the game first! diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index b60595a9e..c34dc3d44 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -566,54 +566,54 @@ Extracción de PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - ¡Parche detectado!\n¡La versión de PKG y del juego coinciden!: %1\n¿Te gustaría - - - - to overwrite? - ¿sobrescribir? - - - - Patch detected!\nPKG Version %1 is older - ¡Parche detectado!\nLa versión de PKG %1 es más antigua - - - - than installed version!: %2\nWould you like - que la versión instalada!: %2\n¿Te gustaría - - - - to overwrite? - ¿sobrescribir? + + Patch detected! + ¡Actualización detectada! - Patch detected!\nGame is installed: %1\nWould you like - ¡Parche detectado!\nJuego está instalado: %1\n¿Te gustaría + PKG and Game versions match: + Las versiones de PKG y del juego coinciden: - to install Patch: %2? - ¿instalar el parche: %2? + Would you like to overwrite? + ¿Desea sobrescribir? - - Game already installed\n%1\nWould you like to overwrite? - Juego ya instalado\n%1\n¿Te gustaría sobrescribirlo? + + PKG Version %1 is older than installed version: + La versión de PKG %1 es más antigua que la versión instalada: + + + + Game is installed: + El juego está instalado: + + + + Would you like to install Patch: + ¿Desea instalar la actualización: DLC Installation - DLC Installation + Instalación de DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + ¿Desea instalar el DLC: %1? + + + + DLC already installed: + DLC ya instalado: + + + + Game already installed + Juego ya instalado diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts index c998d89e5..d667dd379 100644 --- a/src/qt_gui/translations/fi.ts +++ b/src/qt_gui/translations/fi.ts @@ -566,54 +566,54 @@ PKG:n purku - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Korjaus havaittu!\nPKG:n ja pelin versiot vastaavat!: %1\nHaluatko + + Patch detected! + Päivitys havaittu! - - to overwrite? - korvata? + + PKG and Game versions match: + PKG- ja peliversiot vastaavat: - - Patch detected!\nPKG Version %1 is older - Korjaus havaittu!\nPKG Version %1 on vanhempi + + Would you like to overwrite? + Haluatko korvata? - - than installed version!: %2\nWould you like - kuin asennettu versio!: %2\nHaluatko + + PKG Version %1 is older than installed version: + PKG-versio %1 on vanhempi kuin asennettu versio: - - to overwrite? - korvata? + + Game is installed: + Peli on asennettu: - - Patch detected!\nGame is installed: %1\nWould you like - Korjaus havaittu!\nPeli on asennettu: %1\nHaluatko - - - - to install Patch: %2? - asentaa korjaus: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Peli on jo asennettu\n%1\nHaluatko korvata sen? + + Would you like to install Patch: + Haluatko asentaa päivityksen: DLC Installation - DLC Installation + DLC-asennus Would you like to install DLC: %1? - Would you like to install DLC: %1? + Haluatko asentaa DLC:n: %1? + + + + DLC already installed: + DLC on jo asennettu: + + + + Game already installed + Peli on jo asennettu diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index cf64d760d..388912d23 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -566,54 +566,54 @@ Extraction du PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch détecté !\nLa version du PKG et du jeu correspondent : %1\nSouhaitez-vous + + Patch detected! + Patch détecté ! - - to overwrite? - écraser ? + + PKG and Game versions match: + Les versions PKG et jeu correspondent : - - Patch detected!\nPKG Version %1 is older - Patch détecté !\nVersion PKG %1 est plus ancienne + + Would you like to overwrite? + Souhaitez-vous remplacer ? - - than installed version!: %2\nWould you like - que la version installée ! : %2\nSouhaitez-vous + + PKG Version %1 is older than installed version: + La version PKG %1 est plus ancienne que la version installée : - - to overwrite? - écraser ? + + Game is installed: + Jeu installé : - - Patch detected!\nGame is installed: %1\nWould you like - Patch détecté !\nJeu est installé : %1\nSouhaitez-vous - - - - to install Patch: %2? - installer le patch : %2 ? - - - - Game already installed\n%1\nWould you like to overwrite? - Jeu déjà installé\n%1\nSouhaitez-vous écraser ? + + Would you like to install Patch: + Souhaitez-vous installer le patch : DLC Installation - DLC Installation + Installation du DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Souhaitez-vous installer le DLC : %1 ? + + + + DLC already installed: + DLC déjà installé : + + + + Game already installed + Jeu déjà installé diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index 53c9d46e6..e5fb25a5d 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -566,54 +566,54 @@ PKG kicsomagolás - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Javítás észlelve!\nA PKG és a játék verziók egyeznek: %1\nSzeretnéd - - - - to overwrite? - felülírni? - - - - Patch detected!\nPKG Version %1 is older - Javítás észlelve!\nA PKG verzió %1 régebbi - - - - than installed version!: %2\nWould you like - mint a telepített verzió: %2\nSzeretnéd - - - - to overwrite? - felülírni? + + Patch detected! + Frissítés észlelve! - Patch detected!\nGame is installed: %1\nWould you like - Javítás észlelve!\nA játék telepítve van: %1\nSzeretnéd + PKG and Game versions match: + A PKG és a játék verziói egyeznek: - to install Patch: %2? - a javítást telepíteni: %2? + Would you like to overwrite? + Szeretné felülírni? - - Game already installed\n%1\nWould you like to overwrite? - A játék már telepítve van\n%1\nSzeretnéd felülírni? + + PKG Version %1 is older than installed version: + A %1-es PKG verzió régebbi, mint a telepített verzió: + + + + Game is installed: + A játék telepítve van: + + + + Would you like to install Patch: + Szeretné telepíteni a frissítést: DLC Installation - DLC Installation + DLC Telepítés Would you like to install DLC: %1? - Would you like to install DLC: %1? + Szeretné telepíteni a DLC-t: %1? + + + + DLC already installed: + DLC már telepítve: + + + + Game already installed + A játék már telepítve van diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts index 9f31bd779..b8ce27cde 100644 --- a/src/qt_gui/translations/id.ts +++ b/src/qt_gui/translations/id.ts @@ -566,54 +566,54 @@ Ekstraksi PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch terdeteksi!\nVersi PKG dan Game cocok!: %1\nApakah Anda ingin - - - - to overwrite? - menimpa? - - - - Patch detected!\nPKG Version %1 is older - Patch terdeteksi!\nVersi PKG %1 lebih lama - - - - than installed version!: %2\nWould you like - daripada versi yang terpasang!: %2\nApakah Anda ingin - - - - to overwrite? - menimpa? + + Patch detected! + Patch terdeteksi! - Patch detected!\nGame is installed: %1\nWould you like - Patch terdeteksi!\nGame terpasang: %1\nApakah Anda ingin + PKG and Game versions match: + Versi PKG dan Game cocok: - to install Patch: %2? - memasang Patch: %2? + Would you like to overwrite? + Apakah Anda ingin menimpa? - - Game already installed\n%1\nWould you like to overwrite? - Game sudah terpasang\n%1\nApakah Anda ingin menimpa? + + PKG Version %1 is older than installed version: + Versi PKG %1 lebih lama dari versi yang terpasang: + + + + Game is installed: + Game telah terpasang: + + + + Would you like to install Patch: + Apakah Anda ingin menginstal patch: DLC Installation - DLC Installation + Instalasi DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Apakah Anda ingin menginstal DLC: %1? + + + + DLC already installed: + DLC sudah terpasang: + + + + Game already installed + Game sudah terpasang diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 846d27d14..cf0faa6bf 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -566,44 +566,34 @@ Estrazione file PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch rilevata! Il\nPKG e la versione del gioco coincidono!: %1\nVuoi + + Patch detected! + Patch rilevato! - - to overwrite? - sovrascrivere? + + PKG and Game versions match: + Le versioni di PKG e del gioco corrispondono: - - Patch detected!\nPKG Version %1 is older - Patch rilevata! La \nPKG Versione %1 è più vecchia + + Would you like to overwrite? + Vuoi sovrascrivere? - - than installed version!: %2\nWould you like - della versione installata!: %2\nVuoi + + PKG Version %1 is older than installed version: + La versione PKG %1 è più vecchia rispetto alla versione installata: - - to overwrite? - sovrascrivere? + + Game is installed: + Gioco installato: - - Patch detected!\nGame is installed: %1\nWould you like - Patch rilevata!\nGioco installato: %1\Vuoi - - - - to install Patch: %2? - installare la Patch: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Gioco già installato\n%1\nVuoi sovrascrivere?? + + Would you like to install Patch: + Vuoi installare il patch: @@ -615,6 +605,16 @@ Would you like to install DLC: %1? Vuoi installare il DLC: %1? + + + DLC already installed: + DLC già installato: + + + + Game already installed + Gioco già installato + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index acf0e613e..3d62de0de 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -566,54 +566,54 @@ PKG抽出 - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - パッチが検出されました!\nPKGとゲームバージョンが一致しています!: %1\n上書きしますか - - - - to overwrite? - 上書きしますか? - - - - Patch detected!\nPKG Version %1 is older - パッチが検出されました!\nPKGバージョン %1 は古い - - - - than installed version!: %2\nWould you like - インストールされているバージョンよりも古いです!: %2\n上書きしますか - - - - to overwrite? - 上書きしますか? + + Patch detected! + パッチが検出されました! - Patch detected!\nGame is installed: %1\nWould you like - パッチが検出されました!\nゲームがインストールされています: %1\nインストールしますか + PKG and Game versions match: + PKGとゲームのバージョンが一致しています: - to install Patch: %2? - パッチをインストールしますか: %2? + Would you like to overwrite? + 上書きしてもよろしいですか? - - Game already installed\n%1\nWould you like to overwrite? - ゲームはすでにインストールされています\n%1\n上書きしますか? + + PKG Version %1 is older than installed version: + PKGバージョン %1 はインストールされているバージョンよりも古いです: + + + + Game is installed: + ゲームはインストール済みです: + + + + Would you like to install Patch: + パッチをインストールしてもよろしいですか: DLC Installation - DLC Installation + DLCのインストール Would you like to install DLC: %1? - Would you like to install DLC: %1? + DLCをインストールしてもよろしいですか: %1? + + + + DLC already installed: + DLCはすでにインストールされています: + + + + Game already installed + ゲームはすでにインストールされています diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index cb15c24b8..f7f171dc6 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -566,44 +566,34 @@ PKG Extraction - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch detected!\nPKG and Game versions match!: %1\nWould you like - - - - to overwrite? - to overwrite? - - - - Patch detected!\nPKG Version %1 is older - Patch detected!\nPKG Version %1 is older - - - - than installed version!: %2\nWould you like - than installed version!: %2\nWould you like - - - - to overwrite? - to overwrite? + + Patch detected! + Patch detected! - Patch detected!\nGame is installed: %1\nWould you like - Patch detected!\nGame is installed: %1\nWould you like + PKG and Game versions match: + PKG and Game versions match: - to install Patch: %2? - to install Patch: %2? + Would you like to overwrite? + Would you like to overwrite? - - Game already installed\n%1\nWould you like to overwrite? - Game already installed\n%1\nWould 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: @@ -615,6 +605,16 @@ 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 is a patch, please install the game first! diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index 5f1276bca..7aa4402e6 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -566,54 +566,54 @@ PKG ištraukimas - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Pataisa aptikta!\nPKG ir žaidimo versijos atitinka!: %1\nAr norėtumėte - - - - to overwrite? - perrašyti? - - - - Patch detected!\nPKG Version %1 is older - Pataisa aptikta!\nPKG versija %1 yra senesnė - - - - than installed version!: %2\nWould you like - nei įdiegta versija!: %2\nAr norėtumėte - - - - to overwrite? - perrašyti? + + Patch detected! + Rasta atnaujinimą! - Patch detected!\nGame is installed: %1\nWould you like - Pataisa aptikta!\nŽaidimas įdiegtas: %1\nAr norėtumėte + PKG and Game versions match: + PKG ir žaidimo versijos sutampa: - to install Patch: %2? - įdiegti pataisą: %2? + Would you like to overwrite? + Ar norite perrašyti? - - Game already installed\n%1\nWould you like to overwrite? - Žaidimas jau įdiegtas\n%1\nAr norėtumėte perrašyti? + + PKG Version %1 is older than installed version: + PKG versija %1 yra senesnė nei įdiegta versija: + + + + Game is installed: + Žaidimas įdiegtas: + + + + Would you like to install Patch: + Ar norite įdiegti atnaujinimą: DLC Installation - DLC Installation + DLC diegimas Would you like to install DLC: %1? - Would you like to install DLC: %1? + Ar norite įdiegti DLC: %1? + + + + DLC already installed: + DLC jau įdiegtas: + + + + Game already installed + Žaidimas jau įdiegtas diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts index 01dc32f1d..76cad45b2 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb.ts @@ -566,54 +566,54 @@ PKG-ekstraksjon - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Oppdatering oppdaget!\nPKG og spillversjoner stemmer!: %1\nØnsker du å + + Patch detected! + Oppdatering oppdaget! - - to overwrite? - overskrive? + + PKG and Game versions match: + PKG- og spillversjoner stemmer overens: - - Patch detected!\nPKG Version %1 is older - Oppdatering oppdaget!\nPKG-versjon %1 er eldre + + Would you like to overwrite? + Ønsker du å overskrive? - - than installed version!: %2\nWould you like - enn installert versjon!: %2\nØnsker du å + + PKG Version %1 is older than installed version: + PKG-versjon %1 er eldre enn installert versjon: - - to overwrite? - overskrive? + + Game is installed: + Spillet er installert: - - Patch detected!\nGame is installed: %1\nWould you like - Oppdatering oppdaget!\nSpillet er installert: %1\nØnsker du å - - - - to install Patch: %2? - installere oppdateringen: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Spill allerede installert\n%1\nØnsker du å overskrive? + + Would you like to install Patch: + Ønsker du å installere oppdateringen: DLC Installation - DLC Installation + DLC-installasjon Would you like to install DLC: %1? - 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 diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts index 682321b9e..b00460479 100644 --- a/src/qt_gui/translations/nl.ts +++ b/src/qt_gui/translations/nl.ts @@ -566,54 +566,54 @@ PKG-extractie - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch gedetecteerd!\nPKG en spelversies komen overeen!: %1\nWil je + + Patch detected! + Patch gedetecteerd! - - to overwrite? - overschrijven? + + PKG and Game versions match: + PKG- en gameversies komen overeen: - - Patch detected!\nPKG Version %1 is older - Patch gedetecteerd!\nPKG-versie %1 is ouder + + Would you like to overwrite? + Wilt u overschrijven? - - than installed version!: %2\nWould you like - dan de geïnstalleerde versie!: %2\nWil je + + PKG Version %1 is older than installed version: + PKG-versie %1 is ouder dan de geïnstalleerde versie: - - to overwrite? - overschrijven? + + Game is installed: + Game is geïnstalleerd: - - Patch detected!\nGame is installed: %1\nWould you like - Patch gedetecteerd!\nSpel is geïnstalleerd: %1\nWil je - - - - to install Patch: %2? - de patch installeren: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Spel al geïnstalleerd\n%1\nWil je het overschrijven? + + Would you like to install Patch: + Wilt u de patch installeren: DLC Installation - DLC Installation + DLC-installatie Would you like to install DLC: %1? - Would you like to install DLC: %1? + Wilt u DLC installeren: %1? + + + + DLC already installed: + DLC al geïnstalleerd: + + + + Game already installed + Game al geïnstalleerd diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index 40f8933e1..80f0aa5c4 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -566,54 +566,54 @@ Ekstrakcja PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Wykryto poprawkę!\nWersje PKG i gry pasują do siebie!: %1\nCzy chcesz + + Patch detected! + Wykryto łatkę! - - to overwrite? - nadpisać? + + PKG and Game versions match: + Wersje PKG i gry są zgodne: - - Patch detected!\nPKG Version %1 is older - Wykryto poprawkę!\nWersja PKG %1 jest starsza + + Would you like to overwrite? + Czy chcesz nadpisać? - - than installed version!: %2\nWould you like - niż zainstalowana wersja!: %2\nCzy chcesz + + PKG Version %1 is older than installed version: + Wersja PKG %1 jest starsza niż zainstalowana wersja: - - to overwrite? - nadpisać? + + Game is installed: + Gra jest zainstalowana: - - Patch detected!\nGame is installed: %1\nWould you like - Wykryto poprawkę!\nGra jest zainstalowana: %1\nCzy chcesz - - - - to install Patch: %2? - zainstalować poprawkę: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Gra już zainstalowana\n%1\nCzy chcesz ją nadpisać? + + Would you like to install Patch: + Czy chcesz zainstalować łatkę: DLC Installation - Instalacja dodadkowej zawartości (DLC) + Instalacja DLC Would you like to install DLC: %1? - Czy na pewno chcesz zainstalować dodatkową zawartość (DLC): %1? + Czy chcesz zainstalować DLC: %1? + + + + DLC already installed: + DLC już zainstalowane: + + + + Game already installed + Gra już zainstalowana diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 96fb78f86..8b4538b9d 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -566,44 +566,34 @@ Extração de PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch detectado!\nVersões PKG e do Jogo correspondem!: %1\nGostaria de - - - - to overwrite? - substituir? - - - - Patch detected!\nPKG Version %1 is older - Patch detectado!\nVersão do PKG %1 é mais antiga - - - - than installed version!: %2\nWould you like - do que a versão instalada!: %2\nGostaria de - - - - to overwrite? - substituir? + + Patch detected! + Atualização detectada! - Patch detected!\nGame is installed: %1\nWould you like - Patch detectado!\nO Jogo está instalado: %1\nGostaria de + PKG and Game versions match: + As versões do PKG e do Jogo são igual: - to install Patch: %2? - instalar o Patch: %2? + Would you like to overwrite? + Gostaria de substituir? - - Game already installed\n%1\nWould you like to overwrite? - Jogo já instalado\n%1\nGostaria de substituir? + + PKG Version %1 is older than installed version: + Versão do PKG %1 é mais antiga do que a versão instalada: + + + + Game is installed: + Jogo instalado: + + + + Would you like to install Patch: + Você gostaria de instalar a atualização: @@ -613,7 +603,17 @@ Would you like to install DLC: %1? - Gostaria de instalar a DLC: %1? + Você gostaria de instalar o DLC: %1? + + + + DLC already installed: + DLC já instalada: + + + + Game already installed + O jogo já está instalado: diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index af5c57630..8b2fda0c1 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -566,54 +566,54 @@ Extracție PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Patch detectat!\nVersiunile PKG și Joc se potrivesc!: %1\nAi dori să + + Patch detected! + Patch detectat! - - to overwrite? - să suprascrii? + + PKG and Game versions match: + Versiunile PKG și ale jocului sunt compatibile: - - Patch detected!\nPKG Version %1 is older - Patch detectat!\nVersiunea PKG %1 este mai veche + + Would you like to overwrite? + Doriți să suprascrieți? - - than installed version!: %2\nWould you like - decât versiunea instalată!: %2\nAi dori să + + PKG Version %1 is older than installed version: + Versiunea PKG %1 este mai veche decât versiunea instalată: - - to overwrite? - să suprascrii? + + Game is installed: + Jocul este instalat: - - Patch detected!\nGame is installed: %1\nWould you like - Patch detectat!\nJocul este instalat: %1\nAi dori să - - - - to install Patch: %2? - să instalezi Patch-ul: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Jocul este deja instalat\n%1\nAi dori să suprascrii? + + Would you like to install Patch: + Doriți să instalați patch-ul: DLC Installation - DLC Installation + Instalare DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Doriți să instalați DLC-ul: %1? + + + + DLC already installed: + DLC deja instalat: + + + + Game already installed + Jocul deja instalat diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index f4e8fbfdd..9e3446ad4 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -566,44 +566,34 @@ Извлечение PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Обнаружен патч!\nВерсии PKG и игры совпадают!: %1\nХотите - - - - to overwrite? - перезаписать? - - - - Patch detected!\nPKG Version %1 is older - Обнаружен патч!\nВерсия PKG %1 устарела - - - - than installed version!: %2\nWould you like - по сравнению с установленной версией!: %2\nХотите - - - - to overwrite? - перезаписать? + + Patch detected! + Обнаружен патч! - Patch detected!\nGame is installed: %1\nWould you like - Обнаружен патч!\nИгра установлена: %1\nХотите + PKG and Game versions match: + Версии PKG и игры совпадают: - to install Patch: %2? - установить патч: %2? + Would you like to overwrite? + Хотите перезаписать? - - Game already installed\n%1\nWould you like to overwrite? - Игра уже установлена\n%1\nХотите перезаписать? + + PKG Version %1 is older than installed version: + Версия PKG %1 старее установленной версии: + + + + Game is installed: + Игра установлена: + + + + Would you like to install Patch: + Хотите установить патч: @@ -613,8 +603,18 @@ Would you like to install DLC: %1? - Вы хотите установить DLC: %1? + Вы хотите установить DLC: %1?? + + + DLC already installed: + DLC уже установлен: + + + + Game already installed + Игра уже установлена + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 2393b654d..e11a2d960 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -566,54 +566,54 @@ PKG Çıkartma - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Yama tespit edildi!\nPKG ve Oyun sürümleri uyuyor!: %1\nÜzerine yazmak ister misiniz? - - - - to overwrite? - üzerine yazmak? - - - - Patch detected!\nPKG Version %1 is older - Yama tespit edildi!\nPKG Sürümü %1 daha eski - - - - than installed version!: %2\nWould you like - yüklü sürümden!: %2\nÜzerine yazmak ister misiniz? - - - - to overwrite? - üzerine yazmak? + + Patch detected! + Yamanın tespit edildi! - Patch detected!\nGame is installed: %1\nWould you like - Yama tespit edildi!\nOyun yüklü: %1\nÜzerine yazmak ister misiniz? + PKG and Game versions match: + PKG ve oyun sürümleri uyumlu: - to install Patch: %2? - Yamayı kurmak ister misiniz: %2? + Would you like to overwrite? + Üzerine yazmak ister misiniz? - - Game already installed\n%1\nWould you like to overwrite? - Oyun zaten yüklü\n%1\nÜzerine yazmak ister misiniz? + + PKG Version %1 is older than installed version: + PKG Sürümü %1, kurulu sürümden daha eski: + + + + Game is installed: + Oyun yüklendi: + + + + Would you like to install Patch: + Yamanın yüklenmesini ister misiniz: DLC Installation - DLC Installation + DLC Yükleme Would you like to install DLC: %1? - Would you like to install DLC: %1? + DLC'yi yüklemek ister misiniz: %1? + + + + DLC already installed: + DLC zaten yüklü: + + + + Game already installed + Oyun zaten yüklü diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 8e28afb64..aead45a63 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -566,55 +566,55 @@ Giải nén PKG - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - Đã phát hiện bản vá!\nPhiên bản PKG và trò chơi khớp!: %1\nBạn có muốn + + Patch detected! + Đã phát hiện bản vá! - - to overwrite? - ghi đè không? + + PKG and Game versions match: + Các phiên bản PKG và trò chơi khớp nhau: - - Patch detected!\nPKG Version %1 is older - Đã phát hiện bản vá!\nPhiên bản PKG %1 cũ hơn + + Would you like to overwrite? + Bạn có muốn ghi đè không? - - than installed version!: %2\nWould you like - so với phiên bản đã cài đặt!: %2\nBạn có muốn + + PKG Version %1 is older than installed version: + Phiên bản PKG %1 cũ hơn phiên bản đã cài đặt: - - to overwrite? - ghi đè không? + + Game is installed: + Trò chơi đã được cài đặt: - - Patch detected!\nGame is installed: %1\nWould you like - Đã phát hiện bản vá!\nTrò chơi đã được cài đặt: %1\nBạn có muốn - - - - to install Patch: %2? - cài đặt bản vá: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - Trò chơi đã được cài đặt\n%1\nBạn có muốn ghi đè không? + + Would you like to install Patch: + Bạn có muốn cài đặt bản vá: DLC Installation - DLC Installation + Cài đặt DLC Would you like to install DLC: %1? - Would you like to install DLC: %1? + Bạn có muốn cài đặt DLC: %1? + + + DLC already installed: + DLC đã được cài đặt: + + + + Game already installed + Trò chơi đã được cài đặt + PKG is a patch, please install the game first! diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 3e01df031..a1b2523b8 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -566,54 +566,54 @@ PKG 解压 - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - 检测到补丁!\nPKG 和游戏版本匹配:%1\n您想要 + + Patch detected! + 检测到补丁! - - to overwrite? - 覆盖吗? + + PKG and Game versions match: + PKG 和游戏版本匹配: - - Patch detected!\nPKG Version %1 is older - 检测到补丁!\nPKG 版本 %1 较旧 + + Would you like to overwrite? + 您想要覆盖吗? - - than installed version!: %2\nWould you like - 与已安装版本相比:%2\n您想要 + + PKG Version %1 is older than installed version: + PKG 版本 %1 比已安装版本更旧: - - to overwrite? - 覆盖吗? + + Game is installed: + 游戏已安装: - - Patch detected!\nGame is installed: %1\nWould you like - 检测到补丁!\n游戏已安装:%1\n您想要 - - - - to install Patch: %2? - 安装补丁:%2? - - - - Game already installed\n%1\nWould you like to overwrite? - 游戏已安装\n%1\n您想要覆盖吗? + + Would you like to install Patch: + 您想安装补丁吗: DLC Installation - DLC Installation + DLC 安装 Would you like to install DLC: %1? - Would you like to install DLC: %1? + 您想安装 DLC: %1 吗? + + + + DLC already installed: + DLC 已经安装: + + + + Game already installed + 游戏已经安装 diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 1fb74c695..3836ed18a 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -566,54 +566,54 @@ PKG 解壓縮 - - Patch detected!\nPKG and Game versions match!: %1\nWould you like - 偵測到修補檔!\nPKG 和遊戲版本匹配!: %1\n您是否希望 + + Patch detected! + 檢測到補丁! - - to overwrite? - 覆蓋嗎? + + PKG and Game versions match: + PKG 和遊戲版本匹配: - - Patch detected!\nPKG Version %1 is older - 偵測到修補檔!\nPKG 版本 %1 較舊 + + Would you like to overwrite? + 您想要覆蓋嗎? - - than installed version!: %2\nWould you like - 比安裝的版本舊!: %2\n您是否希望 + + PKG Version %1 is older than installed version: + PKG 版本 %1 比已安裝版本更舊: - - to overwrite? - 覆蓋嗎? + + Game is installed: + 遊戲已安裝: - - Patch detected!\nGame is installed: %1\nWould you like - 偵測到修補檔!\n遊戲已安裝: %1\n您是否希望 - - - - to install Patch: %2? - 安裝修補檔: %2? - - - - Game already installed\n%1\nWould you like to overwrite? - 遊戲已經安裝\n%1\n您是否希望覆蓋? + + Would you like to install Patch: + 您想要安裝補丁嗎: DLC Installation - DLC Installation + DLC 安裝 Would you like to install DLC: %1? - Would you like to install DLC: %1? + 您想要安裝 DLC: %1 嗎? + + + + DLC already installed: + DLC 已經安裝: + + + + Game already installed + 遊戲已經安裝 From bdfff5e8eaf68fc320b042be9440783b1fbc32da Mon Sep 17 00:00:00 2001 From: bigol83 <38129260+bigol83@users.noreply.github.com> Date: Fri, 30 Aug 2024 11:01:48 +0200 Subject: [PATCH 117/147] Update it.ts --- src/qt_gui/translations/it.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index cf0faa6bf..380a8e43b 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -181,7 +181,7 @@ Install application from a .pkg file - Installa applicazione da un file .pkg file + Installa applicazione da un file .pkg @@ -236,7 +236,7 @@ List View - Visualizzazione lista + Visualizzazione Lista @@ -341,7 +341,7 @@ toolBar - barra strumenti + Barra strumenti @@ -568,7 +568,7 @@ Patch detected! - Patch rilevato! + Patch rilevata! @@ -593,7 +593,7 @@ Would you like to install Patch: - Vuoi installare il patch: + Vuoi installare la patch: @@ -651,12 +651,12 @@ Cheats / Patches - Cheat / Patch + Trucchi / Patch defaultTextEdit_MSG - I cheats/patches sono sperimentali.\nUtilizzali con cautela.\n\nScarica i cheats singolarmente selezionando il repository e cliccando sul pulsante di download.\nNella scheda Patches, puoi scaricare tutti i patch in una volta sola, scegliere quali vuoi utilizzare e salvare la tua selezione.\n\nPoiché non sviluppiamo i Cheats/Patches,\nper favore segnala i problemi all'autore del cheat.\n\nHai creato un nuovo cheat? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats + I trucchi e le patch sono sperimentali.\nUtilizzali con cautela.\n\nScarica i trucchi singolarmente selezionando l'archivio e cliccando sul pulsante di download.\nNella scheda Patch, puoi scaricare tutte le patch in una volta sola, scegliere quali vuoi utilizzare e salvare la tua selezione.\n\nPoiché non sviluppiamo i trucchi e le patch,\nper favore segnala i problemi all'autore dei trucchi.\n\nHai creato un nuovo trucco? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats From 0f87d1e3d41689064778f2653f1c1584713b6fa9 Mon Sep 17 00:00:00 2001 From: adjonesey Date: Fri, 30 Aug 2024 10:59:50 +0100 Subject: [PATCH 118/147] Remove from_compute check in texture cache invalidation (#665) * Remove from_compute check in texture cache invalidation (hack) * Remove from_compute parameter --------- Co-authored-by: Adam Jones --- src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 4 ++-- src/video_core/texture_cache/texture_cache.cpp | 4 ++-- src/video_core/texture_cache/texture_cache.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index dd22bfbc6..1d9001238 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -127,7 +127,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } const u32 size = vsharp.GetSize(); if (desc.is_written) { - texture_cache.InvalidateMemory(address, size, true); + texture_cache.InvalidateMemory(address, size); } const u32 alignment = is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); @@ -167,7 +167,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } } if (desc.is_written) { - texture_cache.InvalidateMemory(address, size, true); + texture_cache.InvalidateMemory(address, size); } const u32 alignment = instance.TexelBufferMinAlignment(); const auto [vk_buffer, offset] = diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index cae124220..3354a8ecb 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -34,10 +34,10 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& TextureCache::~TextureCache() = default; -void TextureCache::InvalidateMemory(VAddr address, size_t size, bool from_compute) { +void TextureCache::InvalidateMemory(VAddr address, size_t size) { std::unique_lock lock{mutex}; ForEachImageInRegion(address, size, [&](ImageId image_id, Image& image) { - if (from_compute && !image.Overlaps(address, size)) { + if (!image.Overlaps(address, size)) { return; } // Ensure image is reuploaded when accessed again. diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 8af68424a..31b1e3939 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -38,7 +38,7 @@ public: ~TextureCache(); /// Invalidates any image in the logical page range. - void InvalidateMemory(VAddr address, size_t size, bool from_compute = false); + void InvalidateMemory(VAddr address, size_t size); /// Evicts any images that overlap the unmapped range. void UnmapMemory(VAddr cpu_addr, size_t size); From 6e552aac6a8152e480714b267959474c0956adcd Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 30 Aug 2024 04:42:40 -0700 Subject: [PATCH 119/147] Initialize patch stack before thread TLS. --- src/core/libraries/kernel/thread_management.cpp | 2 +- src/core/linker.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index ac7c8da83..a2befd4c7 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -994,8 +994,8 @@ static void* run_thread(void* arg) { auto* thread = static_cast(arg); Common::SetCurrentThreadName(thread->name.c_str()); auto* linker = Common::Singleton::Instance(); - linker->InitTlsForThread(false); Core::InitializeThreadPatchStack(); + linker->InitTlsForThread(false); void* ret = nullptr; g_pthread_self = thread; pthread_cleanup_push(cleanup_thread, thread); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 2e242129a..4ef62c4a3 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -86,8 +86,8 @@ void Linker::Execute() { // Init primary thread. Common::SetCurrentThreadName("GAME_MainThread"); Libraries::Kernel::pthreadInitSelfMainThread(); - InitTlsForThread(true); InitializeThreadPatchStack(); + InitTlsForThread(true); // Start shared library modules for (auto& m : m_modules) { From 6080066f759c32968a5d3cb87527bb76a598805b Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:40:39 -0700 Subject: [PATCH 120/147] vulkan: Few fixes for MoltenVK (#670) * vulkan: Use SPIR-V 1.5 when Vulkan version is 1.2 * vulkan: Fix Format2_10_10_10 mismap --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 14 +++++--------- src/video_core/renderer_vulkan/vk_shader_cache.cpp | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 3ae19a82a..57593e919 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -287,8 +287,8 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) { std::span GetAllFormats() { static constexpr std::array formats{ + vk::Format::eA2B10G10R10SnormPack32, vk::Format::eA2B10G10R10UnormPack32, - vk::Format::eA2R10G10B10SnormPack32, vk::Format::eA2R10G10B10UnormPack32, vk::Format::eB5G6R5UnormPack16, vk::Format::eB8G8R8A8Srgb, @@ -424,6 +424,10 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eA2B10G10R10UnormPack32; } + if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && + num_format == AmdGpu::NumberFormat::Snorm) { + return vk::Format::eA2B10G10R10SnormPack32; + } if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Srgb) { return vk::Format::eBc7SrgbBlock; } @@ -472,14 +476,6 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu num_format == AmdGpu::NumberFormat::Snorm) { return vk::Format::eR16G16Snorm; } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eA2R10G10B10UnormPack32; - } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eA2R10G10B10SnormPack32; - } if (data_format == AmdGpu::DataFormat::Format10_11_11 && num_format == AmdGpu::NumberFormat::Float) { return vk::Format::eB10G11R11UfloatPack32; diff --git a/src/video_core/renderer_vulkan/vk_shader_cache.cpp b/src/video_core/renderer_vulkan/vk_shader_cache.cpp index 762557125..9250f84ce 100644 --- a/src/video_core/renderer_vulkan/vk_shader_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_cache.cpp @@ -107,7 +107,7 @@ Shader::Info MakeShaderInfo(const GuestProgram& pgm, const AmdGpu::Liverpool::Re ShaderCache::ShaderCache(const Instance& instance_, AmdGpu::Liverpool* liverpool_) : instance{instance_}, liverpool{liverpool_}, inst_pool{8192}, block_pool{512} { profile = Shader::Profile{ - .supported_spirv = 0x00010600U, + .supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U, .subgroup_size = instance.SubgroupSize(), .support_explicit_workgroup_layout = true, }; From 7886761476841b335cc5f01be6c3f355f40ca363 Mon Sep 17 00:00:00 2001 From: Xphalnos <164882787+Xphalnos@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:48:21 +0200 Subject: [PATCH 121/147] Reorganization of includes (Part 2) --- externals/glslang | 2 +- externals/robin-map | 2 +- externals/sirit | 2 +- externals/toml11 | 2 +- externals/xbyak | 2 +- src/core/libraries/app_content/app_content.cpp | 9 ++++----- src/core/libraries/audio/audioout.cpp | 3 ++- src/core/libraries/dialogs/error_dialog.cpp | 1 - src/core/libraries/dialogs/ime_dialog.cpp | 1 - src/core/libraries/disc_map/disc_map.cpp | 1 - src/core/libraries/kernel/event_flag/event_flag.cpp | 2 +- .../libraries/kernel/event_flag/event_flag_obj.cpp | 1 + src/core/libraries/kernel/event_flag/event_flag_obj.h | 2 ++ src/core/libraries/kernel/event_queue.cpp | 1 + src/core/libraries/kernel/libkernel.h | 1 + src/core/libraries/kernel/memory_management.cpp | 1 + src/core/libraries/kernel/thread_management.cpp | 1 + src/core/libraries/kernel/thread_management.h | 1 + src/core/libraries/kernel/threads/semaphore.cpp | 1 + src/core/libraries/kernel/time_management.cpp | 1 + src/core/libraries/libc_internal/libc_internal.cpp | 1 + src/core/libraries/libs.cpp | 10 +++++----- src/core/libraries/libs.h | 1 + src/core/libraries/np_manager/np_manager.cpp | 1 - src/core/libraries/np_score/np_score.cpp | 1 - src/core/libraries/np_trophy/np_trophy.cpp | 1 - src/core/libraries/pad/pad.cpp | 5 ++--- src/core/libraries/playgo/playgo.cpp | 2 +- src/core/libraries/playgo/playgo.h | 1 + src/core/libraries/random/random.h | 1 + src/core/libraries/rtc/rtc.cpp | 2 +- src/core/libraries/save_data/savedata.cpp | 9 +++++---- src/core/libraries/screenshot/screenshot.cpp | 1 - src/core/libraries/usbd/usbd.cpp | 1 - src/core/libraries/usbd/usbd.h | 1 + src/core/libraries/videoout/buffer.h | 1 + src/core/libraries/videoout/driver.cpp | 1 + src/qt_gui/gui_context_menus.h | 2 +- src/qt_gui/main_window.cpp | 2 +- 39 files changed, 45 insertions(+), 36 deletions(-) diff --git a/externals/glslang b/externals/glslang index d59c84d38..12cbda959 160000 --- a/externals/glslang +++ b/externals/glslang @@ -1 +1 @@ -Subproject commit d59c84d388c805022e2bddea08aa41cbe7e43e55 +Subproject commit 12cbda959b6df2af119a76a73ff906c2bed36884 diff --git a/externals/robin-map b/externals/robin-map index 1115dad3f..2c48a1a50 160000 --- a/externals/robin-map +++ b/externals/robin-map @@ -1 +1 @@ -Subproject commit 1115dad3ffa0994e3f43b693d9b9cc99944c64c1 +Subproject commit 2c48a1a50203bbaf1e3d0d64c5d726d56f8d3bb3 diff --git a/externals/sirit b/externals/sirit index 8db09231c..37090c74c 160000 --- a/externals/sirit +++ b/externals/sirit @@ -1 +1 @@ -Subproject commit 8db09231c448b913ae905d5237ce2eca46e3fe87 +Subproject commit 37090c74cc6e680f2bc334cac8fd182f7634a1f6 diff --git a/externals/toml11 b/externals/toml11 index cc0bee4fd..4b7401272 160000 --- a/externals/toml11 +++ b/externals/toml11 @@ -1 +1 @@ -Subproject commit cc0bee4fd46ea1f5db147d63ea545208cc9e8405 +Subproject commit 4b740127230472779c4a4d71e1a75aaa3a367a2d diff --git a/externals/xbyak b/externals/xbyak index aabb091ae..ccdf68421 160000 --- a/externals/xbyak +++ b/externals/xbyak @@ -1 +1 @@ -Subproject commit aabb091ae37068498751fd58202a9854408ecb0e +Subproject commit ccdf68421bc8eb85693f573080fc0a5faad862db diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index c2523124a..125d19684 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -1,17 +1,16 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include -#include -#include -#include -#include #include "app_content.h" #include "common/io_file.h" #include "common/logging/log.h" +#include "common/path_util.h" +#include "common/singleton.h" #include "common/string_util.h" +#include "core/file_format/psf.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/audio/audioout.cpp b/src/core/libraries/audio/audioout.cpp index cb676afc1..54db4c673 100644 --- a/src/core/libraries/audio/audioout.cpp +++ b/src/core/libraries/audio/audioout.cpp @@ -2,9 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include #include + #include "audio_core/sdl_audio.h" +#include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/audio/audioout.h" #include "core/libraries/error_codes.h" diff --git a/src/core/libraries/dialogs/error_dialog.cpp b/src/core/libraries/dialogs/error_dialog.cpp index 02f82c096..7df9b1c83 100644 --- a/src/core/libraries/dialogs/error_dialog.cpp +++ b/src/core/libraries/dialogs/error_dialog.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/dialogs/ime_dialog.cpp b/src/core/libraries/dialogs/ime_dialog.cpp index e73c1881b..ddb1a89f8 100644 --- a/src/core/libraries/dialogs/ime_dialog.cpp +++ b/src/core/libraries/dialogs/ime_dialog.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/disc_map/disc_map.cpp b/src/core/libraries/disc_map/disc_map.cpp index 79f4acb34..bb566a149 100644 --- a/src/core/libraries/disc_map/disc_map.cpp +++ b/src/core/libraries/disc_map/disc_map.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/event_flag/event_flag.cpp b/src/core/libraries/kernel/event_flag/event_flag.cpp index 8afd139c0..0fd0c3bb7 100644 --- a/src/core/libraries/kernel/event_flag/event_flag.cpp +++ b/src/core/libraries/kernel/event_flag/event_flag.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include +#include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp index ed01d7cc0..6d6dcf7a9 100644 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp +++ b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "core/libraries/error_codes.h" #include "event_flag_obj.h" diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h index fe50be697..8d1624e2b 100644 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.h +++ b/src/core/libraries/kernel/event_flag/event_flag_obj.h @@ -2,8 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include #include + #include "common/types.h" namespace Libraries::Kernel { diff --git a/src/core/libraries/kernel/event_queue.cpp b/src/core/libraries/kernel/event_queue.cpp index 3555fddc9..88918bf54 100644 --- a/src/core/libraries/kernel/event_queue.cpp +++ b/src/core/libraries/kernel/event_queue.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/assert.h" #include "core/libraries/kernel/event_queue.h" diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/libkernel.h index 5b7f1e722..c28a548ff 100644 --- a/src/core/libraries/kernel/libkernel.h +++ b/src/core/libraries/kernel/libkernel.h @@ -4,6 +4,7 @@ #pragma once #include + #include "common/types.h" namespace Core::Loader { diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index 3fc837d96..a5288a656 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/alignment.h" #include "common/assert.h" #include "common/logging/log.h" diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index a2befd4c7..74ef392fa 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -4,6 +4,7 @@ #include #include #include + #include "common/alignment.h" #include "common/assert.h" #include "common/error.h" diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index 27cd7929a..a2b2f6fea 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -10,6 +10,7 @@ #include #include #include + #include "common/types.h" namespace Core::Loader { diff --git a/src/core/libraries/kernel/threads/semaphore.cpp b/src/core/libraries/kernel/threads/semaphore.cpp index e2f438037..63ca25338 100644 --- a/src/core/libraries/kernel/threads/semaphore.cpp +++ b/src/core/libraries/kernel/threads/semaphore.cpp @@ -5,6 +5,7 @@ #include #include #include + #include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index d01b0c83f..7a6ba4f62 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/assert.h" #include "common/debug.h" #include "common/native_clock.h" diff --git a/src/core/libraries/libc_internal/libc_internal.cpp b/src/core/libraries/libc_internal/libc_internal.cpp index 0607e93b7..8eea41eb3 100644 --- a/src/core/libraries/libc_internal/libc_internal.cpp +++ b/src/core/libraries/libc_internal/libc_internal.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index f0171199b..e91a51e68 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -2,13 +2,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/config.h" +#include "core/libraries/ajm/ajm.h" #include "core/libraries/app_content/app_content.h" #include "core/libraries/audio/audioin.h" #include "core/libraries/audio/audioout.h" +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/dialogs/error_dialog.h" +#include "core/libraries/dialogs/ime_dialog.h" #include "core/libraries/disc_map/disc_map.h" #include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/libc_internal/libc_internal.h" +#include "core/libraries/libpng/pngdec.h" #include "core/libraries/libs.h" #include "core/libraries/network/http.h" #include "core/libraries/network/net.h" @@ -32,11 +37,6 @@ #include "core/libraries/system/userservice.h" #include "core/libraries/usbd/usbd.h" #include "core/libraries/videoout/video_out.h" -#include "src/core/libraries/ajm/ajm.h" -#include "src/core/libraries/avplayer/avplayer.h" -#include "src/core/libraries/dialogs/error_dialog.h" -#include "src/core/libraries/dialogs/ime_dialog.h" -#include "src/core/libraries/libpng/pngdec.h" namespace Libraries { diff --git a/src/core/libraries/libs.h b/src/core/libraries/libs.h index 7cad7f8ba..ea928101e 100644 --- a/src/core/libraries/libs.h +++ b/src/core/libraries/libs.h @@ -4,6 +4,7 @@ #pragma once #include + #include "common/logging/log.h" #include "core/loader/elf.h" #include "core/loader/symbols_resolver.h" diff --git a/src/core/libraries/np_manager/np_manager.cpp b/src/core/libraries/np_manager/np_manager.cpp index c657fbf60..a761caa73 100644 --- a/src/core/libraries/np_manager/np_manager.cpp +++ b/src/core/libraries/np_manager/np_manager.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/config.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" diff --git a/src/core/libraries/np_score/np_score.cpp b/src/core/libraries/np_score/np_score.cpp index d6e4631ce..dc16e12d2 100644 --- a/src/core/libraries/np_score/np_score.cpp +++ b/src/core/libraries/np_score/np_score.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/np_trophy/np_trophy.cpp b/src/core/libraries/np_trophy/np_trophy.cpp index 4b1f43694..ed25322b4 100644 --- a/src/core/libraries/np_trophy/np_trophy.cpp +++ b/src/core/libraries/np_trophy/np_trophy.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include #include "common/logging/log.h" diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index a0abfdf73..cb0da552a 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -1,11 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator -#include -#include +#include "common/assert.h" #include "common/config.h" #include "common/logging/log.h" +#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "input/controller.h" diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp index 66422dc28..d4f5c6b7c 100644 --- a/src/core/libraries/playgo/playgo.cpp +++ b/src/core/libraries/playgo/playgo.cpp @@ -1,9 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "common/logging/log.h" #include "common/singleton.h" +#include "core/file_format/playgo_chunk.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/system/systemservice.h" diff --git a/src/core/libraries/playgo/playgo.h b/src/core/libraries/playgo/playgo.h index f5ae1baa6..2338c9ebf 100644 --- a/src/core/libraries/playgo/playgo.h +++ b/src/core/libraries/playgo/playgo.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include "common/types.h" #include "playgo_types.h" diff --git a/src/core/libraries/random/random.h b/src/core/libraries/random/random.h index 7bb41f016..b483cf6ed 100644 --- a/src/core/libraries/random/random.h +++ b/src/core/libraries/random/random.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include "common/types.h" namespace Core::Loader { diff --git a/src/core/libraries/rtc/rtc.cpp b/src/core/libraries/rtc/rtc.cpp index f6faa5382..387a8558b 100644 --- a/src/core/libraries/rtc/rtc.cpp +++ b/src/core/libraries/rtc/rtc.cpp @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include + #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index eb309183f..d5ea76e08 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -3,12 +3,13 @@ #include #include -#include -#include -#include -#include + #include "common/assert.h" #include "common/logging/log.h" +#include "common/path_util.h" +#include "common/singleton.h" +#include "core/file_format/psf.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/save_data/savedata.h" diff --git a/src/core/libraries/screenshot/screenshot.cpp b/src/core/libraries/screenshot/screenshot.cpp index 1924ddf54..eaa535de7 100644 --- a/src/core/libraries/screenshot/screenshot.cpp +++ b/src/core/libraries/screenshot/screenshot.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index 2a1f6028a..c0e1b7ea8 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "common/singleton.h" #include "core/libraries/error_codes.h" diff --git a/src/core/libraries/usbd/usbd.h b/src/core/libraries/usbd/usbd.h index 6aad31ebc..4ed153587 100644 --- a/src/core/libraries/usbd/usbd.h +++ b/src/core/libraries/usbd/usbd.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include "common/types.h" namespace Core::Loader { diff --git a/src/core/libraries/videoout/buffer.h b/src/core/libraries/videoout/buffer.h index 8f49be591..08552bddb 100644 --- a/src/core/libraries/videoout/buffer.h +++ b/src/core/libraries/videoout/buffer.h @@ -4,6 +4,7 @@ #pragma once #include + #include "common/assert.h" #include "common/types.h" diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 09e9cef5b..91694cfaf 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/assert.h" #include "common/config.h" #include "common/debug.h" diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index c43ff8f87..fb1994bb0 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -140,7 +140,7 @@ public: new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage); cheatsPatches->show(); connect(widget->parent(), &QWidget::destroyed, cheatsPatches, - [widget, cheatsPatches]() { cheatsPatches->deleteLater(); }); + [cheatsPatches]() { cheatsPatches->deleteLater(); }); } if (selected == &openTrophyViewer) { diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 944ff4a6b..988e01a50 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -366,7 +366,7 @@ void MainWindow::CreateConnects() { panelDialog->accept(); }); - connect(downloadAllPatchesButton, &QPushButton::clicked, this, [this, panelDialog]() { + connect(downloadAllPatchesButton, &QPushButton::clicked, [panelDialog]() { QEventLoop eventLoop; int pendingDownloads = 0; From 69d4fecdfe70c8b9a5b27cd9d62753d6b6f57b36 Mon Sep 17 00:00:00 2001 From: jnack <55568980+jnackmclain@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:51:20 -0500 Subject: [PATCH 122/147] Allow graphics/compute shader list for skipping (#674) * Allow graphics/compute shader list for skipping * nintendo ultra 64 + formatting * indentation.. * allow empty array in ShouldSkipShader * simpler check for skip hashes --- .../renderer_vulkan/vk_pipeline_cache.cpp | 29 ++++++++++++++++--- .../renderer_vulkan/vk_pipeline_cache.h | 4 +-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 7e880657e..f8de5ffeb 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -38,7 +38,9 @@ const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() { LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped"); return nullptr; } - RefreshGraphicsKey(); + if (!RefreshGraphicsKey()) { + return nullptr; + } const auto [it, is_new] = graphics_pipelines.try_emplace(graphics_key); if (is_new) { it.value() = std::make_unique(instance, scheduler, graphics_key, @@ -49,7 +51,9 @@ const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() { } const ComputePipeline* PipelineCache::GetComputePipeline() { - RefreshComputeKey(); + if (!RefreshComputeKey()) { + return nullptr; + } const auto [it, is_new] = compute_pipelines.try_emplace(compute_key); if (is_new) { it.value() = std::make_unique(instance, scheduler, *pipeline_cache, @@ -59,7 +63,16 @@ const ComputePipeline* PipelineCache::GetComputePipeline() { return pipeline; } -void PipelineCache::RefreshGraphicsKey() { +bool ShouldSkipShader(u64 shader_hash, const char* shader_type) { + static constexpr std::array skip_hashes = {}; + if (std::ranges::contains(skip_hashes, shader_hash)) { + LOG_WARNING(Render_Vulkan, "Skipped {} shader hash {:#x}.", shader_type, shader_hash); + return true; + } + return false; +} + +bool PipelineCache::RefreshGraphicsKey() { auto& regs = liverpool->regs; auto& key = graphics_key; @@ -160,18 +173,26 @@ void PipelineCache::RefreshGraphicsKey() { infos[i] = nullptr; continue; } + if (ShouldSkipShader(bininfo->shader_hash, "graphics")) { + return false; + } const auto stage = Shader::Stage{i}; const GuestProgram guest_pgm{pgm, stage}; std::tie(infos[i], modules[i], key.stage_hashes[i]) = shader_cache->GetProgram(guest_pgm, binding); } + return true; } -void PipelineCache::RefreshComputeKey() { +bool PipelineCache::RefreshComputeKey() { u32 binding{}; const auto* cs_pgm = &liverpool->regs.cs_program; const GuestProgram guest_pgm{cs_pgm, Shader::Stage::Compute}; + if (ShouldSkipShader(guest_pgm.hash, "compute")) { + return false; + } std::tie(infos[0], modules[0], compute_key) = shader_cache->GetProgram(guest_pgm, binding); + return true; } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index d0eb0c660..40853b746 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -30,8 +30,8 @@ public: const ComputePipeline* GetComputePipeline(); private: - void RefreshGraphicsKey(); - void RefreshComputeKey(); + bool RefreshGraphicsKey(); + bool RefreshComputeKey(); private: const Instance& instance; From ca1613258f79789995e704af3635e1627894c5f0 Mon Sep 17 00:00:00 2001 From: psucien <168137814+psucien@users.noreply.github.com> Date: Fri, 30 Aug 2024 22:59:56 +0200 Subject: [PATCH 123/147] video_core: added support for indirect draws (#678) * video_core: added support for indirect draws * barriers simplified --- src/core/libraries/gnmdriver/gnmdriver.cpp | 12 ++-- src/core/libraries/gnmdriver/gnmdriver.h | 4 +- src/video_core/amdgpu/liverpool.cpp | 31 +++++++++ src/video_core/amdgpu/pm4_cmds.h | 61 +++++++++++++---- .../renderer_vulkan/vk_rasterizer.cpp | 65 +++++++++++++++---- .../renderer_vulkan/vk_rasterizer.h | 2 + 6 files changed, 140 insertions(+), 35 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 6b8b070b8..34d056156 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -650,12 +650,12 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 } s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags) { LOG_TRACE(Lib_GnmDriver, "called"); if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) && - (vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) { + (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) { const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; cmdbuf = WriteHeader( @@ -665,7 +665,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, cmdbuf[0] = data_offset; cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset; - cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset; + cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[3] = 0; cmdbuf += 4; @@ -707,11 +707,11 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, } s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags) { + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags) { LOG_TRACE(Lib_GnmDriver, "called"); if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) && - (vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) { + (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) { const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; cmdbuf = WriteHeader(cmdbuf, 4, PM4ShaderType::ShaderGraphics, @@ -721,7 +721,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 cmdbuf[0] = data_offset; cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset; - cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset; + cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[3] = 2; // auto index cmdbuf += 4; diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 84872297e..40a6ca5b6 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -45,7 +45,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr u32 flags, u32 type); s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags); s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags); int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti(); @@ -53,7 +53,7 @@ int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced(); s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count, u32 flags); s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags); + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags); int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndirectMulti(); u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size); diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index e61f8cec0..2a595516d 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -368,6 +368,36 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); + const auto offset = draw_indirect->data_offset; + const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; + const auto size = sizeof(PM4CmdDrawIndirect::DrawInstancedArgs); + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndirect", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->DrawIndirect(false, ib_address, offset, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndexIndirect: { + const auto* draw_index_indirect = + reinterpret_cast(header); + const auto offset = draw_index_indirect->data_offset; + const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; + const auto size = sizeof(PM4CmdDrawIndexIndirect::DrawIndexInstancedArgs); + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin( + fmt::format("dcb:{}:DrawIndexIndirect", cmd_address)); + rasterizer->Breadcrumb(u64(cmd_address)); + rasterizer->DrawIndirect(true, ib_address, offset, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } case PM4ItOpcode::DispatchDirect: { const auto* dispatch_direct = reinterpret_cast(header); regs.cs_program.dim_x = dispatch_direct->dim_x; @@ -488,6 +518,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::spanCpSync(); break; } default: diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 50e4c93a1..58ade221b 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -253,20 +253,6 @@ struct PM4CmdDrawIndexAuto { u32 draw_initiator; }; -struct PM4CmdDrawIndirect { - PM4Type3Header header; ///< header - u32 data_offset; ///< DWORD aligned offset - union { - u32 dw2; - BitField<0, 16, u32> base_vtx_loc; ///< base vertex location - }; - union { - u32 dw3; - BitField<0, 16, u32> start_inst_loc; ///< start instance location - }; - u32 draw_initiator; ///< Draw Initiator Register -}; - enum class DataSelect : u32 { None = 0, Data32Low = 1, @@ -740,4 +726,51 @@ struct PM4CmdDispatchIndirect { u32 dispatch_initiator; ///< Dispatch Initiator Register }; +struct PM4CmdDrawIndirect { + struct DrawInstancedArgs { + u32 vertex_count_per_instance; + u32 instance_count; + u32 start_vertex_location; + u32 start_instance_location; + }; + + PM4Type3Header header; ///< header + u32 data_offset; ///< Byte aligned offset where the required data structure starts + union { + u32 dw2; + BitField<0, 16, u32> base_vtx_loc; ///< Offset where the CP will write the + ///< BaseVertexLocation it fetched from memory + }; + union { + u32 dw3; + BitField<0, 16, u32> start_inst_loc; ///< Offset where the CP will write the + ///< StartInstanceLocation it fetched from memory + }; + u32 draw_initiator; ///< Draw Initiator Register +}; + +struct PM4CmdDrawIndexIndirect { + struct DrawIndexInstancedArgs { + u32 index_count_per_instance; + u32 instance_count; + u32 start_index_location; + u32 base_vertex_location; + u32 start_instance_location; + }; + + PM4Type3Header header; ///< header + u32 data_offset; ///< Byte aligned offset where the required data structure starts + union { + u32 dw2; + BitField<0, 16, u32> base_vtx_loc; ///< Offset where the CP will write the + ///< BaseVertexLocation it fetched from memory + }; + union { // NOTE: this one is undocumented in AMD spec, but Gnm driver writes this field + u32 dw3; + BitField<0, 16, u32> start_inst_loc; ///< Offset where the CP will write the + ///< StartInstanceLocation it fetched from memory + }; + u32 draw_initiator; ///< Draw Initiator Register +}; + } // namespace AmdGpu diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9231c5104..cadce01eb 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -29,6 +29,19 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_, Rasterizer::~Rasterizer() = default; +void Rasterizer::CpSync() { + scheduler.EndRendering(); + auto cmdbuf = scheduler.CommandBuffer(); + + const vk::MemoryBarrier ib_barrier{ + .srcAccessMask = vk::AccessFlagBits::eShaderWrite, + .dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead, + }; + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, + vk::PipelineStageFlagBits::eDrawIndirect, + vk::DependencyFlagBits::eByRegion, ib_barrier, {}, {}); +} + void Rasterizer::Draw(bool is_indexed, u32 index_offset) { RENDERER_TRACE; @@ -66,6 +79,45 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { } } +void Rasterizer::DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size) { + RENDERER_TRACE; + + const auto cmdbuf = scheduler.CommandBuffer(); + const auto& regs = liverpool->regs; + const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline(); + if (!pipeline) { + return; + } + + ASSERT_MSG(regs.primitive_type != AmdGpu::Liverpool::PrimitiveType::RectList, + "Unsupported primitive type for indirect draw"); + + try { + pipeline->BindResources(regs, buffer_cache, texture_cache); + } catch (...) { + UNREACHABLE(); + } + + const auto& vs_info = pipeline->GetStage(Shader::Stage::Vertex); + buffer_cache.BindVertexBuffers(vs_info); + const u32 num_indices = buffer_cache.BindIndexBuffer(is_indexed, 0); + + BeginRendering(); + UpdateDynamicState(*pipeline); + + const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true); + const auto total_offset = base + offset; + + // We can safely ignore both SGPR UD indices and results of fetch shader parsing, as vertex and + // instance offsets will be automatically applied by Vulkan from indirect args buffer. + + if (is_indexed) { + cmdbuf.drawIndexedIndirect(buffer->Handle(), total_offset, 1, 0); + } else { + cmdbuf.drawIndirect(buffer->Handle(), total_offset, 1, 0); + } +} + void Rasterizer::DispatchDirect() { RENDERER_TRACE; @@ -113,19 +165,6 @@ void Rasterizer::DispatchIndirect(VAddr address, u32 offset, u32 size) { cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle()); const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true); const auto total_offset = base + offset; - - // Emulate PFP-to-ME sync packet - const vk::BufferMemoryBarrier ib_barrier{ - .srcAccessMask = vk::AccessFlagBits::eShaderWrite, - .dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead, - .buffer = buffer->Handle(), - .offset = total_offset, - .size = size, - }; - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, - vk::PipelineStageFlagBits::eDrawIndirect, - vk::DependencyFlagBits::eByRegion, {}, ib_barrier, {}); - cmdbuf.dispatchIndirect(buffer->Handle(), total_offset); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 34f6ae726..c38fe6ee9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -32,6 +32,7 @@ public: } void Draw(bool is_indexed, u32 index_offset = 0); + void DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size); void DispatchDirect(); void DispatchIndirect(VAddr address, u32 offset, u32 size); @@ -45,6 +46,7 @@ public: void MapMemory(VAddr addr, u64 size); void UnmapMemory(VAddr addr, u64 size); + void CpSync(); u64 Flush(); private: From 418274038433e674b5e793322742b9b286c12802 Mon Sep 17 00:00:00 2001 From: psucien Date: Sat, 31 Aug 2024 00:10:47 +0200 Subject: [PATCH 124/147] Don't load `sync2` ext if `nv_checkpoints` isn't used --- src/video_core/renderer_vulkan/vk_instance.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index e1a5cb414..34727d27e 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -220,12 +220,12 @@ bool Instance::CreateDevice() { const bool maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); - const bool has_sync2 = add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); - if (has_sync2) { - has_nv_checkpoints = Config::isMarkersEnabled() - ? add_extension(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME) - : false; + if (Config::isMarkersEnabled()) { + const bool has_sync2 = add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); + if (has_sync2) { + has_nv_checkpoints = add_extension(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME); + } } #ifdef __APPLE__ From 61db246c5ec86aa63215a13ad915f42da1f98426 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:47:07 -0700 Subject: [PATCH 125/147] core: Fix CPU patch stack issues --- CMakeLists.txt | 2 +- src/core/cpu_patches.cpp | 30 +++++++------------ .../libraries/kernel/thread_management.cpp | 3 +- src/core/linker.cpp | 4 +-- 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c7e03e3c..a65e9c599 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -636,7 +636,7 @@ target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAlloca if (APPLE) # Reserve system-managed memory space. - target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x400000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x10000000000) + target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x400000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x20000000000) # Link MoltenVK for Vulkan support find_library(MOLTENVK MoltenVK REQUIRED) diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp index 55bbf23b1..e713155ae 100644 --- a/src/core/cpu_patches.cpp +++ b/src/core/cpu_patches.cpp @@ -126,39 +126,35 @@ static Xbyak::Reg AllocateScratchRegister( static pthread_key_t stack_pointer_slot; static pthread_key_t patch_stack_slot; static std::once_flag patch_context_slots_init_flag; +static constexpr u32 patch_stack_size = 0x1000; static_assert(sizeof(void*) == sizeof(u64), "Cannot fit a register inside a thread local storage slot."); +static void FreePatchStack(void* patch_stack) { + // Subtract back to the bottom of the stack for free. + std::free(static_cast(patch_stack) - patch_stack_size); +} + static void InitializePatchContextSlots() { ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0, "Unable to allocate thread-local register for stack pointer."); - ASSERT_MSG(pthread_key_create(&patch_stack_slot, nullptr) == 0, + ASSERT_MSG(pthread_key_create(&patch_stack_slot, FreePatchStack) == 0, "Unable to allocate thread-local register for patch stack."); } void InitializeThreadPatchStack() { std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); - const auto* patch_stack = std::malloc(0x1000); - pthread_setspecific(patch_stack_slot, patch_stack); -} - -void CleanupThreadPatchStack() { - std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); - - auto* patch_stack = pthread_getspecific(patch_stack_slot); - if (patch_stack != nullptr) { - std::free(patch_stack); - pthread_setspecific(patch_stack_slot, nullptr); - } + pthread_setspecific(patch_stack_slot, + static_cast(std::malloc(patch_stack_size)) + patch_stack_size); } /// Saves the stack pointer to thread local storage and loads the patch stack. static void SaveStack(Xbyak::CodeGenerator& c) { std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); - // Save stack pointer and load patch stack. + // Save original stack pointer and load patch stack. c.putSeg(gs); c.mov(qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))], rsp); c.putSeg(gs); @@ -184,10 +180,6 @@ void InitializeThreadPatchStack() { // No-op } -void CleanupThreadPatchStack() { - // No-op -} - /// Saves the stack pointer to thread local storage and loads the patch stack. static void SaveStack(Xbyak::CodeGenerator& c) { UNIMPLEMENTED(); @@ -244,7 +236,7 @@ static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst) { if (!dst.isREG() || dst.getIdx() != reg) { c.pop(Xbyak::Reg64(reg)); } else { - c.add(rsp, 4); + c.add(rsp, 8); } } RestoreStack(c); diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index a2befd4c7..5c84c35d7 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -986,15 +986,14 @@ static void cleanup_thread(void* arg) { destructor(value); } } - Core::CleanupThreadPatchStack(); thread->is_almost_done = true; } static void* run_thread(void* arg) { auto* thread = static_cast(arg); Common::SetCurrentThreadName(thread->name.c_str()); - auto* linker = Common::Singleton::Instance(); Core::InitializeThreadPatchStack(); + auto* linker = Common::Singleton::Instance(); linker->InitTlsForThread(false); void* ret = nullptr; g_pthread_self = thread; diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 4ef62c4a3..0c914cef1 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -85,8 +85,8 @@ void Linker::Execute() { // Init primary thread. Common::SetCurrentThreadName("GAME_MainThread"); - Libraries::Kernel::pthreadInitSelfMainThread(); InitializeThreadPatchStack(); + Libraries::Kernel::pthreadInitSelfMainThread(); InitTlsForThread(true); // Start shared library modules @@ -106,8 +106,6 @@ void Linker::Execute() { RunMainEntry(m->GetEntryAddress(), &p, ProgramExitFunc); } } - - CleanupThreadPatchStack(); } s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { From ebfed28f6b4dc227bfec47a2a09817457bc748f3 Mon Sep 17 00:00:00 2001 From: Exhigh Date: Sat, 31 Aug 2024 08:21:23 +0400 Subject: [PATCH 126/147] savedata: Handle a missing case in saveDataMount This should potentially fix the mount issue in Resistance : Retribution (CUSA32636) Testing is welcome. --- src/core/libraries/save_data/savedata.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index d5ea76e08..959a75705 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -522,6 +522,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, } break; case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | From 382f1043696d54520a1face57ff2e6fa7f931f2e Mon Sep 17 00:00:00 2001 From: bigqy Date: Sat, 31 Aug 2024 22:48:59 +0800 Subject: [PATCH 127/147] update zh_CN translation --- src/qt_gui/translations/zh_CN.ts | 174 +++++++++++++++---------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index a1b2523b8..7584fd5ea 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + 关于 shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 是一款实验性质的开源 PlayStation 4模拟器软件。 This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + 本软件不得用于运行未经合法授权而获得的游戏。 @@ -29,7 +29,7 @@ Open Folder - Open Folder + 打开文件夹 @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + 加载游戏列表中, 请稍等 :3 Cancel - Cancel + 取消 Loading... - Loading... + 加载中... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - 选择文件目录 Directory to install games - Directory to install games + 要安装游戏的目录 Browse - Browse + 浏览 Error - Error + 错误 The value for location to install games is not valid. - The value for location to install games is not valid. + 游戏安装位置无效。 @@ -83,72 +83,72 @@ Create Shortcut - Create Shortcut + 创建快捷方式 Open Game Folder - Open Game Folder + 打开游戏文件夹 Cheats / Patches - Zuòbì / Bǔdīng + 作弊码 / 补丁 SFO Viewer - SFO Viewer + SFO 查看器 Trophy Viewer - Trophy Viewer + Trophy 查看器 Copy info - Copy info + 复制信息 Copy Name - Copy Name + 复制名称 Copy Serial - Copy Serial + 复制序列号 Copy All - Copy All + 复制全部 Shortcut creation - Shortcut creation + 创建快捷方式 Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + 创建快捷方式成功!\n %1 Error - Error + 错误 Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + 创建快捷方式出错!\n %1 Install PKG - Install PKG + 安装 PKG @@ -156,162 +156,162 @@ Open/Add Elf Folder - Open/Add Elf Folder + 打开/添加Elf文件夹 Install Packages (PKG) - Install Packages (PKG) + 安装 Packages (PKG) Boot Game - Boot Game + 启动游戏 About shadPS4 - About shadPS4 + 关于 shadPS4 Configure... - Configure... + 设置... Install application from a .pkg file - Install application from a .pkg file + 从 .pkg 文件安装应用程序 Recent Games - Recent Games + 最近启动的游戏 Exit - Exit + 退出 Exit shadPS4 - Exit shadPS4 + 退出 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 + Elf 查看器 Game Install Directory - Game Install Directory + 游戏安装目录 Download Cheats/Patches - Xiàzài Zuòbì / Bǔdīng + 下载作弊码/补丁 Dump Game List - Dump Game List + 转储游戏列表 PKG Viewer - PKG Viewer + PKG 查看器 Search... - Search... + 搜索... File - File + 文件 View - View + 显示 Game List Icons - Game List Icons + 游戏列表图标 Game List Mode - Game List Mode + 游戏列表模式 Settings - Settings + 设置 Utils - Utils + 工具 Themes - Themes + 主题 About - About + 关于 @@ -341,7 +341,7 @@ toolBar - toolBar + 工具栏 @@ -349,7 +349,7 @@ Open Folder - Open Folder + 打开文件夹 @@ -357,7 +357,7 @@ Trophy Viewer - Trophy Viewer + Trophy 查看器 @@ -365,87 +365,87 @@ Settings - Settings + 设置 General - General + 通用 System - System + 系统 Console Language - Console Language + 主机语言 Emulator Language - Emulator Language + 模拟器语言 Emulator - Emulator + 模拟器 Enable Fullscreen - Enable Fullscreen + 启用全屏 Show Splash - Show Splash + 显示Splash Is PS4 Pro - Is PS4 Pro + 是否是 PS4 Pro Username - Username + 用户名 Logger - Logger + 日志 Log Type - Log Type + 日志类型 Log Filter - Log Filter + 日志过滤 Graphics - Graphics + 图像 Graphics Device - Graphics Device + 图像设备 Width - Width + 宽带 Height - Height + 高度 @@ -455,47 +455,47 @@ Advanced - Advanced + 高级 Enable Shaders Dumping - Enable Shaders Dumping + 启用着色器转储 Enable NULL GPU - Enable NULL GPU + 启用 NULL GPU Enable PM4 Dumping - Enable PM4 Dumping + 启用 PM4 转储 Debug - Debug + 调试 Enable Debug Dumping - Enable Debug Dumping + 启用调试转储 Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + 启用 Vulkan 验证层 Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + 启用 Vulkan 同步验证 Enable RenderDoc Debugging - Enable RenderDoc Debugging + 启用 RenderDoc 调试 From fb5c7c50629d42e2bb9e8204fb8045182606ba5a Mon Sep 17 00:00:00 2001 From: Xphalnos <164882787+Xphalnos@users.noreply.github.com> Date: Sat, 31 Aug 2024 17:30:19 +0200 Subject: [PATCH 128/147] Qt: Update Game List --- src/qt_gui/game_info.h | 1 - src/qt_gui/game_list_frame.cpp | 21 +++++++++------------ src/qt_gui/game_list_utils.h | 1 - src/qt_gui/main_window_ui.h | 6 +----- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/qt_gui/game_info.h b/src/qt_gui/game_info.h index ae02114a2..6032e1c3a 100644 --- a/src/qt_gui/game_info.h +++ b/src/qt_gui/game_info.h @@ -41,7 +41,6 @@ public: : fw.left(3).insert(1, '.'); game.fw = (fw_int == 0) ? "0.00" : fw_.toStdString(); game.version = psf.GetString("APP_VER"); - game.category = psf.GetString("CATEGORY"); } return game; } diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index 2699c9615..f5c2facbe 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -23,14 +23,13 @@ GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidg this->horizontalHeader()->setSortIndicatorShown(true); this->horizontalHeader()->setStretchLastSection(true); this->setContextMenuPolicy(Qt::CustomContextMenu); - this->setColumnCount(9); - this->setColumnWidth(1, 250); - this->setColumnWidth(2, 110); - this->setColumnWidth(3, 80); - this->setColumnWidth(4, 90); - this->setColumnWidth(5, 80); - this->setColumnWidth(6, 80); - this->setColumnWidth(7, 80); + this->setColumnCount(8); + this->setColumnWidth(1, 300); // Name + this->setColumnWidth(2, 120); // Serial + this->setColumnWidth(3, 90); // Region + this->setColumnWidth(4, 90); // Firmware + this->setColumnWidth(5, 90); // Size + this->setColumnWidth(6, 90); // Version QStringList headers; headers << "Icon" << "Name" @@ -39,7 +38,6 @@ GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidg << "Firmware" << "Size" << "Version" - << "Category" << "Path"; this->setHorizontalHeaderLabels(headers); this->horizontalHeader()->setSortIndicatorShown(true); @@ -87,8 +85,7 @@ void GameListFrame::PopulateGameList() { SetTableItem(i, 4, QString::fromStdString(m_game_info->m_games[i].fw)); SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].size)); SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].version)); - SetTableItem(i, 7, QString::fromStdString(m_game_info->m_games[i].category)); - SetTableItem(i, 8, QString::fromStdString(m_game_info->m_games[i].path)); + SetTableItem(i, 7, QString::fromStdString(m_game_info->m_games[i].path)); } } @@ -168,7 +165,7 @@ void GameListFrame::SetTableItem(int row, int column, QString itemStr) { QVBoxLayout* layout = new QVBoxLayout(widget); QLabel* label = new QLabel(itemStr, widget); - label->setStyleSheet("color: white; font-size: 15px; font-weight: bold;"); + label->setStyleSheet("color: white; font-size: 16px; font-weight: bold;"); // Create shadow effect QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(); diff --git a/src/qt_gui/game_list_utils.h b/src/qt_gui/game_list_utils.h index 7911ce46f..476c90035 100644 --- a/src/qt_gui/game_list_utils.h +++ b/src/qt_gui/game_list_utils.h @@ -14,7 +14,6 @@ struct GameInfo { std::string serial = "Unknown"; std::string version = "Unknown"; std::string region = "Unknown"; - std::string category = "Unknown"; std::string fw = "Unknown"; }; diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 498cec735..0acfade0e 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -7,8 +7,6 @@ #include #include -QT_BEGIN_NAMESPACE - class Ui_MainWindow { public: QAction* bootInstallPkgAct; @@ -354,6 +352,4 @@ public: namespace Ui { class MainWindow : public Ui_MainWindow {}; -} // namespace Ui - -QT_END_NAMESPACE \ No newline at end of file +} // namespace Ui \ No newline at end of file From 766c286d626e65e757313e59649d15f4c83c58de Mon Sep 17 00:00:00 2001 From: psucien Date: Sat, 31 Aug 2024 22:01:08 +0200 Subject: [PATCH 129/147] libraries: gnmdriver: `sceGnmValidateCommandBuffers` added --- src/core/libraries/gnmdriver/gnmdriver.cpp | 6 +++--- src/core/libraries/gnmdriver/gnmdriver.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 34d056156..a2ef94037 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -2346,9 +2346,9 @@ s32 PS4_SYSV_ABI sceGnmUpdateVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmValidateCommandBuffers() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceGnmValidateCommandBuffers() { + LOG_TRACE(Lib_GnmDriver, "called"); + return ORBIS_GNM_ERROR_VALIDATION_NOT_ENABLED; // not available in retail FW; } int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics() { diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 40a6ca5b6..754d488f8 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -223,7 +223,7 @@ s32 PS4_SYSV_ABI sceGnmUpdatePsShader(u32* cmdbuf, u32 size, const u32* ps_regs) s32 PS4_SYSV_ABI sceGnmUpdatePsShader350(u32* cmdbuf, u32 size, const u32* ps_regs); s32 PS4_SYSV_ABI sceGnmUpdateVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u32 shader_modifier); -int PS4_SYSV_ABI sceGnmValidateCommandBuffers(); +s32 PS4_SYSV_ABI sceGnmValidateCommandBuffers(); int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics(); int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics2(); int PS4_SYSV_ABI sceGnmValidateDispatchCommandBuffers(); From 5aaab7f8412591e8d4d8034e3dd4a18d294ac7bc Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:12:59 -0700 Subject: [PATCH 130/147] ci: Remove translations folder from macOS upload. --- .github/workflows/macos-qt.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml index def98ea34..8a882b30f 100644 --- a/.github/workflows/macos-qt.yml +++ b/.github/workflows/macos-qt.yml @@ -50,7 +50,6 @@ jobs: run: | mkdir upload mv ${{github.workspace}}/build/shadps4.app upload - mv ${{github.workspace}}/build/translations upload macdeployqt upload/shadps4.app tar cf shadps4-macos-qt.tar.gz -C upload . From 95943e42edd4373430ade3cd97ca675cbbd19c69 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:28:22 -0700 Subject: [PATCH 131/147] ci: Remove translations folder from Windows upload. --- .github/workflows/windows-qt.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml index 70c33ebe9..1c8657365 100644 --- a/.github/workflows/windows-qt.yml +++ b/.github/workflows/windows-qt.yml @@ -40,7 +40,6 @@ jobs: run: | mkdir upload move build/Release/shadPS4.exe upload - move build/translations upload windeployqt --dir upload upload/shadPS4.exe - name: Upload executable From 0c90ab92dae00ceccd83f742101a69a4d336dcbd Mon Sep 17 00:00:00 2001 From: Mmpr87 <115404923+Mmpr87@users.noreply.github.com> Date: Sun, 1 Sep 2024 01:31:01 +0330 Subject: [PATCH 132/147] Added Persian(Farsi) Translation (#689) * Adding Persian(Farsi)Translation * Update Copyright --- src/qt_gui/translations/fa_IR.ts | 899 +++++++++++++++++++++++++++++++ 1 file changed, 899 insertions(+) create mode 100644 src/qt_gui/translations/fa_IR.ts diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts new file mode 100644 index 000000000..129d54792 --- /dev/null +++ b/src/qt_gui/translations/fa_IR.ts @@ -0,0 +1,899 @@ + + + + AboutDialog + + + About shadPS4 + درباره ShadPS4 + + + + shadPS4 + ShadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + یک شبیه ساز متن باز برای پلی استیشن 4 است. + + + + This software should not be used to play games you have not legally obtained. + این برنامه نباید برای بازی هایی که شما به صورت غیرقانونی به دست آوردید استفاده شود. + + + + ElfViewer + + + Open Folder + فولدر را بازکن + + + + GameInfoClass + + + Loading game list, please wait :3 + درحال بارگیری لیست بازی ها,لطفا کمی صبرکنید :3 + + + + Cancel + لغو + + + + Loading... + ...درحال بارگیری + + + + GameInstallDialog + + + shadPS4 - Choose directory + ShadPS4 - انتخاب محل نصب بازی + + + + Directory to install games + محل نصب بازی ها + + + + Browse + انتخاب دستی + + + + Error + ارور + + + + The value for location to install games is not valid. + .مکان داده شده برای نصب بازی درست نمی باشد + + + + GuiContextMenus + + + Create Shortcut + ساخت شورتکات + + + + Open Game Folder + بازکردن محل نصب بازی + + + + Cheats / Patches + چیت/پچ ها + + + + SFO Viewer + SFO مشاهده + + + + Trophy Viewer + مشاهده تروفی ها + + + + Copy info + کپی کردن اطلاعات + + + + Copy Name + کپی کردن نام + + + + Copy Serial + کپی کردن سریال + + + + Copy All + کپی کردن تمامی مقادیر + + + + Shortcut creation + سازنده شورتکات + + + + Shortcut created successfully!\n %1 + شورتکات با موفقیت ساخته شد! \n %1 + + + + Error + ارور + + + + Error creating shortcut!\n %1 + مشکلی در هنگام ساخت شورتکات بوجود آمد!\n %1 + + + + Install PKG + نصب PKG + + + + MainWindow + + + Open/Add Elf Folder + ELF بازکردن/ساختن پوشه + + + + Install Packages (PKG) + نصب بسته (PKG) + + + + Boot Game + اجرای بازی + + + + About shadPS4 + ShadPS4 درباره + + + + Configure... + ...تنظیمات + + + + Install application from a .pkg file + .PKG نصب بازی از فایل + + + + Recent Games + بازی های اخیر + + + + Exit + خروج + + + + Exit shadPS4 + ShadPS4 بستن + + + + Exit the application. + بستن برنامه + + + + Show Game List + نشان دادن بازی ها + + + + Game List Refresh + رفرش لیست بازی ها + + + + Tiny + کوچک ترین + + + + Small + کوچک + + + + Medium + متوسط + + + + Large + بزرگ + + + + List View + لیستی + + + + Grid View + شبکه ای (چهارخونه) + + + + Elf Viewer + Elf Viewer + + + + Game Install Directory + محل نصب بازی + + + + Download Cheats/Patches + دانلود چیت/پچ + + + + Dump Game List + استخراج لیست بازی ها + + + + PKG Viewer + PKG مشاهده گر + + + + Search... + جست و جو... + + + + File + فایل + + + + View + شخصی سازی + + + + Game List Icons + آیکون ها + + + + Game List Mode + حالت نمایش لیست بازی ها + + + + Settings + تنظیمات + + + + Utils + ابزارها + + + + Themes + تم ها + + + + About + درباره ما + + + + Dark + تیره + + + + Light + روشن + + + + Green + سبز + + + + Blue + آبی + + + + Violet + بنفش + + + + toolBar + نوار ابزار + + + + * Unsupported Vulkan Version + شما پشتیبانی نمیشود Vulkan ورژن* + + + + Download Cheats For All Installed Games + دانلود چیت برای همه بازی ها + + + + Download Patches For All Games + دانلود پچ برای همه بازی ها + + + + Download Complete + دانلود کامل شد✅ + + + + You have downloaded cheats for all the games you have installed. + چیت برای همه بازی های شما دانلودشد✅ + + + + Patches Downloaded Successfully! + پچ ها با موفقیت دانلود شد✅ + + + + All Patches available for all games have been downloaded. + ✅تمام پچ های موجود برای همه بازی های شما دانلود شد + + + + Games: + بازی ها: + + + + PKG File (*.PKG) + PKG فایل (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF فایل های (*.bin *.elf *.oelf) + + + + Game Boot + اجرای بازی + + + + Only one file can be selected! + فقط یک فایل انتخاب کنید! + + + + PKG Extraction + PKG استخراج فایل + + + + Patch detected! + پچ شناسایی شد! + + + + PKG and Game versions match: + و نسخه بازی همخوانی دارد PKG فایل: + + + + Would you like to overwrite? + آیا مایل به جایگزینی فایل هستید؟ + + + + PKG Version %1 is older than installed version: + نسخه فایل PKG %1 قدیمی تر از نسخه نصب شده است: + + + + Game is installed: + بازی نصب شد: + + + + Would you like to install Patch: + آیا مایل به نصب پچ هستید: + + + + DLC Installation + نصب DLC + + + + Would you like to install DLC: %1? + آیا مایل به نصب DLC هستید: %1 + + + + DLC already installed: + قبلا نصب شده DLC این: + + + + Game already installed + این بازی قبلا نصب شده + + + + PKG is a patch, please install the game first! + فایل انتخاب شده یک پچ است, لطفا اول بازی را نصب کنید + + + + PKG ERROR + PKG ارور فایل + + + + Extracting PKG %1/%2 + درحال استخراج PKG %1/%2 + + + + Extraction Finished + استخراج به پایان رسید + + + + Game successfully installed at %1 + بازی با موفقیت در %1 نصب شد + + + + File doesn't appear to be a valid PKG file + این فایل یک PKG درست به نظر نمی آید + + + + PKGViewer + + + Open Folder + بازکردن پوشه + + + + TrophyViewer + + + Trophy Viewer + تروفی ها + + + + SettingsDialog + + + Settings + تنظیمات + + + + General + عمومی + + + + System + سیستم + + + + Console Language + زبان کنسول + + + + Emulator Language + زبان شبیه ساز + + + + Emulator + شبیه ساز + + + + Enable Fullscreen + تمام صفحه + + + + Show Splash + Splash نمایش + + + + Is PS4 Pro + PS4 Pro حالت + + + + Username + نام کاربری + + + + Logger + Logger + + + + Log Type + Log نوع + + + + Log Filter + Log فیلتر + + + + Graphics + گرافیک + + + + Graphics Device + کارت گرافیک مورداستفاده + + + + Width + عرض + + + + Height + طول + + + + Vblank Divider + Vblank Divider + + + + Advanced + ...بیشتر + + + + Enable Shaders Dumping + Shaders Dumping فعال کردن + + + + Enable NULL GPU + NULL GPU فعال کردن + + + + Enable PM4 Dumping + PM4 Dumping فعال کردن + + + + Debug + Debug + + + + Enable Debug Dumping + Debug Dumping + + + + Enable Vulkan Validation Layers + Vulkan Validation Layers + + + + Enable Vulkan Synchronization Validation + Vulkan Synchronization Validation + + + + Enable RenderDoc Debugging + RenderDoc Debugging + + + + CheatsPatches + + + Cheats / Patches + چیت / پچ ها + + + + defaultTextEdit_MSG + defaultTextEdit_MSG + + + + No Image Available + تصویری موجود نمی باشد + + + + Serial: + سریال: + + + + Version: + ورژن: + + + + Size: + حجم: + + + + Select Cheat File: + فایل چیت را انتخاب کنید: + + + + Repository: + :منبع + + + + Download Cheats + دانلود چیت ها + + + + Delete File + پاک کردن فایل + + + + No files selected. + فایلی انتخاب نشده. + + + + You can delete the cheats you don't want after downloading them. + شما میتوانید بعد از دانلود چیت هایی که نمیخواهید را پاک کنید + + + + Do you want to delete the selected file?\n%1 + آیا میخواهید فایل های انتخاب شده را پاک کنید؟ \n%1 + + + + Select Patch File: + فایل پچ را انتخاب کنید + + + + Download Patches + دانلود کردن پچ ها + + + + Save + ذخیره + + + + Cheats + چیت ها + + + + Patches + پچ ها + + + + Error + ارور + + + + No patch selected. + هیچ پچ انتخاب نشده + + + + Unable to open files.json for reading. + .json مشکل در خواندن فایل + + + + No patch file found for the current serial. + هیچ فایل پچ برای سریال بازی شما پیدا نشد. + + + + Unable to open the file for reading. + خطا در خواندن فایل + + + + Unable to open the file for writing. + خطا در نوشتن فایل + + + + Failed to parse XML: + انجام نشد XML تجزیه فایل: + + + + Success + عملیات موفق بود + + + + Options saved successfully. + تغییرات با موفقیت ذخیره شد✅ + + + + Invalid Source + منبع نامعتبر❌ + + + + The selected source is invalid. + منبع انتخاب شده نامعتبر است + + + + File Exists + فایل وجود دارد + + + + File already exists. Do you want to replace it? + فایل از قبل وجود دارد. آیا می خواهید آن را جایگزین کنید؟ + + + + Failed to save file: + ذخیره فایل موفقیت آمیز نبود: + + + + Failed to download file: + خطا در دانلود فایل: + + + + Cheats Not Found + چیت یافت نشد + + + + CheatsNotFound_MSG + متاسفانه هیچ چیتی از منبع انتخاب شده پیدا نشد! شما میتوانید منابع دیگری را برای دانلود انتخاب و یا چیت های خود را به صورت دستی واردکنید. + + + + Cheats Downloaded Successfully + دانلود چیت ها موفقیت آمیز بود✅ + + + + CheatsDownloadedSuccessfully_MSG + تمامی چیت های موجود برای این بازی از منبع انتخاب شده دانلود شد! شما همچنان میتوانید چیت های دیگری را ازمنابع مختلف دانلود کنید و درصورت موجود بودن از آنها استفاده کنید. + + + + Failed to save: + خطا در ذخیره اطلاعات: + + + + Failed to download: + خطا در دانلود❌ + + + + Download Complete + دانلود موفقیت آمیز بود✅ + + + + DownloadComplete_MSG + دانلود با موفقیت به اتمام رسید✅ + + + + Failed to parse JSON data from HTML. + HTML از JSON خطا در تجزیه اطلاعات. + + + + Failed to retrieve HTML page. + HTML خطا دربازیابی صفحه + + + + Failed to open file: + خطا در اجرای فایل: + + + + XML ERROR: + XML ERROR: + + + + Failed to open files.json for writing + .json خطا در نوشتن فایل + + + + Author: + تولید کننده: + + + + Directory does not exist: + پوشه وجود ندارد: + + + + Failed to open files.json for reading. + .json خطا در خواندن فایل + + + + Name: + نام: + + + From 7551f061ad15545eb11287340ffcb7f9e19d50cf Mon Sep 17 00:00:00 2001 From: huss2342 <89368091+huss2342@users.noreply.github.com> Date: Sat, 31 Aug 2024 17:01:14 -0500 Subject: [PATCH 133/147] Added arabic translation (#693) * added arabic translation * added arabic translation --- src/qt_gui/translations/ar.ts | 915 ++++++++++++++++++++++++++++++++++ 1 file changed, 915 insertions(+) create mode 100644 src/qt_gui/translations/ar.ts diff --git a/src/qt_gui/translations/ar.ts b/src/qt_gui/translations/ar.ts new file mode 100644 index 000000000..d35bbbf86 --- /dev/null +++ b/src/qt_gui/translations/ar.ts @@ -0,0 +1,915 @@ + + + + + + AboutDialog + + + About shadPS4 + حول shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 هو محاكي تجريبي مفتوح المصدر لجهاز PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + يجب عدم استخدام هذا البرنامج لتشغيل الألعاب التي لم تحصل عليها بشكل قانوني. + + + + ElfViewer + + + Open Folder + فتح المجلد + + + + GameInfoClass + + + Loading game list, please wait :3 + جارٍ تحميل قائمة الألعاب، يرجى الانتظار :3 + + + + Cancel + إلغاء + + + + Loading... + ...جارٍ التحميل + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - اختر المجلد + + + + Directory to install games + مجلد تثبيت الألعاب + + + + Browse + تصفح + + + + Error + خطأ + + + + The value for location to install games is not valid. + قيمة موقع تثبيت الألعاب غير صالحة. + + + + GuiContextMenus + + + Create Shortcut + إنشاء اختصار + + + + Open Game Folder + فتح مجلد اللعبة + + + + Cheats / Patches + الغش / التصحيحات + + + + SFO Viewer + عارض SFO + + + + Trophy Viewer + عارض الجوائز + + + + Copy info + نسخ المعلومات + + + + Copy Name + نسخ الاسم + + + + Copy Serial + نسخ الرقم التسلسلي + + + + Copy All + نسخ الكل + + + + Shortcut creation + إنشاء اختصار + + + + Shortcut created successfully!\n %1 + تم إنشاء الاختصار بنجاح!\n %1 + + + + Error + خطأ + + + + Error creating shortcut!\n %1 + !\n %1 خطأ في إنشاء الاختصار + + + + Install PKG + PKG تثبيت + + + + MainWindow + + + Open/Add Elf Folder + Elf فتح/إضافة مجلد + + + + Install Packages (PKG) + (PKG) تثبيت الحزم + + + + Boot Game + تشغيل اللعبة + + + + About shadPS4 + shadPS4 حول + + + + Configure... + ...تكوين + + + + Install application from a .pkg file + .pkg تثبيت التطبيق من ملف + + + + Recent Games + الألعاب الأخيرة + + + + Exit + خروج + + + + Exit shadPS4 + الخروج من shadPS4 + + + + Exit the application. + الخروج من التطبيق. + + + + Show Game List + إظهار قائمة الألعاب + + + + Game List Refresh + تحديث قائمة الألعاب + + + + Tiny + صغير جدًا + + + + Small + صغير + + + + Medium + متوسط + + + + Large + كبير + + + + List View + عرض القائمة + + + + Grid View + عرض الشبكة + + + + Elf Viewer + عارض Elf + + + + Game Install Directory + دليل تثبيت اللعبة + + + + Download Cheats/Patches + تنزيل الغش/التصحيحات + + + + Dump Game List + تفريغ قائمة الألعاب + + + + PKG Viewer + عارض PKG + + + + Search... + ...بحث + + + + File + ملف + + + + View + عرض + + + + Game List Icons + أيقونات قائمة الألعاب + + + + Game List Mode + وضع قائمة الألعاب + + + + Settings + الإعدادات + + + + Utils + الأدوات + + + + Themes + السمات + + + + About + حول + + + + Dark + داكن + + + + Light + فاتح + + + + Green + أخضر + + + + Blue + أزرق + + + + Violet + بنفسجي + + + + toolBar + شريط الأدوات + + + + PKGViewer + + + Open Folder + فتح المجلد + + + + TrophyViewer + + + Trophy Viewer + عارض الجوائز + + + + SettingsDialog + + + Settings + الإعدادات + + + + General + عام + + + + System + النظام + + + + Console Language + لغة وحدة التحكم + + + + Emulator Language + لغة المحاكي + + + + Emulator + المحاكي + + + + Enable Fullscreen + تمكين ملء الشاشة + + + + Show Splash + إظهار شاشة البداية + + + + Is PS4 Pro + PS4 Pro هل هو + + + + Username + اسم المستخدم + + + + Logger + المسجل + + + + Log Type + نوع السجل + + + + Log Filter + مرشح السجل + + + + Graphics + الرسومات + + + + Graphics Device + جهاز الرسومات + + + + Width + العرض + + + + Height + الارتفاع + + + + Vblank Divider + Vblank مقسم + + + + Advanced + متقدم + + + + Enable Shaders Dumping + تمكين تفريغ الشيدرات + + + + Enable NULL GPU + تمكين وحدة معالجة الرسومات الفارغة + + + + Enable PM4 Dumping + PM4 تمكين تفريغ + + + + Debug + تصحيح الأخطاء + + + + Enable Debug Dumping + تمكين تفريغ التصحيح + + + + Enable Vulkan Validation Layers + Vulkan تمكين طبقات التحقق من + + + + Enable Vulkan Synchronization Validation + Vulkan تمكين التحقق من تزامن + + + + Enable RenderDoc Debugging + RenderDoc تمكين تصحيح أخطاء + + + + MainWindow + + + * Unsupported Vulkan Version + * إصدار Vulkan غير مدعوم + + + + Download Cheats For All Installed Games + تنزيل الغش لجميع الألعاب المثبتة + + + + Download Patches For All Games + تنزيل التصحيحات لجميع الألعاب + + + + Download Complete + اكتمل التنزيل + + + + You have downloaded cheats for all the games you have installed. + لقد قمت بتنزيل الغش لجميع الألعاب التي قمت بتثبيتها. + + + + Patches Downloaded Successfully! + !تم تنزيل التصحيحات بنجاح + + + + All Patches available for all games have been downloaded. + .تم تنزيل جميع التصحيحات المتاحة لجميع الألعاب + + + + Games: + :الألعاب + + + + PKG File (*.PKG) + PKG (*.PKG) ملف + + + + ELF files (*.bin *.elf *.oelf) + ELF (*.bin *.elf *.oelf) ملفات + + + + Game Boot + تشغيل اللعبة + + + + Only one file can be selected! + !يمكن تحديد ملف واحد فقط + + + + PKG Extraction + PKG استخراج + + + + Patch detected! + تم اكتشاف تصحيح! + + + + PKG and Game versions match: + :واللعبة تتطابق إصدارات PKG + + + + Would you like to overwrite? + هل ترغب في الكتابة فوق الملف الموجود؟ + + + + PKG Version %1 is older than installed version: + :أقدم من الإصدار المثبت PKG Version %1 + + + + Game is installed: + :اللعبة مثبتة + + + + Would you like to install Patch: + :هل ترغب في تثبيت التصحيح + + + + DLC Installation + تثبيت المحتوى القابل للتنزيل + + + + Would you like to install DLC: %1? + هل ترغب في تثبيت المحتوى القابل للتنزيل: 1%؟ + + + + DLC already installed: + :المحتوى القابل للتنزيل مثبت بالفعل + + + + Game already installed + اللعبة مثبتة بالفعل + + + + PKG is a patch, please install the game first! + !PKG هو تصحيح، يرجى تثبيت اللعبة أولاً + + + + PKG ERROR + PKG خطأ في + + + + Extracting PKG %1/%2 + PKG %1/%2 جاري استخراج + + + + Extraction Finished + اكتمل الاستخراج + + + + Game successfully installed at %1 + تم تثبيت اللعبة بنجاح في %1 + + + + File doesn't appear to be a valid PKG file + يبدو أن الملف ليس ملف PKG صالحًا + + + + CheatsPatches + + + Cheats / Patches + الغش / التصحيحات + + + + defaultTextEdit_MSG + الغش والتصحيحات هي ميزات تجريبية. + استخدمها بحذر. + + قم بتنزيل الغش بشكل فردي عن طريق اختيار المستودع والنقر على زر التنزيل. + في علامة تبويب التصحيحات، يمكنك تنزيل جميع التصحيحات دفعة واحدة، واختيار ما تريد استخدامه، وحفظ اختياراتك. + + نظرًا لأننا لا نقوم بتطوير الغش/التصحيحات، + يرجى الإبلاغ عن أي مشاكل إلى مؤلف الغش. + + هل قمت بإنشاء غش جديد؟ قم بزيارة: + https://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + لا تتوفر صورة + + + + Serial: + الرقم التسلسلي: + + + + Version: + الإصدار: + + + + Size: + الحجم: + + + + Select Cheat File: + اختر ملف الغش: + + + + Repository: + المستودع: + + + + Download Cheats + تنزيل الغش + + + + Delete File + حذف الملف + + + + No files selected. + لم يتم اختيار أي ملفات. + + + + You can delete the cheats you don't want after downloading them. + يمكنك حذف الغش الذي لا تريده بعد تنزيله. + + + + Do you want to delete the selected file?\n%1 + هل تريد حذف الملف المحدد؟ + %1 + + + + Select Patch File: + اختر ملف التصحيح: + + + + Download Patches + تنزيل التصحيحات + + + + Save + حفظ + + + + Cheats + الغش + + + + Patches + التصحيحات + + + + Error + خطأ + + + + No patch selected. + لم يتم اختيار أي تصحيح. + + + + Unable to open files.json for reading. + تعذر فتح files.json للقراءة. + + + + No patch file found for the current serial. + لم يتم العثور على ملف تصحيح للرقم التسلسلي الحالي. + + + + Unable to open the file for reading. + تعذر فتح الملف للقراءة. + + + + Unable to open the file for writing. + تعذر فتح الملف للكتابة. + + + + Failed to parse XML: + :فشل في تحليل XML + + + + Success + نجاح + + + + Options saved successfully. + تم حفظ الخيارات بنجاح. + + + + Invalid Source + مصدر غير صالح + + + + The selected source is invalid. + المصدر المحدد غير صالح. + + + + File Exists + الملف موجود + + + + File already exists. Do you want to replace it? + الملف موجود بالفعل. هل تريد استبداله؟ + + + + Failed to save file: + :فشل في حفظ الملف + + + + Failed to download file: + :فشل في تنزيل الملف + + + + Cheats Not Found + لم يتم العثور على الغش + + + + CheatsNotFound_MSG + لم يتم العثور على غش لهذه اللعبة في هذا الإصدار من المستودع المحدد. حاول استخدام مستودع آخر أو إصدار آخر من اللعبة. + + + + Cheats Downloaded Successfully + تم تنزيل الغش بنجاح + + + + CheatsDownloadedSuccessfully_MSG + لقد نجحت في تنزيل الغش لهذا الإصدار من اللعبة من المستودع المحدد. يمكنك محاولة التنزيل من مستودع آخر. إذا كان متاحًا، يمكنك اختياره عن طريق تحديد الملف من القائمة. + + + + Failed to save: + :فشل في الحفظ + + + + Failed to download: + :فشل في التنزيل + + + + Download Complete + اكتمل التنزيل + + + + DownloadComplete_MSG + تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات لجميع الألعاب، ولا داعي لتنزيلها بشكل فردي لكل لعبة كما هو الحال مع الغش. + + + + Failed to parse JSON data from HTML. + فشل في تحليل بيانات JSON من HTML. + + + + Failed to retrieve HTML page. + .HTML فشل في استرجاع صفحة + + + + Failed to open file: + :فشل في فتح الملف + + + + XML ERROR: + :خطأ في XML + + + + Failed to open files.json for writing + فشل في فتح files.json للكتابة + + + + Author: + :المؤلف + + + + Directory does not exist: + :المجلد غير موجود + + + + Failed to open files.json for reading. + فشل في فتح files.json للقراءة. + + + + Name: + :الاسم + + + From 946dec7df879914662c97ae17621c9500e45f860 Mon Sep 17 00:00:00 2001 From: Fabian <38659818+Fejbien@users.noreply.github.com> Date: Sun, 1 Sep 2024 01:00:24 +0200 Subject: [PATCH 134/147] whitespace added, "patch" consistency --- src/qt_gui/translations/pl_PL.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index 80f0aa5c4..ac4a75dd3 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -93,7 +93,7 @@ Cheats / Patches - Kody / Patche + Kody / Łatki @@ -256,7 +256,7 @@ Download Cheats/Patches - Pobierz Kody / Patche + Pobierz Kody / Łatki @@ -821,7 +821,7 @@ CheatsNotFound_MSG - Nie znaleziono kodów do tej gry w tej wersji wybranego repozytorium.Spróbuj innego repozytorium lub innej wersji gry. + Nie znaleziono kodów do tej gry w tej wersji wybranego repozytorium. Spróbuj innego repozytorium lub innej wersji gry. @@ -899,4 +899,4 @@ Nie udało się sparsować JSON: - \ No newline at end of file + From 5b2779d54868ce3fec808e19db4cb5b9f441ed6e Mon Sep 17 00:00:00 2001 From: CrazyBloo Date: Sun, 1 Sep 2024 01:44:51 -0400 Subject: [PATCH 135/147] only apply cheats at runtime --- src/qt_gui/cheats_patches.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index fd0bc4e14..f7326192c 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -1158,6 +1158,13 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) { if (!m_cheats.contains(modName)) return; + if (MemoryPatcher::g_eboot_address == 0 && enabled) { + QMessageBox::critical(this, tr("Error"), + tr("Can't apply cheats before the game is started")); + uncheckAllCheatCheckBoxes(); + return; + } + Cheat cheat = m_cheats[modName]; for (const MemoryMod& memoryMod : cheat.memoryMods) { @@ -1167,16 +1174,9 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) { std::string offsetStr = memoryMod.offset.toStdString(); std::string valueStr = value.toStdString(); - if (MemoryPatcher::g_eboot_address == 0) { - MemoryPatcher::patchInfo addingPatch; - addingPatch.modNameStr = modNameStr; - addingPatch.offsetStr = offsetStr; - addingPatch.valueStr = valueStr; - addingPatch.isOffset = true; + if (MemoryPatcher::g_eboot_address == 0) + return; - MemoryPatcher::AddPatchToQueue(addingPatch); - continue; - } // Determine if the hint field is present bool isHintPresent = m_cheats[modName].hasHint; MemoryPatcher::PatchMemory(modNameStr, offsetStr, valueStr, !isHintPresent, false); From 6510083778d5bec1fa589ae4a98a0ce6425d3e5f Mon Sep 17 00:00:00 2001 From: tGecko Date: Sun, 1 Sep 2024 10:33:46 +0200 Subject: [PATCH 136/147] improve german translation --- src/qt_gui/translations/de.ts | 190 +++++++++++++++++----------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index c833f2e28..c208ad441 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -6,7 +6,7 @@ About shadPS4 - About shadPS4 + Über shadPS4 @@ -16,12 +16,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 ist ein experimenteller Open-Source-Emulator für die Playstation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Diese Software soll nicht dazu benutzt werden illegal kopierte Spiele zu spielen. @@ -29,7 +29,7 @@ Open Folder - Open Folder + Ordner öffnen @@ -37,17 +37,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Lade Spielliste, bitte warten :3 Cancel - Cancel + Abbrechen Loading... - Loading... + Lade... @@ -55,27 +55,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Wähle Ordner Directory to install games - Directory to install games + Installationsverzeichnis für Spiele Browse - Browse + Durchsuchen Error - Error + Fehler The value for location to install games is not valid. - The value for location to install games is not valid. + Der ausgewählte Ordner ist nicht gültig. @@ -83,12 +83,12 @@ Create Shortcut - Create Shortcut + Verknüpfung erstellen Open Game Folder - Open Game Folder + Spieleordner öffnen @@ -98,57 +98,57 @@ SFO Viewer - SFO Viewer + SFO anzeigen Trophy Viewer - Trophy Viewer + Trophäen anzeigen Copy info - Copy info + Infos kopieren Copy Name - Copy Name + Namen kopieren Copy Serial - Copy Serial + Seriennummer kopieren Copy All - Copy All + Alles kopieren Shortcut creation - Shortcut creation + Verknüpfungserstellung Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Verknüpfung erfolgreich erstellt!\n %1 Error - Error + Fehler Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Fehler beim Erstellen der Verknüpfung!\n %1 Install PKG - Install PKG + PKG installieren @@ -156,102 +156,102 @@ Open/Add Elf Folder - Open/Add Elf Folder + Elf-Ordner öffnen/hinzufügen Install Packages (PKG) - Install Packages (PKG) + Pakete installieren (PKG) Boot Game - Boot Game + Spiel starten About shadPS4 - About shadPS4 + Über shadPS4 Configure... - Configure... + Konfigurieren... Install application from a .pkg file - Install application from a .pkg file + Installiere Anwendung aus .pkg-Datei Recent Games - Recent Games + Zuletzt gespielt Exit - Exit + Beenden Exit shadPS4 - Exit shadPS4 + shadPS4 beenden Exit the application. - Exit the application. + Die Anwendung beenden. Show Game List - Show Game List + Spielliste anzeigen Game List Refresh - Game List Refresh + Spielliste aktualisieren Tiny - Tiny + Winzig Small - Small + Klein Medium - Medium + Mittel Large - Large + Groß List View - List View + Listenansicht Grid View - Grid View + Gitteransicht Elf Viewer - Elf Viewer + Elf-Ansicht Game Install Directory - Game Install Directory + Installationsverzeichnis für Spiele @@ -261,27 +261,27 @@ Dump Game List - Dump Game List + Spielliste ausgeben PKG Viewer - PKG Viewer + PKG-Ansicht Search... - Search... + Suchen... File - File + Datei View - View + Ansicht @@ -291,52 +291,52 @@ Game List Mode - Game List Mode + Spiellisten-Symoble Settings - Settings + Einstellungen Utils - Utils + Werkzeuge Themes - Themes + Stile About - About + Über Dark - Dark + Dunkel Light - Light + Hell Green - Green + Grün Blue - Blue + Blau Violet - Violet + Violett @@ -349,7 +349,7 @@ Open Folder - Open Folder + Ordner öffnen @@ -357,7 +357,7 @@ Trophy Viewer - Trophy Viewer + Trophäenansicht @@ -365,12 +365,12 @@ Settings - Settings + Einstellungen General - General + Allgemein @@ -380,12 +380,12 @@ Console Language - Console Language + Konsolensprache Emulator Language - Emulator Language + Emulatorsprache @@ -395,22 +395,22 @@ Enable Fullscreen - Enable Fullscreen + Vollbild aktivieren Show Splash - Show Splash + Startbildschirm anzeigen Is PS4 Pro - Is PS4 Pro + Ist PS4 Pro Username - Username + Benutzername @@ -420,57 +420,57 @@ Log Type - Log Type + Logtyp Log Filter - Log Filter + Log-Filter Graphics - Graphics + Grafik Graphics Device - Graphics Device + Grafikgerät Width - Width + Breite Height - Height + Höhe Vblank Divider - Vblank Divider + Vblank-Teiler Advanced - Advanced + Erweitert Enable Shaders Dumping - Enable Shaders Dumping + Shader-Dumping aktivieren Enable NULL GPU - Enable NULL GPU + NULL GPU aktivieren Enable PM4 Dumping - Enable PM4 Dumping + PM4-Dumping aktivieren @@ -480,22 +480,22 @@ Enable Debug Dumping - Enable Debug Dumping + Debug-Dumping aktivieren Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Vulkan Validations-Ebenen aktivieren Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Vulkan Synchronisations-Validierung aktivieren Enable RenderDoc Debugging - Enable RenderDoc Debugging + RenderDoc-Debugging aktivieren @@ -578,7 +578,7 @@ Would you like to overwrite? - Würden Sie gerne überschreiben? + Willst du überschreiben? @@ -593,7 +593,7 @@ Would you like to install Patch: - Möchten Sie den Patch installieren: + Willst du den Patch installieren: @@ -603,7 +603,7 @@ Would you like to install DLC: %1? - Würden Sie gerne DLC installieren: %1? + Willst du den DLC installieren: %1? @@ -623,7 +623,7 @@ PKG ERROR - PKG-ERROR + PKG-FEHLER @@ -656,7 +656,7 @@ defaultTextEdit_MSG - Cheats/Patches sind experimentell.\nVerwenden Sie sie mit Vorsicht.\n\nLaden Sie Cheats einzeln herunter, indem Sie das Repository auswählen und auf die Download-Schaltfläche klicken.\nAuf der Registerkarte Patches können Sie alle Patches auf einmal herunterladen, auswählen, welche Sie verwenden möchten, und die Auswahl speichern.\n\nDa wir die Cheats/Patches nicht entwickeln,\nbitte melden Sie Probleme an den Cheat-Autor.\n\nHaben Sie einen neuen Cheat erstellt? Besuchen Sie:\nhttps://github.com/shadps4-emu/ps4_cheats + Cheats/Patches sind experimentell.\nVerwende sie mit Vorsicht.\n\nLade Cheats einzeln herunter, indem du das Repository auswählst und auf die Download-Schaltfläche klickst.\nAuf der Registerkarte Patches kannst du alle Patches auf einmal herunterladen, auswählen, welche du verwenden möchtest, und die Auswahl speichern.\n\nDa wir die Cheats/Patches nicht entwickeln,\nbitte melde Probleme an den Cheat-Autor.\n\nHast du einen neuen Cheat erstellt? Besuche:\nhttps://github.com/shadps4-emu/ps4_cheats @@ -706,12 +706,12 @@ You can delete the cheats you don't want after downloading them. - Sie können die Cheats, die Sie nicht möchten, nach dem Herunterladen löschen. + Du kannst die Cheats, die du nicht möchtest, nach dem Herunterladen löschen. Do you want to delete the selected file?\n%1 - Wollen Sie die ausgewählte Datei löschen?\n%1 + Willst du die ausgewählte Datei löschen?\n%1 @@ -801,7 +801,7 @@ File already exists. Do you want to replace it? - Datei existiert bereits. Möchten Sie sie ersetzen? + Datei existiert bereits. Möchtest du sie ersetzen? @@ -821,7 +821,7 @@ CheatsNotFound_MSG - Keine Cheats für dieses Spiel in dieser Version des gewählten Repositories gefunden. Versuchen Sie es mit einem anderen Repository oder einer anderen Version des Spiels. + Keine Cheats für dieses Spiel in dieser Version des gewählten Repositories gefunden. Versuche es mit einem anderen Repository oder einer anderen Version des Spiels. @@ -831,7 +831,7 @@ CheatsDownloadedSuccessfully_MSG - Sie haben erfolgreich Cheats für diese Version des Spiels aus dem gewählten Repository heruntergeladen. Sie können versuchen, von einem anderen Repository herunterzuladen. Wenn verfügbar, können Sie es auswählen, indem Sie die Datei aus der Liste auswählen. + Du hast erfolgreich Cheats für diese Version des Spiels aus dem gewählten Repository heruntergeladen. Du kannst auch versuchen, Cheats von einem anderen Repository herunterzuladen. Wenn verfügbar, kannst du sie auswählen, indem du die Datei aus der Liste auswählst. From 9e5047947b2c2b8fef712cd3840a84908eca7a11 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 1 Sep 2024 02:22:42 -0700 Subject: [PATCH 137/147] macos: Remove need for TLS patch by storing TCB pointer in FS. --- CMakeLists.txt | 2 +- src/core/cpu_patches.cpp | 14 +-- .../libraries/kernel/thread_management.cpp | 2 + src/core/linker.cpp | 2 + src/core/tls.cpp | 109 +++++++++++++++--- src/core/tls.h | 2 + 6 files changed, 103 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a65e9c599..a5331a7ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -636,7 +636,7 @@ target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAlloca if (APPLE) # Reserve system-managed memory space. - target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x400000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x20000000000) + target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x20000000000) # Link MoltenVK for Vulkan support find_library(MOLTENVK MoltenVK REQUIRED) diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp index e713155ae..151d34986 100644 --- a/src/core/cpu_patches.cpp +++ b/src/core/cpu_patches.cpp @@ -499,7 +499,6 @@ static bool FilterTcbAccess(const ZydisDecodedOperand* operands) { static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { const auto dst = ZydisToXbyakRegisterOperand(operands[0]); - const auto slot = GetTcbKey(); #if defined(_WIN32) // The following logic is based on the Kernel32.dll asm of TlsGetValue @@ -507,6 +506,8 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe static constexpr u32 TlsExpansionSlotsOffset = 0x1780; static constexpr u32 TlsMinimumAvailable = 64; + const auto slot = GetTcbKey(); + // Load the pointer to the table of TLS slots. c.putSeg(gs); if (slot < TlsMinimumAvailable) { @@ -520,11 +521,6 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe // Load the pointer to our buffer. c.mov(dst, qword[dst + tls_index * sizeof(LPVOID)]); } -#elif defined(__APPLE__) - // The following logic is based on the Darwin implementation of _os_tsd_get_direct, used by - // pthread_getspecific https://github.com/apple/darwin-xnu/blob/main/libsyscall/os/tsd.h#L89-L96 - c.putSeg(gs); - c.mov(dst, qword[reinterpret_cast(slot * sizeof(void*))]); #else const auto src = ZydisToXbyakMemoryOperand(operands[1]); @@ -548,10 +544,10 @@ struct PatchInfo { }; static const std::unordered_map Patches = { -#if defined(_WIN32) || defined(__APPLE__) - // Windows and Apple need a trampoline. +#if defined(_WIN32) + // Windows needs a trampoline. {ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}}, -#else +#elif !defined(__APPLE__) {ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}}, #endif diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index b69f8b412..11d472a49 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -18,6 +18,7 @@ #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" #include "core/linker.h" +#include "core/tls.h" #ifdef _WIN64 #include #else @@ -987,6 +988,7 @@ static void cleanup_thread(void* arg) { destructor(value); } } + Core::SetTcbBase(nullptr); thread->is_almost_done = true; } diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 0c914cef1..0d76f4b9e 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -106,6 +106,8 @@ void Linker::Execute() { RunMainEntry(m->GetEntryAddress(), &p, ProgramExitFunc); } } + + SetTcbBase(nullptr); } s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { diff --git a/src/core/tls.cpp b/src/core/tls.cpp index 3216d0fe4..4a0cdb0dc 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -9,7 +9,10 @@ #ifdef _WIN32 #include #elif defined(__APPLE__) -#include +#include +#include +#include +#include #endif namespace Core { @@ -17,11 +20,17 @@ namespace Core { #ifdef _WIN32 static DWORD slot = 0; +static std::once_flag slot_alloc_flag; static void AllocTcbKey() { slot = TlsAlloc(); } +u32 GetTcbKey() { + std::call_once(slot_alloc_flag, &AllocTcbKey); + return slot; +} + void SetTcbBase(void* image_address) { const BOOL result = TlsSetValue(GetTcbKey(), image_address); ASSERT(result != 0); @@ -33,27 +42,98 @@ Tcb* GetTcbBase() { #elif defined(__APPLE__) -static pthread_key_t slot = 0; +// Reserve space in the 32-bit address range for allocating TCB pages. +asm(".zerofill TCB_SPACE,TCB_SPACE,__guest_system,0x3FC000"); -static void AllocTcbKey() { - ASSERT(pthread_key_create(&slot, nullptr) == 0); +static constexpr u64 ldt_region_base = 0x4000; +static constexpr u64 ldt_region_size = 0x3FC000; +static constexpr u16 ldt_block_size = 0x1000; +static constexpr u16 ldt_index_base = 8; +static constexpr u16 ldt_index_total = (ldt_region_size - ldt_region_base) / ldt_block_size; + +static boost::icl::interval_set free_ldts{}; +static std::mutex free_ldts_lock; +static std::once_flag ldt_region_init_flag; + +static u16 GetLdtIndex() { + sel_t selector; + asm volatile("mov %%fs, %0" : "=r"(selector)); + return selector.index; +} + +static void InitLdtRegion() { + const void* result = + mmap(reinterpret_cast(ldt_region_base), ldt_region_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + ASSERT_MSG(result != MAP_FAILED, "Failed to map memory region for LDT entries."); + + free_ldts += + boost::icl::interval::right_open(ldt_index_base, ldt_index_base + ldt_index_total); +} + +static void** SetupThreadLdt() { + std::call_once(ldt_region_init_flag, InitLdtRegion); + + // Allocate a new LDT index for the current thread. + u16 ldt_index; + { + std::unique_lock lock{free_ldts_lock}; + ASSERT_MSG(!free_ldts.empty(), "Out of LDT space."); + ldt_index = first(*free_ldts.begin()); + free_ldts -= ldt_index; + } + const u64 addr = ldt_region_base + (ldt_index - ldt_index_base) * ldt_block_size; + + // Create an LDT entry for the TCB. + const ldt_entry ldt{.data{ + .base00 = static_cast(addr), + .base16 = static_cast(addr >> 16), + .base24 = static_cast(addr >> 24), + .limit00 = static_cast(ldt_block_size - 1), + .limit16 = 0, + .type = DESC_DATA_WRITE, + .dpl = 3, // User accessible + .present = 1, // Segment present + .stksz = DESC_DATA_32B, + .granular = DESC_GRAN_BYTE, + }}; + int ret = i386_set_ldt(ldt_index, &ldt, 1); + ASSERT_MSG(ret == ldt_index, + "Failed to set LDT for TLS area: expected {}, but syscall returned {}", ldt_index, + ret); + + // Set the FS segment to the created LDT. + const sel_t sel{ + .rpl = USER_PRIV, + .ti = SEL_LDT, + .index = ldt_index, + }; + asm volatile("mov %0, %%fs" ::"r"(sel)); + + return reinterpret_cast(addr); +} + +static void FreeThreadLdt() { + std::unique_lock lock{free_ldts_lock}; + free_ldts += GetLdtIndex(); } void SetTcbBase(void* image_address) { - ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0); + if (image_address != nullptr) { + *SetupThreadLdt() = image_address; + } else { + FreeThreadLdt(); + } } Tcb* GetTcbBase() { - return reinterpret_cast(pthread_getspecific(GetTcbKey())); + Tcb* tcb; + asm volatile("mov %%fs:0x0, %0" : "=r"(tcb)); + return tcb; } #else -// Placeholder for code compatibility. -static constexpr u32 slot = 0; - -static void AllocTcbKey() {} - void SetTcbBase(void* image_address) { asm volatile("wrgsbase %0" ::"r"(image_address) : "memory"); } @@ -66,11 +146,4 @@ Tcb* GetTcbBase() { #endif -static std::once_flag slot_alloc_flag; - -u32 GetTcbKey() { - std::call_once(slot_alloc_flag, &AllocTcbKey); - return slot; -} - } // namespace Core diff --git a/src/core/tls.h b/src/core/tls.h index 9829c8d9a..f5bf33184 100644 --- a/src/core/tls.h +++ b/src/core/tls.h @@ -22,8 +22,10 @@ struct Tcb { void* tcb_thread; }; +#ifdef _WIN32 /// Gets the thread local storage key for the TCB block. u32 GetTcbKey(); +#endif /// Sets the data pointer to the TCB block. void SetTcbBase(void* image_address); From 7415cee34ccb5d08094ad05987fdde1873d847bf Mon Sep 17 00:00:00 2001 From: Marcin Mitura Date: Fri, 30 Aug 2024 20:59:08 +0200 Subject: [PATCH 138/147] [macOS] Place `shadPS4/user` folder in `Application Support` Partially resolves #509 --- .gitignore | 3 +++ src/common/path_util.cpp | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2a3145085..087f29683 100644 --- a/.gitignore +++ b/.gitignore @@ -409,3 +409,6 @@ FodyWeavers.xsd /out/* /third-party/out/* /src/common/scm_rev.cpp + +# for macOS +**/.DS_Store \ No newline at end of file diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 8d369fc7b..e6c1fc1af 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -82,11 +82,20 @@ static std::filesystem::path GetBundleParentDirectory() { static auto UserPaths = [] { #ifdef __APPLE__ - std::filesystem::current_path(GetBundleParentDirectory()); + // Start by assuming the base directory is the bundle's parent directory. + std::filesystem::path base_dir = GetBundleParentDirectory(); + std::filesystem::path user_dir = base_dir / PORTABLE_DIR; + // Check if the "user" directory exists in the current path: + if (!std::filesystem::exists(user_dir)) { + // If it doesn't exist, use the new hardcoded path: + user_dir = + std::filesystem::path(getenv("HOME")) / "Library" / "Application Support" / "shadPS4"; + } +#else + const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR; #endif std::unordered_map paths; - const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR; const auto create_path = [&](PathType shad_path, const fs::path& new_path) { std::filesystem::create_directory(new_path); @@ -155,4 +164,4 @@ void SetUserPath(PathType shad_path, const fs::path& new_path) { UserPaths.insert_or_assign(shad_path, new_path); } -} // namespace Common::FS +} // namespace Common::FS \ No newline at end of file From 079ae9ef431477cf4eb17d05d20457ebbf1001ab Mon Sep 17 00:00:00 2001 From: tGecko Date: Sun, 1 Sep 2024 12:40:51 +0200 Subject: [PATCH 139/147] include git short hash in artifact filename --- .github/workflows/linux-qt.yml | 6 +++++- .github/workflows/linux.yml | 8 ++++++-- .github/workflows/macos-qt.yml | 6 +++++- .github/workflows/macos.yml | 6 +++++- .github/workflows/windows-qt.yml | 9 ++++++++- .github/workflows/windows.yml | 9 ++++++++- 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/.github/workflows/linux-qt.yml b/.github/workflows/linux-qt.yml index 26b80d683..efafb6e5d 100644 --- a/.github/workflows/linux-qt.yml +++ b/.github/workflows/linux-qt.yml @@ -34,8 +34,12 @@ jobs: - name: Run AppImage packaging script run: ./.github/linux-appimage-qt.sh + - name: Retrieve Git Hash + id: git-hash + run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-linux-qt + name: shadps4-linux-qt-${{ steps.git-hash.outputs.hash }} path: Shadps4-qt.AppImage \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index ef77a16c8..081e3259d 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -31,10 +31,14 @@ jobs: - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + - name: Retrieve Git Hash + id: git-hash + run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-ubuntu64 + name: shadps4-ubuntu64-${{ steps.git-hash.outputs.hash }} path: | ${{github.workspace}}/build/shadps4 @@ -44,5 +48,5 @@ jobs: - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-sdl-appimage + name: shadps4-sdl-appimage-${{ steps.git-hash.outputs.hash }} path: Shadps4-sdl.AppImage diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml index 8a882b30f..2b94c7b0c 100644 --- a/.github/workflows/macos-qt.yml +++ b/.github/workflows/macos-qt.yml @@ -53,8 +53,12 @@ jobs: macdeployqt upload/shadps4.app tar cf shadps4-macos-qt.tar.gz -C upload . + - name: Retrieve Git Hash + id: git-hash + run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-macos-qt + name: shadps4-macos-qt-${{ steps.git-hash.outputs.hash }} path: shadps4-macos-qt.tar.gz diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1a2a6eff6..451b06e81 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -45,8 +45,12 @@ jobs: install_name_tool -add_rpath "@loader_path" upload/shadps4 tar cf shadps4-macos-sdl.tar.gz -C upload . + - name: Retrieve Git Hash + id: git-hash + run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-macos-sdl + name: shadps4-macos-sdl-${{ steps.git-hash.outputs.hash }} path: shadps4-macos-sdl.tar.gz diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml index 1c8657365..8b5430050 100644 --- a/.github/workflows/windows-qt.yml +++ b/.github/workflows/windows-qt.yml @@ -41,9 +41,16 @@ jobs: mkdir upload move build/Release/shadPS4.exe upload windeployqt --dir upload upload/shadPS4.exe + + - name: Retrieve Git Hash + id: git-hash + shell: cmd + run: | + FOR /F "tokens=*" %%g IN ('git rev-parse --short HEAD') do (SET HASH=%%g) + echo hash=%HASH% >> %GITHUB_OUTPUT% - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-win64-qt + name: shadps4-win64-qt-${{ steps.git-hash.outputs.hash }} path: upload diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 499124863..a2beae629 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -26,9 +26,16 @@ jobs: - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + - name: Retrieve Git Hash + id: git-hash + shell: cmd + run: | + FOR /F "tokens=*" %%g IN ('git rev-parse --short HEAD') do (SET HASH=%%g) + echo hash=%HASH% >> %GITHUB_OUTPUT% + - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-win64-sdl + name: shadps4-win64-sdl-${{ steps.git-hash.outputs.hash }} path: | ${{github.workspace}}/build/Release/shadPS4.exe From ad22e2cfac7165d16ca50abd23c35178eb940952 Mon Sep 17 00:00:00 2001 From: tGecko Date: Sun, 1 Sep 2024 17:24:53 +0200 Subject: [PATCH 140/147] include build date use pwsh instead of cmd on windows workflows --- .github/workflows/linux-qt.yml | 10 ++++++---- .github/workflows/linux.yml | 12 +++++++----- .github/workflows/macos-qt.yml | 11 +++++++---- .github/workflows/macos.yml | 10 ++++++---- .github/workflows/windows-qt.yml | 12 ++++++------ .github/workflows/windows.yml | 12 ++++++------ 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/.github/workflows/linux-qt.yml b/.github/workflows/linux-qt.yml index efafb6e5d..06e048c0e 100644 --- a/.github/workflows/linux-qt.yml +++ b/.github/workflows/linux-qt.yml @@ -34,12 +34,14 @@ jobs: - name: Run AppImage packaging script run: ./.github/linux-appimage-qt.sh - - name: Retrieve Git Hash - id: git-hash - run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Get date and git hash + id: vars + run: | + echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-linux-qt-${{ steps.git-hash.outputs.hash }} + name: shadps4-linux-qt-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: Shadps4-qt.AppImage \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 081e3259d..ee1340984 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -31,14 +31,16 @@ jobs: - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - - name: Retrieve Git Hash - id: git-hash - run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Get date and git hash + id: vars + run: | + echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-ubuntu64-${{ steps.git-hash.outputs.hash }} + name: shadps4-ubuntu64-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: | ${{github.workspace}}/build/shadps4 @@ -48,5 +50,5 @@ jobs: - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-sdl-appimage-${{ steps.git-hash.outputs.hash }} + name: shadps4-sdl-appimage-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: Shadps4-sdl.AppImage diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml index 2b94c7b0c..f04d3091c 100644 --- a/.github/workflows/macos-qt.yml +++ b/.github/workflows/macos-qt.yml @@ -53,12 +53,15 @@ jobs: macdeployqt upload/shadps4.app tar cf shadps4-macos-qt.tar.gz -C upload . - - name: Retrieve Git Hash - id: git-hash - run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Get date and git hash + id: vars + run: | + echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-macos-qt-${{ steps.git-hash.outputs.hash }} + name: shadps4-macos-qt-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: shadps4-macos-qt.tar.gz diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 451b06e81..0eb0ad17a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -45,12 +45,14 @@ jobs: install_name_tool -add_rpath "@loader_path" upload/shadps4 tar cf shadps4-macos-sdl.tar.gz -C upload . - - name: Retrieve Git Hash - id: git-hash - run: echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Get date and git hash + id: vars + run: | + echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-macos-sdl-${{ steps.git-hash.outputs.hash }} + name: shadps4-macos-sdl-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: shadps4-macos-sdl.tar.gz diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml index 8b5430050..83b1a908b 100644 --- a/.github/workflows/windows-qt.yml +++ b/.github/workflows/windows-qt.yml @@ -42,15 +42,15 @@ jobs: move build/Release/shadPS4.exe upload windeployqt --dir upload upload/shadPS4.exe - - name: Retrieve Git Hash - id: git-hash - shell: cmd + - name: Get date and git hash + id: vars + shell: pwsh run: | - FOR /F "tokens=*" %%g IN ('git rev-parse --short HEAD') do (SET HASH=%%g) - echo hash=%HASH% >> %GITHUB_OUTPUT% + echo "date=$(Get-Date -Format 'yyyy-MM-dd')" >> $env:GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $env:GITHUB_OUTPUT - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-win64-qt-${{ steps.git-hash.outputs.hash }} + name: shadps4-win64-qt-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: upload diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a2beae629..413277927 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -26,16 +26,16 @@ jobs: - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - - name: Retrieve Git Hash - id: git-hash - shell: cmd + - name: Get date and git hash + id: vars + shell: pwsh run: | - FOR /F "tokens=*" %%g IN ('git rev-parse --short HEAD') do (SET HASH=%%g) - echo hash=%HASH% >> %GITHUB_OUTPUT% + echo "date=$(Get-Date -Format 'yyyy-MM-dd')" >> $env:GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $env:GITHUB_OUTPUT - name: Upload executable uses: actions/upload-artifact@v4 with: - name: shadps4-win64-sdl-${{ steps.git-hash.outputs.hash }} + name: shadps4-win64-sdl-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }} path: | ${{github.workspace}}/build/Release/shadPS4.exe From 450c825873b493e8bfe87f22e7721b7c56af1a32 Mon Sep 17 00:00:00 2001 From: Marcin Mitura Date: Sun, 1 Sep 2024 19:18:59 +0200 Subject: [PATCH 141/147] Correct machine translations --- src/qt_gui/translations/pl_PL.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index ac4a75dd3..deaab42fb 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -93,7 +93,7 @@ Cheats / Patches - Kody / Łatki + Kody / poprawki @@ -251,12 +251,12 @@ Game Install Directory - Katalog zainstalowanej gry + Katalog zainstalowanych gry Download Cheats/Patches - Pobierz Kody / Łatki + Pobierz kody / poprawki @@ -349,7 +349,7 @@ Open Folder - Open Folder + Otwórz folder @@ -450,7 +450,7 @@ Vblank Divider - Dzielnik pionowego blankingu (Vblank) + Dzielnik przerwy pionowej (Vblank) @@ -563,7 +563,7 @@ PKG Extraction - Ekstrakcja PKG + Wypakowywanie PKG @@ -628,12 +628,12 @@ Extracting PKG %1/%2 - Ekstrakcja PKG %1/%2 + Wypakowywanie PKG %1/%2 Extraction Finished - Ekstrakcja zakończona + Wypakowywanie zakończone @@ -651,7 +651,7 @@ Cheats / Patches - Kody / Poprawki + Kody / poprawki @@ -771,7 +771,7 @@ Failed to parse XML: - Nie udało się sparsować XML: + Nie udało się przeanalizować XML: @@ -856,7 +856,7 @@ Failed to parse JSON data from HTML. - Nie udało się sparsować danych JSON z HTML. + Nie udało się przeanalizować danych JSON z HTML. @@ -896,7 +896,7 @@ Failed to parse JSON: - Nie udało się sparsować JSON: + Nie udało się przeanlizować JSON: From 0276ed92a64d6476d3e1f61b66877754cc1829d8 Mon Sep 17 00:00:00 2001 From: Random <28494085+Random06457@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:48:34 +0200 Subject: [PATCH 142/147] Force PIE usage on linux (#625) * force PIE usage on linux * get rid of explicit -pie linker flag * change UNIX with UNIX AND NOT APPLE in CMakeLists.txt * cmake: add proper check for PIE support at link time --------- Co-authored-by: Mikhail Paulyshka --- CMakeLists.txt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5331a7ef..6c40f0a8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,18 @@ endif() project(shadPS4) +# Forcing PIE makes sure that the base address is high enough so that it doesn't clash with the PS4 memory. +if(UNIX AND NOT APPLE) + set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) + + # check PIE support at link time + include(CheckPIESupported) + check_pie_supported(OUTPUT_VARIABLE pie_check LANGUAGES C CXX) + if(NOT CMAKE_C_LINK_PIE_SUPPORTED OR NOT CMAKE_CXX_LINK_PIE_SUPPORTED) + message(WARNING "PIE is not supported at link time: ${pie_check}") + endif() +endif() + option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF) # This function should be passed a list of all files in a target. It will automatically generate file groups @@ -151,7 +163,7 @@ set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp src/core/libraries/gnmdriver/gnm_error.h ) -set(KERNEL_LIB +set(KERNEL_LIB src/core/libraries/kernel/event_flag/event_flag.cpp src/core/libraries/kernel/event_flag/event_flag.h src/core/libraries/kernel/event_flag/event_flag_obj.cpp @@ -347,7 +359,7 @@ set(CORE src/core/aerolib/stubs.cpp src/core/cpu_patches.cpp src/core/cpu_patches.h src/core/crypto/crypto.cpp - src/core/crypto/crypto.h + src/core/crypto/crypto.h src/core/crypto/keys.h src/core/file_format/pfs.h src/core/file_format/pkg.cpp @@ -372,7 +384,7 @@ set(CORE src/core/aerolib/stubs.cpp src/core/loader/elf.h src/core/loader/symbols_resolver.h src/core/loader/symbols_resolver.cpp - src/core/libraries/error_codes.h + src/core/libraries/error_codes.h src/core/libraries/libs.h src/core/libraries/libs.cpp ${AUDIO_LIB} From e4d8857eb5a757dae712b98e4a110f964f1eba76 Mon Sep 17 00:00:00 2001 From: Emulator-Team-2 <38318848+Emulator-Team-2@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:49:01 +0200 Subject: [PATCH 143/147] Adding missing data format - (1_5_5_5) (#701) * added data_format=17 and num_format=0 * Set `sceSaveDataDialogIsReadyToDisplay` temporary to 1 until is properly implemented. --- src/core/libraries/system/savedatadialog.cpp | 2 +- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/system/savedatadialog.cpp b/src/core/libraries/system/savedatadialog.cpp index d842fd11a..5aad480d0 100644 --- a/src/core/libraries/system/savedatadialog.cpp +++ b/src/core/libraries/system/savedatadialog.cpp @@ -30,7 +30,7 @@ int PS4_SYSV_ABI sceSaveDataDialogInitialize() { int PS4_SYSV_ABI sceSaveDataDialogIsReadyToDisplay() { LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; + return 1; } int PS4_SYSV_ABI sceSaveDataDialogOpen() { diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 57593e919..358a00447 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -312,6 +312,7 @@ std::span GetAllFormats() { vk::Format::eD32SfloatS8Uint, vk::Format::eR4G4B4A4UnormPack16, vk::Format::eR5G6B5UnormPack16, + vk::Format::eR5G5B5A1UnormPack16, vk::Format::eR8G8B8A8Srgb, vk::Format::eR8G8B8A8Uint, vk::Format::eR8G8B8A8Unorm, @@ -386,6 +387,10 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eB5G6R5UnormPack16; } + if (data_format == AmdGpu::DataFormat::Format1_5_5_5 && + num_format == AmdGpu::NumberFormat::Unorm) { + return vk::Format::eR5G5B5A1UnormPack16; + } if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eR8Unorm; } From 1bd9317509aff59a67810b86cdcf89d1918b35a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Hage?= <33609333+greggameplayer@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:49:42 +0200 Subject: [PATCH 144/147] Implement V_READFIRSTLANE_B32 (#681) * Implement V_READFIRSTLANE_B32 * refactor --- .../backend/spirv/emit_spirv_warp.cpp | 2 +- .../frontend/translate/data_share.cpp | 10 ++++++++-- src/shader_recompiler/ir/opcodes.inc | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index c55763c5d..898de8b57 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp @@ -23,7 +23,7 @@ Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index) { } Id EmitReadFirstLane(EmitContext& ctx, Id value) { - UNREACHABLE(); + return ctx.OpGroupNonUniformBroadcastFirst(ctx.U32[1], SubgroupScope(ctx), value); } Id EmitReadLane(EmitContext& ctx, Id value, u32 lane) { diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index aa9b49b63..7c23c7284 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -167,8 +167,14 @@ void Translator::S_BARRIER() { } void Translator::V_READFIRSTLANE_B32(const GcnInst& inst) { - ASSERT(info.stage != Stage::Compute); - SetDst(inst.dst[0], GetSrc(inst.src[0])); + const IR::ScalarReg dst{inst.dst[0].code}; + const IR::U32 value{GetSrc(inst.src[0])}; + + if (info.stage != Stage::Compute) { + ir.SetScalarReg(dst, value); + } else { + ir.SetScalarReg(dst, ir.ReadFirstLane(value)); + } } void Translator::V_READLANE_B32(const GcnInst& inst) { diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 1e33d6d45..40dcfa441 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -340,6 +340,6 @@ OPCODE(ImageAtomicExchange32, U32, Opaq OPCODE(LaneId, U32, ) OPCODE(WarpId, U32, ) OPCODE(QuadShuffle, U32, U32, U32 ) -OPCODE(ReadFirstLane, U32, U32, U32 ) +OPCODE(ReadFirstLane, U32, U32, ) OPCODE(ReadLane, U32, U32, U32 ) OPCODE(WriteLane, U32, U32, U32, U32 ) From f514fdfd1891506fd179bb94aa0b656713f5bbc0 Mon Sep 17 00:00:00 2001 From: Paris Oplopoios Date: Sun, 1 Sep 2024 22:20:22 +0300 Subject: [PATCH 145/147] Replace recursive_mutex with mutex (#708) * Replace recursive_mutex with mutex * Move mutex lock outside of ObtainBuffer --- src/core/memory.cpp | 7 +++++-- src/core/memory.h | 4 +++- src/video_core/buffer_cache/buffer_cache.cpp | 2 +- src/video_core/buffer_cache/buffer_cache.h | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2722c68a9..b7b4aebe1 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -101,7 +101,7 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) { } } for (const auto& [addr, size] : remove_list) { - UnmapMemory(addr, size); + UnmapMemoryImpl(addr, size); } // Mark region as free and attempt to coalesce it with neighbours. @@ -124,7 +124,7 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem const auto& vma = FindVMA(mapped_addr)->second; // If the VMA is mapped, unmap the region first. if (vma.IsMapped()) { - UnmapMemory(mapped_addr, size); + UnmapMemoryImpl(mapped_addr, size); } const size_t remaining_size = vma.base + vma.size - mapped_addr; ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size); @@ -233,7 +233,10 @@ int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, Mem void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { std::scoped_lock lk{mutex}; + UnmapMemoryImpl(virtual_addr, size); +} +void MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) { const auto it = FindVMA(virtual_addr); const auto& vma_base = it->second; ASSERT_MSG(vma_base.Contains(virtual_addr, size), diff --git a/src/core/memory.h b/src/core/memory.h index c8638626a..b7edee33a 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -214,11 +214,13 @@ private: DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area); + void UnmapMemoryImpl(VAddr virtual_addr, size_t size); + private: AddressSpace impl; DMemMap dmem_map; VMAMap vma_map; - std::recursive_mutex mutex; + std::mutex mutex; size_t total_direct_size{}; size_t total_flexible_size{}; size_t flexible_usage{}; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 0151f2c13..71228786e 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -230,7 +230,6 @@ u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, bool is_written, bool is_texel_buffer) { - std::scoped_lock lk{mutex}; static constexpr u64 StreamThreshold = CACHING_PAGESIZE; const bool is_gpu_dirty = memory_tracker.IsRegionGpuModified(device_addr, size); if (!is_written && !is_texel_buffer && size <= StreamThreshold && !is_gpu_dirty) { @@ -461,6 +460,7 @@ void BufferCache::ChangeRegister(BufferId buffer_id) { } bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size) { + std::scoped_lock lk{mutex}; boost::container::small_vector copies; u64 total_size_bytes = 0; u64 largest_copy = 0; diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index a07470b8e..b9002cea2 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -126,7 +126,7 @@ private: PageManager& tracker; StreamBuffer staging_buffer; StreamBuffer stream_buffer; - std::recursive_mutex mutex; + std::mutex mutex; Common::SlotVector slot_buffers; MemoryTracker memory_tracker; PageTable page_table; From 101aeb920dd2a20c0f0997853984a20e46c3ab57 Mon Sep 17 00:00:00 2001 From: baggins183 Date: Sun, 1 Sep 2024 12:20:42 -0700 Subject: [PATCH 146/147] Implement V_BFM_B32 and V_FFBH_U32 (#663) * Implement V_BFM_B32 * Render.Recompiler: Implement V_FFBH_U32 * fix clang-format --- .../frontend/translate/translate.h | 2 ++ .../frontend/translate/vector_alu.cpp | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 8d418421c..f1619e810 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -189,6 +189,8 @@ public: void V_CMP_CLASS_F32(const GcnInst& inst); void V_FFBL_B32(const GcnInst& inst); void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst); + void V_BFM_B32(const GcnInst& inst); + void V_FFBH_U32(const GcnInst& inst); // Vector Memory void BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 13a8342d3..7fef91377 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -311,6 +311,11 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_MBCNT_U32_B32(false, inst); case Opcode::V_NOP: return; + + case Opcode::V_BFM_B32: + return V_BFM_B32(inst); + case Opcode::V_FFBH_U32: + return V_FFBH_U32(inst); default: LogMissingOpcode(inst); } @@ -964,4 +969,24 @@ void Translator::V_MBCNT_U32_B32(bool is_low, const GcnInst& inst) { SetDst(inst.dst[0], ir.LaneId()); } +void Translator::V_BFM_B32(const GcnInst& inst) { + // bitmask width + const IR::U32 src0{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(4))}; + // bitmask offset + const IR::U32 src1{ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(4))}; + const IR::U32 ones = ir.ISub(ir.ShiftLeftLogical(ir.Imm32(1), src0), ir.Imm32(1)); + SetDst(inst.dst[0], ir.ShiftLeftLogical(ones, src1)); +} + +void Translator::V_FFBH_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) + // position + const IR::U32 msb_pos = ir.FindUMsb(src0); + const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); + // Select 0xFFFFFFFF if src0 was 0 + const IR::U1 cond = ir.INotEqual(src0, ir.Imm32(0)); + SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); +} + } // namespace Shader::Gcn From f3a62891ed83b6c1beb306eda4af57fc819b225e Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Sun, 1 Sep 2024 22:39:22 -0500 Subject: [PATCH 147/147] Fix VirtualQuery Found this issue while looking at code from fpPS4. VirtualQuery was setting is_commited to true when the queried region was reserved. Also sets the protection value in the VirtualQueryInfo, as I'd assume not storing that could cause issues in games. This fixes all games currently hanging on the sceKernelmprotect stub. --- src/core/memory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2722c68a9..0ee8e4498 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -305,9 +305,10 @@ int MemoryManager::VirtualQuery(VAddr addr, int flags, const auto& vma = it->second; info->start = vma.base; info->end = vma.base + vma.size; + info->protection = static_cast(vma.prot); info->is_flexible.Assign(vma.type == VMAType::Flexible); info->is_direct.Assign(vma.type == VMAType::Direct); - info->is_commited.Assign(vma.type != VMAType::Free); + info->is_commited.Assign(vma.type != VMAType::Free && vma.type != VMAType::Reserved); vma.name.copy(info->name.data(), std::min(info->name.size(), vma.name.size())); if (vma.type == VMAType::Direct) { const auto dmem_it = FindDmemArea(vma.phys_base);