diff --git a/.github/ISSUE_TEMPLATE/app-bug-report.yaml b/.github/ISSUE_TEMPLATE/app-bug-report.yaml new file mode 100644 index 000000000..cd540e06e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/app-bug-report.yaml @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later +# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema +name: Application Bug Report +description: Problem with the application itself (ie. bad file path handling, UX issue) +title: "[APP BUG]: " +body: + - type: markdown + attributes: + value: | + ## Important: Read First + + **Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only. + If you have a support request or are unsure about the nature of your issue please contact us on [discord](https://discord.gg/bFJxfftGW6).** + + Please make an effort to make sure your issue isn't already reported. + + Do not create issues involving software piracy, our rules specifically prohibit this. Otherwise your issue will be closed and you will be banned in this repository. + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: I have searched for a similar issue in this repository and did not find one. + required: true + - label: I am using an official build obtained from [releases](https://github.com/shadps4-emu/shadPS4/releases) or updated one of those builds using its in-app updater. + required: true + - type: textarea + id: desc + attributes: + label: Describe the Bug + description: "A clear and concise description of what the bug is" + validations: + required: true + - type: textarea + id: repro + attributes: + label: Reproduction Steps + description: "Detailed steps to reproduce the behavior" + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: "A clear and concise description of what you expected to happen" + validations: + required: false + - type: input + id: os + attributes: + label: Specify OS Version + placeholder: "Example: Windows 11, Arch Linux, MacOS 15" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..5adcf1437 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later +blank_issues_enabled: false +contact_links: + - name: Discord + url: https://discord.gg/bFJxfftGW6 + about: Get direct support and hang out with us + - name: Wiki + url: https://github.com/shadps4-emu/shadPS4/wiki + about: Information, guides, etc. diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml new file mode 100644 index 000000000..a1b49362a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later +# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema +name: Feature Request +description: Suggest a new feature or improve an existing one +title: "[Feature Request]: " +body: + - type: markdown + attributes: + value: | + ## Important: Read First + + Please make an effort to make sure your issue isn't already reported. + + Do not create issues involving software piracy, our rules specifically prohibit this. Otherwise your issue will be closed and you will be banned in this repository. + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: I have searched for a similar issue in this repository and did not find one. + required: true + - type: textarea + id: desc + attributes: + label: Description + description: | + A concise description of the feature you want + + Include step by step examples of how the feature should work under various circumstances + validations: + required: true + - type: textarea + id: reason + attributes: + label: Reason + description: | + Give a reason why you want this feature + - How will it make things easier for you? + - How does this feature help your enjoyment of the emulator? + - What does it provide that isn't being provided currently? + validations: + required: true + - type: textarea + id: examples + attributes: + label: Examples + description: | + Provide examples of the feature as implemented by other software + + Include screenshots or video if you like to help demonstrate how you'd like this feature to work + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/game-bug-report.yaml b/.github/ISSUE_TEMPLATE/game-bug-report.yaml new file mode 100644 index 000000000..a9c669ff9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/game-bug-report.yaml @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later +# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema +name: Game Emulation Bug Report +description: Problem in a game (ie. graphical artifacts, crashes, etc.) +title: "[GAME BUG]: " +body: + - type: markdown + attributes: + value: | + ## Important: Read First + + **Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only. + If you have a support request or are unsure about the nature of your issue please contact us on [discord](https://discord.gg/bFJxfftGW6).** + + This repository does not provide support for modded games. You should perform and test a clean game installation before submitting an issue. + + This repository does not provide support for game patches. If you are having issues with patches please refer to [Cheats and Patches Repository](https://github.com/shadps4-emu/ps4_cheats). + + Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-emu/shadps4-game-compatibility) for the information about the status of the game. + + Please make an effort to make sure your issue isn't already reported. + + Do not create issues involving software piracy, our rules specifically prohibit this. Otherwise your issue will be closed and you will be banned in this repository. + - type: checkboxes + id: checklist + attributes: + label: Checklist (we expect you to perform these steps before opening the issue) + options: + - label: I have searched for a similar issue in this repository and did not find one. + required: true + - label: I am using an official build obtained from [releases](https://github.com/shadps4-emu/shadPS4/releases) or updated one of those builds using its in-app updater. + required: true + - label: I have re-dumped the game and performed a clean install without mods and the issue is still present. + required: true + - label: I have disabled all patches and cheats and the issue is still present. + required: true + - label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) installed. + required: true + - type: textarea + id: desc + attributes: + label: Describe the Bug + description: "A clear and concise description of what the bug is" + validations: + required: true + - type: textarea + id: repro + attributes: + label: Reproduction Steps + description: "Detailed steps to reproduce the behavior" + validations: + required: true + - type: input + id: os + attributes: + label: Specify OS Version + placeholder: "Example: Windows 11, Arch Linux, MacOS 15" + validations: + required: true + - type: input + id: cpu + attributes: + label: CPU + placeholder: "Example: Intel Core i7-8700" + validations: + required: true + - type: input + id: gpu + attributes: + label: GPU + placeholder: "Example: nVidia GTX 1650" + validations: + required: true + - type: input + id: ram + attributes: + label: Amount of RAM in GB + placeholder: "Example: 16 GB" + validations: + required: true + - type: input + id: vram + attributes: + label: Amount of VRAM in GB + placeholder: "Example: 8 GB" + validations: + required: true + - type: textarea + id: logs + attributes: + label: "Log File" + description: Drag and drop the log file here. It can be found by right clicking on a game name -> Open Folder... -> Open Log Folder. Make sure that the log type is set to `sync`. + validations: + required: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b5690438..c36c026fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,14 +14,14 @@ env: jobs: reuse: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 continue-on-error: true steps: - uses: actions/checkout@v4 - uses: fsfe/reuse-action@v5 clang-format: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 continue-on-error: true steps: - uses: actions/checkout@v4 @@ -39,7 +39,7 @@ jobs: run: ./.ci/clang-format.sh get-info: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: date: ${{ steps.vars.outputs.date }} shorthash: ${{ steps.vars.outputs.shorthash }} @@ -57,7 +57,7 @@ jobs: echo "fullhash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT windows-sdl: - runs-on: windows-latest + runs-on: windows-2025 needs: get-info steps: - uses: actions/checkout@v4 @@ -101,7 +101,7 @@ jobs: path: ${{github.workspace}}/build/shadPS4.exe windows-qt: - runs-on: windows-latest + runs-on: windows-2025 needs: get-info steps: - uses: actions/checkout@v4 @@ -376,6 +376,78 @@ jobs: name: shadps4-linux-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} path: Shadps4-qt.AppImage + linux-sdl-gcc: + runs-on: ubuntu-24.04 + needs: get-info + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install dependencies + run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev + + - name: Cache CMake Configuration + uses: actions/cache@v4 + env: + cache-name: ${{ runner.os }}-sdl-cache-cmake-configuration + with: + path: | + ${{github.workspace}}/build + key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + restore-keys: | + ${{ env.cache-name }}- + + - name: Cache CMake Build + uses: hendrikmuhs/ccache-action@v1.2.14 + env: + cache-name: ${{ runner.os }}-sdl-cache-cmake-build + with: + append-timestamp: false + key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + + - name: Configure CMake + run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc) + + linux-qt-gcc: + runs-on: ubuntu-24.04 + needs: get-info + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install dependencies + run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev + + - name: Cache CMake Configuration + uses: actions/cache@v4 + env: + cache-name: ${{ runner.os }}-qt-cache-cmake-configuration + with: + path: | + ${{github.workspace}}/build + key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + restore-keys: | + ${{ env.cache-name }}- + + - name: Cache CMake Build + uses: hendrikmuhs/ccache-action@v1.2.14 + env: + cache-name: ${{ runner.os }}-qt-cache-cmake-build + with: + append-timestamp: false + key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + + - name: Configure CMake + run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc) + pre-release: if: github.ref == 'refs/heads/main' && github.repository == 'shadps4-emu/shadPS4' && github.event_name == 'push' needs: [get-info, windows-sdl, windows-qt, macos-sdl, macos-qt, linux-sdl, linux-qt] diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bc3a3c16..cad5407de 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,7 +106,7 @@ git_describe(GIT_DESC --always --long --dirty) git_branch_name(GIT_BRANCH) string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S") -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY) find_package(Boost 1.84.0 CONFIG) find_package(FFmpeg 5.1.2 MODULE) @@ -188,6 +188,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp src/core/libraries/ajm/ajm_context.cpp src/core/libraries/ajm/ajm_context.h src/core/libraries/ajm/ajm_error.h + src/core/libraries/ajm/ajm_instance_statistics.cpp + src/core/libraries/ajm/ajm_instance_statistics.h src/core/libraries/ajm/ajm_instance.cpp src/core/libraries/ajm/ajm_instance.h src/core/libraries/ajm/ajm_mp3.cpp @@ -198,15 +200,16 @@ set(AUDIO_LIB src/core/libraries/audio/audioin.cpp src/core/libraries/audio/audioin.h src/core/libraries/audio/audioout.cpp src/core/libraries/audio/audioout.h - src/core/libraries/audio/sdl_audio.cpp - src/core/libraries/audio/sdl_audio.h + src/core/libraries/audio/audioout_backend.h src/core/libraries/audio/audioout_error.h + src/core/libraries/audio/sdl_audio.cpp src/core/libraries/ngs2/ngs2.cpp src/core/libraries/ngs2/ngs2.h ) set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp src/core/libraries/gnmdriver/gnmdriver.h + src/core/libraries/gnmdriver/gnmdriver_init.h src/core/libraries/gnmdriver/gnm_error.h ) @@ -333,6 +336,8 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/share_play/shareplay.h src/core/libraries/razor_cpu/razor_cpu.cpp src/core/libraries/razor_cpu/razor_cpu.h + src/core/libraries/mouse/mouse.cpp + src/core/libraries/mouse/mouse.h ) set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h @@ -423,6 +428,8 @@ set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp src/core/libraries/screenshot/screenshot.h + src/core/libraries/move/move.cpp + src/core/libraries/move/move.h ) set(DEV_TOOLS src/core/devtools/layer.cpp @@ -517,7 +524,7 @@ set(COMMON src/common/logging/backend.cpp src/common/number_utils.cpp src/common/memory_patcher.h src/common/memory_patcher.cpp - src/common/scm_rev.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp src/common/scm_rev.h ) @@ -694,6 +701,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/ir/post_order.h src/shader_recompiler/ir/program.cpp src/shader_recompiler/ir/program.h + src/shader_recompiler/ir/reinterpret.h src/shader_recompiler/ir/reg.h src/shader_recompiler/ir/type.cpp src/shader_recompiler/ir/type.h @@ -907,11 +915,19 @@ endif() if (APPLE) if (ENABLE_QT_GUI) # Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. - target_sources(shadps4 PRIVATE externals/MoltenVK/MoltenVK_icd.json) - set_source_files_properties(externals/MoltenVK/MoltenVK_icd.json - PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d) - add_custom_command(TARGET shadps4 POST_BUILD - COMMAND cmake -E copy $ $/Contents/Frameworks/libMoltenVK.dylib) + set(MVK_ICD ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK_icd.json) + target_sources(shadps4 PRIVATE ${MVK_ICD}) + set_source_files_properties(${MVK_ICD} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d) + + set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) + set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) + add_custom_command( + OUTPUT ${MVK_DYLIB_DST} + DEPENDS ${MVK_DYLIB_SRC} + COMMAND cmake -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) + add_custom_target(CopyMoltenVK DEPENDS ${MVK_DYLIB_DST}) + add_dependencies(CopyMoltenVK MoltenVK) + add_dependencies(shadps4 CopyMoltenVK) set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") else() # For non-bundled SDL build, just do a normal library link. @@ -1032,7 +1048,6 @@ install(TARGETS shadps4 BUNDLE DESTINATION .) if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux") install(FILES "dist/net.shadps4.shadPS4.desktop" DESTINATION "share/applications") - install(FILES "dist/net.shadps4.shadPS4.releases.xml" DESTINATION "share/metainfo/releases") install(FILES "dist/net.shadps4.shadPS4.metainfo.xml" DESTINATION "share/metainfo") install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png") install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps") diff --git a/README.md b/README.md index 8072a5652..7c3657065 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,11 @@ Keyboard and mouse inputs can be customized in the settings menu by clicking the - [**skmp**](https://github.com/skmp) - [**wheremyfoodat**](https://github.com/wheremyfoodat) - [**raziel1000**](https://github.com/raziel1000) +- [**viniciuslrangel**](https://github.com/viniciuslrangel) +- [**roamic**](https://github.com/vladmikhalin) +- [**poly**](https://github.com/polybiusproxy) +- [**squidbus**](https://github.com/squidbus) +- [**frodo**](https://github.com/baggins183) Logo is done by [**Xphalnos**](https://github.com/Xphalnos) diff --git a/REUSE.toml b/REUSE.toml index cba63adf1..55d76673d 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -11,7 +11,6 @@ path = [ "dist/net.shadps4.shadPS4.desktop", "dist/net.shadps4.shadPS4_metadata.pot", "dist/net.shadps4.shadPS4.metainfo.xml", - "dist/net.shadps4.shadPS4.releases.xml", "documents/changelog.md", "documents/Quickstart/2.png", "documents/Screenshots/*", diff --git a/dist/net.shadps4.shadPS4.metainfo.xml b/dist/net.shadps4.shadPS4.metainfo.xml index bef0bec4c..384cf75e8 100644 --- a/dist/net.shadps4.shadPS4.metainfo.xml +++ b/dist/net.shadps4.shadPS4.metainfo.xml @@ -36,9 +36,30 @@ Game - - - + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.5.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.4.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.3.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.2.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/0.1.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.3 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.2 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.1 diff --git a/dist/net.shadps4.shadPS4.releases.xml b/dist/net.shadps4.shadPS4.releases.xml deleted file mode 100644 index 8da203fe4..000000000 --- a/dist/net.shadps4.shadPS4.releases.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.4.0 - - - https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.3.0 - - - https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.2.0 - - - https://github.com/shadps4-emu/shadPS4/releases/tag/0.1.0 - - - https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.3 - - - https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.2 - - - https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.1 - - diff --git a/documents/building-windows.md b/documents/building-windows.md index 0d523692e..845cdd10f 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -64,7 +64,7 @@ Go through the Git for Windows installation as normal 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.3\msvc2022_64\bin\windeployqt.exe "C:\path\to\shadps4.exe"` +`C:\Qt\6.7.3\msvc2022_64\bin\windeployqt6.exe "C:\path\to\shadps4.exe"` (Change Qt path if you've installed it to non-default path) ## Option 2: MSYS2/MinGW diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 4350948b7..4ce5636d8 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -213,9 +213,7 @@ endif() # Discord RPC if (ENABLE_DISCORD_RPC) - set(BUILD_EXAMPLES OFF) add_subdirectory(discord-rpc) - target_include_directories(discord-rpc INTERFACE discord-rpc/include) endif() # GCN Headers diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 5ad3ee5d2..9f0b616d9 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 5ad3ee5d2f84342950c3fe93dec97719574d1932 +Subproject commit 9f0b616d9e2c39464d2a859b79dbc655c4a30e7e diff --git a/externals/discord-rpc b/externals/discord-rpc index 4ec218155..51b09d426 160000 --- a/externals/discord-rpc +++ b/externals/discord-rpc @@ -1 +1 @@ -Subproject commit 4ec218155d73bcb8022f8f7ca72305d801f84beb +Subproject commit 51b09d426a4a1bcfa6ee6d4894e57d669f4a2e65 diff --git a/externals/sirit b/externals/sirit index 1e74f4ef8..26ad5a9d0 160000 --- a/externals/sirit +++ b/externals/sirit @@ -1 +1 @@ -Subproject commit 1e74f4ef8d2a0e3221a4de51977663f342b53c35 +Subproject commit 26ad5a9d0fe13260b0d7d6c64419d01a196b2e32 diff --git a/src/common/config.cpp b/src/common/config.cpp index eca9682ce..ea46a5492 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -33,6 +33,7 @@ namespace Config { static bool isNeo = false; static bool isFullscreen = false; +static std::string fullscreenMode = "borderless"; static bool playBGM = false; static bool isTrophyPopupDisabled = false; static int BGMvolume = 50; @@ -47,6 +48,7 @@ static std::string updateChannel; static std::string backButtonBehavior = "left"; static bool useSpecialPad = false; static int specialPadClass = 1; +static bool isMotionControlsEnabled = true; static bool isDebugDump = false; static bool isShaderDebug = false; static bool isShowSplash = false; @@ -67,6 +69,7 @@ static int cursorHideTimeout = 5; // 5 seconds (default) static bool separateupdatefolder = false; static bool compatibilityData = false; static bool checkCompatibilityOnStartup = false; +static std::string trophyKey; // Gui std::vector settings_install_dirs = {}; @@ -91,14 +94,26 @@ std::string emulator_language = "en"; // Language u32 m_language = 1; // english -bool isNeoMode() { +std::string getTrophyKey() { + return trophyKey; +} + +void setTrophyKey(std::string key) { + trophyKey = key; +} + +bool isNeoModeConsole() { return isNeo; } -bool isFullscreenMode() { +bool getIsFullscreen() { return isFullscreen; } +std::string getFullscreenMode() { + return fullscreenMode; +} + bool getisTrophyPopupDisabled() { return isTrophyPopupDisabled; } @@ -163,6 +178,10 @@ int getSpecialPadClass() { return specialPadClass; } +bool getIsMotionControlsEnabled() { + return isMotionControlsEnabled; +} + bool debugDump() { return isDebugDump; } @@ -295,10 +314,14 @@ void setVblankDiv(u32 value) { vblankDivider = value; } -void setFullscreenMode(bool enable) { +void setIsFullscreen(bool enable) { isFullscreen = enable; } +void setFullscreenMode(std::string mode) { + fullscreenMode = mode; +} + void setisTrophyPopupDisabled(bool disable) { isTrophyPopupDisabled = disable; } @@ -359,6 +382,10 @@ void setSpecialPadClass(int type) { specialPadClass = type; } +void setIsMotionControlsEnabled(bool use) { + isMotionControlsEnabled = use; +} + void setSeparateUpdateEnabled(bool use) { separateupdatefolder = use; } @@ -557,6 +584,7 @@ void load(const std::filesystem::path& path) { isNeo = toml::find_or(general, "isPS4Pro", false); isFullscreen = toml::find_or(general, "Fullscreen", false); + fullscreenMode = toml::find_or(general, "FullscreenMode", "borderless"); playBGM = toml::find_or(general, "playBGM", false); isTrophyPopupDisabled = toml::find_or(general, "isTrophyPopupDisabled", false); BGMvolume = toml::find_or(general, "BGMvolume", 50); @@ -585,6 +613,7 @@ void load(const std::filesystem::path& path) { backButtonBehavior = toml::find_or(input, "backButtonBehavior", "left"); useSpecialPad = toml::find_or(input, "useSpecialPad", false); specialPadClass = toml::find_or(input, "specialPadClass", 1); + isMotionControlsEnabled = toml::find_or(input, "isMotionControlsEnabled", true); } if (data.contains("GPU")) { @@ -652,6 +681,11 @@ void load(const std::filesystem::path& path) { m_language = toml::find_or(settings, "consoleLanguage", 1); } + + if (data.contains("Keys")) { + const toml::value& keys = data.at("Keys"); + trophyKey = toml::find_or(keys, "TrophyKey", ""); + } } void save(const std::filesystem::path& path) { @@ -677,6 +711,7 @@ void save(const std::filesystem::path& path) { data["General"]["isPS4Pro"] = isNeo; data["General"]["Fullscreen"] = isFullscreen; + data["General"]["FullscreenMode"] = fullscreenMode; data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled; data["General"]["playBGM"] = playBGM; data["General"]["BGMvolume"] = BGMvolume; @@ -695,6 +730,7 @@ void save(const std::filesystem::path& path) { data["Input"]["backButtonBehavior"] = backButtonBehavior; data["Input"]["useSpecialPad"] = useSpecialPad; data["Input"]["specialPadClass"] = specialPadClass; + data["Input"]["isMotionControlsEnabled"] = isMotionControlsEnabled; data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenHeight"] = screenHeight; data["GPU"]["nullGpu"] = isNullGpu; @@ -712,6 +748,8 @@ void save(const std::filesystem::path& path) { data["Debug"]["DebugDump"] = isDebugDump; data["Debug"]["CollectShader"] = isShaderDebug; + data["Keys"]["TrophyKey"] = trophyKey; + std::vector install_dirs; for (const auto& dirString : settings_install_dirs) { install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data}); diff --git a/src/common/config.h b/src/common/config.h index 56750b22d..2a86eaa89 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -15,8 +15,11 @@ void load(const std::filesystem::path& path); void save(const std::filesystem::path& path); void saveMainWindow(const std::filesystem::path& path); -bool isNeoMode(); -bool isFullscreenMode(); +std::string getTrophyKey(); +void setTrophyKey(std::string key); +bool getIsFullscreen(); +std::string getFullscreenMode(); +bool isNeoModeConsole(); bool getPlayBGM(); int getBGMvolume(); bool getisTrophyPopupDisabled(); @@ -35,6 +38,7 @@ int getCursorHideTimeout(); std::string getBackButtonBehavior(); bool getUseSpecialPad(); int getSpecialPadClass(); +bool getIsMotionControlsEnabled(); u32 getScreenWidth(); u32 getScreenHeight(); @@ -62,7 +66,8 @@ void setVblankDiv(u32 value); void setGpuId(s32 selectedGpuId); void setScreenWidth(u32 width); void setScreenHeight(u32 height); -void setFullscreenMode(bool enable); +void setIsFullscreen(bool enable); +void setFullscreenMode(std::string mode); void setisTrophyPopupDisabled(bool disable); void setPlayBGM(bool enable); void setBGMvolume(int volume); @@ -81,6 +86,7 @@ void setCursorHideTimeout(int newcursorHideTimeout); void setBackButtonBehavior(const std::string& type); void setUseSpecialPad(bool use); void setSpecialPadClass(int type); +void setIsMotionControlsEnabled(bool use); void setLogType(const std::string& type); void setLogFilter(const std::string& type); @@ -139,4 +145,4 @@ std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = "") // settings u32 GetLanguage(); -}; // namespace Config \ No newline at end of file +}; // namespace Config diff --git a/src/common/elf_info.h b/src/common/elf_info.h index 5a2c914e0..cb32679bb 100644 --- a/src/common/elf_info.h +++ b/src/common/elf_info.h @@ -7,6 +7,7 @@ #include #include "assert.h" +#include "bit_field.h" #include "singleton.h" #include "types.h" @@ -16,6 +17,46 @@ class Emulator; namespace Common { +union PSFAttributes { + /// Supports initial user's logout + BitField<0, 1, u32> support_initial_user_logout; + /// Enter button for the common dialog is cross. + BitField<1, 1, u32> enter_button_cross; + /// Warning dialog for PS Move is displayed in the options menu. + BitField<2, 1, u32> ps_move_warning; + /// Supports stereoscopic 3D. + BitField<3, 1, u32> support_stereoscopic_3d; + /// Suspends when PS button is pressed. + BitField<4, 1, u32> ps_button_suspend; + /// Enter button for the common dialog is assigned by the system software. + BitField<5, 1, u32> enter_button_system; + /// Overrides share menu behavior. + BitField<6, 1, u32> override_share_menu; + /// Suspends when PS button is pressed and special output resolution is set. + BitField<8, 1, u32> special_res_ps_button_suspend; + /// Enable HDCP. + BitField<9, 1, u32> enable_hdcp; + /// Disable HDCP for non-game. + BitField<10, 1, u32> disable_hdcp_non_game; + /// Supports PS VR. + BitField<14, 1, u32> support_ps_vr; + /// CPU mode (6 CPU) + BitField<15, 1, u32> six_cpu_mode; + /// CPU mode (7 CPU) + BitField<16, 1, u32> seven_cpu_mode; + /// Supports PS4 Pro (Neo) mode. + BitField<23, 1, u32> support_neo_mode; + /// Requires PS VR. + BitField<26, 1, u32> require_ps_vr; + /// Supports HDR. + BitField<29, 1, u32> support_hdr; + /// Display location. + BitField<31, 1, u32> display_location; + + u32 raw{}; +}; +static_assert(sizeof(PSFAttributes) == 4); + class ElfInfo { friend class Core::Emulator; @@ -26,6 +67,7 @@ class ElfInfo { std::string app_ver{}; u32 firmware_ver = 0; u32 raw_firmware_ver = 0; + PSFAttributes psf_attributes{}; public: static constexpr u32 FW_15 = 0x1500000; @@ -34,6 +76,7 @@ public: static constexpr u32 FW_20 = 0x2000000; static constexpr u32 FW_25 = 0x2500000; static constexpr u32 FW_30 = 0x3000000; + static constexpr u32 FW_35 = 0x3500000; static constexpr u32 FW_40 = 0x4000000; static constexpr u32 FW_45 = 0x4500000; static constexpr u32 FW_50 = 0x5000000; @@ -67,6 +110,11 @@ public: ASSERT(initialized); return raw_firmware_ver; } + + [[nodiscard]] const PSFAttributes& GetPSFAttributes() const { + ASSERT(initialized); + return psf_attributes; + } }; } // namespace Common diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 75c61a188..5ee2dce73 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -97,6 +97,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, Http) \ SUB(Lib, Ssl) \ SUB(Lib, SysModule) \ + SUB(Lib, Move) \ SUB(Lib, NpManager) \ SUB(Lib, NpScore) \ SUB(Lib, NpTrophy) \ @@ -125,6 +126,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, Vdec2) \ SUB(Lib, Videodec) \ SUB(Lib, RazorCpu) \ + SUB(Lib, Mouse) \ CLS(Frontend) \ CLS(Render) \ SUB(Render, Vulkan) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index a0e7d021f..6829e2d1b 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -57,8 +57,9 @@ enum class Class : u8 { Lib_MsgDlg, ///< The LibSceMsgDialog implementation. Lib_AudioOut, ///< The LibSceAudioOut implementation. Lib_AudioIn, ///< The LibSceAudioIn implementation. + Lib_Move, ///< The LibSceMove implementation. Lib_Net, ///< The LibSceNet implementation. - Lib_NetCtl, ///< The LibSecNetCtl implementation. + Lib_NetCtl, ///< The LibSceNetCtl implementation. Lib_SaveData, ///< The LibSceSaveData implementation. Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation. Lib_Ssl, ///< The LibSceSsl implementation. @@ -92,6 +93,7 @@ enum class Class : u8 { Lib_Vdec2, ///< The LibSceVideodec2 implementation. Lib_Videodec, ///< The LibSceVideodec implementation. Lib_RazorCpu, ///< The LibRazorCpu implementation. + Lib_Mouse, ///< The LibSceMouse implementation Frontend, ///< Emulator UI Render, ///< Video Core Render_Vulkan, ///< Vulkan backend diff --git a/src/common/native_clock.cpp b/src/common/native_clock.cpp index c3fa637aa..0c05dbe84 100644 --- a/src/common/native_clock.cpp +++ b/src/common/native_clock.cpp @@ -4,11 +4,6 @@ #include "common/native_clock.h" #include "common/rdtsc.h" #include "common/uint128.h" -#ifdef _WIN64 -#include -#else -#include -#endif namespace Common { @@ -34,10 +29,4 @@ u64 NativeClock::GetUptime() const { return FencedRDTSC(); } -u64 NativeClock::GetProcessTimeUS() const { - timespec ret; - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ret); - return ret.tv_nsec / 1000 + ret.tv_sec * 1000000; -} - } // namespace Common diff --git a/src/common/native_clock.h b/src/common/native_clock.h index b5e389452..1542c2f3a 100644 --- a/src/common/native_clock.h +++ b/src/common/native_clock.h @@ -20,7 +20,6 @@ public: u64 GetTimeUS(u64 base_ptc = 0) const; u64 GetTimeMS(u64 base_ptc = 0) const; u64 GetUptime() const; - u64 GetProcessTimeUS() const; private: u64 rdtsc_frequency; diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index 24f5e9f87..2b7331cbd 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -26,7 +26,7 @@ asm(".zerofill GUEST_SYSTEM,GUEST_SYSTEM,__guest_system,0xFBFC00000"); namespace Core { -static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE_PRO; +static constexpr size_t BackingSize = SCE_KERNEL_TOTAL_MEM_PRO; #ifdef _WIN32 diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp index aa1c96724..4020edfd8 100644 --- a/src/core/crypto/crypto.cpp +++ b/src/core/crypto/crypto.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "crypto.h" CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() { @@ -137,20 +138,20 @@ void Crypto::aesCbcCfb128DecryptEntry(std::span ivkey, } } -void Crypto::decryptEFSM(std::span NPcommID, +void Crypto::decryptEFSM(std::span trophyKey, + std::span NPcommID, std::span efsmIv, std::span ciphertext, std::span decrypted) { - std::vector TrophyKey = {0x21, 0xF4, 0x1A, 0x6B, 0xAD, 0x8A, 0x1D, 0x3E, - 0xCA, 0x7A, 0xD5, 0x86, 0xC1, 0x01, 0xB7, 0xA9}; - std::vector TrophyIV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // step 1: Encrypt NPcommID CryptoPP::CBC_Mode::Encryption encrypt; - encrypt.SetKeyWithIV(TrophyKey.data(), TrophyKey.size(), TrophyIV.data()); + std::vector trophyIv(16, 0); std::vector trpKey(16); + encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data()); encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16); + // step 2: decrypt efsm. CryptoPP::CBC_Mode::Decryption decrypt; decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data()); diff --git a/src/core/crypto/crypto.h b/src/core/crypto/crypto.h index 83249bd7d..b5d8104b5 100644 --- a/src/core/crypto/crypto.h +++ b/src/core/crypto/crypto.h @@ -32,7 +32,8 @@ public: void aesCbcCfb128DecryptEntry(std::span ivkey, std::span ciphertext, std::span decrypted); - void decryptEFSM(std::span, std::span efsmIv, + void decryptEFSM(std::span trophyKey, + std::span NPcommID, std::span efsmIv, std::span ciphertext, std::span decrypted); void PfsGenCryptoKey(std::span ekpfs, std::span seed, diff --git a/src/core/debug_state.cpp b/src/core/debug_state.cpp index daf614bd9..6508a9875 100644 --- a/src/core/debug_state.cpp +++ b/src/core/debug_state.cpp @@ -11,6 +11,7 @@ #include "libraries/kernel/time.h" #include "libraries/system/msgdialog.h" #include "video_core/amdgpu/pm4_cmds.h" +#include "video_core/renderer_vulkan/vk_pipeline_cache.h" using namespace DebugStateType; @@ -168,8 +169,12 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, if ((*dump)->regs.stage_enable.IsStageEnabled(i)) { auto stage = (*dump)->regs.ProgramForStage(i); if (stage->address_lo != 0) { + const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(stage->Address()); auto code = stage->Code(); (*dump)->stages[i] = PipelineShaderProgramDump{ + .name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i), + info.shader_hash), + .hash = info.shader_hash, .user_data = *stage, .code = std::vector{code.begin(), code.end()}, }; @@ -191,7 +196,10 @@ void DebugStateImpl::PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_a auto& cs = (*dump)->regs.cs_program; cs = cs_state; + const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(cs.Address()); (*dump)->cs_data = PipelineComputerProgramDump{ + .name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, info.shader_hash), + .hash = info.shader_hash, .cs_program = cs, .code = std::vector{cs.Code().begin(), cs.Code().end()}, }; diff --git a/src/core/debug_state.h b/src/core/debug_state.h index a0e428b6b..6a8e15baa 100644 --- a/src/core/debug_state.h +++ b/src/core/debug_state.h @@ -50,11 +50,15 @@ struct QueueDump { }; struct PipelineShaderProgramDump { + std::string name; + u64 hash; Vulkan::Liverpool::ShaderProgram user_data{}; std::vector code{}; }; struct PipelineComputerProgramDump { + std::string name; + u64 hash; Vulkan::Liverpool::ComputeProgram cs_program{}; std::vector code{}; }; diff --git a/src/core/devtools/widget/cmd_list.cpp b/src/core/devtools/widget/cmd_list.cpp index 7c550cf2e..dc3eb9cdd 100644 --- a/src/core/devtools/widget/cmd_list.cpp +++ b/src/core/devtools/widget/cmd_list.cpp @@ -1174,7 +1174,7 @@ CmdListViewer::CmdListViewer(DebugStateType::FrameDump* _frame_dump, } } -void CmdListViewer::Draw(bool only_batches_view) { +void CmdListViewer::Draw(bool only_batches_view, CmdListFilter& filter) { const auto& ctx = *GetCurrentContext(); if (batch_view.open) { @@ -1285,6 +1285,41 @@ void CmdListViewer::Draw(bool only_batches_view) { } auto& batch = std::get(event); + + // filtering + { + bool remove = false; + + if (filter.shader_name[0] != '\0') { + remove = true; + std::string_view shader_name{filter.shader_name}; + const auto& data = frame_dump->regs.find(batch.command_addr); + if (data != frame_dump->regs.end()) { + DebugStateType::RegDump& dump = data->second; + if (dump.is_compute) { + if (dump.cs_data.name.contains(shader_name)) { + remove = false; + break; + } + } else { + for (int i = 0; i < DebugStateType::RegDump::MaxShaderStages; ++i) { + if (dump.regs.stage_enable.IsStageEnabled(i)) { + auto& stage = dump.stages[i]; + if (stage.name.contains(shader_name)) { + remove = false; + break; + } + } + } + } + } + } + + if (remove) { + continue; + } + } + auto const* pm4_hdr = reinterpret_cast(cmdb_addr + batch.start_addr); diff --git a/src/core/devtools/widget/cmd_list.h b/src/core/devtools/widget/cmd_list.h index ed71d0b76..e2c61f6b9 100644 --- a/src/core/devtools/widget/cmd_list.h +++ b/src/core/devtools/widget/cmd_list.h @@ -35,6 +35,10 @@ void ParseDepthControl(u32 value, bool begin_table = true); void ParseEqaa(u32 value, bool begin_table = true); void ParseZInfo(u32 value, bool begin_table = true); +struct CmdListFilter { + char shader_name[128]{}; +}; + class CmdListViewer { DebugStateType::FrameDump* frame_dump; @@ -70,7 +74,7 @@ public: explicit CmdListViewer(DebugStateType::FrameDump* frame_dump, const std::vector& cmd_list, uintptr_t base_addr = 0, std::string name = ""); - void Draw(bool only_batches_view = false); + void Draw(bool only_batches_view, CmdListFilter& filter); }; } // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/common.h b/src/core/devtools/widget/common.h index 75eb55301..4684f6e3b 100644 --- a/src/core/devtools/widget/common.h +++ b/src/core/devtools/widget/common.h @@ -117,7 +117,7 @@ static bool IsDrawCall(AmdGpu::PM4ItOpcode opcode) { inline std::optional exec_cli(const char* cli) { std::array buffer{}; std::string output; - const auto f = popen(cli, "rt"); + const auto f = popen(cli, "r"); if (!f) { pclose(f); return {}; diff --git a/src/core/devtools/widget/frame_dump.cpp b/src/core/devtools/widget/frame_dump.cpp index 055ce1333..646ccb6d6 100644 --- a/src/core/devtools/widget/frame_dump.cpp +++ b/src/core/devtools/widget/frame_dump.cpp @@ -132,6 +132,15 @@ void FrameDumpViewer::Draw() { } } EndDisabled(); + SameLine(); + if (BeginMenu("Filter")) { + + TextUnformatted("Shader name"); + SameLine(); + InputText("##filter_shader", filter.shader_name, sizeof(filter.shader_name)); + + ImGui::EndMenu(); + } TextEx("Submit num"); SameLine(); @@ -187,7 +196,7 @@ void FrameDumpViewer::Draw() { EndGroup(); } if (is_showing && selected_cmd != -1) { - cmd_list_viewer[selected_cmd].Draw(is_collapsed); + cmd_list_viewer[selected_cmd].Draw(is_collapsed, filter); } End(); } diff --git a/src/core/devtools/widget/frame_dump.h b/src/core/devtools/widget/frame_dump.h index cc4fe6381..94075112b 100644 --- a/src/core/devtools/widget/frame_dump.h +++ b/src/core/devtools/widget/frame_dump.h @@ -27,6 +27,8 @@ class FrameDumpViewer { s32 selected_queue_num2; s32 selected_cmd = -1; + CmdListFilter filter; + public: bool is_open = true; diff --git a/src/core/devtools/widget/frame_graph.cpp b/src/core/devtools/widget/frame_graph.cpp index 952f50c34..0e170db38 100644 --- a/src/core/devtools/widget/frame_graph.cpp +++ b/src/core/devtools/widget/frame_graph.cpp @@ -19,6 +19,57 @@ constexpr float BAR_HEIGHT_MULT = 1.25f; constexpr float FRAME_GRAPH_PADDING_Y = 3.0f; constexpr static float FRAME_GRAPH_HEIGHT = 50.0f; +void FrameGraph::DrawFrameGraph() { + // Frame graph - inspired by + // https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times + const float full_width = GetContentRegionAvail().x; + auto pos = GetCursorScreenPos(); + const ImVec2 size{full_width, FRAME_GRAPH_HEIGHT + FRAME_GRAPH_PADDING_Y * 2.0f}; + ItemSize(size); + if (!ItemAdd({pos, pos + size}, GetID("FrameGraph"))) { + return; + } + + float target_dt = 1.0f / (TARGET_FPS * (float)Config::vblankDiv()); + float cur_pos_x = pos.x + full_width; + pos.y += FRAME_GRAPH_PADDING_Y; + const float final_pos_y = pos.y + FRAME_GRAPH_HEIGHT; + + auto& draw_list = *GetWindowDrawList(); + draw_list.AddRectFilled({pos.x, pos.y - FRAME_GRAPH_PADDING_Y}, + {pos.x + full_width, final_pos_y + FRAME_GRAPH_PADDING_Y}, + IM_COL32(0x33, 0x33, 0x33, 0xFF)); + draw_list.PushClipRect({pos.x, pos.y}, {pos.x + full_width, final_pos_y}, true); + for (u32 i = 0; i < FRAME_BUFFER_SIZE; ++i) { + const auto& frame_info = frame_list[(DebugState.GetFrameNum() - i) % FRAME_BUFFER_SIZE]; + const float dt_factor = target_dt / frame_info.delta; + + const float width = std::ceil(BAR_WIDTH_MULT / dt_factor); + const float height = + std::min(std::log2(BAR_HEIGHT_MULT / dt_factor) / 3.0f, 1.0f) * FRAME_GRAPH_HEIGHT; + + ImU32 color; + if (dt_factor >= 0.95f) { // BLUE + color = IM_COL32(0x33, 0x33, 0xFF, 0xFF); + } else if (dt_factor >= 0.5f) { // GREEN <> YELLOW + float t = 1.0f - (dt_factor - 0.5f) * 2.0f; + int r = (int)(0xFF * t); + color = IM_COL32(r, 0xFF, 0, 0xFF); + } else { // YELLOW <> RED + float t = dt_factor * 2.0f; + int g = (int)(0xFF * t); + color = IM_COL32(0xFF, g, 0, 0xFF); + } + draw_list.AddRectFilled({cur_pos_x - width, final_pos_y - height}, {cur_pos_x, final_pos_y}, + color); + cur_pos_x -= width; + if (cur_pos_x < width) { + break; + } + } + draw_list.PopClipRect(); +} + void FrameGraph::Draw() { if (!is_open) { return; @@ -43,55 +94,9 @@ void FrameGraph::Draw() { Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate); Text("Flip frame: %d Gnm submit frame: %d", DebugState.flip_frame_count.load(), DebugState.gnm_frame_count.load()); + SeparatorText("Frame graph"); - - const float full_width = GetContentRegionAvail().x; - // Frame graph - inspired by - // https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times - auto pos = GetCursorScreenPos(); - const ImVec2 size{full_width, FRAME_GRAPH_HEIGHT + FRAME_GRAPH_PADDING_Y * 2.0f}; - ItemSize(size); - if (!ItemAdd({pos, pos + size}, GetID("FrameGraph"))) { - return; - } - - float target_dt = 1.0f / (TARGET_FPS * (float)Config::vblankDiv()); - float cur_pos_x = pos.x + full_width; - pos.y += FRAME_GRAPH_PADDING_Y; - const float final_pos_y = pos.y + FRAME_GRAPH_HEIGHT; - - draw_list.AddRectFilled({pos.x, pos.y - FRAME_GRAPH_PADDING_Y}, - {pos.x + full_width, final_pos_y + FRAME_GRAPH_PADDING_Y}, - IM_COL32(0x33, 0x33, 0x33, 0xFF)); - draw_list.PushClipRect({pos.x, pos.y}, {pos.x + full_width, final_pos_y}, true); - for (u32 i = 0; i < FRAME_BUFFER_SIZE; ++i) { - const auto& frame_info = frame_list[(DebugState.GetFrameNum() - i) % FRAME_BUFFER_SIZE]; - const float dt_factor = target_dt / frame_info.delta; - - const float width = std::ceil(BAR_WIDTH_MULT / dt_factor); - const float height = - std::min(std::log2(BAR_HEIGHT_MULT / dt_factor) / 3.0f, 1.0f) * FRAME_GRAPH_HEIGHT; - - ImU32 color; - if (dt_factor >= 0.95f) { // BLUE - color = IM_COL32(0x33, 0x33, 0xFF, 0xFF); - } else if (dt_factor >= 0.5f) { // GREEN <> YELLOW - float t = 1.0f - (dt_factor - 0.5f) * 2.0f; - int r = (int)(0xFF * t); - color = IM_COL32(r, 0xFF, 0, 0xFF); - } else { // YELLOW <> RED - float t = dt_factor * 2.0f; - int g = (int)(0xFF * t); - color = IM_COL32(0xFF, g, 0, 0xFF); - } - draw_list.AddRectFilled({cur_pos_x - width, final_pos_y - height}, - {cur_pos_x, final_pos_y}, color); - cur_pos_x -= width; - if (cur_pos_x < width) { - break; - } - } - draw_list.PopClipRect(); + DrawFrameGraph(); } End(); } diff --git a/src/core/devtools/widget/frame_graph.h b/src/core/devtools/widget/frame_graph.h index 700b6b2a2..40a68ffa7 100644 --- a/src/core/devtools/widget/frame_graph.h +++ b/src/core/devtools/widget/frame_graph.h @@ -16,6 +16,8 @@ class FrameGraph { std::array frame_list{}; + void DrawFrameGraph(); + public: bool is_open = true; diff --git a/src/core/devtools/widget/reg_popup.cpp b/src/core/devtools/widget/reg_popup.cpp index 2727e1745..fae620901 100644 --- a/src/core/devtools/widget/reg_popup.cpp +++ b/src/core/devtools/widget/reg_popup.cpp @@ -66,7 +66,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) { "GetColorSliceSize()", buffer.GetColorSliceSize(), "GetTilingMode()", buffer.GetTilingMode(), "IsTiled()", buffer.IsTiled(), - "NumFormat()", buffer.NumFormat() + "NumFormat()", buffer.GetNumberFmt() ); // clang-format on diff --git a/src/core/devtools/widget/reg_view.cpp b/src/core/devtools/widget/reg_view.cpp index 79b02a849..a1b7937df 100644 --- a/src/core/devtools/widget/reg_view.cpp +++ b/src/core/devtools/widget/reg_view.cpp @@ -292,6 +292,17 @@ void RegView::Draw() { EndMenuBar(); } + const char* shader_name = "_"; + if (data.is_compute) { + shader_name = data.cs_data.name.c_str(); + } else if (selected_shader >= 0) { + shader_name = data.stages[selected_shader].name.c_str(); + } + + TextUnformatted("Shader: "); + SameLine(); + TextUnformatted(shader_name); + if (!data.is_compute && BeginChild("STAGES", {}, ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY)) { diff --git a/src/core/devtools/widget/shader_list.cpp b/src/core/devtools/widget/shader_list.cpp index 2c97db7fd..97d01896d 100644 --- a/src/core/devtools/widget/shader_list.cpp +++ b/src/core/devtools/widget/shader_list.cpp @@ -112,6 +112,10 @@ bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) { ReloadShader(value); } } + SameLine(); + if (Button("Copy name")) { + SetClipboardText(value.name.c_str()); + } if (value.is_patched) { if (BeginCombo("Shader type", showing_bin ? "SPIRV" : "GLSL", @@ -229,9 +233,16 @@ void ShaderList::Draw() { return; } + InputTextEx("##search_shader", "Search by name", search_box, sizeof(search_box), {}, + ImGuiInputTextFlags_None); + auto width = GetContentRegionAvail().x; int i = 0; for (const auto& shader : DebugState.shader_dump_list) { + if (search_box[0] != '\0' && !shader.name.contains(search_box)) { + i++; + continue; + } char name[128]; if (shader.is_patched) { snprintf(name, sizeof(name), "%s (PATCH ON)", shader.name.c_str()); diff --git a/src/core/devtools/widget/shader_list.h b/src/core/devtools/widget/shader_list.h index 2534ded35..fbb8d2070 100644 --- a/src/core/devtools/widget/shader_list.h +++ b/src/core/devtools/widget/shader_list.h @@ -31,6 +31,8 @@ class ShaderList { std::vector open_shaders{}; + char search_box[128]{}; + public: bool open = false; diff --git a/src/core/file_format/trp.cpp b/src/core/file_format/trp.cpp index 2ca88c778..d25c93c3f 100644 --- a/src/core/file_format/trp.cpp +++ b/src/core/file_format/trp.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/config.h" #include "common/logging/log.h" #include "common/path_util.h" #include "trp.h" @@ -33,12 +34,29 @@ static void removePadding(std::vector& vec) { } } +static void hexToBytes(const char* hex, unsigned char* dst) { + for (size_t i = 0; hex[i] != 0; i++) { + const unsigned char value = (hex[i] < 0x3A) ? (hex[i] - 0x30) : (hex[i] - 0x37); + dst[i / 2] |= ((i % 2) == 0) ? (value << 4) : (value); + } +} + bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string titleId) { std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/"; if (!std::filesystem::exists(gameSysDir)) { LOG_CRITICAL(Common_Filesystem, "Game sce_sys directory doesn't exist"); return false; } + + const auto user_key_str = Config::getTrophyKey(); + if (user_key_str.size() != 32) { + LOG_CRITICAL(Common_Filesystem, "Trophy decryption key is not specified"); + return false; + } + + std::array user_key{}; + hexToBytes(user_key_str.c_str(), user_key.data()); + for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) { if (it.is_regular_file()) { GetNPcommID(trophyPath, index); @@ -97,7 +115,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit return false; } file.Read(ESFM); - crypto.decryptEFSM(np_comm_id, esfmIv, ESFM, XML); // decrypt + crypto.decryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt removePadding(XML); std::string xml_name = entry.entry_name; size_t pos = xml_name.find("ESFM"); diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index bf340e9e3..7d456780b 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -40,7 +40,8 @@ void MntPoints::UnmountAll() { m_mnt_pairs.clear(); } -std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_read_only) { +std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_read_only, + bool force_base_path) { // Evil games like Turok2 pass double slashes e.g /app0//game.kpf std::string corrected_path(path); size_t pos = corrected_path.find("//"); @@ -72,7 +73,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea patch_path /= rel_path; if ((corrected_path.starts_with("/app0") || corrected_path.starts_with("/hostapp")) && - std::filesystem::exists(patch_path)) { + !force_base_path && std::filesystem::exists(patch_path)) { return patch_path; } @@ -132,8 +133,10 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea return std::optional(current_path); }; - if (const auto path = search(patch_path)) { - return *path; + if (!force_base_path) { + if (const auto path = search(patch_path)) { + return *path; + } } if (const auto path = search(host_path)) { return *path; @@ -144,6 +147,39 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea return host_path; } +// TODO: Does not handle mount points inside mount points. +void MntPoints::IterateDirectory(std::string_view guest_directory, + const IterateDirectoryCallback& callback) { + const auto base_path = GetHostPath(guest_directory, nullptr, true); + const auto patch_path = GetHostPath(guest_directory, nullptr, false); + // Only need to consider patch path if it exists and does not resolve to the same as base. + const auto apply_patch = base_path != patch_path && std::filesystem::exists(patch_path); + + // Pass 1: Any files that existed in the base directory, using patch directory if needed. + if (std::filesystem::exists(base_path)) { + for (const auto& entry : std::filesystem::directory_iterator(base_path)) { + if (apply_patch) { + const auto patch_entry_path = patch_path / entry.path().filename(); + if (std::filesystem::exists(patch_entry_path)) { + callback(patch_entry_path, !std::filesystem::is_directory(patch_entry_path)); + continue; + } + } + callback(entry.path(), !entry.is_directory()); + } + } + + // Pass 2: Any files that exist only in the patch directory. + if (apply_patch) { + for (const auto& entry : std::filesystem::directory_iterator(patch_path)) { + const auto base_entry_path = base_path / entry.path().filename(); + if (!std::filesystem::exists(base_entry_path)) { + callback(entry.path(), !entry.is_directory()); + } + } + } +} + int HandleTable::CreateHandle() { std::scoped_lock lock{m_mutex}; diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 56df32ad0..6638b48e8 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -36,7 +36,11 @@ public: void UnmountAll(); std::filesystem::path GetHostPath(std::string_view guest_directory, - bool* is_read_only = nullptr); + bool* is_read_only = nullptr, bool force_base_path = false); + using IterateDirectoryCallback = + std::function; + void IterateDirectory(std::string_view guest_directory, + const IterateDirectoryCallback& callback); const MntPair* GetMountFromHostPath(const std::string& host_path) { std::scoped_lock lock{m_mutex}; diff --git a/src/core/libraries/ajm/ajm.cpp b/src/core/libraries/ajm/ajm.cpp index 3184fa64f..5c55d2c06 100644 --- a/src/core/libraries/ajm/ajm.cpp +++ b/src/core/libraries/ajm/ajm.cpp @@ -183,13 +183,15 @@ int PS4_SYSV_ABI sceAjmInstanceSwitch() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAjmMemoryRegister() { - LOG_ERROR(Lib_Ajm, "(STUBBED) called"); +int PS4_SYSV_ABI sceAjmMemoryRegister(u32 context_id, void* ptr, size_t num_pages) { + // All memory is already shared with our implementation since we do not use any hardware. + LOG_TRACE(Lib_Ajm, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceAjmMemoryUnregister() { - LOG_ERROR(Lib_Ajm, "(STUBBED) called"); +int PS4_SYSV_ABI sceAjmMemoryUnregister(u32 context_id, void* ptr) { + // All memory is already shared with our implementation since we do not use any hardware. + LOG_TRACE(Lib_Ajm, "(STUBBED) called"); return ORBIS_OK; } diff --git a/src/core/libraries/ajm/ajm.h b/src/core/libraries/ajm/ajm.h index 1ac7c7629..34aeb9aa4 100644 --- a/src/core/libraries/ajm/ajm.h +++ b/src/core/libraries/ajm/ajm.h @@ -74,6 +74,26 @@ union AjmJobFlags { }; }; +enum class AjmStatisticsFlags : u64 { + Memory = 1 << 0, + EnginePerCodec = 1 << 15, + Engine = 1 << 16, +}; +DECLARE_ENUM_FLAG_OPERATORS(AjmStatisticsFlags) + +union AjmStatisticsJobFlags { + AjmStatisticsJobFlags(AjmJobFlags job_flags) : raw(job_flags.raw) {} + + u64 raw; + struct { + u64 version : 3; + u64 : 12; + AjmStatisticsFlags statistics_flags : 17; + u64 : 32; + }; +}; +static_assert(sizeof(AjmStatisticsJobFlags) == 8); + struct AjmSidebandResult { s32 result; s32 internal_result; @@ -126,6 +146,31 @@ union AjmSidebandInitParameters { u8 reserved[8]; }; +struct AjmSidebandStatisticsEngine { + float usage_batch; + float usage_interval[3]; +}; + +struct AjmSidebandStatisticsEnginePerCodec { + u8 codec_count; + u8 codec_id[3]; + float codec_percentage[3]; +}; + +struct AjmSidebandStatisticsMemory { + u32 instance_free; + u32 buffer_free; + u32 batch_size; + u32 input_size; + u32 output_size; + u32 small_size; +}; + +struct AjmSidebandStatisticsEngineParameters { + u32 interval_count; + float interval[3]; +}; + union AjmInstanceFlags { u64 raw; struct { @@ -178,8 +223,8 @@ int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmI int PS4_SYSV_ABI sceAjmInstanceDestroy(u32 context, u32 instance); int PS4_SYSV_ABI sceAjmInstanceExtend(); int PS4_SYSV_ABI sceAjmInstanceSwitch(); -int PS4_SYSV_ABI sceAjmMemoryRegister(); -int PS4_SYSV_ABI sceAjmMemoryUnregister(); +int PS4_SYSV_ABI sceAjmMemoryRegister(u32 context_id, void* ptr, size_t num_pages); +int PS4_SYSV_ABI sceAjmMemoryUnregister(u32 context_id, void* ptr); int PS4_SYSV_ABI sceAjmModuleRegister(u32 context, AjmCodecType codec_type, s64 reserved); int PS4_SYSV_ABI sceAjmModuleUnregister(); int PS4_SYSV_ABI sceAjmStrError(); diff --git a/src/core/libraries/ajm/ajm_batch.cpp b/src/core/libraries/ajm/ajm_batch.cpp index b1cec88b3..30e1deb71 100644 --- a/src/core/libraries/ajm/ajm_batch.cpp +++ b/src/core/libraries/ajm/ajm_batch.cpp @@ -54,6 +54,8 @@ public: : m_p_begin(begin), m_p_current(m_p_begin), m_size(size) {} AjmBatchBuffer(std::span data) : m_p_begin(data.data()), m_p_current(m_p_begin), m_size(data.size()) {} + AjmBatchBuffer(AjmChunkBuffer& buffer) + : AjmBatchBuffer(reinterpret_cast(buffer.p_address), buffer.size) {} AjmBatchBuffer SubBuffer(size_t size = s_dynamic_extent) { auto current = m_p_current; @@ -113,6 +115,88 @@ private: size_t m_size{}; }; +AjmJob AjmStatisticsJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { + std::optional job_flags = {}; + std::optional input_control_buffer = {}; + std::optional output_control_buffer = {}; + + AjmJob job; + job.instance_id = instance_id; + + while (!batch_buffer.IsEmpty()) { + auto& header = batch_buffer.Peek(); + switch (header.ident) { + case Identifier::AjmIdentInputControlBuf: { + ASSERT_MSG(!input_control_buffer.has_value(), + "Only one instance of input control buffer is allowed per job"); + const auto& buffer = batch_buffer.Consume(); + if (buffer.p_address != nullptr && buffer.size != 0) { + input_control_buffer = buffer; + } + break; + } + case Identifier::AjmIdentControlFlags: { + ASSERT_MSG(!job_flags.has_value(), "Only one instance of job flags is allowed per job"); + auto& chunk = batch_buffer.Consume(); + job_flags = AjmJobFlags{ + .raw = (u64(chunk.header.payload) << 32) + chunk.flags_low, + }; + break; + } + case Identifier::AjmIdentReturnAddressBuf: { + // Ignore return address buffers. + batch_buffer.Skip(); + break; + } + case Identifier::AjmIdentOutputControlBuf: { + ASSERT_MSG(!output_control_buffer.has_value(), + "Only one instance of output control buffer is allowed per job"); + const auto& buffer = batch_buffer.Consume(); + if (buffer.p_address != nullptr && buffer.size != 0) { + output_control_buffer = buffer; + } + break; + } + default: + UNREACHABLE_MSG("Unknown chunk: {}", header.ident); + } + } + + ASSERT(job_flags.has_value()); + job.flags = job_flags.value(); + + AjmStatisticsJobFlags flags(job.flags); + if (input_control_buffer.has_value()) { + AjmBatchBuffer input_batch(input_control_buffer.value()); + if (True(flags.statistics_flags & AjmStatisticsFlags::Engine)) { + job.input.statistics_engine_parameters = + input_batch.Consume(); + } + } + + if (output_control_buffer.has_value()) { + AjmBatchBuffer output_batch(output_control_buffer.value()); + job.output.p_result = &output_batch.Consume(); + *job.output.p_result = AjmSidebandResult{}; + + if (True(flags.statistics_flags & AjmStatisticsFlags::Engine)) { + job.output.p_engine = &output_batch.Consume(); + *job.output.p_engine = AjmSidebandStatisticsEngine{}; + } + if (True(flags.statistics_flags & AjmStatisticsFlags::EnginePerCodec)) { + job.output.p_engine_per_codec = + &output_batch.Consume(); + *job.output.p_engine_per_codec = AjmSidebandStatisticsEnginePerCodec{}; + } + if (True(flags.statistics_flags & AjmStatisticsFlags::Memory)) { + job.output.p_memory = &output_batch.Consume(); + *job.output.p_memory = AjmSidebandStatisticsMemory{}; + } + } + + return job; +} + AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { std::optional job_flags = {}; std::optional input_control_buffer = {}; @@ -155,15 +239,6 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { batch_buffer.Skip(); break; } - case Identifier::AjmIdentInlineBuf: { - ASSERT_MSG(!output_control_buffer.has_value(), - "Only one instance of inline buffer is allowed per job"); - const auto& buffer = batch_buffer.Consume(); - if (buffer.p_address != nullptr && buffer.size != 0) { - inline_buffer = buffer; - } - break; - } case Identifier::AjmIdentOutputRunBuf: { auto& buffer = batch_buffer.Consume(); u8* p_begin = reinterpret_cast(buffer.p_address); @@ -186,13 +261,12 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { } } + ASSERT(job_flags.has_value()); job.flags = job_flags.value(); // Initialize sideband input parameters if (input_control_buffer.has_value()) { - AjmBatchBuffer input_batch(reinterpret_cast(input_control_buffer->p_address), - input_control_buffer->size); - + AjmBatchBuffer input_batch(input_control_buffer.value()); const auto sideband_flags = job_flags->sideband_flags; if (True(sideband_flags & AjmJobSidebandFlags::Format) && !input_batch.IsEmpty()) { job.input.format = input_batch.Consume(); @@ -202,6 +276,9 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { } const auto control_flags = job_flags.value().control_flags; + if (True(control_flags & AjmJobControlFlags::Resample)) { + job.input.resample_parameters = input_batch.Consume(); + } if (True(control_flags & AjmJobControlFlags::Initialize)) { job.input.init_params = AjmDecAt9InitializeParameters{}; std::memcpy(&job.input.init_params.value(), input_batch.GetCurrent(), @@ -209,21 +286,9 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { } } - if (inline_buffer.has_value()) { - AjmBatchBuffer inline_batch(reinterpret_cast(inline_buffer->p_address), - inline_buffer->size); - - const auto control_flags = job_flags.value().control_flags; - if (True(control_flags & AjmJobControlFlags::Resample)) { - job.input.resample_parameters = inline_batch.Consume(); - } - } - // Initialize sideband output parameters if (output_control_buffer.has_value()) { - AjmBatchBuffer output_batch(reinterpret_cast(output_control_buffer->p_address), - output_control_buffer->size); - + AjmBatchBuffer output_batch(output_control_buffer.value()); job.output.p_result = &output_batch.Consume(); *job.output.p_result = AjmSidebandResult{}; @@ -260,9 +325,21 @@ std::shared_ptr AjmBatch::FromBatchBuffer(std::span data) { AjmBatchBuffer buffer(data); while (!buffer.IsEmpty()) { auto& job_chunk = buffer.Consume(); + if (job_chunk.header.ident == AjmIdentInlineBuf) { + // Inline buffers are used to store sideband input data. + // We should just skip them as they do not require any special handling. + buffer.Advance(job_chunk.size); + continue; + } ASSERT(job_chunk.header.ident == AjmIdentJob); auto instance_id = job_chunk.header.payload; - batch->jobs.push_back(AjmJobFromBatchBuffer(instance_id, buffer.SubBuffer(job_chunk.size))); + if (instance_id == AJM_INSTANCE_STATISTICS) { + batch->jobs.push_back( + AjmStatisticsJobFromBatchBuffer(instance_id, buffer.SubBuffer(job_chunk.size))); + } else { + batch->jobs.push_back( + AjmJobFromBatchBuffer(instance_id, buffer.SubBuffer(job_chunk.size))); + } } return batch; diff --git a/src/core/libraries/ajm/ajm_batch.h b/src/core/libraries/ajm/ajm_batch.h index 65110ee73..09daa630d 100644 --- a/src/core/libraries/ajm/ajm_batch.h +++ b/src/core/libraries/ajm/ajm_batch.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ struct AjmJob { struct Input { std::optional init_params; std::optional resample_parameters; + std::optional statistics_engine_parameters; std::optional format; std::optional gapless_decode; std::vector buffer; @@ -32,6 +34,9 @@ struct AjmJob { AjmSidebandResult* p_result = nullptr; AjmSidebandStream* p_stream = nullptr; AjmSidebandFormat* p_format = nullptr; + AjmSidebandStatisticsMemory* p_memory = nullptr; + AjmSidebandStatisticsEnginePerCodec* p_engine_per_codec = nullptr; + AjmSidebandStatisticsEngine* p_engine = nullptr; AjmSidebandGaplessDecode* p_gapless_decode = nullptr; AjmSidebandMFrame* p_mframe = nullptr; u8* p_codec_info = nullptr; diff --git a/src/core/libraries/ajm/ajm_context.cpp b/src/core/libraries/ajm/ajm_context.cpp index 09255110c..8992dd83b 100644 --- a/src/core/libraries/ajm/ajm_context.cpp +++ b/src/core/libraries/ajm/ajm_context.cpp @@ -9,6 +9,7 @@ #include "core/libraries/ajm/ajm_context.h" #include "core/libraries/ajm/ajm_error.h" #include "core/libraries/ajm/ajm_instance.h" +#include "core/libraries/ajm/ajm_instance_statistics.h" #include "core/libraries/ajm/ajm_mp3.h" #include "core/libraries/error_codes.h" @@ -70,15 +71,19 @@ void AjmContext::ProcessBatch(u32 id, std::span jobs) { LOG_TRACE(Lib_Ajm, "Processing job {} for instance {}. flags = {:#x}", id, job.instance_id, job.flags.raw); - std::shared_ptr instance; - { - std::shared_lock lock(instances_mutex); - auto* p_instance = instances.Get(job.instance_id); - ASSERT_MSG(p_instance != nullptr, "Attempting to execute job on null instance"); - instance = *p_instance; - } + if (job.instance_id == AJM_INSTANCE_STATISTICS) { + AjmInstanceStatistics::Getinstance().ExecuteJob(job); + } else { + std::shared_ptr instance; + { + std::shared_lock lock(instances_mutex); + auto* p_instance = instances.Get(job.instance_id); + ASSERT_MSG(p_instance != nullptr, "Attempting to execute job on null instance"); + instance = *p_instance; + } - instance->ExecuteJob(job); + instance->ExecuteJob(job); + } } } diff --git a/src/core/libraries/ajm/ajm_instance.cpp b/src/core/libraries/ajm/ajm_instance.cpp index ea7fd5617..8af105c77 100644 --- a/src/core/libraries/ajm/ajm_instance.cpp +++ b/src/core/libraries/ajm/ajm_instance.cpp @@ -68,11 +68,11 @@ void AjmInstance::ExecuteJob(AjmJob& job) { m_codec->Initialize(¶ms, sizeof(params)); } if (job.input.resample_parameters.has_value()) { - UNREACHABLE_MSG("Unimplemented: resample parameters"); + LOG_ERROR(Lib_Ajm, "Unimplemented: resample parameters"); m_resample_parameters = job.input.resample_parameters.value(); } if (job.input.format.has_value()) { - UNREACHABLE_MSG("Unimplemented: format parameters"); + LOG_ERROR(Lib_Ajm, "Unimplemented: format parameters"); m_format = job.input.format.value(); } if (job.input.gapless_decode.has_value()) { diff --git a/src/core/libraries/ajm/ajm_instance_statistics.cpp b/src/core/libraries/ajm/ajm_instance_statistics.cpp new file mode 100644 index 000000000..c0c1af8bb --- /dev/null +++ b/src/core/libraries/ajm/ajm_instance_statistics.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/libraries/ajm/ajm.h" +#include "core/libraries/ajm/ajm_instance_statistics.h" + +namespace Libraries::Ajm { + +void AjmInstanceStatistics::ExecuteJob(AjmJob& job) { + if (job.output.p_engine) { + job.output.p_engine->usage_batch = 0.01; + const auto ic = job.input.statistics_engine_parameters->interval_count; + for (u32 idx = 0; idx < ic; ++idx) { + job.output.p_engine->usage_interval[idx] = 0.01; + } + } + if (job.output.p_engine_per_codec) { + job.output.p_engine_per_codec->codec_count = 1; + job.output.p_engine_per_codec->codec_id[0] = static_cast(AjmCodecType::At9Dec); + job.output.p_engine_per_codec->codec_percentage[0] = 0.01; + } + if (job.output.p_memory) { + job.output.p_memory->instance_free = 0x400000; + job.output.p_memory->buffer_free = 0x400000; + job.output.p_memory->batch_size = 0x4200; + job.output.p_memory->input_size = 0x2000; + job.output.p_memory->output_size = 0x2000; + job.output.p_memory->small_size = 0x200; + } +} + +AjmInstanceStatistics& AjmInstanceStatistics::Getinstance() { + static AjmInstanceStatistics instance; + return instance; +} + +} // namespace Libraries::Ajm diff --git a/src/core/libraries/ajm/ajm_instance_statistics.h b/src/core/libraries/ajm/ajm_instance_statistics.h new file mode 100644 index 000000000..ea70c9d56 --- /dev/null +++ b/src/core/libraries/ajm/ajm_instance_statistics.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/libraries/ajm/ajm_batch.h" + +namespace Libraries::Ajm { + +class AjmInstanceStatistics { +public: + void ExecuteJob(AjmJob& job); + + static AjmInstanceStatistics& Getinstance(); +}; + +} // namespace Libraries::Ajm diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index ca3cdad39..1d23e7f44 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -145,8 +145,10 @@ int PS4_SYSV_ABI sceAppContentDownloadDataFormat() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb() { +int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(OrbisAppContentMountPoint* mountPoint, + u64* availableSpaceKb) { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); + *availableSpaceKb = 1048576; return ORBIS_OK; } @@ -294,9 +296,9 @@ int PS4_SYSV_ABI sceAppContentTemporaryDataFormat() { } int PS4_SYSV_ABI sceAppContentTemporaryDataGetAvailableSpaceKb( - const OrbisAppContentMountPoint* mountPoint, size_t* availableSpaceKb) { + const OrbisAppContentMountPoint* mountPoint, u64* availableSpaceKb) { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - *availableSpaceKb = 1073741824; + *availableSpaceKb = 1048576; return ORBIS_OK; } diff --git a/src/core/libraries/app_content/app_content.h b/src/core/libraries/app_content/app_content.h index f41f7dccf..05bd3bc49 100644 --- a/src/core/libraries/app_content/app_content.h +++ b/src/core/libraries/app_content/app_content.h @@ -84,7 +84,8 @@ int PS4_SYSV_ABI sceAppContentDownload0Shrink(); int PS4_SYSV_ABI sceAppContentDownload1Expand(); int PS4_SYSV_ABI sceAppContentDownload1Shrink(); int PS4_SYSV_ABI sceAppContentDownloadDataFormat(); -int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(); +int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(OrbisAppContentMountPoint* mountPoint, + u64* availableSpaceKb); int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress(); int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlementLabel, @@ -105,7 +106,7 @@ int PS4_SYSV_ABI sceAppContentSmallSharedDataMount(); int PS4_SYSV_ABI sceAppContentSmallSharedDataUnmount(); int PS4_SYSV_ABI sceAppContentTemporaryDataFormat(); int PS4_SYSV_ABI sceAppContentTemporaryDataGetAvailableSpaceKb( - const OrbisAppContentMountPoint* mountPoint, size_t* availableSpaceKb); + const OrbisAppContentMountPoint* mountPoint, u64* availableSpaceKb); int PS4_SYSV_ABI sceAppContentTemporaryDataMount(); int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOption option, OrbisAppContentMountPoint* mountPoint); diff --git a/src/core/libraries/audio/audioout.cpp b/src/core/libraries/audio/audioout.cpp index db43ee928..f0ad59c3b 100644 --- a/src/core/libraries/audio/audioout.cpp +++ b/src/core/libraries/audio/audioout.cpp @@ -3,140 +3,48 @@ #include #include -#include +#include +#include #include #include "common/assert.h" +#include "common/config.h" #include "common/logging/log.h" +#include "common/thread.h" #include "core/libraries/audio/audioout.h" +#include "core/libraries/audio/audioout_backend.h" #include "core/libraries/audio/audioout_error.h" -#include "core/libraries/audio/sdl_audio.h" #include "core/libraries/libs.h" namespace Libraries::AudioOut { -struct PortOut { - void* impl; - u32 samples_num; - u32 freq; - OrbisAudioOutParamFormat format; - OrbisAudioOutPort type; - int channels_num; - bool is_float; - std::array volume; - u8 sample_size; - bool is_open; -}; -std::shared_mutex ports_mutex; +std::mutex port_open_mutex{}; std::array ports_out{}; static std::unique_ptr audio; -static std::string_view GetAudioOutPort(OrbisAudioOutPort port) { - switch (port) { - case OrbisAudioOutPort::Main: - return "MAIN"; - case OrbisAudioOutPort::Bgm: - return "BGM"; - case OrbisAudioOutPort::Voice: - return "VOICE"; - case OrbisAudioOutPort::Personal: - return "PERSONAL"; - case OrbisAudioOutPort::Padspk: - return "PADSPK"; - case OrbisAudioOutPort::Aux: - return "AUX"; - default: - return "INVALID"; - } -} - -static std::string_view GetAudioOutParamFormat(OrbisAudioOutParamFormat param) { - switch (param) { - case OrbisAudioOutParamFormat::S16Mono: - return "S16_MONO"; - case OrbisAudioOutParamFormat::S16Stereo: - return "S16_STEREO"; - case OrbisAudioOutParamFormat::S16_8CH: - return "S16_8CH"; - case OrbisAudioOutParamFormat::FloatMono: - return "FLOAT_MONO"; - case OrbisAudioOutParamFormat::FloatStereo: - return "FLOAT_STEREO"; - case OrbisAudioOutParamFormat::Float_8CH: - return "FLOAT_8CH"; - case OrbisAudioOutParamFormat::S16_8CH_Std: - return "S16_8CH_STD"; - case OrbisAudioOutParamFormat::Float_8CH_Std: - return "FLOAT_8CH_STD"; - default: - return "INVALID"; - } -} - -static std::string_view GetAudioOutParamAttr(OrbisAudioOutParamAttr attr) { - switch (attr) { - case OrbisAudioOutParamAttr::None: - return "NONE"; - case OrbisAudioOutParamAttr::Restricted: - return "RESTRICTED"; - case OrbisAudioOutParamAttr::MixToMain: - return "MIX_TO_MAIN"; - default: - return "INVALID"; - } -} - -static bool IsFormatFloat(const OrbisAudioOutParamFormat format) { - switch (format) { - case OrbisAudioOutParamFormat::S16Mono: - case OrbisAudioOutParamFormat::S16Stereo: - case OrbisAudioOutParamFormat::S16_8CH: - case OrbisAudioOutParamFormat::S16_8CH_Std: - return false; - case OrbisAudioOutParamFormat::FloatMono: - case OrbisAudioOutParamFormat::FloatStereo: - case OrbisAudioOutParamFormat::Float_8CH: - case OrbisAudioOutParamFormat::Float_8CH_Std: - return true; - default: - UNREACHABLE_MSG("Unknown format"); - } -} - -static int GetFormatNumChannels(const OrbisAudioOutParamFormat format) { - switch (format) { - case OrbisAudioOutParamFormat::S16Mono: - case OrbisAudioOutParamFormat::FloatMono: - return 1; - case OrbisAudioOutParamFormat::S16Stereo: - case OrbisAudioOutParamFormat::FloatStereo: - return 2; - case OrbisAudioOutParamFormat::S16_8CH: - case OrbisAudioOutParamFormat::Float_8CH: - case OrbisAudioOutParamFormat::S16_8CH_Std: - case OrbisAudioOutParamFormat::Float_8CH_Std: - return 8; - default: - UNREACHABLE_MSG("Unknown format"); - } -} - -static u8 GetFormatSampleSize(const OrbisAudioOutParamFormat format) { - switch (format) { - case OrbisAudioOutParamFormat::S16Mono: - case OrbisAudioOutParamFormat::S16Stereo: - case OrbisAudioOutParamFormat::S16_8CH: - case OrbisAudioOutParamFormat::S16_8CH_Std: - return 2; - case OrbisAudioOutParamFormat::FloatMono: - case OrbisAudioOutParamFormat::FloatStereo: - case OrbisAudioOutParamFormat::Float_8CH: - case OrbisAudioOutParamFormat::Float_8CH_Std: - return 4; - default: - UNREACHABLE_MSG("Unknown format"); - } +static AudioFormatInfo GetFormatInfo(const OrbisAudioOutParamFormat format) { + static constexpr std::array format_infos = {{ + // S16Mono + {false, 2, 1, {0}}, + // S16Stereo + {false, 2, 2, {0, 1}}, + // S16_8CH + {false, 2, 8, {0, 1, 2, 3, 4, 5, 6, 7}}, + // FloatMono + {true, 4, 1, {0}}, + // FloatStereo + {true, 4, 2, {0, 1}}, + // Float_8CH + {true, 4, 8, {0, 1, 2, 3, 4, 5, 6, 7}}, + // S16_8CH_Std + {false, 2, 8, {0, 1, 2, 3, 6, 7, 4, 5}}, + // Float_8CH_Std + {true, 4, 8, {0, 1, 2, 3, 6, 7, 4, 5}}, + }}; + const auto index = static_cast(format); + ASSERT_MSG(index < format_infos.size(), "Unknown audio format {}", index); + return format_infos[index]; } int PS4_SYSV_ABI sceAudioOutDeviceIdOpen() { @@ -185,15 +93,20 @@ int PS4_SYSV_ABI sceAudioOutClose(s32 handle) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - std::scoped_lock lock(ports_mutex); + std::unique_lock open_lock{port_open_mutex}; auto& port = ports_out.at(handle - 1); - if (!port.is_open) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + { + std::unique_lock lock{port.mutex}; + if (!port.IsOpen()) { + return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + } + std::free(port.output_buffer); + port.output_buffer = nullptr; + port.output_ready = false; + port.impl = nullptr; } - - audio->Close(port.impl); - port.impl = nullptr; - port.is_open = false; + // Stop outside of port lock scope to prevent deadlocks. + port.output_thread.Stop(); return ORBIS_OK; } @@ -262,35 +175,34 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - std::scoped_lock lock(ports_mutex); - const auto& port = ports_out.at(handle - 1); - if (!port.is_open) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + auto& port = ports_out.at(handle - 1); + { + std::unique_lock lock{port.mutex}; + if (!port.IsOpen()) { + return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + } + switch (port.type) { + case OrbisAudioOutPort::Main: + case OrbisAudioOutPort::Bgm: + case OrbisAudioOutPort::Voice: + state->output = 1; + state->channel = port.format_info.num_channels > 2 ? 2 : port.format_info.num_channels; + break; + case OrbisAudioOutPort::Personal: + case OrbisAudioOutPort::Padspk: + state->output = 4; + state->channel = 1; + break; + case OrbisAudioOutPort::Aux: + state->output = 0; + state->channel = 0; + break; + default: + UNREACHABLE(); + } + state->rerouteCounter = 0; + state->volume = 127; } - - state->rerouteCounter = 0; - state->volume = 127; - - switch (port.type) { - case OrbisAudioOutPort::Main: - case OrbisAudioOutPort::Bgm: - case OrbisAudioOutPort::Voice: - state->output = 1; - state->channel = port.channels_num > 2 ? 2 : port.channels_num; - break; - case OrbisAudioOutPort::Personal: - case OrbisAudioOutPort::Padspk: - state->output = 4; - state->channel = 1; - break; - case OrbisAudioOutPort::Aux: - state->output = 0; - state->channel = 0; - break; - default: - UNREACHABLE(); - } - return ORBIS_OK; } @@ -358,6 +270,31 @@ int PS4_SYSV_ABI sceAudioOutMbusInit() { return ORBIS_OK; } +static void AudioOutputThread(PortOut* port, const std::stop_token& stop) { + { + const auto thread_name = fmt::format("shadPS4:AudioOutputThread:{}", fmt::ptr(port)); + Common::SetCurrentThreadName(thread_name.c_str()); + } + + Common::AccurateTimer timer( + std::chrono::nanoseconds(1000000000ULL * port->buffer_frames / port->sample_rate)); + while (true) { + timer.Start(); + { + std::unique_lock lock{port->mutex}; + if (port->output_cv.wait(lock, stop, [&] { return port->output_ready; })) { + port->impl->Output(port->output_buffer); + port->output_ready = false; + } + } + port->output_cv.notify_one(); + if (stop.stop_requested()) { + break; + } + timer.End(); + } +} + s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, OrbisAudioOutPort port_type, s32 index, u32 length, u32 sample_rate, @@ -365,9 +302,9 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, LOG_INFO(Lib_AudioOut, "id = {} port_type = {} index = {} length = {} sample_rate = {} " "param_type = {} attr = {}", - user_id, GetAudioOutPort(port_type), index, length, sample_rate, - GetAudioOutParamFormat(param_type.data_format), - GetAudioOutParamAttr(param_type.attributes)); + user_id, magic_enum::enum_name(port_type), index, length, sample_rate, + magic_enum::enum_name(param_type.data_format.Value()), + magic_enum::enum_name(param_type.attributes.Value())); if ((port_type < OrbisAudioOutPort::Main || port_type > OrbisAudioOutPort::Padspk) && (port_type != OrbisAudioOutPort::Aux)) { LOG_ERROR(Lib_AudioOut, "Invalid port type"); @@ -398,24 +335,30 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT; } - std::scoped_lock lock{ports_mutex}; - const auto port = std::ranges::find(ports_out, false, &PortOut::is_open); + std::unique_lock open_lock{port_open_mutex}; + const auto port = + std::ranges::find_if(ports_out, [&](const PortOut& p) { return !p.IsOpen(); }); if (port == ports_out.end()) { LOG_ERROR(Lib_AudioOut, "Audio ports are full"); return ORBIS_AUDIO_OUT_ERROR_PORT_FULL; } - port->is_open = true; - port->type = port_type; - port->samples_num = length; - port->freq = sample_rate; - port->format = format; - port->is_float = IsFormatFloat(format); - port->channels_num = GetFormatNumChannels(format); - port->sample_size = GetFormatSampleSize(format); - port->volume.fill(SCE_AUDIO_OUT_VOLUME_0DB); + { + std::unique_lock port_lock(port->mutex); - port->impl = audio->Open(port->is_float, port->channels_num, port->freq); + port->type = port_type; + port->format_info = GetFormatInfo(format); + port->sample_rate = sample_rate; + port->buffer_frames = length; + port->volume.fill(SCE_AUDIO_OUT_VOLUME_0DB); + + port->impl = audio->Open(*port); + + port->output_buffer = std::malloc(port->BufferSize()); + port->output_ready = false; + port->output_thread.Run( + [port](const std::stop_token& stop) { AudioOutputThread(&*port, stop); }); + } return std::distance(ports_out.begin(), port) + 1; } @@ -424,29 +367,33 @@ int PS4_SYSV_ABI sceAudioOutOpenEx() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr) { +s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) { if (handle < 1 || handle > SCE_AUDIO_OUT_NUM_PORTS) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - if (ptr == nullptr) { - // Nothing to output - return ORBIS_OK; - } auto& port = ports_out.at(handle - 1); - if (!port.is_open) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + { + std::unique_lock lock{port.mutex}; + if (!port.IsOpen()) { + return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + } + port.output_cv.wait(lock, [&] { return !port.output_ready; }); + if (ptr != nullptr && port.IsOpen()) { + std::memcpy(port.output_buffer, ptr, port.BufferSize()); + port.output_ready = true; + } } - - const size_t data_size = port.samples_num * port.sample_size * port.channels_num; - audio->Output(port.impl, ptr, data_size); + port.output_cv.notify_one(); return ORBIS_OK; } int PS4_SYSV_ABI sceAudioOutOutputs(OrbisAudioOutOutputParam* param, u32 num) { for (u32 i = 0; i < num; i++) { - if (const auto err = sceAudioOutOutput(param[i].handle, param[i].ptr); err != 0) - return err; + const auto [handle, ptr] = param[i]; + if (const auto ret = sceAudioOutOutput(handle, ptr); ret != ORBIS_OK) { + return ret; + } } return ORBIS_OK; } @@ -546,40 +493,19 @@ s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - std::scoped_lock lock(ports_mutex); auto& port = ports_out.at(handle - 1); - if (!port.is_open) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; - } - - for (int i = 0; i < port.channels_num; i++, flag >>= 1u) { - auto bit = flag & 0x1u; - if (bit == 1) { - int src_index = i; - if (port.format == OrbisAudioOutParamFormat::Float_8CH_Std || - port.format == OrbisAudioOutParamFormat::S16_8CH_Std) { - switch (i) { - case 4: - src_index = 6; - break; - case 5: - src_index = 7; - break; - case 6: - src_index = 4; - break; - case 7: - src_index = 5; - break; - default: - break; - } - } - port.volume[i] = vol[src_index]; + { + std::unique_lock lock{port.mutex}; + if (!port.IsOpen()) { + return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } + for (int i = 0; i < port.format_info.num_channels; i++, flag >>= 1u) { + if (flag & 0x1u) { + port.volume[i] = vol[i]; + } + } + port.impl->SetVolume(port.volume); } - - audio->SetVolume(port.impl, port.volume); return ORBIS_OK; } diff --git a/src/core/libraries/audio/audioout.h b/src/core/libraries/audio/audioout.h index c66a0e9f5..5eafb43a1 100644 --- a/src/core/libraries/audio/audioout.h +++ b/src/core/libraries/audio/audioout.h @@ -3,20 +3,26 @@ #pragma once -#include "common/bit_field.h" +#include +#include +#include +#include "common/bit_field.h" +#include "core/libraries/kernel/threads.h" #include "core/libraries/system/userservice.h" namespace Libraries::AudioOut { +class PortBackend; + // Main up to 8 ports, BGM 1 port, voice up to 4 ports, // personal up to 4 ports, padspk up to 5 ports, aux 1 port -constexpr int SCE_AUDIO_OUT_NUM_PORTS = 22; -constexpr int SCE_AUDIO_OUT_VOLUME_0DB = 32768; // max volume value +constexpr s32 SCE_AUDIO_OUT_NUM_PORTS = 22; +constexpr s32 SCE_AUDIO_OUT_VOLUME_0DB = 32768; // max volume value enum class OrbisAudioOutPort { Main = 0, Bgm = 1, Voice = 2, Personal = 3, Padspk = 4, Aux = 127 }; -enum class OrbisAudioOutParamFormat { +enum class OrbisAudioOutParamFormat : u32 { S16Mono = 0, S16Stereo = 1, S16_8CH = 2, @@ -27,7 +33,7 @@ enum class OrbisAudioOutParamFormat { Float_8CH_Std = 7 }; -enum class OrbisAudioOutParamAttr { +enum class OrbisAudioOutParamAttr : u32 { None = 0, Restricted = 1, MixToMain = 2, @@ -43,7 +49,7 @@ union OrbisAudioOutParamExtendedInformation { struct OrbisAudioOutOutputParam { s32 handle; - const void* ptr; + void* ptr; }; struct OrbisAudioOutPortState { @@ -56,6 +62,43 @@ struct OrbisAudioOutPortState { u64 reserved64[2]; }; +struct AudioFormatInfo { + bool is_float; + u8 sample_size; + u8 num_channels; + /// Layout array remapping channel indices, specified in this order: + /// FL, FR, FC, LFE, BL, BR, SL, SR + std::array channel_layout; + + [[nodiscard]] u16 FrameSize() const { + return sample_size * num_channels; + } +}; + +struct PortOut { + std::mutex mutex; + std::unique_ptr impl{}; + + void* output_buffer; + std::condition_variable_any output_cv; + bool output_ready; + Kernel::Thread output_thread{}; + + OrbisAudioOutPort type; + AudioFormatInfo format_info; + u32 sample_rate; + u32 buffer_frames; + std::array volume; + + [[nodiscard]] bool IsOpen() const { + return impl != nullptr; + } + + [[nodiscard]] u32 BufferSize() const { + return buffer_frames * format_info.FrameSize(); + } +}; + int PS4_SYSV_ABI sceAudioOutDeviceIdOpen(); int PS4_SYSV_ABI sceAudioDeviceControlGet(); int PS4_SYSV_ABI sceAudioDeviceControlSet(); @@ -94,7 +137,7 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, OrbisAudioOutPort port_type, s32 index, u32 length, u32 sample_rate, OrbisAudioOutParamExtendedInformation param_type); int PS4_SYSV_ABI sceAudioOutOpenEx(); -s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr); +s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr); s32 PS4_SYSV_ABI sceAudioOutOutputs(OrbisAudioOutOutputParam* param, u32 num); int PS4_SYSV_ABI sceAudioOutPtClose(); int PS4_SYSV_ABI sceAudioOutPtGetLastOutputTime(); diff --git a/src/core/libraries/audio/audioout_backend.h b/src/core/libraries/audio/audioout_backend.h index 238ef0201..0f36f19c8 100644 --- a/src/core/libraries/audio/audioout_backend.h +++ b/src/core/libraries/audio/audioout_backend.h @@ -5,15 +5,30 @@ namespace Libraries::AudioOut { +struct PortOut; + +class PortBackend { +public: + virtual ~PortBackend() = default; + + /// Guaranteed to be called in intervals of at least port buffer time, + /// with size equal to port buffer size. + virtual void Output(void* ptr) = 0; + + virtual void SetVolume(const std::array& ch_volumes) = 0; +}; + class AudioOutBackend { public: AudioOutBackend() = default; virtual ~AudioOutBackend() = default; - virtual void* Open(bool is_float, int num_channels, u32 sample_rate) = 0; - virtual void Close(void* impl) = 0; - virtual void Output(void* impl, const void* ptr, size_t size) = 0; - virtual void SetVolume(void* impl, std::array ch_volumes) = 0; + virtual std::unique_ptr Open(PortOut& port) = 0; +}; + +class SDLAudioOut final : public AudioOutBackend { +public: + std::unique_ptr Open(PortOut& port) override; }; } // namespace Libraries::AudioOut diff --git a/src/core/libraries/audio/sdl_audio.cpp b/src/core/libraries/audio/sdl_audio.cpp index ce385ad9c..9aee2b447 100644 --- a/src/core/libraries/audio/sdl_audio.cpp +++ b/src/core/libraries/audio/sdl_audio.cpp @@ -1,44 +1,118 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include -#include -#include +#include -#include "common/assert.h" -#include "core/libraries/audio/sdl_audio.h" +#include "common/logging/log.h" +#include "core/libraries/audio/audioout.h" +#include "core/libraries/audio/audioout_backend.h" namespace Libraries::AudioOut { -constexpr int AUDIO_STREAM_BUFFER_THRESHOLD = 65536; // Define constant for buffer threshold - -void* SDLAudioOut::Open(bool is_float, int num_channels, u32 sample_rate) { - SDL_AudioSpec fmt; - SDL_zero(fmt); - fmt.format = is_float ? SDL_AUDIO_F32 : SDL_AUDIO_S16; - fmt.channels = num_channels; - fmt.freq = sample_rate; - - auto* stream = - SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, nullptr, nullptr); - SDL_ResumeAudioStreamDevice(stream); - return stream; -} - -void SDLAudioOut::Close(void* impl) { - SDL_DestroyAudioStream(static_cast(impl)); -} - -void SDLAudioOut::Output(void* impl, const void* ptr, size_t size) { - auto* stream = static_cast(impl); - SDL_PutAudioStreamData(stream, ptr, size); - while (SDL_GetAudioStreamAvailable(stream) > AUDIO_STREAM_BUFFER_THRESHOLD) { - SDL_Delay(0); +class SDLPortBackend : public PortBackend { +public: + explicit SDLPortBackend(const PortOut& port) + : frame_size(port.format_info.FrameSize()), guest_buffer_size(port.BufferSize()) { + const SDL_AudioSpec fmt = { + .format = port.format_info.is_float ? SDL_AUDIO_F32LE : SDL_AUDIO_S16LE, + .channels = port.format_info.num_channels, + .freq = static_cast(port.sample_rate), + }; + stream = + SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, nullptr, nullptr); + if (stream == nullptr) { + LOG_ERROR(Lib_AudioOut, "Failed to create SDL audio stream: {}", SDL_GetError()); + return; + } + CalculateQueueThreshold(); + if (!SDL_SetAudioStreamInputChannelMap(stream, port.format_info.channel_layout.data(), + port.format_info.num_channels)) { + LOG_ERROR(Lib_AudioOut, "Failed to configure SDL audio stream channel map: {}", + SDL_GetError()); + SDL_DestroyAudioStream(stream); + stream = nullptr; + return; + } + if (!SDL_ResumeAudioStreamDevice(stream)) { + LOG_ERROR(Lib_AudioOut, "Failed to resume SDL audio stream: {}", SDL_GetError()); + SDL_DestroyAudioStream(stream); + stream = nullptr; + return; + } } -} -void SDLAudioOut::SetVolume(void* impl, std::array ch_volumes) { - // Not yet implemented + ~SDLPortBackend() override { + if (!stream) { + return; + } + SDL_DestroyAudioStream(stream); + stream = nullptr; + } + + void Output(void* ptr) override { + if (!stream) { + return; + } + // AudioOut library manages timing, but we still need to guard against the SDL + // audio queue stalling, which may happen during device changes, for example. + // Otherwise, latency may grow over time unbounded. + if (const auto queued = SDL_GetAudioStreamQueued(stream); queued >= queue_threshold) { + LOG_WARNING(Lib_AudioOut, + "SDL audio queue backed up ({} queued, {} threshold), clearing.", queued, + queue_threshold); + SDL_ClearAudioStream(stream); + // Recalculate the threshold in case this happened because of a device change. + CalculateQueueThreshold(); + } + if (!SDL_PutAudioStreamData(stream, ptr, static_cast(guest_buffer_size))) { + LOG_ERROR(Lib_AudioOut, "Failed to output to SDL audio stream: {}", SDL_GetError()); + } + } + + void SetVolume(const std::array& ch_volumes) override { + if (!stream) { + return; + } + // SDL does not have per-channel volumes, for now just take the maximum of the channels. + const auto vol = *std::ranges::max_element(ch_volumes); + if (!SDL_SetAudioStreamGain(stream, static_cast(vol) / SCE_AUDIO_OUT_VOLUME_0DB)) { + LOG_WARNING(Lib_AudioOut, "Failed to change SDL audio stream volume: {}", + SDL_GetError()); + } + } + +private: + void CalculateQueueThreshold() { + SDL_AudioSpec discard; + int sdl_buffer_frames; + if (!SDL_GetAudioDeviceFormat(SDL_GetAudioStreamDevice(stream), &discard, + &sdl_buffer_frames)) { + LOG_WARNING(Lib_AudioOut, "Failed to get SDL audio stream buffer size: {}", + SDL_GetError()); + sdl_buffer_frames = 0; + } + const auto sdl_buffer_size = sdl_buffer_frames * frame_size; + const auto new_threshold = std::max(guest_buffer_size, sdl_buffer_size) * 4; + if (host_buffer_size != sdl_buffer_size || queue_threshold != new_threshold) { + host_buffer_size = sdl_buffer_size; + queue_threshold = new_threshold; + LOG_INFO(Lib_AudioOut, + "SDL audio buffers: guest = {} bytes, host = {} bytes, threshold = {} bytes", + guest_buffer_size, host_buffer_size, queue_threshold); + } + } + + u32 frame_size; + u32 guest_buffer_size; + u32 host_buffer_size{}; + u32 queue_threshold{}; + SDL_AudioStream* stream{}; +}; + +std::unique_ptr SDLAudioOut::Open(PortOut& port) { + return std::make_unique(port); } } // namespace Libraries::AudioOut diff --git a/src/core/libraries/audio/sdl_audio.h b/src/core/libraries/audio/sdl_audio.h deleted file mode 100644 index d55f2f6e3..000000000 --- a/src/core/libraries/audio/sdl_audio.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/libraries/audio/audioout_backend.h" - -namespace Libraries::AudioOut { - -class SDLAudioOut final : public AudioOutBackend { -public: - void* Open(bool is_float, int num_channels, u32 sample_rate) override; - void Close(void* impl) override; - void Output(void* impl, const void* ptr, size_t size) override; - void SetVolume(void* impl, std::array ch_volumes) override; -}; - -} // namespace Libraries::AudioOut diff --git a/src/core/libraries/fiber/fiber.cpp b/src/core/libraries/fiber/fiber.cpp index 7bb81b61e..b77b5b5b6 100644 --- a/src/core/libraries/fiber/fiber.cpp +++ b/src/core/libraries/fiber/fiber.cpp @@ -3,6 +3,7 @@ #include "fiber.h" +#include "common/elf_info.h" #include "common/logging/log.h" #include "core/libraries/fiber/fiber_error.h" #include "core/libraries/libs.h" @@ -41,6 +42,41 @@ void PS4_SYSV_ABI _sceFiberCheckStackOverflow(OrbisFiberContext* ctx) { } } +s32 PS4_SYSV_ABI _sceFiberAttachContext(OrbisFiber* fiber, void* addr_context, u64 size_context) { + if (size_context && size_context < ORBIS_FIBER_CONTEXT_MINIMUM_SIZE) { + return ORBIS_FIBER_ERROR_RANGE; + } + if (size_context & 15) { + return ORBIS_FIBER_ERROR_INVALID; + } + if (!addr_context || !size_context) { + return ORBIS_FIBER_ERROR_INVALID; + } + if (fiber->addr_context) { + return ORBIS_FIBER_ERROR_INVALID; + } + + fiber->addr_context = addr_context; + fiber->size_context = size_context; + fiber->context_start = addr_context; + fiber->context_end = reinterpret_cast(addr_context) + size_context; + + /* Apply signature to start of stack */ + *(u64*)addr_context = kFiberStackSignature; + + if (fiber->flags & FiberFlags::ContextSizeCheck) { + u64* stack_start = reinterpret_cast(fiber->context_start); + u64* stack_end = reinterpret_cast(fiber->context_end); + + u64* stack_ptr = stack_start + 1; + while (stack_ptr < stack_end) { + *stack_ptr++ = kFiberStackSizeCheck; + } + } + + return ORBIS_OK; +} + void PS4_SYSV_ABI _sceFiberSwitchToFiber(OrbisFiber* fiber, u64 arg_on_run_to, OrbisFiberContext* ctx) { OrbisFiberContext* fiber_ctx = fiber->context; @@ -62,8 +98,7 @@ void PS4_SYSV_ABI _sceFiberSwitchToFiber(OrbisFiber* fiber, u64 arg_on_run_to, data.entry = fiber->entry; data.arg_on_initialize = fiber->arg_on_initialize; data.arg_on_run_to = arg_on_run_to; - data.stack_addr = - reinterpret_cast(reinterpret_cast(fiber->addr_context) + fiber->size_context); + data.stack_addr = reinterpret_cast(fiber->addr_context) + fiber->size_context; if (fiber->flags & FiberFlags::SetFpuRegs) { data.fpucw = 0x037f; data.mxcsr = 0x9fc0; @@ -111,9 +146,10 @@ void PS4_SYSV_ABI _sceFiberTerminate(OrbisFiber* fiber, u64 arg_on_return, Orbis __builtin_trap(); } -s32 PS4_SYSV_ABI sceFiberInitialize(OrbisFiber* fiber, const char* name, OrbisFiberEntry entry, - u64 arg_on_initialize, void* addr_context, u64 size_context, - const OrbisFiberOptParam* opt_param, u32 build_ver) { +s32 PS4_SYSV_ABI sceFiberInitializeImpl(OrbisFiber* fiber, const char* name, OrbisFiberEntry entry, + u64 arg_on_initialize, void* addr_context, u64 size_context, + const OrbisFiberOptParam* opt_param, u32 flags, + u32 build_ver) { if (!fiber || !name || !entry) { return ORBIS_FIBER_ERROR_NULL; } @@ -139,12 +175,12 @@ s32 PS4_SYSV_ABI sceFiberInitialize(OrbisFiber* fiber, const char* name, OrbisFi return ORBIS_FIBER_ERROR_INVALID; } - u32 flags = FiberFlags::None; - if (build_ver >= 0x3500000) { - flags |= FiberFlags::SetFpuRegs; + u32 user_flags = flags; + if (build_ver >= Common::ElfInfo::FW_35) { + user_flags |= FiberFlags::SetFpuRegs; } if (context_size_check) { - flags |= FiberFlags::ContextSizeCheck; + user_flags |= FiberFlags::ContextSizeCheck; } strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH); @@ -154,7 +190,7 @@ s32 PS4_SYSV_ABI sceFiberInitialize(OrbisFiber* fiber, const char* name, OrbisFi fiber->addr_context = addr_context; fiber->size_context = size_context; fiber->context = nullptr; - fiber->flags = flags; + fiber->flags = user_flags; /* A low stack area is problematic, as we can easily @@ -169,8 +205,7 @@ s32 PS4_SYSV_ABI sceFiberInitialize(OrbisFiber* fiber, const char* name, OrbisFi if (addr_context != nullptr) { fiber->context_start = addr_context; - fiber->context_end = - reinterpret_cast(reinterpret_cast(addr_context) + size_context); + fiber->context_end = reinterpret_cast(addr_context) + size_context; /* Apply signature to start of stack */ *(u64*)addr_context = kFiberStackSignature; @@ -221,11 +256,12 @@ s32 PS4_SYSV_ABI sceFiberFinalize(OrbisFiber* fiber) { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFiberRun(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_on_return) { +s32 PS4_SYSV_ABI sceFiberRunImpl(OrbisFiber* fiber, void* addr_context, u64 size_context, + u64 arg_on_run_to, u64* arg_on_return) { if (!fiber) { return ORBIS_FIBER_ERROR_NULL; } - if ((u64)fiber & 7) { + if ((u64)fiber & 7 || (u64)addr_context & 15) { return ORBIS_FIBER_ERROR_ALIGNMENT; } if (fiber->magic_start != kFiberSignature0 || fiber->magic_end != kFiberSignature1) { @@ -237,6 +273,14 @@ s32 PS4_SYSV_ABI sceFiberRun(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_on_r return ORBIS_FIBER_ERROR_PERMISSION; } + /* Caller wants to attach context and run. */ + if (addr_context != nullptr || size_context != 0) { + s32 res = _sceFiberAttachContext(fiber, addr_context, size_context); + if (res < 0) { + return res; + } + } + FiberState expected = FiberState::Idle; if (!fiber->state.compare_exchange_strong(expected, FiberState::Run)) { return ORBIS_FIBER_ERROR_STATE; @@ -288,11 +332,12 @@ s32 PS4_SYSV_ABI sceFiberRun(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_on_r return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFiberSwitch(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_on_run) { +s32 PS4_SYSV_ABI sceFiberSwitchImpl(OrbisFiber* fiber, void* addr_context, u64 size_context, + u64 arg_on_run_to, u64* arg_on_run) { if (!fiber) { return ORBIS_FIBER_ERROR_NULL; } - if ((u64)fiber & 7) { + if ((u64)fiber & 7 || (u64)addr_context & 15) { return ORBIS_FIBER_ERROR_ALIGNMENT; } if (fiber->magic_start != kFiberSignature0 || fiber->magic_end != kFiberSignature1) { @@ -304,6 +349,14 @@ s32 PS4_SYSV_ABI sceFiberSwitch(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_o return ORBIS_FIBER_ERROR_PERMISSION; } + /* Caller wants to attach context and switch. */ + if (addr_context != nullptr || size_context != 0) { + s32 res = _sceFiberAttachContext(fiber, addr_context, size_context); + if (res < 0) { + return res; + } + } + FiberState expected = FiberState::Idle; if (!fiber->state.compare_exchange_strong(expected, FiberState::Run)) { return ORBIS_FIBER_ERROR_STATE; @@ -462,9 +515,39 @@ s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name) { return ORBIS_OK; } +s32 PS4_SYSV_ABI sceFiberGetThreadFramePointerAddress(u64* addr_frame_pointer) { + if (!addr_frame_pointer) { + return ORBIS_FIBER_ERROR_NULL; + } + + OrbisFiberContext* g_ctx = GetFiberContext(); + if (!g_ctx) { + return ORBIS_FIBER_ERROR_PERMISSION; + } + + *addr_frame_pointer = g_ctx->rbp; + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberInitialize(OrbisFiber* fiber, const char* name, OrbisFiberEntry entry, + u64 arg_on_initialize, void* addr_context, u64 size_context, + const OrbisFiberOptParam* opt_param, u32 build_ver) { + return sceFiberInitializeImpl(fiber, name, entry, arg_on_initialize, addr_context, size_context, + opt_param, 0, build_ver); +} + +s32 PS4_SYSV_ABI sceFiberRun(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_on_return) { + return sceFiberRunImpl(fiber, nullptr, 0, arg_on_run_to, arg_on_return); +} + +s32 PS4_SYSV_ABI sceFiberSwitch(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_on_run) { + return sceFiberSwitchImpl(fiber, nullptr, 0, arg_on_run_to, arg_on_run); +} + void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("hVYD7Ou2pCQ", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberInitialize); - LIB_FUNCTION("7+OJIpko9RY", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberInitialize); + LIB_FUNCTION("7+OJIpko9RY", "libSceFiber", 1, "libSceFiber", 1, 1, + sceFiberInitializeImpl); // _sceFiberInitializeWithInternalOptionImpl LIB_FUNCTION("asjUJJ+aa8s", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberOptParamInitialize); LIB_FUNCTION("JeNX5F-NzQU", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberFinalize); @@ -473,12 +556,20 @@ void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("p+zLIOg27zU", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberGetSelf); LIB_FUNCTION("B0ZX2hx9DMw", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberReturnToThread); + LIB_FUNCTION("avfGJ94g36Q", "libSceFiber", 1, "libSceFiber", 1, 1, + sceFiberRunImpl); // _sceFiberAttachContextAndRun + LIB_FUNCTION("ZqhZFuzKT6U", "libSceFiber", 1, "libSceFiber", 1, 1, + sceFiberSwitchImpl); // _sceFiberAttachContextAndSwitch + LIB_FUNCTION("uq2Y5BFz0PE", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberGetInfo); LIB_FUNCTION("Lcqty+QNWFc", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberStartContextSizeCheck); LIB_FUNCTION("Kj4nXMpnM8Y", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberStopContextSizeCheck); LIB_FUNCTION("JzyT91ucGDc", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberRename); + + LIB_FUNCTION("0dy4JtMUcMQ", "libSceFiber", 1, "libSceFiber", 1, 1, + sceFiberGetThreadFramePointerAddress); } } // namespace Libraries::Fiber diff --git a/src/core/libraries/fiber/fiber.h b/src/core/libraries/fiber/fiber.h index 3c4e3b70e..edcd9afe8 100644 --- a/src/core/libraries/fiber/fiber.h +++ b/src/core/libraries/fiber/fiber.h @@ -114,5 +114,7 @@ s32 PS4_SYSV_ABI sceFiberStopContextSizeCheck(void); s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name); +s32 PS4_SYSV_ABI sceFiberGetThreadFramePointerAddress(u64* addr_frame_pointer); + void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Fiber \ No newline at end of file diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 1a6007bf8..fdc3a1acd 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -12,6 +12,7 @@ #include "core/address_space.h" #include "core/debug_state.h" #include "core/libraries/gnmdriver/gnm_error.h" +#include "core/libraries/gnmdriver/gnmdriver_init.h" #include "core/libraries/kernel/orbis_error.h" #include "core/libraries/kernel/process.h" #include "core/libraries/libs.h" @@ -29,7 +30,7 @@ namespace Libraries::GnmDriver { using namespace AmdGpu; -enum GnmEventIdents : u64 { +enum GnmEventType : u64 { Compute0RelMem = 0x00, Compute1RelMem = 0x01, Compute2RelMem = 0x02, @@ -54,244 +55,11 @@ enum ShaderStages : u32 { static constexpr std::array indirect_sgpr_offsets{0u, 0u, 0x4cu, 0u, 0xccu, 0u, 0x14cu}; -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, - 0xc0016900u, 0x2f9u, 0x2du, - 0xc0016900u, 0x282u, 8u, - 0xc0016900u, 0x280u, 0x80008u, - 0xc0016900u, 0x281u, 0xffff0000u, - 0xc0016900u, 0x204u, 0u, - 0xc0016900u, 0x206u, 0x43fu, - 0xc0016900u, 0x83u, 0xffffu, - 0xc0016900u, 0x317u, 0x10u, - 0xc0016900u, 0x2fau, 0x3f800000u, - 0xc0016900u, 0x2fcu, 0x3f800000u, - 0xc0016900u, 0x2fbu, 0x3f800000u, - 0xc0016900u, 0x2fdu, 0x3f800000u, - 0xc0016900u, 0x202u, 0xcc0010u, - 0xc0016900u, 0x30eu, 0xffffffffu, - 0xc0016900u, 0x30fu, 0xffffffffu, - 0xc0002f00u, 1u, - 0xc0017600u, 7u, 0x1ffu, - 0xc0017600u, 0x46u, 0x1ffu, - 0xc0017600u, 0x87u, 0x1ffu, - 0xc0017600u, 0xc7u, 0x1ffu, - 0xc0017600u, 0x107u, 0u, - 0xc0017600u, 0x147u, 0x1ffu, - 0xc0016900u, 0x1b1u, 2u, - 0xc0016900u, 0x101u, 0u, - 0xc0016900u, 0x100u, 0xffffffffu, - 0xc0016900u, 0x103u, 0u, - 0xc0016900u, 0x284u, 0u, - 0xc0016900u, 0x290u, 0u, - 0xc0016900u, 0x2aeu, 0u, - 0xc0016900u, 0x292u, 0u, - 0xc0016900u, 0x293u, 0x6000000u, - 0xc0016900u, 0x2f8u, 0u, - 0xc0016900u, 0x2deu, 0x1e9u, - 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, - 0xc0017900u, 0x200u, 0xe0000000u, -}; -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, - 0xc0016900u, 0x2f9u, 0x2du, - 0xc0016900u, 0x282u, 8u, - 0xc0016900u, 0x280u, 0x80008u, - 0xc0016900u, 0x281u, 0xffff0000u, - 0xc0016900u, 0x204u, 0u, - 0xc0016900u, 0x206u, 0x43fu, - 0xc0016900u, 0x83u, 0xffffu, - 0xc0016900u, 0x317u, 0x10u, - 0xc0016900u, 0x2fau, 0x3f800000u, - 0xc0016900u, 0x2fcu, 0x3f800000u, - 0xc0016900u, 0x2fbu, 0x3f800000u, - 0xc0016900u, 0x2fdu, 0x3f800000u, - 0xc0016900u, 0x202u, 0xcc0010u, - 0xc0016900u, 0x30eu, 0xffffffffu, - 0xc0016900u, 0x30fu, 0xffffffffu, - 0xc0002f00u, 1u, - 0xc0017600u, 7u, 0x1ffu, - 0xc0017600u, 0x46u, 0x1ffu, - 0xc0017600u, 0x87u, 0x1ffu, - 0xc0017600u, 0xc7u, 0x1ffu, - 0xc0017600u, 0x107u, 0u, - 0xc0017600u, 0x147u, 0x1ffu, - 0xc0016900u, 0x1b1u, 2u, - 0xc0016900u, 0x101u, 0u, - 0xc0016900u, 0x100u, 0xffffffffu, - 0xc0016900u, 0x103u, 0u, - 0xc0016900u, 0x284u, 0u, - 0xc0016900u, 0x290u, 0u, - 0xc0016900u, 0x2aeu, 0u, - 0xc0016900u, 0x292u, 0u, - 0xc0016900u, 0x293u, 0x6020000u, - 0xc0016900u, 0x2f8u, 0u, - 0xc0016900u, 0x2deu, 0x1e9u, - 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, - 0xc0017900u, 0x200u, 0xe0000000u, -}; -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, - 0xc0016900u, 0x2f9u, 0x2du, - 0xc0016900u, 0x282u, 8u, - 0xc0016900u, 0x280u, 0x80008u, - 0xc0016900u, 0x281u, 0xffff0000u, - 0xc0016900u, 0x204u, 0u, - 0xc0016900u, 0x206u, 0x43fu, - 0xc0016900u, 0x83u, 0xffffu, - 0xc0016900u, 0x317u, 0x10u, - 0xc0016900u, 0x2fau, 0x3f800000u, - 0xc0016900u, 0x2fcu, 0x3f800000u, - 0xc0016900u, 0x2fbu, 0x3f800000u, - 0xc0016900u, 0x2fdu, 0x3f800000u, - 0xc0016900u, 0x202u, 0xcc0010u, - 0xc0016900u, 0x30eu, 0xffffffffu, - 0xc0016900u, 0x30fu, 0xffffffffu, - 0xc0002f00u, 1u, - 0xc0017600u, 7u, 0x1701ffu, - 0xc0017600u, 0x46u, 0x1701fdu, - 0xc0017600u, 0x87u, 0x1701ffu, - 0xc0017600u, 0xc7u, 0x1701fdu, - 0xc0017600u, 0x107u, 0x17u, - 0xc0017600u, 0x147u, 0x1701fdu, - 0xc0017600u, 0x47u, 0x1cu, - 0xc0016900u, 0x1b1u, 2u, - 0xc0016900u, 0x101u, 0u, - 0xc0016900u, 0x100u, 0xffffffffu, - 0xc0016900u, 0x103u, 0u, - 0xc0016900u, 0x284u, 0u, - 0xc0016900u, 0x290u, 0u, - 0xc0016900u, 0x2aeu, 0u, - 0xc0016900u, 0x292u, 0u, - 0xc0016900u, 0x293u, 0x6020000u, - 0xc0016900u, 0x2f8u, 0u, - 0xc0016900u, 0x2deu, 0x1e9u, - 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, - 0xc0017900u, 0x200u, 0xe0000000u, -}; -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, - 0xc0016900u, 0x2f9u, 0x2du, - 0xc0016900u, 0x282u, 8u, - 0xc0016900u, 0x280u, 0x80008u, - 0xc0016900u, 0x281u, 0xffff0000u, - 0xc0016900u, 0x204u, 0u, - 0xc0016900u, 0x206u, 0x43fu, - 0xc0016900u, 0x83u, 0xffffu, - 0xc0016900u, 0x317u, 0x10u, - 0xc0016900u, 0x2fau, 0x3f800000u, - 0xc0016900u, 0x2fcu, 0x3f800000u, - 0xc0016900u, 0x2fbu, 0x3f800000u, - 0xc0016900u, 0x2fdu, 0x3f800000u, - 0xc0016900u, 0x202u, 0xcc0010u, - 0xc0016900u, 0x30eu, 0xffffffffu, - 0xc0016900u, 0x30fu, 0xffffffffu, - 0xc0002f00u, 1u, - 0xc0017600u, 7u, 0x1701ffu, - 0xc0017600u, 0x46u, 0x1701fdu, - 0xc0017600u, 0x87u, 0x1701ffu, - 0xc0017600u, 0xc7u, 0x1701fdu, - 0xc0017600u, 0x107u, 0x17u, - 0xc0017600u, 0x147u, 0x1701fdu, - 0xc0017600u, 0x47u, 0x1cu, - 0xc0016900u, 0x1b1u, 2u, - 0xc0016900u, 0x101u, 0u, - 0xc0016900u, 0x100u, 0xffffffffu, - 0xc0016900u, 0x103u, 0u, - 0xc0016900u, 0x284u, 0u, - 0xc0016900u, 0x290u, 0u, - 0xc0016900u, 0x2aeu, 0u, - 0xc0016900u, 0x102u, 0u, - 0xc0016900u, 0x292u, 0u, - 0xc0016900u, 0x293u, 0x6020000u, - 0xc0016900u, 0x2f8u, 0u, - 0xc0016900u, 0x2deu, 0x1e9u, - 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, - 0xc0017900u, 0x200u, 0xe0000000u, - 0xc0016900u, 0x2aau, 0xffu, -}; -static_assert(InitSequence350.size() == 0x7c + 2); - -static constexpr std::array CtxInitSequence{ - 0xc0012800u, 0x80000000u, 0x80000000u, - 0xc0001200u, 0u, - 0xc0002f00u, 1u, - 0xc0016900u, 0x102u, 0u, - 0xc0016900u, 0x202u, 0xcc0010u, - 0xc0111000u, 0u -}; -static_assert(CtxInitSequence.size() == 0x0f); - -static constexpr std::array CtxInitSequence400{ - 0xc0012800u, 0x80000000u, 0x80000000u, - 0xc0001200u, 0u, - 0xc0016900u, 0x2f9u, 0x2du, - 0xc0016900u, 0x282u, 8u, - 0xc0016900u, 0x280u, 0x80008u, - 0xc0016900u, 0x281u, 0xffff0000u, - 0xc0016900u, 0x204u, 0u, - 0xc0016900u, 0x206u, 0x43fu, - 0xc0016900u, 0x83u, 0xffffu, - 0xc0016900u, 0x317u, 0x10u, - 0xc0016900u, 0x2fau, 0x3f800000u, - 0xc0016900u, 0x2fcu, 0x3f800000u, - 0xc0016900u, 0x2fbu, 0x3f800000u, - 0xc0016900u, 0x2fdu, 0x3f800000u, - 0xc0016900u, 0x202u, 0xcc0010u, - 0xc0016900u, 0x30eu, 0xffffffffu, - 0xc0016900u, 0x30fu, 0xffffffffu, - 0xc0002f00u, 1u, - 0xc0016900u, 0x1b1u, 2u, - 0xc0016900u, 0x101u, 0u, - 0xc0016900u, 0x100u, 0xffffffffu, - 0xc0016900u, 0x103u, 0u, - 0xc0016900u, 0x284u, 0u, - 0xc0016900u, 0x290u, 0u, - 0xc0016900u, 0x2aeu, 0u, - 0xc0016900u, 0x102u, 0u, - 0xc0016900u, 0x292u, 0u, - 0xc0016900u, 0x293u, 0x6020000u, - 0xc0016900u, 0x2f8u, 0u, - 0xc0016900u, 0x2deu, 0x1e9u, - 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, - 0xc0016900u, 0x2aau, 0xffu, - 0xc09e1000u, -}; -static_assert(CtxInitSequence400.size() == 0x61); -// clang-format on +// Gates use of what appear to be the neo-mode init sequences but with the older +// IA_MULTI_VGT_PARAM register address. No idea what this is for as the ioctl +// that controls it is still a mystery, but leaving the sequences in gated behind +// this flag in case we need it in the future. +static constexpr bool UseNeoCompatSequences = false; // In case if `submitDone` is issued we need to block submissions until GPU idle static u32 submission_lock{}; @@ -317,6 +85,14 @@ static void WaitGpuIdle() { cv_lock.wait(lock, [] { return submission_lock == 0; }); } +// Write a special ending NOP packet with N DWs data block +static inline u32* WriteTrailingNop(u32* cmdbuf, u32 data_block_size) { + auto* nop = reinterpret_cast(cmdbuf); + nop->header = PM4Type3Header{PM4ItOpcode::Nop, data_block_size - 1}; + nop->data_block[0] = 0u; // only one out of `data_block_size` is initialized + return cmdbuf + data_block_size + 1 /* header */; +} + // Write a special ending NOP packet with N DWs data block template static inline u32* WriteTrailingNop(u32* cmdbuf) { @@ -337,6 +113,12 @@ static inline u32* ClearContextState(u32* cmdbuf) { return cmdbuf + ClearStateSequence.size(); } +static inline bool IsValidEventType(Platform::InterruptId id) { + return (static_cast(id) >= static_cast(Platform::InterruptId::Compute0RelMem) && + static_cast(id) <= static_cast(Platform::InterruptId::Compute6RelMem)) || + static_cast(id) == static_cast(Platform::InterruptId::GfxEop); +} + s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) { LOG_TRACE(Lib_GnmDriver, "called"); @@ -347,8 +129,7 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) { EqueueEvent kernel_event{}; kernel_event.event.ident = id; kernel_event.event.filter = SceKernelEvent::Filter::GraphicsCore; - // The library only sets EV_ADD but it is suspected the kernel driver forces EV_CLEAR - kernel_event.event.flags = SceKernelEvent::Flags::Clear; + kernel_event.event.flags = SceKernelEvent::Flags::Add; kernel_event.event.fflags = 0; kernel_event.event.data = id; kernel_event.event.udata = udata; @@ -357,11 +138,15 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) { Platform::IrqC::Instance()->Register( static_cast(id), [=](Platform::InterruptId irq) { - ASSERT_MSG(irq == static_cast(id), - "An unexpected IRQ occured"); // We need to convert IRQ# to event id and do - // proper filtering in trigger function - eq->TriggerEvent(static_cast(id), SceKernelEvent::Filter::GraphicsCore, - nullptr); + ASSERT_MSG(irq == static_cast(id), "An unexpected IRQ occured"); + + // We need to convert IRQ# to event id + if (!IsValidEventType(irq)) + return; + + // Event data is expected to be an event type as per sceGnmGetEqEventType. + eq->TriggerEvent(static_cast(id), SceKernelEvent::Filter::GraphicsCore, + reinterpret_cast(id)); }, eq); return ORBIS_OK; @@ -476,7 +261,7 @@ s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) { return ORBIS_KERNEL_ERROR_EBADF; } - eq->RemoveEvent(id); + eq->RemoveEvent(id, SceKernelEvent::Filter::GraphicsCore); Platform::IrqC::Instance()->Unregister(static_cast(id), eq); return ORBIS_OK; @@ -504,10 +289,14 @@ void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) { auto vqid = gnm_vqid - 1; auto& asc_queue = liverpool->asc_queues[{vqid}]; - const auto& offs_dw = asc_next_offs_dw[vqid]; + auto& offs_dw = asc_next_offs_dw[vqid]; - if (next_offs_dw < offs_dw) { - ASSERT_MSG(next_offs_dw == 0, "ACB submission is split at the end of ring buffer"); + if (next_offs_dw < offs_dw && next_offs_dw != 0) { + // For cases if a submission is split at the end of the ring buffer, we need to submit it in + // two parts to handle the wrap + liverpool->SubmitAsc(gnm_vqid, {reinterpret_cast(asc_queue.map_addr) + offs_dw, + asc_queue.ring_size_dw - offs_dw}); + offs_dw = 0; } const auto* acb_ptr = reinterpret_cast(asc_queue.map_addr) + offs_dw; @@ -594,9 +383,16 @@ s32 PS4_SYSV_ABI sceGnmDispatchIndirect(u32* cmdbuf, u32 size, u32 data_offset, return -1; } -int PS4_SYSV_ABI sceGnmDispatchIndirectOnMec() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceGnmDispatchIndirectOnMec(u32* cmdbuf, u32 size, VAddr args, u32 modifier) { + if (cmdbuf != nullptr && size == 8 && args != 0 && ((args & 3u) == 0)) { + cmdbuf[0] = 0xc0021602 | (modifier & 1u); + *(VAddr*)(&cmdbuf[1]) = args; + cmdbuf[3] = (modifier & 0x18) | 1u; + cmdbuf[4] = 0xc0021000; + cmdbuf[5] = 0; + return ORBIS_OK; + } + return ORBIS_FAIL; } u32 PS4_SYSV_ABI sceGnmDispatchInitDefaultHardwareState(u32* cmdbuf, u32 size) { @@ -606,17 +402,30 @@ u32 PS4_SYSV_ABI sceGnmDispatchInitDefaultHardwareState(u32* cmdbuf, u32 size) { return 0; } - cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x216u, - 0xffffffffu); // COMPUTE_STATIC_THREAD_MGMT_SE0 - cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x217u, - 0xffffffffu); // COMPUTE_STATIC_THREAD_MGMT_SE1 - cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x215u, 0x170u); // COMPUTE_RESOURCE_LIMITS + cmdbuf = PM4CmdSetData::SetShReg( + cmdbuf, 0x216u, + 0xffffffffu); // COMPUTE_STATIC_THREAD_MGMT_SE0 + cmdbuf = PM4CmdSetData::SetShReg( + cmdbuf, 0x217u, + 0xffffffffu); // COMPUTE_STATIC_THREAD_MGMT_SE1 + + if (sceKernelIsNeoMode()) { + cmdbuf = PM4CmdSetData::SetShReg( + cmdbuf, 0x219u, + 0xffffffffu); // COMPUTE_STATIC_THREAD_MGMT_SE2 + cmdbuf = PM4CmdSetData::SetShReg( + cmdbuf, 0x21au, + 0xffffffffu); // COMPUTE_STATIC_THREAD_MGMT_SE3 + } + + cmdbuf = PM4CmdSetData::SetShReg( + cmdbuf, 0x215u, 0x170u); // COMPUTE_RESOURCE_LIMITS cmdbuf = WriteHeader(cmdbuf, 6); - cmdbuf = WriteBody(cmdbuf, 0x28000000u, 0u, 0u, 0u, 0u, 0u); + cmdbuf = WriteBody(cmdbuf, 0x28000000u, 0u, 0u, 0u, 0u, 0xau); - cmdbuf = WriteHeader(cmdbuf, 0xef); - cmdbuf = WriteBody(cmdbuf, 0xau, 0u); + cmdbuf = WriteHeader(cmdbuf, sceKernelIsNeoMode() ? 0xe9 : 0xef); + cmdbuf = WriteBody(cmdbuf, 0u); return HwInitPacketSize; } @@ -633,7 +442,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr draw_index->index_base_lo = u32(index_addr); draw_index->index_base_hi = u32(index_addr >> 32); draw_index->index_count = index_count; - draw_index->draw_initiator = 0; + draw_index->draw_initiator = sceKernelIsNeoMode() ? flags & 0xe0000000u : 0; WriteTrailingNop<3>(cmdbuf + 6); return ORBIS_OK; @@ -646,8 +455,9 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 if (cmdbuf && (size == 7) && (flags & 0x1ffffffe) == 0) { // no predication will be set in the packet - cmdbuf = WritePacket(cmdbuf, PM4ShaderType::ShaderGraphics, - index_count, 2u); + cmdbuf = WritePacket( + cmdbuf, PM4ShaderType::ShaderGraphics, index_count, + sceKernelIsNeoMode() ? flags & 0xe0000000u | 2u : 2u); WriteTrailingNop<3>(cmdbuf); return ORBIS_OK; } @@ -671,7 +481,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_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset; - cmdbuf[3] = 0; + cmdbuf[3] = sceKernelIsNeoMode() ? flags & 0xe0000000u : 0u; cmdbuf += 4; WriteTrailingNop<3>(cmdbuf); @@ -686,8 +496,9 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(u32* cmdbuf, u32 size, u32 da u32 flags) { LOG_TRACE(Lib_GnmDriver, "called"); - if (cmdbuf && (size == 16) && (shader_stage < ShaderStages::Max) && - (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) { + if ((!sceKernelIsNeoMode() || !UseNeoCompatSequences) && !cmdbuf && (size == 16) && + (shader_stage < ShaderStages::Max) && (vertex_sgpr_offset < 0x10u) && + (instance_sgpr_offset < 0x10u)) { cmdbuf = WriteHeader(cmdbuf, 2); cmdbuf = WriteBody(cmdbuf, 0u); @@ -706,7 +517,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(u32* cmdbuf, u32 size, u32 da cmdbuf[4] = max_count; *(u64*)(&cmdbuf[5]) = count_addr; cmdbuf[7] = sizeof(DrawIndexedIndirectArgs); - cmdbuf[8] = 0; + cmdbuf[8] = sceKernelIsNeoMode() ? flags & 0xe0000000u : 0; cmdbuf += 9; WriteTrailingNop<2>(cmdbuf); @@ -735,7 +546,8 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; cmdbuf = WriteHeader( cmdbuf, 4, PM4ShaderType::ShaderGraphics, predicate); - cmdbuf = WriteBody(cmdbuf, index_count, index_offset, index_count, 0u); + cmdbuf = WriteBody(cmdbuf, index_count, index_offset, index_count, + sceKernelIsNeoMode() ? flags & 0xe0000000u : 0u); WriteTrailingNop<3>(cmdbuf); return ORBIS_OK; @@ -759,7 +571,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_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset; - cmdbuf[3] = 2; // auto index + cmdbuf[3] = sceKernelIsNeoMode() ? flags & 0xe0000000u | 2u : 2u; // auto index cmdbuf += 4; WriteTrailingNop<3>(cmdbuf); @@ -788,6 +600,7 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size) { } const auto& SetupContext = [](u32* cmdbuf, u32 size, bool clear_state) { + const auto* cmdbuf_end = cmdbuf + HwInitPacketSize; if (clear_state) { cmdbuf = ClearContextState(cmdbuf); } @@ -795,10 +608,8 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size) { std::memcpy(cmdbuf, &InitSequence[2], (InitSequence.size() - 2) * 4); cmdbuf += InitSequence.size() - 2; - const auto cmdbuf_left = - HwInitPacketSize - (InitSequence.size() - 2) - (clear_state ? 0xc : 0) - 1; - cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); - cmdbuf = WriteBody(cmdbuf, 0u); + const auto cmdbuf_left = cmdbuf_end - cmdbuf - 1; + WriteTrailingNop(cmdbuf, cmdbuf_left); return HwInitPacketSize; }; @@ -813,12 +624,13 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState175(u32* cmdbuf, u32 size) { return 0; } + const auto* cmdbuf_end = cmdbuf + HwInitPacketSize; cmdbuf = ClearContextState(cmdbuf); std::memcpy(cmdbuf, &InitSequence175[2], (InitSequence175.size() - 2) * 4); cmdbuf += InitSequence175.size() - 2; - constexpr auto cmdbuf_left = HwInitPacketSize - (InitSequence175.size() - 2) - 0xc - 1; - WriteTrailingNop(cmdbuf); + const auto cmdbuf_left = cmdbuf_end - cmdbuf - 1; + WriteTrailingNop(cmdbuf, cmdbuf_left); return HwInitPacketSize; } @@ -831,17 +643,27 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState200(u32* cmdbuf, u32 size) { } const auto& SetupContext200 = [](u32* cmdbuf, u32 size, bool clear_state) { + const auto* cmdbuf_end = cmdbuf + HwInitPacketSize; if (clear_state) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, &InitSequence200[2], (InitSequence200.size() - 2) * 4); - cmdbuf += InitSequence200.size() - 2; + if (sceKernelIsNeoMode()) { + if (!UseNeoCompatSequences) { + std::memcpy(cmdbuf, &InitSequence200Neo[2], (InitSequence200Neo.size() - 2) * 4); + cmdbuf += InitSequence200Neo.size() - 2; + } else { + std::memcpy(cmdbuf, &InitSequence200NeoCompat[2], + (InitSequence200NeoCompat.size() - 2) * 4); + cmdbuf += InitSequence200NeoCompat.size() - 2; + } + } else { + std::memcpy(cmdbuf, &InitSequence200[2], (InitSequence200.size() - 2) * 4); + cmdbuf += InitSequence200.size() - 2; + } - const auto cmdbuf_left = - HwInitPacketSize - (InitSequence200.size() - 2) - (clear_state ? 0xc : 0) - 1; - cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); - cmdbuf = WriteBody(cmdbuf, 0u); + const auto cmdbuf_left = cmdbuf_end - cmdbuf - 1; + WriteTrailingNop(cmdbuf, cmdbuf_left); return HwInitPacketSize; }; @@ -857,17 +679,27 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState350(u32* cmdbuf, u32 size) { } const auto& SetupContext350 = [](u32* cmdbuf, u32 size, bool clear_state) { + const auto* cmdbuf_end = cmdbuf + HwInitPacketSize; if (clear_state) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, &InitSequence350[2], (InitSequence350.size() - 2) * 4); - cmdbuf += InitSequence350.size() - 2; + if (sceKernelIsNeoMode()) { + if (!UseNeoCompatSequences) { + std::memcpy(cmdbuf, &InitSequence350Neo[2], (InitSequence350Neo.size() - 2) * 4); + cmdbuf += InitSequence350Neo.size() - 2; + } else { + std::memcpy(cmdbuf, &InitSequence350NeoCompat[2], + (InitSequence350NeoCompat.size() - 2) * 4); + cmdbuf += InitSequence350NeoCompat.size() - 2; + } + } else { + std::memcpy(cmdbuf, &InitSequence350[2], (InitSequence350.size() - 2) * 4); + cmdbuf += InitSequence350.size() - 2; + } - const auto cmdbuf_left = - HwInitPacketSize - (InitSequence350.size() - 2) - (clear_state ? 0xc : 0) - 1; - cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); - cmdbuf = WriteBody(cmdbuf, 0u); + const auto cmdbuf_left = cmdbuf_end - cmdbuf - 1; + WriteTrailingNop(cmdbuf, cmdbuf_left); return HwInitPacketSize; }; @@ -883,7 +715,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitToDefaultContextState(u32* cmdbuf, u32 size) { return 0; } - std::memcpy(cmdbuf, CtxInitSequence.data(), CtxInitSequence.size() * 4); + if (sceKernelIsNeoMode()) { + std::memcpy(cmdbuf, CtxInitSequenceNeo.data(), CtxInitSequenceNeo.size() * 4); + } else { + std::memcpy(cmdbuf, CtxInitSequence.data(), CtxInitSequence.size() * 4); + } return CtxInitPacketSize; } @@ -895,7 +731,16 @@ u32 PS4_SYSV_ABI sceGnmDrawInitToDefaultContextState400(u32* cmdbuf, u32 size) { return 0; } - std::memcpy(cmdbuf, CtxInitSequence400.data(), CtxInitSequence400.size() * 4); + if (sceKernelIsNeoMode()) { + if (!UseNeoCompatSequences) { + std::memcpy(cmdbuf, CtxInitSequence400Neo.data(), CtxInitSequence400Neo.size() * 4); + } else { + std::memcpy(cmdbuf, CtxInitSequence400NeoCompat.data(), + CtxInitSequence400NeoCompat.size() * 4); + } + } else { + std::memcpy(cmdbuf, CtxInitSequence400.data(), CtxInitSequence400.size() * 4); + } return CtxInitPacketSize; } @@ -1000,9 +845,9 @@ int PS4_SYSV_ABI sceGnmGetDebugTimestamp() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmGetEqEventType() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceGnmGetEqEventType(const SceKernelEvent* ev) { + LOG_TRACE(Lib_GnmDriver, "called"); + return sceKernelGetEventData(ev); } int PS4_SYSV_ABI sceGnmGetEqTimeStamp() { @@ -1017,7 +862,8 @@ int PS4_SYSV_ABI sceGnmGetGpuBlockStatus() { u32 PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency() { LOG_TRACE(Lib_GnmDriver, "called"); - return Config::isNeoMode() ? 911'000'000 : 800'000'000; + // On console this uses an ioctl check, but we assume it is equal to just checking for neo mode. + return sceKernelIsNeoMode() ? 911'000'000 : 800'000'000; } int PS4_SYSV_ABI sceGnmGetGpuInfoStatus() { @@ -1356,7 +1202,15 @@ s32 PS4_SYSV_ABI sceGnmResetVgtControl(u32* cmdbuf, u32 size) { if (cmdbuf == nullptr || size != 3) { return -1; } - PM4CmdSetData::SetContextReg(cmdbuf, 0x2aau, 0xffu); // IA_MULTI_VGT_PARAM + if (sceKernelIsNeoMode()) { + if (!UseNeoCompatSequences) { + PM4CmdSetData::SetUconfigReg(cmdbuf, 0x40000258u, 0x6d007fu); // IA_MULTI_VGT_PARAM + } else { + PM4CmdSetData::SetContextReg(cmdbuf, 0x100002aau, 0xd00ffu); // IA_MULTI_VGT_PARAM + } + } else { + PM4CmdSetData::SetContextReg(cmdbuf, 0x2aau, 0xffu); // IA_MULTI_VGT_PARAM + } return ORBIS_OK; } @@ -1817,9 +1671,25 @@ s32 PS4_SYSV_ABI sceGnmSetVgtControl(u32* cmdbuf, u32 size, u32 prim_group_sz_mi return -1; } - const u32 reg_value = - ((partial_vs_wave_mode & 1) << 0x10) | (prim_group_sz_minus_one & 0xffffu); - PM4CmdSetData::SetContextReg(cmdbuf, 0x2aau, reg_value); // IA_MULTI_VGT_PARAM + if (sceKernelIsNeoMode()) { + const u32 wd_switch_on_eop = u32(wd_switch_only_on_eop_mode != 0) << 0x14; + const u32 switch_on_eoi = u32(wd_switch_only_on_eop_mode == 0) << 0x13; + const u32 reg_value = + wd_switch_only_on_eop_mode != 0 + ? (partial_vs_wave_mode & 1) << 0x10 | prim_group_sz_minus_one | wd_switch_on_eop | + switch_on_eoi | 0x40000u + : prim_group_sz_minus_one & 0x1cffffu | wd_switch_on_eop | switch_on_eoi | 0x50000u; + if (!UseNeoCompatSequences) { + PM4CmdSetData::SetUconfigReg(cmdbuf, 0x40000258u, + reg_value | 0x600000u); // IA_MULTI_VGT_PARAM + } else { + PM4CmdSetData::SetContextReg(cmdbuf, 0x100002aau, reg_value); // IA_MULTI_VGT_PARAM + } + } else { + const u32 reg_value = + ((partial_vs_wave_mode & 1) << 0x10) | (prim_group_sz_minus_one & 0xffffu); + PM4CmdSetData::SetContextReg(cmdbuf, 0x2aau, reg_value); // IA_MULTI_VGT_PARAM + } return ORBIS_OK; } @@ -2202,9 +2072,25 @@ int PS4_SYSV_ABI sceGnmSubmitCommandBuffersForWorkload(u32 workload, u32 count, if (sdk_version <= 0x1ffffffu) { liverpool->SubmitGfx(InitSequence, {}); } else if (sdk_version <= 0x3ffffffu) { - liverpool->SubmitGfx(InitSequence200, {}); + if (sceKernelIsNeoMode()) { + if (!UseNeoCompatSequences) { + liverpool->SubmitGfx(InitSequence200Neo, {}); + } else { + liverpool->SubmitGfx(InitSequence200NeoCompat, {}); + } + } else { + liverpool->SubmitGfx(InitSequence200, {}); + } } else { - liverpool->SubmitGfx(InitSequence350, {}); + if (sceKernelIsNeoMode()) { + if (!UseNeoCompatSequences) { + liverpool->SubmitGfx(InitSequence350Neo, {}); + } else { + liverpool->SubmitGfx(InitSequence350NeoCompat, {}); + } + } else { + liverpool->SubmitGfx(InitSequence350, {}); + } } send_init_packet = false; } diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 017dbe3ad..609e26c0d 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -39,7 +39,7 @@ int PS4_SYSV_ABI sceGnmDisableMipStatsReport(); s32 PS4_SYSV_ABI sceGnmDispatchDirect(u32* cmdbuf, u32 size, u32 threads_x, u32 threads_y, u32 threads_z, u32 flags); s32 PS4_SYSV_ABI sceGnmDispatchIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 flags); -int PS4_SYSV_ABI sceGnmDispatchIndirectOnMec(); +s32 PS4_SYSV_ABI sceGnmDispatchIndirectOnMec(u32* cmdbuf, u32 size, VAddr args, u32 modifier); u32 PS4_SYSV_ABI sceGnmDispatchInitDefaultHardwareState(u32* cmdbuf, u32 size); s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr_t index_addr, u32 flags, u32 type); @@ -85,7 +85,7 @@ int PS4_SYSV_ABI sceGnmGetCoredumpMode(); int PS4_SYSV_ABI sceGnmGetCoredumpProtectionFaultTimestamp(); int PS4_SYSV_ABI sceGnmGetDbgGcHandle(); int PS4_SYSV_ABI sceGnmGetDebugTimestamp(); -int PS4_SYSV_ABI sceGnmGetEqEventType(); +int PS4_SYSV_ABI sceGnmGetEqEventType(const SceKernelEvent* ev); int PS4_SYSV_ABI sceGnmGetEqTimeStamp(); int PS4_SYSV_ABI sceGnmGetGpuBlockStatus(); u32 PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency(); diff --git a/src/core/libraries/gnmdriver/gnmdriver_init.h b/src/core/libraries/gnmdriver/gnmdriver_init.h new file mode 100644 index 000000000..da6d65f32 --- /dev/null +++ b/src/core/libraries/gnmdriver/gnmdriver_init.h @@ -0,0 +1,542 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +namespace Libraries::GnmDriver { + +constexpr auto HwInitPacketSize = 0x100u; + +// clang-format off +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, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1ffu, + 0xc0017600u, 0x46u, 0x1ffu, + 0xc0017600u, 0x87u, 0x1ffu, + 0xc0017600u, 0xc7u, 0x1ffu, + 0xc0017600u, 0x107u, 0u, + 0xc0017600u, 0x147u, 0x1ffu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6000000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, +}; +static_assert(InitSequence.size() == 0x73 + 2); + +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, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1ffu, + 0xc0017600u, 0x46u, 0x1ffu, + 0xc0017600u, 0x87u, 0x1ffu, + 0xc0017600u, 0xc7u, 0x1ffu, + 0xc0017600u, 0x107u, 0u, + 0xc0017600u, 0x147u, 0x1ffu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, +}; +static_assert(InitSequence175.size() == 0x73 + 2); + +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, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1701ffu, + 0xc0017600u, 0x46u, 0x1701fdu, + 0xc0017600u, 0x87u, 0x1701ffu, + 0xc0017600u, 0xc7u, 0x1701fdu, + 0xc0017600u, 0x107u, 0x17u, + 0xc0017600u, 0x147u, 0x1701fdu, + 0xc0017600u, 0x47u, 0x1cu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, +}; +static_assert(InitSequence200.size() == 0x76 + 2); + +constexpr std::array InitSequence200Neo{ + // 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, 0x219u, 0xffffffffu, + 0xc0017600u, 0x21au, 0xffffffffu, + 0xc0017600u, 0x215u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1701ffu, + 0xc0017600u, 0x46u, 0x1701fdu, + 0xc0017600u, 0x87u, 0x1701ffu, + 0xc0017600u, 0xc7u, 0x1701fdu, + 0xc0017600u, 0x107u, 0x17u, + 0xc0017600u, 0x147u, 0x1701fdu, + 0xc0017600u, 0x47u, 0x1cu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, + 0xc0017900u, 0x40000258u, 0x6d007fu, +}; +static_assert(InitSequence200Neo.size() == 0x83 + 2); + +constexpr std::array InitSequence200NeoCompat{ + // 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, 0x219u, 0xffffffffu, + 0xc0017600u, 0x21au, 0xffffffffu, + 0xc0017600u, 0x215u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1701ffu, + 0xc0017600u, 0x46u, 0x1701fdu, + 0xc0017600u, 0x87u, 0x1701ffu, + 0xc0017600u, 0xc7u, 0x1701fdu, + 0xc0017600u, 0x107u, 0x17u, + 0xc0017600u, 0x147u, 0x1701fdu, + 0xc0017600u, 0x47u, 0x1cu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, + 0xc0016900u, 0x100002aau, 0xd00ffu, +}; +static_assert(InitSequence200NeoCompat.size() == 0x83 + 2); + +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, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1701ffu, + 0xc0017600u, 0x46u, 0x1701fdu, + 0xc0017600u, 0x87u, 0x1701ffu, + 0xc0017600u, 0xc7u, 0x1701fdu, + 0xc0017600u, 0x107u, 0x17u, + 0xc0017600u, 0x147u, 0x1701fdu, + 0xc0017600u, 0x47u, 0x1cu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, + 0xc0016900u, 0x2aau, 0xffu, +}; +static_assert(InitSequence350.size() == 0x7c + 2); + +constexpr std::array InitSequence350Neo{ + // 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, 0x219u, 0xffffffffu, + 0xc0017600u, 0x21au, 0xffffffffu, + 0xc0017600u, 0x215u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1701ffu, + 0xc0017600u, 0x46u, 0x1701fdu, + 0xc0017600u, 0x87u, 0x1701ffu, + 0xc0017600u, 0xc7u, 0x1701fdu, + 0xc0017600u, 0x107u, 0x17u, + 0xc0017600u, 0x147u, 0x1701fdu, + 0xc0017600u, 0x47u, 0x1cu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, + 0xc0017900u, 0x40000258u, 0x6d007fu, +}; +static_assert(InitSequence350Neo.size() == 0x86 + 2); + +constexpr std::array InitSequence350NeoCompat{ + // 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, 0x219u, 0xffffffffu, + 0xc0017600u, 0x21au, 0xffffffffu, + 0xc0017600u, 0x215u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0017600u, 7u, 0x1701ffu, + 0xc0017600u, 0x46u, 0x1701fdu, + 0xc0017600u, 0x87u, 0x1701ffu, + 0xc0017600u, 0xc7u, 0x1701fdu, + 0xc0017600u, 0x107u, 0x17u, + 0xc0017600u, 0x147u, 0x1701fdu, + 0xc0017600u, 0x47u, 0x1cu, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x200u, 0xe0000000u, + 0xc0016900u, 0x100002aau, 0xd00ffu, +}; +static_assert(InitSequence350NeoCompat.size() == 0x86 + 2); + +constexpr std::array CtxInitSequence{ + 0xc0012800u, 0x80000000u, 0x80000000u, + 0xc0001200u, 0u, + 0xc0002f00u, 1u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0111000u, 0u +}; +static_assert(CtxInitSequence.size() == 0x0f); + +constexpr std::array CtxInitSequenceNeo{ + 0xc0012800u, 0x80000000u, 0x80000000u, + 0xc0001200u, 0u, + 0xc0002f00u, 1u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc00d1000, 0u +}; +static_assert(CtxInitSequenceNeo.size() == 0x13); + +constexpr std::array CtxInitSequence400{ + 0xc0012800u, 0x80000000u, 0x80000000u, + 0xc0001200u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0016900u, 0x2aau, 0xffu, + 0xc09e1000u, +}; +static_assert(CtxInitSequence400.size() == 0x61); + +constexpr std::array CtxInitSequence400Neo{ + 0xc0012800u, 0x80000000u, 0x80000000u, + 0xc0001200u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0017900u, 0x40000258u, 0x6d007fu, + 0xc09a1000u, +}; +static_assert(CtxInitSequence400Neo.size() == 0x65); + +constexpr std::array CtxInitSequence400NeoCompat{ + 0xc0012800u, 0x80000000u, 0x80000000u, + 0xc0001200u, 0u, + 0xc0016900u, 0x2f9u, 0x2du, + 0xc0016900u, 0x282u, 8u, + 0xc0016900u, 0x280u, 0x80008u, + 0xc0016900u, 0x281u, 0xffff0000u, + 0xc0016900u, 0x204u, 0u, + 0xc0016900u, 0x206u, 0x43fu, + 0xc0016900u, 0x83u, 0xffffu, + 0xc0016900u, 0x317u, 0x10u, + 0xc0016900u, 0x2fau, 0x3f800000u, + 0xc0016900u, 0x2fcu, 0x3f800000u, + 0xc0016900u, 0x2fbu, 0x3f800000u, + 0xc0016900u, 0x2fdu, 0x3f800000u, + 0xc0016900u, 0x202u, 0xcc0010u, + 0xc0016900u, 0x30eu, 0xffffffffu, + 0xc0016900u, 0x30fu, 0xffffffffu, + 0xc0002f00u, 1u, + 0xc0016900u, 0x1b1u, 2u, + 0xc0016900u, 0x101u, 0u, + 0xc0016900u, 0x100u, 0xffffffffu, + 0xc0016900u, 0x103u, 0u, + 0xc0016900u, 0x284u, 0u, + 0xc0016900u, 0x290u, 0u, + 0xc0016900u, 0x2aeu, 0u, + 0xc0016900u, 0x102u, 0u, + 0xc0016900u, 0x292u, 0u, + 0xc0016900u, 0x293u, 0x6020000u, + 0xc0016900u, 0x2f8u, 0u, + 0xc0016900u, 0x2deu, 0x1e9u, + 0xc0026900u, 0xebu, 0xff00ff00u, 0xff00u, + 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, + 0xc0016900u, 0x100002aau, 0xd00ffu, + 0xc09a1000u, +}; +static_assert(CtxInitSequence400Neo.size() == 0x65); +// clang-format on + +} // namespace Libraries::GnmDriver diff --git a/src/core/libraries/kernel/equeue.cpp b/src/core/libraries/kernel/equeue.cpp index 42a8eed89..64d4966c0 100644 --- a/src/core/libraries/kernel/equeue.cpp +++ b/src/core/libraries/kernel/equeue.cpp @@ -12,6 +12,8 @@ namespace Libraries::Kernel { +// Events are uniquely identified by id and filter. + bool EqueueInternal::AddEvent(EqueueEvent& event) { std::scoped_lock lock{m_mutex}; @@ -27,12 +29,13 @@ bool EqueueInternal::AddEvent(EqueueEvent& event) { return true; } -bool EqueueInternal::RemoveEvent(u64 id) { +bool EqueueInternal::RemoveEvent(u64 id, s16 filter) { bool has_found = false; std::scoped_lock lock{m_mutex}; - const auto& it = - std::ranges::find_if(m_events, [id](auto& ev) { return ev.event.ident == id; }); + const auto& it = std::ranges::find_if(m_events, [id, filter](auto& ev) { + return ev.event.ident == id && ev.event.filter == filter; + }); if (it != m_events.cend()) { m_events.erase(it); has_found = true; @@ -68,7 +71,7 @@ int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) { if (ev->flags & SceKernelEvent::Flags::OneShot) { for (auto ev_id = 0u; ev_id < count; ++ev_id) { - RemoveEvent(ev->ident); + RemoveEvent(ev->ident, ev->filter); } } @@ -94,8 +97,11 @@ int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) { int count = 0; for (auto& event : m_events) { if (event.IsTriggered()) { + // Event should not trigger again + event.ResetTriggerState(); + if (event.event.flags & SceKernelEvent::Flags::Clear) { - event.Reset(); + event.Clear(); } ev[count++] = event.event; if (count == num) { @@ -277,6 +283,19 @@ s32 PS4_SYSV_ABI sceKernelAddHRTimerEvent(SceKernelEqueue eq, int id, timespec* return ORBIS_OK; } +int PS4_SYSV_ABI sceKernelDeleteHRTimerEvent(SceKernelEqueue eq, int id) { + if (eq == nullptr) { + return ORBIS_KERNEL_ERROR_EBADF; + } + + if (eq->HasSmallTimer()) { + return eq->RemoveSmallTimer(id) ? ORBIS_OK : ORBIS_KERNEL_ERROR_ENOENT; + } else { + return eq->RemoveEvent(id, SceKernelEvent::Filter::HrTimer) ? ORBIS_OK + : ORBIS_KERNEL_ERROR_ENOENT; + } +} + int PS4_SYSV_ABI sceKernelAddUserEvent(SceKernelEqueue eq, int id) { if (eq == nullptr) { return ORBIS_KERNEL_ERROR_EBADF; @@ -334,16 +353,20 @@ int PS4_SYSV_ABI sceKernelDeleteUserEvent(SceKernelEqueue eq, int id) { return ORBIS_KERNEL_ERROR_EBADF; } - if (!eq->RemoveEvent(id)) { + if (!eq->RemoveEvent(id, SceKernelEvent::Filter::User)) { return ORBIS_KERNEL_ERROR_ENOENT; } return ORBIS_OK; } -s16 PS4_SYSV_ABI sceKernelGetEventFilter(const SceKernelEvent* ev) { +int PS4_SYSV_ABI sceKernelGetEventFilter(const SceKernelEvent* ev) { return ev->filter; } +u64 PS4_SYSV_ABI sceKernelGetEventData(const SceKernelEvent* ev) { + return ev->data; +} + void RegisterEventQueue(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue); LIB_FUNCTION("jpFjmgAC5AE", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteEqueue); @@ -352,10 +375,12 @@ void RegisterEventQueue(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("4R6-OvI2cEA", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEvent); LIB_FUNCTION("WDszmSbWuDk", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEventEdge); LIB_FUNCTION("R74tt43xP6k", "libkernel", 1, "libkernel", 1, 1, sceKernelAddHRTimerEvent); + LIB_FUNCTION("J+LF6LwObXU", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteHRTimerEvent); LIB_FUNCTION("F6e0kwo4cnk", "libkernel", 1, "libkernel", 1, 1, sceKernelTriggerUserEvent); LIB_FUNCTION("LJDwdSNTnDg", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteUserEvent); LIB_FUNCTION("mJ7aghmgvfc", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventId); LIB_FUNCTION("23CPPI1tyBY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventFilter); + LIB_FUNCTION("kwGyyjohI50", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventData); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/equeue.h b/src/core/libraries/kernel/equeue.h index 5a13bdecd..2db5e6ca7 100644 --- a/src/core/libraries/kernel/equeue.h +++ b/src/core/libraries/kernel/equeue.h @@ -66,8 +66,11 @@ struct EqueueEvent { std::chrono::steady_clock::time_point time_added; std::unique_ptr timer; - void Reset() { + void ResetTriggerState() { is_triggered = false; + } + + void Clear() { event.fflags = 0; event.data = 0; } @@ -83,7 +86,7 @@ struct EqueueEvent { } bool operator==(const EqueueEvent& ev) const { - return ev.event.ident == event.ident; + return ev.event.ident == event.ident && ev.event.filter == event.filter; } private: @@ -99,7 +102,7 @@ public: } bool AddEvent(EqueueEvent& event); - bool RemoveEvent(u64 id); + bool RemoveEvent(u64 id, s16 filter); int WaitForEvents(SceKernelEvent* ev, int num, u32 micros); bool TriggerEvent(u64 ident, s16 filter, void* trigger_data); int GetTriggeredEvents(SceKernelEvent* ev, int num); @@ -108,6 +111,13 @@ public: bool HasSmallTimer() const { return small_timer_event.event.data != 0; } + bool RemoveSmallTimer(u64 id) { + if (HasSmallTimer() && small_timer_event.event.ident == id) { + small_timer_event = {}; + return true; + } + return false; + } int WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros); @@ -122,6 +132,8 @@ private: using SceKernelUseconds = u32; using SceKernelEqueue = EqueueInternal*; +u64 PS4_SYSV_ABI sceKernelGetEventData(const SceKernelEvent* ev); + void RegisterEventQueue(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 57efbb631..2eb5d1621 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -46,17 +46,6 @@ static std::map available_device = { namespace Libraries::Kernel { -auto GetDirectoryEntries(const std::filesystem::path& path) { - std::vector files; - for (const auto& entry : std::filesystem::directory_iterator(path)) { - auto& dir_entry = files.emplace_back(); - dir_entry.name = entry.path().filename().string(); - dir_entry.isFile = !std::filesystem::is_directory(entry.path().string()); - } - - return files; -} - int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) { LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", raw_path, flags, mode); auto* h = Common::Singleton::Instance(); @@ -115,7 +104,12 @@ int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) { if (create) { return handle; // dir already exists } else { - file->dirents = GetDirectoryEntries(file->m_host_name); + mnt->IterateDirectory(file->m_guest_name, + [&file](const auto& ent_path, const auto ent_is_file) { + auto& dir_entry = file->dirents.emplace_back(); + dir_entry.name = ent_path.filename().string(); + dir_entry.isFile = ent_is_file; + }); file->dirents_index = 0; } } @@ -695,66 +689,12 @@ static int GetDents(int fd, char* buf, int nbytes, s64* basep) { return sizeof(OrbisKernelDirent); } -static int HandleSeparateUpdateDents(int fd, char* buf, int nbytes, s64* basep) { - int dir_entries = 0; - - auto* h = Common::Singleton::Instance(); - auto* mnt = Common::Singleton::Instance(); - auto* file = h->GetFile(fd); - auto update_dir_name = std::string{fmt::UTF(file->m_host_name.u8string()).data}; - auto mount = mnt->GetMountFromHostPath(update_dir_name); - auto suffix = std::string{fmt::UTF(mount->host_path.u8string()).data}; - - size_t pos = update_dir_name.find("-UPDATE"); - if (pos != std::string::npos) { - update_dir_name.erase(pos, 7); - auto guest_name = mount->mount + "/" + update_dir_name.substr(suffix.size() + 1); - int descriptor; - - auto existent_folder = h->GetFile(update_dir_name); - if (!existent_folder) { - u32 handle = h->CreateHandle(); - auto* new_file = h->GetFile(handle); - new_file->type = Core::FileSys::FileType::Directory; - new_file->m_guest_name = guest_name; - new_file->m_host_name = update_dir_name; - if (!std::filesystem::is_directory(new_file->m_host_name)) { - h->DeleteHandle(handle); - return dir_entries; - } else { - new_file->dirents = GetDirectoryEntries(new_file->m_host_name); - new_file->dirents_index = 0; - } - new_file->is_opened = true; - descriptor = h->GetFileDescriptor(new_file); - } else { - descriptor = h->GetFileDescriptor(existent_folder); - } - - dir_entries = GetDents(descriptor, buf, nbytes, basep); - if (dir_entries == ORBIS_OK && existent_folder) { - existent_folder->dirents_index = 0; - file->dirents_index = 0; - } - } - - return dir_entries; -} - int PS4_SYSV_ABI sceKernelGetdents(int fd, char* buf, int nbytes) { - int a = GetDents(fd, buf, nbytes, nullptr); - if (a == ORBIS_OK) { - return HandleSeparateUpdateDents(fd, buf, nbytes, nullptr); - } - return a; + return GetDents(fd, buf, nbytes, nullptr); } int PS4_SYSV_ABI sceKernelGetdirentries(int fd, char* buf, int nbytes, s64* basep) { - int a = GetDents(fd, buf, nbytes, basep); - if (a == ORBIS_OK) { - return HandleSeparateUpdateDents(fd, buf, nbytes, basep); - } - return a; + return GetDents(fd, buf, nbytes, basep); } s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset) { diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 7d326cbbf..8deefb496 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -505,6 +505,41 @@ int PS4_SYSV_ABI posix_munmap(void* addr, size_t len) { return result; } +static constexpr int MAX_PRT_APERTURES = 3; +static constexpr VAddr PRT_AREA_START_ADDR = 0x1000000000; +static constexpr size_t PRT_AREA_SIZE = 0xec00000000; +static std::array, MAX_PRT_APERTURES> PrtApertures{}; + +int PS4_SYSV_ABI sceKernelSetPrtAperture(int id, VAddr address, size_t size) { + if (id < 0 || id >= MAX_PRT_APERTURES) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + if (address < PRT_AREA_START_ADDR || address + size > PRT_AREA_START_ADDR + PRT_AREA_SIZE) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + if (address % 4096 != 0) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + LOG_WARNING(Kernel_Vmm, + "PRT aperture id = {}, address = {:#x}, size = {:#x} is set but not used", id, + address, size); + + PrtApertures[id] = {address, size}; + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceKernelGetPrtAperture(int id, VAddr* address, size_t* size) { + if (id < 0 || id >= MAX_PRT_APERTURES) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + std::tie(*address, *size) = PrtApertures[id]; + return ORBIS_OK; +} + void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1, sceKernelAllocateDirectMemory); LIB_FUNCTION("B+vc2AO2Zrc", "libkernel", 1, "libkernel", 1, 1, @@ -551,6 +586,10 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("BPE9s9vQQXo", "libScePosix", 1, "libkernel", 1, 1, posix_mmap); LIB_FUNCTION("UqDGjXA5yUM", "libkernel", 1, "libkernel", 1, 1, posix_munmap); LIB_FUNCTION("UqDGjXA5yUM", "libScePosix", 1, "libkernel", 1, 1, posix_munmap); + + // PRT memory management + LIB_FUNCTION("BohYr-F7-is", "libkernel", 1, "libkernel", 1, 1, sceKernelSetPrtAperture); + LIB_FUNCTION("L0v2Go5jOuM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetPrtAperture); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index 2d19ceb49..400b6c3fc 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -6,9 +6,11 @@ #include "common/bit_field.h" #include "common/types.h" -constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB -// TODO: Confirm this value on hardware. -constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE_PRO = 5568_MB; // ~ 5.5GB +constexpr u64 SCE_KERNEL_TOTAL_MEM = 5248_MB; +constexpr u64 SCE_KERNEL_TOTAL_MEM_PRO = 5888_MB; + +constexpr u64 SCE_FLEXIBLE_MEMORY_BASE = 64_MB; +constexpr u64 SCE_FLEXIBLE_MEMORY_SIZE = 512_MB; namespace Core::Loader { class SymbolsResolver; @@ -129,10 +131,6 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags); int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); -void* Malloc(size_t size); - -void Free(void* ptr); - void RegisterMemory(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/process.cpp b/src/core/libraries/kernel/process.cpp index 97cc01ebc..c21257c50 100644 --- a/src/core/libraries/kernel/process.cpp +++ b/src/core/libraries/kernel/process.cpp @@ -14,7 +14,8 @@ namespace Libraries::Kernel { int PS4_SYSV_ABI sceKernelIsNeoMode() { LOG_DEBUG(Kernel_Sce, "called"); - return Config::isNeoMode(); + return Config::isNeoModeConsole() && + Common::ElfInfo::Instance().GetPSFAttributes().support_neo_mode; } int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver) { diff --git a/src/core/libraries/kernel/threads.h b/src/core/libraries/kernel/threads.h index ad1393599..409136968 100644 --- a/src/core/libraries/kernel/threads.h +++ b/src/core/libraries/kernel/threads.h @@ -55,6 +55,9 @@ public: stop.request_stop(); Join(); } + thread = nullptr; + func = nullptr; + stop = std::stop_source{}; } static void* PS4_SYSV_ABI RunWrapper(void* arg) { diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index 610e61238..e81207a0d 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -244,10 +244,9 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAtt new_thread->tid = ++TidCounter; if (new_thread->attr.stackaddr_attr == 0) { - /* Enforce minimum stack size of 64 KB */ - static constexpr size_t MinimumStack = 64_KB; - auto& stacksize = new_thread->attr.stacksize_attr; - stacksize = std::max(stacksize, MinimumStack); + /* Add additional stack space for HLE */ + static constexpr size_t AdditionalStack = 128_KB; + new_thread->attr.stacksize_attr += AdditionalStack; } if (thread_state->CreateStack(&new_thread->attr) != 0) { diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 66cdd5b87..69728e523 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -18,6 +18,8 @@ #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libpng/pngdec.h" #include "core/libraries/libs.h" +#include "core/libraries/mouse/mouse.h" +#include "core/libraries/move/move.h" #include "core/libraries/network/http.h" #include "core/libraries/network/net.h" #include "core/libraries/network/netctl.h" @@ -46,6 +48,8 @@ #include "core/libraries/videodec/videodec.h" #include "core/libraries/videodec/videodec2.h" #include "core/libraries/videoout/video_out.h" +#include "fiber/fiber.h" +#include "jpeg/jpegenc.h" namespace Libraries { @@ -91,6 +95,10 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::Remoteplay::RegisterlibSceRemoteplay(sym); Libraries::Videodec::RegisterlibSceVideodec(sym); Libraries::RazorCpu::RegisterlibSceRazorCpu(sym); + Libraries::Move::RegisterlibSceMove(sym); + Libraries::Fiber::RegisterlibSceFiber(sym); + Libraries::JpegEnc::RegisterlibSceJpegEnc(sym); + Libraries::Mouse::RegisterlibSceMouse(sym); } } // namespace Libraries diff --git a/src/core/libraries/mouse/mouse.cpp b/src/core/libraries/mouse/mouse.cpp new file mode 100644 index 000000000..dffd2346c --- /dev/null +++ b/src/core/libraries/mouse/mouse.cpp @@ -0,0 +1,99 @@ +// 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" +#include "mouse.h" + +namespace Libraries::Mouse { + +int PS4_SYSV_ABI sceMouseClose() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseConnectPort() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseDebugGetDeviceId() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseDeviceOpen() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseDisconnectDevice() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseDisconnectPort() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseGetDeviceInfo() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseInit() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseMbusInit() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseOpen() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseRead() { + LOG_DEBUG(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseSetHandType() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseSetPointerSpeed() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMouseSetProcessPrivilege() { + LOG_ERROR(Lib_Mouse, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceMouse(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("cAnT0Rw-IwU", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseClose); + LIB_FUNCTION("Ymyy1HSSJLQ", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseConnectPort); + LIB_FUNCTION("BRXOoXQtb+k", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseDebugGetDeviceId); + LIB_FUNCTION("WiGKINCZWkc", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseDeviceOpen); + LIB_FUNCTION("eDQTFHbgeTU", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseDisconnectDevice); + LIB_FUNCTION("jJP1vYMEPd4", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseDisconnectPort); + LIB_FUNCTION("QA9Qupz3Zjw", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseGetDeviceInfo); + LIB_FUNCTION("Qs0wWulgl7U", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseInit); + LIB_FUNCTION("1FeceR5YhAo", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseMbusInit); + LIB_FUNCTION("RaqxZIf6DvE", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseOpen); + LIB_FUNCTION("x8qnXqh-tiM", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseRead); + LIB_FUNCTION("crkFfp-cmFo", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseSetHandType); + LIB_FUNCTION("ghLUU2Z5Lcg", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseSetPointerSpeed); + LIB_FUNCTION("6aANndpS0Wo", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseSetProcessPrivilege); +}; + +} // namespace Libraries::Mouse \ No newline at end of file diff --git a/src/core/libraries/mouse/mouse.h b/src/core/libraries/mouse/mouse.h new file mode 100644 index 000000000..8264f62e0 --- /dev/null +++ b/src/core/libraries/mouse/mouse.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Mouse { + +int PS4_SYSV_ABI sceMouseClose(); +int PS4_SYSV_ABI sceMouseConnectPort(); +int PS4_SYSV_ABI sceMouseDebugGetDeviceId(); +int PS4_SYSV_ABI sceMouseDeviceOpen(); +int PS4_SYSV_ABI sceMouseDisconnectDevice(); +int PS4_SYSV_ABI sceMouseDisconnectPort(); +int PS4_SYSV_ABI sceMouseGetDeviceInfo(); +int PS4_SYSV_ABI sceMouseInit(); +int PS4_SYSV_ABI sceMouseMbusInit(); +int PS4_SYSV_ABI sceMouseOpen(); +int PS4_SYSV_ABI sceMouseRead(); +int PS4_SYSV_ABI sceMouseSetHandType(); +int PS4_SYSV_ABI sceMouseSetPointerSpeed(); +int PS4_SYSV_ABI sceMouseSetProcessPrivilege(); + +void RegisterlibSceMouse(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Mouse \ No newline at end of file diff --git a/src/core/libraries/move/move.cpp b/src/core/libraries/move/move.cpp new file mode 100644 index 000000000..626fed9b4 --- /dev/null +++ b/src/core/libraries/move/move.cpp @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "move.h" + +namespace Libraries::Move { + +int PS4_SYSV_ABI sceMoveOpen() { + LOG_ERROR(Lib_Move, "(STUBBED) called"); + return ORBIS_FAIL; +} + +int PS4_SYSV_ABI sceMoveGetDeviceInfo() { + LOG_ERROR(Lib_Move, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMoveReadStateRecent() { + LOG_TRACE(Lib_Move, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMoveTerm() { + LOG_ERROR(Lib_Move, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceMoveInit() { + LOG_ERROR(Lib_Move, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceMove(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("HzC60MfjJxU", "libSceMove", 1, "libSceMove", 1, 1, sceMoveOpen); + LIB_FUNCTION("GWXTyxs4QbE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveGetDeviceInfo); + LIB_FUNCTION("f2bcpK6kJfg", "libSceMove", 1, "libSceMove", 1, 1, sceMoveReadStateRecent); + LIB_FUNCTION("tsZi60H4ypY", "libSceMove", 1, "libSceMove", 1, 1, sceMoveTerm); + LIB_FUNCTION("j1ITE-EoJmE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveInit); +}; + +} // namespace Libraries::Move \ No newline at end of file diff --git a/src/core/libraries/move/move.h b/src/core/libraries/move/move.h new file mode 100644 index 000000000..2d7adaba7 --- /dev/null +++ b/src/core/libraries/move/move.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Move { + +int PS4_SYSV_ABI sceMoveOpen(); +int PS4_SYSV_ABI sceMoveGetDeviceInfo(); +int PS4_SYSV_ABI sceMoveReadStateRecent(); +int PS4_SYSV_ABI sceMoveTerm(); +int PS4_SYSV_ABI sceMoveInit(); + +void RegisterlibSceMove(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Move \ No newline at end of file diff --git a/src/core/libraries/np_manager/np_manager.cpp b/src/core/libraries/np_manager/np_manager.cpp index ec9cc6bf5..87d752c69 100644 --- a/src/core/libraries/np_manager/np_manager.cpp +++ b/src/core/libraries/np_manager/np_manager.cpp @@ -972,11 +972,8 @@ int PS4_SYSV_ABI sceNpGetGamePresenceStatusA() { } int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) { - LOG_INFO(Lib_NpManager, "user_id {}", user_id); - const auto name = Config::getUserName(); - std::memset(np_id, 0, sizeof(OrbisNpId)); - name.copy(np_id->handle.data, sizeof(np_id->handle.data)); - return ORBIS_OK; + LOG_DEBUG(Lib_NpManager, "user_id {}", user_id); + return ORBIS_NP_ERROR_SIGNED_OUT; } int PS4_SYSV_ABI sceNpGetNpReachabilityState() { @@ -986,10 +983,7 @@ int PS4_SYSV_ABI sceNpGetNpReachabilityState() { int PS4_SYSV_ABI sceNpGetOnlineId(s32 user_id, OrbisNpOnlineId* online_id) { LOG_DEBUG(Lib_NpManager, "user_id {}", user_id); - const auto name = Config::getUserName(); - std::memset(online_id, 0, sizeof(OrbisNpOnlineId)); - name.copy(online_id->data, sizeof(online_id->data)); - return ORBIS_OK; + return ORBIS_NP_ERROR_SIGNED_OUT; } int PS4_SYSV_ABI sceNpGetParentalControlInfo() { diff --git a/src/core/libraries/np_trophy/np_trophy.cpp b/src/core/libraries/np_trophy/np_trophy.cpp index 9324ed6bb..ccd8ab710 100644 --- a/src/core/libraries/np_trophy/np_trophy.cpp +++ b/src/core/libraries/np_trophy/np_trophy.cpp @@ -498,7 +498,7 @@ int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(OrbisNpTrophyContext context, OrbisNpT s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyFlagArray* flags, u32* count) { - LOG_INFO(Lib_NpTrophy, "GetTrophyUnlockState called"); + LOG_INFO(Lib_NpTrophy, "called"); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; @@ -519,8 +519,9 @@ s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context, pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); if (!result) { - LOG_ERROR(Lib_NpTrophy, "Failed to open trophy xml : {}", result.description()); - return -1; + LOG_ERROR(Lib_NpTrophy, "Failed to open trophy XML: {}", result.description()); + *count = 0; + return ORBIS_OK; } int num_trophies = 0; diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index 98f086dd9..7eb628a90 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -286,6 +286,7 @@ int PS4_SYSV_ABI scePadOutputReport() { } int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { + LOG_TRACE(Lib_Pad, "called"); int connected_count = 0; bool connected = false; Input::State states[64]; @@ -304,16 +305,15 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { pData[i].rightStick.y = states[i].axes[static_cast(Input::Axis::RightY)]; pData[i].analogButtons.l2 = states[i].axes[static_cast(Input::Axis::TriggerLeft)]; pData[i].analogButtons.r2 = states[i].axes[static_cast(Input::Axis::TriggerRight)]; - pData[i].orientation.x = 0.0f; - pData[i].orientation.y = 0.0f; - pData[i].orientation.z = 0.0f; - pData[i].orientation.w = 1.0f; - pData[i].acceleration.x = 0.0f; - pData[i].acceleration.y = 0.0f; - pData[i].acceleration.z = 0.0f; - pData[i].angularVelocity.x = 0.0f; - pData[i].angularVelocity.y = 0.0f; - pData[i].angularVelocity.z = 0.0f; + pData[i].acceleration.x = states[i].acceleration.x; + pData[i].acceleration.y = states[i].acceleration.y; + pData[i].acceleration.z = states[i].acceleration.z; + pData[i].angularVelocity.x = states[i].angularVelocity.x; + pData[i].angularVelocity.y = states[i].angularVelocity.y; + pData[i].angularVelocity.z = states[i].angularVelocity.z; + Input::GameController::CalculateOrientation(pData[i].acceleration, pData[i].angularVelocity, + 1.0f / controller->accel_poll_rate, + pData[i].orientation); 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; @@ -352,6 +352,7 @@ int PS4_SYSV_ABI scePadReadHistory() { } int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) { + LOG_TRACE(Lib_Pad, "called"); if (handle == ORBIS_PAD_ERROR_DEVICE_NO_HANDLE) { return ORBIS_PAD_ERROR_INVALID_HANDLE; } @@ -367,16 +368,15 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) { pData->rightStick.y = state.axes[static_cast(Input::Axis::RightY)]; pData->analogButtons.l2 = state.axes[static_cast(Input::Axis::TriggerLeft)]; pData->analogButtons.r2 = state.axes[static_cast(Input::Axis::TriggerRight)]; - pData->orientation.x = 0; - pData->orientation.y = 0; - pData->orientation.z = 0; - pData->orientation.w = 1; - pData->acceleration.x = 0.0f; - pData->acceleration.y = 0.0f; - pData->acceleration.z = 0.0f; - pData->angularVelocity.x = 0.0f; - pData->angularVelocity.y = 0.0f; - pData->angularVelocity.z = 0.0f; + pData->acceleration.x = state.acceleration.x; + pData->acceleration.y = state.acceleration.y; + pData->acceleration.z = state.acceleration.z; + pData->angularVelocity.x = state.angularVelocity.x; + pData->angularVelocity.y = state.angularVelocity.y; + pData->angularVelocity.z = state.angularVelocity.z; + Input::GameController::CalculateOrientation(pData->acceleration, pData->angularVelocity, + 1.0f / controller->accel_poll_rate, + pData->orientation); pData->touchData.touchNum = (state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0); pData->touchData.touch[0].x = state.touchpad[0].x; @@ -498,6 +498,8 @@ int PS4_SYSV_ABI scePadSetLoginUserNumber() { int PS4_SYSV_ABI scePadSetMotionSensorState(s32 handle, bool bEnable) { LOG_ERROR(Lib_Pad, "(STUBBED) called"); return ORBIS_OK; + // it's already handled by the SDL backend and will be on no matter what + // (assuming the controller supports it) } int PS4_SYSV_ABI scePadSetProcessFocus() { diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp index 848533ff7..ade2ee496 100644 --- a/src/core/libraries/playgo/playgo.cpp +++ b/src/core/libraries/playgo/playgo.cpp @@ -157,7 +157,7 @@ s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoCh } for (int i = 0; i < numberOfEntries; i++) { - if (chunkIds[i] <= playgo->chunks.size()) { + if (chunkIds[i] < playgo->chunks.size()) { outLoci[i] = OrbisPlayGoLocus::LocalFast; } else { outLoci[i] = OrbisPlayGoLocus::NotDownloaded; diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 66899fb34..b573ded1e 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include @@ -1139,10 +1140,6 @@ Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getPar LOG_INFO(Lib_SaveData, "called without save memory initialized"); return Error::MEMORY_NOT_READY; } - if (SaveMemory::IsSaving()) { - LOG_TRACE(Lib_SaveData, "called while saving"); - return Error::BUSY_FOR_SAVING; - } LOG_DEBUG(Lib_SaveData, "called"); auto data = getParam->data; if (data != nullptr) { @@ -1502,8 +1499,14 @@ Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* return Error::MEMORY_NOT_READY; } if (SaveMemory::IsSaving()) { - LOG_TRACE(Lib_SaveData, "called while saving"); - return Error::BUSY_FOR_SAVING; + int count = 0; + while (++count < 100 && SaveMemory::IsSaving()) { // try for more 10 seconds + std::this_thread::sleep_for(chrono::milliseconds(100)); + } + if (SaveMemory::IsSaving()) { + LOG_TRACE(Lib_SaveData, "called while saving"); + return Error::BUSY_FOR_SAVING; + } } LOG_DEBUG(Lib_SaveData, "called"); auto data = setParam->data; @@ -1584,8 +1587,8 @@ Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetu } else { SaveMemory::SetIcon(nullptr, 0); } + SaveMemory::TriggerSaveWithoutEvent(); } - SaveMemory::TriggerSaveWithoutEvent(); if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) { result->existedMemorySize = existed_size; } diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index c0e1b7ea8..fdfa50b23 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -10,327 +10,327 @@ namespace Libraries::Usbd { int PS4_SYSV_ABI sceUsbdAllocTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdAttachKernelDriver() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdBulkTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdCancelTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdCheckConnected() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdClaimInterface() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdClearHalt() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdClose() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdControlTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdControlTransferGetData() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdDetachKernelDriver() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdEventHandlerActive() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdEventHandlingOk() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdExit() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillBulkTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillControlSetup() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillControlTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillIsoTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFreeDeviceList() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFreeTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetBusNumber() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetConfiguration() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceAddress() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceList() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetStringDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdHandleEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdHandleEventsLocked() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdHandleEventsTimeout() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_DEBUG(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdInit() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return 0x80240005; // Skip } int PS4_SYSV_ABI sceUsbdInterruptTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdKernelDriverActive() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdLockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdLockEventWaiters() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdOpen() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdRefDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdReleaseInterface() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdResetDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSetConfiguration() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSubmitTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdTryLockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdUnlockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdUnrefDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdWaitForEvent() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_65F6EF33E38FFF50() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_97F056BAD90AADE7() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_C55104A33B35B264() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_D56B43060720B1E0() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } diff --git a/src/core/libraries/videoout/video_out.cpp b/src/core/libraries/videoout/video_out.cpp index f36de6ade..78a2b11a4 100644 --- a/src/core/libraries/videoout/video_out.cpp +++ b/src/core/libraries/videoout/video_out.cpp @@ -52,8 +52,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Kernel::SceKernelEqueue eq, s32 handle, Kernel::EqueueEvent event{}; event.event.ident = u64(OrbisVideoOutEventId::Flip); event.event.filter = Kernel::SceKernelEvent::Filter::VideoOut; - // The library only sets EV_ADD but kernel driver forces EV_CLEAR - event.event.flags = Kernel::SceKernelEvent::Flags::Clear; + event.event.flags = Kernel::SceKernelEvent::Flags::Add; event.event.udata = udata; event.event.fflags = 0; event.event.data = 0; @@ -79,8 +78,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddVblankEvent(Kernel::SceKernelEqueue eq, s32 handl Kernel::EqueueEvent event{}; event.event.ident = u64(OrbisVideoOutEventId::Vblank); event.event.filter = Kernel::SceKernelEvent::Filter::VideoOut; - // The library only sets EV_ADD but kernel driver forces EV_CLEAR - event.event.flags = Kernel::SceKernelEvent::Flags::Clear; + event.event.flags = Kernel::SceKernelEvent::Flags::Add; event.event.udata = udata; event.event.fflags = 0; event.event.data = 0; diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 9cf4198ae..28d2eea7b 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -5,6 +5,7 @@ #include "common/arch.h" #include "common/assert.h" #include "common/config.h" +#include "common/elf_info.h" #include "common/logging/log.h" #include "common/path_util.h" #include "common/string_util.h" @@ -65,21 +66,41 @@ void Linker::Execute() { Relocate(m.get()); } - // Configure used flexible memory 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); - } + // Configure the direct and flexible memory regions. + u64 fmem_size = SCE_FLEXIBLE_MEMORY_SIZE; + bool use_extended_mem1 = true, use_extended_mem2 = true; + + const auto* proc_param = GetProcParam(); + ASSERT(proc_param); + + Core::OrbisKernelMemParam mem_param{}; + if (proc_param->size >= offsetof(OrbisProcParam, mem_param) + sizeof(OrbisKernelMemParam*)) { + if (proc_param->mem_param) { + 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) { + fmem_size = *flexible_size + SCE_FLEXIBLE_MEMORY_BASE; } } } } + if (mem_param.size < offsetof(OrbisKernelMemParam, extended_memory_1) + sizeof(u64*)) { + mem_param.extended_memory_1 = nullptr; + } + if (mem_param.size < offsetof(OrbisKernelMemParam, extended_memory_2) + sizeof(u64*)) { + mem_param.extended_memory_2 = nullptr; + } + + const u64 sdk_ver = proc_param->sdk_version; + if (sdk_ver < Common::ElfInfo::FW_50) { + use_extended_mem1 = mem_param.extended_memory_1 ? *mem_param.extended_memory_1 : false; + use_extended_mem2 = mem_param.extended_memory_2 ? *mem_param.extended_memory_2 : false; + } + + memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2); + main_thread.Run([this, module](std::stop_token) { Common::SetCurrentThreadName("GAME_MainThread"); LoadSharedLibraries(); diff --git a/src/core/linker.h b/src/core/linker.h index d6b5d648a..7ef13ae56 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -22,8 +22,9 @@ struct OrbisKernelMemParam { u8* extended_memory_1; u64* extended_gpu_page_table; u8* extended_memory_2; - u64* exnteded_cpu_page_table; + u64* extended_cpu_page_table; }; +static_assert(sizeof(OrbisKernelMemParam) == 0x38); struct OrbisProcParam { u64 size; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 41db7df4b..619941000 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -7,17 +7,13 @@ #include "common/debug.h" #include "core/libraries/kernel/memory.h" #include "core/libraries/kernel/orbis_error.h" +#include "core/libraries/kernel/process.h" #include "core/memory.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" namespace Core { -constexpr u64 SCE_DEFAULT_FLEXIBLE_MEMORY_SIZE = 448_MB; - MemoryManager::MemoryManager() { - // 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(); const size_t system_managed_size = impl.SystemManagedVirtualSize(); @@ -38,10 +34,17 @@ MemoryManager::MemoryManager() { MemoryManager::~MemoryManager() = default; -void MemoryManager::SetupMemoryRegions(u64 flexible_size) { - const auto total_size = - Config::isNeoMode() ? SCE_KERNEL_MAIN_DMEM_SIZE_PRO : SCE_KERNEL_MAIN_DMEM_SIZE; - total_flexible_size = flexible_size; +void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, + bool use_extended_mem2) { + const bool is_neo = ::Libraries::Kernel::sceKernelIsNeoMode(); + auto total_size = is_neo ? SCE_KERNEL_TOTAL_MEM_PRO : SCE_KERNEL_TOTAL_MEM; + if (!use_extended_mem1 && is_neo) { + total_size -= 256_MB; + } + if (!use_extended_mem2 && !is_neo) { + total_size -= 128_MB; + } + total_flexible_size = flexible_size - SCE_FLEXIBLE_MEMORY_BASE; total_direct_size = total_size - flexible_size; // Insert an area that covers direct memory physical block. @@ -101,13 +104,17 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, auto dmem_area = FindDmemArea(search_start); const auto is_suitable = [&] { + if (dmem_area == dmem_map.end()) { + return false; + } const auto aligned_base = Common::AlignUp(dmem_area->second.base, alignment); 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) { + while (dmem_area != dmem_map.end() && !is_suitable() && + dmem_area->second.GetEnd() <= search_end) { ++dmem_area; } ASSERT_MSG(is_suitable(), "Unable to find free direct memory area: size = {:#x}", size); @@ -164,10 +171,11 @@ int MemoryManager::PoolReserve(void** out_addr, VAddr virtual_addr, size_t size, // Fixed mapping means the virtual address must exactly match the provided one. if (True(flags & MemoryMapFlags::Fixed)) { - const auto& vma = FindVMA(mapped_addr)->second; + auto& vma = FindVMA(mapped_addr)->second; // If the VMA is mapped, unmap the region first. if (vma.IsMapped()) { UnmapMemoryImpl(mapped_addr, size); + vma = FindVMA(mapped_addr)->second; } const size_t remaining_size = vma.base + vma.size - mapped_addr; ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size); @@ -201,10 +209,11 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem // Fixed mapping means the virtual address must exactly match the provided one. if (True(flags & MemoryMapFlags::Fixed)) { - const auto& vma = FindVMA(mapped_addr)->second; + auto& vma = FindVMA(mapped_addr)->second; // If the VMA is mapped, unmap the region first. if (vma.IsMapped()) { UnmapMemoryImpl(mapped_addr, size); + vma = FindVMA(mapped_addr)->second; } const size_t remaining_size = vma.base + vma.size - mapped_addr; ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size); @@ -386,14 +395,18 @@ s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) { ASSERT_MSG(vma_base.Contains(virtual_addr, size), "Existing mapping does not contain requested unmap range"); + const auto type = vma_base.type; + if (type == VMAType::Free) { + return ORBIS_OK; + } + const auto vma_base_addr = vma_base.base; const auto vma_base_size = vma_base.size; const auto phys_base = vma_base.phys_base; const bool is_exec = vma_base.is_exec; const auto start_in_vma = virtual_addr - vma_base_addr; - const auto type = vma_base.type; const bool has_backing = type == VMAType::Direct || type == VMAType::File; - if (type == VMAType::Direct) { + if (type == VMAType::Direct || type == VMAType::Pooled) { rasterizer->UnmapMemory(virtual_addr, size); } if (type == VMAType::Flexible) { @@ -411,10 +424,12 @@ s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) { MergeAdjacent(vma_map, new_it); 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_file); - TRACK_FREE(virtual_addr, "VMEM"); + if (type != VMAType::Reserved && type != VMAType::PoolReserved) { + // 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_file); + TRACK_FREE(virtual_addr, "VMEM"); + } return ORBIS_OK; } diff --git a/src/core/memory.h b/src/core/memory.h index a9f2df322..615ecc3eb 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -166,7 +166,7 @@ public: bool TryWriteBacking(void* address, const void* data, u32 num_bytes); - void SetupMemoryRegions(u64 flexible_size); + void SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, bool use_extended_mem2); PAddr PoolExpand(PAddr search_start, PAddr search_end, size_t size, u64 alignment); diff --git a/src/emulator.cpp b/src/emulator.cpp index 252a34418..dbe693340 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -28,8 +28,6 @@ #include "core/file_format/trp.h" #include "core/file_sys/fs.h" #include "core/libraries/disc_map/disc_map.h" -#include "core/libraries/fiber/fiber.h" -#include "core/libraries/jpeg/jpegenc.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/ngs2/ngs2.h" @@ -45,10 +43,6 @@ Frontend::WindowSDL* g_window = nullptr; namespace Core { Emulator::Emulator() { - // Read configuration file. - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); - Config::load(config_dir / "config.toml"); - // Initialize NT API functions and set high priority #ifdef _WIN32 Common::NtApi::Initialize(); @@ -63,8 +57,8 @@ Emulator::Emulator() { LOG_INFO(Loader, "Branch {}", Common::g_scm_branch); LOG_INFO(Loader, "Description {}", Common::g_scm_desc); - LOG_INFO(Config, "General Logtype: {}", Config::getLogType()); - LOG_INFO(Config, "General isNeo: {}", Config::isNeoMode()); + LOG_INFO(Config, "General LogType: {}", Config::getLogType()); + LOG_INFO(Config, "General isNeo: {}", Config::isNeoModeConsole()); LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu()); LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders()); LOG_INFO(Config, "GPU vblankDivider: {}", Config::vblankDiv()); @@ -105,19 +99,12 @@ Emulator::~Emulator() { } void Emulator::Run(const std::filesystem::path& file) { - - // Use the eboot from the separated updates folder if it's there - std::filesystem::path game_patch_folder = file.parent_path(); - game_patch_folder += "-UPDATE"; - std::filesystem::path eboot_path = std::filesystem::exists(game_patch_folder / file.filename()) - ? game_patch_folder / file.filename() - : 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"); + const auto game_folder = file.parent_path(); + mnt->Mount(game_folder, "/app0"); // Certain games may use /hostapp as well such as CUSA001100 - mnt->Mount(file.parent_path(), "/hostapp"); + mnt->Mount(game_folder, "/hostapp"); auto& game_info = Common::ElfInfo::Instance(); @@ -126,50 +113,52 @@ void Emulator::Run(const std::filesystem::path& file) { std::string title; std::string app_version; u32 fw_version; + Common::PSFAttributes psf_attributes{}; - std::filesystem::path sce_sys_folder = eboot_path.parent_path() / "sce_sys"; - if (std::filesystem::is_directory(sce_sys_folder)) { - for (const auto& entry : std::filesystem::directory_iterator(sce_sys_folder)) { - if (entry.path().filename() == "param.sfo") { - auto* param_sfo = Common::Singleton::Instance(); - const bool success = param_sfo->Open(sce_sys_folder / "param.sfo"); - ASSERT_MSG(success, "Failed to open param.sfo"); - const auto content_id = param_sfo->GetString("CONTENT_ID"); - ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID"); - id = std::string(*content_id, 7, 9); - Libraries::NpTrophy::game_serial = id; - const auto trophyDir = - Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles"; - if (!std::filesystem::exists(trophyDir)) { - TRP trp; - if (!trp.Extract(eboot_path.parent_path(), id)) { - LOG_ERROR(Loader, "Couldn't extract trophies"); - } - } + const auto param_sfo_path = mnt->GetHostPath("/app0/sce_sys/param.sfo"); + if (std::filesystem::exists(param_sfo_path)) { + auto* param_sfo = Common::Singleton::Instance(); + const bool success = param_sfo->Open(param_sfo_path); + ASSERT_MSG(success, "Failed to open param.sfo"); + const auto content_id = param_sfo->GetString("CONTENT_ID"); + ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID"); + id = std::string(*content_id, 7, 9); + Libraries::NpTrophy::game_serial = id; + const auto trophyDir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles"; + if (!std::filesystem::exists(trophyDir)) { + TRP trp; + if (!trp.Extract(game_folder, id)) { + LOG_ERROR(Loader, "Couldn't extract trophies"); + } + } #ifdef ENABLE_QT_GUI - MemoryPatcher::g_game_serial = id; + MemoryPatcher::g_game_serial = id; - // Timer for 'Play Time' - QTimer* timer = new QTimer(); - QObject::connect(timer, &QTimer::timeout, [this, id]() { - UpdatePlayTime(id); - start_time = std::chrono::steady_clock::now(); - }); - timer->start(60000); // 60000 ms = 1 minute + // Timer for 'Play Time' + QTimer* timer = new QTimer(); + QObject::connect(timer, &QTimer::timeout, [this, id]() { + UpdatePlayTime(id); + start_time = std::chrono::steady_clock::now(); + }); + timer->start(60000); // 60000 ms = 1 minute #endif - title = param_sfo->GetString("TITLE").value_or("Unknown title"); - LOG_INFO(Loader, "Game id: {} Title: {}", id, title); - fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000); - app_version = param_sfo->GetString("APP_VER").value_or("Unknown version"); - LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); - } else if (entry.path().filename() == "pic1.png") { - auto* splash = Common::Singleton::Instance(); - if (splash->IsLoaded()) { - continue; - } - if (!splash->Open(entry.path())) { - LOG_ERROR(Loader, "Game splash: unable to open file"); - } + title = param_sfo->GetString("TITLE").value_or("Unknown title"); + LOG_INFO(Loader, "Game id: {} Title: {}", id, title); + fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000); + app_version = param_sfo->GetString("APP_VER").value_or("Unknown version"); + LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); + if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) { + psf_attributes.raw = *raw_attributes; + } + } + + const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png"); + if (std::filesystem::exists(pic1_path)) { + auto* splash = Common::Singleton::Instance(); + if (!splash->IsLoaded()) { + if (!splash->Open(pic1_path)) { + LOG_ERROR(Loader, "Game splash: unable to open file"); } } } @@ -180,6 +169,7 @@ void Emulator::Run(const std::filesystem::path& file) { game_info.app_ver = app_version; game_info.firmware_ver = fw_version & 0xFFF00000; game_info.raw_firmware_ver = fw_version; + game_info.psf_attributes = psf_attributes; std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version); std::string window_title = ""; @@ -223,42 +213,19 @@ void Emulator::Run(const std::filesystem::path& file) { Libraries::InitHLELibs(&linker->GetHLESymbols()); // Load the module with the linker + const auto eboot_path = mnt->GetHostPath("/app0/" + file.filename().string()); linker->LoadModule(eboot_path); // check if we have system modules to load - LoadSystemModules(eboot_path, game_info.game_serial); + LoadSystemModules(game_info.game_serial); // Load all prx from game's sce_module folder - std::vector modules_to_load; - std::filesystem::path game_module_folder = file.parent_path() / "sce_module"; - if (std::filesystem::is_directory(game_module_folder)) { - for (const auto& entry : std::filesystem::directory_iterator(game_module_folder)) { - if (entry.is_regular_file()) { - modules_to_load.push_back(entry.path()); - } + mnt->IterateDirectory("/app0/sce_module", [this](const auto& path, const auto is_file) { + if (is_file) { + LOG_INFO(Loader, "Loading {}", fmt::UTF(path.u8string())); + linker->LoadModule(path); } - } - - // Load all prx from separate update's sce_module folder - std::filesystem::path update_module_folder = game_patch_folder / "sce_module"; - if (std::filesystem::is_directory(update_module_folder)) { - for (const auto& entry : std::filesystem::directory_iterator(update_module_folder)) { - auto it = std::find_if(modules_to_load.begin(), modules_to_load.end(), - [&entry](const std::filesystem::path& p) { - return p.filename() == entry.path().filename(); - }); - if (it != modules_to_load.end()) { - *it = entry.path(); - } else { - modules_to_load.push_back(entry.path()); - } - } - } - - for (const auto& module_path : modules_to_load) { - LOG_INFO(Loader, "Loading {}", fmt::UTF(module_path.u8string())); - linker->LoadModule(module_path); - } + }); #ifdef ENABLE_DISCORD_RPC // Discord RPC @@ -285,17 +252,15 @@ void Emulator::Run(const std::filesystem::path& file) { std::exit(0); } -void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) { - constexpr std::array ModulesToLoad{ +void Emulator::LoadSystemModules(const std::string& game_serial) { + constexpr std::array ModulesToLoad{ {{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2}, - {"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber}, {"libSceUlt.sprx", nullptr}, {"libSceJson.sprx", nullptr}, {"libSceJson2.sprx", nullptr}, {"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal}, {"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap}, {"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc}, - {"libSceJpegEnc.sprx", &Libraries::JpegEnc::RegisterlibSceJpegEnc}, {"libSceCesCs.sprx", nullptr}, {"libSceFont.sprx", nullptr}, {"libSceFontFt.sprx", nullptr}, @@ -311,8 +276,9 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string found_modules, [&](const auto& path) { return path.filename() == module_name; }); if (it != found_modules.end()) { LOG_INFO(Loader, "Loading {}", it->string()); - linker->LoadModule(*it); - continue; + if (linker->LoadModule(*it) != -1) { + continue; + } } if (init_func) { LOG_INFO(Loader, "Can't Load {} switching to HLE", module_name); @@ -321,7 +287,7 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string LOG_INFO(Loader, "No HLE available for {} module", module_name); } } - if (std::filesystem::exists(sys_module_path / game_serial)) { + if (!game_serial.empty() && std::filesystem::exists(sys_module_path / game_serial)) { for (const auto& entry : std::filesystem::directory_iterator(sys_module_path / game_serial)) { LOG_INFO(Loader, "Loading {} from game serial file {}", entry.path().string(), diff --git a/src/emulator.h b/src/emulator.h index e973e9022..a08ab43c3 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -29,7 +29,7 @@ public: void UpdatePlayTime(const std::string& serial); private: - void LoadSystemModules(const std::filesystem::path& file, std::string game_serial); + void LoadSystemModules(const std::string& game_serial); Core::MemoryManager* memory; Input::GameController* controller; diff --git a/src/input/controller.cpp b/src/input/controller.cpp index 3927b096f..eb43e6adf 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/config.h" +#include "common/logging/log.h" #include "core/libraries/kernel/time.h" #include "core/libraries/pad/pad.h" #include "input/controller.h" @@ -116,6 +118,98 @@ void GameController::Axis(int id, Input::Axis axis, int value) { AddState(state); } +void GameController::Gyro(int id, const float gyro[3]) { + std::scoped_lock lock{m_mutex}; + auto state = GetLastState(); + state.time = Libraries::Kernel::sceKernelGetProcessTime(); + + // Update the angular velocity (gyro data) + state.angularVelocity.x = gyro[0]; // X-axis + state.angularVelocity.y = gyro[1]; // Y-axis + state.angularVelocity.z = gyro[2]; // Z-axis + + AddState(state); +} +void GameController::Acceleration(int id, const float acceleration[3]) { + std::scoped_lock lock{m_mutex}; + auto state = GetLastState(); + state.time = Libraries::Kernel::sceKernelGetProcessTime(); + + // Update the acceleration values + state.acceleration.x = acceleration[0]; // X-axis + state.acceleration.y = acceleration[1]; // Y-axis + state.acceleration.z = acceleration[2]; // Z-axis + + AddState(state); +} + +// Stolen from +// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs +float eInt[3] = {0.0f, 0.0f, 0.0f}; // Integral error terms +const float Kp = 50.0f; // Proportional gain +const float Ki = 1.0f; // Integral gain +Libraries::Pad::OrbisFQuaternion o = {1, 0, 0, 0}; +void GameController::CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration, + Libraries::Pad::OrbisFVector3& angularVelocity, + float deltaTime, + Libraries::Pad::OrbisFQuaternion& orientation) { + float ax = acceleration.x, ay = acceleration.y, az = acceleration.z; + float gx = angularVelocity.x, gy = angularVelocity.y, gz = angularVelocity.z; + + float q1 = o.w, q2 = o.x, q3 = o.y, q4 = o.z; + + // Normalize accelerometer measurement + float norm = std::sqrt(ax * ax + ay * ay + az * az); + if (norm == 0.0f) + return; // Handle NaN + norm = 1.0f / norm; + ax *= norm; + ay *= norm; + az *= norm; + + // Estimated direction of gravity + float vx = 2.0f * (q2 * q4 - q1 * q3); + float vy = 2.0f * (q1 * q2 + q3 * q4); + float vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; + + // Error is cross product between estimated direction and measured direction of gravity + float ex = (ay * vz - az * vy); + float ey = (az * vx - ax * vz); + float ez = (ax * vy - ay * vx); + if (Ki > 0.0f) { + eInt[0] += ex * deltaTime; // Accumulate integral error + eInt[1] += ey * deltaTime; + eInt[2] += ez * deltaTime; + } else { + eInt[0] = eInt[1] = eInt[2] = 0.0f; // Prevent integral wind-up + } + + // Apply feedback terms + gx += Kp * ex + Ki * eInt[0]; + gy += Kp * ey + Ki * eInt[1]; + gz += Kp * ez + Ki * eInt[2]; + + //// Integrate rate of change of quaternion + q1 += (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * deltaTime); + q2 += (q1 * gx + q3 * gz - q4 * gy) * (0.5f * deltaTime); + q3 += (q1 * gy - q2 * gz + q4 * gx) * (0.5f * deltaTime); + q4 += (q1 * gz + q2 * gy - q3 * gx) * (0.5f * deltaTime); + + // Normalize quaternion + norm = std::sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4); + norm = 1.0f / norm; + orientation.w = q1 * norm; + orientation.x = q2 * norm; + orientation.y = q3 * norm; + orientation.z = q4 * norm; + o.w = q1 * norm; + o.x = q2 * norm; + o.y = q3 * norm; + o.z = q4 * norm; + LOG_DEBUG(Lib_Pad, "Calculated orientation: {:.2f} {:.2f} {:.2f} {:.2f}", orientation.x, + orientation.y, orientation.z, orientation.w); +} + void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) { if (m_sdl_gamepad != nullptr) { SDL_SetGamepadLED(m_sdl_gamepad, r, g, b); @@ -149,6 +243,21 @@ void GameController::TryOpenSDLController() { int gamepad_count; SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr; + if (Config::getIsMotionControlsEnabled()) { + if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_GYRO, true)) { + gyro_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_GYRO); + LOG_INFO(Input, "Gyro initialized, poll rate: {}", gyro_poll_rate); + } else { + LOG_ERROR(Input, "Failed to initialize gyro controls for gamepad"); + } + if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_ACCEL, true)) { + accel_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_ACCEL); + LOG_INFO(Input, "Accel initialized, poll rate: {}", accel_poll_rate); + } else { + LOG_ERROR(Input, "Failed to initialize accel controls for gamepad"); + } + } + SDL_free(gamepads); SetLightBarRGB(0, 0, 255); @@ -156,6 +265,7 @@ void GameController::TryOpenSDLController() { } u32 GameController::Poll() { + std::scoped_lock lock{m_mutex}; if (m_connected) { auto time = Libraries::Kernel::sceKernelGetProcessTime(); if (m_states_num == 0) { diff --git a/src/input/controller.h b/src/input/controller.h index d425fb46c..c6fc02c24 100644 --- a/src/input/controller.h +++ b/src/input/controller.h @@ -33,6 +33,9 @@ struct State { u64 time = 0; int axes[static_cast(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0}; TouchpadEntry touchpad[2] = {{false, 0, 0}, {false, 0, 0}}; + Libraries::Pad::OrbisFVector3 acceleration = {0.0f, 0.0f, 0.0f}; + Libraries::Pad::OrbisFVector3 angularVelocity = {0.0f, 0.0f, 0.0f}; + Libraries::Pad::OrbisFQuaternion orientation = {0.0f, 0.0f, 0.0f, 1.0f}; }; inline int GetAxis(int min, int max, int value) { @@ -53,12 +56,21 @@ public: void CheckButton(int id, Libraries::Pad::OrbisPadButtonDataOffset button, bool isPressed); void AddState(const State& state); void Axis(int id, Input::Axis axis, int value); + void Gyro(int id, const float gyro[3]); + void Acceleration(int id, const float acceleration[3]); 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(); u32 Poll(); + float gyro_poll_rate; + float accel_poll_rate; + static void CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration, + Libraries::Pad::OrbisFVector3& angularVelocity, + float deltaTime, + Libraries::Pad::OrbisFQuaternion& orientation); + private: struct StateInternal { bool obtained = false; diff --git a/src/main.cpp b/src/main.cpp index 17b5c11fe..54772870c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,11 +4,14 @@ #include "functional" #include "iostream" #include "string" +#include "system_error" #include "unordered_map" #include #include "common/config.h" #include "common/memory_patcher.h" +#include "common/path_util.h" +#include "core/file_sys/fs.h" #include "emulator.h" #ifdef _WIN32 @@ -20,6 +23,10 @@ int main(int argc, char* argv[]) { SetConsoleOutputCP(CP_UTF8); #endif + // Load configurations + const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + Config::load(user_dir / "config.toml"); + bool has_game_argument = false; std::string game_path; @@ -33,6 +40,7 @@ int main(int argc, char* argv[]) { " -p, --patch Apply specified patch file\n" " -f, --fullscreen Specify window initial fullscreen " "state. Does not overwrite the config file.\n" + " --add-game-folder Adds a new game folder to the config.\n" " -h, --help Display this help message\n"; exit(0); }}, @@ -78,9 +86,28 @@ int main(int argc, char* argv[]) { exit(1); } // Set fullscreen mode without saving it to config file - Config::setFullscreenMode(is_fullscreen); + Config::setIsFullscreen(is_fullscreen); }}, {"--fullscreen", [&](int& i) { arg_map["-f"](i); }}, + {"--add-game-folder", + [&](int& i) { + if (++i >= argc) { + std::cerr << "Error: Missing argument for --add-game-folder\n"; + exit(1); + } + std::string config_dir(argv[i]); + std::filesystem::path config_path = std::filesystem::path(config_dir); + std::error_code discard; + if (!std::filesystem::exists(config_path, discard)) { + std::cerr << "Error: File does not exist: " << config_path << "\n"; + exit(1); + } + + Config::addGameInstallDir(config_path); + Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); + std::cout << "Game folder successfully saved.\n"; + exit(0); + }}, }; if (argc == 1) { @@ -105,20 +132,41 @@ int main(int argc, char* argv[]) { } } + // If no game directory is set and no command line argument, prompt for it + if (Config::getGameInstallDirs().empty()) { + std::cout << "Warning: No game folder set, please set it by calling shadps4" + " with the --add-game-folder argument"; + } + if (!has_game_argument) { std::cerr << "Error: Please provide a game path or ID.\n"; exit(1); } // Check if the game path or ID exists - if (!std::filesystem::exists(game_path)) { - std::cerr << "Error: Game file not found\n"; - return -1; + std::filesystem::path eboot_path(game_path); + + // Check if the provided path is a valid file + if (!std::filesystem::exists(eboot_path)) { + // If not a file, treat it as a game ID and search in install directories + bool game_found = false; + for (const auto& install_dir : Config::getGameInstallDirs()) { + const auto candidate_path = install_dir / game_path / "eboot.bin"; + if (std::filesystem::exists(candidate_path)) { + eboot_path = candidate_path; + game_found = true; + break; + } + } + if (!game_found) { + std::cerr << "Error: Game ID or file path not found: " << game_path << std::endl; + return 1; + } } - // Run the emulator with the specified game + // Run the emulator with the resolved eboot path Core::Emulator emulator; - emulator.Run(game_path); + emulator.Run(eboot_path); return 0; } diff --git a/src/qt_gui/check_update.cpp b/src/qt_gui/check_update.cpp index edd55b804..e3e019144 100644 --- a/src/qt_gui/check_update.cpp +++ b/src/qt_gui/check_update.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -24,11 +25,9 @@ #include #include #include -#include #include "check_update.h" using namespace Common::FS; -namespace fs = std::filesystem; CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent) : QDialog(parent), networkManager(new QNetworkAccessManager(this)) { @@ -254,7 +253,11 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate, connect(noButton, &QPushButton::clicked, this, [this]() { close(); }); autoUpdateCheckBox->setChecked(Config::autoUpdate()); +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [](int state) { +#else + connect(autoUpdateCheckBox, &QCheckBox::checkStateChanged, this, [](Qt::CheckState state) { +#endif const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); Config::setAutoUpdate(state == Qt::Checked); Config::save(user_dir / "config.toml"); diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index bba3c2891..b1cd07216 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -133,16 +133,16 @@ void GameListFrame::PopulateGameList() { QString formattedPlayTime; if (hours > 0) { - formattedPlayTime += QString("%1h ").arg(hours); + formattedPlayTime += QString("%1").arg(hours) + tr("h"); } if (minutes > 0) { - formattedPlayTime += QString("%1m ").arg(minutes); + formattedPlayTime += QString("%1").arg(minutes) + tr("m"); } formattedPlayTime = formattedPlayTime.trimmed(); m_game_info->m_games[i].play_time = playTime.toStdString(); if (formattedPlayTime.isEmpty()) { - SetTableItem(i, 8, QString("%1s").arg(seconds)); + SetTableItem(i, 8, QString("%1").arg(seconds) + tr("s")); } else { SetTableItem(i, 8, formattedPlayTime); } diff --git a/src/qt_gui/game_list_utils.h b/src/qt_gui/game_list_utils.h index 16c0307c8..ab9233886 100644 --- a/src/qt_gui/game_list_utils.h +++ b/src/qt_gui/game_list_utils.h @@ -30,10 +30,11 @@ struct GameInfo { CompatibilityEntry compatibility = CompatibilityEntry{CompatibilityStatus::Unknown}; }; -class GameListUtils { +class GameListUtils : public QObject { + Q_OBJECT public: static QString FormatSize(qint64 size) { - static const QStringList suffixes = {"B", "KB", "MB", "GB", "TB"}; + static const QStringList suffixes = {tr("B"), tr("KB"), tr("MB"), tr("GB"), tr("TB")}; int suffixIndex = 0; double gameSize = static_cast(size); diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index d26b860c1..0e8675c0c 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -283,15 +283,15 @@ public: #ifdef Q_OS_WIN if (createShortcutWin(linkPath, ebootPath, icoPath, exePath)) { #else - if (createShortcutLinux(linkPath, ebootPath, iconPath)) { + if (createShortcutLinux(linkPath, m_games[itemID].name, ebootPath, iconPath)) { #endif QMessageBox::information( nullptr, tr("Shortcut creation"), - QString(tr("Shortcut created successfully!\n %1")).arg(linkPath)); + QString(tr("Shortcut created successfully!") + "\n%1").arg(linkPath)); } else { QMessageBox::critical( nullptr, tr("Error"), - QString(tr("Error creating shortcut!\n %1")).arg(linkPath)); + QString(tr("Error creating shortcut!") + "\n%1").arg(linkPath)); } } else { QMessageBox::critical(nullptr, tr("Error"), tr("Failed to convert icon.")); @@ -301,15 +301,15 @@ public: #ifdef Q_OS_WIN if (createShortcutWin(linkPath, ebootPath, iconPath, exePath)) { #else - if (createShortcutLinux(linkPath, ebootPath, iconPath)) { + if (createShortcutLinux(linkPath, m_games[itemID].name, ebootPath, iconPath)) { #endif QMessageBox::information( nullptr, tr("Shortcut creation"), - QString(tr("Shortcut created successfully!\n %1")).arg(linkPath)); + QString(tr("Shortcut created successfully!") + "\n%1").arg(linkPath)); } else { QMessageBox::critical( nullptr, tr("Error"), - QString(tr("Error creating shortcut!\n %1")).arg(linkPath)); + QString(tr("Error creating shortcut!") + "\n%1").arg(linkPath)); } } } @@ -347,9 +347,8 @@ public: if (selected == deleteUpdate) { if (!std::filesystem::exists(Common::FS::PathFromQString(game_update_path))) { - QMessageBox::critical( - nullptr, tr("Error"), - QString(tr("This game has no separate update to delete!"))); + QMessageBox::critical(nullptr, tr("Error"), + QString(tr("This game has no update to delete!"))); error = true; } else { folder_path = game_update_path; @@ -511,8 +510,8 @@ private: return SUCCEEDED(hres); } #else - bool createShortcutLinux(const QString& linkPath, const QString& targetPath, - const QString& iconPath) { + bool createShortcutLinux(const QString& linkPath, const std::string& name, + const QString& targetPath, const QString& iconPath) { QFile shortcutFile(linkPath); if (!shortcutFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(nullptr, "Error", @@ -523,7 +522,7 @@ private: QTextStream out(&shortcutFile); out << "[Desktop Entry]\n"; out << "Version=1.0\n"; - out << "Name=" << QFileInfo(linkPath).baseName() << "\n"; + out << "Name=" << QString::fromStdString(name) << "\n"; out << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n"; out << "Icon=" << iconPath << "\n"; out << "Terminal=false\n"; diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index 318245053..2d524e199 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "iostream" +#include "system_error" #include "unordered_map" #include "common/config.h" @@ -31,7 +32,7 @@ int main(int argc, char* argv[]) { bool has_command_line_argument = argc > 1; bool show_gui = false, has_game_argument = false; - std::string gamePath; + std::string game_path; // Map of argument strings to lambda functions std::unordered_map> arg_map = { @@ -46,6 +47,7 @@ int main(int argc, char* argv[]) { " -s, --show-gui Show the GUI\n" " -f, --fullscreen Specify window initial fullscreen " "state. Does not overwrite the config file.\n" + " --add-game-folder Adds a new game folder to the config.\n" " -h, --help Display this help message\n"; exit(0); }}, @@ -57,7 +59,7 @@ int main(int argc, char* argv[]) { {"-g", [&](int& i) { if (i + 1 < argc) { - gamePath = argv[++i]; + game_path = argv[++i]; has_game_argument = true; } else { std::cerr << "Error: Missing argument for -g/--game\n"; @@ -95,9 +97,28 @@ int main(int argc, char* argv[]) { exit(1); } // Set fullscreen mode without saving it to config file - Config::setFullscreenMode(is_fullscreen); + Config::setIsFullscreen(is_fullscreen); }}, {"--fullscreen", [&](int& i) { arg_map["-f"](i); }}, + {"--add-game-folder", + [&](int& i) { + if (++i >= argc) { + std::cerr << "Error: Missing argument for --add-game-folder\n"; + exit(1); + } + std::string config_dir(argv[i]); + std::filesystem::path config_path = std::filesystem::path(config_dir); + std::error_code discard; + if (!std::filesystem::is_directory(config_path, discard)) { + std::cerr << "Error: Directory does not exist: " << config_path << "\n"; + exit(1); + } + + Config::addGameInstallDir(config_path); + Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); + std::cout << "Game folder successfully saved.\n"; + exit(0); + }}, }; // Parse command-line arguments using the map @@ -106,6 +127,10 @@ int main(int argc, char* argv[]) { auto it = arg_map.find(cur_arg); if (it != arg_map.end()) { it->second(i); // Call the associated lambda function + } else if (i == argc - 1 && !has_game_argument) { + // Assume the last argument is the game file if not specified via -g/--game + game_path = argv[i]; + has_game_argument = true; } else { std::cerr << "Unknown argument: " << cur_arg << ", see --help for info.\n"; return 1; @@ -134,14 +159,14 @@ int main(int argc, char* argv[]) { // Process game path or ID if provided if (has_game_argument) { - std::filesystem::path game_file_path(gamePath); + std::filesystem::path game_file_path(game_path); // Check if the provided path is a valid file if (!std::filesystem::exists(game_file_path)) { // If not a file, treat it as a game ID and search in install directories bool game_found = false; for (const auto& install_dir : Config::getGameInstallDirs()) { - auto potential_game_path = install_dir / gamePath / "eboot.bin"; + auto potential_game_path = install_dir / game_path / "eboot.bin"; if (std::filesystem::exists(potential_game_path)) { game_file_path = potential_game_path; game_found = true; @@ -149,7 +174,7 @@ int main(int argc, char* argv[]) { } } if (!game_found) { - std::cerr << "Error: Game ID or file path not found: " << gamePath << std::endl; + std::cerr << "Error: Game ID or file path not found: " << game_path << std::endl; return 1; } } @@ -165,4 +190,4 @@ int main(int argc, char* argv[]) { // Show the main window and run the Qt application m_main_window->show(); return a.exec(); -} \ No newline at end of file +} diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 29dfb7119..0dd2a58a8 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -79,8 +79,8 @@ bool MainWindow::Init() { this->setStatusBar(statusBar.data()); // Update status bar int numGames = m_game_info->m_games.size(); - QString statusMessage = - "Games: " + QString::number(numGames) + " (" + QString::number(duration.count()) + "ms)"; + QString statusMessage = tr("Games: ") + QString::number(numGames) + " (" + + QString::number(duration.count()) + "ms)"; statusBar->showMessage(statusMessage); #ifdef ENABLE_DISCORD_RPC @@ -116,6 +116,7 @@ void MainWindow::CreateActions() { m_theme_act_group->addAction(ui->setThemeBlue); m_theme_act_group->addAction(ui->setThemeViolet); m_theme_act_group->addAction(ui->setThemeGruvbox); + m_theme_act_group->addAction(ui->setThemeTokyoNight); } void MainWindow::AddUiWidgets() { @@ -569,6 +570,14 @@ void MainWindow::CreateConnects() { isIconBlack = false; } }); + connect(ui->setThemeTokyoNight, &QAction::triggered, &m_window_themes, [this]() { + m_window_themes.SetWindowTheme(Theme::TokyoNight, ui->mw_searchbar); + Config::setMainWindowTheme(static_cast(Theme::TokyoNight)); + if (isIconBlack) { + SetUiIcons(false); + isIconBlack = false; + } + }); } void MainWindow::StartGame() { @@ -944,6 +953,11 @@ void MainWindow::SetLastUsedTheme() { isIconBlack = false; SetUiIcons(false); break; + case Theme::TokyoNight: + ui->setThemeTokyoNight->setChecked(true); + isIconBlack = false; + SetUiIcons(false); + break; } } diff --git a/src/qt_gui/main_window_themes.cpp b/src/qt_gui/main_window_themes.cpp index a52b4466e..5fffd4c9e 100644 --- a/src/qt_gui/main_window_themes.cpp +++ b/src/qt_gui/main_window_themes.cpp @@ -143,5 +143,27 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) { themePalette.setColor(QPalette::HighlightedText, Qt::black); qApp->setPalette(themePalette); break; + case Theme::TokyoNight: + mw_searchbar->setStyleSheet( + "QLineEdit {" + "background-color: #1a1b26; color: #9d7cd8; border: 1px solid #9d7cd8; " + "border-radius: 4px; padding: 5px; }" + "QLineEdit:focus {" + "border: 1px solid #7aa2f7; }"); + themePalette.setColor(QPalette::Window, QColor(31, 35, 53)); + themePalette.setColor(QPalette::WindowText, QColor(192, 202, 245)); + themePalette.setColor(QPalette::Base, QColor(25, 28, 39)); + themePalette.setColor(QPalette::AlternateBase, QColor(36, 40, 59)); + themePalette.setColor(QPalette::ToolTipBase, QColor(192, 202, 245)); + themePalette.setColor(QPalette::ToolTipText, QColor(192, 202, 245)); + themePalette.setColor(QPalette::Text, QColor(192, 202, 245)); + themePalette.setColor(QPalette::Button, QColor(30, 30, 41)); + themePalette.setColor(QPalette::ButtonText, QColor(192, 202, 245)); + themePalette.setColor(QPalette::BrightText, QColor(197, 59, 83)); + themePalette.setColor(QPalette::Link, QColor(79, 214, 190)); + themePalette.setColor(QPalette::Highlight, QColor(79, 214, 190)); + themePalette.setColor(QPalette::HighlightedText, Qt::black); + qApp->setPalette(themePalette); + break; } } \ No newline at end of file diff --git a/src/qt_gui/main_window_themes.h b/src/qt_gui/main_window_themes.h index d162da87b..0ec2cce58 100644 --- a/src/qt_gui/main_window_themes.h +++ b/src/qt_gui/main_window_themes.h @@ -7,7 +7,7 @@ #include #include -enum class Theme : int { Dark, Light, Green, Blue, Violet, Gruvbox }; +enum class Theme : int { Dark, Light, Green, Blue, Violet, Gruvbox, TokyoNight }; class WindowThemes : public QObject { Q_OBJECT diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index df64361fd..0d5038d7e 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -37,6 +37,7 @@ public: QAction* setThemeBlue; QAction* setThemeViolet; QAction* setThemeGruvbox; + QAction* setThemeTokyoNight; QWidget* centralWidget; QLineEdit* mw_searchbar; QPushButton* playButton; @@ -162,6 +163,9 @@ public: setThemeGruvbox = new QAction(MainWindow); setThemeGruvbox->setObjectName("setThemeGruvbox"); setThemeGruvbox->setCheckable(true); + setThemeTokyoNight = new QAction(MainWindow); + setThemeTokyoNight->setObjectName("setThemeTokyoNight"); + setThemeTokyoNight->setCheckable(true); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName("centralWidget"); sizePolicy.setHeightForWidth(centralWidget->sizePolicy().hasHeightForWidth()); @@ -287,6 +291,7 @@ public: menuThemes->addAction(setThemeBlue); menuThemes->addAction(setThemeViolet); menuThemes->addAction(setThemeGruvbox); + menuThemes->addAction(setThemeTokyoNight); menuGame_List_Icons->addAction(setIconSizeTinyAct); menuGame_List_Icons->addAction(setIconSizeSmallAct); menuGame_List_Icons->addAction(setIconSizeMediumAct); @@ -374,6 +379,7 @@ public: setThemeBlue->setText(QCoreApplication::translate("MainWindow", "Blue", nullptr)); setThemeViolet->setText(QCoreApplication::translate("MainWindow", "Violet", nullptr)); setThemeGruvbox->setText("Gruvbox"); + setThemeTokyoNight->setText("Tokyo Night"); toolBar->setWindowTitle(QCoreApplication::translate("MainWindow", "toolBar", nullptr)); } // retranslateUi }; diff --git a/src/qt_gui/pkg_viewer.cpp b/src/qt_gui/pkg_viewer.cpp index 0ffb9b579..b4dd3afdf 100644 --- a/src/qt_gui/pkg_viewer.cpp +++ b/src/qt_gui/pkg_viewer.cpp @@ -47,6 +47,9 @@ PKGViewer::PKGViewer(std::shared_ptr game_info_get, QWidget* pare connect(treeWidget, &QTreeWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) { + if (treeWidget->selectedItems().isEmpty()) { + return; + } m_gui_context_menus.RequestGameMenuPKGViewer(pos, m_full_pkg_list, treeWidget, InstallDragDropPkg); }); diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index f9095d8a0..3f4970dad 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -3,22 +3,25 @@ #include #include +#include #include +#include -#include #include "common/config.h" +#include "common/version.h" #include "qt_gui/compatibility_info.h" #ifdef ENABLE_DISCORD_RPC #include "common/discord_rpc_handler.h" +#include "common/singleton.h" #endif #ifdef ENABLE_UPDATER #include "check_update.h" #endif +#include #include +#include "background_music_player.h" #include "common/logging/backend.h" #include "common/logging/filter.h" -#include "common/logging/formatter.h" -#include "main_window.h" #include "settings_dialog.h" #include "ui_settings_dialog.h" QStringList languageNames = {"Arabic", @@ -130,8 +133,13 @@ SettingsDialog::SettingsDialog(std::span physical_devices, // GENERAL TAB { #ifdef ENABLE_UPDATER +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, [](int state) { Config::setAutoUpdate(state == Qt::Checked); }); +#else + connect(ui->updateCheckBox, &QCheckBox::checkStateChanged, this, + [](Qt::CheckState state) { Config::setAutoUpdate(state == Qt::Checked); }); +#endif connect(ui->updateComboBox, &QComboBox::currentTextChanged, this, [](const QString& channel) { Config::setUpdateChannel(channel.toStdString()); }); @@ -150,7 +158,12 @@ SettingsDialog::SettingsDialog(std::span physical_devices, emit CompatibilityChanged(); }); +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) connect(ui->enableCompatibilityCheckBox, &QCheckBox::stateChanged, this, [this](int state) { +#else + connect(ui->enableCompatibilityCheckBox, &QCheckBox::checkStateChanged, this, + [this](Qt::CheckState state) { +#endif Config::setCompatibilityEnabled(state); emit CompatibilityChanged(); }); @@ -191,6 +204,16 @@ SettingsDialog::SettingsDialog(std::span physical_devices, }); } + // DEBUG TAB + { + connect(ui->OpenLogLocationButton, &QPushButton::clicked, this, []() { + QString userPath; + Common::FS::PathToQString(userPath, + Common::FS::GetUserPath(Common::FS::PathType::UserDir)); + QDesktopServices::openUrl(QUrl::fromLocalFile(userPath + "/log")); + }); + } + // Descriptions { // General @@ -199,9 +222,10 @@ SettingsDialog::SettingsDialog(std::span physical_devices, ui->fullscreenCheckBox->installEventFilter(this); ui->separateUpdatesCheckBox->installEventFilter(this); ui->showSplashCheckBox->installEventFilter(this); - ui->ps4proCheckBox->installEventFilter(this); ui->discordRPCCheckbox->installEventFilter(this); ui->userName->installEventFilter(this); + ui->label_Trophy->installEventFilter(this); + ui->trophyKeyLineEdit->installEventFilter(this); ui->logTypeGroupBox->installEventFilter(this); ui->logFilter->installEventFilter(this); #ifdef ENABLE_UPDATER @@ -287,16 +311,20 @@ void SettingsDialog::LoadValuesFromConfig() { ui->discordRPCCheckbox->setChecked( toml::find_or(data, "General", "enableDiscordRPC", true)); ui->fullscreenCheckBox->setChecked(toml::find_or(data, "General", "Fullscreen", false)); + ui->fullscreenModeComboBox->setCurrentText(QString::fromStdString( + toml::find_or(data, "General", "FullscreenMode", "Borderless"))); ui->separateUpdatesCheckBox->setChecked( toml::find_or(data, "General", "separateUpdateEnabled", false)); ui->showSplashCheckBox->setChecked(toml::find_or(data, "General", "showSplash", false)); - ui->ps4proCheckBox->setChecked(toml::find_or(data, "General", "isPS4Pro", false)); ui->logTypeComboBox->setCurrentText( QString::fromStdString(toml::find_or(data, "General", "logType", "async"))); ui->logFilterLineEdit->setText( QString::fromStdString(toml::find_or(data, "General", "logFilter", ""))); ui->userNameLineEdit->setText( QString::fromStdString(toml::find_or(data, "General", "userName", "shadPS4"))); + ui->trophyKeyLineEdit->setText( + QString::fromStdString(toml::find_or(data, "Keys", "TrophyKey", ""))); + ui->trophyKeyLineEdit->setEchoMode(QLineEdit::Password); ui->debugDump->setChecked(toml::find_or(data, "Debug", "DebugDump", false)); ui->vkValidationCheckBox->setChecked(toml::find_or(data, "Vulkan", "validation", false)); ui->vkSyncValidationCheckBox->setChecked( @@ -324,6 +352,8 @@ void SettingsDialog::LoadValuesFromConfig() { toml::find_or(data, "Input", "backButtonBehavior", "left")); int index = ui->backButtonBehaviorComboBox->findData(backButtonBehavior); ui->backButtonBehaviorComboBox->setCurrentIndex(index != -1 ? index : 0); + ui->motionControlsCheckBox->setChecked( + toml::find_or(data, "Input", "isMotionControlsEnabled", true)); ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty()); ResetInstallFolders(); @@ -360,7 +390,7 @@ void SettingsDialog::InitializeEmulatorLanguages() { idx++; } - connect(ui->emulatorLanguageComboBox, qOverload(&QComboBox::currentIndexChanged), this, + connect(ui->emulatorLanguageComboBox, &QComboBox::currentIndexChanged, this, &SettingsDialog::OnLanguageChanged); } @@ -405,12 +435,14 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { text = tr("separateUpdatesCheckBox"); } else if (elementName == "showSplashCheckBox") { text = tr("showSplashCheckBox"); - } else if (elementName == "ps4proCheckBox") { - text = tr("ps4proCheckBox"); } else if (elementName == "discordRPCCheckbox") { text = tr("discordRPCCheckbox"); } else if (elementName == "userName") { text = tr("userName"); + } else if (elementName == "label_Trophy") { + text = tr("TrophyKey"); + } else if (elementName == "trophyKeyLineEdit") { + text = tr("TrophyKey"); } else if (elementName == "logTypeGroupBox") { text = tr("logTypeGroupBox"); } else if (elementName == "logFilter") { @@ -515,14 +547,15 @@ void SettingsDialog::UpdateSettings() { const QVector TouchPadIndex = {"left", "center", "right", "none"}; Config::setBackButtonBehavior(TouchPadIndex[ui->backButtonBehaviorComboBox->currentIndex()]); - Config::setNeoMode(ui->ps4proCheckBox->isChecked()); - Config::setFullscreenMode(ui->fullscreenCheckBox->isChecked()); + Config::setIsFullscreen(ui->fullscreenCheckBox->isChecked()); + Config::setFullscreenMode(ui->fullscreenModeComboBox->currentText().toStdString()); + Config::setIsMotionControlsEnabled(ui->motionControlsCheckBox->isChecked()); Config::setisTrophyPopupDisabled(ui->disableTrophycheckBox->isChecked()); Config::setPlayBGM(ui->playBGMCheckBox->isChecked()); - Config::setNeoMode(ui->ps4proCheckBox->isChecked()); Config::setLogType(ui->logTypeComboBox->currentText().toStdString()); Config::setLogFilter(ui->logFilterLineEdit->text().toStdString()); Config::setUserName(ui->userNameLineEdit->text().toStdString()); + Config::setTrophyKey(ui->trophyKeyLineEdit->text().toStdString()); Config::setCursorState(ui->hideCursorComboBox->currentIndex()); Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value()); Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1); diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index e6a9d5a58..089158fd3 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -11,8 +11,8 @@ 0 0 - 900 - 660 + 970 + 750 @@ -42,45 +42,42 @@ - + true - - QFrame::Shape::NoFrame + + + 0 + 0 + - - true + + 0 - - + + true - - - 0 - -97 - 815 - 618 - - - - - 0 - 0 - - - - 0 - - - - General - - + + General + + + + + 0 + 0 + 946 + 536 + + + - - + + + 0 + + @@ -117,7 +114,7 @@ - + @@ -127,12 +124,44 @@ + + 10 + Enable Fullscreen + + + + + Fullscreen Mode + + + + + + + 0 + 0 + + + + + Borderless + + + + + True + + + + + + @@ -148,13 +177,6 @@ - - - - Is PS4 Pro - - - @@ -195,92 +217,11 @@ - - - - - - Logger - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Log Type - - - - - - - async - - - - - sync - - - - - - - - - - - - - - 6 - - - 0 - - - - - - - Log Filter - - - - - - - - - - - - - - - - - - - - - - + + + 6 + QLayout::SizeConstraint::SetDefaultConstraint @@ -296,7 +237,7 @@ 0 - + @@ -306,7 +247,7 @@ - 265 + 0 0 @@ -321,7 +262,7 @@ - 5 + 10 1 @@ -343,7 +284,7 @@ 0 - 75 + 0 @@ -404,8 +345,8 @@ - 197 - 28 + 0 + 0 @@ -443,9 +384,82 @@ - + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Game Compatibility + + + + 10 + + + 1 + + + 11 + + + + + Display Compatibility Data + + + + + + + Update Compatibility Database On Startup + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Update Compatibility Database + + + + + + + + + - + @@ -470,9 +484,15 @@ 11 - + + + + 0 + 0 + + - Disable Trophy Pop-ups + Play title music @@ -485,36 +505,7 @@ 0 - - - - 0 - 0 - - - - Play title music - - - - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::Fixed - - - - 20 - 2 - - - - - - + 0 @@ -566,6 +557,62 @@ + + + + 6 + + + 0 + + + 80 + + + + + + + Trophy + + + + + + Disable Trophy Pop-ups + + + + + + + Trophy Key + + + + + + + + 0 + 0 + + + + + 10 + false + + + + + + + + + + + @@ -573,94 +620,27 @@ - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Game Compatibility - - - - 1 - - - 11 - - - - - Display Compatibility Data - - - - - - - Update Compatibility Database On Startup - - - - - - - 1 - - - 0 - - - - - - 0 - 0 - - - - - 197 - 28 - - - - - 16777215 - 16777215 - - - - Update Compatibility Database - - - - - - - + - - - - - - - Input - + + + + true + + + Input + + + + + 0 + 0 + 926 + 536 + + @@ -769,8 +749,8 @@ - 80 - 30 + 0 + 0 @@ -856,7 +836,7 @@ - 237 + 0 0 @@ -873,6 +853,13 @@ + + + + Enable Motion Controls + + + @@ -935,10 +922,23 @@ - - - Graphics - + + + + true + + + Graphics + + + + + 0 + 0 + 926 + 536 + + @@ -1173,58 +1173,61 @@ - - - Paths - - + + + + true + + + Paths + + + + + 0 + 0 + 926 + 536 + + + - + Game Folders - - - - 0 - 20 - 401 - 331 - - - - - - - 100 - 360 - 91 - 24 - - - - Add... - - - - - - 199 - 360 - 91 - 24 - - - - Remove - - + + + + + 0 + + + + + Add... + + + + + + + Remove + + + + + + + + + - + Qt::Orientation::Horizontal @@ -1243,71 +1246,165 @@ - - - Debug - + + + + true + + + Debug + + + + + 0 + 0 + 926 + 536 + + - + + + 0 + + + 0 + - - - true - - - General - - - Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop - - - - - - Enable Debug Dumping - - - - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::MinimumExpanding - - - - 0 - 0 - - - - - - - - Enable Vulkan Validation Layers - - - - - - - Enable Vulkan Synchronization Validation - - - - - - - Enable RenderDoc Debugging - - - - - + + + + + true + + + General + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + + + + Enable Debug Dumping + + + + + + + Enable Vulkan Validation Layers + + + + + + + Enable Vulkan Synchronization Validation + + + + + + + Enable RenderDoc Debugging + + + + + + + + + + + + + + Logger + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Log Type + + + + + + + async + + + + + sync + + + + + + + + + + + + + + 6 + + + 0 + + + + + + + Log Filter + + + + + + + + + + + + + + + + Open Log Location + + + + + + + diff --git a/src/qt_gui/translations/ar.ts b/src/qt_gui/translations/ar.ts index dad4469cb..4fc9c2de1 100644 --- a/src/qt_gui/translations/ar.ts +++ b/src/qt_gui/translations/ar.ts @@ -6,22 +6,18 @@ 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. يجب عدم استخدام هذا البرنامج لتشغيل الألعاب التي لم تحصل عليها بشكل قانوني. @@ -29,7 +25,6 @@ ElfViewer - Open Folder فتح المجلد @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 جارٍ تحميل قائمة الألعاب، يرجى الانتظار :3 - Cancel إلغاء - Loading... ...جارٍ التحميل @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - اختر المجلد - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - اختر المجلد - Directory to install games مجلد تثبيت الألعاب - Browse تصفح - Error خطأ - The value for location to install games is not valid. قيمة موقع تثبيت الألعاب غير صالحة. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut إنشاء اختصار - Cheats / Patches الغش / التصحيحات - SFO Viewer عارض SFO - Trophy Viewer عارض الجوائز - Open Folder... فتح المجلد... - Open Game Folder فتح مجلد اللعبة - Open Save Data Folder فتح مجلد بيانات الحفظ - Open Log Folder فتح مجلد السجل - Copy info... ...نسخ المعلومات - Copy Name نسخ الاسم - Copy Serial نسخ الرقم التسلسلي - Copy All نسخ الكل - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation إنشاء اختصار - - Shortcut created successfully!\n %1 - تم إنشاء الاختصار بنجاح!\n %1 + Shortcut created successfully! + تم إنشاء الاختصار بنجاح! - Error خطأ - - Error creating shortcut!\n %1 - !\n %1 خطأ في إنشاء الاختصار + Error creating shortcut! + خطأ في إنشاء الاختصار - Install PKG PKG تثبيت - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Elf فتح/إضافة مجلد - Install Packages (PKG) (PKG) تثبيت الحزم - Boot Game تشغيل اللعبة - Check for Updates تحقق من التحديثات - 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 السمات - Help مساعدة - Dark داكن - Light فاتح - Green أخضر - Blue أزرق - Violet بنفسجي - toolBar شريط الأدوات + + Game List + ققائمة الألعاب + + + * 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 صالحًا + PKGViewer - Open Folder فتح المجلد @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer عارض الجوائز @@ -458,989 +509,704 @@ SettingsDialog - Settings الإعدادات - General عام - System النظام - Console Language لغة وحدة التحكم - Emulator Language لغة المحاكي - Emulator المحاكي - Enable Fullscreen تمكين ملء الشاشة - Enable Separate Update Folder Enable Separate Update Folder - Show Splash إظهار شاشة البداية - Is PS4 Pro PS4 Pro هل هو - Enable Discord Rich Presence تفعيل حالة الثراء في ديسكورد - Username اسم المستخدم - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger المسجل - Log Type نوع السجل - Log Filter مرشح السجل - + Open Log Location + افتح موقع السجل + + Input إدخال - Cursor مؤشر - Hide Cursor إخفاء المؤشر - Hide Cursor Idle Timeout مهلة إخفاء المؤشر عند الخمول - + s + s + + Controller التحكم - Back Button Behavior سلوك زر العودة - Graphics الرسومات - Graphics Device جهاز الرسومات - Width العرض - Height الارتفاع - Vblank Divider Vblank مقسم - Advanced متقدم - Enable Shaders Dumping تمكين تفريغ الشيدرات - Enable NULL GPU تمكين وحدة معالجة الرسومات الفارغة - Paths المسارات - Game Folders مجلدات اللعبة - Add... إضافة... - Remove إزالة - Debug تصحيح الأخطاء - Enable Debug Dumping تمكين تفريغ التصحيح - Enable Vulkan Validation Layers Vulkan تمكين طبقات التحقق من - Enable Vulkan Synchronization Validation Vulkan تمكين التحقق من تزامن - Enable RenderDoc Debugging RenderDoc تمكين تصحيح أخطاء - Update تحديث - Check for Updates at Startup تحقق من التحديثات عند بدء التشغيل - Update Channel قناة التحديث - Check for Updates التحقق من التحديثات - GUI Settings إعدادات الواجهة - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music تشغيل موسيقى العنوان - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume الصوت - - - MainWindow - - Game List - ققائمة الألعاب + Audio Backend + Audio Backend - - * 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 for - Cheats / Patches for - - - - 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. - فشل في تحليل بيانات JSON من HTML. - - - - Failed to retrieve HTML page. - .HTML فشل في استرجاع صفحة - - - - The game is in version: %1 - اللعبة في الإصدار: %1 - - - - The downloaded patch only works on version: %1 - الباتش الذي تم تنزيله يعمل فقط على الإصدار: %1 - - - - You may need to update your game. - قد تحتاج إلى تحديث لعبتك. - - - - Incompatibility Notice - إشعار عدم التوافق - - - - 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: - :الاسم - - - - Can't apply cheats before the game is started - لا يمكن تطبيق الغش قبل بدء اللعبة. - - - - SettingsDialog - - - Save - حفظ - - - Apply تطبيق - Restore Defaults استعادة الإعدادات الافتراضية - Close إغلاق - Point your mouse at an option to display its description. وجّه الماوس نحو خيار لعرض وصفه. - consoleLanguageGroupBox لغة الجهاز:\nتحدد لغة اللعبة التي يستخدمها جهاز PS4.\nيوصى بضبطها على لغة يدعمها الجهاز، والتي قد تختلف حسب المنطقة. - emulatorLanguageGroupBox لغة المحاكي:\nتحدد لغة واجهة المستخدم الخاصة بالمحاكي. - fullscreenCheckBox تمكين وضع ملء الشاشة:\nيجعل نافذة اللعبة تنتقل تلقائيًا إلى وضع ملء الشاشة.\nيمكن التبديل بالضغط على المفتاح F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox إظهار شاشة البداية:\nيعرض شاشة البداية الخاصة باللعبة (صورة خاصة) أثناء بدء التشغيل. - ps4proCheckBox هل هو PS4 Pro:\nيجعل المحاكي يعمل كـ PS4 PRO، مما قد يتيح ميزات خاصة في الألعاب التي تدعمه. - discordRPCCheckbox تفعيل حالة الثراء في ديسكورد:\nيعرض أيقونة المحاكي ومعلومات ذات صلة على ملفك الشخصي في ديسكورد. - userName اسم المستخدم:\nيضبط اسم حساب PS4، الذي قد يتم عرضه في بعض الألعاب. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox نوع السجل:\nيضبط ما إذا كان سيتم مزامنة مخرجات نافذة السجل للأداء. قد يؤثر سلبًا على المحاكاة. - logFilter فلتر السجل:\nيقوم بتصفية السجل لطباعة معلومات محددة فقط.\nأمثلة: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" المستويات: Trace, Debug, Info, Warning, Error, Critical - بالترتيب، مستوى محدد يخفي جميع المستويات التي تسبقه ويعرض جميع المستويات بعده. - updaterGroupBox تحديث: Release: إصدارات رسمية تصدر شهريًا، قد تكون قديمة بعض الشيء، لكنها أكثر استقرارًا واختبارًا. Nightly: إصدارات تطوير تحتوي على أحدث الميزات والإصلاحات، لكنها قد تحتوي على أخطاء وأقل استقرارًا. - GUIgroupBox تشغيل موسيقى العنوان:\nإذا كانت اللعبة تدعم ذلك، قم بتمكين تشغيل موسيقى خاصة عند اختيار اللعبة في واجهة المستخدم. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox إخفاء المؤشر:\nاختر متى سيختفي المؤشر:\nأبداً: سترى الفأرة دائماً.\nعاطل: حدد وقتاً لاختفائه بعد أن يكون غير مستخدم.\nدائماً: لن ترى الفأرة أبداً. - idleTimeoutGroupBox حدد وقتاً لاختفاء الفأرة بعد أن تكون غير مستخدم. - backButtonBehaviorGroupBox سلوك زر العودة:\nيضبط زر العودة في وحدة التحكم ليحاكي الضغط على الموضع المحدد على لوحة اللمس في PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never أبداً - Idle خامل - Always دائماً - Touchpad Left لوحة اللمس اليسرى - Touchpad Right لوحة اللمس اليمنى - Touchpad Center وسط لوحة اللمس - None لا شيء - graphicsAdapterGroupBox جهاز الرسومات:\nعلى الأنظمة متعددة وحدات معالجة الرسومات، اختر وحدة معالجة الرسومات التي سيستخدمها المحاكي من قائمة منسدلة،\nأو اختر "Auto Select" لتحديدها تلقائيًا. - resolutionLayout العرض / الارتفاع:\nيضبط حجم نافذة المحاكي عند التشغيل، والذي يمكن تغيير حجمه أثناء اللعب.\nهذا يختلف عن دقة اللعبة نفسها. - heightDivider مقسم معدل التحديث:\nيتم مضاعفة معدل الإطارات الذي يتم تحديث المحاكي به بواسطة هذا الرقم. قد يؤدي تغيير هذا إلى آثار سلبية، مثل زيادة سرعة اللعبة أو كسر الوظائف الأساسية التي لا تتوقع هذا التغيير! - dumpShadersCheckBox تمكين تفريغ الـ Shaders:\nلأغراض تصحيح الأخطاء التقنية، يحفظ الـ Shaders الخاصة باللعبة في مجلد أثناء التشغيل. - nullGpuCheckBox تمكين GPU الافتراضية:\nلأغراض تصحيح الأخطاء التقنية، يقوم بتعطيل عرض اللعبة كما لو لم يكن هناك بطاقة رسومات. - gameFoldersBox مجلدات اللعبة:\nقائمة بالمجلدات للتحقق من الألعاب المثبتة. - addFolderButton إضافة:\nأضف مجلداً إلى القائمة. - removeFolderButton إزالة:\nأزل مجلداً من القائمة. - debugDump تمكين تفريغ التصحيح:\nيحفظ رموز الاستيراد والتصدير ومعلومات رأس الملف للبرنامج الحالي لجهاز PS4 إلى دليل. - vkValidationCheckBox تمكين طبقات التحقق من Vulkan:\nيتيح نظام يتحقق من حالة مشغل Vulkan ويسجل معلومات حول حالته الداخلية. سيؤدي هذا إلى تقليل الأداء ومن المحتمل تغيير سلوك المحاكاة. - vkSyncValidationCheckBox تمكين التحقق من تزامن Vulkan:\nيتيح نظام يتحقق من توقيت مهام عرض Vulkan. سيؤدي ذلك إلى تقليل الأداء ومن المحتمل تغيير سلوك المحاكاة. - rdocCheckBox تمكين تصحيح RenderDoc:\nإذا تم التمكين، سيوفر المحاكي توافقًا مع Renderdoc لالتقاط وتحليل الإطار الذي يتم عرضه حاليًا. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. + فشل في تحليل بيانات JSON من HTML. + + + Failed to retrieve HTML page. + .HTML فشل في استرجاع صفحة + + + The game is in version: %1 + اللعبة في الإصدار: %1 + + + The downloaded patch only works on version: %1 + الباتش الذي تم تنزيله يعمل فقط على الإصدار: %1 + + + You may need to update your game. + قد تحتاج إلى تحديث لعبتك. + + + Incompatibility Notice + إشعار عدم التوافق + + + 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: + :الاسم + + + Can't apply cheats before the game is started + لا يمكن تطبيق الغش قبل بدء اللعبة. + + GameListFrame - Icon أيقونة - Name اسم - Serial سيريال - Compatibility Compatibility - Region منطقة - Firmware البرمجيات الثابتة - Size حجم - Version إصدار - Path مسار - Play Time وقت اللعب - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater محدث تلقائي - Error خطأ - Network error: خطأ في الشبكة: - Failed to parse update information. فشل في تحليل معلومات التحديث. - No pre-releases found. لم يتم العثور على أي إصدارات مسبقة. - Invalid release data. بيانات الإصدار غير صالحة. - No download URL found for the specified asset. لم يتم العثور على عنوان URL للتنزيل للأصل المحدد. - Your version is already up to date! نسختك محدثة بالفعل! - Update Available تحديث متاح - Update Channel قناة التحديث - Current Version الإصدار الحالي - Latest Version آخر إصدار - Do you want to update? هل تريد التحديث؟ - Show Changelog عرض سجل التغييرات - Check for Updates at Startup تحقق من التحديثات عند بدء التشغيل - Update تحديث - No لا - Hide Changelog إخفاء سجل التغييرات - Changes تغييرات - Network error occurred while trying to access the URL حدث خطأ في الشبكة أثناء محاولة الوصول إلى عنوان URL - Download Complete اكتمل التنزيل - The update has been downloaded, press OK to install. تم تنزيل التحديث، اضغط على OK للتثبيت. - Failed to save the update file at فشل في حفظ ملف التحديث في - Starting Update... بدء التحديث... - Failed to create the update script file فشل في إنشاء ملف سكريبت التحديث + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 2448d4426..ef1ae27a3 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Trick / Patches - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Åbn Mappe... - Open Game Folder Åbn Spilmappe - Open Save Data Folder Åbn Gem Data Mappe - Open Log Folder Åbn Log Mappe - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Tjek for opdateringer - 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 - Download Cheats/Patches Download Tricks / Patches - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Hjælp - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Spiloversigt + + + * 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! + Opdatering detekteret! + + + PKG and Game versions match: + PKG og spilversioner matcher: + + + Would you like to overwrite? + Vil du overskrive? + + + PKG Version %1 is older than installed version: + PKG Version %1 er ældre end den installerede version: + + + Game is installed: + Spillet er installeret: + + + Would you like to install Patch: + Vil du installere opdateringen: + + + DLC Installation + DLC Installation + + + 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 + + + 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Aktiver Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Åbn logplacering + + Input Indtastning - Cursor Markør - Hide Cursor Skjul markør - Hide Cursor Idle Timeout Timeout for skjul markør ved inaktivitet - + s + s + + Controller Controller - Back Button Behavior Tilbageknap adfærd - 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 - Paths Stier - Game Folders Spilmapper - Add... Tilføj... - Remove Fjern - 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 - Update Opdatering - Check for Updates at Startup Tjek for opdateringer ved start - Update Channel Opdateringskanal - Check for Updates Tjek for opdateringer - GUI Settings GUI-Indstillinger - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Afspil titelsang - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Lydstyrke - - - MainWindow - - Game List - Spiloversigt + Audio Backend + Audio Backend - - * 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! - Opdatering detekteret! - - - - PKG and Game versions match: - PKG og spilversioner matcher: - - - - Would you like to overwrite? - Vil du overskrive? - - - - PKG Version %1 is older than installed version: - PKG Version %1 er ældre end den installerede version: - - - - Game is installed: - Spillet er installeret: - - - - Would you like to install Patch: - Vil du installere opdateringen: - - - - DLC Installation - DLC Installation - - - - 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 - - - - 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 for - Cheats / Patches for - - - - 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. Hvis opdateringen ikke vises, kan det være, at den ikke findes for den specifikke serie og version af spillet. - - - - Failed to parse JSON data from HTML. - Kunne ikke analysere JSON-data fra HTML. - - - - Failed to retrieve HTML page. - Kunne ikke hente HTML-side. - - - - The game is in version: %1 - Spillet er i version: %1 - - - - The downloaded patch only works on version: %1 - Den downloadede patch fungerer kun på version: %1 - - - - You may need to update your game. - Du skal muligvis opdatere dit spil. - - - - Incompatibility Notice - Uforenelighedsmeddelelse - - - - 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: - - - - Can't apply cheats before the game is started - Kan ikke anvende snyd før spillet er startet. - - - - SettingsDialog - - - Save - Gem - - - Apply Anvend - Restore Defaults Gendan standardindstillinger - Close Luk - Point your mouse at an option to display its description. Peg musen over et valg for at vise dets beskrivelse. - consoleLanguageGroupBox Konsolsprog:\nIndstiller sproget, som PS4-spillet bruger.\nDet anbefales at indstille dette til et sprog, som spillet understøtter, hvilket kan variere efter region. - emulatorLanguageGroupBox Emulatorsprog:\nIndstiller sproget i emulatorens brugergrænseflade. - fullscreenCheckBox Aktiver fuld skærm:\nSætter automatisk spilvinduet i fuld skærm.\nDette kan skiftes ved at trykke på F11-tasten. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Vis startskærm:\nViser en startskærm (speciel grafik) under opstarten. - ps4proCheckBox Er det en PS4 Pro:\nGør det muligt for emulatoren at fungere som en PS4 PRO, hvilket kan aktivere visse funktioner i spil, der understøtter det. - discordRPCCheckbox Aktiver Discord Rich Presence:\nViser emulatorikonet og relevante oplysninger på din Discord-profil. - userName Brugernavn:\nIndstiller PS4-kontoens navn, som kan blive vist i nogle spil. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Logtype:\nIndstiller, om logvinduets output vil blive synkroniseret for at øge ydeevnen. Dette kan påvirke emulatorens ydeevne negativt. - logFilter Logfilter:\nFiltrerer loggen for kun at udskrive bestemte oplysninger.\nEksempler: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Niveaus: Trace, Debug, Info, Warning, Error, Critical - i rækkefølge, et valgt niveau skjuler alle forudgående niveauer og viser alle efterfølgende niveauer. - updaterGroupBox Opdatering:\nRelease: Officielle builds, der frigives månedligt, som kan være meget ældre, men mere stabile og testet.\nNightly: Udviklerbuilds med de nyeste funktioner og rettelser, men som kan indeholde fejl og være mindre stabile. - GUIgroupBox Titelsmusikafspilning:\nHvis spillet understøtter det, aktiver speciel musik, når spillet vælges i brugergrænsefladen. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Skjul Cursor:\nVælg hvornår cursoren skal forsvinde:\nAldrig: Du vil altid se musen.\nInaktiv: Indstil en tid for, hvornår den skal forsvinde efter at være inaktiv.\nAltid: du vil aldrig se musen. - idleTimeoutGroupBox Indstil en tid for, at musen skal forsvinde efter at være inaktiv. - backButtonBehaviorGroupBox Tilbageknap Adfærd:\nIndstiller controllerens tilbageknap til at efterligne tryk på den angivne position på PS4 berøringsflade. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Aldrig - Idle Inaktiv - Always Altid - Touchpad Left Berøringsplade Venstre - Touchpad Right Berøringsplade Højre - Touchpad Center Berøringsplade Center - None Ingen - graphicsAdapterGroupBox Grafikadapter:\nPå systemer med flere GPU'er skal du vælge den GPU, emulatoren vil bruge fra en rullemenu,\neller vælge "Auto Select" for at vælge den automatisk. - resolutionLayout Skærmopløsning:\nIndstiller emulatorvinduets størrelse under afspilning, som kan ændres under afspilning.\nDette er forskelligt fra selve spillets opløsning. - heightDivider Opdateringshastighedsdeler:\nMultiplicerer den frekvens, som emulatoren opdaterer billedet med, med dette tal. Ændring af dette kan have negative effekter, såsom hurtigere spil eller ødelagte funktioner! - dumpShadersCheckBox Aktiver dumping af Shaders:\nTil teknisk fejlfinding gemmer det spillets shaders i en mappe under afspilning. - nullGpuCheckBox Aktiver virtuel GPU:\nTil teknisk fejlfinding deaktiverer det spilvisning, som om der ikke var et grafikkort. - gameFoldersBox Spilmappen:\nListen over mapper til at tjekke for installerede spil. - addFolderButton Tilføj:\nTilføj en mappe til listen. - removeFolderButton Fjern:\nFjern en mappe fra listen. - debugDump Aktiver debugging-dump:\nGemmer import/export-symboler og headeroplysninger for det aktuelle PS4-program til en mappe. - vkValidationCheckBox Aktiver Vulkan-valideringslag:\nAktiverer et system, der validerer Vulkan-driverens tilstand og logger oplysninger om dens interne tilstand. Dette vil reducere ydeevnen og kan muligvis ændre emulatorens adfærd. - vkSyncValidationCheckBox Aktiver Vulkan-synkroniseringsvalidering:\nAktiverer et system, der validerer tidspunktet for Vulkan's renderingsopgaver. Dette vil reducere ydeevnen og kan muligvis ændre emulatorens adfærd. - rdocCheckBox Aktiver RenderDoc-fejlfinding:\nHvis aktiveret, giver det emulatoren mulighed for kompatibilitet med Renderdoc til at fange og analysere det aktuelle gengivne billede. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. Hvis opdateringen ikke vises, kan det være, at den ikke findes for den specifikke serie og version af spillet. + + + Failed to parse JSON data from HTML. + Kunne ikke analysere JSON-data fra HTML. + + + Failed to retrieve HTML page. + Kunne ikke hente HTML-side. + + + The game is in version: %1 + Spillet er i version: %1 + + + The downloaded patch only works on version: %1 + Den downloadede patch fungerer kun på version: %1 + + + You may need to update your game. + Du skal muligvis opdatere dit spil. + + + Incompatibility Notice + Uforenelighedsmeddelelse + + + 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: + + + Can't apply cheats before the game is started + Kan ikke anvende snyd før spillet er startet. + + GameListFrame - Icon Ikon - Name Navn - Serial Seriel - Compatibility Compatibility - Region Region - Firmware Firmware - Size Størrelse - Version Version - Path Sti - Play Time Spilletid - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Automatisk opdatering - Error Fejl - Network error: Netsværksfejl: - Failed to parse update information. Kunne ikke analysere opdateringsoplysninger. - No pre-releases found. Ingen forhåndsudgivelser fundet. - Invalid release data. Ugyldige udgivelsesdata. - No download URL found for the specified asset. Ingen download-URL fundet for den specificerede aktiver. - Your version is already up to date! Din version er allerede opdateret! - Update Available Opdatering tilgængelig - Update Channel Opdateringskanal - Current Version Nuværende version - Latest Version Nyeste version - Do you want to update? Vil du opdatere? - Show Changelog Vis ændringslog - Check for Updates at Startup Tjek for opdateringer ved start - Update Opdater - No Nej - Hide Changelog Skjul ændringslog - Changes Ændringer - Network error occurred while trying to access the URL Netsværksfejl opstod, mens der blev forsøgt at få adgang til URL'en - Download Complete Download fuldført - The update has been downloaded, press OK to install. Opdateringen er blevet downloadet, tryk på OK for at installere. - Failed to save the update file at Kunne ikke gemme opdateringsfilen på - Starting Update... Starter opdatering... - Failed to create the update script file Kunne ikke oprette opdateringsscriptfilen + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index dd98c209b..2fc6a29fe 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 Über shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 ist ein experimenteller Open-Source-Emulator für die Playstation 4. - 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 +25,6 @@ ElfViewer - Open Folder Ordner öffnen @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Lade Spielliste, bitte warten :3 - Cancel Abbrechen - Loading... Lade... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Wähle Ordner - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Wähle Ordner - Directory to install games Installationsverzeichnis für Spiele - Browse Durchsuchen - Error Fehler - The value for location to install games is not valid. Der ausgewählte Ordner ist nicht gültig. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Verknüpfung erstellen - Cheats / Patches Cheats / Patches - SFO Viewer SFO anzeigen - Trophy Viewer Trophäen anzeigen - Open Folder... Ordner öffnen... - Open Game Folder Spielordner öffnen - Open Save Data Folder Speicherordner öffnen - Open Log Folder Protokollordner öffnen - Copy info... Infos kopieren... - Copy Name Namen kopieren - Copy Serial Seriennummer kopieren - Copy All Alles kopieren - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Verknüpfungserstellung - - Shortcut created successfully!\n %1 - Verknüpfung erfolgreich erstellt!\n %1 + Shortcut created successfully! + Verknüpfung erfolgreich erstellt! - Error Fehler - - Error creating shortcut!\n %1 - Fehler beim Erstellen der Verknüpfung!\n %1 + Error creating shortcut! + Fehler beim Erstellen der Verknüpfung! - Install PKG PKG installieren - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Elf-Ordner öffnen/hinzufügen - Install Packages (PKG) Pakete installieren (PKG) - Boot Game Spiel starten - Check for Updates Nach Updates suchen - About shadPS4 Über shadPS4 - Configure... Konfigurieren... - Install application from a .pkg file Installiere Anwendung aus .pkg-Datei - Recent Games Zuletzt gespielt - Exit Beenden - Exit shadPS4 shadPS4 beenden - Exit the application. Die Anwendung beenden. - Show Game List Spielliste anzeigen - Game List Refresh Spielliste aktualisieren - Tiny Winzig - Small Klein - Medium Mittel - Large Groß - List View Listenansicht - Grid View Gitteransicht - Elf Viewer Elf-Ansicht - Game Install Directory Installationsverzeichnis für Spiele - Download Cheats/Patches Cheats / Patches herunterladen - Dump Game List Spielliste ausgeben - PKG Viewer PKG-Ansicht - Search... Suchen... - File Datei - View Ansicht - Game List Icons Game List Icons - Game List Mode Spiellisten-Symoble - Settings Einstellungen - Utils Werkzeuge - Themes Stile - Help Hilfe - Dark Dunkel - Light Hell - Green Grün - Blue Blau - Violet Violett - toolBar toolBar + + Game List + Spieleliste + + + * 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! + Patch erkannt! + + + PKG and Game versions match: + PKG- und Spielversionen stimmen überein: + + + Would you like to overwrite? + Willst du überschreiben? + + + PKG Version %1 is older than installed version: + PKG-Version %1 ist älter als die installierte Version: + + + Game is installed: + Spiel ist installiert: + + + Would you like to install Patch: + Willst du den Patch installieren: + + + DLC Installation + DLC-Installation + + + Would you like to install DLC: %1? + Willst du den DLC installieren: %1? + + + DLC already installed: + DLC bereits installiert: + + + Game already installed + Spiel bereits installiert + + + PKG is a patch, please install the game first! + PKG ist ein Patch, bitte installieren Sie zuerst das Spiel! + + + PKG ERROR + PKG-FEHLER + + + 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 + PKGViewer - Open Folder Ordner öffnen @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophäenansicht @@ -458,989 +509,704 @@ SettingsDialog - Settings Einstellungen - General Allgemein - System System - Console Language Konsolensprache - Emulator Language Emulatorsprache - Emulator Emulator - Enable Fullscreen Vollbild aktivieren - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Startbildschirm anzeigen - Is PS4 Pro Ist PS4 Pro - Enable Discord Rich Presence Discord Rich Presence aktivieren - Username Benutzername - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Logtyp - Log Filter Log-Filter - + Open Log Location + Protokollspeicherort öffnen + + Input Eingabe - Cursor Cursor - Hide Cursor Cursor ausblenden - Hide Cursor Idle Timeout Inaktivitätszeitüberschreitung zum Ausblenden des Cursors - + s + s + + Controller Controller - Back Button Behavior Verhalten der Zurück-Taste - Graphics Grafik - Graphics Device Grafikgerät - Width Breite - Height Höhe - Vblank Divider Vblank-Teiler - Advanced Erweitert - Enable Shaders Dumping Shader-Dumping aktivieren - Enable NULL GPU NULL GPU aktivieren - Paths Pfad - Game Folders Spieleordner - Add... Hinzufügen... - Remove Entfernen - Debug Debug - Enable Debug Dumping Debug-Dumping aktivieren - Enable Vulkan Validation Layers Vulkan Validations-Ebenen aktivieren - Enable Vulkan Synchronization Validation Vulkan Synchronisations-Validierung aktivieren - Enable RenderDoc Debugging RenderDoc-Debugging aktivieren - Update Aktualisieren - Check for Updates at Startup Beim Start nach Updates suchen - Update Channel Update-Kanal - Check for Updates Nach Updates suchen - GUI Settings GUI-Einstellungen - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Titelmusik abspielen - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Lautstärke - - - MainWindow - - Game List - Spieleliste + Audio Backend + Audio Backend - - * 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! - Patch erkannt! - - - - PKG and Game versions match: - PKG- und Spielversionen stimmen überein: - - - - Would you like to overwrite? - Willst du überschreiben? - - - - PKG Version %1 is older than installed version: - PKG-Version %1 ist älter als die installierte Version: - - - - Game is installed: - Spiel ist installiert: - - - - Would you like to install Patch: - Willst du den Patch installieren: - - - - DLC Installation - DLC-Installation - - - - Would you like to install DLC: %1? - Willst du den DLC installieren: %1? - - - - DLC already installed: - DLC bereits installiert: - - - - Game already installed - Spiel bereits installiert - - - - PKG is a patch, please install the game first! - PKG ist ein Patch, bitte installieren Sie zuerst das Spiel! - - - - PKG ERROR - PKG-FEHLER - - - - 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 for - Cheats / Patches for - - - - defaultTextEdit_MSG - 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 - - - - 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. - Du kannst die Cheats, die du nicht möchtest, nach dem Herunterladen löschen. - - - - Do you want to delete the selected file?\n%1 - Willst du 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öchtest du 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. Versuche es mit einem anderen Repository oder einer anderen Version des Spiels. - - - - Cheats Downloaded Successfully - Cheats erfolgreich heruntergeladen - - - - CheatsDownloadedSuccessfully_MSG - 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. - - - - 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. Wenn der Patch nicht angezeigt wird, könnte es sein, dass er für die spezifische Seriennummer und Version des Spiels nicht existiert. - - - - 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. - - - - The game is in version: %1 - Das Spiel ist in der Version: %1 - - - - The downloaded patch only works on version: %1 - Der heruntergeladene Patch funktioniert nur in der Version: %1 - - - - You may need to update your game. - Sie müssen möglicherweise Ihr Spiel aktualisieren. - - - - Incompatibility Notice - Inkompatibilitätsbenachrichtigung - - - - 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: - - - - Can't apply cheats before the game is started - Kann keine Cheats anwenden, bevor das Spiel gestartet ist. - - - - SettingsDialog - - - Save - Speichern - - - Apply Übernehmen - Restore Defaults Werkseinstellungen wiederherstellen - Close Schließen - Point your mouse at an option to display its description. Bewege die Maus über eine Option, um deren Beschreibung anzuzeigen. - consoleLanguageGroupBox Konsolensprache:\nLegt die Sprache fest, die das PS4-Spiel verwendet.\nEs wird empfohlen, diese auf eine vom Spiel unterstützte Sprache einzustellen, die je nach Region unterschiedlich sein kann. - emulatorLanguageGroupBox Emulatorsprache:\nLegt die Sprache der Emulator-Benutzeroberfläche fest. - fullscreenCheckBox Vollbildmodus aktivieren:\nSchaltet das Spielfenster automatisch in den Vollbildmodus.\nKann durch Drücken der F11-Taste umgeschaltet werden. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Startbildschirm anzeigen:\nZeigt beim Start einen speziellen Bildschirm (Splash) des Spiels an. - ps4proCheckBox Ist es eine PS4 Pro:\nErmöglicht es dem Emulator, als PS4 PRO zu arbeiten, was in Spielen, die dies unterstützen, spezielle Funktionen aktivieren kann. - discordRPCCheckbox Discord Rich Presence aktivieren:\nZeigt das Emulator-Icon und relevante Informationen in deinem Discord-Profil an. - userName Benutzername:\nLegt den Namen des PS4-Kontos fest, der in einigen Spielen angezeigt werden kann. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Protokolltyp:\nLegt fest, ob die Ausgabe des Protokollfensters synchronisiert wird, um die Leistung zu verbessern. Dies kann sich negativ auf die Emulation auswirken. - logFilter Protokollfilter:\nFiltert das Protokoll so, dass nur bestimmte Informationen ausgegeben werden.\nBeispiele: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Ebenen: Trace, Debug, Info, Warning, Error, Critical - in dieser Reihenfolge, ein ausgewähltes Level blendet alle vorherigen Ebenen aus und zeigt alle nachfolgenden an. - updaterGroupBox Update:\nRelease: Offizielle Builds, die monatlich veröffentlicht werden, können viel älter sein, aber stabiler und getestet.\nNightly: Entwickler-Builds, die die neuesten Funktionen und Fehlerbehebungen enthalten, aber Fehler enthalten und weniger stabil sein können. - GUIgroupBox Wiedergabe der Titelmusik:\nWenn das Spiel dies unterstützt, wird beim Auswählen des Spiels in der Benutzeroberfläche spezielle Musik abgespielt. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Maus ausblenden:\nWählen Sie, wann der Cursor verschwinden soll:\nNie: Sie sehen die Maus immer.\nInaktiv: Legen Sie eine Zeit fest, nach der sie nach Inaktivität verschwindet.\nImmer: Sie sehen die Maus niemals. - idleTimeoutGroupBox Stellen Sie eine Zeit ein, nach der die Maus nach Inaktivität verschwinden soll. - backButtonBehaviorGroupBox Zurück-Button Verhalten:\nStellt die Zurück-Taste des Controllers so ein, dass sie das Antippen der angegebenen Position auf dem PS4-Touchpad emuliert. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Niemals - Idle Im Leerlauf - Always Immer - Touchpad Left Touchpad Links - Touchpad Right Touchpad Rechts - Touchpad Center Touchpad Mitte - None Keine - graphicsAdapterGroupBox Grafikkarte:\nAuf Systemen mit mehreren GPUs wählen Sie aus einem Dropdown-Menü die GPU aus, die der Emulator verwenden wird,\noder wählen Sie "Auto Select", um sie automatisch auszuwählen. - resolutionLayout Auflösung:\nLegt die Größe des Emulator-Fensters während der Wiedergabe fest, die während der Wiedergabe geändert werden kann.\nDies unterscheidet sich von der tatsächlichen Spielauflösung. - heightDivider Framerate-Teiler:\nMultipliziert die Bildrate, mit der der Emulator aktualisiert wird, mit diesem Wert. Dies kann sich negativ auswirken, wie z.B. beschleunigtes Gameplay oder Funktionsstörungen! - dumpShadersCheckBox Shader-Dumping aktivieren:\nZum technischen Debuggen speichert es die Shaders des Spiels in einem Ordner während der Wiedergabe. - nullGpuCheckBox Virtuelle GPU aktivieren:\nFür das technische Debugging deaktiviert es die Spielanzeige, als ob keine Grafikkarte vorhanden wäre. - gameFoldersBox Spieleordner:\nDie Liste der Ordner, in denen nach installierten Spielen gesucht wird. - addFolderButton Hinzufügen:\nFügen Sie einen Ordner zur Liste hinzu. - removeFolderButton Entfernen:\nEntfernen Sie einen Ordner aus der Liste. - debugDump Debug-Dump aktivieren:\nSpeichert Import-/Exportsymbole und Headerinformationen des aktuellen PS4-Programms in einem Verzeichnis. - vkValidationCheckBox Vulkan-Validierungsebenen aktivieren:\nAktiviert ein System, das den Zustand des Vulkan-Treibers validiert und Informationen über dessen internen Zustand protokolliert. Dies verringert die Leistung und kann möglicherweise das Verhalten der Emulation ändern. - vkSyncValidationCheckBox Vulkan-Synchronisationsvalidierung aktivieren:\nAktiviert ein System, das die Zeitplanung der Rendering-Aufgaben von Vulkan validiert. Dies wird die Leistung verringern und kann möglicherweise das Verhalten der Emulation ändern. - rdocCheckBox RenderDoc-Debugging aktivieren:\nWenn aktiviert, bietet der Emulator Kompatibilität mit Renderdoc zur Erfassung und Analyse des aktuell gerenderten Frames. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + defaultTextEdit_MSG + 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 + + + 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. + Du kannst die Cheats, die du nicht möchtest, nach dem Herunterladen löschen. + + + Do you want to delete the selected file?\n%1 + Willst du 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öchtest du 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. Versuche es mit einem anderen Repository oder einer anderen Version des Spiels. + + + Cheats Downloaded Successfully + Cheats erfolgreich heruntergeladen + + + CheatsDownloadedSuccessfully_MSG + 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. + + + 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. Wenn der Patch nicht angezeigt wird, könnte es sein, dass er für die spezifische Seriennummer und Version des Spiels nicht existiert. + + + 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. + + + The game is in version: %1 + Das Spiel ist in der Version: %1 + + + The downloaded patch only works on version: %1 + Der heruntergeladene Patch funktioniert nur in der Version: %1 + + + You may need to update your game. + Sie müssen möglicherweise Ihr Spiel aktualisieren. + + + Incompatibility Notice + Inkompatibilitätsbenachrichtigung + + + 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: + + + Can't apply cheats before the game is started + Kann keine Cheats anwenden, bevor das Spiel gestartet ist. + + GameListFrame - Icon Symbol - Name Name - Serial Seriennummer - Compatibility Compatibility - Region Region - Firmware Firmware - Size Größe - Version Version - Path Pfad - Play Time Spielzeit - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Automatischer Aktualisierer - Error Fehler - Network error: Netzwerkfehler: - Failed to parse update information. Fehler beim Parsen der Aktualisierungsinformationen. - No pre-releases found. Keine Vorabveröffentlichungen gefunden. - Invalid release data. Ungültige Versionsdaten. - No download URL found for the specified asset. Keine Download-URL für das angegebene Asset gefunden. - Your version is already up to date! Ihre Version ist bereits aktuell! - Update Available Aktualisierung verfügbar - Update Channel Update-Kanal - Current Version Aktuelle Version - Latest Version Neueste Version - Do you want to update? Möchten Sie aktualisieren? - Show Changelog Änderungsprotokoll anzeigen - Check for Updates at Startup Beim Start nach Updates suchen - Update Aktualisieren - No Nein - Hide Changelog Änderungsprotokoll ausblenden - Changes Änderungen - Network error occurred while trying to access the URL Beim Zugriff auf die URL ist ein Netzwerkfehler aufgetreten - Download Complete Download abgeschlossen - The update has been downloaded, press OK to install. Die Aktualisierung wurde heruntergeladen, drücken Sie OK, um zu installieren. - Failed to save the update file at Fehler beim Speichern der Aktualisierungsdatei in - Starting Update... Aktualisierung wird gestartet... - Failed to create the update script file Fehler beim Erstellen der Aktualisierungs-Skriptdatei + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts index afb8ebddf..8d3885808 100644 --- a/src/qt_gui/translations/el.ts +++ b/src/qt_gui/translations/el.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Kodikí / Enimeróseis - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Άνοιγμα Φακέλου... - Open Game Folder Άνοιγμα Φακέλου Παιχνιδιού - Open Save Data Folder Άνοιγμα Φακέλου Αποθηκευμένων Δεδομένων - Open Log Folder Άνοιγμα Φακέλου Καταγραφής - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Έλεγχος για ενημερώσεις - About shadPS4 About shadPS4 - Configure... Configure... - Install application from a .pkg file Install application from a .pkg file - Recent Games Recent Games - Exit Exit - Exit shadPS4 Exit shadPS4 - Exit the application. Exit the application. - Show Game List Show Game List - Game List Refresh Game List Refresh - Tiny Tiny - Small Small - Medium Medium - Large Large - List View List View - Grid View Grid View - Elf Viewer Elf Viewer - Game Install Directory Game Install Directory - Download Cheats/Patches Κατεβάστε Κωδικούς / Ενημερώσεις - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Βοήθεια - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Λίστα παιχνιδιών + + + * 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! + Αναγνώριση ενημέρωσης! + + + 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 είναι 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Ενεργοποίηση Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Άνοιγμα τοποθεσίας αρχείου καταγραφής + + Input Είσοδος - Cursor Δείκτης - Hide Cursor Απόκρυψη δείκτη - Hide Cursor Idle Timeout Χρόνος αδράνειας απόκρυψης δείκτη - + s + s + + Controller Controller - Back Button Behavior Συμπεριφορά κουμπιού επιστροφής - 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 - Paths Διαδρομές - Game Folders Φάκελοι παιχνιδιών - Add... Προσθήκη... - Remove Αφαίρεση - Debug Debug - Enable Debug Dumping Enable Debug Dumping - Enable Vulkan Validation Layers Enable Vulkan Validation Layers - Enable Vulkan Synchronization Validation Enable Vulkan Synchronization Validation - Enable RenderDoc Debugging Enable RenderDoc Debugging - Update Ενημέρωση - Check for Updates at Startup Έλεγχος για ενημερώσεις κατά την εκκίνηση - Update Channel Κανάλι Ενημέρωσης - Check for Updates Έλεγχος για ενημερώσεις - GUI Settings Ρυθμίσεις GUI - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Αναπαραγωγή μουσικής τίτλου - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume ένταση - - - MainWindow - - Game List - Λίστα παιχνιδιών + Audio Backend + Audio Backend - - * 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! - Αναγνώριση ενημέρωσης! - - - - 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 είναι 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 for - Cheats / Patches for - - - - 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. - - - - The game is in version: %1 - Το παιχνίδι είναι στην έκδοση: %1 - - - - The downloaded patch only works on version: %1 - Η ληφθείσα ενημέρωση λειτουργεί μόνο στην έκδοση: %1 - - - - You may need to update your game. - Μπορεί να χρειαστεί να ενημερώσετε το παιχνίδι σας. - - - - Incompatibility Notice - Ειδοποίηση ασυμβατότητας - - - - 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: - Όνομα: - - - - Can't apply cheats before the game is started - Δεν μπορείτε να εφαρμόσετε cheats πριν ξεκινήσει το παιχνίδι. - - - - SettingsDialog - - - Save - Αποθήκευση - - - Apply Εφαρμογή - Restore Defaults Επαναφορά Προεπιλογών - Close Κλείσιμο - Point your mouse at an option to display its description. Τοποθετήστε το ποντίκι σας πάνω σε μια επιλογή για να εμφανίσετε την περιγραφή της. - consoleLanguageGroupBox Γλώσσα Κονσόλας:\nΡυθμίζει τη γλώσσα που θα χρησιμοποιήσει το παιχνίδι PS4.\nΣυνιστάται να επιλέξετε μία από τις γλώσσες που υποστηρίζονται από το παιχνίδι, η οποία ενδέχεται να διαφέρει ανάλογα με την περιοχή. - emulatorLanguageGroupBox Γλώσσα Εξομοιωτή:\nΡυθμίζει τη γλώσσα του γραφικού περιβάλλοντος του εξομοιωτή. - fullscreenCheckBox Ενεργοποίηση Πλήρους Οθόνης:\nΑυτόματα μετατρέπει το παράθυρο του παιχνιδιού σε λειτουργία πλήρους οθόνης.\nΜπορεί να ενεργοποιηθεί/απενεργοποιηθεί πατώντας το πλήκτρο F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Εμφάνιση Splash Screen:\nΕμφανίζει ειδική γραφική οθόνη κατά την εκκίνηση. - ps4proCheckBox Είναι PS4 Pro:\nΕπιτρέπει στον εξομοιωτή να λειτουργεί σαν PS4 PRO, κάτι που μπορεί να ενεργοποιήσει συγκεκριμένες λειτουργίες σε παιχνίδια που το υποστηρίζουν. - discordRPCCheckbox Ενεργοποίηση Discord Rich Presence:\nΕμφανίζει το εικονίδιο του emulator και σχετικές πληροφορίες στο προφίλ σας στο Discord. - userName Όνομα Χρήστη:\nΟρίζει το όνομα του λογαριασμού PS4, το οποίο μπορεί να εμφανιστεί σε ορισμένα παιχνίδια. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Τύπος Καταγραφής:\nΚαθορίζει αν η έξοδος του παραθύρου καταγραφής θα συγχρονιστεί για αύξηση της απόδοσης. Αυτό μπορεί να επηρεάσει αρνητικά τις επιδόσεις του εξομοιωτή. - logFilter Φίλτρο Καταγραφής:\nΦιλτράρει τις καταγραφές ώστε να εκτυπώνονται μόνο συγκεκριμένες πληροφορίες.\nΠαραδείγματα: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Επίπεδα: Trace, Debug, Info, Warning, Error, Critical - με τη σειρά αυτή, κάθε επίπεδο που επιλέγεται αποκλείει τα προηγούμενα και εμφανίζει τα επόμενα επίπεδα. - updaterGroupBox Ενημερώσεις:\nRelease: Επίσημες εκδόσεις που κυκλοφορούν μηνιαίως, είναι παλαιότερες αλλά πιο σταθερές και δοκιμασμένες.\nNightly: Εκδόσεις προγραμματιστών με νέες δυνατότητες και διορθώσεις, αλλά μπορεί να περιέχουν σφάλματα και να είναι λιγότερο σταθερές. - GUIgroupBox Αναπαραγωγή Μουσικής Τίτλων:\nΕάν το παιχνίδι το υποστηρίζει, ενεργοποιεί ειδική μουσική κατά την επιλογή του παιχνιδιού από τη διεπαφή χρήστη. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Απόκρυψη Κέρσορα:\nΕπιλέξτε πότε θα εξαφανιστεί ο κέρσορας:\nΠοτέ: θα βλέπετε πάντα το ποντίκι.\nΑδρανές: ορίστε έναν χρόνο για να εξαφανιστεί μετά από αδράνεια.\nΠάντα: δεν θα δείτε ποτέ το ποντίκι. - idleTimeoutGroupBox Ορίστε έναν χρόνο για να εξαφανιστεί το ποντίκι μετά από αδράνεια. - backButtonBehaviorGroupBox Συμπεριφορά Κουμπιού Επιστροφής:\nΟρίζει το κουμπί επιστροφής του ελεγκτή να προσομοιώνει το πάτημα της καθορισμένης θέσης στην οθόνη αφής PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Ποτέ - Idle Αδρανής - Always Πάντα - Touchpad Left Touchpad Αριστερά - Touchpad Right Touchpad Δεξιά - Touchpad Center Κέντρο Touchpad - None Κανένα - graphicsAdapterGroupBox Προσαρμογέας Γραφικών:\nΣε συστήματα με πολλές GPU, επιλέξτε από το μενού την GPU που θα χρησιμοποιήσει ο εξομοιωτής,\nή επιλέξτε "Auto Select" για αυτόματη επιλογή. - resolutionLayout Ανάλυση Οθόνης:\nΚαθορίζει το μέγεθος του παραθύρου του εξομοιωτή κατά την αναπαραγωγή, το οποίο μπορεί να αλλάξει κατά τη διάρκεια του παιχνιδιού.\nΑυτό είναι διαφορετικό από την ανάλυση του ίδιου του παιχνιδιού. - heightDivider Διαιρέτης Συχνότητας Ανανέωσης:\nΠολλαπλασιάζει τον ρυθμό με τον οποίο ο εξομοιωτής ενημερώνει την εικόνα με αυτόν τον αριθμό. Η αλλαγή αυτής της ρύθμισης μπορεί να έχει αρνητικές επιπτώσεις, όπως ταχύτερο παιχνίδι ή σπασμένες λειτουργίες! - dumpShadersCheckBox Ενεργοποίηση Καταγραφής Σκιάσεων (Shaders):\nΓια τεχνικό εντοπισμό σφαλμάτων, αποθηκεύει τις σκιάσεις του παιχνιδιού σε φάκελο κατά τη διάρκεια της αναπαραγωγής. - nullGpuCheckBox Ενεργοποίηση Εικονικής GPU:\nΓια τεχνικό εντοπισμό σφαλμάτων, απενεργοποιεί την εμφάνιση του παιχνιδιού σαν να μην υπάρχει κάρτα γραφικών. - gameFoldersBox Φάκελοι Παιχνιδιών:\nΗ λίστα των φακέλων για έλεγχο των εγκατεστημένων παιχνιδιών. - addFolderButton Προσθήκη:\nΠροσθέστε έναν φάκελο στη λίστα. - removeFolderButton Αφαίρεση:\nΑφαιρέστε έναν φάκελο από τη λίστα. - debugDump Ενεργοποίηση Καταγραφής Αποσφαλμάτωσης:\nΑποθηκεύει τα σύμβολα εισαγωγής/εξαγωγής και τις κεφαλίδες πληροφοριών του τρέχοντος προγράμματος PS4 σε έναν φάκελο. - vkValidationCheckBox Ενεργοποίηση Επικύρωσης Vulkan:\nΕνεργοποιεί ένα σύστημα που επικυρώνει την κατάσταση του προγράμματος οδήγησης Vulkan και καταγράφει πληροφορίες για την εσωτερική του κατάσταση. Αυτό θα μειώσει την απόδοση και ενδέχεται να αλλάξει τη συμπεριφορά του εξομοιωτή. - vkSyncValidationCheckBox Ενεργοποίηση Επικύρωσης Συγχρονισμού Vulkan:\nΕνεργοποιεί ένα σύστημα που επικυρώνει τον συγχρονισμό των εργασιών απόδοσης του Vulkan. Αυτό θα μειώσει την απόδοση και ενδέχεται να αλλάξει τη συμπεριφορά του εξομοιωτή. - rdocCheckBox Ενεργοποίηση Καταγραφής RenderDoc:\nΌταν είναι ενεργοποιημένο, ο εξομοιωτής είναι συμβατός με το RenderDoc για τη λήψη και ανάλυση του τρέχοντος καρέ. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. + + + The game is in version: %1 + Το παιχνίδι είναι στην έκδοση: %1 + + + The downloaded patch only works on version: %1 + Η ληφθείσα ενημέρωση λειτουργεί μόνο στην έκδοση: %1 + + + You may need to update your game. + Μπορεί να χρειαστεί να ενημερώσετε το παιχνίδι σας. + + + Incompatibility Notice + Ειδοποίηση ασυμβατότητας + + + 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: + Όνομα: + + + Can't apply cheats before the game is started + Δεν μπορείτε να εφαρμόσετε cheats πριν ξεκινήσει το παιχνίδι. + + GameListFrame - Icon Εικονίδιο - Name Όνομα - Serial Σειριακός αριθμός - Compatibility Compatibility - Region Περιοχή - Firmware Λογισμικό - Size Μέγεθος - Version Έκδοση - Path Διαδρομή - Play Time Χρόνος παιχνιδιού - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Αυτόματος Ενημερωτής - Error Σφάλμα - Network error: Σφάλμα δικτύου: - Failed to parse update information. Αποτυχία ανάλυσης πληροφοριών ενημέρωσης. - No pre-releases found. Δεν βρέθηκαν προ-κυκλοφορίες. - Invalid release data. Μη έγκυρα δεδομένα έκδοσης. - No download URL found for the specified asset. Δεν βρέθηκε URL λήψης για το συγκεκριμένο στοιχείο. - Your version is already up to date! Η έκδοσή σας είναι ήδη ενημερωμένη! - Update Available Διαθέσιμη Ενημέρωση - Update Channel Κανάλι Ενημέρωσης - Current Version Τρέχουσα Έκδοση - Latest Version Τελευταία Έκδοση - Do you want to update? Θέλετε να ενημερώσετε; - Show Changelog Εμφάνιση Ιστορικού Αλλαγών - Check for Updates at Startup Έλεγχος για ενημερώσεις κατά την εκκίνηση - Update Ενημέρωση - No Όχι - Hide Changelog Απόκρυψη Ιστορικού Αλλαγών - Changes Αλλαγές - Network error occurred while trying to access the URL Σφάλμα δικτύου κατά την προσπάθεια πρόσβασης στη διεύθυνση URL - Download Complete Λήψη ολοκληρώθηκε - The update has been downloaded, press OK to install. Η ενημέρωση έχει ληφθεί, πατήστε OK για να εγκαταστήσετε. - Failed to save the update file at Αποτυχία αποθήκευσης του αρχείου ενημέρωσης στο - Starting Update... Εκκίνηση Ενημέρωσης... - Failed to create the update script file Αποτυχία δημιουργίας του αρχείου σεναρίου ενημέρωσης + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts index 1bbc68e61..0262ee149 100644 --- a/src/qt_gui/translations/en.ts +++ b/src/qt_gui/translations/en.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Cheats / Patches - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Open Folder... - Open Game Folder Open Game Folder - Open Save Data Folder Open Save Data Folder - Open Log Folder Open Log Folder - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Check for Updates - About shadPS4 About shadPS4 - Configure... Configure... - Install application from a .pkg file Install application from a .pkg file - Recent Games Recent Games - Exit Exit - Exit shadPS4 Exit shadPS4 - Exit the application. Exit the application. - Show Game List Show Game List - Game List Refresh Game List Refresh - Tiny Tiny - Small Small - Medium Medium - Large Large - List View List View - Grid View Grid View - Elf Viewer Elf Viewer - Game Install Directory Game Install Directory - Download Cheats/Patches Download Cheats / Patches - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Help - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Game List + + + * Unsupported Vulkan Version + * Unsupported Vulkan Version + + + Download Cheats For All Installed Games + Download Cheats For All Installed Games + + + Download Patches For All Games + Download Patches For All Games + + + Download Complete + Download Complete + + + You have downloaded cheats for all the games you have installed. + You have downloaded cheats for all the games you have installed. + + + Patches Downloaded Successfully! + Patches Downloaded Successfully! + + + All Patches available for all games have been downloaded. + All Patches available for all games have been downloaded. + + + Games: + Games: + + + 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! + Patch detected! + + + PKG and Game versions match: + PKG and Game versions match: + + + Would you like to overwrite? + Would you like to overwrite? + + + PKG Version %1 is older than installed version: + PKG Version %1 is older than installed version: + + + Game is installed: + Game is installed: + + + Would you like to install Patch: + Would you like to install Patch: + + + DLC Installation + DLC Installation + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + + + DLC already installed: + DLC already installed: + + + Game already installed + Game already installed + + + PKG 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Enable Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Open Log Location + + Input Input - Cursor Cursor - Hide Cursor Hide Cursor - Hide Cursor Idle Timeout Hide Cursor Idle Timeout - + s + s + + Controller Controller - Back Button Behavior Back Button Behavior - Graphics Graphics - 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 - Paths Paths - Game Folders Game Folders - Add... Add... - Remove Remove - Debug Debug - Enable Debug Dumping Enable Debug Dumping - Enable Vulkan Validation Layers Enable Vulkan Validation Layers - Enable Vulkan Synchronization Validation Enable Vulkan Synchronization Validation - Enable RenderDoc Debugging Enable RenderDoc Debugging - Update Update - Check for Updates at Startup Check for Updates at Startup - Update Channel Update Channel - Check for Updates Check for Updates - GUI Settings GUI Settings - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Play title music - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Volume - - - MainWindow - - Game List - Game List + Audio Backend + Audio Backend - - * 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! - Patch detected! - - - - PKG and Game versions match: - PKG and Game versions match: - - - - Would you like to overwrite? - Would you like to overwrite? - - - - PKG Version %1 is older than installed version: - PKG Version %1 is older than installed version: - - - - Game is installed: - Game is installed: - - - - Would you like to install Patch: - Would you like to install Patch: - - - - DLC Installation - DLC Installation - - - - Would you like to install DLC: %1? - Would you like to install DLC: %1? - - - - DLC already installed: - DLC already installed: - - - - Game already installed - Game already installed - - - - PKG 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 for - Cheats / Patches for - - - - 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. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. - - - - Failed to parse JSON data from HTML. - Failed to parse JSON data from HTML. - - - - Failed to retrieve HTML page. - Failed to retrieve HTML page. - - - - The game is in version: %1 - The game is in version: %1 - - - - The downloaded patch only works on version: %1 - The downloaded patch only works on version: %1 - - - - You may need to update your game. - You may need to update your game. - - - - Incompatibility Notice - Incompatibility Notice - - - - Failed to open file: - Failed to open file: - - - - XML ERROR: - XML ERROR: - - - - Failed to open files.json for writing - Failed to open files.json for writing - - - - Author: - Author: - - - - Directory does not exist: - Directory does not exist: - - - - Failed to open files.json for reading. - Failed to open files.json for reading. - - - - Name: - Name: - - - - Can't apply cheats before the game is started - Can't apply cheats before the game is started. - - - - SettingsDialog - - - Save - Save - - - Apply Apply - Restore Defaults Restore Defaults - Close Close - Point your mouse at an option to display its description. Point your mouse at an option to display its description. - consoleLanguageGroupBox Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. - emulatorLanguageGroupBox Emulator Language:\nSets the language of the emulator's user interface. - fullscreenCheckBox Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID. - showSplashCheckBox Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. - ps4proCheckBox Is PS4 Pro:\nMakes the emulator act as a PS4 PRO, which may enable special features in games that support it. - discordRPCCheckbox Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. - userName Username:\nSets the PS4's account username, which may be displayed by some games. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. - logFilter Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. - updaterGroupBox Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. - GUIgroupBox Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. - idleTimeoutGroupBox Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. - backButtonBehaviorGroupBox Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Never - Idle Idle - Always Always - Touchpad Left Touchpad Left - Touchpad Right Touchpad Right - Touchpad Center Touchpad Center - None None - graphicsAdapterGroupBox Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - resolutionLayout Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. - heightDivider Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! - dumpShadersCheckBox Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. - nullGpuCheckBox Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - gameFoldersBox Game Folders:\nThe list of folders to check for installed games. - addFolderButton Add:\nAdd a folder to the list. - removeFolderButton Remove:\nRemove a folder from the list. - debugDump Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. - vkValidationCheckBox Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. - vkSyncValidationCheckBox Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks.\nThis will reduce performance and likely change the behavior of emulation. - rdocCheckBox Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. + + + Failed to parse JSON data from HTML. + Failed to parse JSON data from HTML. + + + Failed to retrieve HTML page. + Failed to retrieve HTML page. + + + The game is in version: %1 + The game is in version: %1 + + + The downloaded patch only works on version: %1 + The downloaded patch only works on version: %1 + + + You may need to update your game. + You may need to update your game. + + + Incompatibility Notice + Incompatibility Notice + + + Failed to open file: + Failed to open file: + + + XML ERROR: + XML ERROR: + + + Failed to open files.json for writing + Failed to open files.json for writing + + + Author: + Author: + + + Directory does not exist: + Directory does not exist: + + + Failed to open files.json for reading. + Failed to open files.json for reading. + + + Name: + Name: + + + Can't apply cheats before the game is started + Can't apply cheats before the game is started. + + GameListFrame - Icon Icon - Name Name - Serial Serial - Compatibility Compatibility - Region Region - Firmware Firmware - Size Size - Version Version - Path Path - Play Time Play Time - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Auto Updater - Error Error - Network error: Network error: - Failed to parse update information. Failed to parse update information. - No pre-releases found. No pre-releases found. - Invalid release data. Invalid release data. - No download URL found for the specified asset. No download URL found for the specified asset. - Your version is already up to date! Your version is already up to date! - Update Available Update Available - Update Channel Update Channel - Current Version Current Version - Latest Version Latest Version - Do you want to update? Do you want to update? - Show Changelog Show Changelog - Check for Updates at Startup Check for Updates at Startup - Update Update - No No - Hide Changelog Hide Changelog - Changes Changes - Network error occurred while trying to access the URL Network error occurred while trying to access the URL - Download Complete Download Complete - The update has been downloaded, press OK to install. The update has been downloaded, press OK to install. - Failed to save the update file at Failed to save the update file at - Starting Update... Starting Update... - Failed to create the update script file Failed to create the update script file + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 badb18d2f..a25ff639e 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 Acerca de shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 es un emulador experimental de código abierto para la PlayStation 4. - This software should not be used to play games you have not legally obtained. Este software no debe utilizarse para jugar juegos que hayas obtenido ilegalmente. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Abrir carpeta @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Cargando lista de juegos, por favor espera :3 - Cancel Cancelar - Loading... Cargando... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Elegir carpeta - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Elegir carpeta - Directory to install games Carpeta para instalar juegos - Browse Buscar - Error Error - 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Crear acceso directo - Cheats / Patches Trucos / Parches - SFO Viewer Vista SFO - Trophy Viewer Ver trofeos - Open Folder... Abrir Carpeta... - Open Game Folder Abrir Carpeta del Juego - Open Save Data Folder Abrir Carpeta de Datos Guardados - Open Log Folder Abrir Carpeta de Registros - Copy info... Copiar información... - Copy Name Copiar nombre - Copy Serial Copiar número de serie - Copy All Copiar todo - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Acceso directo creado - - Shortcut created successfully!\n %1 - ¡Acceso directo creado con éxito!\n %1 + Shortcut created successfully! + ¡Acceso directo creado con éxito! - Error Error - - Error creating shortcut!\n %1 - ¡Error al crear el acceso directo!\n %1 + Error creating shortcut! + ¡Error al crear el acceso directo! - Install PKG Instalar PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Abrir/Agregar carpeta Elf - Install Packages (PKG) Instalar paquetes (PKG) - Boot Game Iniciar juego - Check for Updates Buscar actualizaciones - About shadPS4 Acerca de shadPS4 - Configure... Configurar... - Install application from a .pkg file Instalar aplicación desde un archivo .pkg - Recent Games Juegos recientes - Exit Salir - Exit shadPS4 Salir de shadPS4 - Exit the application. Salir de la aplicación. - Show Game List Mostrar lista de juegos - Game List Refresh Actualizar lista de juegos - Tiny Muy pequeño - Small Pequeño - Medium Mediano - Large Grande - List View Vista de lista - Grid View Vista de cuadrícula - Elf Viewer Vista Elf - Game Install Directory Carpeta de instalación de los juegos - Download Cheats/Patches Descargar Trucos / Parches - Dump Game List Volcar lista de juegos - PKG Viewer Vista PKG - Search... Buscar... - File Archivo - View Vista - Game List Icons Iconos de los juegos - Game List Mode Tipo de lista - Settings Configuración - Utils Utilidades - Themes Temas - Help Ayuda - Dark Oscuro - Light Claro - Green Verde - Blue Azul - Violet Violeta - toolBar Barra de herramientas + + Game List + Lista de juegos + + + * 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 han sido descargados para todos los juegos. + + + 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! + ¡Actualización detectada! + + + PKG and Game versions match: + Las versiones de PKG y del juego coinciden: + + + Would you like to overwrite? + ¿Desea sobrescribir? + + + 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 + Instalación de DLC + + + Would you like to install DLC: %1? + ¿Desea instalar el DLC: %1? + + + DLC already installed: + DLC ya instalado: + + + Game already installed + Juego ya instalado + + + 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 parece no ser un archivo PKG válido + PKGViewer - Open Folder Abrir carpeta @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Vista de trofeos @@ -458,989 +509,704 @@ SettingsDialog - Settings Configuración - General General - System Sistema - Console Language Idioma de la consola - Emulator Language Idioma del emulador - Emulator Emulador - Enable Fullscreen Habilitar pantalla completa - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Mostrar splash - Is PS4 Pro Modo PS4 Pro - Enable Discord Rich Presence Habilitar Discord Rich Presence - Username Nombre de usuario - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Registro - Log Type Tipo de registro - Log Filter Filtro de registro - + Open Log Location + Abrir ubicación del registro + + Input Entrada - Cursor Cursor - Hide Cursor Ocultar cursor - Hide Cursor Idle Timeout Tiempo de espera para ocultar cursor inactivo - + s + s + + Controller Controlador - Back Button Behavior Comportamiento del botón de retroceso - Graphics Gráficos - Graphics Device Dispositivo gráfico - Width Ancho - Height Alto - Vblank Divider Divisor de Vblank - Advanced Avanzado - Enable Shaders Dumping Habilitar volcado de shaders - Enable NULL GPU Habilitar GPU NULL - Paths Rutas - Game Folders Carpetas de juego - Add... Añadir... - Remove Eliminar - Debug Depuración - Enable Debug Dumping Habilitar volcado de depuración - Enable Vulkan Validation Layers Habilitar capas de validación de Vulkan - Enable Vulkan Synchronization Validation Habilitar validación de sincronización de Vulkan - Enable RenderDoc Debugging Habilitar depuración de RenderDoc - Update Actualización - Check for Updates at Startup Buscar actualizaciones al iniciar - Update Channel Canal de Actualización - Check for Updates Verificar actualizaciones - GUI Settings Configuraciones de la Interfaz - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Reproducir la música de apertura - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Volumen - - - MainWindow - - Game List - Lista de juegos + Audio Backend + Audio Backend - - * 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 han sido descargados para todos los juegos. - - - - 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! - ¡Actualización detectada! - - - - PKG and Game versions match: - Las versiones de PKG y del juego coinciden: - - - - Would you like to overwrite? - ¿Desea sobrescribir? - - - - 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 - Instalación de DLC - - - - Would you like to install DLC: %1? - ¿Desea instalar el DLC: %1? - - - - DLC already installed: - DLC ya instalado: - - - - Game already installed - Juego ya instalado - - - - 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 parece no ser un archivo PKG válido - - - - CheatsPatches - - - Cheats / Patches for - Cheats / Patches for - - - - 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: - Número de 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 una vez descargados. - - - - 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 - Parches - - - - 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 el número de 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. Si el parche no aparece, puede ser que no exista para el número de serie y versión específicos del juego. - - - - 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. - - - - The game is in version: %1 - El juego está en la versión: %1 - - - - The downloaded patch only works on version: %1 - El parche descargado solo funciona en la versión: %1 - - - - You may need to update your game. - Puede que necesites actualizar tu juego. - - - - Incompatibility Notice - Aviso de incompatibilidad - - - - 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: - - - - Can't apply cheats before the game is started - No se pueden aplicar trucos antes de que se inicie el juego. - - - - SettingsDialog - - - Save - Guardar - - - Apply Aplicar - Restore Defaults Restaurar Valores Predeterminados - Close Cerrar - Point your mouse at an option to display its description. Coloque el mouse sobre una opción para mostrar su descripción. - consoleLanguageGroupBox Idioma de la Consola:\nEstablece el idioma que utiliza el juego de PS4.\nSe recomienda configurarlo a un idioma que el juego soporte, lo cual varía por región. - emulatorLanguageGroupBox Idioma del Emulador:\nConfigura el idioma de la interfaz de usuario del emulador. - fullscreenCheckBox Habilitar Pantalla Completa:\nColoca automáticamente la ventana del juego en modo de pantalla completa.\nEsto se puede alternar presionando la tecla F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Mostrar Pantalla de Inicio:\nMuestra la pantalla de inicio del juego (una imagen especial) mientras el juego se está iniciando. - ps4proCheckBox Es PS4 Pro:\nHace que el emulador actúe como una PS4 PRO, lo que puede habilitar funciones especiales en los juegos que lo admitan. - discordRPCCheckbox Habilitar Discord Rich Presence:\nMuestra el ícono del emulador y la información relevante en tu perfil de Discord. - userName Nombre de Usuario:\nEstablece el nombre de usuario de la cuenta de PS4, que puede ser mostrado por algunos juegos. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Tipo de Registro:\nEstablece si sincronizar la salida de la ventana de registro para mejorar el rendimiento. Puede tener efectos adversos en la emulación. - logFilter Filtro de Registro:\nFiltra el registro para imprimir solo información específica.\nEjemplos: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Niveles: Trace, Debug, Info, Warning, Error, Critical - en este orden, un nivel específico silencia todos los niveles anteriores en la lista y registra cada nivel posterior. - updaterGroupBox Actualización:\nRelease: Versiones oficiales lanzadas cada mes que pueden estar muy desactualizadas, pero son más confiables y están probadas.\nNightly: Versiones de desarrollo que tienen todas las últimas funciones y correcciones, pero pueden contener errores y son menos estables. - GUIgroupBox Reproducir Música del Título:\nSi un juego lo admite, habilita la reproducción de música especial al seleccionar el juego en la interfaz gráfica. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Ocultar Cursor:\nElija cuándo desaparecerá el cursor:\nNunca: Siempre verá el mouse.\nInactivo: Establezca un tiempo para que desaparezca después de estar inactivo.\nSiempre: nunca verá el mouse. - idleTimeoutGroupBox Establezca un tiempo para que el mouse desaparezca después de estar inactivo. - backButtonBehaviorGroupBox Comportamiento del Botón Atrás:\nEstablece el botón atrás del controlador para emular el toque en la posición especificada en el touchpad del PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Nunca - Idle Inactivo - Always Siempre - Touchpad Left Touchpad Izquierda - Touchpad Right Touchpad Derecha - Touchpad Center Centro del Touchpad - None Ninguno - graphicsAdapterGroupBox Dispositivo Gráfico:\nEn sistemas con múltiples GPU, selecciona la GPU que el emulador utilizará de la lista desplegable,\o selecciona "Auto Select" para determinarla automáticamente. - resolutionLayout Anchura/Altura:\nEstablece el tamaño de la ventana del emulador al iniciar, que se puede redimensionar durante el juego.\nEsto es diferente de la resolución en el juego. - heightDivider Divisor de Vblank:\nLa tasa de cuadros a la que se refresca el emulador se multiplica por este número. Cambiar esto puede tener efectos adversos, como aumentar la velocidad del juego, o romper la funcionalidad crítica del juego que no espera que esto cambie. - dumpShadersCheckBox Habilitar la Volcadura de Sombras:\nPor el bien de la depuración técnica, guarda las sombras del juego en una carpeta mientras se renderizan. - nullGpuCheckBox Habilitar GPU Nula:\nPor el bien de la depuración técnica, desactiva el renderizado del juego como si no hubiera tarjeta gráfica. - gameFoldersBox Carpetas de Juegos:\nLa lista de carpetas para verificar los juegos instalados. - addFolderButton Añadir:\nAgregar una carpeta a la lista. - removeFolderButton Eliminar:\nEliminar una carpeta de la lista. - debugDump Habilitar la Volcadura de Depuración:\nGuarda los símbolos de importación y exportación y la información del encabezado del archivo del programa de PS4 que se está ejecutando actualmente en un directorio. - vkValidationCheckBox Habilitar Capas de Validación de Vulkan:\nHabilita un sistema que valida el estado del renderizador de Vulkan y registra información sobre su estado interno. Esto reducirá el rendimiento y probablemente cambiará el comportamiento de la emulación. - vkSyncValidationCheckBox Habilitar Validación de Sincronización de Vulkan:\nHabilita un sistema que valida el tiempo de las tareas de renderizado de Vulkan. Esto reducirá el rendimiento y probablemente cambiará el comportamiento de la emulación. - rdocCheckBox Habilitar Depuración de RenderDoc:\nSi se habilita, el emulador proporcionará compatibilidad con Renderdoc para permitir la captura y análisis del fotograma actualmente renderizado. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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: + Número de 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 una vez descargados. + + + 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 + Parches + + + 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 el número de 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. Si el parche no aparece, puede ser que no exista para el número de serie y versión específicos del juego. + + + 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. + + + The game is in version: %1 + El juego está en la versión: %1 + + + The downloaded patch only works on version: %1 + El parche descargado solo funciona en la versión: %1 + + + You may need to update your game. + Puede que necesites actualizar tu juego. + + + Incompatibility Notice + Aviso de incompatibilidad + + + 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: + + + Can't apply cheats before the game is started + No se pueden aplicar trucos antes de que se inicie el juego. + + GameListFrame - Icon Icono - Name Nombre - Serial Numero de serie - Compatibility Compatibility - Region Región - Firmware Firmware - Size Tamaño - Version Versión - Path Ruta - Play Time Tiempo de Juego - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Actualizador Automático - Error Error - Network error: Error de red: - Failed to parse update information. Error al analizar la información de actualización. - No pre-releases found. No se encontraron prelanzamientos. - Invalid release data. Datos de versión no válidos. - No download URL found for the specified asset. No se encontró URL de descarga para el activo especificado. - Your version is already up to date! ¡Su versión ya está actualizada! - Update Available Actualización disponible - Update Channel Canal de Actualización - Current Version Versión actual - Latest Version Última versión - Do you want to update? ¿Quieres actualizar? - Show Changelog Mostrar registro de cambios - Check for Updates at Startup Buscar actualizaciones al iniciar - Update Actualizar - No No - Hide Changelog Ocultar registro de cambios - Changes Cambios - Network error occurred while trying to access the URL Se produjo un error de red al intentar acceder a la URL - Download Complete Descarga completa - The update has been downloaded, press OK to install. La actualización se ha descargado, presione Aceptar para instalar. - Failed to save the update file at No se pudo guardar el archivo de actualización en - Starting Update... Iniciando actualización... - Failed to create the update script file No se pudo crear el archivo del script de actualización + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts index 7b6583f45..52aa4b17c 100644 --- a/src/qt_gui/translations/fa_IR.ts +++ b/src/qt_gui/translations/fa_IR.ts @@ -6,22 +6,18 @@ 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. این برنامه نباید برای بازی هایی که شما به صورت غیرقانونی به دست آوردید استفاده شود. @@ -29,7 +25,6 @@ ElfViewer - Open Folder فولدر را بازکن @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 درحال بارگیری لیست بازی ها,لطفا کمی صبرکنید :3 - Cancel لغو - Loading... ...درحال بارگیری @@ -55,40 +47,33 @@ InstallDirSelect - shadPS4 - Choose directory ShadPS4 - انتخاب محل نصب بازی - Select which directory you want to install to. - Select which directory you want to install to. + محلی را که می‌خواهید در آن نصب شود، انتخاب کنید. GameInstallDialog - shadPS4 - Choose directory ShadPS4 - انتخاب محل نصب بازی - Directory to install games محل نصب بازی ها - Browse انتخاب دستی - Error ارور - The value for location to install games is not valid. .مکان داده شده برای نصب بازی درست نمی باشد @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut - ساخت شورتکات + ایجاد میانبر - Cheats / Patches چیت/پچ ها - SFO Viewer SFO مشاهده - Trophy Viewer - مشاهده تروفی ها + مشاهده جوایز - Open Folder... باز کردن پوشه... - Open Game Folder باز کردن پوشه بازی - Open Save Data Folder پوشه ذخیره داده را باز کنید - Open Log Folder باز کردن پوشه لاگ - Copy info... ...کپی کردن اطلاعات - Copy Name کپی کردن نام - Copy Serial کپی کردن سریال - Copy All کپی کردن تمامی مقادیر - Delete... - Delete... + حذف... - Delete Game - Delete Game + حذف بازی - Delete Update - Delete Update + حذف به‌روزرسانی - Delete DLC - Delete DLC + حذف محتوای اضافی (DLC) + + + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report - Shortcut creation - سازنده شورتکات + ایجاد میانبر - - Shortcut created successfully!\n %1 - شورتکات با موفقیت ساخته شد! \n %1 + Shortcut created successfully! + میانبر با موفقیت ساخته شد! - Error ارور - - Error creating shortcut!\n %1 - مشکلی در هنگام ساخت شورتکات بوجود آمد!\n %1 + Error creating shortcut! + مشکلی در هنگام ساخت میانبر بوجود آمد! - Install PKG نصب PKG - Game - Game + بازی - requiresEnableSeparateUpdateFolder_MSG - This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. + این قابلیت نیازمند فعال‌سازی گزینه تنظیمات «ایجاد پوشه جداگانه برای به‌روزرسانی» است. در صورت تمایل به استفاده از این قابلیت، لطفاً آن را فعال کنید. - This game has no update to delete! - This game has no update to delete! + این بازی به‌روزرسانی‌ای برای حذف ندارد! - - + Update - Update + به‌روزرسانی - This game has no DLC to delete! - This game has no DLC to delete! + این بازی محتوای اضافی (DLC) برای حذف ندارد! - DLC DLC - Delete %1 - Delete %1 + حذف %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder ELF بازکردن/ساختن پوشه - Install Packages (PKG) نصب بسته (PKG) - Boot Game اجرای بازی - Check for Updates به روز رسانی را بررسی کنید - 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 + مشاهده گر 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 تم ها - Help کمک - Dark تیره - Light روشن - Green سبز - Blue آبی - Violet بنفش - toolBar نوار ابزار + + Game List + لیست بازی + + + * 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 بازکردن پوشه @@ -450,1127 +502,839 @@ TrophyViewer - Trophy Viewer - تروفی ها + مشاهده جوایز SettingsDialog - Settings تنظیمات - General عمومی - System سیستم - Console Language زبان کنسول - Emulator Language زبان شبیه ساز - Emulator شبیه ساز - Enable Fullscreen تمام صفحه - Enable Separate Update Folder - Enable Separate Update Folder + فعال‌سازی پوشه جداگانه برای به‌روزرسانی - Show Splash Splash نمایش - Is PS4 Pro PS4 Pro حالت - Enable Discord Rich Presence Discord Rich Presence را فعال کنید - Username نام کاربری - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log نوع - Log Filter Log فیلتر - + Open Log Location + باز کردن مکان گزارش + + Input ورودی - Cursor نشانگر - Hide Cursor پنهان کردن نشانگر - Hide Cursor Idle Timeout مخفی کردن زمان توقف مکان نما - - Controller - کنترل کننده + s + s + + + Controller + دسته بازی - Back Button Behavior رفتار دکمه بازگشت - Graphics گرافیک - Graphics Device کارت گرافیک مورداستفاده - Width عرض - Height طول - Vblank Divider - Vblank Divider + تقسیم‌کننده Vblank - Advanced ...بیشتر - Enable Shaders Dumping - Shaders Dumping فعال کردن + فعال‌سازی ذخیره‌سازی شیدرها - Enable NULL GPU NULL GPU فعال کردن - Paths مسیرها - Game Folders پوشه های بازی - Add... افزودن... - Remove حذف - 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 - Update - بروزرسانی + به‌روزرسانی - Check for Updates at Startup - بررسی بروزرسانی هنگام شروع + بررسی به‌روزرسانی‌ها در زمان راه‌اندازی - Update Channel - کانال بروزرسانی + کانال به‌روزرسانی - Check for Updates - به روز رسانی را بررسی کنید + بررسی به‌روزرسانی‌ها - GUI Settings تنظیمات رابط کاربری - Disable Trophy Pop-ups - Disable Trophy Pop-ups + غیرفعال کردن نمایش جوایز - Play title music پخش موسیقی عنوان - Update Compatibility Database On Startup - Update Compatibility Database On Startup + به‌روزرسانی پایگاه داده سازگاری هنگام راه‌اندازی - Game Compatibility - Game Compatibility + سازگاری بازی با سیستم - Display Compatibility Data - Display Compatibility Data + نمایش داده‌های سازگاری - Update Compatibility Database - Update Compatibility Database + به‌روزرسانی پایگاه داده سازگاری - Volume - صدا - - - - MainWindow - - - Game List - لیست بازی + صدا - - * Unsupported Vulkan Version - شما پشتیبانی نمیشود Vulkan ورژن* + Audio Backend + Audio Backend - - 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 درست به نظر نمی آید - - - - CheatsPatches - - - Cheats / Patches for - Cheats / Patches for ا - - - - 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 - پچ ها با موفقیت بارگیری شدند! تمام وصله های موجود برای همه بازی ها دانلود شده اند، نیازی به دانلود جداگانه آنها برای هر بازی نیست، همانطور که در Cheats اتفاق می افتد. اگر پچ ظاهر نشد، ممکن است برای سریال و نسخه خاصی از بازی وجود نداشته باشد. - - - - Failed to parse JSON data from HTML. - HTML از JSON خطا در تجزیه اطلاعات. - - - - Failed to retrieve HTML page. - HTML خطا دربازیابی صفحه - - - - The game is in version: %1 - بازی در نسخه: %1 است - - - - The downloaded patch only works on version: %1 - وصله دانلود شده فقط در نسخه: %1 کار می کند - - - - You may need to update your game. - شاید لازم باشد بازی خود را به روز کنید. - - - - Incompatibility Notice - اطلاعیه عدم سازگاری - - - - 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: - نام: - - - - Can't apply cheats before the game is started - قبل از شروع بازی نمی توانید تقلب ها را اعمال کنید. - - - - SettingsDialog - - - Save - ذخیره - - - Apply اعمال - Restore Defaults بازیابی پیش فرض ها - Close بستن - Point your mouse at an option to display its description. ماوس خود را بر روی یک گزینه قرار دهید تا توضیحات آن نمایش داده شود. - consoleLanguageGroupBox Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. - emulatorLanguageGroupBox - Emulator Language:\nSets the language of the emulator's user interface. + زبان شبیه‌ساز:\nزبان رابط کاربری شبیه‌ساز را انتخاب می‌کند. - fullscreenCheckBox - Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. + فعال‌سازی تمام صفحه:\nپنجره بازی را به‌طور خودکار به حالت تمام صفحه در می‌آورد.\nبرای تغییر این حالت می‌توانید کلید F11 را فشار دهید. - separateUpdatesCheckBox - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + فعال‌سازی پوشه جداگانه برای به‌روزرسانی:\nامکان نصب به‌روزرسانی‌های بازی در یک پوشه جداگانه برای مدیریت راحت‌تر را فراهم می‌کند. - showSplashCheckBox - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. + نمایش صفحه شروع:\nصفحه شروع بازی (تصویری ویژه) را هنگام بارگذاری بازی نمایش می‌دهد. - ps4proCheckBox - Is PS4 Pro:\nMakes the emulator act as a PS4 PRO, which may enable special features in games that support it. + حالت PS4 Pro:\nشبیه‌ساز را به‌عنوان PS4 Pro شبیه‌سازی می‌کند که ممکن است ویژگی‌های ویژه‌ای را در بازی‌های پشتیبانی‌شده فعال کند. - discordRPCCheckbox فعال کردن Discord Rich Presence:\nآیکون شبیه ساز و اطلاعات مربوطه را در نمایه Discord شما نمایش می دهد. - userName - Username:\nSets the PS4's account username, which may be displayed by some games. + نام کاربری:\nنام کاربری حساب PS4 را تنظیم می‌کند که ممکن است توسط برخی بازی‌ها نمایش داده شود. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - logTypeGroupBox - Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. + نوع لاگ:\nتنظیم می‌کند که آیا خروجی پنجره لاگ برای بهبود عملکرد همگام‌سازی شود یا خیر. این ممکن است تأثیر منفی بر شبیه‌سازی داشته باشد. - logFilter Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Levels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. - updaterGroupBox - Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. + به‌روزرسانی:\nانتشار: نسخه‌های رسمی که هر ماه منتشر می‌شوند و ممکن است بسیار قدیمی باشند، اما پایدارتر و تست‌ شده‌تر هستند.\nشبانه: نسخه‌های توسعه‌ای که شامل جدیدترین ویژگی‌ها و اصلاحات هستند، اما ممکن است دارای اشکال باشند و کمتر پایدار باشند. - GUIgroupBox - Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. + پخش موسیقی عنوان:\nIدر صورتی که بازی از آن پشتیبانی کند، پخش موسیقی ویژه هنگام انتخاب بازی در رابط کاربری را فعال می‌کند. - disableTrophycheckBox - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + غیرفعال کردن نمایش جوایز:\nنمایش اعلان‌های جوایز درون بازی را غیرفعال می‌کند. پیشرفت جوایز همچنان از طریق نمایشگر جوایز (کلیک راست روی بازی در پنجره اصلی) قابل پیگیری است.. - hideCursorGroupBox پنهان کردن نشانگر:\nانتخاب کنید که نشانگر چه زمانی ناپدید شود:\nهرگز: شما همیشه ماوس را خواهید دید.\nغیرفعال: زمانی را برای ناپدید شدن بعد از غیرفعالی تعیین کنید.\nهمیشه: شما هرگز ماوس را نخواهید دید. - idleTimeoutGroupBox زمانی را برای ناپدید شدن ماوس بعد از غیرفعالی تعیین کنید. - backButtonBehaviorGroupBox رفتار دکمه برگشت:\nدکمه برگشت کنترلر را طوری تنظیم می کند که ضربه زدن روی موقعیت مشخص شده روی صفحه لمسی PS4 را شبیه سازی کند. - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + نمایش داده‌های سازگاری:\nاطلاعات سازگاری بازی را به صورت جدول نمایش می‌دهد. برای دریافت اطلاعات به‌روز، گزینه "به‌روزرسانی سازگاری هنگام راه‌اندازی" را فعال کنید. - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + به‌روزرسانی سازگاری هنگام راه‌اندازی:\nبه‌طور خودکار پایگاه داده سازگاری را هنگام راه‌اندازی ShadPS4 به‌روزرسانی می‌کند. - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. + به‌روزرسانی پایگاه داده سازگاری:\nپایگاه داده سازگاری را بلافاصله به‌روزرسانی می‌کند. - Never هرگز - Idle بیکار - Always همیشه - Touchpad Left - پد لمسی سمت چپ + صفحه لمسی سمت چپ - Touchpad Right صفحه لمسی سمت راست - Touchpad Center - مرکز تاچ پد + مرکز صفحه لمسی - None هیچ کدام - graphicsAdapterGroupBox - Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. + دستگاه گرافیکی:\nدر سیستم‌های با چندین پردازنده گرافیکی، از فهرست کشویی، پردازنده گرافیکی که شبیه‌ساز از آن استفاده می‌کند را انتخاب کنید، یا گزینه "انتخاب خودکار" را انتخاب کنید تا به طور خودکار تعیین شود. - resolutionLayout - Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. + عرض/ارتفاع:\nاندازه پنجره شبیه‌ساز را در هنگام راه‌اندازی تنظیم می‌کند، که در حین بازی قابل تغییر اندازه است.\nاین با وضوح داخل بازی متفاوت است. - heightDivider - Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! + تقسیم‌کننده Vblank:\nمیزان فریم ریت که شبیه‌ساز با آن به‌روزرسانی می‌شود، در این عدد ضرب می‌شود. تغییر این مقدار ممکن است تأثیرات منفی داشته باشد، مانند افزایش سرعت بازی یا خراب شدن عملکردهای حیاتی بازی که انتظار تغییر آن را ندارند! - dumpShadersCheckBox - Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. + فعال‌سازی ذخیره‌سازی شیدرها:\nبه‌منظور اشکال‌زدایی فنی، شیدرهای بازی را هنگام رندر شدن در یک پوشه ذخیره می‌کند. - nullGpuCheckBox Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - gameFoldersBox پوشه های بازی:\nلیست پوشه هایی که باید بازی های نصب شده را بررسی کنید. - addFolderButton اضافه کردن:\nیک پوشه به لیست اضافه کنید. - removeFolderButton حذف:\nیک پوشه را از لیست حذف کنید. - debugDump - Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. + فعال‌سازی ذخیره‌سازی دیباگ:\nنمادهای import و export و اطلاعات هدر فایل برنامه در حال اجرای PS4 را در یک پوشه ذخیره می‌کند. - vkValidationCheckBox Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state. This will reduce performance and likely change the behavior of emulation. - vkSyncValidationCheckBox Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks. This will reduce performance and likely change the behavior of emulation. - rdocCheckBox Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + + CheatsPatches + + Cheats / Patches for + چیت / پچ برای + + + 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 + پچ ها با موفقیت بارگیری شدند! تمام وصله های موجود برای همه بازی ها دانلود شده اند، نیازی به دانلود جداگانه آنها برای هر بازی نیست، همانطور که در Cheats اتفاق می افتد. اگر پچ ظاهر نشد، ممکن است برای سریال و نسخه خاصی از بازی وجود نداشته باشد. + + + Failed to parse JSON data from HTML. + HTML از JSON خطا در تجزیه اطلاعات. + + + Failed to retrieve HTML page. + HTML خطا دربازیابی صفحه + + + The game is in version: %1 + بازی در نسخه: %1 است + + + The downloaded patch only works on version: %1 + وصله دانلود شده فقط در نسخه: %1 کار می کند + + + You may need to update your game. + شاید لازم باشد بازی خود را به روز کنید. + + + Incompatibility Notice + اطلاعیه عدم سازگاری + + + 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: + نام: + + + Can't apply cheats before the game is started + قبل از شروع بازی نمی توانید تقلب ها را اعمال کنید. + + GameListFrame - Icon آیکون - Name نام - Serial سریال - Compatibility - Compatibility + سازگاری - Region منطقه - Firmware - فریمور + فریم‌ور - Size اندازه - Version نسخه - Path مسیر - Play Time زمان بازی - Never Played - Never Played + هرگز بازی نشده + + + h + h + + + m + m + + + s + s - Compatibility is untested - Compatibility is untested + سازگاری تست نشده است - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + بازی به درستی راه‌اندازی نمی‌شود / شبیه‌ساز کرش می‌کند - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + بازی اجرا می‌شود، اما فقط یک صفحه خالی نمایش داده می‌شود - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + بازی تصویری نمایش می‌دهد، اما از منو فراتر نمی‌رود - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + بازی دارای اشکالات بحرانی یا عملکرد غیرقابل بازی است - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + بازی با عملکرد قابل قبول و بدون اشکالات عمده قابل بازی است. CheckUpdate - Auto Updater - به روز رسانی خودکار + به‌روزرسانی خودکار - Error خطا - Network error: خطای شبکه: - Failed to parse update information. خطا در تجزیه اطلاعات بهروزرسانی. - No pre-releases found. هیچ پیش انتشاری یافت نشد. - Invalid release data. داده های نسخه نامعتبر است. - No download URL found for the specified asset. هیچ URL دانلودی برای دارایی مشخص شده پیدا نشد. - Your version is already up to date! نسخه شما اکنون به روز شده است! - Update Available به روز رسانی موجود است - Update Channel - کانال بروزرسانی + کانال به‌روزرسانی - Current Version نسخه فعلی - Latest Version جدیدترین نسخه - Do you want to update? آیا می خواهید به روز رسانی کنید؟ - Show Changelog نمایش تغییرات - Check for Updates at Startup - بررسی بروزرسانی هنگام شروع + بررسی به‌روزرسانی هنگام شروع - Update به روز رسانی - No خیر - Hide Changelog مخفی کردن تغییرات - Changes تغییرات - Network error occurred while trying to access the URL در حین تلاش برای دسترسی به URL خطای شبکه رخ داد - Download Complete دانلود کامل شد - The update has been downloaded, press OK to install. به روز رسانی دانلود شده است، برای نصب OK را فشار دهید. - Failed to save the update file at فایل به روز رسانی ذخیره نشد - Starting Update... شروع به روز رسانی... - Failed to create the update script file فایل اسکریپت به روز رسانی ایجاد نشد + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts index 7c933c5ec..97fee5dfa 100644 --- a/src/qt_gui/translations/fi.ts +++ b/src/qt_gui/translations/fi.ts @@ -6,1571 +6,1335 @@ AboutDialog - About shadPS4 - About shadPS4 + Tietoa shadPS4:sta - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 on kokeellinen avoimen lähdekoodin PlayStation 4 emulaattori. - 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. + Tätä ohjelmistoa ei saa käyttää pelien pelaamiseen, joita et ole hankkinut laillisesti. ElfViewer - Open Folder - Open Folder + Avaa Hakemisto GameInfoClass - Loading game list, please wait :3 - Loading game list, please wait :3 + Ole hyvä ja odota, ladataan pelilistaa :3 - Cancel - Cancel + Peruuta - Loading... - Loading... + Ladataan... InstallDirSelect - shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Valitse hakemisto - Select which directory you want to install to. - Select which directory you want to install to. + Valitse, mihin hakemistoon haluat asentaa. GameInstallDialog - shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Valitse hakemisto - Directory to install games - Directory to install games + Pelien asennushakemisto - Browse - Browse + Selaa - Error - Error + Virhe - The value for location to install games is not valid. - The value for location to install games is not valid. + Peliasennushakemiston sijainti on virheellinen. GuiContextMenus - Create Shortcut - Create Shortcut + Luo Pikakuvake - Cheats / Patches Huijaukset / Korjaukset - SFO Viewer - SFO Viewer + SFO Selain - Trophy Viewer - Trophy Viewer + Trophy Selain - Open Folder... - Avaa Kansio... + Avaa Hakemisto... - Open Game Folder - Avaa Pelikansio + Avaa Pelihakemisto - Open Save Data Folder - Avaa Tallennustiedostokansio + Avaa Tallennustiedostohakemisto - Open Log Folder - Avaa Lokikansio + Avaa Lokihakemisto - Copy info... - Copy info... + Kopioi tietoja... - Copy Name - Copy Name + Kopioi Nimi - Copy Serial - Copy Serial + Kopioi Sarjanumero - Copy All - Copy All + Kopioi kaikki - Delete... - Delete... + Poista... - Delete Game - Delete Game + Poista Peli - Delete Update - Delete Update + Poista Päivitys - Delete DLC - Delete DLC + Poista Lisäsisältö + + + Compatibility... + Yhteensopivuus... + + + Update database + Päivitä tietokanta + + + View report + Näytä raportti + + + Submit a report + Tee raportti - Shortcut creation - Shortcut creation + Pikakuvakkeen luonti - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Pikakuvake luotu onnistuneesti! - Error - Error + Virhe - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Virhe pikakuvakkeen luonnissa! - Install PKG - Install PKG + Asenna PKG - Game - Game + Peli - requiresEnableSeparateUpdateFolder_MSG - This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. + Tämä ominaisuus vaatii, että 'Ota käyttöön erillinen päivityshakemisto' -asetus on päällä. Jos haluat käyttää tätä ominaisuutta, laita se asetus päälle. - This game has no update to delete! - This game has no update to delete! + Tällä pelillä ei ole poistettavaa päivitystä! - - + Update - Update + Päivitä - This game has no DLC to delete! - This game has no DLC to delete! + Tällä pelillä ei ole poistettavaa lisäsisältöä! - DLC - DLC + Lisäsisältö - Delete %1 - Delete %1 + Poista %1 - Are you sure you want to delete %1's %2 directory? - Are you sure you want to delete %1's %2 directory? + Haluatko varmasti poistaa %1n %2hakemiston? MainWindow - Open/Add Elf Folder - Open/Add Elf Folder + Avaa/Lisää Elf Hakemisto - Install Packages (PKG) - Install Packages (PKG) + Asenna Paketteja (PKG) - Boot Game - Boot Game + Käynnistä Peli - Check for Updates - Tarkista päivitykset + Tarkista Päivitykset - About shadPS4 - About shadPS4 + Tietoa shadPS4:sta - Configure... - Configure... + Asetukset... - Install application from a .pkg file - Install application from a .pkg file + Asenna sovellus .pkg tiedostosta - Recent Games - Recent Games + Viimeisimmät Pelit - Exit - Exit + Sulje - Exit shadPS4 - Exit shadPS4 + Sulje shadPS4 - Exit the application. - Exit the application. + Sulje sovellus. - Show Game List - Show Game List + Avaa pelilista - Game List Refresh - Game List Refresh + Päivitä pelilista - Tiny - Tiny + Hyvin pieni - Small - Small + Pieni - Medium - Medium + Keskikokoinen - Large - Large + Suuri - List View - List View + Listanäkymä - Grid View - Grid View + Ruudukkonäkymä - Elf Viewer - Elf Viewer + Elf Selain - Game Install Directory - Game Install Directory + Peliasennushakemisto - Download Cheats/Patches Lataa Huijaukset / Korjaukset - Dump Game List - Dump Game List + Kirjoita Pelilista Tiedostoon - PKG Viewer - PKG Viewer + PKG Selain - Search... - Search... + Hae... - File - File + Tiedosto - View - View + Näkymä - Game List Icons - Game List Icons + Pelilistan Ikonit - Game List Mode - Game List Mode + Pelilistamuoto - Settings - Settings + Asetukset - Utils - Utils + Työkalut - Themes - Themes + Teemat - Help Apua - Dark - Dark + Tumma - Light - Light + Vaalea - Green - Green + Vihreä - Blue - Blue + Sininen - Violet - Violet + Violetti - toolBar - toolBar - - - - PKGViewer - - - Open Folder - Open Folder - - - - TrophyViewer - - - Trophy Viewer - Trophy Viewer - - - - SettingsDialog - - - Settings - Settings + Työkalupalkki - - General - General - - - - System - System - - - - Console Language - Console Language - - - - Emulator Language - Emulator Language - - - - Emulator - Emulator - - - - Enable Fullscreen - Enable Fullscreen - - - - Enable Separate Update Folder - Enable Separate Update Folder - - - - Show Splash - Show Splash - - - - Is PS4 Pro - Is PS4 Pro - - - - Enable Discord Rich Presence - Ota käyttöön Discord Rich Presence - - - - Username - Username - - - - Logger - Logger - - - - Log Type - Log Type - - - - Log Filter - Log Filter - - - - Input - Syöttö - - - - Cursor - Kursori - - - - Hide Cursor - Piilota kursor - - - - Hide Cursor Idle Timeout - Inaktiivisuuden aikaraja kursorin piilottamiselle - - - - Controller - Ohjain - - - - Back Button Behavior - Takaisin-painikkeen käyttäytyminen - - - - 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 - - - - Paths - Polut - - - - Game Folders - Pelihakemistot - - - - Add... - Lisää... - - - - Remove - Poista - - - - 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 - - - - Update - Päivitys - - - - Check for Updates at Startup - Tarkista päivitykset alussa - - - - Update Channel - Päivityskanava - - - - Check for Updates - Tarkista päivitykset - - - - GUI Settings - GUI-Asetukset - - - - Disable Trophy Pop-ups - Disable Trophy Pop-ups - - - - Play title music - Soita otsikkomusiikkia - - - - Update Compatibility Database On Startup - Update Compatibility Database On Startup - - - - Game Compatibility - Game Compatibility - - - - Display Compatibility Data - Display Compatibility Data - - - - Update Compatibility Database - Update Compatibility Database - - - - Volume - Äänenvoimakkuus - - - - MainWindow - - Game List Pelilista - * Unsupported Vulkan Version - * Tuettu Vulkan-versio + * Ei Tuettu Vulkan-versio - Download Cheats For All Installed Games - Lataa huijaukset kaikille asennetuille peleille + Lataa Huijaukset Kaikille Asennetuille Peleille - Download Patches For All Games - Lataa korjaukset kaikille peleille + Lataa Paikkaukset Kaikille Peleille - Download Complete - Lataus valmis + 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! + Paikkaukset Ladattu Onnistuneesti! - All Patches available for all games have been downloaded. - Kaikki saatavilla olevat korjaukset kaikille peleille on ladattu. + Kaikki saatavilla olevat Paikkaukset 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 + Pelin Käynnistys - Only one file can be selected! - Vain yksi tiedosto voidaan valita! + Vain yksi tiedosto voi olla valittuna! - PKG Extraction PKG:n purku - Patch detected! Päivitys havaittu! - PKG and Game versions match: PKG- ja peliversiot vastaavat: - Would you like to overwrite? Haluatko korvata? - PKG Version %1 is older than installed version: PKG-versio %1 on vanhempi kuin asennettu versio: - Game is installed: Peli on asennettu: - Would you like to install Patch: Haluatko asentaa päivityksen: - DLC Installation - DLC-asennus + Lisäsisällön asennus - Would you like to install DLC: %1? - Haluatko asentaa DLC:n: %1? + Haluatko asentaa lisäsisällön: %1? - DLC already installed: - DLC on jo asennettu: + Lisäsisältö on jo asennettu: - Game already installed Peli on jo asennettu - PKG is a patch, please install the game first! - PKG on korjaus, asenna peli ensin! + PKG on päivitys, 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 + PKGViewer - - Cheats / Patches for - Cheats / Patches for + Open Folder + Avaa Hakemisto + + + TrophyViewer - - 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. Jos päivitystä ei näy, se saattaa olla, että sitä ei ole saatavilla tietylle sarjanumerolle ja peliversiolle. - - - - 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. - - - - The game is in version: %1 - Peli on versiossa: %1 - - - - The downloaded patch only works on version: %1 - ladattu päivitys toimii vain versiossa: %1 - - - - You may need to update your game. - Sinun on ehkä päivitettävä peliäsi. - - - - Incompatibility Notice - Yhteensopivuusilmoitus - - - - 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: - - - - Can't apply cheats before the game is started - Ei voi käyttää huijauksia ennen kuin peli on aloitettu. + Trophy Viewer + Trophy Selain SettingsDialog - + Settings + Asetukset + + + General + Yleinen + + + System + Järjestelmä + + + Console Language + Konsolin Kieli + + + Emulator Language + Emulaattorin Kieli + + + Emulator + Emulaattori + + + Enable Fullscreen + Ota Käyttöön Koko Ruudun Tila + + + Enable Separate Update Folder + Ota Käyttöön Erillinen Päivityshakemisto + + + Show Splash + Näytä Aloitusnäyttö + + + Is PS4 Pro + On PS4 Pro + + + Enable Discord Rich Presence + Ota käyttöön Discord Rich Presence + + + Username + Käyttäjänimi + + + Trophy Key + Trophy Avain + + + Trophy + Trophy + + + Logger + Lokinkerääjä + + + Log Type + Lokin Tyyppi + + + Log Filter + Lokisuodatin + + + Open Log Location + Avaa lokin sijainti + + + Input + Syöttö + + + Cursor + Kursori + + + Hide Cursor + Piilota Kursori + + + Hide Cursor Idle Timeout + Inaktiivisuuden Aikaraja Kursorin Piilottamiseen + + + s + s + + + Controller + Ohjain + + + Back Button Behavior + Takaisin-painikkeen Käyttäytyminen + + + Graphics + Grafiikka + + + Graphics Device + Näytönohjain + + + Width + Leveys + + + Height + Korkeus + + + Vblank Divider + Vblank jakaja + + + Advanced + Lisäasetukset + + + Enable Shaders Dumping + Ota Käyttöön Varjostinvedokset + + + Enable NULL GPU + Ota Käyttöön NULL GPU + + + Paths + Polut + + + Game Folders + Pelihakemistot + + + Add... + Lisää... + + + Remove + Poista + + + Debug + Virheenkorjaus + + + Enable Debug Dumping + Ota Käyttöön Virheenkorjausvedokset + + + Enable Vulkan Validation Layers + Ota Käyttöön Vulkan-validointikerrokset + + + Enable Vulkan Synchronization Validation + Ota Käyttöön Vulkan-synkronointivalidointi + + + Enable RenderDoc Debugging + Ota Käyttöön RenderDoc Virheenkorjaus + + + Update + Päivitys + + + Check for Updates at Startup + Tarkista Päivitykset Käynnistäessä + + + Update Channel + Päivityskanava + + + Check for Updates + Tarkista Päivitykset + + + GUI Settings + GUI-asetukset + + + Disable Trophy Pop-ups + Poista Trophy Pop-upit Käytöstä + + + Play title music + Soita Otsikkomusiikkia + + + Update Compatibility Database On Startup + Päivitä Yhteensopivuustietokanta Käynnistäessä + + + Game Compatibility + Peliyhteensopivuus + + + Display Compatibility Data + Näytä Yhteensopivuustiedot + + + Update Compatibility Database + Päivitä Yhteensopivuustietokanta + + + Volume + Äänenvoimakkuus + + + Audio Backend + Äänijärjestelmä + + Save Tallenna - Apply Ota käyttöön - Restore Defaults - Palauta oletukset + Palauta Oletukset - Close Sulje - Point your mouse at an option to display its description. - Siirrä hiiri vaihtoehdon päälle näyttämään sen kuvaus. + Siirrä hiiri vaihtoehdon päälle näyttääksesi sen kuvauksen. - consoleLanguageGroupBox - Konsoli Kieli:\nAseta PS4 pelin käyttämä kieli.\nOn suositeltavaa asettaa tämä kieleksi, jota peli tukee, mikä vaihtelee alueittain. + Konsolin Kieli:\nAseta PS4-pelin käyttämä kieli.\nOn suositeltavaa asettaa tämä kieleksi, jota peli tukee, mikä vaihtelee alueittain. - emulatorLanguageGroupBox Emulaattorin Kieli:\nAsettaa emulaattorin käyttöliittymän kielen. - fullscreenCheckBox - Ota Täysikokoisuus käyttöön:\nSiirtää pelin ikkunan automaattisesti täysikokoiseen tilaan.\nTätä voidaan vaihtaa painamalla F11-näppäintä. + Ota Koko Näytön Tila Käyttöön:\nAvaa pelin ikkunan automaattisesti koko näytön tilassa.\nTilaa voi vaihtaa painamalla F11-näppäintä. - separateUpdatesCheckBox - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + Ota Käyttöön Erillinen Päivityskansio:\nOttaa käyttöön päivitysten asennuksen erilliseen kansioon helpottamaan niiden hallintaa.\nTämä on tehtävissä manuaalisesti lisäämällä puretun päivityksen pelikansioon "CUSA00000-UPDATE" nimellä, missä CUSA ID vastaa pelin ID:tä. - showSplashCheckBox - Näytä Alkunäyttö:\nNäyttää pelin alkunäytön (erityinen kuva) pelin käynnistyessä. + Näytä Aloitusnäyttö:\nNäyttää pelin aloitusnäytön (erityinen kuva) pelin käynnistyessä. - ps4proCheckBox - Onko PS4 Pro:\nAsettaa emulaattorin toimimaan PS4 PRO:na, mikä voi mahdollistaa erityisiä ominaisuuksia peleissä, jotka tukevat sitä. + On PS4 Pro:\nAsettaa emulaattorin toimimaan PS4 PRO:na, mikä voi mahdollistaa erityisiä ominaisuuksia peleissä, jotka tukevat sitä. - discordRPCCheckbox Ota käyttöön Discord Rich Presence:\nNäyttää emulaattorin kuvakkeen ja asiaankuuluvat tiedot Discord-profiilissasi. - userName - Käyttäjänimi:\nAsettaa PS4-tilin käyttäjänimen, joka voi näkyä joissakin peleissä. + Käyttäjänimi:\nAsettaa PS4-tilin käyttäjänimen, joka voi näkyä joissain peleissä. + + + TrophyKey + Trophy Avain:\nThrophyjen dekryptoinnissa käytetty avain. Pitää hankkia jailbreakatusta konsolista.\nSaa sisältää vain hex-merkkejä. - logTypeGroupBox Lokityyppi:\nAsettaa, synkronoidaanko loki-ikkunan ulostulo suorituskyvyn vuoksi. Tämä voi vaikuttaa haitallisesti emulointiin. - logFilter - Lokifiltteri:\nSuodattaa lokia tulostamaan vain erityistä tietoa.\nEsimerkkejä: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Tasot: Jälki, Virheenkorjaus, Tieto, Varoitus, Virhe, Kriittinen - tällä järjestyksellä, tietty taso vaientaa kaikki edeltävät tasot luettelossa ja kirjaa kaikki tasot sen jälkeen. + Lokisuodatin:\nSuodattaa lokia tulostamaan vain määrättyä tietoa.\nEsimerkkejä: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nTasot: Trace, Debug, Info, Warning, Error, Critical - tässä järjestyksessä. Valittu taso vaientaa kaikki edeltävät tasot luettelossa ja kirjaa kaikki tasot sen jälkeen. - updaterGroupBox - Päivitys:\nRelease: Viralliset versiot, jotka julkaistaan joka kuukausi ja voivat olla hyvin vanhoja, mutta ovat luotettavampia ja testatumpia.\nNightly: Kehitysversiot, joissa on kaikki uusimmat ominaisuudet ja korjaukset, mutta ne voivat sisältää bugeja ja ovat vähemmän vakaita. + Päivitys:\nRelease: Viralliset versiot, jotka julkaistaan kuukausittain ja saattavat olla hyvin vanhoja, mutta ovat luotettavampia ja testatumpia.\nNightly: Kehitysversiot, joissa on kaikki uusimmat ominaisuudet ja korjaukset, mutta ne saattavat sisältää virheitä ja ovat vähemmän vakaita. - GUIgroupBox Soita Otsikkomusiikkia:\nJos peli tukee sitä, ota käyttöön erityisen musiikin soittaminen pelin valinnan yhteydessä käyttöliittymässä. - disableTrophycheckBox - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Poista Trophy Pop-upit Käytöstä:\nPoista trophy ilmoitukset pelin aikana. Trophyjen edistystä voi silti seurata Trophy Selainta käyttämällä (klikkaa peliä hiiren oikealla emulaattorin pääikkunassa). - hideCursorGroupBox - Piilota kursori:\nValitse, milloin kursori häviää:\nEi koskaan: Näet hiiren aina.\nAktiivinen: Aseta aika, jolloin se häviää oltuaan aktiivinen.\nAina: et koskaan näe hiirtä. + Piilota kursori:\nValitse, milloin kursori häviää:\nEi koskaan: Näet hiiren aina.\nInaktiivinen: Aseta aika, jolloin se häviää oltuaan aktiivinen.\nAina: et koskaan näe hiirtä. - idleTimeoutGroupBox - Aseta aika, jolloin hiiri häviää oltuaan aktiivinen. + Aseta aika, milloin hiiri häviää oltuaan aktiivinen. - backButtonBehaviorGroupBox Takaisin-napin käyttäytyminen:\nAsettaa ohjaimen takaisin-napin jäljittelemään kosketusta PS4:n kosketuslevyn määritettyyn kohtaan. - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Näytä Yhteensopivuustiedot:\nNäyttää pelien yhteensopivuustiedot listanäkymässä. Ota käyttöön "Päivitä Yhteensopivuustietokanta Käynnistäessä" saadaksesi ajantasaista tietoa. - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Päivitä Yhteensopivuustiedot Käynnistäessä:\nPäivitä yhteensopivuustiedot automaattisesti shadPS4:n käynnistyessä. - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. + Päivitä Yhteensopivuustietokanta:\nPäivitää yhteensopivuustietokannan heti. - Never Ei koskaan - Idle - Odotustila + Inaktiivinen - Always - aina + Aina - Touchpad Left - Kosketuslevy Vasemmalla + Kosketuslevyn Vasen Puoli - Touchpad Right - Kosketuslevy Oikealla + Kosketuslevyn Oikea Puoli - Touchpad Center - Kosketuslevy Keskellä + Kosketuslevyn Keskikohta - None Ei mitään - graphicsAdapterGroupBox - Kuvakortti:\nValitse GPU, jota emulaattori käyttää monigpu-järjestelmissä pudotusvalikosta,\n tai valitse "Auto Select" automaattiseen määrittämiseen. + Näytönohjain:\nUseamman näytönohjaimen järjestelmissä, valitse pudotusvalikosta, mitä näytönohjainta emulaattori käyttää,\n tai valitse "Auto Select" automaattiseen määritykseen. - resolutionLayout - Leveys/Korkeus:\nAsettaa emulaattorin ikkunan koon käynnistyksen aikana, jota voidaan muuttaa pelin aikana.\nTämä on eri kuin pelin sisäinen resoluutio. + Leveys/Korkeus:\nAsettaa käynnistetyn emulaattori-ikkunan koon, jota voidaan muuttaa pelin aikana.\nTämä on eri, kuin pelin sisäinen resoluutio. - heightDivider - Vblank Jakaja:\nEmulaattorin virkistystaajuus kerrotaan tällä numerolla. Tämän muuttaminen voi vaikuttaa haitallisesti, kuten pelin nopeuden lisääminen tai kriittisten pelitoimintojen rikkoutuminen, jotka eivät odota tämän muuttuvan! + Vblank Jakaja:\nEmulaattorin virkistystaajuus kerrotaan tällä numerolla. Tämän muuttaminen voi vaikuttaa haitallisesti, kuten lisätä pelin nopeutta tai rikkoa kriittisiä pelitoimintoja, jotka eivät odota tämän muuttuvan! - dumpShadersCheckBox - Ota Shadersin dumpaus käyttöön:\nTeknistä vianetsintää varten pelin shadereita tallennetaan kansioon niiden renderöinnin aikana. + Ota Käyttöön Varjostinvedokset:\nTeknistä vianetsintää varten. Pelin varjostimia tallennetaan hakemistoon niiden renderöityessä. - nullGpuCheckBox - Ota Null GPU käyttöön:\nTeknistä vianetsintää varten pelin renderöinti estetään niin, että ikään kuin grafiikkakorttia ei olisi. + Ota Null GPU käyttöön:\nTeknistä vianetsintää varten. Pelin renderöinti estetään, ikään kuin näytönohjainta ei olisi. - gameFoldersBox - Pelihakemistot:\nLuettelo hakemistoista asennettujen pelien tarkistamiseksi. + Pelihakemistot:\nLista hakemistoista, joista pelejä haetaan. - addFolderButton - Lisää:\nLisää hakemisto luetteloon. + Lisää:\nLisää hakemisto listalle. - removeFolderButton - Poista:\nPoista hakemisto luettelosta. + Poista:\nPoista hakemisto listalta. - debugDump - Ota Debug Dumpaus käyttöön:\nTallentaa käynnissä olevan PS4-ohjelman tuonti- ja vientisymbolit ja tiedosto-otsikkotiedot hakemistoon. + Ota Käyttöön Virheenkorjausvedokset:\nTallentaa käynnissä olevan PS4-ohjelman tuonti- ja vientisymbolit ja tiedosto-otsikkotiedot hakemistoon. - vkValidationCheckBox - Ota Vulkanin Validointikerrokset käyttöön:\nAktivoi järjestelmä, joka validoi Vulkan-renderöijän tilan ja kirjaa tietoa sen sisäisestä tilasta. Tämä heikentää suorituskykyä ja todennäköisesti muuttaa emulaation käyttäytymistä. + Ota Käyttöön Vulkan-validointikerrokset:\nAktivoi järjestelmä, joka validoi Vulkan-renderöijän tilan ja kirjaa tietoa sen sisäisestä tilasta. Tämä heikentää suorituskykyä ja todennäköisesti muuttaa emulaation käyttäytymistä. - vkSyncValidationCheckBox - Ota Vulkanin Synkronointivalaistus käyttöön:\nAktivoi järjestelmä, joka validoi Vulkan-renderöinnin tehtävien aikataulutuksen. Tämä heikentää suorituskykyä ja todennäköisesti muuttaa emulaation käyttäytymistä. + Ota Käyttöön Vulkan-synkronointivalidointi:\nAktivoi järjestelmä, joka validoi Vulkan-renderöinnin tehtävien aikataulutuksen. Tämä heikentää suorituskykyä ja todennäköisesti muuttaa emulaation käyttäytymistä. - rdocCheckBox - Ota RenderDoc Debugging käyttöön:\nJos se on käytössä, emulaattori tarjoaa yhteensopivuuden Renderdocin kanssa, mikä mahdollistaa nykyisen renderöidyn kehyksen tallennuksen ja analysoinnin. + Ota Käyttöön RenderDoc Virheenkorjaus:\nJos käytössä, emulaattori tarjoaa Renderdoc-yhteensopivuuden, mikä mahdollistaa renderöidyn kehyksen tallennuksen ja analysoinnin. + + + + CheatsPatches + + Cheats / Patches for + Huijaukset / Paikkaukset pelille + + + defaultTextEdit_MSG + Huijaukset/Paikkaukset ovat kokeellisia.\nKäytä varoen.\n\nLataa huijaukset yksitellen valitsemalla repositorion ja napsauttamalla latauspainiketta.\nPaikkaukset-välilehdessä voit ladata kaikki paikkaukset kerralla, valita, mitä haluat käyttää ja tallentaa valinnan.\n\nKoska me emme kehitä Huijauksia/Paikkauksia,\nole hyvä ja ilmoita ongelmista huijauksen tekijälle.\n\nLoitko uuden huijauksen? 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: + Repositorio: + + + Download Cheats + Lataa Huijaukset + + + Delete File + Poista Tiedosto + + + No files selected. + Tiedostoja ei ole valittuna. + + + 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 Paikkaustiedosto: + + + Download Patches + Lataa Paikkaukset + + + Save + Tallenna + + + Cheats + Huijaukset + + + Patches + Paikkaukset + + + Error + Virhe + + + No patch selected. + Paikkausta ei ole valittuna. + + + 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 paikkaustiedostoa. + + + 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 + Onnistuminen + + + Options saved successfully. + Vaihtoehdot tallennettu onnistuneesti. + + + Invalid Source + Virheellinen Lähde + + + The selected source is invalid. + Valittu lähde on virheellinen. + + + File Exists + Olemassaoleva Tiedosto + + + 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 pelin versiolle valitusta repositoriosta. Kokeile toista repositoriota tai eri versiota pelistä. + + + 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 listasta. + + + Failed to save: + Tallentaminen epäonnistui: + + + Failed to download: + Lataus epäonnistui: + + + Download Complete + Lataus valmis + + + DownloadComplete_MSG + Paikkaukset ladattu onnistuneesti! Kaikki saatavilla olevat paikkaukset kaikille peleille on ladattu, eikä niitä tarvitse ladata yksittäin jokaiselle pelille, kuten huijausten kohdalla. Jos paikkausta ei näy, saattaa olla, että sitä ei ole saatavilla kyseiselle sarjanumerolle ja peliversiolle. + + + 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. + + + The game is in version: %1 + Peli on versiossa: %1 + + + The downloaded patch only works on version: %1 + Ladattu paikkaus toimii vain versiossa: %1 + + + You may need to update your game. + Sinun on ehkä päivitettävä pelisi. + + + Incompatibility Notice + Yhteensopivuusilmoitus + + + 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: + Hakemistoa ei ole olemassa: + + + Failed to open files.json for reading. + Tiedostoa files.json ei voitu avata lukemista varten. + + + Name: + Nimi: + + + Can't apply cheats before the game is started + Huijauksia ei voi käyttää ennen kuin peli on käynnissä. GameListFrame - Icon Ikoni - Name Nimi - Serial Sarjanumero - Compatibility Compatibility - Region Alue - Firmware Ohjelmisto - Size Koko - Version Versio - Path Polku - Play Time Peliaika - Never Played - Never Played + Pelaamaton + + + h + h + + + m + m + + + s + s - Compatibility is untested - Compatibility is untested + Yhteensopivuutta ei ole testattu - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + Peli ei alustaudu kunnolla / kaataa emulaattorin - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + Peli käynnistyy, mutta näyttää vain tyhjän ruudun - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + Peli näyttää kuvan mutta ei mene valikosta eteenpäin - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + Pelissä on pelikokemusta rikkovia häiriöitä tai kelvoton suorituskyky - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + Pelillä on hyväksyttävä suorituskyky, eikä mitään suuria häiriöitä CheckUpdate - Auto Updater - Automaattinen päivitys + Automaattinen Päivitys - Error Virhe - Network error: Verkkovirhe: - Failed to parse update information. - Päivitysinformaation jäsentäminen epäonnistui. + Päivitystietojen jäsentäminen epäonnistui. - No pre-releases found. Ennakkojulkaisuja ei löytynyt. - Invalid release data. Virheelliset julkaisutiedot. - No download URL found for the specified asset. - Ei lataus-URL:ia löytynyt määritetylle omaisuudelle. + Lataus-URL:ia ei löytynyt määritetylle omaisuudelle. - Your version is already up to date! Versiosi on jo ajan tasalla! - Update Available - Päivitys saatavilla + Päivitys Saatavilla - Update Channel Päivityskanava - Current Version - Nykyinen versio + Nykyinen Versio - Latest Version - Uusin versio + Uusin Versio - Do you want to update? Haluatko päivittää? - Show Changelog - Näytä muutospäiväkirja + Näytä Muutoshistoria - Check for Updates at Startup - Tarkista päivitykset alussa + Tarkista Päivitykset Käynnistettäessä - Update Päivitä - No Ei - Hide Changelog - Piilota muutospäiväkirja + Piilota Muutoshistoria - Changes - Muutos + Muutokset - Network error occurred while trying to access the URL - Verkkovirhe tapahtui yrittäessäsi päästä URL-osoitteeseen + URL-osoitteeseen yhdistettäessä tapahtui verkkovirhe - Download Complete - Download valmis + Lataus Valmis - The update has been downloaded, press OK to install. Päivitys on ladattu, paina OK asentaaksesi. - Failed to save the update file at - Päivitystiedoston tallentaminen epäonnistui osoitteeseen + Päivitystiedoston tallentaminen epäonnistui sijaintiin - Starting Update... - Aloitetaan päivitys... + Aloitetaan päivitystä... - Failed to create the update script file Päivitysskripttitiedoston luominen epäonnistui + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 7a61dc292..d25ad30f4 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 À propos de shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 est un émulateur open-source expérimental de la PlayStation 4. - 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 +25,6 @@ ElfViewer - Open Folder Ouvrir un dossier @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Chargement de la liste de jeu, veuillez patienter... - Cancel Annuler - Loading... Chargement... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choisir un répertoire - Select which directory you want to install to. Sélectionnez le répertoire où vous souhaitez effectuer l'installation. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Choisir un répertoire - Directory to install games Répertoire d'installation des jeux - Browse Parcourir - Error Erreur - The value for location to install games is not valid. Le répertoire d'installation des jeux n'est pas valide. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Créer un raccourci - Cheats / Patches Cheats/Patchs - SFO Viewer Visionneuse SFO - Trophy Viewer Visionneuse de trophées - Open Folder... Ouvrir le Dossier... - Open Game Folder Ouvrir le Dossier du Jeu - Open Save Data Folder Ouvrir le Dossier des Données de Sauvegarde - Open Log Folder Ouvrir le Dossier des Logs - Copy info... Copier infos... - Copy Name Copier le nom - Copy Serial Copier le N° de série - Copy All Copier tout - Delete... Supprimer... - Delete Game Supprimer jeu - Delete Update Supprimer MÀJ - Delete DLC Supprimer DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Création du raccourci - - Shortcut created successfully!\n %1 - Raccourci créé avec succès !\n %1 + Shortcut created successfully! + Raccourci créé avec succès ! - Error Erreur - - Error creating shortcut!\n %1 - Erreur lors de la création du raccourci !\n %1 + Error creating shortcut! + Erreur lors de la création du raccourci ! - Install PKG Installer un PKG - Game Jeu - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! Ce jeu n'a pas de mise à jour à supprimer! - - + Update Mise à jour - This game has no DLC to delete! Ce jeu n'a pas de DLC à supprimer! - DLC DLC - Delete %1 Supprime %1 - Are you sure you want to delete %1's %2 directory? Êtes vous sûr de vouloir supprimer le répertoire %1 %2 ? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Ouvrir/Ajouter un dossier ELF - Install Packages (PKG) Installer des packages (PKG) - Boot Game Démarrer un jeu - Check for Updates Vérifier les mises à jour - About shadPS4 À propos de shadPS4 - Configure... Configurer... - Install application from a .pkg file Installer une application depuis un fichier .pkg - Recent Games Jeux récents - Exit Fermer - Exit shadPS4 Fermer shadPS4 - Exit the application. Fermer l'application. - Show Game List Afficher la liste de jeux - Game List Refresh Rafraîchir la liste de jeux - Tiny Très Petit - Small Petit - Medium Moyen - Large Grand - List View Mode liste - Grid View Mode grille - Elf Viewer Visionneuse ELF - Game Install Directory Répertoire des jeux - Download Cheats/Patches Télécharger Cheats/Patchs - Dump Game List Dumper la liste des jeux - PKG Viewer Visionneuse PKG - Search... Chercher... - File Fichier - View Affichage - Game List Icons Icônes des jeux - Game List Mode Mode d'affichage - Settings Paramètres - Utils Utilitaires - Themes Thèmes - Help Aide - Dark Sombre - Light Clair - Green Vert - Blue Bleu - Violet Violet - toolBar Bare d'outils + + Game List + Liste de jeux + + + * Unsupported Vulkan Version + * Version de 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 patchs 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 installés. + + + Patches Downloaded Successfully! + Patchs téléchargés avec succès ! + + + All Patches available for all games have been downloaded. + Tous les patchs disponibles ont été téléchargés. + + + Games: + Jeux: + + + PKG File (*.PKG) + Fichiers PKG (*.PKG) + + + ELF files (*.bin *.elf *.oelf) + Fichiers ELF (*.bin *.elf *.oelf) + + + Game Boot + Démarrer un jeu + + + Only one file can be selected! + Un seul fichier peut être sélectionné ! + + + PKG Extraction + Extraction du PKG + + + Patch detected! + Patch détecté ! + + + PKG and Game versions match: + Les versions PKG et jeu correspondent: + + + Would you like to overwrite? + Souhaitez-vous remplacer ? + + + PKG Version %1 is older than installed version: + La version PKG %1 est plus ancienne que la version installée: + + + Game is installed: + Jeu installé: + + + Would you like to install Patch: + Souhaitez-vous installer le patch: + + + DLC Installation + Installation du DLC + + + 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é + + + PKG is a patch, please install the game first! + Le 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 PKG valide + PKGViewer - Open Folder Ouvrir un dossier @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Visionneuse de trophées @@ -458,989 +509,704 @@ SettingsDialog - Settings Paramètres - General Général - System Système - Console Language Langage de la console - Emulator Language Langage de l'émulateur - Emulator Émulateur - Enable Fullscreen Plein écran - Enable Separate Update Folder Dossier séparé pour les mises à jours - Show Splash Afficher l'image du jeu - Is PS4 Pro Mode PS4 Pro - Enable Discord Rich Presence Activer la présence Discord - Username Nom d'utilisateur - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Journalisation - Log Type Type - Log Filter Filtre - + Open Log Location + Ouvrir l'emplacement du journal + + Input Entrée - Cursor Curseur - Hide Cursor Masquer le curseur - Hide Cursor Idle Timeout Délai d'inactivité pour masquer le curseur - + s + s + + Controller Manette - Back Button Behavior Comportement du bouton retour - Graphics Graphismes - Graphics Device Carte graphique - Width Largeur - Height Hauteur - Vblank Divider Vblank - Advanced Avancé - Enable Shaders Dumping Dumper les shaders - Enable NULL GPU NULL GPU - Paths Chemins - Game Folders Dossiers de jeu - Add... Ajouter... - Remove Supprimer - Debug Débogage - Enable Debug Dumping Activer le débogage - Enable Vulkan Validation Layers Activer la couche de validation Vulkan - Enable Vulkan Synchronization Validation Activer la synchronisation de la validation Vulkan - Enable RenderDoc Debugging Activer le débogage RenderDoc - Update Mise à jour - Check for Updates at Startup Vérif. maj au démarrage - Update Channel Canal de Mise à Jour - Check for Updates Vérifier les mises à jour - GUI Settings Paramètres de l'interface - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Lire la musique du titre - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Volume - - - MainWindow - - Game List - Liste de jeux + Audio Backend + Audio Backend - - * Unsupported Vulkan Version - * Version de 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 patchs 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 installés. - - - - Patches Downloaded Successfully! - Patchs téléchargés avec succès ! - - - - All Patches available for all games have been downloaded. - Tous les patchs disponibles ont été téléchargés. - - - - Games: - Jeux: - - - - PKG File (*.PKG) - Fichiers PKG (*.PKG) - - - - ELF files (*.bin *.elf *.oelf) - Fichiers ELF (*.bin *.elf *.oelf) - - - - Game Boot - Démarrer un jeu - - - - Only one file can be selected! - Un seul fichier peut être sélectionné ! - - - - PKG Extraction - Extraction du PKG - - - - Patch detected! - Patch détecté ! - - - - PKG and Game versions match: - Les versions PKG et jeu correspondent: - - - - Would you like to overwrite? - Souhaitez-vous remplacer ? - - - - PKG Version %1 is older than installed version: - La version PKG %1 est plus ancienne que la version installée: - - - - Game is installed: - Jeu installé: - - - - Would you like to install Patch: - Souhaitez-vous installer le patch: - - - - DLC Installation - Installation du DLC - - - - 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é - - - - PKG is a patch, please install the game first! - Le 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 PKG valide - - - - CheatsPatches - - - Cheats / Patches for - Cheats/Patchs pour - - - - defaultTextEdit_MSG - 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 - - - - 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 patchs - - - 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. Si le correctif n'apparaît pas, il se peut qu'il n'existe pas pour le numéro de série et la version spécifiques du jeu. - - - - 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. - - - - The game is in version: %1 - Le jeu est en version: %1 - - - - The downloaded patch only works on version: %1 - Le patch téléchargé ne fonctionne que sur la version: %1 - - - - You may need to update your game. - Vous devrez peut-être mettre à jour votre jeu. - - - - Incompatibility Notice - Avis d'incompatibilité - - - - 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: - - - - Can't apply cheats before the game is started - Impossible d'appliquer les Cheats avant que le jeu ne commence. - - - - SettingsDialog - - - Save - Enregistrer - - - Apply Appliquer - Restore Defaults Restaurer les paramètres par défaut - Close Fermer - Point your mouse at an option to display its description. Pointez votre souris sur une option pour afficher sa description. - consoleLanguageGroupBox Langue de la console:\nDéfinit la langue utilisée par le jeu PS4.\nIl est recommandé de le définir sur une langue que le jeu prend en charge, ce qui variera selon la région. - emulatorLanguageGroupBox Langue de l'émulateur:\nDéfinit la langue de l'interface utilisateur de l'émulateur. - fullscreenCheckBox Activer le mode plein écran:\nMet automatiquement la fenêtre du jeu en mode plein écran.\nCela peut être activé en appuyant sur la touche F11. - separateUpdatesCheckBox Dossier séparé pour les mises à jours:\nInstalle les mises à jours des jeux dans un dossier séparé pour une gestion plus facile. - showSplashCheckBox Afficher l'écran de démarrage:\nAffiche l'écran de démarrage du jeu (une image spéciale) lors du démarrage du jeu. - ps4proCheckBox Mode PS4 Pro:\nFait en sorte que l'émulateur se comporte comme un PS4 PRO, ce qui peut activer des fonctionnalités spéciales dans les jeux qui le prennent en charge. - discordRPCCheckbox Activer Discord Rich Presence:\nAffiche l'icône de l'émulateur et les informations pertinentes sur votre profil Discord. - userName Nom d'utilisateur:\nDéfinit le nom d'utilisateur du compte PS4, qui peut être affiché par certains jeux. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Type de journal:\nDétermine si la sortie de la fenêtre de journalisation est synchronisée pour des raisons de performance. Cela peut avoir un impact négatif sur l'émulation. - logFilter Filtre de journal:\n n'imprime que des informations spécifiques.\nExemples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Niveaux: Trace, Debug, Info, Avertissement, Erreur, Critique - dans cet ordre, un niveau particulier désactive tous les niveaux précédents de la liste et enregistre tous les niveaux suivants. - updaterGroupBox Mise à jour:\nRelease: versions officielles publiées chaque mois qui peuvent être très anciennes, mais plus fiables et testées.\nNightly: versions de développement avec toutes les dernières fonctionnalités et correctifs, mais pouvant avoir des bogues et être moins stables. - GUIgroupBox Jouer de la musique de titre:\nSi le jeu le prend en charge, cela active la musique spéciale lorsque vous sélectionnez le jeu dans l'interface utilisateur. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Masquer le curseur:\nChoisissez quand le curseur disparaîtra:\nJamais: Vous verrez toujours la souris.\nInactif: Définissez un temps pour qu'il disparaisse après inactivité.\nToujours: vous ne verrez jamais la souris. - idleTimeoutGroupBox Définissez un temps pour que la souris disparaisse après être inactif. - backButtonBehaviorGroupBox Comportement du bouton retour:\nDéfinit le bouton de retour de la manette pour imiter le toucher de la position spécifiée sur le pavé tactile PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Jamais - Idle Inactif - Always Toujours - Touchpad Left Pavé Tactile Gauche - Touchpad Right Pavé Tactile Droit - Touchpad Center Centre du Pavé Tactile - None Aucun - graphicsAdapterGroupBox Adaptateur graphique:\nSélectionnez le GPU que l'émulateur utilisera dans les systèmes multi-GPU à partir de la liste déroulante,\nou choisissez "Auto Select" pour le déterminer automatiquement. - resolutionLayout Largeur/Hauteur:\nDéfinit la taille de la fenêtre de l'émulateur au démarrage, qui peut être redimensionnée pendant le jeu.\nCela diffère de la résolution interne du jeu. - heightDivider Diviseur Vblank:\nLe taux de rafraîchissement de l'émulateur est multiplié par ce nombre. Changer cela peut avoir des effets négatifs, tels qu'une augmentation de la vitesse du jeu ou la rupture de fonctionnalités critiques du jeu qui ne s'attendent pas à ce changement ! - dumpShadersCheckBox Activer l'exportation de shaders:\nPour le débogage technique, les shaders du jeu sont enregistrés dans un dossier lors du rendu. - nullGpuCheckBox Activer le GPU nul:\nPour le débogage technique, désactive le rendu du jeu comme s'il n'y avait pas de carte graphique. - gameFoldersBox Dossiers de jeux:\nLa liste des dossiers à vérifier pour les jeux installés. - addFolderButton Ajouter:\nAjouter un dossier à la liste. - removeFolderButton Supprimer:\nSupprimer un dossier de la liste. - debugDump Activer l'exportation de débogage:\nEnregistre les symboles d'importation et d'exportation et les informations d'en-tête du fichier du programme PS4 actuel dans un répertoire. - vkValidationCheckBox Activer les couches de validation Vulkan:\nActive un système qui valide l'état du rendu Vulkan et enregistre des informations sur son état interne. Cela réduit les performances et peut changer le comportement de l'émulation. - vkSyncValidationCheckBox Activer la validation de synchronisation Vulkan:\nActive un système qui valide la planification des tâches de rendu Vulkan. Cela réduit les performances et peut changer le comportement de l'émulation. - rdocCheckBox Activer le débogage RenderDoc:\nS'il est activé, l'émulateur fournit une compatibilité avec Renderdoc, permettant d'enregistrer et d'analyser la trame rendue actuelle. + + CheatsPatches + + Cheats / Patches for + Cheats/Patchs pour + + + defaultTextEdit_MSG + 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 + + + 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 patchs + + + 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. Si le correctif n'apparaît pas, il se peut qu'il n'existe pas pour le numéro de série et la version spécifiques du jeu. + + + 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. + + + The game is in version: %1 + Le jeu est en version: %1 + + + The downloaded patch only works on version: %1 + Le patch téléchargé ne fonctionne que sur la version: %1 + + + You may need to update your game. + Vous devrez peut-être mettre à jour votre jeu. + + + Incompatibility Notice + Avis d'incompatibilité + + + 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: + + + Can't apply cheats before the game is started + Impossible d'appliquer les Cheats avant que le jeu ne commence. + + GameListFrame - Icon Icône - Name Nom - Serial Série - Compatibility Compatibility - Region Région - Firmware Firmware - Size Taille - Version Version - Path Répertoire - Play Time Temps de jeu - Never Played Jamais joué - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Mise à jour automatique - Error Erreur - Network error: Erreur réseau: - Failed to parse update information. Échec de l'analyse des informations de mise à jour. - No pre-releases found. Aucune pré-version trouvée. - Invalid release data. Données de version invalides. - No download URL found for the specified asset. Aucune URL de téléchargement trouvée pour l'élément spécifié. - Your version is already up to date! Votre version est déjà à jour ! - Update Available Mise à jour disponible - Update Channel Canal de Mise à Jour - Current Version Version actuelle - Latest Version Dernière version - Do you want to update? Voulez-vous mettre à jour ? - Show Changelog Afficher le journal des modifications - Check for Updates at Startup Vérif. maj au démarrage - Update Mettre à jour - No Non - Hide Changelog Cacher le journal des modifications - Changes Modifications - Network error occurred while trying to access the URL Une erreur réseau s'est produite en essayant d'accéder à l'URL - Download Complete Téléchargement terminé - The update has been downloaded, press OK to install. La mise à jour a été téléchargée, appuyez sur OK pour l'installer. - Failed to save the update file at Échec de la sauvegarde du fichier de mise à jour à - Starting Update... Démarrage de la mise à jour... - Failed to create the update script file Échec de la création du fichier de script de mise à jour + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 bf0b26988..6ecc3fc90 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 A shadPS4-ről - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. A shadPS4 egy kezdetleges, open-source PlayStation 4 emulátor. - 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 +25,6 @@ ElfViewer - Open Folder Mappa megnyitása @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Játék könyvtár betöltése, kérjük várjon :3 - Cancel Megszakítás - Loading... Betöltés.. @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Mappa kiválasztása - Select which directory you want to install to. Válassza ki a mappát a játékok telepítésére. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Mappa kiválasztása - Directory to install games Mappa a játékok telepítésére - Browse Böngészés - Error Hiba - The value for location to install games is not valid. A játékok telepítéséhez megadott útvonal nem érvényes. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Parancsikon Létrehozása - Cheats / Patches Csalások / Javítások - SFO Viewer SFO Nézegető - Trophy Viewer Trófeák Megtekintése - Open Folder... Mappa megnyitása... - Open Game Folder Játék Mappa Megnyitása - Open Save Data Folder Mentési adatok mappa megnyitása - Open Log Folder Napló mappa megnyitása - Copy info... Információ Másolása... - Copy Name Név Másolása - Copy Serial Széria Másolása - Copy All Összes Másolása - Delete... Törlés... - Delete Game Játék törlése - Delete Update Frissítések törlése - Delete DLC DLC-k törlése - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Parancsikon létrehozása - - Shortcut created successfully!\n %1 - Parancsikon sikeresen létrehozva!\n %1 + Shortcut created successfully! + Parancsikon sikeresen létrehozva! - Error Hiba - - Error creating shortcut!\n %1 - Hiba a parancsikon létrehozásával!\n %1 + Error creating shortcut! + Hiba a parancsikon létrehozásával! - Install PKG PKG telepítése - Game Játék - requiresEnableSeparateUpdateFolder_MSG Ehhez a funkcióhoz szükséges a 'Külön Frissítési Mappa Engedélyezése' opció, hogy működjön. Ha használni akarja, először engedélyezze azt. - This game has no update to delete! Ehhez a játékhoz nem tartozik törlendő frissítés! - - + Update Frissítés - This game has no DLC to delete! Ehhez a játékhoz nem tartozik törlendő DLC! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Biztosan törölni akarja a %1's %2 mappát? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder ELF Mappa Megnyitása/Hozzáadása - Install Packages (PKG) PKG-k Telepítése (PKG) - Boot Game Játék Indítása - Check for Updates Frissítések keresése - About shadPS4 A shadPS4-ről - Configure... Konfigurálás... - Install application from a .pkg file Program telepítése egy .pkg fájlból - Recent Games Legutóbbi Játékok - Exit Kilépés - Exit shadPS4 Kilépés a shadPS4-ből - Exit the application. Lépjen ki a programból. - Show Game List Játék Könyvtár Megjelenítése - Game List Refresh Játék Könyvtár Újratöltése - Tiny Apró - Small Kicsi - Medium Közepes - Large Nagy - List View Lista Nézet - Grid View Rács Nézet - Elf Viewer Elf Nézegető - Game Install Directory Játék Telepítési Mappa - Download Cheats/Patches Csalások / Javítások letöltése - Dump Game List Játéklista Dumpolása - PKG Viewer PKG Nézegető - Search... Keresés... - File Fájl - View Nézet - Game List Icons Játékkönyvtár Ikonok - Game List Mode Játékkönyvtár Nézet - Settings Beállítások - Utils Segédeszközök - Themes Témák - Help Segítség - Dark Sötét - Light Világos - Green Zöld - Blue Kék - Violet Ibolya - toolBar Eszköztár + + Game List + Játéklista + + + * Unsupported Vulkan Version + * Nem támogatott Vulkan verzió + + + Download Cheats For All Installed Games + Csalások letöltése minden telepített játékhoz + + + Download Patches For All Games + Javítások letöltése minden játékhoz + + + Download Complete + Letöltés befejezve + + + You have downloaded cheats for all the games you have installed. + Minden elérhető csalás letöltődött az összes telepített játékhoz. + + + Patches Downloaded Successfully! + Javítások sikeresen letöltve! + + + All Patches available for all games have been downloaded. + Az összes játékhoz elérhető javí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! + Frissítés észlelve! + + + PKG and Game versions match: + A PKG és a játék verziói egyeznek: + + + Would you like to overwrite? + Szeretné felülírni? + + + PKG Version %1 is older than installed version: + A(z) %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 Telepítés + + + Would you like to install DLC: %1? + Szeretné telepíteni a %1 DLC-t? + + + DLC already installed: + DLC már telepítve: + + + Game already installed + A játék már telepítve van + + + 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 + PKGViewer - Open Folder Mappa Megnyitása @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trófeák Megtekintése @@ -458,989 +509,704 @@ SettingsDialog - Settings Beállítások - General Általános - System Rendszer - Console Language A Konzol Nyelvezete - Emulator Language Az Emulátor Nyelvezete - Emulator Emulátor - Enable Fullscreen Teljes Képernyő Engedélyezése - Enable Separate Update Folder Külön Frissítési Mappa Engedélyezése - Show Splash Indítóképernyő Mutatása - Is PS4 Pro PS4 Pro mód - Enable Discord Rich Presence A Discord Rich Presence engedélyezése - Username Felhasználónév - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Naplózó - Log Type Naplózási Típus - Log Filter Naplózási Filter - + Open Log Location + Napló helyének megnyitása + + Input Bemenet - Cursor Kurzor - Hide Cursor Kurzor elrejtése - Hide Cursor Idle Timeout Kurzor inaktivitási időtúllépés - + s + s + + Controller Kontroller - Back Button Behavior Vissza gomb Viselkedése - Graphics Grafika - Graphics Device Grafikai Eszköz - Width Szélesség - Height Magasság - Vblank Divider Vblank Elosztó - Advanced Haladó - Enable Shaders Dumping Shader Dumpolás Engedélyezése - Enable NULL GPU NULL GPU Engedélyezése - Paths Útvonalak - Game Folders Játékmappák - Add... Hozzáadás... - Remove Eltávolítás - Debug Debugolás - Enable Debug Dumping Debug Dumpolás Engedélyezése - Enable Vulkan Validation Layers Vulkan Validációs Rétegek Engedélyezése - Enable Vulkan Synchronization Validation Vulkan Szinkronizálás Validáció - Enable RenderDoc Debugging RenderDoc Debugolás Engedélyezése - Update Frissítés - Check for Updates at Startup Frissítések keresése indításkor - Update Channel Frissítési Csatorna - Check for Updates Frissítések keresése - GUI Settings GUI Beállítások - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Címzene lejátszása - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Hangerő - - - MainWindow - - Game List - Játéklista + Audio Backend + Audio Backend - - * Unsupported Vulkan Version - * Nem támogatott Vulkan verzió - - - - Download Cheats For All Installed Games - Csalások letöltése minden telepített játékhoz - - - - Download Patches For All Games - Javítások letöltése minden játékhoz - - - - Download Complete - Letöltés befejezve - - - - You have downloaded cheats for all the games you have installed. - Minden elérhető csalás letöltődött az összes telepített játékhoz. - - - - Patches Downloaded Successfully! - Javítások sikeresen letöltve! - - - - All Patches available for all games have been downloaded. - Az összes játékhoz elérhető javí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! - Frissítés észlelve! - - - - PKG and Game versions match: - A PKG és a játék verziói egyeznek: - - - - Would you like to overwrite? - Szeretné felülírni? - - - - PKG Version %1 is older than installed version: - A(z) %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 Telepítés - - - - Would you like to install DLC: %1? - Szeretné telepíteni a %1 DLC-t? - - - - DLC already installed: - DLC már telepítve: - - - - Game already installed - A játék már telepítve van - - - - 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 for - Cheats / Patches for - - - - defaultTextEdit_MSG - A csalások/javítások kísérleti jellegűek.\nHasználja őket óvatosan.\n\nTöltse le a csalásokat egyesével a tároló kiválasztásával és a letöltés gombra kattintással.\nA Javítások fül alatt egyszerre letöltheti az összes javítást, majd választhat, melyeket szeretné használni, és elmentheti a választását.\n\nMivel nem mi 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. Ha a javítások nem jelennek meg, lehet, hogy nem léteznek a játék adott sorozatszámához és verziójához. - - - - 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. - - - - The game is in version: %1 - A játék verziója: %1 - - - - The downloaded patch only works on version: %1 - A letöltött javításhoz a(z) %1 verzió működik - - - - You may need to update your game. - Lehet, hogy frissítened kell a játékodat. - - - - Incompatibility Notice - Inkompatibilitási értesítés - - - - 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 mappa nem létezik: - - - - Failed to open files.json for reading. - Nem sikerült megnyitni a files.json fájlt olvasásra. - - - - Name: - Név: - - - - Can't apply cheats before the game is started - Nem lehet csalásokat alkalmazni, mielőtt a játék elindul. - - - - SettingsDialog - - - Save - Mentés - - - Apply Alkalmaz - Restore Defaults Alapértelmezett értékek visszaállítása - Close Bezárás - Point your mouse at an option to display its description. Helyezze az egérmutatót egy lehetőség fölé, hogy megjelenítse annak leírását. - consoleLanguageGroupBox Konzol nyelve:\nBeállítja a PS4 játék nyelvét.\nAjánlott a játék által támogatott nyelvre állítani, amely régiónként változhat. - emulatorLanguageGroupBox Emulátor nyelve:\nBeállítja az emulátor felhasználói felületének nyelvét. - fullscreenCheckBox Teljes képernyő engedélyezése:\nAutomatikusan teljes képernyőre állítja a játék ablakát.\nEz a F11 billentyű megnyomásával kapcsolható ki/be. - separateUpdatesCheckBox Külön Frissítéi Mappa Engedélyezése:\nEngedélyezi a frissítések külön mappába helyezését, a könnyű kezelésük érdekében. - showSplashCheckBox Indítóképernyő megjelenítése:\nMegjeleníti a játék indítóképernyőjét (különleges képet) a játék elindításakor. - ps4proCheckBox PS4 Pro:\nAz emulátort PS4 PRO-ként kezeli, ami engedélyezhet speciális funkciókat olyan játékokban, amelyek támogatják azt. - discordRPCCheckbox A Discord Rich Presence engedélyezése:\nMegjeleníti az emulator ikonját és a kapcsolódó információkat a Discord profilján. - userName Felhasználónév:\nBeállítja a PS4 fiók felhasználónevét, amelyet egyes játékok megjeleníthetnek. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Napló típusa:\nBeállítja, hogy szinkronizálja-e a naplóablak kimenetét a teljesítmény érdekében. Ennek kedvezőtlen hatásai lehetnek az emulációra. - logFilter Napló szűrő:\nCsak bizonyos információk megjelenítésére szűri a naplót.\nPéldák: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Szintek: Trace, Debug, Info, Warning, Error, Critical - ebben a sorrendben, egy konkrét szint elnémítja az előtte lévő összes szintet, és naplózza az utána következő szinteket. - updaterGroupBox Frissítés:\nRelease: Hivatalos verziók, amelyeket havonta adnak ki, és amelyek nagyon elavultak lehetnek, de megbízhatóbbak és teszteltek.\nNightly: Fejlesztési verziók, amelyek az összes legújabb funkciót és javítást tartalmazzák, de hibákat tartalmazhatnak és kevésbé stabilak. - GUIgroupBox Játék címzene lejátszása:\nHa a játék támogatja, engedélyezze egy speciális zene lejátszását, amikor a játékot kiválasztja a GUI-ban. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Kurzor elrejtése:\nVálassza ki, mikor tűnjön el az egérmutató:\nSoha: Az egér mindig látható.\nInaktív: Állítson be egy időt, amennyi idő mozdulatlanság után eltűnik.\nMindig: az egér mindig el lesz rejtve. - idleTimeoutGroupBox Állítson be egy időt, ami után egér inaktív állapotban eltűnik. - backButtonBehaviorGroupBox Vissza gomb viselkedés:\nBeállítja a vezérlő vissza gombját, hogy utánozza a PS4 érintőpadján megadott pozíció megérintését. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Soha - Idle Inaktív - Always Mindig - Touchpad Left Érintőpad Bal - Touchpad Right Érintőpad Jobb - Touchpad Center Érintőpad Közép - None Semmi - graphicsAdapterGroupBox Grafikus eszköz:\nTöbb GPU-s rendszereken válassza ki, melyik GPU-t használja az emulátor a legördülő listából,\nvagy válassza az "Auto Select" lehetőséget, hogy automatikusan kiválassza azt. - resolutionLayout Szélesség/Magasság:\nBeállítja az emulátor ablakának méretét induláskor, amely a játék során átméretezhető.\nEz különbözik a játékbeli felbontástól. - heightDivider Vblank elosztó:\nAz emulátor frissítési sebessége e számot megszorozva működik. Ennek megváltoztatása kedvezőtlen hatásokat okozhat, például növelheti a játék sebességét, vagy megszakíthat kritikus játékfunkciókat, amelyek nem számítanak arra, hogy ez megváltozik! - dumpShadersCheckBox Shader dumping engedélyezése:\nMűszaki hibaelhárítás céljából a játékok shaderjeit elmenti egy mappába, ahogy renderelődnek. - nullGpuCheckBox Null GPU engedélyezése:\nMűszaki hibaelhárítás céljából letiltja a játék renderelését, mintha nem lenne grafikus kártya. - gameFoldersBox Játék mappák:\nA mappák listája, ahol telepített játékok vannak. - addFolderButton Hozzáadás:\nHozzon létre egy mappát a listában. - removeFolderButton Eltávolítás:\nTávolítson el egy mappát a listából. - debugDump Debug dumpolás engedélyezése:\nElmenti a futó PS4 program import- és exportszimbólumait, valamint a fájl fejlécinformációit egy könyvtárba. - vkValidationCheckBox Vulkan validációs rétegek engedélyezése:\nEngedélyezi a Vulkan renderelő állapotának validálását és információk naplózását annak belső állapotáról. Ez csökkenti a teljesítményt és valószínűleg megváltoztatja az emuláció viselkedését. - vkSyncValidationCheckBox Vulkan szinkronizációs validáció engedélyezése:\nEngedélyezi a Vulkan renderelési feladatok időzítésének validálását. Ez csökkenti a teljesítményt és valószínűleg megváltoztatja az emuláció viselkedését. - rdocCheckBox RenderDoc hibakeresés engedélyezése:\nHa engedélyezve van, az emulátor kompatibilitást biztosít a Renderdoc számára, hogy lehetővé tegye a jelenleg renderelt keret rögzítését és elemzését. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + defaultTextEdit_MSG + A csalások/javítások kísérleti jellegűek.\nHasználja őket óvatosan.\n\nTöltse le a csalásokat egyesével a tároló kiválasztásával és a letöltés gombra kattintással.\nA Javítások fül alatt egyszerre letöltheti az összes javítást, majd választhat, melyeket szeretné használni, és elmentheti a választását.\n\nMivel nem mi 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. Ha a javítások nem jelennek meg, lehet, hogy nem léteznek a játék adott sorozatszámához és verziójához. + + + 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. + + + The game is in version: %1 + A játék verziója: %1 + + + The downloaded patch only works on version: %1 + A letöltött javításhoz a(z) %1 verzió működik + + + You may need to update your game. + Lehet, hogy frissítened kell a játékodat. + + + Incompatibility Notice + Inkompatibilitási értesítés + + + 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 mappa nem létezik: + + + Failed to open files.json for reading. + Nem sikerült megnyitni a files.json fájlt olvasásra. + + + Name: + Név: + + + Can't apply cheats before the game is started + Nem lehet csalásokat alkalmazni, mielőtt a játék elindul. + + GameListFrame - Icon Ikon - Name Név - Serial Sorozatszám - Compatibility Compatibility - Region Régió - Firmware Firmware - Size Méret - Version Verzió - Path Útvonal - Play Time Játékidő - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Automatikus frissítő - Error Hiba - Network error: Hálózati hiba: - Failed to parse update information. A frissítési információk elemzése sikertelen. - No pre-releases found. Nem található előzetes kiadás. - Invalid release data. Érvénytelen kiadási adatok. - No download URL found for the specified asset. Nincs letöltési URL a megadott eszközhöz. - Your version is already up to date! A verziód már naprakész! - Update Available Frissítés elérhető - Update Channel Frissítési Csatorna - Current Version Jelenlegi verzió - Latest Version Új verzió - Do you want to update? Szeretnéd frissíteni? - Show Changelog Változások megjelenítése - Check for Updates at Startup Frissítések keresése indításkor - Update Frissítés - No Mégse - Hide Changelog Változások elrejtése - Changes Változások - Network error occurred while trying to access the URL Hálózati hiba történt az URL elérésekor - Download Complete Letöltés kész - The update has been downloaded, press OK to install. A frissítés letöltődött, nyomja meg az OK gombot az telepítéshez. - Failed to save the update file at A frissítési fájl mentése nem sikerült a következő helyre - Starting Update... Frissítés indítása... - Failed to create the update script file A frissítési szkript fájl létrehozása nem sikerült + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts index 098c17bc4..fc5ad4a99 100644 --- a/src/qt_gui/translations/id.ts +++ b/src/qt_gui/translations/id.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Cheat / Patch - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Buka Folder... - Open Game Folder Buka Folder Game - Open Save Data Folder Buka Folder Data Simpanan - Open Log Folder Buka Folder Log - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Periksa pembaruan - 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 - Download Cheats/Patches Unduh Cheat / Patch - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Bantuan - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Daftar game + + + * 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! + Patch terdeteksi! + + + PKG and Game versions match: + Versi PKG dan Game cocok: + + + Would you like to overwrite? + Apakah 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 + Instalasi DLC + + + 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 + + + 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Aktifkan Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Buka Lokasi Log + + Input Masukan - Cursor Kursor - Hide Cursor Sembunyikan kursor - Hide Cursor Idle Timeout Batas waktu sembunyikan kursor tidak aktif - + s + s + + Controller Pengontrol - Back Button Behavior Perilaku tombol kembali - 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 - Paths Jalur - Game Folders Folder Permainan - Add... Tambah... - Remove Hapus - 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 - Update Pembaruan - Check for Updates at Startup Periksa pembaruan saat mulai - Update Channel Saluran Pembaruan - Check for Updates Periksa pembaruan - GUI Settings Pengaturan GUI - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Putar musik judul - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Volume - - - MainWindow - - Game List - Daftar game + Audio Backend + Audio Backend - - * 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! - Patch terdeteksi! - - - - PKG and Game versions match: - Versi PKG dan Game cocok: - - - - Would you like to overwrite? - Apakah 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 - Instalasi DLC - - - - 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 - - - - 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 for - Cheats / Patches for - - - - 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. Jika patch tidak muncul, mungkin patch tersebut tidak ada untuk nomor seri dan versi game yang spesifik. - - - - Failed to parse JSON data from HTML. - Gagal menganalisis data JSON dari HTML. - - - - Failed to retrieve HTML page. - Gagal mengambil halaman HTML. - - - - The game is in version: %1 - Permainan berada di versi: %1 - - - - The downloaded patch only works on version: %1 - Patch yang diunduh hanya berfungsi pada versi: %1 - - - - You may need to update your game. - Anda mungkin perlu memperbarui permainan Anda. - - - - Incompatibility Notice - Pemberitahuan Ketidakcocokan - - - - 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: - - - - Can't apply cheats before the game is started - Tidak bisa menerapkan cheat sebelum permainan dimulai. - - - - SettingsDialog - - - Save - Simpan - - - Apply Terapkan - Restore Defaults Kembalikan Pengaturan Default - Close Tutup - Point your mouse at an option to display its description. Arahkan mouse Anda pada opsi untuk menampilkan deskripsinya. - consoleLanguageGroupBox Bahasa Konsol:\nMenetapkan bahasa yang digunakan oleh permainan PS4.\nDisarankan untuk mengatur ini ke bahasa yang didukung oleh permainan, yang dapat bervariasi berdasarkan wilayah. - emulatorLanguageGroupBox Bahasa Emulator:\nMenetapkan bahasa antarmuka pengguna emulator. - fullscreenCheckBox Aktifkan Mode Layar Penuh:\nSecara otomatis menempatkan jendela permainan dalam mode layar penuh.\nIni dapat dinonaktifkan dengan menekan tombol F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Tampilkan Layar Pembuka:\nMenampilkan layar pembuka permainan (gambar khusus) saat permainan dimulai. - ps4proCheckBox Adalah PS4 Pro:\nMembuat emulator berfungsi sebagai PS4 PRO, yang mungkin mengaktifkan fitur khusus dalam permainan yang mendukungnya. - discordRPCCheckbox Aktifkan Discord Rich Presence:\nMenampilkan ikon emulator dan informasi relevan di profil Discord Anda. - userName Nama Pengguna:\nMenetapkan nama pengguna akun PS4, yang mungkin ditampilkan oleh beberapa permainan. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Jenis Log:\nMenetapkan apakah untuk menyinkronkan output jendela log untuk kinerja. Dapat memiliki efek buruk pada emulasi. - logFilter Filter Log:\nMenyaring log untuk hanya mencetak informasi tertentu.\nContoh: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Tingkatan: Trace, Debug, Info, Warning, Error, Critical - dalam urutan ini, tingkat tertentu membungkam semua tingkat sebelumnya dalam daftar dan mencatat setiap tingkat setelahnya. - updaterGroupBox Pembaruan:\nRelease: Versi resmi yang dirilis setiap bulan yang mungkin sangat ketinggalan zaman, tetapi lebih dapat diandalkan dan teruji.\nNightly: Versi pengembangan yang memiliki semua fitur dan perbaikan terbaru, tetapi mungkin mengandung bug dan kurang stabil. - GUIgroupBox Putar Musik Judul Permainan:\nJika permainan mendukungnya, aktifkan pemutaran musik khusus saat memilih permainan di GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Sembunyikan Kursor:\nPilih kapan kursor akan menghilang:\nTidak Pernah: Anda akan selalu melihat mouse.\nTidak Aktif: Tetapkan waktu untuk menghilang setelah tidak aktif.\nSelalu: Anda tidak akan pernah melihat mouse. - idleTimeoutGroupBox Tetapkan waktu untuk mouse menghilang setelah tidak aktif. - backButtonBehaviorGroupBox Perilaku Tombol Kembali:\nMengatur tombol kembali pada pengontrol untuk meniru ketukan di posisi yang ditentukan di touchpad PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Tidak Pernah - Idle Diam - Always Selalu - Touchpad Left Touchpad Kiri - Touchpad Right Touchpad Kanan - Touchpad Center Pusat Touchpad - None Tidak Ada - graphicsAdapterGroupBox Perangkat Grafis:\nPada sistem GPU ganda, pilih GPU yang akan digunakan emulator dari daftar dropdown,\natau pilih "Auto Select" untuk menentukan secara otomatis. - resolutionLayout Lebar/Tinggi:\nMenetapkan ukuran jendela emulator saat diluncurkan, yang dapat diubah ukurannya selama permainan.\nIni berbeda dari resolusi dalam permainan. - heightDivider Pembagi Vblank:\nKecepatan bingkai di mana emulator menyegarkan dikalikan dengan angka ini. Mengubah ini dapat memiliki efek buruk, seperti meningkatkan kecepatan permainan, atau merusak fungsi kritis permainan yang tidak mengharapkan ini berubah! - dumpShadersCheckBox Aktifkan Pembuangan Shader:\nUntuk tujuan debugging teknis, menyimpan shader permainan ke folder saat mereka dirender. - nullGpuCheckBox Aktifkan GPU Null:\nUntuk tujuan debugging teknis, menonaktifkan rendering permainan seolah-olah tidak ada kartu grafis. - gameFoldersBox Folder Permainan:\nDaftar folder untuk memeriksa permainan yang diinstal. - addFolderButton Tambah:\nTambahkan folder ke daftar. - removeFolderButton Hapus:\nHapus folder dari daftar. - debugDump Aktifkan Pembuangan Debug:\nMenyimpan simbol impor dan ekspor serta informasi header file dari program PS4 yang sedang berjalan ke direktori. - vkValidationCheckBox Aktifkan Vulkan Validation Layers:\nMengaktifkan sistem yang memvalidasi status penggambaran Vulkan dan mencatat informasi tentang status internalnya. Ini akan mengurangi kinerja dan kemungkinan mengubah perilaku emulasi. - vkSyncValidationCheckBox Aktifkan Vulkan Synchronization Validation:\nMengaktifkan sistem yang memvalidasi waktu tugas penggambaran Vulkan. Ini akan mengurangi kinerja dan kemungkinan mengubah perilaku emulasi. - rdocCheckBox Aktifkan Debugging RenderDoc:\nJika diaktifkan, emulator akan menyediakan kompatibilitas dengan Renderdoc untuk memungkinkan pengambilan dan analisis bingkai yang sedang dirender. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. Jika patch tidak muncul, mungkin patch tersebut tidak ada untuk nomor seri dan versi game yang spesifik. + + + Failed to parse JSON data from HTML. + Gagal menganalisis data JSON dari HTML. + + + Failed to retrieve HTML page. + Gagal mengambil halaman HTML. + + + The game is in version: %1 + Permainan berada di versi: %1 + + + The downloaded patch only works on version: %1 + Patch yang diunduh hanya berfungsi pada versi: %1 + + + You may need to update your game. + Anda mungkin perlu memperbarui permainan Anda. + + + Incompatibility Notice + Pemberitahuan Ketidakcocokan + + + 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: + + + Can't apply cheats before the game is started + Tidak bisa menerapkan cheat sebelum permainan dimulai. + + GameListFrame - Icon Ikon - Name Nama - Serial Serial - Compatibility Compatibility - Region Wilayah - Firmware Firmware - Size Ukuran - Version Versi - Path Jalur - Play Time Waktu Bermain - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Pembaruan Otomatis - Error Kesalahan - Network error: Kesalahan jaringan: - Failed to parse update information. Gagal memparse informasi pembaruan. - No pre-releases found. Tidak ada pra-rilis yang ditemukan. - Invalid release data. Data rilis tidak valid. - No download URL found for the specified asset. Tidak ada URL unduhan ditemukan untuk aset yang ditentukan. - Your version is already up to date! Versi Anda sudah terbaru! - Update Available Pembaruan Tersedia - Update Channel Saluran Pembaruan - Current Version Versi Saat Ini - Latest Version Versi Terbaru - Do you want to update? Apakah Anda ingin memperbarui? - Show Changelog Tampilkan Catatan Perubahan - Check for Updates at Startup Periksa pembaruan saat mulai - Update Perbarui - No Tidak - Hide Changelog Sembunyikan Catatan Perubahan - Changes Perubahan - Network error occurred while trying to access the URL Kesalahan jaringan terjadi saat mencoba mengakses URL - Download Complete Unduhan Selesai - The update has been downloaded, press OK to install. Pembaruan telah diunduh, tekan OK untuk menginstal. - Failed to save the update file at Gagal menyimpan file pembaruan di - Starting Update... Memulai Pembaruan... - Failed to create the update script file Gagal membuat file skrip pembaruan + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index dfbbf1cf3..f7ba3661b 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 Riguardo shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 è un emulatore sperimentale open-source per PlayStation 4. - 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 +25,6 @@ ElfViewer - Open Folder Apri Cartella @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Caricamento lista giochi, attendere :3 - Cancel Annulla - Loading... Caricamento... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Scegli cartella - Select which directory you want to install to. Seleziona in quale cartella vuoi effettuare l'installazione. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Scegli cartella - Directory to install games Cartella di installazione dei giochi - Browse Sfoglia - Error Errore - The value for location to install games is not valid. Il valore del percorso di installazione dei giochi non è valido. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Crea scorciatoia - Cheats / Patches Trucchi / Patch - SFO Viewer Visualizzatore SFO - Trophy Viewer Visualizzatore Trofei - Open Folder... Apri Cartella... - Open Game Folder Apri Cartella del Gioco - Open Save Data Folder Apri Cartella dei Dati di Salvataggio - Open Log Folder Apri Cartella dei Log - Copy info... Copia informazioni... - Copy Name Copia Nome - Copy Serial Copia Seriale - Copy All Copia Tutto - Delete... Elimina... - Delete Game Elimina Gioco - Delete Update Elimina Aggiornamento - Delete DLC Elimina DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Creazione scorciatoia - - Shortcut created successfully!\n %1 - Scorciatoia creata con successo!\n %1 + Shortcut created successfully! + Scorciatoia creata con successo! - Error Errore - - Error creating shortcut!\n %1 - Errore nella creazione della scorciatoia!\n %1 + Error creating shortcut! + Errore nella creazione della scorciatoia! - Install PKG Installa PKG - Game Gioco - requiresEnableSeparateUpdateFolder_MSG - This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. + Questa feature richiede che venga attivata l'opzione "Abilita Cartella Aggiornamenti Separata" per poter funzionare, per favore abilitala. - This game has no update to delete! Questo gioco non ha alcun aggiornamento da eliminare! - - + Update Update - This game has no DLC to delete! Questo gioco non ha alcun DLC da eliminare! - DLC DLC - Delete %1 Elimina %1 - Are you sure you want to delete %1's %2 directory? Sei sicuro di eliminale la cartella %2 di %1? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Apri/Aggiungi cartella Elf - Install Packages (PKG) Installa Pacchetti (PKG) - Boot Game Avvia Gioco - Check for Updates Controlla aggiornamenti - About shadPS4 Riguardo a shadPS4 - Configure... Configura... - Install application from a .pkg file Installa applicazione da un file .pkg - Recent Games Giochi Recenti - Exit Uscita - Exit shadPS4 Esci da shadPS4 - Exit the application. Esci dall'applicazione. - Show Game List Mostra Lista Giochi - Game List Refresh Aggiorna Lista Giochi - Tiny Minuscolo - Small Piccolo - Medium Medio - Large Grande - List View Visualizzazione Lista - Grid View Visualizzazione Griglia - Elf Viewer Visualizzatore Elf - Game Install Directory Cartella Installazione Giochi - Download Cheats/Patches Scarica Trucchi/Patch - Dump Game List Scarica Lista Giochi - PKG Viewer Visualizzatore PKG - Search... Cerca... - File File - View Visualizza - Game List Icons Icone Lista Giochi - Game List Mode Modalità Lista Giochi - Settings Impostazioni - Utils Utilità - Themes Temi - Help Aiuto - Dark Scuro - Light Chiaro - Green Verde - Blue Blu - Violet Viola - toolBar Barra strumenti + + Game List + Elenco giochi + + + * Unsupported Vulkan Version + * Versione Vulkan non supportata + + + Download Cheats For All Installed Games + Scarica Trucchi per tutti i giochi installati + + + Download Patches For All Games + Scarica Patch per tutti i giochi + + + Download Complete + Download completato + + + You have downloaded cheats for all the games you have installed. + Hai scaricato trucchi per tutti i giochi installati. + + + Patches Downloaded Successfully! + Patch scaricate con successo! + + + All Patches available for all games have been downloaded. + Tutte le patch disponibili per tutti i giochi sono state scaricate. + + + Games: + Giochi: + + + PKG File (*.PKG) + File PKG (*.PKG) + + + ELF files (*.bin *.elf *.oelf) + File ELF (*.bin *.elf *.oelf) + + + Game Boot + Avvia Gioco + + + Only one file can be selected! + Si può selezionare solo un file! + + + PKG Extraction + Estrazione file PKG + + + Patch detected! + Patch rilevata! + + + PKG and Game versions match: + Le versioni di PKG e del Gioco corrispondono: + + + Would you like to overwrite? + Vuoi sovrascrivere? + + + PKG Version %1 is older than installed version: + La versione PKG %1 è più vecchia rispetto alla versione installata: + + + Game is installed: + Gioco installato: + + + Would you like to install Patch: + Vuoi installare la patch: + + + DLC Installation + Installazione DLC + + + 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! + Questo file PKG contiene una patch. Per favore, installa prima il gioco! + + + PKG ERROR + ERRORE PKG + + + Extracting PKG %1/%2 + Estrazione file PKG %1/%2 + + + Extraction Finished + Estrazione Completata + + + Game successfully installed at %1 + Gioco installato correttamente in %1 + + + File doesn't appear to be a valid PKG file + Il file sembra non essere un file PKG valido + PKGViewer - Open Folder Apri Cartella @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Visualizzatore Trofei @@ -458,1119 +509,832 @@ SettingsDialog - Settings Impostazioni - General Generale - System Sistema - Console Language Lingua della console - Emulator Language Lingua dell'emulatore - Emulator Emulatore - Enable Fullscreen Abilita Schermo Intero - Enable Separate Update Folder - Abilità Cartella Aggiornamenti Separata + Abilita Cartella Aggiornamenti Separata - Show Splash Mostra Schermata Iniziale - Is PS4 Pro Modalità Ps4 Pro - Enable Discord Rich Presence Abilita Discord Rich Presence - Username Nome Utente - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Tipo di Log - Log Filter Filtro Log - + Open Log Location + Apri posizione del registro + + Input Input - Cursor Cursore - Hide Cursor Nascondi Cursore - Hide Cursor Idle Timeout Timeout inattività per nascondere il cursore - + s + s + + Controller Controller - Back Button Behavior Comportamento del pulsante Indietro - Graphics Grafica - Graphics Device Scheda Grafica - Width Larghezza - Height Altezza - Vblank Divider Divisore Vblank - Advanced Avanzate - Enable Shaders Dumping Abilita Dump Shader - Enable NULL GPU Abilita NULL GPU - Paths Percorsi - Game Folders Cartelle di gioco - Add... - Aggiungi... + Aggiungi... - Remove Rimuovi - Debug Debug - Enable Abilita Debug Dumping - Enable Vulkan Validation Layers Abilita Vulkan Validation Layers - Enable Vulkan Synchronization Validation Abilita Vulkan Synchronization Validation - Enable RenderDoc Debugging Abilita RenderDoc Debugging - Update Aggiornamento - Check for Updates at Startup Verifica aggiornamenti all’avvio - Update Channel Canale di Aggiornamento - Check for Updates Controlla aggiornamenti - GUI Settings Impostazioni GUI - Disable Trophy Pop-ups - Disable Trophy Pop-ups + Disabilita Notifica Trofei - Play title music Riproduci musica del titolo - Update Compatibility Database On Startup - Update Compatibility Database On Startup + Aggiorna Database Compatibilità all'Avvio - Game Compatibility - Game Compatibility + Compatibilità Gioco - Display Compatibility Data - Display Compatibility Data + Mostra Dati Compatibilità - Update Compatibility Database - Update Compatibility Database + Aggiorna Database Compatibilità - Volume Volume - - - MainWindow - - Game List - Elenco giochi + Audio Backend + Audio Backend - - * Unsupported Vulkan Version - * Versione Vulkan non supportata - - - - Download Cheats For All Installed Games - Scarica Trucchi per tutti i giochi installati - - - - Download Patches For All Games - Scarica Patch per tutti i giochi - - - - Download Complete - Download completato - - - - You have downloaded cheats for all the games you have installed. - Hai scaricato trucchi per tutti i giochi installati. - - - - Patches Downloaded Successfully! - Patch scaricate con successo! - - - - All Patches available for all games have been downloaded. - Tutte le patch disponibili per tutti i giochi sono state scaricate. - - - - Games: - Giochi: - - - - PKG File (*.PKG) - File PKG (*.PKG) - - - - ELF files (*.bin *.elf *.oelf) - File ELF (*.bin *.elf *.oelf) - - - - Game Boot - Avvia Gioco - - - - Only one file can be selected! - Si può selezionare solo un file! - - - - PKG Extraction - Estrazione file PKG - - - - Patch detected! - Patch rilevata! - - - - PKG and Game versions match: - Le versioni di PKG e del Gioco corrispondono: - - - - Would you like to overwrite? - Vuoi sovrascrivere? - - - - PKG Version %1 is older than installed version: - La versione PKG %1 è più vecchia rispetto alla versione installata: - - - - Game is installed: - Gioco installato: - - - - Would you like to install Patch: - Vuoi installare la patch: - - - - DLC Installation - Installazione DLC - - - - 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! - Questo file PKG contiene una patch. Per favore, installa prima il gioco! - - - - PKG ERROR - ERRORE PKG - - - - Extracting PKG %1/%2 - Estrazione file PKG %1/%2 - - - - Extraction Finished - Estrazione Completata - - - - Game successfully installed at %1 - Gioco installato correttamente in %1 - - - - File doesn't appear to be a valid PKG file - Il file sembra non essere un file PKG valido - - - - CheatsPatches - - - Cheats / Patches for - Cheats / Patches for - - - - defaultTextEdit_MSG - 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 - - - - No Image Available - Nessuna immagine disponibile - - - - Serial: - Seriale: - - - - Version: - Versione: - - - - Size: - Dimensione: - - - - Select Cheat File: - Seleziona File Trucchi: - - - - Repository: - Archivio: - - - - Download Cheats - Scarica trucchi - - - - Delete File - Cancella File - - - - No files selected. - Nessun file selezionato. - - - - You can delete the cheats you don't want after downloading them. - Puoi cancellare i trucchi che non vuoi utilizzare dopo averli scaricati. - - - - Do you want to delete the selected file?\n%1 - Vuoi cancellare il file selezionato?\n%1 - - - - Select Patch File: - Seleziona File Patch: - - - - Download Patches - Scarica Patch - - - Save Salva - - Cheats - Trucchi - - - - Patches - Patch - - - - Error - Errore - - - - No patch selected. - Nessuna patch selezionata. - - - - Unable to open files.json for reading. - Impossibile aprire il file .json per la lettura. - - - - No patch file found for the current serial. - Nessun file patch trovato per il seriale selezionato. - - - - Unable to open the file for reading. - Impossibile aprire il file per la lettura. - - - - Unable to open the file for writing. - Impossibile aprire il file per la scrittura. - - - - Failed to parse XML: - Analisi XML fallita: - - - - Success - Successo - - - - Options saved successfully. - Opzioni salvate con successo. - - - - Invalid Source - Fonte non valida - - - - The selected source is invalid. - La fonte selezionata non è valida. - - - - File Exists - Il file è presente - - - - File already exists. Do you want to replace it? - Il file è già presente. Vuoi sostituirlo? - - - - Failed to save file: - Salvataggio file fallito: - - - - Failed to download file: - Scaricamento file fallito: - - - - Cheats Not Found - Trucchi non trovati - - - - CheatsNotFound_MSG - 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 - Trucchi scaricati con successo! - - - - CheatsDownloadedSuccessfully_MSG - 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: - Salvataggio fallito: - - - - Failed to download: - Impossibile scaricare: - - - - Download Complete - Scaricamento completo - - - - DownloadComplete_MSG - 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. Se la patch non appare, potrebbe essere che non esista per il numero di serie e la versione specifica del gioco. - - - - Failed to parse JSON data from HTML. - Impossibile analizzare i dati JSON dall'HTML. - - - - Failed to retrieve HTML page. - Impossibile recuperare la pagina HTML. - - - - The game is in version: %1 - Il gioco è nella versione: %1 - - - - The downloaded patch only works on version: %1 - La patch scaricata funziona solo sulla versione: %1 - - - - You may need to update your game. - Potresti aver bisogno di aggiornare il tuo gioco. - - - - Incompatibility Notice - Avviso di incompatibilità - - - - Failed to open file: - Impossibile aprire file: - - - - XML ERROR: - ERRORE XML: - - - - Failed to open files.json for writing - Impossibile aprire i file .json per la scrittura - - - - Author: - Autore: - - - - Directory does not exist: - La cartella non esiste: - - - - Failed to open files.json for reading. - Impossibile aprire i file .json per la lettura. - - - - Name: - Nome: - - - - Can't apply cheats before the game is started - Non è possibile applicare i trucchi prima dell'inizio del gioco. - - - - SettingsDialog - - - Save - Salva - - - Apply Applica - Restore Defaults Ripristina Impostazioni Predefinite - Close Chiudi - Point your mouse at an option to display its description. Sposta il mouse su un'opzione per visualizzarne la descrizione. - consoleLanguageGroupBox Lingua della Console:\nImposta la lingua utilizzata dal gioco PS4.\nÈ consigliabile impostare questa su una lingua supportata dal gioco, che può variare a seconda della regione. - emulatorLanguageGroupBox Lingua dell'Emulatore:\nImposta la lingua dell'interfaccia utente dell'emulatore. - fullscreenCheckBox Abilita Schermo Intero:\nMetti automaticamente la finestra di gioco in modalità schermo intero.\nQuesto può essere disattivato premendo il tasto F11. - separateUpdatesCheckBox Abilita Cartella Aggiornamenti Separata:\nAbilita l'installazione degli aggiornamenti in una cartella separata per una più facile gestione. - showSplashCheckBox Mostra Schermata di Avvio:\nMostra la schermata di avvio del gioco (un'immagine speciale) mentre il gioco si sta avviando. - ps4proCheckBox È PS4 Pro:\nFa sì che l'emulatore si comporti come una PS4 PRO, il che può abilitare funzionalità speciali in giochi che la supportano. - discordRPCCheckbox Abilita Discord Rich Presence:\nMostra l'icona dell'emulatore e informazioni pertinenti sul tuo profilo Discord. - userName Nome Utente:\nImposta il nome utente dell'account PS4, che potrebbe essere visualizzato da alcuni giochi. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Tipo di Log:\nImposta se sincronizzare l'output della finestra di log per le prestazioni. Potrebbe avere effetti avversi sull'emulazione. - logFilter Filtro Log:\nFiltra il log per stampare solo informazioni specifiche.\nEsempi: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Livelli: Trace, Debug, Info, Warning, Error, Critical - in questo ordine, un livello specifico silenzia tutti i livelli precedenti nell'elenco e registra ogni livello successivo. - updaterGroupBox Aggiornamento:\nRelease: Versioni ufficiali rilasciate ogni mese che potrebbero essere molto datate, ma sono più affidabili e testate.\nNightly: Versioni di sviluppo che hanno tutte le ultime funzionalità e correzioni, ma potrebbero contenere bug e sono meno stabili. - GUIgroupBox Riproduci Musica del Titolo:\nSe un gioco lo supporta, attiva la riproduzione di musica speciale quando selezioni il gioco nell'interfaccia grafica. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Nascondi cursore:\nScegli quando il cursore scomparirà:\nMai: Vedrai sempre il mouse.\nInattivo: Imposta un tempo per farlo scomparire dopo essere stato inattivo.\nSempre: non vedrai mai il mouse. - - idleTimeoutGroupBox + idleTimeoutGroupBox Imposta un tempo affinché il mouse scompaia dopo essere stato inattivo. - backButtonBehaviorGroupBox Comportamento del pulsante Indietro:\nImposta il pulsante Indietro del controller per emulare il tocco sulla posizione specificata sul touchpad PS4. - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Mostra Dati Compatibilità:\nMostra informazioni sulla compatibilità del gioco nella visualizzazione lista. Abilita "Aggiorna Compatiblità all'Avvio" per ottenere informazioni aggiornate. - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Aggiorna Compatibilità all'Avvio:\nAggiorna automaticamente il database della compatibilità quando si avvia shadps4. - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. + Aggiorna Database Compatibilità:\nAggiorna immediatamente il database di compatibilità. - Never Mai - Idle Inattivo - Always Sempre - Touchpad Left Touchpad Sinistra - Touchpad Right Touchpad Destra - Touchpad Center Centro del Touchpad - None Nessuno - graphicsAdapterGroupBox Dispositivo Grafico:\nIn sistemi con più GPU, seleziona la GPU che l'emulatore utilizzerà dall'elenco a discesa,\no seleziona "Auto Select" per determinarlo automaticamente. - resolutionLayout Larghezza/Altezza:\nImposta la dimensione della finestra dell'emulatore all'avvio, che può essere ridimensionata durante il gioco.\nQuesto è diverso dalla risoluzione in gioco. - heightDivider Divisore Vblank:\nIl frame rate con cui l'emulatore si aggiorna viene moltiplicato per questo numero. Cambiare questo potrebbe avere effetti avversi, come aumentare la velocità del gioco o rompere funzionalità critiche del gioco che non si aspettano questa modifica! - dumpShadersCheckBox Abilita Pompaggio Shader:\nPer scopi di debug tecnico, salva gli shader dei giochi in una cartella mentre vengono resi. - nullGpuCheckBox Abilita GPU Null:\nPer scopi di debug tecnico, disabilita il rendering del gioco come se non ci fosse alcuna scheda grafica. - gameFoldersBox Cartelle di Gioco:\nL'elenco delle cartelle da controllare per i giochi installati. - addFolderButton Aggiungi:\nAggiungi una cartella all'elenco. - removeFolderButton Rimuovi:\nRimuovi una cartella dall'elenco. - debugDump Abilita Pompaggio di Debug:\nSalva i simboli di importazione ed esportazione e le informazioni sull'intestazione del file del programma PS4 attualmente in esecuzione in una directory. - vkValidationCheckBox Abilita Strati di Validazione Vulkan:\nAbilita un sistema che convalida lo stato del renderer Vulkan e registra informazioni sul suo stato interno. Ciò ridurrà le prestazioni e probabilmente cambierà il comportamento dell'emulazione. - vkSyncValidationCheckBox Abilita Validazione della Sincronizzazione Vulkan:\nAbilita un sistema che convalida il timing delle attività di rendering Vulkan. Ciò ridurrà le prestazioni e probabilmente cambierà il comportamento dell'emulazione. - rdocCheckBox Abilita Debugging RenderDoc:\nSe abilitato, l'emulatore fornirà compatibilità con Renderdoc per consentire la cattura e l'analisi del frame attualmente reso. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + defaultTextEdit_MSG + 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 + + + No Image Available + Nessuna immagine disponibile + + + Serial: + Seriale: + + + Version: + Versione: + + + Size: + Dimensione: + + + Select Cheat File: + Seleziona File Trucchi: + + + Repository: + Archivio: + + + Download Cheats + Scarica trucchi + + + Delete File + Cancella File + + + No files selected. + Nessun file selezionato. + + + You can delete the cheats you don't want after downloading them. + Puoi cancellare i trucchi che non vuoi utilizzare dopo averli scaricati. + + + Do you want to delete the selected file?\n%1 + Vuoi cancellare il file selezionato?\n%1 + + + Select Patch File: + Seleziona File Patch: + + + Download Patches + Scarica Patch + + + Save + Salva + + + Cheats + Trucchi + + + Patches + Patch + + + Error + Errore + + + No patch selected. + Nessuna patch selezionata. + + + Unable to open files.json for reading. + Impossibile aprire il file .json per la lettura. + + + No patch file found for the current serial. + Nessun file patch trovato per il seriale selezionato. + + + Unable to open the file for reading. + Impossibile aprire il file per la lettura. + + + Unable to open the file for writing. + Impossibile aprire il file per la scrittura. + + + Failed to parse XML: + Analisi XML fallita: + + + Success + Successo + + + Options saved successfully. + Opzioni salvate con successo. + + + Invalid Source + Fonte non valida + + + The selected source is invalid. + La fonte selezionata non è valida. + + + File Exists + Il file è presente + + + File already exists. Do you want to replace it? + Il file è già presente. Vuoi sostituirlo? + + + Failed to save file: + Salvataggio file fallito: + + + Failed to download file: + Scaricamento file fallito: + + + Cheats Not Found + Trucchi non trovati + + + CheatsNotFound_MSG + 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 + Trucchi scaricati con successo! + + + CheatsDownloadedSuccessfully_MSG + 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: + Salvataggio fallito: + + + Failed to download: + Impossibile scaricare: + + + Download Complete + Scaricamento completo + + + DownloadComplete_MSG + 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. Se la patch non appare, potrebbe essere che non esista per il numero di serie e la versione specifica del gioco. + + + Failed to parse JSON data from HTML. + Impossibile analizzare i dati JSON dall'HTML. + + + Failed to retrieve HTML page. + Impossibile recuperare la pagina HTML. + + + The game is in version: %1 + Il gioco è nella versione: %1 + + + The downloaded patch only works on version: %1 + La patch scaricata funziona solo sulla versione: %1 + + + You may need to update your game. + Potresti aver bisogno di aggiornare il tuo gioco. + + + Incompatibility Notice + Avviso di incompatibilità + + + Failed to open file: + Impossibile aprire file: + + + XML ERROR: + ERRORE XML: + + + Failed to open files.json for writing + Impossibile aprire i file .json per la scrittura + + + Author: + Autore: + + + Directory does not exist: + La cartella non esiste: + + + Failed to open files.json for reading. + Impossibile aprire i file .json per la lettura. + + + Name: + Nome: + + + Can't apply cheats before the game is started + Non è possibile applicare i trucchi prima dell'inizio del gioco. + + GameListFrame - Icon Icona - Name Nome - Serial Seriale - Compatibility - Compatibility + Compatibilità - Region Regione - Firmware Firmware - Size Dimensione - Version Versione - Path Percorso - Play Time Tempo di Gioco - Never Played - Never Played + Mai Giocato + + + h + h + + + m + m + + + s + s - Compatibility is untested - Compatibility is untested + Nessuna informazione sulla compatibilità - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + Il gioco non si avvia in modo corretto / forza chiusura dell'emulatore - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + Il gioco si avvia, ma mostra solo una schermata nera - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + Il gioco mostra immagini ma non va oltre il menu - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + Il gioco ha problemi gravi di emulazione oppure framerate troppo basso - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + Il gioco può essere completato con buone prestazioni e senza problemi gravi CheckUpdate - Auto Updater Aggiornamento automatico - Error Errore - Network error: Errore di rete: - Failed to parse update information. Impossibile analizzare le informazioni di aggiornamento. - No pre-releases found. Nessuna anteprima trovata. - Invalid release data. Dati della release non validi. - No download URL found for the specified asset. Nessun URL di download trovato per l'asset specificato. - Your version is already up to date! La tua versione è già aggiornata! - Update Available Aggiornamento disponibile - Update Channel Canale di Aggiornamento - Current Version Versione attuale - Latest Version Ultima versione - Do you want to update? Vuoi aggiornare? - Show Changelog Mostra il Changelog - Check for Updates at Startup Controlla aggiornamenti all’avvio - Update Aggiorna - No No - Hide Changelog Nascondi il Changelog - Changes Modifiche - Network error occurred while trying to access the URL Si è verificato un errore di rete durante il tentativo di accesso all'URL - Download Complete Download completato - The update has been downloaded, press OK to install. L'aggiornamento è stato scaricato, premi OK per installare. - Failed to save the update file at Impossibile salvare il file di aggiornamento in - Starting Update... Inizio aggiornamento... - Failed to create the update script file Impossibile creare il file di script di aggiornamento + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 c5ee65ce0..21c8145ed 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -6,22 +6,18 @@ 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. このソフトウェアは、合法的に入手していないゲームをプレイするために使用するものではありません。 @@ -29,7 +25,6 @@ ElfViewer - Open Folder フォルダを開く @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 ゲームリストを読み込み中です。お待ちください :3 - Cancel キャンセル - Loading... 読み込み中... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - ディレクトリを選択 - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - ディレクトリを選択 - Directory to install games ゲームをインストールするディレクトリ - Browse 参照 - Error エラー - The value for location to install games is not valid. ゲームをインストールする場所が無効です。 @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut ショートカットを作成 - Cheats / Patches チート / パッチ - SFO Viewer SFOビューワー - Trophy Viewer トロフィービューワー - Open Folder... フォルダを開く... - Open Game Folder ゲームフォルダを開く - Open Save Data Folder セーブデータフォルダを開く - Open Log Folder ログフォルダを開く - Copy info... 情報をコピー... - Copy Name 名前をコピー - Copy Serial シリアルをコピー - Copy All すべてコピー - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation ショートカットの作成 - - Shortcut created successfully!\n %1 - ショートカットが正常に作成されました!\n %1 + Shortcut created successfully! + ショートカットが正常に作成されました! - Error エラー - - Error creating shortcut!\n %1 - ショートカットの作成に失敗しました!\n %1 + Error creating shortcut! + ショートカットの作成に失敗しました! - Install PKG PKGをインストール - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Elfフォルダを開く/追加する - Install Packages (PKG) パッケージをインストール (PKG) - Boot Game ゲームを起動 - Check for Updates 更新を確認する - 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 テーマ - Help ヘルプ - Dark ダーク - Light ライト - Green グリーン - Blue ブルー - Violet バイオレット - toolBar ツールバー + + Game List + ゲームリスト + + + * 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! + パッチが検出されました! + + + 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はパッチです。ゲームを先にインストールしてください! + + + 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 フォルダーを開く @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer トロフィービューアー @@ -458,989 +509,704 @@ SettingsDialog - Settings 設定 - General 一般 - System システム - Console Language コンソール言語 - Emulator Language エミュレーター言語 - Emulator エミュレーター - Enable Fullscreen フルスクリーンを有効にする - Enable Separate Update Folder Enable Separate Update Folder - Show Splash スプラッシュを表示する - Is PS4 Pro PS4 Proモード - Enable Discord Rich Presence Discord Rich Presenceを有効にする - Username ユーザー名 - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger ロガー - Log Type ログタイプ - Log Filter ログフィルター - + Open Log Location + ログの場所を開く + + Input 入力 - Cursor カーソル - Hide Cursor カーソルを隠す - Hide Cursor Idle Timeout カーソル非アクティブタイムアウト - + s + s + + Controller コントローラー - Back Button Behavior 戻るボタンの動作 - Graphics グラフィックス - Graphics Device グラフィックスデバイス - Width - Height 高さ - Vblank Divider Vblankディバイダー - Advanced 高度な設定 - Enable Shaders Dumping シェーダーのダンプを有効にする - Enable NULL GPU NULL GPUを有効にする - Paths パス - Game Folders ゲームフォルダ - Add... 追加... - Remove 削除 - Debug デバッグ - Enable Debug Dumping デバッグダンプを有効にする - Enable Vulkan Validation Layers Vulkan検証レイヤーを有効にする - Enable Vulkan Synchronization Validation Vulkan同期検証を有効にする - Enable RenderDoc Debugging RenderDocデバッグを有効にする - Update 更新 - Check for Updates at Startup 起動時に更新確認 - Update Channel アップデートチャネル - Check for Updates 更新を確認 - GUI Settings GUI設定 - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music タイトル音楽を再生する - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume 音量 - - - MainWindow - - Game List - ゲームリスト + Audio Backend + Audio Backend - - * 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! - パッチが検出されました! - - - - 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はパッチです。ゲームを先にインストールしてください! - - - - 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 for - Cheats / Patches for - - - - 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ページの取得に失敗しました。 - - - - The game is in version: %1 - ゲームのバージョン: %1 - - - - The downloaded patch only works on version: %1 - ダウンロードしたパッチはバージョン: %1 のみ機能します - - - - You may need to update your game. - ゲームを更新する必要があるかもしれません。 - - - - Incompatibility Notice - 互換性のない通知 - - - - 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: - 名前: - - - - Can't apply cheats before the game is started - ゲームが開始される前にチートを適用することはできません。 - - - - SettingsDialog - - - Save - 保存 - - - Apply 適用 - Restore Defaults デフォルトに戻す - Close 閉じる - Point your mouse at an option to display its description. オプションにマウスをポイントすると、その説明が表示されます。 - consoleLanguageGroupBox コンソール言語:\nPS4ゲームが使用する言語を設定します。\nこれはゲームがサポートする言語に設定することをお勧めしますが、地域によって異なる場合があります。 - emulatorLanguageGroupBox エミュレーター言語:\nエミュレーターのユーザーインターフェースの言語を設定します。 - fullscreenCheckBox 全画面モードを有効にする:\nゲームウィンドウを自動的に全画面モードにします。\nF11キーを押すことで切り替えることができます。 - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox スプラッシュスクリーンを表示:\nゲーム起動中にゲームのスプラッシュスクリーン(特別な画像)を表示します。 - ps4proCheckBox PS4 Proです:\nエミュレーターがPS4 PROとして動作するようにし、これをサポートするゲームで特別な機能を有効にする場合があります。 - discordRPCCheckbox Discord Rich Presenceを有効にする:\nエミュレーターのアイコンと関連情報をDiscordプロフィールに表示します。 - userName ユーザー名:\nPS4のアカウントユーザー名を設定します。これは、一部のゲームで表示される場合があります。 - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox ログタイプ:\nパフォーマンスのためにログウィンドウの出力を同期させるかどうかを設定します。エミュレーションに悪影響を及ぼす可能性があります。 - logFilter ログフィルター:\n特定の情報のみを印刷するようにログをフィルタリングします。\n例: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" レベル: Trace, Debug, Info, Warning, Error, Critical - この順序で、特定のレベルはリスト内のすべての前のレベルをサイレンスし、その後のすべてのレベルをログに記録します。 - updaterGroupBox 更新:\nRelease: 非常に古いかもしれないが、より信頼性が高くテスト済みの公式バージョンを毎月リリースします。\nNightly: 最新の機能と修正がすべて含まれていますが、バグが含まれている可能性があり、安定性は低いです。 - GUIgroupBox タイトルミュージックを再生:\nゲームがそれをサポートしている場合、GUIでゲームを選択したときに特別な音楽を再生することを有効にします。 - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox カーソルを隠す:\nカーソルが消えるタイミングを選択してください:\n決して: いつでもマウスが見えます。\nアイドル: アイダルの後に消えるまでの時間を設定します。\n常に: マウスは決して見えません。 - idleTimeoutGroupBox アイドル後にマウスが消えるまでの時間を設定します。 - backButtonBehaviorGroupBox 戻るボタンの動作:\nコントローラーの戻るボタンを、PS4のタッチパッドの指定された位置をタッチするように設定します。 - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never 決して - Idle アイドル - Always 常に - Touchpad Left タッチパッド左 - Touchpad Right タッチパッド右 - Touchpad Center タッチパッド中央 - None なし - graphicsAdapterGroupBox グラフィックデバイス:\n複数のGPUシステムで、ドロップダウンリストからエミュレーターで使用するGPUを選択するか、\n「自動選択」を選択して自動的に決定します。 - resolutionLayout 幅/高さ:\n起動時にエミュレーターウィンドウのサイズを設定します。ゲーム中にサイズ変更できます。\nこれはゲーム内の解像度とは異なります。 - heightDivider Vblankディバイダー:\nエミュレーターが更新されるフレームレートにこの数を掛けます。これを変更すると、ゲームの速度が上がったり、想定外の変更がある場合、ゲームの重要な機能が壊れる可能性があります! - dumpShadersCheckBox シェーダーダンプを有効にする:\n技術的なデバッグの目的で、レンダリング中にゲームのシェーダーをフォルダーに保存します。 - nullGpuCheckBox Null GPUを有効にする:\n技術的なデバッグの目的で、グラフィックスカードがないかのようにゲームのレンダリングを無効にします。 - gameFoldersBox ゲームフォルダ:\nインストールされたゲームを確認するためのフォルダのリスト。 - addFolderButton 追加:\nリストにフォルダを追加します。 - removeFolderButton 削除:\nリストからフォルダを削除します。 - debugDump デバッグダンプを有効にする:\n現在実行中のPS4プログラムのインポートおよびエクスポートシンボルとファイルヘッダー情報をディレクトリに保存します。 - vkValidationCheckBox Vulkanバリデーションレイヤーを有効にする:\nVulkanのレンダリングステータスを検証し、内部状態に関する情報をログに記録するシステムを有効にします。これによりパフォーマンスが低下し、エミュレーションの動作が変わる可能性があります。 - vkSyncValidationCheckBox Vulkan同期バリデーションを有効にする:\nVulkanのレンダリングタスクのタイミングを検証するシステムを有効にします。これによりパフォーマンスが低下し、エミュレーションの動作が変わる可能性があります。 - rdocCheckBox RenderDocデバッグを有効にする:\n有効にすると、エミュレーターはRenderdocとの互換性を提供し、現在レンダリング中のフレームのキャプチャと分析を可能にします。 + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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ページの取得に失敗しました。 + + + The game is in version: %1 + ゲームのバージョン: %1 + + + The downloaded patch only works on version: %1 + ダウンロードしたパッチはバージョン: %1 のみ機能します + + + You may need to update your game. + ゲームを更新する必要があるかもしれません。 + + + Incompatibility Notice + 互換性のない通知 + + + 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: + 名前: + + + Can't apply cheats before the game is started + ゲームが開始される前にチートを適用することはできません。 + + GameListFrame - Icon アイコン - Name 名前 - Serial シリアル - Compatibility Compatibility - Region 地域 - Firmware ファームウェア - Size サイズ - Version バージョン - Path パス - Play Time プレイ時間 - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater 自動アップデーター - Error エラー - Network error: ネットワークエラー: - Failed to parse update information. アップデート情報の解析に失敗しました。 - No pre-releases found. プレリリースは見つかりませんでした。 - Invalid release data. リリースデータが無効です。 - No download URL found for the specified asset. 指定されたアセットのダウンロードURLが見つかりませんでした。 - Your version is already up to date! あなたのバージョンはすでに最新です! - Update Available アップデートがあります - Update Channel アップデートチャネル - Current Version 現在のバージョン - Latest Version 最新バージョン - Do you want to update? アップデートしますか? - Show Changelog 変更ログを表示 - Check for Updates at Startup 起動時に更新確認 - Update アップデート - No いいえ - Hide Changelog 変更ログを隠す - Changes 変更点 - Network error occurred while trying to access the URL URLにアクセス中にネットワークエラーが発生しました - Download Complete ダウンロード完了 - The update has been downloaded, press OK to install. アップデートがダウンロードされました。インストールするにはOKを押してください。 - Failed to save the update file at 更新ファイルの保存に失敗しました - Starting Update... アップデートを開始しています... - Failed to create the update script file アップデートスクリプトファイルの作成に失敗しました + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 e47db791a..fea8d55bc 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches 치트 / 패치 - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Open Folder... - Open Game Folder Open Game Folder - Open Save Data Folder Open Save Data Folder - Open Log Folder Open Log Folder - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Check for Updates - About shadPS4 About shadPS4 - Configure... Configure... - Install application from a .pkg file Install application from a .pkg file - Recent Games Recent Games - Exit Exit - Exit shadPS4 Exit shadPS4 - Exit the application. Exit the application. - Show Game List Show Game List - Game List Refresh Game List Refresh - Tiny Tiny - Small Small - Medium Medium - Large Large - List View List View - Grid View Grid View - Elf Viewer Elf Viewer - Game Install Directory Game Install Directory - Download Cheats/Patches 치트 / 패치 다운로드 - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Help - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Game List + + + * Unsupported Vulkan Version + * Unsupported Vulkan Version + + + Download Cheats For All Installed Games + Download Cheats For All Installed Games + + + Download Patches For All Games + Download Patches For All Games + + + Download Complete + Download Complete + + + You have downloaded cheats for all the games you have installed. + You have downloaded cheats for all the games you have installed. + + + Patches Downloaded Successfully! + Patches Downloaded Successfully! + + + All Patches available for all games have been downloaded. + All Patches available for all games have been downloaded. + + + Games: + Games: + + + 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! + Patch detected! + + + PKG and Game versions match: + PKG and Game versions match: + + + Would you like to overwrite? + Would you like to overwrite? + + + PKG Version %1 is older than installed version: + PKG Version %1 is older than installed version: + + + Game is installed: + Game is installed: + + + Would you like to install Patch: + Would you like to install Patch: + + + DLC Installation + DLC Installation + + + Would you like to install DLC: %1? + Would you like to install DLC: %1? + + + DLC already installed: + DLC already installed: + + + Game already installed + Game already installed + + + PKG 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Enable Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + 로그 위치 열기 + + Input Input - Cursor Cursor - Hide Cursor Hide Cursor - Hide Cursor Idle Timeout Hide Cursor Idle Timeout - + s + s + + Controller Controller - Back Button Behavior Back Button Behavior - Graphics Graphics - 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 - Paths Paths - Game Folders Game Folders - Add... Add... - Remove Remove - Debug Debug - Enable Debug Dumping Enable Debug Dumping - Enable Vulkan Validation Layers Enable Vulkan Validation Layers - Enable Vulkan Synchronization Validation Enable Vulkan Synchronization Validation - Enable RenderDoc Debugging Enable RenderDoc Debugging - Update Update - Check for Updates at Startup Check for Updates at Startup - Update Channel Update Channel - Check for Updates Check for Updates - GUI Settings GUI Settings - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Play title music - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume 음량 - - - MainWindow - - Game List - Game List + Audio Backend + Audio Backend - - * 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! - Patch detected! - - - - PKG and Game versions match: - PKG and Game versions match: - - - - Would you like to overwrite? - Would you like to overwrite? - - - - PKG Version %1 is older than installed version: - PKG Version %1 is older than installed version: - - - - Game is installed: - Game is installed: - - - - Would you like to install Patch: - Would you like to install Patch: - - - - DLC Installation - DLC Installation - - - - Would you like to install DLC: %1? - Would you like to install DLC: %1? - - - - DLC already installed: - DLC already installed: - - - - Game already installed - Game already installed - - - - PKG 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 for - Cheats / Patches for - - - - 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. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. - - - - Failed to parse JSON data from HTML. - Failed to parse JSON data from HTML. - - - - Failed to retrieve HTML page. - Failed to retrieve HTML page. - - - - The game is in version: %1 - The game is in version: %1 - - - - The downloaded patch only works on version: %1 - The downloaded patch only works on version: %1 - - - - You may need to update your game. - You may need to update your game. - - - - Incompatibility Notice - Incompatibility Notice - - - - Failed to open file: - Failed to open file: - - - - XML ERROR: - XML ERROR: - - - - Failed to open files.json for writing - Failed to open files.json for writing - - - - Author: - Author: - - - - Directory does not exist: - Directory does not exist: - - - - Failed to open files.json for reading. - Failed to open files.json for reading. - - - - Name: - Name: - - - - Can't apply cheats before the game is started - Can't apply cheats before the game is started. - - - - SettingsDialog - - - Save - Save - - - Apply Apply - Restore Defaults Restore Defaults - Close Close - Point your mouse at an option to display its description. Point your mouse at an option to display its description. - consoleLanguageGroupBox Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. - emulatorLanguageGroupBox Emulator Language:\nSets the language of the emulator's user interface. - fullscreenCheckBox Enable Full Screen:\nAutomatically puts the game window into full-screen mode.\nThis can be toggled by pressing the F11 key. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. - ps4proCheckBox Is PS4 Pro:\nMakes the emulator act as a PS4 PRO, which may enable special features in games that support it. - discordRPCCheckbox Discord Rich Presence 활성화:\nDiscord 프로필에 에뮬레이터 아이콘과 관련 정보를 표시합니다. - userName Username:\nSets the PS4's account username, which may be displayed by some games. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. - logFilter Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Levels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. - updaterGroupBox Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. - GUIgroupBox Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. - idleTimeoutGroupBox Set a time for the mouse to disappear after being after being idle. - backButtonBehaviorGroupBox Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Never - Idle Idle - Always Always - Touchpad Left Touchpad Left - Touchpad Right Touchpad Right - Touchpad Center Touchpad Center - None None - graphicsAdapterGroupBox Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - resolutionLayout Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. - heightDivider Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! - dumpShadersCheckBox Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. - nullGpuCheckBox Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - gameFoldersBox Game Folders:\nThe list of folders to check for installed games. - addFolderButton Add:\nAdd a folder to the list. - removeFolderButton Remove:\nRemove a folder from the list. - debugDump Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. - vkValidationCheckBox Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state. This will reduce performance and likely change the behavior of emulation. - vkSyncValidationCheckBox Enable Vulkan Synchronization Validation:\nEnables a system that validates the timing of Vulkan rendering tasks. This will reduce performance and likely change the behavior of emulation. - rdocCheckBox Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. + + + Failed to parse JSON data from HTML. + Failed to parse JSON data from HTML. + + + Failed to retrieve HTML page. + Failed to retrieve HTML page. + + + The game is in version: %1 + The game is in version: %1 + + + The downloaded patch only works on version: %1 + The downloaded patch only works on version: %1 + + + You may need to update your game. + You may need to update your game. + + + Incompatibility Notice + Incompatibility Notice + + + Failed to open file: + Failed to open file: + + + XML ERROR: + XML ERROR: + + + Failed to open files.json for writing + Failed to open files.json for writing + + + Author: + Author: + + + Directory does not exist: + Directory does not exist: + + + Failed to open files.json for reading. + Failed to open files.json for reading. + + + Name: + Name: + + + Can't apply cheats before the game is started + Can't apply cheats before the game is started. + + GameListFrame - Icon Icon - Name Name - Serial Serial - Compatibility Compatibility - Region Region - Firmware Firmware - Size Size - Version Version - Path Path - Play Time Play Time - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Auto Updater - Error Error - Network error: Network error: - Failed to parse update information. Failed to parse update information. - No pre-releases found. No pre-releases found. - Invalid release data. Invalid release data. - No download URL found for the specified asset. No download URL found for the specified asset. - Your version is already up to date! Your version is already up to date! - Update Available Update Available - Update Channel Update Channel - Current Version Current Version - Latest Version Latest Version - Do you want to update? Do you want to update? - Show Changelog Show Changelog - Check for Updates at Startup Check for Updates at Startup - Update Update - No No - Hide Changelog Hide Changelog - Changes Changes - Network error occurred while trying to access the URL Network error occurred while trying to access the URL - Download Complete Download Complete - The update has been downloaded, press OK to install. The update has been downloaded, press OK to install. - Failed to save the update file at Failed to save the update file at - Starting Update... Starting Update... - Failed to create the update script file Failed to create the update script file + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 ba5308358..eaf51a975 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Apgaulės / Pleistrai Cheats / Patches - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Atidaryti Katalogą... - Open Game Folder Atidaryti Žaidimo Katalogą - Open Save Data Folder Atidaryti Išsaugotų Duomenų Katalogą - Open Log Folder Atidaryti Žurnalų Katalogą - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Patikrinti atnaujinimus - 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 - Download Cheats/Patches Atsisiųsti Apgaules / Pleistrus - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Pagalba - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Žaidimų sąrašas + + + * 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! + Rasta atnaujinimą! + + + PKG and Game versions match: + PKG ir žaidimo versijos sutampa: + + + Would you like to overwrite? + Ar norite 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 diegimas + + + Would you like to install DLC: %1? + Ar norite įdiegti DLC: %1? + + + DLC already installed: + DLC jau įdiegtas: + + + Game already installed + Žaidimas jau įdiegtas + + + 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Įjungti Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Atidaryti žurnalo vietą + + Input Įvestis - Cursor Žymeklis - Hide Cursor Slėpti žymeklį - Hide Cursor Idle Timeout Žymeklio paslėpimo neveikimo laikas - + s + s + + Controller Valdiklis - Back Button Behavior Atgal mygtuko elgsena - 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 - Paths Keliai - Game Folders Žaidimų aplankai - Add... Pridėti... - Remove Pašalinti - 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 - Update Atnaujinimas - Check for Updates at Startup Tikrinti naujinimus paleidus - Update Channel Atnaujinimo Kanalas - Check for Updates Patikrinkite atnaujinimus - GUI Settings GUI Nustatymai - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Groti antraštės muziką - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Garsumas - - - MainWindow - - Game List - Žaidimų sąrašas + Audio Backend + Audio Backend - - * 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! - Rasta atnaujinimą! - - - - PKG and Game versions match: - PKG ir žaidimo versijos sutampa: - - - - Would you like to overwrite? - Ar norite 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 diegimas - - - - Would you like to install DLC: %1? - Ar norite įdiegti DLC: %1? - - - - DLC already installed: - DLC jau įdiegtas: - - - - Game already installed - Žaidimas jau įdiegtas - - - - 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 for - Cheats / Patches for - - - - 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. Jei pleistras nepasirodo, gali būti, kad jo nėra tam tikram žaidimo serijos numeriui ir versijai. - - - - Failed to parse JSON data from HTML. - Nepavyko išanalizuoti JSON duomenų iš HTML. - - - - Failed to retrieve HTML page. - Nepavyko gauti HTML puslapio. - - - - The game is in version: %1 - Žaidimas yra versijoje: %1 - - - - The downloaded patch only works on version: %1 - Parsisiųstas pataisas veikia tik versijoje: %1 - - - - You may need to update your game. - Gali tekti atnaujinti savo žaidimą. - - - - Incompatibility Notice - Suderinamumo pranešimas - - - - 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: - - - - Can't apply cheats before the game is started - Negalima taikyti sukčiavimų prieš pradedant žaidimą. - - - - SettingsDialog - - - Save - Įrašyti - - - Apply Taikyti - Restore Defaults Atkurti numatytuosius nustatymus - Close Uždaryti - Point your mouse at an option to display its description. Žymeklį nukreipkite ant pasirinkimo, kad pamatytumėte jo aprašymą. - consoleLanguageGroupBox Konsole kalba:\nNustato kalbą, kurią naudoja PS4 žaidimai.\nRekomenduojama nustatyti kalbą, kurią palaiko žaidimas, priklausomai nuo regiono. - emulatorLanguageGroupBox Emuliatoriaus kalba:\nNustato emuliatoriaus vartotojo sąsajos kalbą. - fullscreenCheckBox Įjungti visą ekraną:\nAutomatiškai perjungia žaidimo langą į viso ekrano režimą.\nTai galima išjungti paspaudus F11 klavišą. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Rodyti paleidimo ekraną:\nPaleidimo metu rodo žaidimo paleidimo ekraną (ypatingą vaizdą). - ps4proCheckBox Ar PS4 Pro:\nPadaro, kad emuliatorius veiktų kaip PS4 PRO, kas gali įjungti specialias funkcijas žaidimuose, kurie tai palaiko. - discordRPCCheckbox Įjungti Discord Rich Presence:\nRodo emuliatoriaus ikoną ir susijusią informaciją jūsų Discord profilyje. - userName Vartotojo vardas:\nNustato PS4 paskyros vartotojo vardą, kuris gali būti rodomas kai kuriuose žaidimuose. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Žurnalo tipas:\nNustato, ar sinchronizuoti žurnalo lango išvestį našumui. Tai gali turėti neigiamą poveikį emuliacijai. - logFilter Žurnalo filtras:\nFiltruojamas žurnalas, kad būtų spausdinama tik konkreti informacija.\nPavyzdžiai: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Lygiai: Trace, Debug, Info, Warning, Error, Critical - šia tvarka, konkretus lygis nutildo visus ankstesnius lygius sąraše ir registruoja visus vėlesnius. - updaterGroupBox Atnaujinti:\nRelease: Oficialios versijos, išleidžiamos kiekvieną mėnesį, kurios gali būti labai pasenusios, tačiau yra patikimos ir išbandytos.\nNightly: Vystymo versijos, kuriose yra visos naujausios funkcijos ir taisymai, tačiau gali turėti klaidų ir būti mažiau stabilios. - GUIgroupBox Groti antraščių muziką:\nJei žaidimas tai palaiko, įjungia specialios muzikos grojimą, kai pasirinkite žaidimą GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Slėpti žymeklį:\nPasirinkite, kada žymeklis dings:\nNiekuomet: Visada matysite pelę.\nNeaktyvus: Nustatykite laiką, po kurio ji dings, kai bus neaktyvi.\nVisada: niekada nematysite pelės. - idleTimeoutGroupBox Nustatykite laiką, po kurio pelė dings, kai bus neaktyvi. - backButtonBehaviorGroupBox Atgal mygtuko elgesys:\nNustato valdiklio atgal mygtuką imituoti paspaudimą nurodytoje vietoje PS4 jutiklinėje plokštėje. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Niekada - Idle Neaktyvus - Always Visada - Touchpad Left Jutiklinis Paviršius Kairėje - Touchpad Right Jutiklinis Paviršius Dešinėje - Touchpad Center Jutiklinis Paviršius Centre - None Nieko - graphicsAdapterGroupBox Grafikos įrenginys:\nDaugiagrafikėse sistemose pasirinkite GPU, kurį emuliatorius naudos iš išskleidžiamojo sąrašo,\n arba pasirinkite "Auto Select", kad jis būtų nustatytas automatiškai. - resolutionLayout Plotis/Aukštis:\nNustato emuliatoriaus lango dydį paleidimo metu, kurį galima keisti žaidimo metu.\nTai skiriasi nuo žaidimo rezoliucijos. - heightDivider Vblank daliklis:\nKadrų dažnis, kuriuo emuliatorius atnaujinamas, dauginamas iš šio skaičiaus. Pakeitus tai gali turėti neigiamą poveikį, pvz., padidinti žaidimo greitį arba sukelti kritinių žaidimo funkcijų sugadinimą, kurios to nesitikėjo! - dumpShadersCheckBox Įjungti šešėlių išmetimą:\nTechninio derinimo tikslais saugo žaidimo šešėlius į aplanką juos renderuojant. - nullGpuCheckBox Įjungti tuščią GPU:\nTechninio derinimo tikslais išjungia žaidimo renderiavimą, tarsi nebūtų grafikos plokštės. - gameFoldersBox Žaidimų aplankai:\nAplankų sąrašas, kurį reikia patikrinti, ar yra įdiegtų žaidimų. - addFolderButton Pridėti:\nPridėti aplanką į sąrašą. - removeFolderButton Pašalinti:\nPašalinti aplanką iš sąrašo. - debugDump Įjungti derinimo išmetimą:\nIšsaugo importo ir eksporto simbolius bei failo antraštės informaciją apie šiuo metu vykdomą PS4 programą į katalogą. - vkValidationCheckBox Įjungti Vulkan patvirtinimo sluoksnius:\nĮjungia sistemą, kuri patvirtina Vulkan renderio būseną ir registruoja informaciją apie jo vidinę būseną. Tai sumažins našumą ir tikriausiai pakeis emuliacijos elgesį. - vkSyncValidationCheckBox Įjungti Vulkan sinchronizacijos patvirtinimą:\nĮjungia sistemą, kuri patvirtina Vulkan renderavimo užduočių laiką. Tai sumažins našumą ir tikriausiai pakeis emuliacijos elgesį. - rdocCheckBox Įjungti RenderDoc derinimą:\nJei įjungta, emuliatorius suteiks suderinamumą su Renderdoc, kad būtų galima užfiksuoti ir analizuoti šiuo metu renderuojamą kadrą. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. Jei pleistras nepasirodo, gali būti, kad jo nėra tam tikram žaidimo serijos numeriui ir versijai. + + + Failed to parse JSON data from HTML. + Nepavyko išanalizuoti JSON duomenų iš HTML. + + + Failed to retrieve HTML page. + Nepavyko gauti HTML puslapio. + + + The game is in version: %1 + Žaidimas yra versijoje: %1 + + + The downloaded patch only works on version: %1 + Parsisiųstas pataisas veikia tik versijoje: %1 + + + You may need to update your game. + Gali tekti atnaujinti savo žaidimą. + + + Incompatibility Notice + Suderinamumo pranešimas + + + 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: + + + Can't apply cheats before the game is started + Negalima taikyti sukčiavimų prieš pradedant žaidimą. + + GameListFrame - Icon Ikona - Name Vardas - Serial Serijinis numeris - Compatibility Compatibility - Region Regionas - Firmware Firmvare - Size Dydis - Version Versija - Path Kelias - Play Time Žaidimo laikas - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Automatinis atnaujinimas - Error Klaida - Network error: Tinklo klaida: - Failed to parse update information. Nepavyko išanalizuoti atnaujinimo informacijos. - No pre-releases found. Išankstinių leidimų nerasta. - Invalid release data. Neteisingi leidimo duomenys. - No download URL found for the specified asset. Nerasta atsisiuntimo URL nurodytam turtui. - Your version is already up to date! Jūsų versija jau atnaujinta! - Update Available Prieinama atnaujinimas - Update Channel Atnaujinimo Kanalas - Current Version Esama versija - Latest Version Paskutinė versija - Do you want to update? Ar norite atnaujinti? - Show Changelog Rodyti pakeitimų sąrašą - Check for Updates at Startup Tikrinti naujinimus paleidus - Update Atnaujinti - No Ne - Hide Changelog Slėpti pakeitimų sąrašą - Changes Pokyčiai - Network error occurred while trying to access the URL Tinklo klaida bandant pasiekti URL - Download Complete Atsisiuntimas baigtas - The update has been downloaded, press OK to install. Atnaujinimas buvo atsisiųstas, paspauskite OK, kad įdiegtumėte. - Failed to save the update file at Nepavyko išsaugoti atnaujinimo failo - Starting Update... Pradedama atnaujinimas... - Failed to create the update script file Nepavyko sukurti atnaujinimo scenarijaus failo + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts index 8fe4cec9b..83dbf7dd8 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 Om shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 er en eksperimentell åpen kildekode-etterligner for PlayStation 4. - This software should not be used to play games you have not legally obtained. Denne programvaren skal ikke brukes til å spille spill du ikke har fått lovlig. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Åpne mappe @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Laster spill-liste, vennligst vent :3 - Cancel Avbryt - Loading... Laster... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Velg mappe - Select which directory you want to install to. Velg hvilken mappe du vil installere til. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Velg mappe - Directory to install games Mappe for å installere spill - Browse Bla gjennom - Error Feil - The value for location to install games is not valid. Stien for å installere spillet er ikke gyldig. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Lag snarvei - Cheats / Patches Juks / Programrettelse - SFO Viewer - SFO Viser + SFO viser - Trophy Viewer - Trofé Viser + Trofé viser - Open Folder... - Åpne Mappen... + Åpne mappen... - Open Game Folder - Åpne Spillmappen + Åpne spillmappen - Open Save Data Folder - Åpne Lagrede Data-mappen + Åpne lagrede datamappen - Open Log Folder - Åpne Loggmappen + Åpne loggmappen - Copy info... Kopier info... - Copy Name - Kopier Navn + Kopier navn - Copy Serial - Kopier Serienummer + Kopier serienummer - Copy All - Kopier Alle + Kopier alle - Delete... Slett... - Delete Game - Slett Spill + Slett spill - Delete Update - Slett Oppdatering + Slett oppdatering - Delete DLC Slett DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Snarvei opprettelse - - Shortcut created successfully!\n %1 - Snarvei opprettet!\n %1 + Shortcut created successfully! + Snarvei opprettet! - Error Feil - - Error creating shortcut!\n %1 - Feil ved opprettelse av snarvei!\n %1 + Error creating shortcut! + Feil ved opprettelse av snarvei! - Install PKG Installer PKG - Game Spill - requiresEnableSeparateUpdateFolder_MSG Denne funksjonen krever 'Aktiver seperat oppdateringsmappe' konfigurasjonsalternativet. Hvis du vil bruke denne funksjonen, må du aktiver den. - This game has no update to delete! Dette spillet har ingen oppdatering å slette! - - + Update Oppdater - This game has no DLC to delete! Dette spillet har ingen DLC å slette! - DLC DLC - Delete %1 Slett %1 - Are you sure you want to delete %1's %2 directory? Er du sikker på at du vil slette %1's %2 directory? @@ -244,1333 +216,1125 @@ MainWindow - Open/Add Elf Folder Åpne/Legg til Elf-mappe - Install Packages (PKG) - Installer Pakker (PKG) + Installer pakker (PKG) - Boot Game - Start Spill + Start spill - Check for Updates Se etter oppdateringer - About shadPS4 Om shadPS4 - Configure... Konfigurer... - Install application from a .pkg file Installer fra en .pkg fil - Recent Games - Nylige Spill + Nylige spill - Exit Avslutt - Exit shadPS4 Avslutt shadPS4 - Exit the application. Avslutt programmet. - Show Game List - Vis Spill-listen + Vis spill-listen - Game List Refresh - Oppdater Spill-listen + Oppdater spill-listen - Tiny Bitteliten - Small Liten - Medium Medium - Large Stor - List View Liste-visning - Grid View Rute-visning - Elf Viewer Elf-visning - Game Install Directory Spillinstallasjons-mappe - Download Cheats/Patches - Last ned Juks /Programrettelse + Last ned juks/programrettelse - Dump Game List - Dump Spill-liste + Dump spill-liste - PKG Viewer - PKG Viser + PKG viser - Search... Søk... - File Fil - View Oversikt - Game List Icons - Spill-liste Ikoner + Spill-liste ikoner - Game List Mode - Spill-liste Modus + Spill-liste modus - Settings Innstillinger - Utils Verktøy - Themes Tema - Help Hjelp - Dark Mørk - Light Lys - Green Grønn - Blue Blå - Violet Lilla - toolBar Verktøylinje - - - PKGViewer - - Open Folder - Åpne Mappe - - - - TrophyViewer - - - Trophy Viewer - Trofé Viser - - - - SettingsDialog - - - Settings - Innstillinger - - - - General - Generell - - - - System - System - - - - Console Language - Konsollspråk - - - - Emulator Language - Etterlignerspråk - - - - Emulator - Etterligner - - - - Enable Fullscreen - Aktiver Fullskjerm - - - - Enable Separate Update Folder - Aktiver Seperat Oppdateringsmappe - - - - Show Splash - Vis Velkomstbilde - - - - Is PS4 Pro - Er PS4 Pro - - - - Enable Discord Rich Presence - Aktiver Discord Rich Presence - - - - Username - Brukernavn - - - - Logger - Logger - - - - Log Type - Log Type - - - - Log Filter - Log Filter - - - - Input - Inndata - - - - Cursor - Musepeker - - - - Hide Cursor - Skjul musepeker - - - - Hide Cursor Idle Timeout - Skjul musepeker ved inaktivitet - - - - Controller - Kontroller - - - - Back Button Behavior - Tilbakeknapp Atferd - - - - Graphics - Grafikk - - - - Graphics Device - Grafikkenhet - - - - Width - Bredde - - - - Height - Høyde - - - - Vblank Divider - Vblank Skillelinje - - - - Advanced - Avansert - - - - Enable Shaders Dumping - Aktiver Skyggelegger Dumping - - - - Enable NULL GPU - Aktiver NULL GPU - - - - Paths - Stier - - - - Game Folders - Spillmapper - - - - Add... - Legg til... - - - - Remove - Fjern - - - - Debug - Feilretting - - - - Enable Debug Dumping - Aktiver Feilretting Dumping - - - - Enable Vulkan Validation Layers - Aktiver Vulkan Valideringslag - - - - Enable Vulkan Synchronization Validation - Aktiver Vulkan Synkroniseringslag - - - - Enable RenderDoc Debugging - Aktiver RenderDoc Feilretting - - - - Update - Oppdatering - - - - Check for Updates at Startup - Se etter oppdateringer ved oppstart - - - - Update Channel - Oppdateringskanal - - - - Check for Updates - Se etter oppdateringer - - - - GUI Settings - GUI-Innstillinger - - - - Disable Trophy Pop-ups - Disable Trophy Pop-ups - - - - Play title music - Spill tittelmusikk - - - - Update Compatibility Database On Startup - Update Compatibility Database On Startup - - - - Game Compatibility - Game Compatibility - - - - Display Compatibility Data - Display Compatibility Data - - - - Update Compatibility Database - Update Compatibility Database - - - - Volume - Volum - - - - MainWindow - - Game List Spill-liste - * Unsupported Vulkan Version * Ustøttet Vulkan-versjon - Download Cheats For All Installed Games Last ned juks for alle installerte spill - Download Patches For All Games - Last ned oppdateringer for alle spill + Last ned programrettelser for alle spill - Download Complete Nedlasting fullført - You have downloaded cheats for all the games you have installed. Du har lastet ned juks for alle spillene du har installert. - Patches Downloaded Successfully! Programrettelser ble lastet ned! - All Patches available for all games have been downloaded. Programrettelser tilgjengelige for alle spill har blitt lastet ned. - Games: Spill: - 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 + PKG-utpakking - Patch detected! Programrettelse oppdaget! - PKG and Game versions match: - PKG- og spillversjoner stemmer overens: + PKG og spillversjoner stemmer overens: - Would you like to overwrite? Ønsker du å overskrive? - PKG Version %1 is older than installed version: PKG-versjon %1 er eldre enn installert versjon: - Game is installed: Spillet er installert: - Would you like to install Patch: Ønsker du å installere programrettelsen: - DLC Installation - DLC-installasjon + DLC installasjon - Would you like to install DLC: %1? Ønsker du å installere DLC: %1? - DLC already installed: DLC allerede installert: - Game already installed Spillet er allerede installert - PKG is a patch, please install the game first! - PKG er en oppdatering, vennligst installer spillet først! + PKG er en programrettelse, vennligst installer spillet først! - PKG ERROR PKG FEIL - Extracting PKG %1/%2 Pakker ut PKG %1/%2 - Extraction Finished Utpakking fullført - Game successfully installed at %1 Spillet ble installert i %1 - File doesn't appear to be a valid PKG file Filen ser ikke ut til å være en gyldig PKG-fil - CheatsPatches + PKGViewer - - Cheats / Patches for - Juks / Programrettelser for + Open Folder + Åpne mappe + + + TrophyViewer - - defaultTextEdit_MSG - Juks/programrettelse er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned juks individuelt ved å velge pakkebrønn og klikke på nedlastingsknappen.\nPå fanen programrettelse kan du laste ned alle programrettelser samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Juksene/Programrettelsene,\nvær vennlig å rapportere problemer til jukse/programrettelse utvikleren.\n\nHar du laget en ny juks? 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 juksefil: - - - - Repository: - Pakkebrønn: - - - - Download Cheats - Last ned juks - - - - Delete File - Slett fil - - - - No files selected. - Ingen filer valgt. - - - - You can delete the cheats you don't want after downloading them. - Du kan slette juksene du ikke ønsker etter å ha lastet dem ned. - - - - Do you want to delete the selected file?\n%1 - Ønsker du å slette den valgte filen?\n%1 - - - - Select Patch File: - Velg programrettelse-filen: - - - - Download Patches - Last ned programrettelse - - - - Save - Lagre - - - - Cheats - Jukser - - - - Patches - Programrettelse - - - - Error - Feil - - - - No patch selected. - Ingen programrettelse valgt. - - - - Unable to open files.json for reading. - Kan ikke åpne files.json for lesing. - - - - No patch file found for the current serial. - Ingen programrettelse-fil funnet for det aktuelle serienummeret. - - - - Unable to open the file for reading. - Kan ikke åpne filen for lesing. - - - - Unable to open the file for writing. - Kan ikke åpne filen for skriving. - - - - Failed to parse XML: - Feil ved tolkning av XML: - - - - Success - Vellykket - - - - Options saved successfully. - Alternativer ble lagret. - - - - Invalid Source - Ugyldig Kilde - - - - The selected source is invalid. - Den valgte kilden er ugyldig. - - - - File Exists - Filen Eksisterer - - - - File already exists. Do you want to replace it? - Filen eksisterer allerede. Ønsker du å erstatte den? - - - - Failed to save file: - Kunne ikke lagre filen: - - - - Failed to download file: - Kunne ikke laste ned filen: - - - - Cheats Not Found - Fant ikke juksene - - - - CheatsNotFound_MSG - Ingen juks funnet for dette spillet i denne versjonen av den valgte pakkebrønnen,prøv en annen pakkebrønn eller en annen versjon av spillet. - - - - Cheats Downloaded Successfully - Juksene ble lastet ned - - - - CheatsDownloadedSuccessfully_MSG - Du har lastet ned jukser for denne versjonen av spillet fra den valgte pakkebrønnen. Du kan prøve å laste ned fra en annen pakkebrønn, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. - - - - Failed to save: - Kunne ikke lagre: - - - - Failed to download: - Kunne ikke laste ned: - - - - Download Complete - Nedlasting fullført - - - - DownloadComplete_MSG - Programrettelser ble lastet ned! Alle programrettelsene tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med jukser. Hvis programrettelsen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. - - - - Failed to parse JSON data from HTML. - Kunne ikke analysere JSON-data fra HTML. - - - - Failed to retrieve HTML page. - Kunne ikke hente HTML-side. - - - - The game is in version: %1 - Spillet er i versjon: %1 - - - - The downloaded patch only works on version: %1 - Den nedlastede programrettelsen fungerer bare på versjon: %1 - - - - You may need to update your game. - Du må kanskje oppdatere spillet ditt. - - - - Incompatibility Notice - Inkompatibilitets-varsel - - - - Failed to open file: - Kunne ikke åpne filen: - - - - XML ERROR: - XML FEIL: - - - - Failed to open files.json for writing - Kunne ikke åpne files.json for skriving - - - - Author: - Forfatter: - - - - Directory does not exist: - Mappen eksisterer ikke: - - - - Failed to open files.json for reading. - Kunne ikke åpne files.json for lesing. - - - - Name: - Navn: - - - - Can't apply cheats before the game is started - Kan ikke bruke juksene før spillet er startet. + Trophy Viewer + Trofé viser SettingsDialog - + Settings + Innstillinger + + + General + Generell + + + System + System + + + Console Language + Konsollspråk + + + Emulator Language + Etterlignerspråk + + + Emulator + Etterligner + + + Enable Fullscreen + Aktiver fullskjerm + + + Enable Separate Update Folder + Aktiver seperat oppdateringsmappe + + + Show Splash + Vis velkomstbilde + + + Is PS4 Pro + Er PS4 Pro + + + Enable Discord Rich Presence + Aktiver Discord Rich Presence + + + Username + Brukernavn + + + Trophy Key + Trophy Key + + + Trophy + Trophy + + + Logger + Logger + + + Log Type + Logg type + + + Log Filter + Logg filter + + + Open Log Location + Åpne loggplassering + + + Input + Inndata + + + Cursor + Musepeker + + + Hide Cursor + Skjul musepeker + + + Hide Cursor Idle Timeout + Skjul musepeker ved inaktivitet + + + s + s + + + Controller + Kontroller + + + Back Button Behavior + Tilbakeknapp atferd + + + Graphics + Grafikk + + + Graphics Device + Grafikkenhet + + + Width + Bredde + + + Height + Høyde + + + Vblank Divider + Vblank skillelinje + + + Advanced + Avansert + + + Enable Shaders Dumping + Aktiver dumping av skyggelegger + + + Enable NULL GPU + Aktiver NULL GPU + + + Paths + Stier + + + Game Folders + Spillmapper + + + Add... + Legg til... + + + Remove + Fjern + + + Debug + Feilretting + + + Enable Debug Dumping + Aktiver dumping av feilretting + + + Enable Vulkan Validation Layers + Aktiver Vulkan valideringslag + + + Enable Vulkan Synchronization Validation + Aktiver Vulkan synkroniseringslag + + + Enable RenderDoc Debugging + Aktiver RenderDoc feilretting + + + Update + Oppdatering + + + Check for Updates at Startup + Se etter oppdateringer ved oppstart + + + Update Channel + Oppdateringskanal + + + Check for Updates + Se etter oppdateringer + + + GUI Settings + GUI-innstillinger + + + Disable Trophy Pop-ups + Deaktiver trofé hurtigmeny + + + Play title music + Spill tittelmusikk + + + Update Compatibility Database On Startup + Oppdater kompatibilitets-database ved oppstart + + + Game Compatibility + Spill kompatibilitet + + + Display Compatibility Data + Vis kompatibilitets-data + + + Update Compatibility Database + Oppdater kompatibilitets-database + + + Volume + Volum + + + Audio Backend + Audio Backend + + Save Lagre - Apply Bruk - Restore Defaults Gjenopprett standardinnstillinger - Close Lukk - Point your mouse at an option to display its description. Pek musen over et alternativ for å vise beskrivelsen. - consoleLanguageGroupBox Konsollspråk:\nAngir språket som PS4-spillet bruker.\nDet anbefales å sette dette til et språk som spillet støtter, noe som kan variere avhengig av region. - emulatorLanguageGroupBox Etterlignerspråket:\nAngir språket for etterlignerens brukergrensesnitt. - fullscreenCheckBox Aktiver fullskjerm:\nSetter spillvinduet automatisk i fullskjermmodus.\nDette kan slås av ved å trykke på F11-tasten. - separateUpdatesCheckBox Aktiver separat oppdateringsmappe:\nAktiverer installering av spill i en egen mappe for enkel administrasjon. - showSplashCheckBox - Vis Velkomstbilde:\nViser spillets velkomstbilde (et spesialbilde) når spillet starter. + Vis velkomstbilde:\nViser spillets velkomstbilde (et spesialbilde) når spillet starter. - ps4proCheckBox Er PS4 Pro:\nFår etterligneren til å fungere som en PS4 PRO, noe som kan aktivere spesielle funksjoner i spill som støtter dette. - discordRPCCheckbox Aktiver Discord Rich Presence:\nViser etterlignerikonet og relevant informasjon på Discord-profilen din. - userName Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox - Logtype:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter for etterligneren. + Logg type:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter for etterligneren. - logFilter - Loggfilter:\nFiltrerer loggen for å kun skrive ut spesifikk informasjon.\nEksempler: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivåer: Trace, Debug, Info, Warning, Error, Critical - i denne rekkefølgen, et spesifikt nivå demper alle tidligere nivåer i listen og logger alle nivåer etter det. + Logg filter:\nFiltrerer loggen for å kun skrive ut spesifikk informasjon.\nEksempler: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivåer: Trace, Debug, Info, Warning, Error, Critical - i denne rekkefølgen, et spesifikt nivå demper alle tidligere nivåer i listen og logger alle nivåer etter det. - updaterGroupBox Oppdatering:\nRelease: Offisielle versjoner utgitt hver måned som kan være veldig utdaterte, men er mer pålitelige og testet.\nNightly: Utviklingsversjoner som har alle de nyeste funksjonene og feilrettingene, men som kan inneholde feil og er mindre stabile. - GUIgroupBox Spille tittelmusikk:\nHvis et spill støtter det, så aktiveres det spesiell musikk når du velger spillet i menyen. - disableTrophycheckBox - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Deaktiver trofé hurtigmeny:\nDeaktiver trofévarsler i spillet. Trofé-fremgang kan fortsatt ved help av troféviseren (høyreklikk på spillet i hovedvinduet). - hideCursorGroupBox Skjul musepeker:\nVelg når musepekeren skal forsvinne:\nAldri: Du vil alltid se musepekeren.\nInaktiv: Sett en tid for at den skal forsvinne etter å ha vært inaktiv.\nAlltid: du vil aldri se musepekeren. - idleTimeoutGroupBox Sett en tid for når musepekeren forsvinner etter å ha vært inaktiv. - backButtonBehaviorGroupBox Atferd for tilbaketasten:\nSetter tilbaketasten på kontrolleren til å imitere et trykk på den angitte posisjonen på PS4s berøringsplate. - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Vis kompatibilitets-data:\nViser informasjon om spillkompatibilitet i tabellvisning. Aktiver "Oppdater kompatibilitets-data ved oppstart" for oppdatert informasjon. - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Oppdater kompatibilitets-data ved oppstart:\nOppdaterer kompatibilitets-databasen automatisk når shadPS4 starter. - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. + Oppdater kompatibilitets-database:\nOppdater kompatibilitets-databasen nå. - Never Aldri - Idle Inaktiv - Always Alltid - Touchpad Left Berøringsplate Venstre - Touchpad Right Berøringsplate Høyre - Touchpad Center Berøringsplate Midt - None Ingen - graphicsAdapterGroupBox - Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en etterligneren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å bestemme den automatisk. + Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en etterligneren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å velge automatisk. - resolutionLayout Bredde/Høyde:\nAngir størrelsen på etterlignerkvinduet ved oppstart, som kan endres under spillingen.\nDette er forskjellig fra oppløsningen i spillet. - heightDivider - Vblank Skillelinje:\nBildehastigheten som etterligneren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten av spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! + Vblank skillelinje:\nBildehastigheten som etterligneren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten av spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! - dumpShadersCheckBox - Aktiver skyggelegger-dumping:\nFor teknisk feilsøking lagrer skyggeleggene fra spillet i en mappe mens de gjengis. + Aktiver dumping av skyggelegger:\nFor teknisk feilsøking lagrer skyggeleggerne fra spillet i en mappe mens de gjengis. - nullGpuCheckBox Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillets-gjengivelse som om det ikke var noe grafikkort. - gameFoldersBox Spillmapper:\nListen over mapper som brukes for å se etter installerte spill. - addFolderButton Legg til:\nLegg til en mappe til listen. - removeFolderButton Fjern:\nFjern en mappe fra listen. - debugDump Aktiver dumping av feilsøking:\nLagrer import- og eksport-symbolene og filoverskriftsinformasjonen til det nåværende kjørende PS4-programmet i en katalog. - vkValidationCheckBox Aktiver Vulkan valideringslag:\nAktiverer et system som validerer tilstanden til Vulkan-gjengiveren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre etterlignerens atferd. - vkSyncValidationCheckBox Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer frekvens tiden av Vulkan-gjengivelsensoppgaver. Dette vil redusere ytelsen og sannsynligvis endre etterlignerens atferd. - rdocCheckBox Aktiver RenderDoc feilsøking:\nHvis aktivert, vil etterligneren gi kompatibilitet med Renderdoc for å tillate opptak og analyse av det nåværende gjengitte bildet. + + CheatsPatches + + Cheats / Patches for + Juks / Programrettelser for + + + defaultTextEdit_MSG + Juks/programrettelse er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned juks individuelt ved å velge pakkebrønn og klikke på nedlastingsknappen.\nPå fanen programrettelse kan du laste ned alle programrettelser samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Juks/Programrettelse,\nvær vennlig å rapportere problemer til juks/programrettelse utvikleren.\n\nHar du laget en ny juks? Besøk:\nhttps://github.com/shadps4-emu/ps4_cheats + + + No Image Available + Ingen bilde tilgjengelig + + + Serial: + Serienummer: + + + Version: + Versjon: + + + Size: + Størrelse: + + + Select Cheat File: + Velg juksefil: + + + Repository: + Pakkebrønn: + + + Download Cheats + Last ned juks + + + Delete File + Slett fil + + + No files selected. + Ingen filer valgt. + + + You can delete the cheats you don't want after downloading them. + Du kan slette juks du ikke ønsker etter å ha lastet dem ned. + + + Do you want to delete the selected file?\n%1 + Ønsker du å slette den valgte filen?\n%1 + + + Select Patch File: + Velg programrettelse-filen: + + + Download Patches + Last ned programrettelser + + + Save + Lagre + + + Cheats + Juks + + + Patches + Programrettelse + + + Error + Feil + + + No patch selected. + Ingen programrettelse valgt. + + + Unable to open files.json for reading. + Kan ikke åpne files.json for lesing. + + + No patch file found for the current serial. + Ingen programrettelse-fil funnet for det aktuelle serienummeret. + + + Unable to open the file for reading. + Kan ikke åpne filen for lesing. + + + Unable to open the file for writing. + Kan ikke åpne filen for skriving. + + + Failed to parse XML: + Feil ved tolkning av XML: + + + Success + Vellykket + + + Options saved successfully. + Alternativer ble lagret. + + + Invalid Source + Ugyldig kilde + + + The selected source is invalid. + Den valgte kilden er ugyldig. + + + File Exists + Filen eksisterer + + + File already exists. Do you want to replace it? + Filen eksisterer allerede. Ønsker du å erstatte den? + + + Failed to save file: + Kunne ikke lagre filen: + + + Failed to download file: + Kunne ikke laste ned filen: + + + Cheats Not Found + Fant ikke juks + + + CheatsNotFound_MSG + Ingen juks funnet for dette spillet i denne versjonen av den valgte pakkebrønnen,prøv en annen pakkebrønn eller en annen versjon av spillet. + + + Cheats Downloaded Successfully + Juks ble lastet ned + + + CheatsDownloadedSuccessfully_MSG + Du har lastet ned juks for denne versjonen av spillet fra den valgte pakkebrønnen. Du kan prøve å laste ned fra en annen pakkebrønn, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. + + + Failed to save: + Kunne ikke lagre: + + + Failed to download: + Kunne ikke laste ned: + + + Download Complete + Nedlasting fullført + + + DownloadComplete_MSG + Programrettelser ble lastet ned! Alle programrettelsene tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med juks. Hvis programrettelsen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. + + + Failed to parse JSON data from HTML. + Kunne ikke analysere JSON-data fra HTML. + + + Failed to retrieve HTML page. + Kunne ikke hente HTML-side. + + + The game is in version: %1 + Spillet er i versjon: %1 + + + The downloaded patch only works on version: %1 + Den nedlastede programrettelsen fungerer bare på versjon: %1 + + + You may need to update your game. + Du må kanskje oppdatere spillet ditt. + + + Incompatibility Notice + Inkompatibilitets-varsel + + + Failed to open file: + Kunne ikke åpne filen: + + + XML ERROR: + XML FEIL: + + + Failed to open files.json for writing + Kunne ikke åpne files.json for skriving + + + Author: + Forfatter: + + + Directory does not exist: + Mappen eksisterer ikke: + + + Failed to open files.json for reading. + Kunne ikke åpne files.json for lesing. + + + Name: + Navn: + + + Can't apply cheats before the game is started + Kan ikke bruke juks før spillet er startet. + + GameListFrame - Icon Ikon - Name Navn - Serial Serienummer - Compatibility - Compatibility + Kompatibilitet - Region Region - Firmware Fastvare - Size Størrelse - Version Versjon - Path Sti - Play Time Spilletid - Never Played - Never Played + Aldri spilt + + + h + h + + + m + m + + + s + s - Compatibility is untested - Compatibility is untested + kompatibilitet er utestet - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + Spillet initialiseres ikke riktig / krasjer etterligneren - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + Spillet starter, men viser bare en tom skjerm - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + Spillet viser et bilde, men går ikke forbi menyen - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + Spillet har spillbrytende feil eller uspillbar ytelse - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + Spillet kan fullføres med spillbar ytelse og ingen store feil CheckUpdate - Auto Updater - Automatisk oppdaterering + Automatisk oppdatering - Error Feil - Network error: Nettverksfeil: - Failed to parse update information. - Kunne ikke analysere oppdateringsinformasjonen. + Kunne ikke analysere oppdaterings-informasjonen. - No pre-releases found. Fant ingen forhåndsutgivelser. - Invalid release data. Ugyldige utgivelsesdata. - No download URL found for the specified asset. Ingen nedlastings-URL funnet for den spesifiserte ressursen. - Your version is already up to date! Din versjon er allerede oppdatert! - Update Available Oppdatering tilgjengelig - Update Channel Oppdateringskanal - Current Version Gjeldende versjon - Latest Version Nyeste versjon - Do you want to update? Vil du oppdatere? - Show Changelog Vis endringslogg - Check for Updates at Startup Se etter oppdateringer ved oppstart - Update Oppdater - No Nei - Hide Changelog Skjul endringslogg - Changes Endringer - Network error occurred while trying to access the URL - Nettverksfeil oppstod mens du prøvde å få tilgang til URL + Nettverksfeil oppstod mens vi prøvde å få tilgang til URL - Download Complete Nedlasting fullført - The update has been downloaded, press OK to install. Oppdateringen har blitt lastet ned, trykk OK for å installere. - Failed to save the update file at Kunne ikke lagre oppdateringsfilen på - Starting Update... Starter oppdatering... - Failed to create the update script file Kunne ikke opprette oppdateringsskriptfilen + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts index 4dd8813b0..3142a17e5 100644 --- a/src/qt_gui/translations/nl.ts +++ b/src/qt_gui/translations/nl.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Cheats / Patches - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Map openen... - Open Game Folder Open Spelmap - Open Save Data Folder Open Map voor Opslagdata - Open Log Folder Open Logmap - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Controleren op updates - 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 - Download Cheats/Patches Download Cheats/Patches - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Help - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Lijst met spellen + + + * 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! + Patch gedetecteerd! + + + PKG and Game versions match: + PKG- en gameversies komen overeen: + + + Would you like to overwrite? + Wilt u overschrijven? + + + PKG Version %1 is older than installed version: + PKG-versie %1 is ouder dan de geïnstalleerde versie: + + + Game is installed: + Game is geïnstalleerd: + + + Would you like to install Patch: + Wilt u de patch installeren: + + + DLC Installation + DLC-installatie + + + 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 + + + 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Discord Rich Presence inschakelen - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Loglocatie openen + + Input Invoer - Cursor Cursor - Hide Cursor Cursor verbergen - Hide Cursor Idle Timeout Inactiviteit timeout voor het verbergen van de cursor - + s + s + + Controller Controller - Back Button Behavior Achterknop gedrag - 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 - Paths Pad - Game Folders Spelmappen - Add... Toevoegen... - Remove Verwijderen - 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 - Update Bijwerken - Check for Updates at Startup Bij opstart op updates controleren - Update Channel Updatekanaal - Check for Updates Controleren op updates - GUI Settings GUI-Instellingen - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Titelmuziek afspelen - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Volume - - - MainWindow - - Game List - Lijst met spellen + Audio Backend + Audio Backend - - * 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! - Patch gedetecteerd! - - - - PKG and Game versions match: - PKG- en gameversies komen overeen: - - - - Would you like to overwrite? - Wilt u overschrijven? - - - - PKG Version %1 is older than installed version: - PKG-versie %1 is ouder dan de geïnstalleerde versie: - - - - Game is installed: - Game is geïnstalleerd: - - - - Would you like to install Patch: - Wilt u de patch installeren: - - - - DLC Installation - DLC-installatie - - - - 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 - - - - 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 for - Cheats / Patches for - - - - 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. Als de patch niet verschijnt, kan het zijn dat deze niet bestaat voor het specifieke serienummer en de versie van het spel. - - - - Failed to parse JSON data from HTML. - Kan JSON-gegevens uit HTML niet parseren. - - - - Failed to retrieve HTML page. - Kan HTML-pagina niet ophalen. - - - - The game is in version: %1 - Het spel is in versie: %1 - - - - The downloaded patch only works on version: %1 - De gedownloade patch werkt alleen op versie: %1 - - - - You may need to update your game. - Misschien moet je je spel bijwerken. - - - - Incompatibility Notice - Incompatibiliteitsmelding - - - - 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: - - - - Can't apply cheats before the game is started - Je kunt geen cheats toepassen voordat het spel is gestart. - - - - SettingsDialog - - - Save - Opslaan - - - Apply Toepassen - Restore Defaults Standaardinstellingen herstellen - Close Sluiten - Point your mouse at an option to display its description. Wijzig de muisaanwijzer naar een optie om de beschrijving weer te geven. - consoleLanguageGroupBox Console Taal:\nStelt de taal in die het PS4-spel gebruikt.\nHet wordt aanbevolen om dit in te stellen op een taal die het spel ondersteunt, wat kan variëren per regio. - emulatorLanguageGroupBox Emulator Taal:\nStelt de taal van de gebruikersinterface van de emulator in. - fullscreenCheckBox Volledig scherm inschakelen:\nZet het gamevenster automatisch in de volledig scherm modus.\nDit kan worden omgeschakeld door op de F11-toets te drukken. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Opstartscherm weergeven:\nToont het opstartscherm van het spel (een speciale afbeelding) tijdens het starten van het spel. - ps4proCheckBox Is PS4 Pro:\nLaat de emulator zich gedragen als een PS4 PRO, wat speciale functies kan inschakelen in games die dit ondersteunen. - discordRPCCheckbox Discord Rich Presence inschakelen:\nToont het emulatoricoon en relevante informatie op je Discord-profiel. - userName Gebruikersnaam:\nStelt de gebruikersnaam van het PS4-account in, die door sommige games kan worden weergegeven. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Logtype:\nStelt in of de uitvoer van het logvenster moet worden gesynchroniseerd voor prestaties. Kan nadelige effecten hebben op emulatie. - logFilter Logfilter:\nFiltert het logboek om alleen specifieke informatie af te drukken.\nVoorbeelden: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Niveaus: Trace, Debug, Info, Waarschuwing, Fout, Kritiek - in deze volgorde, een specifiek niveau dempt alle voorgaande niveaus in de lijst en logt alle niveaus daarna. - updaterGroupBox Updateren:\nRelease: Officiële versies die elke maand worden uitgebracht, die zeer verouderd kunnen zijn, maar betrouwbaar en getest zijn.\nNightly: Ontwikkelingsversies die alle nieuwste functies en bugfixes bevatten, maar mogelijk bugs bevatten en minder stabiel zijn. - GUIgroupBox Speel titelsong:\nAls een game dit ondersteunt, wordt speciale muziek afgespeeld wanneer je het spel in de GUI selecteert. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Verberg cursor:\nKies wanneer de cursor verdwijnt:\nNooit: Je ziet altijd de muis.\nInactief: Stel een tijd in waarna deze verdwijnt na inactiviteit.\nAltijd: je ziet de muis nooit. - idleTimeoutGroupBox Stel een tijd in voor wanneer de muis verdwijnt na inactiviteit. - backButtonBehaviorGroupBox Gedrag van de terugknop:\nStelt de terugknop van de controller in om een aanraking op de opgegeven positie op de PS4-touchpad na te bootsen. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Nooit - Idle Inactief - Always Altijd - Touchpad Left Touchpad Links - Touchpad Right Touchpad Rechts - Touchpad Center Touchpad Midden - None Geen - graphicsAdapterGroupBox Grafische adapter:\nIn systemen met meerdere GPU's, kies de GPU die de emulator uit de vervolgkeuzelijst moet gebruiken,\nof kies "Auto Select" om dit automatisch in te stellen. - resolutionLayout Breedte/Hoogte:\nStelt de grootte van het emulatorvenster bij het opstarten in, wat tijdens het spelen kan worden gewijzigd.\nDit is anders dan de resolutie in de game. - heightDivider Vblank deler:\nDe frame-rate waartegen de emulator wordt vernieuwd, vermenigvuldigd met dit getal. Dit veranderen kan nadelige effecten hebben, zoals het versnellen van het spel of het verpesten van kritieke gamefunctionaliteiten die niet verwachtten dat dit zou veranderen! - dumpShadersCheckBox Shaderdump inschakelen:\nVoor technische foutopsporing slaat het de shaders van de game op in een map terwijl ze worden gerenderd. - nullGpuCheckBox Null GPU inschakelen:\nVoor technische foutopsporing schakelt de game-rendering uit alsof er geen grafische kaart is. - gameFoldersBox Spelmap:\nDe lijst met mappen om te controleren op geïnstalleerde spellen. - addFolderButton Toevoegen:\nVoeg een map toe aan de lijst. - removeFolderButton Verwijderen:\nVerwijder een map uit de lijst. - debugDump Foutopsporing dump inschakelen:\nSlaat de import- en export-symbolen en de bestandsheaderinformatie van de momenteel draaiende PS4-toepassing op in een map. - vkValidationCheckBox Vulkan validatielaag inschakelen:\nSchakelt een systeem in dat de status van de Vulkan-renderer valideert en informatie over de interne status ervan logt. Dit zal de prestaties verlagen en waarschijnlijk het emulatiegedrag veranderen. - vkSyncValidationCheckBox Vulkan synchronisatievalidatie inschakelen:\nSchakelt een systeem in dat de timing van Vulkan-renderingtaken valideert. Dit zal de prestaties verlagen en waarschijnlijk het emulatiegedrag veranderen. - rdocCheckBox RenderDoc foutopsporing inschakelen:\nAls ingeschakeld, biedt de emulator compatibiliteit met Renderdoc om de momenteel gerenderde frame vast te leggen en te analyseren. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. Als de patch niet verschijnt, kan het zijn dat deze niet bestaat voor het specifieke serienummer en de versie van het spel. + + + Failed to parse JSON data from HTML. + Kan JSON-gegevens uit HTML niet parseren. + + + Failed to retrieve HTML page. + Kan HTML-pagina niet ophalen. + + + The game is in version: %1 + Het spel is in versie: %1 + + + The downloaded patch only works on version: %1 + De gedownloade patch werkt alleen op versie: %1 + + + You may need to update your game. + Misschien moet je je spel bijwerken. + + + Incompatibility Notice + Incompatibiliteitsmelding + + + 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: + + + Can't apply cheats before the game is started + Je kunt geen cheats toepassen voordat het spel is gestart. + + GameListFrame - Icon Pictogram - Name Naam - Serial Serienummer - Compatibility Compatibility - Region Regio - Firmware Firmware - Size Grootte - Version Versie - Path Pad - Play Time Speeltijd - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Automatische updater - Error Fout - Network error: Netwerkfout: - Failed to parse update information. Kon update-informatie niet parseren. - No pre-releases found. Geen pre-releases gevonden. - Invalid release data. Ongeldige releasegegevens. - No download URL found for the specified asset. Geen download-URL gevonden voor het opgegeven bestand. - Your version is already up to date! Uw versie is al up-to-date! - Update Available Update beschikbaar - Update Channel Updatekanaal - Current Version Huidige versie - Latest Version Laatste versie - Do you want to update? Wilt u updaten? - Show Changelog Toon changelog - Check for Updates at Startup Bij opstart op updates controleren - Update Bijwerken - No Nee - Hide Changelog Verberg changelog - Changes Wijzigingen - Network error occurred while trying to access the URL Netwerkfout opgetreden tijdens toegang tot de URL - Download Complete Download compleet - The update has been downloaded, press OK to install. De update is gedownload, druk op OK om te installeren. - Failed to save the update file at Kon het updatebestand niet opslaan op - Starting Update... Starten van update... - Failed to create the update script file Kon het update-scriptbestand niet maken + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 012f92164..378673a30 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Otwórz folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Ładowanie listy gier, proszę poczekaj :3 - Cancel Anuluj - Loading... Ładowanie... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Wybierz katalog - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Utwórz skrót - Cheats / Patches Kody / poprawki - SFO Viewer Menedżer plików SFO - Trophy Viewer Menedżer trofeów - Open Folder... Otwórz Folder... - Open Game Folder Otwórz Katalog Gry - Open Save Data Folder Otwórz Folder Danych Zapisów - Open Log Folder Otwórz Folder Dziennika - Copy info... Kopiuj informacje... - Copy Name Kopiuj nazwę - Copy Serial Kopiuj numer seryjny - Copy All Kopiuj wszystko - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Tworzenie skrótu - - Shortcut created successfully!\n %1 - Utworzenie skrótu zakończone pomyślnie!\n %1 + Shortcut created successfully! + Utworzenie skrótu zakończone pomyślnie! - Error Błąd - - Error creating shortcut!\n %1 - Utworzenie skrótu zakończone niepowodzeniem!\n %1 + Error creating shortcut! + Utworzenie skrótu zakończone niepowodzeniem! - Install PKG Zainstaluj PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Otwórz/Dodaj folder Elf - Install Packages (PKG) Zainstaluj paczkę (PKG) - Boot Game Uruchom grę - Check for Updates Sprawdź aktualizacje - 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 zainstalowanych gier - Download Cheats/Patches Pobierz kody / poprawki - 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 - Help Pomoc - Dark Ciemny - Light Jasny - Green Zielony - Blue Niebieski - Violet Fioletowy - toolBar Pasek narzędzi + + Game List + Lista gier + + + * 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 + Wypakowywanie PKG + + + Patch detected! + Wykryto łatkę! + + + PKG and Game versions match: + Wersje PKG i gry są zgodne: + + + Would you like to overwrite? + Czy chcesz nadpisać? + + + PKG Version %1 is older than installed version: + Wersja PKG %1 jest starsza niż zainstalowana wersja: + + + Game is installed: + Gra jest zainstalowana: + + + Would you like to install Patch: + Czy chcesz zainstalować łatkę: + + + DLC Installation + Instalacja DLC + + + Would you like to install DLC: %1? + Czy chcesz zainstalować DLC: %1? + + + DLC already installed: + DLC już zainstalowane: + + + Game already installed + Gra już zainstalowana + + + 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 + Wypakowywanie PKG %1/%2 + + + Extraction Finished + Wypakowywanie zakończone + + + 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 + PKGViewer - Open Folder Otwórz folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Menedżer trofeów @@ -458,989 +509,704 @@ 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 - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Pokaż ekran powitania - Is PS4 Pro Emulacja PS4 Pro - Enable Discord Rich Presence Włącz Discord Rich Presence - Username Nazwa użytkownika - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Dziennik zdarzeń - Log Type Typ dziennika - Log Filter Filtrowanie dziennika - + Open Log Location + Otwórz lokalizację dziennika + + Input Wejście - Cursor Kursor - Hide Cursor Ukryj kursor - Hide Cursor Idle Timeout Czas oczekiwania na ukrycie kursora przy bezczynności - + s + s + + Controller Kontroler - Back Button Behavior Zachowanie przycisku wstecz - Graphics Grafika - Graphics Device Karta graficzna - Width Szerokość - Height Wysokość - Vblank Divider Dzielnik przerwy pionowej (Vblank) - Advanced Zaawansowane - Enable Shaders Dumping Włącz zgrywanie cieni - Enable NULL GPU Wyłącz kartę graficzną - Paths Ścieżki - Game Folders Foldery gier - Add... Dodaj... - Remove Usuń - 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 - Update Aktualizacja - Check for Updates at Startup Sprawdź aktualizacje przy starcie - Update Channel Kanał Aktualizacji - Check for Updates Sprawdź aktualizacje - GUI Settings Ustawienia Interfejsu - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Odtwórz muzykę tytułową - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Głośność - - - MainWindow - - Game List - Lista gier + Audio Backend + Audio Backend - - * 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 - Wypakowywanie PKG - - - - Patch detected! - Wykryto łatkę! - - - - PKG and Game versions match: - Wersje PKG i gry są zgodne: - - - - Would you like to overwrite? - Czy chcesz nadpisać? - - - - PKG Version %1 is older than installed version: - Wersja PKG %1 jest starsza niż zainstalowana wersja: - - - - Game is installed: - Gra jest zainstalowana: - - - - Would you like to install Patch: - Czy chcesz zainstalować łatkę: - - - - DLC Installation - Instalacja DLC - - - - Would you like to install DLC: %1? - Czy chcesz zainstalować DLC: %1? - - - - DLC already installed: - DLC już zainstalowane: - - - - Game already installed - Gra już zainstalowana - - - - 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 - Wypakowywanie PKG %1/%2 - - - - Extraction Finished - Wypakowywanie zakończone - - - - 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 for - Cheats / Patches for - - - - 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ę przeanalizować 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. Jeśli poprawka się nie pojawia, możliwe, że nie istnieje dla konkretnego numeru seryjnego i wersji gry. - - - - Failed to parse JSON data from HTML. - Nie udało się przeanalizować danych JSON z HTML. - - - - Failed to retrieve HTML page. - Nie udało się pobrać strony HTML. - - - - The game is in version: %1 - Gra jest w wersji: %1 - - - - The downloaded patch only works on version: %1 - Pobrana łatka działa tylko w wersji: %1 - - - - You may need to update your game. - Możesz potrzebować zaktualizować swoją grę. - - - - Incompatibility Notice - Powiadomienie o niezgodności - - - - 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ę przeanlizować JSON: - - - - Can't apply cheats before the game is started - Nie można zastosować kodów przed uruchomieniem gry. - - - - SettingsDialog - - - Save - Zapisz - - - Apply Zastosuj - Restore Defaults Przywróć ustawienia domyślne - Close Zamknij - Point your mouse at an option to display its description. Najedź kursorem na opcję, aby wyświetlić jej opis. - consoleLanguageGroupBox Język konsoli:\nUstala język, który używa gra PS4.\nZaleca się ustawienie tego na język, który obsługuje gra, co może się różnić w zależności od regionu. - emulatorLanguageGroupBox Język emulatora:\nUstala język interfejsu użytkownika emulatora. - fullscreenCheckBox Włącz tryb pełnoekranowy:\nAutomatycznie przełącza okno gry w tryb pełnoekranowy.\nMożna to wyłączyć naciskając klawisz F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Wyświetl ekran powitalny:\nPodczas uruchamiania gry wyświetla ekran powitalny (specjalny obraz). - ps4proCheckBox Czy PS4 Pro:\nSprawia, że emulator działa jak PS4 PRO, co może aktywować specjalne funkcje w grach, które to obsługują. - discordRPCCheckbox Włącz Discord Rich Presence:\nWyświetla ikonę emuladora i odpowiednie informacje na twoim profilu Discord. - userName Nazwa użytkownika:\nUstala nazwę użytkownika konta PS4, która może być wyświetlana w niektórych grach. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Typ logu:\nUstala, czy synchronizować wyjście okna dziennika dla wydajności. Może to mieć negatywny wpływ na emulację. - logFilter Filtr logu:\nFiltruje dziennik, aby drukować tylko określone informacje.\nPrzykłady: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Poziomy: Trace, Debug, Info, Warning, Error, Critical - w tej kolejności, konkretny poziom wycisza wszystkie wcześniejsze poziomy w liście i rejestruje wszystkie poziomy później. - updaterGroupBox Aktualizator:\nRelease: Oficjalne wersje wydawane co miesiąc, które mogą być bardzo przestarzałe, ale są niezawodne i przetestowane.\nNightly: Wersje rozwojowe, które zawierają wszystkie najnowsze funkcje i poprawki błędów, ale mogą mieć błędy i być mniej stabilne. - GUIgroupBox Odtwórz muzykę tytułową:\nJeśli gra to obsługuje, aktywuje odtwarzanie specjalnej muzyki podczas wybierania gry w GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Ukryj kursor:\nWybierz, kiedy kursor zniknie:\nNigdy: Zawsze będziesz widział myszkę.\nNieaktywny: Ustaw czas, po którym zniknie po bezczynności.\nZawsze: nigdy nie zobaczysz myszki. - idleTimeoutGroupBox Ustaw czas, po którym mysz zniknie po bezczynności. - backButtonBehaviorGroupBox Zachowanie przycisku Wstecz:\nUstawia przycisk Wstecz kontrolera tak, aby emulował dotknięcie określonego miejsca na panelu dotykowym PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Nigdy - Idle Bezczynny - Always Zawsze - Touchpad Left Touchpad Lewy - Touchpad Right Touchpad Prawy - Touchpad Center Touchpad Środkowy - None Brak - graphicsAdapterGroupBox Urządzenie graficzne:\nW systemach z wieloma GPU, wybierz GPU, który emulator ma używać z rozwijanego menu,\n lub wybierz "Auto Select", aby ustawić go automatycznie. - resolutionLayout Szerokość/Wysokość:\nUstala rozmiar okna emulatora podczas uruchamiania, który może być zmieniany w trakcie gry.\nTo różni się od rozdzielczości w grze. - heightDivider Dzielnik Vblank:\nWskaźnik klatek, z jakim emulator jest odświeżany, pomnożony przez tę liczbę. Zmiana tego może mieć negatywne skutki, takie jak przyspieszenie gry lub zniszczenie krytycznej funkcjonalności gry, która nie spodziewa się, że to zostanie zmienione! - dumpShadersCheckBox Włącz zrzucanie shaderów:\nDla technicznego debugowania zapisuje shadery z gry w folderze podczas renderowania. - nullGpuCheckBox Włącz Null GPU:\nDla technicznego debugowania dezaktywuje renderowanie gry tak, jakby nie było karty graficznej. - gameFoldersBox Foldery gier:\nLista folderów do sprawdzenia zainstalowanych gier. - addFolderButton Dodaj:\nDodaj folder do listy. - removeFolderButton Usuń:\nUsuń folder z listy. - debugDump Włącz zrzut debugowania:\nZapisuje symbole importu i eksportu oraz informacje nagłówkowe pliku dla aktualnie działającej aplikacji PS4 w katalogu. - vkValidationCheckBox Włącz warstwę walidacji Vulkan:\nWłącza system, który waliduje stan renderera Vulkan i loguje informacje o jego wewnętrznym stanie. Zmniejszy to wydajność i prawdopodobnie zmieni zachowanie emulacji. - vkSyncValidationCheckBox Włącz walidację synchronizacji Vulkan:\nWłącza system, który waliduje timing zadań renderowania Vulkan. Zmniejszy to wydajność i prawdopodobnie zmieni zachowanie emulacji. - rdocCheckBox Włącz debugowanie RenderDoc:\nJeśli włączone, emulator zapewnia kompatybilność z Renderdoc, aby umożliwić nagrywanie i analizowanie aktualnie renderowanej klatki. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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ę przeanalizować 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. Jeśli poprawka się nie pojawia, możliwe, że nie istnieje dla konkretnego numeru seryjnego i wersji gry. + + + Failed to parse JSON data from HTML. + Nie udało się przeanalizować danych JSON z HTML. + + + Failed to retrieve HTML page. + Nie udało się pobrać strony HTML. + + + The game is in version: %1 + Gra jest w wersji: %1 + + + The downloaded patch only works on version: %1 + Pobrana łatka działa tylko w wersji: %1 + + + You may need to update your game. + Możesz potrzebować zaktualizować swoją grę. + + + Incompatibility Notice + Powiadomienie o niezgodności + + + 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ę przeanlizować JSON: + + + Can't apply cheats before the game is started + Nie można zastosować kodów przed uruchomieniem gry. + + GameListFrame - Icon Ikona - Name Nazwa - Serial Numer seryjny - Compatibility Compatibility - Region Region - Firmware Oprogramowanie - Size Rozmiar - Version Wersja - Path Ścieżka - Play Time Czas gry - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Automatyczne aktualizacje - Error Błąd - Network error: Błąd sieci: - Failed to parse update information. Nie udało się sparsować informacji o aktualizacji. - No pre-releases found. Nie znaleziono wersji przedpremierowych. - Invalid release data. Nieprawidłowe dane wydania. - No download URL found for the specified asset. Nie znaleziono adresu URL do pobrania dla określonego zasobu. - Your version is already up to date! Twoja wersja jest już aktualna! - Update Available Dostępna aktualizacja - Update Channel Kanał Aktualizacji - Current Version Aktualna wersja - Latest Version Ostatnia wersja - Do you want to update? Czy chcesz zaktualizować? - Show Changelog Pokaż zmiany - Check for Updates at Startup Sprawdź aktualizacje przy starcie - Update Aktualizuj - No Nie - Hide Changelog Ukryj zmiany - Changes Zmiany - Network error occurred while trying to access the URL Błąd sieci wystąpił podczas próby uzyskania dostępu do URL - Download Complete Pobieranie zakończone - The update has been downloaded, press OK to install. Aktualizacja została pobrana, naciśnij OK, aby zainstalować. - Failed to save the update file at Nie udało się zapisać pliku aktualizacji w - Starting Update... Rozpoczynanie aktualizacji... - Failed to create the update script file Nie udało się utworzyć pliku skryptu aktualizacji + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 2d40781cf..5d9c84769 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 Sobre o shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 é um emulador experimental de código-fonte aberto para o PlayStation 4. - 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 +25,6 @@ ElfViewer - Open Folder Abrir Pasta @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Carregando a lista de jogos, por favor aguarde :3 - Cancel Cancelar - Loading... Carregando... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Escolha o diretório - Select which directory you want to install to. Selecione o diretório em que você deseja instalar. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Escolha o diretório - Directory to install games Diretório para instalar jogos - Browse Procurar - Error Erro - The value for location to install games is not valid. O diretório da instalação dos jogos não é válido. @@ -96,353 +81,420 @@ GuiContextMenus - Create Shortcut Criar Atalho - Cheats / Patches Cheats / Patches - SFO Viewer Visualizador de SFO - Trophy Viewer Visualizador de Troféu - Open Folder... Abrir Pasta... - Open Game Folder Abrir Pasta do Jogo - Open Save Data Folder Abrir Pasta de Save - Open Log Folder Abrir Pasta de Log - Copy info... Copiar informação... - Copy Name Copiar Nome - Copy Serial Copiar Serial - Copy All Copiar Tudo - Delete... Deletar... - Delete Game Deletar Jogo - Delete Update Deletar Atualização - Delete DLC Deletar DLC - + Compatibility... + Compatibilidade... + + + Update database + Atualizar banco de dados + + + View report + Ver status + + + Submit a report + Enviar status + + Shortcut creation Criação de atalho - - Shortcut created successfully!\n %1 - Atalho criado com sucesso!\n %1 + Shortcut created successfully! + Atalho criado com sucesso! - Error Erro - - Error creating shortcut!\n %1 - Erro ao criar atalho!\n %1 + Error creating shortcut! + Erro ao criar atalho! - Install PKG Instalar PKG - Game Jogo - requiresEnableSeparateUpdateFolder_MSG Este recurso requer a opção de configuração 'Habilitar Pasta de Atualização Separada' para funcionar. Se você quiser usar este recurso, habilite-o. - This game has no update to delete! Este jogo não tem atualização para excluir! - - + Update Atualização - This game has no DLC to delete! Este jogo não tem DLC para excluir! - DLC DLC - Delete %1 Deletar %1 - Are you sure you want to delete %1's %2 directory? Tem certeza de que deseja excluir o diretório %2 de %1 ? - + MainWindow - Open/Add Elf Folder Abrir/Adicionar pasta Elf - Install Packages (PKG) Instalar Pacotes (PKG) - Boot Game Iniciar Jogo - Check for Updates Verificar atualizações - About shadPS4 Sobre o shadPS4 - Configure... Configurar... - Install application from a .pkg file Instalar aplicação de um arquivo .pkg - Recent Games Jogos Recentes - Exit Sair - Exit shadPS4 Sair do shadPS4 - Exit the application. Sair da aplicação. - Show Game List Mostrar Lista de Jogos - Game List Refresh Atualizar Lista de Jogos - Tiny Muito pequeno - Small Pequeno - Medium Médio - Large Grande - List View Visualizar em Lista - Grid View Visualizar em Grade - Elf Viewer Visualizador de Elf - Game Install Directory Diretório de Instalação de Jogos - Download Cheats/Patches Baixar Cheats/Patches - Dump Game List Dumpar Lista de Jogos - PKG Viewer Visualizador de PKG - Search... Pesquisar... - File Arquivo - View Ver - Game List Icons Ícones da Lista de Jogos - Game List Mode Modo da Lista de Jogos - Settings Configurações - Utils Utilitários - Themes Temas - Help Ajuda - Dark Escuro - Light Claro - Green Verde - Blue Azul - Violet Violeta - toolBar Barra de Ferramentas + + Game List + Lista de Jogos + + + * Unsupported Vulkan Version + * Versão Vulkan não suportada + + + Download Cheats For All Installed Games + Baixar Cheats 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 cheats 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! + Atualização detectada! + + + PKG and Game versions match: + As versões do PKG e do Jogo são igual: + + + Would you like to overwrite? + Gostaria 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: + + + DLC Installation + Instalação de DLC + + + Would you like to install DLC: %1? + Você gostaria de instalar o DLC: %1? + + + DLC already installed: + DLC já instalada: + + + Game already installed + O jogo já está instalado: + + + PKG is a patch, please install the game first! + O PKG é um patch, por favor, instale o jogo primeiro! + + + PKG ERROR + ERRO de 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 + PKGViewer - Open Folder Abrir Pasta @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Visualizador de Troféu @@ -458,989 +509,704 @@ SettingsDialog - Settings Configurações - General Geral - System Sistema - Console Language Idioma do Console - Emulator Language Idioma do Emulador - Emulator Emulador - Enable Fullscreen Ativar Tela Cheia - Enable Separate Update Folder Habilitar pasta de atualização separada - Show Splash Mostrar Splash Inicial - Is PS4 Pro Modo PS4 Pro - Enable Discord Rich Presence Ativar Discord Rich Presence - Username Nome de usuário - + Trophy Key + Trophy Key + + + Trophy + Troféus + + Logger Registro - Log Type Tipo de Registro - Log Filter Filtro do Registro - + Open Log Location + Abrir local do log + + Input Entradas - Cursor Cursor - Hide Cursor Ocultar Cursor - Hide Cursor Idle Timeout Tempo de Inatividade para Ocultar Cursor - + s + s + + Controller Controle - Back Button Behavior Comportamento do botão Voltar - Graphics Gráficos - Graphics Device Placa de Vídeo - Width Largura - Height Altura - Vblank Divider Divisor Vblank - Advanced Avançado - Enable Shaders Dumping Ativar Dumping de Shaders - Enable NULL GPU Ativar GPU NULA - Paths Pastas - Game Folders Pastas dos Jogos - Add... Adicionar... - Remove Remover - Debug Depuração - Enable Debug Dumping Ativar Depuração de Dumping - Enable Vulkan Validation Layers Ativar Camadas de Validação do Vulkan - Enable Vulkan Synchronization Validation Ativar Validação de Sincronização do Vulkan - Enable RenderDoc Debugging Ativar Depuração por RenderDoc - Update Atualização - Check for Updates at Startup Verificar Atualizações ao Iniciar - Update Channel Canal de Atualização - Check for Updates Verificar atualizações - GUI Settings Configurações da Interface - Disable Trophy Pop-ups Desabilitar Pop-ups dos Troféus - Play title music Reproduzir música de abertura - Update Compatibility Database On Startup Atualizar Compatibilidade ao Inicializar - Game Compatibility Compatibilidade dos Jogos - Display Compatibility Data Exibir Dados de Compatibilidade - Update Compatibility Database Atualizar Lista de Compatibilidade - Volume Volume - - - MainWindow - - Game List - Lista de Jogos + Audio Backend + Backend de Áudio - - * Unsupported Vulkan Version - * Versão Vulkan não suportada - - - - Download Cheats For All Installed Games - Baixar Cheats 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 cheats 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! - Atualização detectada! - - - - PKG and Game versions match: - As versões do PKG e do Jogo são igual: - - - - Would you like to overwrite? - Gostaria 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: - - - - DLC Installation - Instalação de DLC - - - - Would you like to install DLC: %1? - Você gostaria de instalar o DLC: %1? - - - - DLC already installed: - DLC já instalada: - - - - Game already installed - O jogo já está instalado: - - - - PKG is a patch, please install the game first! - O PKG é um patch, por favor, instale o jogo primeiro! - - - - PKG ERROR - ERRO de 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 for - Cheats / Patches para - - - - defaultTextEdit_MSG - 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 - - - - No Image Available - Imagem Não Disponível - - - - Serial: - Serial: - - - - Version: - Versão: - - - - Size: - Tamanho: - - - - Select Cheat File: - Selecione o Arquivo de Cheat: - - - - Repository: - Repositório: - - - - Download Cheats - Baixar Cheats - - - - 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 os cheats 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 - Cheats - - - - 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 o serial 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 - Cheats Não Encontrados - - - - CheatsNotFound_MSG - 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 - Cheats Baixados com Sucesso - - - - CheatsDownloadedSuccessfully_MSG - 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. - - - - 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 os Cheats. Se o patch não aparecer, pode ser que ele não exista para o número de série e a versão específicos do jogo. - - - - 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. - - - - The game is in version: %1 - O jogo está na versão: %1 - - - - The downloaded patch only works on version: %1 - O patch baixado só funciona na versão: %1 - - - - You may need to update your game. - Talvez você precise atualizar seu jogo. - - - - Incompatibility Notice - Aviso de incompatibilidade - - - - Failed to open file: - Falha ao abrir o arquivo: - - - - XML ERROR: - ERRO de XML: - - - - Failed to open files.json for writing - Falha ao abrir files.json para gravação - - - - Author: - Autor: - - - - Directory does not exist: - O Diretório não existe: - - - - Failed to open files.json for reading. - Falha ao abrir files.json para leitura. - - - - Name: - Nome: - - - - Can't apply cheats before the game is started - Não é possível aplicar cheats antes que o jogo comece. - - - - SettingsDialog - - - Save - Salvar - - - Apply Aplicar - Restore Defaults Restaurar Padrões - Close Fechar - Point your mouse at an option to display its description. Passe o mouse sobre uma opção para exibir sua descrição. - consoleLanguageGroupBox Idioma do console:\nDefine o idioma usado pelo jogo no PS4.\nRecomenda-se configurá-lo para um idioma que o jogo suporte, o que pode variar conforme a região. - emulatorLanguageGroupBox Idioma do emulador:\nDefine o idioma da interface do emulador. - fullscreenCheckBox Ativar Tela Cheia:\nMove automaticamente a janela do jogo para o modo tela cheia.\nIsso pode ser alterado pressionando a tecla F11. - separateUpdatesCheckBox Habilitar pasta de atualização separada:\nPermite instalar atualizações de jogos em uma pasta separada para fácil gerenciamento. - showSplashCheckBox Mostrar Splash Inicial:\nExibe a tela inicial do jogo (imagem especial) ao iniciar o jogo. - ps4proCheckBox Modo PS4 Pro:\nFaz o emulador agir como um PS4 PRO, o que pode ativar recursos especiais em jogos que o suportam. - discordRPCCheckbox Ativar Discord Rich Presence:\nExibe o ícone do emulador e informações relevantes no seu perfil do Discord. - userName Nome de usuário:\nDefine o nome de usuário da conta PS4 que pode ser exibido por alguns jogos. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Tipo de Registro:\nDefine se a saída da janela de log deve ser sincronizada para melhorar o desempenho. Isso pode impactar negativamente a emulação. - logFilter Filtro de Registro:\nImprime apenas informações específicas.\nExemplos: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nNíveis: Trace, Debug, Info, Warning, Error, Critical - assim, um nível específico desativa todos os níveis anteriores na lista e registra todos os níveis subsequentes. - updaterGroupBox Atualizações:\nRelease: Versões oficiais que são lançadas todo mês e podem ser bastante antigas, mas são mais confiáveis e testadas.\nNightly: Versões de desenvolvimento que têm todos os novos recursos e correções, mas podem ter bugs e ser instáveis. - GUIgroupBox Reproduzir música de abertura:\nSe o jogo suportar, ativa a reprodução de uma música especial ao selecionar o jogo na interface do menu. - disableTrophycheckBox Desabilitar pop-ups dos troféus:\nDesabilite notificações de troféus no jogo. O progresso do troféu ainda pode ser rastreado usando o Trophy Viewer (clique com o botão direito do mouse no jogo na janela principal). - hideCursorGroupBox Ocultar Cursor:\nEscolha quando o cursor desaparecerá:\nNunca: Você sempre verá o mouse.\nParado: Defina um tempo para ele desaparecer após ficar inativo.\nSempre: Você nunca verá o mouse. - idleTimeoutGroupBox Defina um tempo em segundos para o mouse desaparecer após ficar inativo. - backButtonBehaviorGroupBox Comportamento do botão Voltar:\nDefine o botão Voltar do controle para emular o toque na posição especificada no touchpad do PS4. - enableCompatibilityCheckBox Exibir Dados de Compatibilidade:\nExibe informações de compatibilidade dos jogos na janela principal.\nHabilitar "Atualizar Compatibilidade ao Inicializar" para obter informações atualizadas. - checkCompatibilityOnStartupCheckBox Atualizar Compatibilidade ao inicializar:\nAtualiza automaticamente o banco de dados de compatibilidade quando o SHADPS4 é iniciado. - updateCompatibilityButton Atualizar Lista de Compatibilidade:\nAtualizar imediatamente o banco de dados de compatibilidade. - Never Nunca - Idle Parado - Always Sempre - Touchpad Left Touchpad Esquerdo - Touchpad Right Touchpad Direito - Touchpad Center Touchpad Centro - None Nenhum - graphicsAdapterGroupBox Placa de Vídeo:\nEm sistemas com múltiplas GPUs, escolha qual GPU o emulador usará da lista suspensa,\nou escolha "Auto Select" para que ele determine automaticamente. - resolutionLayout Largura/Altura:\nDefine o tamanho da janela do emulador no momento da inicialização, que pode ser redimensionado durante o jogo.\nIsso é diferente da resolução dentro do jogo. - heightDivider Divisor Vblank:\nA taxa de quadros que o emulador atualiza é multiplicada por este número. Mudar isso pode ter efeitos negativos, como aumentar a velocidade do jogo ou quebrar funções vitais do jogo que não esperam que isso mude! - dumpShadersCheckBox Ativar Dumping de Shaders:\nArmazena os shaders do jogo em uma pasta durante a renderização para fins de depuração técnica. - nullGpuCheckBox Ativar GPU NULA:\nDesativa a renderização do jogo para fins de depuração técnica, como se não houvesse nenhuma placa gráfica. - gameFoldersBox Pastas dos jogos:\nA lista de pastas para verificar se há jogos instalados. - addFolderButton Adicionar:\nAdicione uma pasta à lista. - removeFolderButton Remover:\nRemove uma pasta da lista. - debugDump Ativar Depuração de Dumping:\nArmazena os símbolos de importação e exportação e as informações do cabeçalho do arquivo do programa PS4 atual em um diretório. - vkValidationCheckBox Ativar Camadas de Validação do Vulkan:\nAtiva um sistema que valida o estado do renderizador Vulkan e registra informações sobre seu estado interno.\nIsso diminui o desempenho e pode alterar o comportamento da emulação. - vkSyncValidationCheckBox Ativar Validação de Sincronização do Vulkan:\nAtiva um sistema que valida o agendamento de tarefas de renderização Vulkan.\nIsso diminui o desempenho e pode alterar o comportamento da emulação. - rdocCheckBox Ativar depuração por RenderDoc:\nSe ativado, permite que o emulador tenha compatibilidade com RenderDoc para gravação e análise do quadro renderizado atual. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches para + + + defaultTextEdit_MSG + 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 + + + No Image Available + Imagem Não Disponível + + + Serial: + Serial: + + + Version: + Versão: + + + Size: + Tamanho: + + + Select Cheat File: + Selecione o Arquivo de Cheat: + + + Repository: + Repositório: + + + Download Cheats + Baixar Cheats + + + 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 os cheats 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 + Cheats + + + 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 o serial 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 + Cheats Não Encontrados + + + CheatsNotFound_MSG + 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 + Cheats Baixados com Sucesso + + + CheatsDownloadedSuccessfully_MSG + 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. + + + 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 os Cheats. Se o patch não aparecer, pode ser que ele não exista para o número de série e a versão específicos do jogo. + + + 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. + + + The game is in version: %1 + O jogo está na versão: %1 + + + The downloaded patch only works on version: %1 + O patch baixado só funciona na versão: %1 + + + You may need to update your game. + Talvez você precise atualizar seu jogo. + + + Incompatibility Notice + Aviso de incompatibilidade + + + Failed to open file: + Falha ao abrir o arquivo: + + + XML ERROR: + ERRO de XML: + + + Failed to open files.json for writing + Falha ao abrir files.json para gravação + + + Author: + Autor: + + + Directory does not exist: + O Diretório não existe: + + + Failed to open files.json for reading. + Falha ao abrir files.json para leitura. + + + Name: + Nome: + + + Can't apply cheats before the game is started + Não é possível aplicar cheats antes que o jogo comece. + + GameListFrame - Icon Icone - Name Nome - Serial Serial - Compatibility Compatibilidade - Region Região - Firmware Firmware - Size Tamanho - Version Versão - Path Diretório - Play Time Tempo Jogado - Never Played Nunca jogado - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibilidade não testada - Game does not initialize properly / crashes the emulator Jogo não inicializa corretamente / trava o emulador - Game boots, but only displays a blank screen O jogo inicializa, mas exibe apenas uma tela vazia - Game displays an image but does not go past the menu Jogo exibe imagem mas não passa do menu - Game has game-breaking glitches or unplayable performance O jogo tem falhas que interrompem o jogo ou desempenho injogável - Game can be completed with playable performance and no major glitches O jogo pode ser concluído com desempenho jogável e sem grandes falhas @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Atualizador automático - Error Erro - Network error: Erro de rede: - Failed to parse update information. Falha ao analisar as informações de atualização. - No pre-releases found. Nenhuma pre-release encontrada. - Invalid release data. Dados da release inválidos. - No download URL found for the specified asset. Nenhuma URL de download encontrada para o asset especificado. - Your version is already up to date! Sua versão já está atualizada! - Update Available Atualização disponível - Update Channel Canal de Atualização - Current Version Versão atual - Latest Version Última versão - Do you want to update? Você quer atualizar? - Show Changelog Mostrar Changelog - Check for Updates at Startup Verificar Atualizações ao Iniciar - Update Atualizar - No Não - Hide Changelog Ocultar Changelog - Changes Alterações - Network error occurred while trying to access the URL Ocorreu um erro de rede ao tentar acessar o URL - Download Complete Download Completo - The update has been downloaded, press OK to install. A atualização foi baixada, pressione OK para instalar. - Failed to save the update file at Falha ao salvar o arquivo de atualização em - Starting Update... Iniciando atualização... - Failed to create the update script file Falha ao criar o arquivo de script de atualização + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 aa72049af..71354fb06 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Trapaças / Patches Coduri / Patch-uri - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Deschide Folder... - Open Game Folder Deschide Folder Joc - Open Save Data Folder Deschide Folder Date Salvate - Open Log Folder Deschide Folder Jurnal - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Verifică actualizările - 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 - Download Cheats/Patches Descarcă Coduri / Patch-uri - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Ajutor - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Lista jocurilor + + + * 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! + Patch detectat! + + + PKG and Game versions match: + Versiunile PKG și ale jocului sunt compatibile: + + + Would you like to overwrite? + Doriți să suprascrieți? + + + PKG Version %1 is older than installed version: + Versiunea PKG %1 este mai veche decât versiunea instalată: + + + Game is installed: + Jocul este instalat: + + + Would you like to install Patch: + Doriți să instalați patch-ul: + + + DLC Installation + Instalare DLC + + + 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 + + + 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 + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Activați Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Deschide locația jurnalului + + Input Introducere - Cursor Cursor - Hide Cursor Ascunde cursorul - Hide Cursor Idle Timeout Timeout pentru ascunderea cursorului inactiv - + s + s + + Controller Controler - Back Button Behavior Comportament buton înapoi - 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 - Paths Trasee - Game Folders Dosare de joc - Add... Adaugă... - Remove Eliminare - 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 - Update Actualizare - Check for Updates at Startup Verifică actualizări la pornire - Update Channel Canal de Actualizare - Check for Updates Verifică actualizări - GUI Settings Setări GUI - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Redă muzica titlului - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Volum - - - MainWindow - - Game List - Lista jocurilor + Audio Backend + Audio Backend - - * 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! - Patch detectat! - - - - PKG and Game versions match: - Versiunile PKG și ale jocului sunt compatibile: - - - - Would you like to overwrite? - Doriți să suprascrieți? - - - - PKG Version %1 is older than installed version: - Versiunea PKG %1 este mai veche decât versiunea instalată: - - - - Game is installed: - Jocul este instalat: - - - - Would you like to install Patch: - Doriți să instalați patch-ul: - - - - DLC Installation - Instalare DLC - - - - 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 - - - - 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 for - Cheats / Patches for - - - - 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. Dacă patch-ul nu apare, este posibil să nu existe pentru seria și versiunea specifică a jocului. - - - - 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. - - - - The game is in version: %1 - Jocul este în versiunea: %1 - - - - The downloaded patch only works on version: %1 - Patch-ul descărcat funcționează doar pe versiunea: %1 - - - - You may need to update your game. - Este posibil să trebuiască să actualizezi jocul tău. - - - - Incompatibility Notice - Avertizare de incompatibilitate - - - - 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: - - - - Can't apply cheats before the game is started - Nu poți aplica cheats înainte ca jocul să înceapă. - - - - SettingsDialog - - - Save - Salvează - - - Apply Aplică - Restore Defaults Restabilește Impozitivele - Close Închide - Point your mouse at an option to display its description. Indicați mouse-ul asupra unei opțiuni pentru a afișa descrierea acesteia. - consoleLanguageGroupBox Limba consolei:\nSetează limba pe care o folosește jocul PS4.\nSe recomandă să setezi această opțiune pe o limbă pe care jocul o suportă, ceea ce poate varia în funcție de regiune. - emulatorLanguageGroupBox Limba emulatorului:\nSetează limba interfeței utilizatorului a emulatorului. - fullscreenCheckBox Activează modul pe ecran complet:\nPune automat fereastra jocului în modul pe ecran complet.\nAceasta poate fi dezactivată apăsând tasta F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Afișează ecranul de încărcare:\nAfișează ecranul de încărcare al jocului (o imagine specială) în timp ce jocul pornește. - ps4proCheckBox Este PS4 Pro:\nFace ca emulatorul să se comporte ca un PS4 PRO, ceea ce poate activa funcții speciale în jocurile care o suportă. - discordRPCCheckbox Activați Discord Rich Presence:\nAfișează pictograma emulatorului și informații relevante pe profilul dumneavoastră Discord. - userName Nume utilizator:\nSetează numele de utilizator al contului PS4, care poate fi afișat de unele jocuri. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Tip jurnal:\nSetează dacă să sincronizezi ieșirea ferestrei de jurnal pentru performanță. Aceasta poate avea efecte adverse asupra emulării. - logFilter Filtrul jurnalului:\nFiltrează jurnalul pentru a imprima doar informații specifice.\nExemple: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Niveluri: Trace, Debug, Info, Warning, Error, Critical - în această ordine, un nivel specific reduce toate nivelurile anterioare din listă și înregistrează toate nivelurile ulterioare. - updaterGroupBox Actualizare:\nRelease: Versiuni oficiale lansate în fiecare lună, care pot fi foarte învechite, dar sunt mai fiabile și testate.\nNightly: Versiuni de dezvoltare care conțin toate cele mai recente funcții și corecții, dar pot conține erori și sunt mai puțin stabile. - GUIgroupBox Redă muzica titlului:\nDacă un joc o suportă, activează redarea muzicii speciale când selectezi jocul în GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Ascunde cursorul:\nAlegeți când va dispărea cursorul:\nNiciodată: Vei vedea întotdeauna mouse-ul.\nInactiv: Setează un timp pentru a dispărea după inactivitate.\nÎntotdeauna: nu vei vedea niciodată mouse-ul. - idleTimeoutGroupBox Setați un timp pentru ca mouse-ul să dispară după ce a fost inactiv. - backButtonBehaviorGroupBox Comportamentul butonului înapoi:\nSetează butonul înapoi al controlerului să imite atingerea poziției specificate pe touchpad-ul PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Niciodată - Idle Inactiv - Always Întotdeauna - Touchpad Left Touchpad Stânga - Touchpad Right Touchpad Dreapta - Touchpad Center Centru Touchpad - None Niciunul - graphicsAdapterGroupBox Dispozitiv grafic:\nPe sistemele cu mai multe GPU-uri, alege GPU-ul pe care emulatorul îl va folosi din lista derulantă,\nsau selectează "Auto Select" pentru a-l determina automat. - resolutionLayout Lățime/Înălțime:\nSetează dimensiunea ferestrei emulatorului la lansare, care poate fi redimensionată în timpul jocului.\nAceasta este diferită de rezoluția din joc. - heightDivider Împărțitor Vblank:\nRata de cadre cu care emulatorul se reîmprospătează este multiplicată cu acest număr. Schimbarea acestuia poate avea efecte adverse, cum ar fi creșterea vitezei jocului sau distrugerea funcționalității critice a jocului care nu se așteaptă ca aceasta să se schimbe! - dumpShadersCheckBox Activează salvarea shaderelor:\nÎn scopuri de depanare tehnică, salvează shader-urile jocului într-un folder pe măsură ce sunt randate. - nullGpuCheckBox Activează GPU Null:\nÎn scopuri de depanare tehnică, dezactivează redarea jocului ca și cum nu ar exista o placă grafică. - gameFoldersBox Folderele jocurilor:\nLista folderelor pentru a verifica jocurile instalate. - addFolderButton Adăugați:\nAdăugați un folder la listă. - removeFolderButton Eliminați:\nÎndepărtați un folder din listă. - debugDump Activează salvarea pentru depanare:\nSalvează simbolurile de import și export și informațiile din antetul fișierului pentru aplicația PS4 care rulează în prezent într-un director. - vkValidationCheckBox Activează straturile de validare Vulkan:\nActivează un sistem care validează starea renderer-ului Vulkan și înregistrează informații despre starea sa internă. Aceasta va reduce performanța și probabil va schimba comportamentul emulării. - vkSyncValidationCheckBox Activează validarea sincronizării Vulkan:\nActivează un sistem care validează sincronizarea sarcinilor de redare Vulkan. Aceasta va reduce performanța și probabil va schimba comportamentul emulării. - rdocCheckBox Activează depanarea RenderDoc:\nDacă este activat, emulatorul va oferi compatibilitate cu Renderdoc pentru a permite capturarea și analiza cadrului redat în prezent. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. Dacă patch-ul nu apare, este posibil să nu existe pentru seria și versiunea specifică a jocului. + + + 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. + + + The game is in version: %1 + Jocul este în versiunea: %1 + + + The downloaded patch only works on version: %1 + Patch-ul descărcat funcționează doar pe versiunea: %1 + + + You may need to update your game. + Este posibil să trebuiască să actualizezi jocul tău. + + + Incompatibility Notice + Avertizare de incompatibilitate + + + 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: + + + Can't apply cheats before the game is started + Nu poți aplica cheats înainte ca jocul să înceapă. + + GameListFrame - Icon Icon - Name Nume - Serial Serie - Compatibility Compatibility - Region Regiune - Firmware Firmware - Size Dimensiune - Version Versiune - Path Drum - Play Time Timp de Joacă - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Actualizator automat - Error Eroare - Network error: Eroare de rețea: - Failed to parse update information. Nu s-au putut analiza informațiile de actualizare. - No pre-releases found. Nu au fost găsite pre-lansări. - Invalid release data. Datele versiunii sunt invalide. - No download URL found for the specified asset. Nu s-a găsit URL de descărcare pentru resursa specificată. - Your version is already up to date! Versiunea ta este deja actualizată! - Update Available Actualizare disponibilă - Update Channel Canal de Actualizare - Current Version Versiunea curentă - Latest Version Ultima versiune - Do you want to update? Doriți să actualizați? - Show Changelog Afișați jurnalul de modificări - Check for Updates at Startup Verifică actualizări la pornire - Update Actualizare - No Nu - Hide Changelog Ascunde jurnalul de modificări - Changes Modificări - Network error occurred while trying to access the URL A apărut o eroare de rețea în timpul încercării de a accesa URL-ul - Download Complete Descărcare completă - The update has been downloaded, press OK to install. Actualizarea a fost descărcată, apăsați OK pentru a instala. - Failed to save the update file at Nu s-a putut salva fișierul de actualizare la - Starting Update... Încep actualizarea... - Failed to create the update script file Nu s-a putut crea fișierul script de actualizare + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 67a38eeba..0e803ea42 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -6,22 +6,18 @@ 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. Это програмное обеспечение не должно использоваться для запуска игр, которые вы получили нелегально. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Открыть папку @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Загрузка списка игр, пожалуйста подождите :3 - Cancel Отмена - Loading... Загрузка... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Выберите папку - Select which directory you want to install to. Выберите папку, в которую вы хотите установить. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Выберите папку - Directory to install games Папка для установки игр - Browse Обзор - Error Ошибка - The value for location to install games is not valid. Недопустимое значение местоположения для установки игр. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Создать ярлык - Cheats / Patches Читы и патчи - SFO Viewer Просмотр SFO - Trophy Viewer Просмотр трофеев - Open Folder... - Открыть Папку... + Открыть папку... - Open Game Folder Открыть папку с игрой - Open Save Data Folder - Открыть Папку Сохранений + Открыть папку сохранений - Open Log Folder - Открыть Папку Логов + Открыть папку логов - Copy info... Копировать информацию... - Copy Name Копировать имя - Copy Serial Копировать серийный номер - Copy All Копировать все - Delete... Удаление... - Delete Game Удалить игру - Delete Update Удалить обновление - Delete DLC Удалить DLC - + Compatibility... + Совместимость... + + + Update database + Обновить базу данных + + + View report + Посмотреть отчет + + + Submit a report + Отправить отчет + + Shortcut creation Создание ярлыка - - Shortcut created successfully!\n %1 - Ярлык создан успешно!\n %1 + Shortcut created successfully! + Ярлык создан успешно! - Error Ошибка - - Error creating shortcut!\n %1 - Ошибка создания ярлыка!\n %1 + Error creating shortcut! + Ошибка создания ярлыка! - Install PKG Установить PKG - Game Игры - requiresEnableSeparateUpdateFolder_MSG Эта функция требует включения настройки 'Отдельная папка обновлений'. Если вы хотите использовать эту функцию, пожалуйста включите её. - This game has no update to delete! У этой игры нет обновлений для удаления! - - + Update Обновления - This game has no DLC to delete! У этой игры нет DLC для удаления! - DLC DLC - Delete %1 Удалить %1 - Are you sure you want to delete %1's %2 directory? Вы уверены, что хотите удалить папку %2 %1? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Открыть/Добавить папку Elf - Install Packages (PKG) Установить пакеты (PKG) - Boot Game Запустить игру - Check for Updates Проверить обновления - 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 Темы - Help Помощь - Dark Темная - Light Светлая - Green Зеленая - Blue Синяя - Violet Фиолетовая - toolBar Панель инструментов + + Game List + Список игр + + + * 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 - это патч, сначала установите игру! + + + 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 Открыть папку @@ -450,1127 +502,839 @@ TrophyViewer - Trophy Viewer - Трофеи + Просмотр трофеев SettingsDialog - Settings Настройки - General Общее - System Система - Console Language Язык консоли - Emulator Language Язык эмулятора - Emulator Эмулятор - Enable Fullscreen Полноэкранный режим - Enable Separate Update Folder Отдельная папка обновлений - Show Splash Показывать заставку - Is PS4 Pro Режим PS4 Pro - Enable Discord Rich Presence Включить Discord Rich Presence - Username Имя пользователя - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Логирование - Log Type Тип логов - Log Filter Фильтр логов - + Open Log Location + Открыть местоположение журнала + + Input Ввод - Cursor Курсор мыши - Hide Cursor Скрывать курсор - Hide Cursor Idle Timeout - Тайм-аут скрытия курсора при бездействии + Время скрытия курсора при бездействии + + + s + сек - Controller Контроллер - Back Button Behavior Поведение кнопки назад - Graphics Графика - Graphics Device Графическое устройство - Width Ширина - Height Высота - Vblank Divider Делитель Vblank - Advanced Продвинутые - Enable Shaders Dumping Включить дамп шейдеров - Enable NULL GPU Включить NULL GPU - Paths Пути - Game Folders Игровые папки - Add... Добавить... - Remove Удалить - Debug Отладка - Enable Debug Dumping Включить отладочные дампы - Enable Vulkan Validation Layers Включить слои валидации Vulkan - Enable Vulkan Synchronization Validation Включить валидацию синхронизации Vulkan - Enable RenderDoc Debugging Включить отладку RenderDoc - Update Обновление - Check for Updates at Startup Проверка при запуске - Update Channel Канал обновления - Check for Updates Проверить обновления - GUI Settings Интерфейс - Disable Trophy Pop-ups - Disable Trophy Pop-ups + Отключить уведомления о трофеях - Play title music Играть заглавную музыку - Update Compatibility Database On Startup - Update Compatibility Database On Startup + Обновлять базу совместимости при запуске - Game Compatibility - Game Compatibility + Совместимость игр - Display Compatibility Data - Display Compatibility Data + Показывать данные совместимости - Update Compatibility Database - Update Compatibility Database + Обновить базу совместимости - Volume Громкость - - - MainWindow - - Game List - Список игр + Audio Backend + Звуковая Подсистема - - * 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 - это патч, сначала установите игру! - - - - 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 for - Cheats / Patches for - - - - 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. - Не удалось разобрать данные JSON из HTML. - - - - Failed to retrieve HTML page. - Не удалось получить HTML-страницу. - - - - The game is in version: %1 - Игра в версии: %1 - - - - The downloaded patch only works on version: %1 - Скачанный патч работает только на версии: %1 - - - - You may need to update your game. - Вам может понадобиться обновить игру. - - - - Incompatibility Notice - Уведомление о несовместимости - - - - 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: - Имя: - - - - Can't apply cheats before the game is started - Невозможно применить читы до начала игры - - - - SettingsDialog - - - Save - Сохранить - - - Apply Применить - Restore Defaults По умолчанию - Close Закрыть - Point your mouse at an option to display its description. Наведите указатель мыши на опцию, чтобы отобразить ее описание. - consoleLanguageGroupBox Язык консоли:\nУстановите язык, который будет использоваться в играх PS4.\nРекомендуется устанавливать язык который поддерживается игрой, так как он может отличаться в зависимости от региона. - emulatorLanguageGroupBox Язык эмулятора:\nУстановите язык пользовательского интерфейса эмулятора. - fullscreenCheckBox Полноэкранный режим:\nАвтоматически переводит игровое окно в полноэкранный режим.\nВы можете отключить это, нажав клавишу F11. - separateUpdatesCheckBox Отдельная папка обновлений:\nПозволяет устанавливать обновления игры в отдельную папку для удобства. - showSplashCheckBox - Показывать заставку:\nОтображает заставку игры (специальное изображение) во время запуска игры. + Показывать заставку:\nОтображает заставку игры (специальное изображение) во время запуска. - ps4proCheckBox Режим PS4 Pro:\nЗаставляет эмулятор работать как PS4 Pro, что может включить специальные функции в играх, поддерживающих это. - discordRPCCheckbox Включить Discord Rich Presence:\nОтображает значок эмулятора и соответствующую информацию в вашем профиле Discord. - userName Имя пользователя:\nУстановите имя пользователя аккаунта PS4. Это может отображаться в некоторых играх. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Тип логов:\nУстановите, синхронизировать ли вывод окна логов ради производительности. Это может негативно сказаться на эмуляции. - logFilter Фильтр логов:\nФильтрует логи, чтобы показывать только определенную информацию.\nПримеры: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Уровни: Trace, Debug, Info, Warning, Error, Critical - в этом порядке, конкретный уровень глушит все предыдущие уровни в списке и показывает все последующие уровни. - updaterGroupBox Обновление:\nRelease: Официальные версии, которые выпускаются каждый месяц и могут быть очень старыми, но они более надежные и проверенные.\nNightly: Версии разработки, которые содержат все последние функции и исправления, но могут содержать ошибки и менее стабильны. - GUIgroupBox Играть заглавную музыку:\nВключает воспроизведение специальной музыки при выборе игры в списке, если она это поддерживает. - disableTrophycheckBox - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Отключить уведомления о трофеях:\nОтключает внутриигровые уведомления о трофеях. Прогресс трофеев по прежнему можно отслеживать в меню Просмотр трофеев (правая кнопка мыши по игре в главном окне). - hideCursorGroupBox - Скрывать курсор:\nВыберите, когда курсор исчезнет:\nНикогда: Вы всегда будете видеть мышь.\nПри бездействии: Установите время, через которое курсор исчезнет при бездействии.\nВсегда: Вы никогда не будете видеть мышь. + Скрывать курсор:\nВыберите, когда курсор будет скрыт:\nНикогда: Вы всегда будете видеть курсор.\nПри бездействии: Установите время, через которое курсор будет скрыт при бездействии.\nВсегда: Курсор всегда будет скрыт. - idleTimeoutGroupBox Установите время, через которое курсор исчезнет при бездействии. - backButtonBehaviorGroupBox Поведение кнопки «Назад»:\nНастраивает кнопку «Назад» контроллера на эмуляцию нажатия на указанную область на сенсорной панели контроллера PS4. - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Показывать данные совместимости:\nПоказывает информацию о совместимости игр в таблице. Включите «Обновлять базу совместимости при запуске» для получения актуальной информации. - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Обновлять базу совместимости при запуске:\nАвтоматически обновлять базу данных совместимости при запуске shadPS4. - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. + Обновить базу совместимости:\nНемедленно обновить базу данных совместимости. - Never Никогда - Idle При бездействии - Always Всегда - Touchpad Left Тачпад слева - Touchpad Right Тачпад справа - Touchpad Center Центр тачпада - None Нет - graphicsAdapterGroupBox - Графическое устройство:\nВ системах с несколькими GPU выберите GPU, который будет использовать эмулятор из выпадающего списка,\nили выберите "Auto Select", чтобы определить его автоматически. + Графическое устройство:\nВ системах с несколькими GPU выберите GPU, который будет использовать эмулятор.\nВыберите "Auto Select", чтобы определить его автоматически. - resolutionLayout Ширина/Высота:\nУстановите размер окна эмулятора при запуске, который может быть изменен во время игры.\nЭто отличается от разрешения в игре. - heightDivider Делитель Vblank:\nЧастота кадров, с которой обновляется эмулятор, умножается на это число. Изменение этого параметра может иметь негативные последствия, такие как увеличение скорости игры или нарушение критических функций игры, которые этого не ожидают! - dumpShadersCheckBox Включить дамп шейдеров:\nДля технической отладки сохраняет шейдеры игр в папку во время рендеринга. - nullGpuCheckBox Включить NULL GPU:\nДля технической отладки отключает рендеринг игры так, как будто графической карты нет. - gameFoldersBox Игровые папки:\nСписок папок для проверки установленных игр. - addFolderButton Добавить:\nДобавить папку в список. - removeFolderButton Удалить:\nУдалить папку из списка. - debugDump Включить отладочные дампы:\nСохраняет символы импорта, экспорта и информацию о заголовке файла текущей исполняемой программы PS4 в папку. - vkValidationCheckBox Включить слои валидации Vulkan:\nВключает систему, которая проверяет состояние рендерера Vulkan и логирует информацию о его внутреннем состоянии. Это снизит производительность и, вероятно, изменит поведение эмуляции. - vkSyncValidationCheckBox Включить валидацию синхронизации Vulkan:\nВключает систему, которая проверяет тайминг задач рендеринга Vulkan. Это снизит производительность и, вероятно, изменит поведение эмуляции. - rdocCheckBox Включить отладку RenderDoc:\nЕсли включено, эмулятор обеспечит совместимость с Renderdoc, позволяя захватывать и анализировать текущие кадры во время рендеринга. + + CheatsPatches + + Cheats / Patches for + Читы и патчи для + + + 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. + Не удалось разобрать данные JSON из HTML. + + + Failed to retrieve HTML page. + Не удалось получить HTML-страницу. + + + The game is in version: %1 + Игра в версии: %1 + + + The downloaded patch only works on version: %1 + Скачанный патч работает только на версии: %1 + + + You may need to update your game. + Вам может понадобиться обновить игру. + + + Incompatibility Notice + Уведомление о несовместимости + + + 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: + Имя: + + + Can't apply cheats before the game is started + Невозможно применить читы до начала игры + + GameListFrame - Icon Иконка - Name Название - Serial Серийный номер - Compatibility - Compatibility + Совместимость - Region Регион - Firmware Прошивка - Size Размер - Version Версия - Path Путь - Play Time Времени в игре - Never Played - Never Played + Вы не играли + + + h + ч + + + m + м + + + s + с - Compatibility is untested - Compatibility is untested + Совместимость не проверена - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + Игра не иницализируется правильно / крашит эмулятор - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + Игра запускается, но показывает только пустой экран - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + Игра показывает картинку, но не проходит дальше меню - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + Игра имеет ломающие игру глюки или плохую производительность - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + Игра может быть пройдена с хорошей производительностью и без серьезных сбоев CheckUpdate - Auto Updater Автообновление - Error Ошибка - Network error: Сетевая ошибка: - Failed to parse update information. Не удалось разобрать информацию об обновлении. - No pre-releases found. Предварительных версий не найдено. - Invalid release data. Недопустимые данные релиза. - No download URL found for the specified asset. Не найден URL для загрузки указанного ресурса. - Your version is already up to date! Ваша версия уже обновлена! - Update Available Доступно обновление - Update Channel Канал обновления - Current Version Текущая версия - Latest Version Последняя версия - Do you want to update? Вы хотите обновиться? - Show Changelog Показать журнал изменений - Check for Updates at Startup Проверка при запуске - Update - Обновиться + Обновить - No Нет - Hide Changelog Скрыть журнал изменений - Changes Журнал изменений - Network error occurred while trying to access the URL Произошла сетевая ошибка при попытке доступа к URL - Download Complete Скачивание завершено - The update has been downloaded, press OK to install. Обновление загружено, нажмите OK для установки. - Failed to save the update file at Не удалось сохранить файл обновления в - Starting Update... Начало обновления... - Failed to create the update script file Не удалось создать файл скрипта обновления + + GameListUtils + + B + Б + + + KB + КБ + + + MB + МБ + + + GB + ГБ + + + TB + ТБ + + \ No newline at end of file diff --git a/src/qt_gui/translations/sq.ts b/src/qt_gui/translations/sq.ts index 0e89eaaca..7354b4bd9 100644 --- a/src/qt_gui/translations/sq.ts +++ b/src/qt_gui/translations/sq.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 Rreth shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4 është një emulator eksperimental me burim të hapur për PlayStation 4. - This software should not be used to play games you have not legally obtained. Ky program nuk duhet përdorur për të luajtur lojëra që nuk ke marrë ligjërisht. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Hap Dosjen @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Po ngarkohet lista e lojërave, të lutem prit :3 - Cancel Anulo - Loading... Duke ngarkuar... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Përzgjidh dosjen - Select which directory you want to install to. Përzgjidh në cilën dosje do që të instalosh. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Përzgjidh dosjen - Directory to install games Dosja ku do instalohen lojërat - Browse Shfleto - Error Gabim - The value for location to install games is not valid. Vlera për vendndodhjen e instalimit të lojërave nuk është e vlefshme. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Krijo Shkurtore - Cheats / Patches Mashtrime / Arna - SFO Viewer Shikuesi i SFO - Trophy Viewer Shikuesi i Trofeve - Open Folder... Hap Dosjen... - Open Game Folder Hap Dosjen e Lojës - Open Save Data Folder Hap Dosjen e të Dhënave të Ruajtura - Open Log Folder Hap Dosjen e Ditarit - Copy info... Kopjo informacionin... - Copy Name Kopjo Emrin - Copy Serial Kopjo Serikun - Copy All Kopjo të Gjitha - Delete... Fshi... - Delete Game Fshi lojën - Delete Update Fshi përditësimin - Delete DLC Fshi DLC-në - + Compatibility... + Përputhshmëria... + + + Update database + Përditëso bazën e të dhënave + + + View report + Shiko raportin + + + Submit a report + Paraqit një raport + + Shortcut creation Krijimi i shkurtores - - Shortcut created successfully!\n %1 - Shkurtorja u krijua me sukses!\n %1 + Shortcut created successfully! + Shkurtorja u krijua me sukses! - Error Gabim - - Error creating shortcut!\n %1 - Gabim në krijimin e shkurtores!\n %1 + Error creating shortcut! + Gabim në krijimin e shkurtores! - Install PKG Instalo PKG - Game Loja - requiresEnableSeparateUpdateFolder_MSG Kjo veçori kërkon cilësimin 'Aktivizo dosjen e ndarë të përditësimit' për të punuar. Në qoftë se do ta përdorësh këtë veçori, të lutem aktivizoje. - This game has no update to delete! Kjo lojë nuk ka përditësim për të fshirë! - - + Update Përditësim - This game has no DLC to delete! Kjo lojë nuk ka DLC për të fshirë! - DLC DLC - Delete %1 Fshi %1 - Are you sure you want to delete %1's %2 directory? Je i sigurt që do të fsish dosjen %2 të %1? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Hap/Shto Dosje ELF - Install Packages (PKG) Instalo Paketat (PKG) - Boot Game Nis Lojën - Check for Updates Kontrollo për përditësime - About shadPS4 Rreth shadPS4 - Configure... Konfiguro... - Install application from a .pkg file Instalo aplikacionin nga një skedar .pkg - Recent Games Lojërat e fundit - Exit Dil - Exit shadPS4 Dil nga shadPS4 - Exit the application. Dil nga aplikacioni. - Show Game List Shfaq Listën e Lojërave - Game List Refresh Rifresko Listën e Lojërave - Tiny Të vockla - Small Të vogla - Medium Të mesme - Large Të mëdha - List View - Pamja e Listës + Pamja me List - Grid View - Pamja e Rrjetës + Pamja me Rrjetë - Elf Viewer - Shikuesi i Elf + Shikuesi i ELF - Game Install Directory Dosja e Instalimit të Lojës - Download Cheats/Patches Shkarko Mashtrime/Arna - Dump Game List Zbraz Listën e Lojërave - PKG Viewer Shikuesi i PKG - Search... Kërko... - File Skedari - View Pamja - Game List Icons Ikonat e Listës së Lojërave - Game List Mode Mënyra e Listës së Lojërave - Settings Cilësimet - Utils Shërbimet - Themes Motivet - Help Ndihmë - Dark E errët - Light E çelët - Green E gjelbër - Blue E kaltër - Violet Vjollcë - toolBar Shiriti i veglave + + Game List + Lista e lojërave + + + * Unsupported Vulkan Version + * Version i pambështetur i Vulkan + + + Download Cheats For All Installed Games + Shkarko mashtrime për të gjitha lojërat e instaluara + + + Download Patches For All Games + Shkarko arna për të gjitha lojërat e instaluara + + + Download Complete + Shkarkimi përfundoi + + + You have downloaded cheats for all the games you have installed. + Ke shkarkuar mashtrimet për të gjitha lojërat që ke instaluar. + + + Patches Downloaded Successfully! + Arnat u shkarkuan me sukses! + + + All Patches available for all games have been downloaded. + Të gjitha arnat e ofruara për të gjitha lojërat janë shkarkuar. + + + Games: + Lojërat: + + + PKG File (*.PKG) + Skedar PKG (*.PKG) + + + ELF files (*.bin *.elf *.oelf) + Skedarë ELF (*.bin *.elf *.oelf) + + + Game Boot + Nis Lojën + + + Only one file can be selected! + Mund të përzgjidhet vetëm një skedar! + + + PKG Extraction + Nxjerrja e PKG-së + + + Patch detected! + U zbulua një arnë! + + + PKG and Game versions match: + PKG-ja dhe versioni i Lojës përputhen: + + + Would you like to overwrite? + Dëshiron të mbishkruash? + + + PKG Version %1 is older than installed version: + Versioni %1 i PKG-së është më i vjetër se versioni i instaluar: + + + Game is installed: + Loja është instaluar: + + + Would you like to install Patch: + Dëshiron të instalosh Arnën: + + + DLC Installation + Instalimi i DLC-ve + + + Would you like to install DLC: %1? + Dëshiron të instalosh DLC-në: %1? + + + DLC already installed: + DLC-ja është instaluar tashmë: + + + Game already installed + Loja është instaluar tashmë + + + PKG is a patch, please install the game first! + PKG-ja është një arnë, të lutem instalo lojën fillimisht! + + + PKG ERROR + GABIM PKG + + + Extracting PKG %1/%2 + Po nxirret PKG-ja %1/%2 + + + Extraction Finished + Nxjerrja Përfundoi + + + Game successfully installed at %1 + Loja u instalua me sukses në %1 + + + File doesn't appear to be a valid PKG file + Skedari nuk duket si skedar PKG i vlefshëm + PKGViewer - Open Folder Hap Dosjen @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Shikuesi i Trofeve @@ -458,1119 +509,832 @@ SettingsDialog - Settings Cilësimet - General Të përgjithshme - System Sistemi - Console Language Gjuha e Konsolës - Emulator Language Gjuha e emulatorit - Emulator Emulatori - Enable Fullscreen Aktivizo Ekranin e plotë - Enable Separate Update Folder Aktivizo dosjen e ndarë të përditësimit - Show Splash Shfaq Pamjen e nisjes - Is PS4 Pro Mënyra PS4 Pro - Enable Discord Rich Presence Aktivizo Discord Rich Presence - Username Përdoruesi - + Trophy Key + Çelësi i Trofeve + + + Trophy + Trofeu + + Logger Regjistruesi i ditarit - Log Type Lloji i Ditarit - Log Filter Filtri i Ditarit - + Open Log Location + Hap vendndodhjen e regjistrit + + Input Hyrja - Cursor Kursori - Hide Cursor Fshih kursorin - Hide Cursor Idle Timeout Koha për fshehjen e kursorit joaktiv - + s + s + + Controller Dorezë - Back Button Behavior Sjellja e butonit mbrapa - Graphics Grafika - Graphics Device Pajisja e Grafikës - Width Gjerësia - Height Lartësia - Vblank Divider Ndarës Vblank - Advanced Të përparuara - Enable Shaders Dumping Aktivizo Zbrazjen e Shaders-ave - Enable NULL GPU Aktivizo GPU-në NULL - Paths Shtigjet - Game Folders Dosjet e lojës - Add... Shto... - Remove Hiq - Debug Korrigjim - Enable Debug Dumping Aktivizo Zbrazjen për Korrigjim - Enable Vulkan Validation Layers Aktivizo Shtresat e Vlefshmërisë Vulkan - Enable Vulkan Synchronization Validation Aktivizo Vërtetimin e Sinkronizimit Vulkan - Enable RenderDoc Debugging Aktivizo Korrigjimin RenderDoc - Update Përditëso - Check for Updates at Startup Kontrollo për përditësime në nisje - Update Channel Kanali i përditësimit - Check for Updates Kontrollo për përditësime - GUI Settings - Cilësimet e GUI + Cilësimet e GUI-së - Disable Trophy Pop-ups - Disable Trophy Pop-ups + Çaktivizo njoftimet për Trofetë - Play title music Luaj muzikën e titullit - Update Compatibility Database On Startup - Update Compatibility Database On Startup + Përditëso bazën e të dhënave të përputhshmërisë gjatë nisjes - Game Compatibility - Game Compatibility + Përputhshmëria e lojës - Display Compatibility Data - Display Compatibility Data + Shfaq të dhënat e përputhshmërisë - Update Compatibility Database - Update Compatibility Database + Përditëso bazën e të dhënave të përputhshmërisë - Volume Vëllimi i zërit - - - MainWindow - - Game List - Lista e lojërave + Audio Backend + Audio Backend - - * Unsupported Vulkan Version - * Version i pambështetur i Vulkan - - - - Download Cheats For All Installed Games - Shkarko Mashtrime Për Të Gjitha Lojërat e Instaluara - - - - Download Patches For All Games - Shkarko Arna Për Të Gjitha Lojërat e Instaluara - - - - Download Complete - Shkarkimi Përfundoi - - - - You have downloaded cheats for all the games you have installed. - Ke shkarkuar mashtrimet për të gjitha lojërat që ke instaluar. - - - - Patches Downloaded Successfully! - Arnat u shkarkuan me sukses! - - - - All Patches available for all games have been downloaded. - Të gjitha arnat e ofruara për të gjitha lojërat janë shkarkuar. - - - - Games: - Lojërat: - - - - PKG File (*.PKG) - Skedar PKG (*.PKG) - - - - ELF files (*.bin *.elf *.oelf) - Skedarë ELF (*.bin *.elf *.oelf) - - - - Game Boot - Nis Lojën - - - - Only one file can be selected! - Mund të përzgjidhet vetëm një skedar! - - - - PKG Extraction - Nxjerrja e PKG-së - - - - Patch detected! - U zbulua një arnë! - - - - PKG and Game versions match: - PKG-ja dhe versioni i Lojës përputhen: - - - - Would you like to overwrite? - Dëshiron të mbishkruash? - - - - PKG Version %1 is older than installed version: - Versioni %1 i PKG-së është më i vjetër se versioni i instaluar: - - - - Game is installed: - Loja është instaluar: - - - - Would you like to install Patch: - Dëshiron të instalosh Arnën: - - - - DLC Installation - Instalimi i DLC-ve - - - - Would you like to install DLC: %1? - Dëshiron të instalosh DLC-në: %1? - - - - DLC already installed: - DLC-ja është instaluar tashmë: - - - - Game already installed - Loja është instaluar tashmë - - - - PKG is a patch, please install the game first! - PKG-ja është një arnë, të lutem instalo lojën fillimisht! - - - - PKG ERROR - GABIM PKG - - - - Extracting PKG %1/%2 - Po nxirret PKG-ja %1/%2 - - - - Extraction Finished - Nxjerrja Përfundoi - - - - Game successfully installed at %1 - Loja u instalua me sukses në %1 - - - - File doesn't appear to be a valid PKG file - Skedari nuk duket si skedar PKG i vlefshëm - - - - CheatsPatches - - - Cheats / Patches for - Cheats / Patches for - - - - defaultTextEdit_MSG - Mashtrimet/Arnat janë eksperimentale.\nPërdori me kujdes.\n\nShkarko mashtrimet individualisht duke zgjedhur depon dhe duke klikuar butonin e shkarkimit.\nNë skedën Arna, mund t'i shkarkosh të gjitha arnat menjëherë, të zgjidhësh cilat dëshiron të përdorësh dhe të ruash zgjedhjen tënde.\n\nMeqenëse ne nuk zhvillojmë Mashtrimet/Arnat,\ntë lutem raporto problemet te autori i mashtrimit.\n\nKe krijuar një mashtrim të ri? Vizito:\nhttps://github.com/shadps4-emu/ps4_cheats - - - - No Image Available - Nuk ofrohet asnjë imazh - - - - Serial: - Seriku: - - - - Version: - Versioni: - - - - Size: - Madhësia: - - - - Select Cheat File: - Përzgjidh Skedarin e Mashtrimit: - - - - Repository: - Depo: - - - - Download Cheats - Shkarko Mashtrimet - - - - Delete File - Fshi Skedarin - - - - No files selected. - Nuk u zgjodh asnjë skedar. - - - - You can delete the cheats you don't want after downloading them. - Mund t'i fshish mashtrimet që nuk dëshiron pasi t'i kesh shkarkuar. - - - - Do you want to delete the selected file?\n%1 - Dëshiron të fshish skedarin e përzgjedhur?\n%1 - - - - Select Patch File: - Përzgjidh Skedarin e Arnës: - - - - Download Patches - Shkarko Arnat - - - Save Ruaj - - Cheats - Mashtrime - - - - Patches - Arna - - - - Error - Gabim - - - - No patch selected. - Asnjë arnë e përzgjedhur. - - - - Unable to open files.json for reading. - files.json nuk mund të hapet për lexim. - - - - No patch file found for the current serial. - Nuk u gjet asnjë skedar patch për serikun aktual. - - - - Unable to open the file for reading. - Skedari nuk mund të hapet për lexim. - - - - Unable to open the file for writing. - Skedari nuk mund të hapet për shkrim. - - - - Failed to parse XML: - Analiza e XML-së dështoi: - - - - Success - Sukses - - - - Options saved successfully. - Rregullimet u ruajtën me sukses. - - - - Invalid Source - Burim i pavlefshëm - - - - The selected source is invalid. - Burimi i përzgjedhur është i pavlefshëm. - - - - File Exists - Skedari Ekziston - - - - File already exists. Do you want to replace it? - Skedari ekziston tashmë. Dëshiron ta zëvendësosh? - - - - Failed to save file: - Ruajtja e skedarit dështoi: - - - - Failed to download file: - Shkarkimi i skedarit dështoi: - - - - Cheats Not Found - Mashtrimet nuk u gjetën - - - - CheatsNotFound_MSG - Nuk u gjetën mashtrime për këtë lojë në këtë version të depove të përzgjedhura, provo një depo tjetër ose një version tjetër të lojës. - - - - Cheats Downloaded Successfully - Mashtrimet u shkarkuan me sukses - - - - CheatsDownloadedSuccessfully_MSG - Ke shkarkuar me sukses mashtrimet për këtë version të lojës nga depoja e përzgjedhur. Mund të provosh të shkarkosh nga një depo tjetër, nëse ofrohet do të jetë e mundur gjithashtu ta përdorësh duke përzgjedhur skedarin nga lista. - - - - Failed to save: - Ruajtja dështoi: - - - - Failed to download: - Shkarkimi dështoi: - - - - Download Complete - Shkarkimi përfundoi - - - - DownloadComplete_MSG - Arnat u shkarkuan me sukses! Të gjitha arnat e ofruara për të gjitha lojërat janë shkarkuar, nuk ka nevojë t'i shkarkosh ato individualisht për secilën lojë siç ndodh me Mashtrimet. Nëse arna nuk shfaqet, mund të mos ekzistojë për numrin e serikut dhe versionin specifik të lojës. - - - - Failed to parse JSON data from HTML. - Analiza e të dhënave JSON nga HTML dështoi. - - - - Failed to retrieve HTML page. - Gjetja e faqes HTML dështoi. - - - - The game is in version: %1 - Loja është në versionin: %1 - - - - The downloaded patch only works on version: %1 - Arna e shkarkuar funksionon vetëm në versionin: %1 - - - - You may need to update your game. - Mund të duhet të përditësosh lojën tënde. - - - - Incompatibility Notice - Njoftim për papajtueshmëri - - - - Failed to open file: - Hapja e skedarit dështoi: - - - - XML ERROR: - GABIM XML: - - - - Failed to open files.json for writing - Hapja e files.json për shkrim dështoi - - - - Author: - Autori: - - - - Directory does not exist: - Dosja nuk ekziston: - - - - Failed to open files.json for reading. - Hapja e files.json për lexim dështoi. - - - - Name: - Emri: - - - - Can't apply cheats before the game is started - Nuk mund të zbatohen mashtrime para fillimit të lojës. - - - - SettingsDialog - - - Save - Ruaj - - - Apply Zbato - Restore Defaults Rikthe paracaktimet - Close Mbyll - Point your mouse at an option to display its description. Vendos miun mbi një rregullim për të shfaqur përshkrimin e tij. - consoleLanguageGroupBox Gjuha e konsolës:\nPërcakton gjuhën që përdor loja PS4.\nKëshillohet të caktosh një gjuhë që loja mbështet, e cila do të ndryshojë sipas rajonit. - emulatorLanguageGroupBox Gjuha e emulatorit:\nPërcakton gjuhën e ndërfaqes së përdoruesit të emulatorit. - fullscreenCheckBox Aktivizo ekranin e plotë:\nVendos automatikisht dritaren e lojës në mënyrën e ekranit të plotë.\nKjo mund të aktivizohet duke shtypur tastin F11. - separateUpdatesCheckBox - Aktivizo dosjen e ndarë të përditësimit:\nAktivizon instalimin e përditësimeve të lojërave në dosje të veçanta për menaxhim më të lehtë. + Aktivizo dosjen e ndarë të përditësimit:\nAktivizon instalimin e përditësimeve të lojërave në dosje të veçanta për menaxhim më të lehtë.\nKjo mund të krijohet manualisht duke shtuar përditësimin e shpaketuar në dosjen e lojës me emrin "CUSA00000-UPDATE" ku ID-ja CUSA përputhet me ID-në e lojës. - showSplashCheckBox Shfaq ekranin e ngarkesës:\nShfaq ekranin e ngarkesës së lojës (një pamje e veçantë) gjatë fillimit të lojës. - ps4proCheckBox Është PS4 Pro:\nBën që emulatori të veprojë si një PS4 PRO, gjë që mund të aktivizojë veçori të veçanta në lojrat që e mbështesin. - discordRPCCheckbox Aktivizo Discord Rich Presence:\nShfaq ikonën e emulatorit dhe informacionin përkatës në profilin tënd në Discord. - userName Përdoruesi:\nPërcakton emrin e përdoruesit të llogarisë PS4, i cili mund të shfaqet nga disa lojra. - + TrophyKey + Çelësi i Trofeve:\nÇelësi përdoret për të deshifruar trofetë. Duhet të merret nga konsola jote me jailbreak.\nDuhet të përmbajë vetëm karaktere hex. + + logTypeGroupBox Lloji i ditarit:\nPërcakton nëse të sinkronizohet dalja e dritares së ditarit për performancë. Mund të ketë efekte të këqija në emulim. - logFilter Filtri i ditarit:\nFiltron ditarin për të shfaqur vetëm informacione specifike.\nShembuj: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivelet: Trace, Debug, Info, Warning, Error, Critical - në këtë rend, një nivel specifik hesht të gjitha nivelet përpara në listë dhe regjistron çdo nivel pas atij. - updaterGroupBox Përditësimi:\nRelease: Versionet zyrtare të lëshuara çdo muaj që mund të jenë shumë të vjetra, por janë më të besueshme dhe të provuara.\nNightly: Versionet e zhvillimit që kanë të gjitha veçoritë dhe rregullimet më të fundit, por mund të përmbajnë gabime dhe janë më pak të qëndrueshme. - GUIgroupBox Luaj muzikën e titullit:\nNëse një lojë e mbështet, aktivizohet luajtja e muzikës të veçantë kur të zgjidhësh lojën në GUI. - disableTrophycheckBox - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). + Çaktivizo njoftimet për Trofetë:\nÇaktivizo njoftimet për trofetë gjatë lojës. Përparimi i trofeve mund të ndiqet duke përdorur Shikuesin e Trofeve (kliko me të djathtën mbi lojën në dritaren kryesore). - hideCursorGroupBox - Fsheh kursorin:\nZgjidh kur do të fshihet kursori:\nKurrë: Do ta shohësh gjithmonë miun.\nInaktiv: Vendos një kohë për ta fshehur pas mosveprimit.\nGjithmonë: nuk do ta shohësh kurrë miun. + Fsheh kursorin:\nZgjidh kur do të fshihet kursori:\nKurrë: Do ta shohësh gjithmonë miun.\nJoaktiv: Vendos një kohë për ta fshehur pas mosveprimit.\nGjithmonë: nuk do ta shohësh kurrë miun. - idleTimeoutGroupBox Koha për fshehjen e kursorit joaktiv:\nKohëzgjatja (në sekonda) pas së cilës kursori që nuk ka qënë në veprim fshihet. - backButtonBehaviorGroupBox Sjellja e butonit mbrapa:\nLejon të përcaktohet se në cilën pjesë të tastierës prekëse do të imitojë një prekje butoni mprapa. - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + Shfaq të dhënat e përputhshmërisë:\nShfaq informacionin e përputhshmërisë së lojës në formë tabele. Aktivizo 'Përditëso përputhshmërinë gjatë nisjes' për të marrë informacion të përditësuar. - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + Përditëso përputhshmërinë gjatë nisjes:\nPërditëson automatikisht bazën e të dhënave të përputhshmërisë kur shadPS4 niset. - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. + Përditëso bazën e të dhënave të përputhshmërisë:\nPërditëso menjëherë bazën e të dhënave të përputhshmërisë. - Never Kurrë - Idle Joaktiv - Always Gjithmonë - Touchpad Left Tastiera prekëse majtas - Touchpad Right Tastiera prekëse djathtas - Touchpad Center Tastiera prekëse në qendër - None Asnjë - graphicsAdapterGroupBox Pajisja grafike:\nNë sistemet me GPU të shumëfishta, zgjidh GPU-në që do të përdorë emulatori nga lista rënëse,\nose zgjidh "Auto Select" për ta përcaktuar automatikisht. - resolutionLayout Gjerësia/Lartësia:\nPërcakton madhësinë e dritares së emulatorit në nisje, e cila mund të rregullohet gjatë lojës.\nKjo është ndryshe nga rezolucioni në lojë. - heightDivider Ndarësi Vblank:\nFrekuenca pamore me të cilën rifreskohet emulatori shumëzohet me këtë numër. Ndryshimi i këtij mund të ketë efekte të këqija, si rritja e shpejtësisë së lojës ose prishja e punimit thelbësor të lojës që nuk e pret këtë ndryshim! - dumpShadersCheckBox Aktivizo zbrazjen e shaders-ave:\nPër qëllime të korrigjimit teknik, ruan shaders-at e lojës në një dosje ndërsa ato pasqyrohen. - nullGpuCheckBox Aktivizo GPU-në Null:\nPër qëllime të korrigjimit teknik, çaktivizon pasqyrimin e lojës sikur nuk ka një kartë grafike. - gameFoldersBox Dosjet e lojërave:\nLista e dosjeve për të kontrolluar lojërat e instaluara. - addFolderButton Shto:\nShto një dosje në listë. - removeFolderButton Hiq:\nHiq një dosje nga lista. - debugDump Aktivizo zbrazjen për korrigjim:\nRuan simbolet e importit dhe eksportit dhe informacionin e kreut të skedarit për aplikacionin PS4 që po ekzekutohet në një dosje. - vkValidationCheckBox Aktivizo shtresat e vlefshmërisë Vulkan:\nAktivizon një sistem që vërteton gjendjen e pasqyruesit Vulkan dhe regjistron informacionin në lidhje me gjendjen e tij të brendshme. Kjo do të ul performancën dhe ndoshta do të ndryshojë sjelljen e emulimit. - vkSyncValidationCheckBox Aktivizo vërtetimin e sinkronizimit Vulkan:\nAktivizon një sistem që vërteton kohën e detyrave të pasqyrimit Vulkan. Kjo do të ul performancën dhe ndoshta do të ndryshojë sjelljen e emulimit. - rdocCheckBox Aktivizo korrigjimin RenderDoc:\nNëse aktivizohet, emulatori do të ofrojë pajtueshmëri me Renderdoc për të lejuar kapjen dhe analizën e pamjes të pasqyruar në moment. + + CheatsPatches + + Cheats / Patches for + Mashtrime / Arna për + + + defaultTextEdit_MSG + Mashtrimet/Arnat janë eksperimentale.\nPërdori me kujdes.\n\nShkarko mashtrimet individualisht duke zgjedhur depon dhe duke klikuar butonin e shkarkimit.\nNë skedën Arna, mund t'i shkarkosh të gjitha arnat menjëherë, të zgjidhësh cilat dëshiron të përdorësh dhe të ruash zgjedhjen tënde.\n\nMeqenëse ne nuk zhvillojmë Mashtrimet/Arnat,\ntë lutem raporto problemet te autori i mashtrimit.\n\nKe krijuar një mashtrim të ri? Vizito:\nhttps://github.com/shadps4-emu/ps4_cheats + + + No Image Available + Nuk ofrohet asnjë imazh + + + Serial: + Seriku: + + + Version: + Versioni: + + + Size: + Madhësia: + + + Select Cheat File: + Përzgjidh Skedarin e Mashtrimit: + + + Repository: + Depo: + + + Download Cheats + Shkarko Mashtrimet + + + Delete File + Fshi Skedarin + + + No files selected. + Nuk u zgjodh asnjë skedar. + + + You can delete the cheats you don't want after downloading them. + Mund t'i fshish mashtrimet që nuk dëshiron pasi t'i kesh shkarkuar. + + + Do you want to delete the selected file?\n%1 + Dëshiron të fshish skedarin e përzgjedhur?\n%1 + + + Select Patch File: + Përzgjidh Skedarin e Arnës: + + + Download Patches + Shkarko Arnat + + + Save + Ruaj + + + Cheats + Mashtrime + + + Patches + Arna + + + Error + Gabim + + + No patch selected. + Asnjë arnë e përzgjedhur. + + + Unable to open files.json for reading. + files.json nuk mund të hapet për lexim. + + + No patch file found for the current serial. + Nuk u gjet asnjë skedar patch për serikun aktual. + + + Unable to open the file for reading. + Skedari nuk mund të hapet për lexim. + + + Unable to open the file for writing. + Skedari nuk mund të hapet për shkrim. + + + Failed to parse XML: + Analiza e XML-së dështoi: + + + Success + Sukses + + + Options saved successfully. + Rregullimet u ruajtën me sukses. + + + Invalid Source + Burim i pavlefshëm + + + The selected source is invalid. + Burimi i përzgjedhur është i pavlefshëm. + + + File Exists + Skedari Ekziston + + + File already exists. Do you want to replace it? + Skedari ekziston tashmë. Dëshiron ta zëvendësosh? + + + Failed to save file: + Ruajtja e skedarit dështoi: + + + Failed to download file: + Shkarkimi i skedarit dështoi: + + + Cheats Not Found + Mashtrimet nuk u gjetën + + + CheatsNotFound_MSG + Nuk u gjetën mashtrime për këtë lojë në këtë version të depove të përzgjedhura, provo një depo tjetër ose një version tjetër të lojës. + + + Cheats Downloaded Successfully + Mashtrimet u shkarkuan me sukses + + + CheatsDownloadedSuccessfully_MSG + Ke shkarkuar me sukses mashtrimet për këtë version të lojës nga depoja e përzgjedhur. Mund të provosh të shkarkosh nga një depo tjetër, nëse ofrohet do të jetë e mundur gjithashtu ta përdorësh duke përzgjedhur skedarin nga lista. + + + Failed to save: + Ruajtja dështoi: + + + Failed to download: + Shkarkimi dështoi: + + + Download Complete + Shkarkimi përfundoi + + + DownloadComplete_MSG + Arnat u shkarkuan me sukses! Të gjitha arnat e ofruara për të gjitha lojërat janë shkarkuar, nuk ka nevojë t'i shkarkosh ato individualisht për secilën lojë siç ndodh me Mashtrimet. Nëse arna nuk shfaqet, mund të mos ekzistojë për numrin e serikut dhe versionin specifik të lojës. + + + Failed to parse JSON data from HTML. + Analiza e të dhënave JSON nga HTML dështoi. + + + Failed to retrieve HTML page. + Gjetja e faqes HTML dështoi. + + + The game is in version: %1 + Loja është në versionin: %1 + + + The downloaded patch only works on version: %1 + Arna e shkarkuar funksionon vetëm në versionin: %1 + + + You may need to update your game. + Mund të duhet të përditësosh lojën tënde. + + + Incompatibility Notice + Njoftim për papajtueshmëri + + + Failed to open file: + Hapja e skedarit dështoi: + + + XML ERROR: + GABIM XML: + + + Failed to open files.json for writing + Hapja e files.json për shkrim dështoi + + + Author: + Autori: + + + Directory does not exist: + Dosja nuk ekziston: + + + Failed to open files.json for reading. + Hapja e files.json për lexim dështoi. + + + Name: + Emri: + + + Can't apply cheats before the game is started + Nuk mund të zbatohen mashtrime para fillimit të lojës. + + GameListFrame - Icon Ikona - Name Emri - Serial Seriku - Compatibility - Compatibility + Përputhshmëria - Region Rajoni - Firmware Firmueri - Size Madhësia - Version Versioni - Path Shtegu - Play Time Koha e luajtjes - Never Played - Never Played + Nuk është luajtur kurrë + + + h + o + + + m + m + + + s + s - Compatibility is untested - Compatibility is untested + Përputhshmëria nuk është e testuar - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + Loja nuk niset siç duhet / rrëzon emulatorin - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + Loja niset, por shfaq vetëm një ekran të zbrazët - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + Loja shfaq një imazh, por nuk kalon përtej menysë - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + Loja ka probleme kritike ose performancë të papërshtatshme për lojë - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + Loja mund të përfundohet me performancë të luajtshme dhe pa probleme të mëdha CheckUpdate - Auto Updater Përditësues automatik - Error Gabim - Network error: Gabim rrjeti: - Failed to parse update information. Analizimi i informacionit të përditësimit deshtoi. - No pre-releases found. Nuk u gjetën botime paraprake. - Invalid release data. Të dhënat e lëshimit janë të pavlefshme. - No download URL found for the specified asset. Nuk u gjet URL-ja e shkarkimit për burimin e specifikuar. - Your version is already up to date! Versioni jotë është i përditësuar tashmë! - Update Available Ofrohet një përditësim - Update Channel Kanali i përditësimit - Current Version Versioni i tanishëm - Latest Version Versioni më i fundit - Do you want to update? Do të përditësosh? - Show Changelog Trego ndryshimet - Check for Updates at Startup Kontrollo për përditësime në nisje - Update Përditëso - No Jo - Hide Changelog Fshih ndryshimet - Changes Ndryshimet - Network error occurred while trying to access the URL Ka ndodhur një gabim rrjeti gjatë përpjekjes për të qasur në URL-në - Download Complete Shkarkimi përfundoi - The update has been downloaded, press OK to install. Përditësimi është shkarkuar, shtyp OK për ta instaluar. - Failed to save the update file at Dështoi ruajtja e skedarit të përditësimit në - Starting Update... Po fillon përditësimi... - Failed to create the update script file Krijimi i skedarit skript të përditësimit dështoi - \ No newline at end of file + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + + diff --git a/src/qt_gui/translations/sv.ts b/src/qt_gui/translations/sv.ts new file mode 100644 index 000000000..3a6f060cb --- /dev/null +++ b/src/qt_gui/translations/sv.ts @@ -0,0 +1,1419 @@ + + + + + + AboutDialog + + About shadPS4 + Om shadPS4 + + + shadPS4 + shadPS4 + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 är en experimentell emulator för PlayStation 4 baserad på öppen källkod. + + + This software should not be used to play games you have not legally obtained. + Denna programvara bör inte användas för att spela spel som du inte legalt äger. + + + + CheatsPatches + + Cheats / Patches for + Fusk / Patchar för + + + defaultTextEdit_MSG + Fusk/Patchar är experimentella.\nAnvänd med försiktighet.\n\nHämta fusk individuellt genom att välja förrådet och klicka på hämtningsknappen.\nUnder Patchar-fliken kan du hämta alla patchar på en gång, välj vilken du vill använda och spara ditt val.\n\nEftersom vi inte utvecklar fusk eller patchar,\nrapportera gärna problem till fuskets upphovsperson.\n\nSkapat ett nytt fusk? Besök:\nhttps://github.com/shadps4-emu/ps4_cheats + + + No Image Available + Ingen bild tillgänglig + + + Serial: + Serienummer: + + + Version: + Version: + + + Size: + Storlek: + + + Select Cheat File: + Välj fuskfil: + + + Repository: + Förråd: + + + Download Cheats + Hämta fusk + + + Delete File + Ta bort fil + + + No files selected. + Inga filer valda. + + + You can delete the cheats you don't want after downloading them. + Du kan ta bort fusk som du inte vill ha efter de hämtats ner. + + + Do you want to delete the selected file?\n%1 + Vill du ta bort markerade filen?\n%1 + + + Select Patch File: + Välj patchfil: + + + Download Patches + Hämta patchar + + + Save + Spara + + + Cheats + Fusk + + + Patches + Patchar + + + Error + Fel + + + No patch selected. + Ingen patch vald. + + + Unable to open files.json for reading. + Kunde inte öppna files.json för läsning. + + + No patch file found for the current serial. + Ingen patchfil hittades för aktuella serienumret. + + + Unable to open the file for reading. + Kunde inte öppna filen för läsning. + + + Unable to open the file for writing. + Kunde inte öppna filen för skrivning. + + + Failed to parse XML: + Misslyckades med att tolka XML: + + + Success + Lyckades + + + Options saved successfully. + Inställningarna sparades. + + + Invalid Source + Ogiltig källa + + + The selected source is invalid. + Vald källa är ogiltig. + + + File Exists + Filen finns + + + File already exists. Do you want to replace it? + Filen finns redan. Vill du ersätta den? + + + Failed to save file: + Misslyckades med att spara fil: + + + Failed to download file: + Misslyckades med att hämta filen: + + + Cheats Not Found + Fusk hittades inte + + + CheatsNotFound_MSG + Inga fusk hittades för detta spel i denna version av det valda förrådet. Prova ett annat förråd eller en annan version av spelet + + + Cheats Downloaded Successfully + Fusk hämtades ner + + + CheatsDownloadedSuccessfully_MSG + Du har hämtat ner fusken för denna version av spelet från valt förråd. Du kan försöka att hämta från andra förråd, om de är tillgängliga så kan det vara möjligt att använda det genom att välja det genom att välja filen från listan + + + Failed to save: + Misslyckades med att spara: + + + Failed to download: + Misslyckades med att hämta: + + + Download Complete + Hämtning färdig + + + DownloadComplete_MSG + Patchhämtningen är färdig! Alla patchar tillgängliga för alla spel har hämtats och de behövs inte hämtas individuellt för varje spel som med fusk. Om patchen inte dyker upp kan det bero på att den inte finns för det specifika serienumret och versionen av spelet + + + Failed to parse JSON data from HTML. + Misslyckades med att tolka JSON-data från HTML. + + + Failed to retrieve HTML page. + Misslyckades med att hämta HTML-sida. + + + The game is in version: %1 + Spelet är i version: %1 + + + The downloaded patch only works on version: %1 + Hämtad patch fungerar endast på version: %1 + + + You may need to update your game. + Du kan behöva uppdatera ditt spel. + + + Incompatibility Notice + Inkompatibilitetsmeddelande + + + Failed to open file: + Misslyckades med att öppna filen: + + + XML ERROR: + XML-FEL: + + + Failed to open files.json for writing + Misslyckades med att öppna files.json för skrivning + + + Author: + Upphovsperson: + + + Directory does not exist: + Katalogen finns inte: + + + Failed to open files.json for reading. + Misslyckades med att öppna files.json för läsning. + + + Name: + Namn: + + + Can't apply cheats before the game is started + Kan inte tillämpa fusk innan spelet är startat + + + Error: + Fel: + + + ERROR + FEL + + + + CheckUpdate + + Auto Updater + Automatisk uppdatering + + + Error + Fel + + + Network error: + Nätverksfel: + + + Failed to parse update information. + Misslyckades med att tolka uppdateringsinformationen. + + + No pre-releases found. + Inga förutgåva hittades. + + + Invalid release data. + Ogiltig release-data. + + + No download URL found for the specified asset. + Ingen hämtnings-URL hittades för angiven tillgång. + + + Your version is already up to date! + Din version är redan den senaste! + + + Update Available + Uppdatering tillgänglig + + + Update Channel + Uppdateringskanal + + + Current Version + Aktuell version + + + Latest Version + Senaste version + + + Do you want to update? + Vill du uppdatera? + + + Show Changelog + Visa ändringslogg + + + Check for Updates at Startup + Leta efter uppdateringar vid uppstart + + + Update + Uppdatera + + + No + Nej + + + Hide Changelog + Dölj ändringslogg + + + Changes + Ändringar + + + Network error occurred while trying to access the URL + Nätverksfel inträffade vid försök att komma åt URL:en + + + Download Complete + Hämtning färdig + + + The update has been downloaded, press OK to install. + Uppdateringen har hämtats. Tryck på Ok för att installera. + + + Failed to save the update file at + Misslyckades med att spara uppdateringsfilen i + + + Starting Update... + Startar uppdatering... + + + Failed to create the update script file + Misslyckades med att skapa uppdateringsskriptfil + + + + CompatibilityInfoClass + + Fetching compatibility data, please wait + Hämtar kompatibilitetsdata, vänta + + + Cancel + Avbryt + + + Loading... + Läser in... + + + Error + Fel + + + Unable to update compatibility data! Try again later. + Kunde inte uppdatera kompatibilitetsdata! Försök igen senare. + + + Unable to open compatibility.json for writing. + Kunde inte öppna compatibility.json för skrivning. + + + + ElfViewer + + Open Folder + Öppna mapp + + + + GameInfoClass + + Loading game list, please wait :3 + Läser in spellistan, vänta :3 + + + Cancel + Avbryt + + + Loading... + Läser in... + + + + GameInstallDialog + + shadPS4 - Choose directory + shadPS4 - Välj katalog + + + Directory to install games + Katalog att installera spel till + + + Browse + Bläddra + + + Error + Fel + + + Directory to install DLC + Katalog för att installera DLC + + + + GameListFrame + + Icon + Ikon + + + Name + Namn + + + Serial + Serienummer + + + Compatibility + Kompatibilitet + + + Region + Region + + + Firmware + Firmware + + + Size + Storlek + + + Version + Version + + + Path + Sökväg + + + Play Time + Speltid + + + Never Played + Aldrig spelat + + + h + h + + + m + m + + + s + s + + + Compatibility is untested + Kompatibilitet är otestat + + + Game does not initialize properly / crashes the emulator + Spelet initierar inte korrekt / kraschar emulatorn + + + Game boots, but only displays a blank screen + Spelet startar men visar endast en blank skärm + + + Game displays an image but does not go past the menu + Spelet visar en bild men kommer inte förbi menyn + + + Game has game-breaking glitches or unplayable performance + Spelet har allvarliga problem eller ospelbar prestanda + + + Game can be completed with playable performance and no major glitches + Spelet kan spelas klart med spelbar prestanda och utan större problem + + + Click to go to issue + Klicka för att gå till problem + + + Last updated + Senast uppdaterad + + + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + + + GuiContextMenus + + Create Shortcut + Skapa genväg + + + Cheats / Patches + Fusk / Patchar + + + SFO Viewer + SFO-visare + + + Trophy Viewer + Trofé-visare + + + Open Folder... + Öppna mapp... + + + Open Game Folder + Öppna spelmapp + + + Open Save Data Folder + Öppna mapp för sparat data + + + Open Log Folder + Öppna loggmapp + + + Copy info... + Kopiera till... + + + Copy Name + Kopiera namn + + + Copy Serial + Kopiera serienummer + + + Copy All + Kopiera alla + + + Delete... + Ta bort... + + + Delete Game + Ta bort spel + + + Delete Update + Ta bort uppdatering + + + Delete DLC + Ta bort DLC + + + Compatibility... + Kompatibilitet... + + + Update database + Uppdatera databasen + + + View report + Visa rapport + + + Submit a report + Skicka en rapport + + + Shortcut creation + Skapa genväg + + + Shortcut created successfully! + Genvägen skapades! + + + Error + Fel + + + Error creating shortcut! + Fel vid skapandet av genväg! + + + Install PKG + Installera PKG + + + Game + Spel + + + This game has no update to delete! + Detta spel har ingen uppdatering att ta bort! + + + Update + Uppdatera + + + This game has no DLC to delete! + Detta spel har inga DLC att ta bort! + + + DLC + DLC + + + Delete %1 + Ta bort %1 + + + Are you sure you want to delete %1's %2 directory? + Är du säker på att du vill ta bort %1s %2-katalog? + + + Failed to convert icon. + Misslyckades med att konvertera ikon. + + + + InstallDirSelect + + shadPS4 - Choose directory + shadPS4 - Välj katalog + + + Select which directory you want to install to. + Välj vilken katalog som du vill installera till. + + + + MainWindow + + Open/Add Elf Folder + Öppna/Lägg till Elf-mapp + + + Install Packages (PKG) + Installera paket (PKG) + + + Boot Game + Starta spel + + + Check for Updates + Leta efter uppdateringar + + + About shadPS4 + Om shadPS4 + + + Configure... + Konfigurera... + + + Install application from a .pkg file + Installera program från en .pkg-fil + + + Recent Games + Senaste spel + + + Exit + Avsluta + + + Exit shadPS4 + Avsluta shadPS4 + + + Exit the application. + Avsluta programmet. + + + Show Game List + Visa spellista + + + Game List Refresh + Uppdatera spellista + + + Tiny + Mycket små + + + Small + Små + + + Medium + Medel + + + Large + Stora + + + List View + Listvy + + + Grid View + Rutnätsvy + + + Elf Viewer + Elf-visare + + + Game Install Directory + Installationskatalog för spel + + + Download Cheats/Patches + Hämta fusk/patchar + + + Dump Game List + Dumpa spellista + + + PKG Viewer + PKG-visare + + + Search... + Sök... + + + File + Arkiv + + + View + Visa + + + Game List Icons + Ikoner för spellista + + + Game List Mode + Läge för spellista + + + Settings + Inställningar + + + Utils + Verktyg + + + Themes + Teman + + + Help + Hjälp + + + Dark + Mörk + + + Light + Ljus + + + Green + Grön + + + Blue + Blå + + + Violet + Lila + + + toolBar + toolBar + + + Game List + Spellista + + + * Unsupported Vulkan Version + * Vulkan-versionen stöds inte + + + Download Cheats For All Installed Games + Hämta fusk för alla installerade spel + + + Download Patches For All Games + Hämta patchar för alla spel + + + Download Complete + Hämtning färdig + + + You have downloaded cheats for all the games you have installed. + Du har hämtat fusk till alla spelen som du har installerade. + + + Patches Downloaded Successfully! + Patchar hämtades ner! + + + All Patches available for all games have been downloaded. + Alla patchar tillgängliga för alla spel har hämtats ner. + + + Games: + Spel: + + + ELF files (*.bin *.elf *.oelf) + ELF-filer (*.bin *.elf *.oelf) + + + Game Boot + Starta spel + + + Only one file can be selected! + Endast en fil kan väljas! + + + PKG Extraction + PKG-extrahering + + + Patch detected! + Patch upptäcktes! + + + PKG and Game versions match: + PKG och spelversioner matchar: + + + Would you like to overwrite? + Vill du skriva över? + + + PKG Version %1 is older than installed version: + PKG-versionen %1 är äldre än installerad version: + + + Game is installed: + Spelet är installerat: + + + Would you like to install Patch: + Vill du installera patch: + + + DLC Installation + DLC-installation + + + Would you like to install DLC: %1? + Vill du installera DLC: %1? + + + DLC already installed: + DLC redan installerat: + + + Game already installed + Spelet redan installerat + + + PKG ERROR + PKG-FEL + + + Extracting PKG %1/%2 + Extraherar PKG %1/%2 + + + Extraction Finished + Extrahering färdig + + + Game successfully installed at %1 + Spelet installerades i %1 + + + File doesn't appear to be a valid PKG file + Filen verkar inte vara en giltig PKG-fil + + + Run Game + Kör spel + + + Eboot.bin file not found + Filen eboot.bin hittades inte + + + PKG File (*.PKG *.pkg) + PKG-fil (*.PKG *.pkg) + + + PKG is a patch or DLC, please install the game first! + PKG är en patch eller DLC. Installera spelet först! + + + Game is already running! + Spelet är redan igång! + + + shadPS4 + shadPS4 + + + + PKGViewer + + Open Folder + Öppna mapp + + + &File + &Arkiv + + + PKG ERROR + PKG-FEL + + + + SettingsDialog + + Settings + Inställningar + + + General + Allmänt + + + System + System + + + Console Language + Konsollspråk + + + Emulator Language + Emulatorspråk + + + Emulator + Emulator + + + Enable Fullscreen + Aktivera helskärm + + + Enable Separate Update Folder + Aktivera separat uppdateringsmapp + + + Show Splash + Visa startskärm + + + Enable Discord Rich Presence + Aktivera Discord Rich Presence + + + Username + Användarnamn + + + Trophy Key + Trofényckel + + + Trophy + Trofé + + + Logger + Loggning + + + Log Type + Loggtyp + + + Log Filter + Loggfilter + + + Open Log Location + Öppna loggplats + + + Input + Inmatning + + + Cursor + Pekare + + + Hide Cursor + Dölj pekare + + + Hide Cursor Idle Timeout + Dölj pekare vid overksam + + + s + s + + + Controller + Handkontroller + + + Back Button Behavior + Beteende för bakåtknapp + + + Graphics + Grafik + + + Graphics Device + Grafikenhet + + + Width + Bredd + + + Height + Höjd + + + Vblank Divider + Vblank Divider + + + Advanced + Avancerat + + + Enable Shaders Dumping + Aktivera Shaders Dumping + + + Enable NULL GPU + Aktivera NULL GPU + + + Paths + Sökvägar + + + Game Folders + Spelmappar + + + Add... + Lägg till... + + + Remove + Ta bort + + + Debug + Felsök + + + Enable Debug Dumping + Aktivera felsökningsdumpning + + + Enable Vulkan Validation Layers + Aktivera Vulkan Validation Layers + + + Enable Vulkan Synchronization Validation + Aktivera Vulkan Synchronization Validation + + + Enable RenderDoc Debugging + Aktivera RenderDoc-felsökning + + + Update + Uppdatera + + + Check for Updates at Startup + Leta efter uppdateringar vid uppstart + + + Update Channel + Uppdateringskanal + + + Check for Updates + Leta efter uppdateringar + + + GUI Settings + Gränssnittsinställningar + + + Disable Trophy Pop-ups + Inaktivera popup för troféer + + + Play title music + Spela titelmusik + + + Update Compatibility Database On Startup + Uppdatera databas vid uppstart + + + Game Compatibility + Spelkompatibilitet + + + Display Compatibility Data + Visa kompatibilitetsdata + + + Update Compatibility Database + Uppdatera kompatibilitetsdatabasen + + + Volume + Volym + + + Save + Spara + + + Apply + Verkställ + + + Restore Defaults + Återställ till standard + + + Close + Stäng + + + Point your mouse at an option to display its description. + Peka din mus på ett alternativ för att visa dess beskrivning. + + + consoleLanguageGroupBox + Konsollspråk:\nStäller in språket som PS4-spelet använder.\nDet rekommenderas att ställa in detta till ett språk som spelet har stöd för, vilket kan skilja sig mellan regioner + + + emulatorLanguageGroupBox + Emulatorspråk:\nStäller in språket för emulatorns användargränssnitt + + + fullscreenCheckBox + Aktivera helskärm:\nStäller automatiskt in spelfönstret till helskämsläget.\nDetta kan växlas genom att trycka på F11-tangenten + + + separateUpdatesCheckBox + Aktivera separat uppdateringsmapp:\nAktiverar installation av speluppdateringar i en separat mapp för enkel hantering.\nDetta kan skapas manuellt genom att lägga till uppackad uppdatering till spelmappen med namnet "CUSA00000-UPDATE" där CUSA ID matchar spelets id + + + showSplashCheckBox + Visa startskärm:\nVisar spelets startskärm (en speciell bild) när spelet startas + + + discordRPCCheckbox + Aktivera Discord Rich Presence:\nVisar emulatorikonen och relevant information på din Discord-profil + + + userName + Användarnamn:\nStäller in PS4ans användarkonto, som kan visas av vissa spel + + + TrophyKey + Trofényckel:\nNyckel som används för att avkryptera troféer. Måste hämtas från din konsoll (jailbroken).\nMåste innehålla endast hex-tecken + + + logTypeGroupBox + Loggtyp:\nStäller in huruvida synkronisering av utdata för loggfönstret för prestanda. Kan ha inverkan på emulationen + + + logFilter + Loggfilter:\nFiltrera loggen till att endast skriva ut specifik information.\nExempel: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nNivåer: Trace, Debug, Info, Warning, Error, Critical - i den ordningen, en specifik nivå som tystar alla nivåer före den i listan och loggar allting efter den + + + updaterGroupBox + updaterGroupBox + + + GUIgroupBox + Spela upp titelmusik:\nOm ett spel har stöd för det kan speciell musik spelas upp från spelet i gränssnittet + + + disableTrophycheckBox + Inaktivera popup för troféer:\nInaktivera troféeaviseringar i spel. Troféförlopp kan fortfarande följas med Troféevisaren (högerklicka på spelet i huvudfönstret) + + + hideCursorGroupBox + Dölj pekare:\nVälj när muspekaren ska försvinna:\nAldrig: Du kommer alltid se muspekaren.\nOverksam: Ställ in en tid för när den ska försvinna efter den inte använts.\nAlltid: du kommer aldrig se muspekaren + + + idleTimeoutGroupBox + Dölj pekare vid overksam:\nLängden (sekunder) efter vilken som muspekaren som har varit overksam döljer sig själv + + + backButtonBehaviorGroupBox + Beteende för bakåtknapp:\nStäller in handkontrollerns bakåtknapp för att emulera ett tryck på angivna positionen på PS4ns touchpad + + + enableCompatibilityCheckBox + Visa kompatibilitetsdata:\nVisar information om spelkompatibilitet i tabellvyn. Aktivera "Uppdatera kompatibilitet vid uppstart" för att få uppdaterad information + + + checkCompatibilityOnStartupCheckBox + Uppdatera kompatibilitet vid uppstart:\nUppdatera automatiskt kompatibilitetsdatabasen när shadPS4 startar + + + updateCompatibilityButton + Uppdatera kompatibilitetsdatabasen:\nUppdaterar kompatibilitetsdatabasen direkt + + + Never + Aldrig + + + Idle + Overksam + + + Always + Alltid + + + Touchpad Left + Touchpad vänster + + + Touchpad Right + Touchpad höger + + + Touchpad Center + Touchpad mitten + + + None + Ingen + + + graphicsAdapterGroupBox + Grafikenhet:\nFör system med flera GPUer kan du välja den GPU som emulatorn ska använda från rullgardinsmenyn,\neller välja "Auto Select" för att automatiskt bestämma det + + + resolutionLayout + Bredd/Höjd:\nStäller in storleken för emulatorfönstret vid uppstart, som kan storleksändras under spelning.\nDetta är inte det samma som spelupplösningen + + + heightDivider + Vblank Divider:\nBildfrekvensen som emulatorn uppdaterar vid multipliceras med detta tal. Ändra detta kan ha inverkan på saker, såsom ökad spelhastighet eller göra sönder kritisk spelfunktionalitet, som inte förväntar sig denna ändring + + + dumpShadersCheckBox + Aktivera Shaders Dumping:\nFör teknisk felsökning, sparar spelets shaders till en mapp när de renderas + + + nullGpuCheckBox + Aktivera Null GPU:\nFör teknisk felsökning, inaktiverar spelrenderingen som om det inte fanns något grafikkort + + + gameFoldersBox + Spelmappar:\nListan över mappar att leta i efter installerade spel + + + addFolderButton + Aktivera separat uppdateringsmapp:\nAktiverar installation av speluppdateringar till en separat mapp för enkel hantering.\nDetta kan manuellt skapas genom att lägga till den uppackade uppdateringen till spelmappen med namnet "CUSA00000-UPDATE" där CUSA ID matchar spelets id + + + removeFolderButton + Ta bort:\nTa bort en mapp från listan + + + debugDump + Aktivera felsökningsdumpning:\nSparar import och export av symboler och fil-header-information för aktuellt körande PS4-program till en katalog + + + vkValidationCheckBox + Aktivera Vulkan Validation Layers:\nAktiverar ett system som validerar tillståndet för Vulkan renderer och loggar information om dess interna tillstånd.\nDetta kommer minska prestandan och antagligen ändra beteendet för emuleringen + + + vkSyncValidationCheckBox + Aktivera Vulkan Synchronization Validation:\nAktiverar ett system som validerar timing för Vulkan rendering tasks.\nDetta kommer minska prestandan och antagligen ändra beteendet för emuleringen + + + rdocCheckBox + Aktivera RenderDoc-felsökning:\nOm aktiverad kommer emulatorn att tillhandahålla kompatibilitet med Renderdoc för att tillåta fångst och analys för aktuell renderad bildruta + + + Release + Release + + + Nightly + Nightly + + + Set the volume of the background music. + Ställ in volymen för bakgrundsmusiken. + + + async + asynk + + + sync + synk + + + Directory to install games + Katalog att installera spel till + + + + TrophyViewer + + Trophy Viewer + Trofé-visare + + + diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 33e8d0905..4596000f2 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -6,22 +6,18 @@ AboutDialog - About shadPS4 shadPS4 Hakkında - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. shadPS4, PlayStation 4 için deneysel bir açık kaynak kodlu emülatördür. - 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 +25,6 @@ ElfViewer - Open Folder Klasörü Aç @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Oyun listesi yükleniyor, lütfen bekleyin :3 - Cancel İptal - Loading... Yükleniyor... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Klasörü Seç - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Klasörü Seç - Directory to install games Oyunların yükleneceği klasör - Browse Gözat - Error Hata - 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Kısayol Oluştur - Cheats / Patches Hileler / Yamanlar - SFO Viewer SFO Görüntüleyici - Trophy Viewer Kupa Görüntüleyici - Open Folder... Klasörü Aç... - Open Game Folder Oyun Klasörünü Aç - Open Save Data Folder Kaydetme Verileri Klasörünü Aç - Open Log Folder Log Klasörünü Aç - Copy info... Bilgiyi Kopyala... - Copy Name Adı Kopyala - Copy Serial Seri Numarasını Kopyala - Copy All Tümünü Kopyala - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Kısayol oluşturma - - Shortcut created successfully!\n %1 - Kısayol başarıyla oluşturuldu!\n %1 + Shortcut created successfully! + Kısayol başarıyla oluşturuldu! - Error Hata - - Error creating shortcut!\n %1 - Kısayol oluşturulurken hata oluştu!\n %1 + Error creating shortcut! + Kısayol oluşturulurken hata oluştu! - Install PKG PKG Yükle - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Elf Klasörünü Aç/Ekle - Install Packages (PKG) Paketleri Kur (PKG) - Boot Game Oyunu Başlat - Check for Updates Güncellemeleri kontrol et - About shadPS4 shadPS4 Hakkında - Configure... Yapılandır... - Install application from a .pkg file .pkg dosyasından uygulama yükle - Recent Games Son Oyunlar - Exit Çıkış - Exit shadPS4 shadPS4'ten Çık - Exit the application. Uygulamadan çık. - Show Game List Oyun Listesini Göster - Game List Refresh Oyun Listesini Yenile - Tiny Küçük - Small Ufak - Medium Orta - Large Büyük - List View Liste Görünümü - Grid View Izgara Görünümü - Elf Viewer Elf Görüntüleyici - Game Install Directory Oyun Kurulum Klasörü - Download Cheats/Patches Hileleri/Yamaları İndir - Dump Game List Oyun Listesini Kaydet - PKG Viewer PKG Görüntüleyici - Search... Ara... - File Dosya - View Görünüm - Game List Icons Oyun Listesi Simgeleri - Game List Mode Oyun Listesi Modu - Settings Ayarlar - Utils Yardımcı Araçlar - Themes Temalar - Help Yardım - Dark Koyu - Light Açık - Green Yeşil - Blue Mavi - Violet Mor - toolBar Araç Çubuğu + + Game List + Oyun Listesi + + + * 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 Yamaları İ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! + Yama tespit edildi! + + + PKG and Game versions match: + PKG ve oyun sürümleri uyumlu: + + + Would you like to overwrite? + Ü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 Yükleme + + + 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ü + + + 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 + PKGViewer - Open Folder Klasörü Aç @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Kupa Görüntüleyici @@ -458,989 +509,704 @@ SettingsDialog - Settings Ayarlar - General Genel - System Sistem - Console Language Konsol Dili - Emulator Language Emülatör Dili - Emulator Emülatör - Enable Fullscreen Tam Ekranı Etkinleştir - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Başlangıç Ekranını Göster - Is PS4 Pro PS4 Pro - Enable Discord Rich Presence Discord Rich Presence'i etkinleştir - Username Kullanıcı Adı - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Kayıt Tutucu - Log Type Kayıt Türü - Log Filter Kayıt Filtresi - + Open Log Location + Günlük Konumunu Aç + + Input Girdi - Cursor İmleç - Hide Cursor İmleci Gizle - Hide Cursor Idle Timeout İmleç İçin Hareketsizlik Zaman Aşımı - + s + s + + Controller Kontrolcü - Back Button Behavior Geri Dön Butonu Davranışı - Graphics Grafikler - Graphics Device Grafik Cihazı - Width Genişlik - Height Yükseklik - Vblank Divider Vblank Bölücü - Advanced Gelişmiş - Enable Shaders Dumping Shader Kaydını Etkinleştir - Enable NULL GPU NULL GPU'yu Etkinleştir - Paths Yollar - Game Folders Oyun Klasörleri - Add... Ekle... - Remove Kaldır - Debug Hata Ayıklama - Enable Debug Dumping Hata Ayıklama Dökümü Etkinleştir - Enable Vulkan Validation Layers Vulkan Doğrulama Katmanlarını Etkinleştir - Enable Vulkan Synchronization Validation Vulkan Senkronizasyon Doğrulamasını Etkinleştir - Enable RenderDoc Debugging RenderDoc Hata Ayıklamayı Etkinleştir - Update Güncelle - Check for Updates at Startup Başlangıçta güncellemeleri kontrol et - Update Channel Güncelleme Kanalı - Check for Updates Güncellemeleri Kontrol Et - GUI Settings GUI Ayarları - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Başlık müziğini çal - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Ses seviyesi - - - MainWindow - - Game List - Oyun Listesi + Audio Backend + Audio Backend - - * 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 Yamaları İ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! - Yama tespit edildi! - - - - PKG and Game versions match: - PKG ve oyun sürümleri uyumlu: - - - - Would you like to overwrite? - Ü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 Yükleme - - - - 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ü - - - - 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 for - Cheats / Patches for - - - - 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 - - - - Delete File - Dosyayı Sil - - - - No files selected. - Hiçbir dosya seçilmedi. - - - - 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ı 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. Yamanın görünmemesi durumunda, belirli seri numarası ve oyun sürümü için mevcut olmayabilir. - - - - Failed to parse JSON data from HTML. - HTML'den JSON verileri ayrıştırılamadı. - - - - Failed to retrieve HTML page. - HTML sayfası alınamadı. - - - - The game is in version: %1 - Oyun sürümde: %1 - - - - The downloaded patch only works on version: %1 - İndirilen yamanın sadece sürümde çalışıyor: %1 - - - - You may need to update your game. - Oyunuzu güncellemeniz gerekebilir. - - - - Incompatibility Notice - Uyumsuzluk Bildirimi - - - - 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: - - - - Can't apply cheats before the game is started - Hileleri oyuna başlamadan önce uygulayamazsınız. - - - - SettingsDialog - - - Save - Kaydet - - - Apply Uygula - Restore Defaults Varsayılanları Geri Yükle - Close Kapat - Point your mouse at an option to display its description. Seçenek üzerinde farenizi tutarak açıklamasını görüntüleyin. - consoleLanguageGroupBox Konsol Dili:\nPS4 oyununun kullandığı dili ayarlar.\nBu seçeneği, oyunun desteklediği bir dilde ayarlamanız önerilir; bu durum bölgeye göre değişebilir. - emulatorLanguageGroupBox Emülatör Dili:\nEmülatörün kullanıcı arayüzünün dilini ayarlar. - fullscreenCheckBox Tam Ekranı Etkinleştir:\nOyun penceresini otomatik olarak tam ekran moduna alır.\nBu, F11 tuşuna basarak geçiş yapılabilir. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Açılış Ekranını Göster:\nOyun açılırken (özel bir görüntü) açılış ekranını gösterir. - ps4proCheckBox PS4 Pro:\nEmülatörü bir PS4 PRO gibi çalıştırır; bu, bunu destekleyen oyunlarda özel özellikleri etkinleştirebilir. - discordRPCCheckbox Discord Rich Presence'i etkinleştir:\nEmülatör simgesini ve Discord profilinizdeki ilgili bilgileri gösterir. - userName Kullanıcı Adı:\nBazı oyunlar tarafından gösterilebilen PS4 hesabının kullanıcı adını ayarlar. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Günlük Türü:\nPerformans için günlük penceresi çıkışını senkronize etme durumunu ayarlar. Bu, emülasyonda olumsuz etkilere yol açabilir. - logFilter Günlük Filtre:\nSadece belirli bilgileri yazdırmak için günlüğü filtreler.\nÖrnekler: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Düzeyler: Trace, Debug, Info, Warning, Error, Critical - bu sırada, belirli bir seviye listede önceki tüm seviyeleri susturur ve sonraki tüm seviyeleri kaydeder. - updaterGroupBox Güncelleme:\nRelease: Her ay yayınlanan resmi sürümler; çok eski olabilirler, ancak daha güvenilirdir ve test edilmiştir.\nNightly: Tüm en son özellikler ve düzeltmeler ile birlikte geliştirme sürümleri; hatalar içerebilir ve daha az kararlıdırlar. - GUIgroupBox Başlık Müziklerini Çal:\nEğer bir oyun bunu destekliyorsa, GUI'de oyunu seçtiğinizde özel müziklerin çalmasını etkinleştirir. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox İmleci gizle:\nİmlecin ne zaman kaybolacağını seçin:\nAsla: Fareyi her zaman göreceksiniz.\nPasif: Hareketsiz kaldıktan sonra kaybolması için bir süre belirleyin.\nHer zaman: fareyi asla göremeyeceksiniz. - idleTimeoutGroupBox Hareket etmeden sonra imlecin kaybolacağı süreyi ayarlayın. - backButtonBehaviorGroupBox Geri düğmesi davranışı:\nKontrol cihazındaki geri düğmesini, PS4'ün dokunmatik panelindeki belirlenen noktaya dokunmak için ayarlar. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Asla - Idle Boşta - Always Her zaman - Touchpad Left Dokunmatik Yüzey Sol - Touchpad Right Dokunmatik Yüzey Sağ - Touchpad Center Dokunmatik Yüzey Orta - None Yok - graphicsAdapterGroupBox Grafik Aygıtı:\nBirden fazla GPU'ya sahip sistemlerde, emülatörün kullanacağı GPU'yu açılır listeden seçin,\nor "Auto Select" seçeneğini seçerek otomatik olarak belirlenmesini sağlayın. - resolutionLayout Genişlik/Yükseklik:\nEmülatör penceresinin açılışta boyutunu ayarlar; bu, oyun sırasında yeniden boyutlandırılabilir.\nBu, oyundaki çözünürlükten farklıdır. - heightDivider Vblank Bölücü:\nEmülatörün yenileme hızı bu sayı ile çarpılır. Bu değerin değiştirilmesi olumsuz etkilere yol açabilir; oyun hızını artırabilir veya oyunun beklemediği kritik işlevselliği bozabilir! - dumpShadersCheckBox Shader'ları Dışa Aktarmayı Etkinleştir:\nTeknik hata ayıklama amacıyla, shader'ları render edildikçe bir klasöre kaydeder. - nullGpuCheckBox Null GPU'yu Etkinleştir:\nTeknik hata ayıklama amacıyla, oyunun render edilmesini grafik kartı yokmuş gibi devre dışı bırakır. - gameFoldersBox Oyun klasörleri:\nYüklenmiş oyunları kontrol etmek için klasörlerin listesi. - addFolderButton Ekle:\nListeye bir klasör ekle. - removeFolderButton Kaldır:\nListeden bir klasörü kaldır. - debugDump Hata Ayıklama için Dışa Aktarmayı Etkinleştir:\nŞu anda çalışan PS4 uygulaması için içe aktarılan ve dışa aktarılan sembolleri ve dosya başlık bilgilerini bir dizine kaydedin. - vkValidationCheckBox Vulkan Doğrulama Katmanlarını Etkinleştir:\nVulkan renderlayıcısının durumunu doğrulayan ve iç durum hakkında bilgi kaydeden bir sistemi etkinleştirir. Bu, performansı düşürür ve muhtemelen emülasyon davranışını değiştirir. - vkSyncValidationCheckBox Vulkan Senkronizasyon Doğrulamasını Etkinleştir:\nVulkan renderlama görevlerinin senkronizasyonunu doğrulayan bir sistemi etkinleştirir. Bu, performansı düşürür ve muhtemelen emülasyon davranışını değiştirir. - rdocCheckBox RenderDoc Hata Ayıklamayı Etkinleştir:\nEğer etkinleştirilirse, emülatör mevcut render edilmiş çerçeveyi yakalamak ve analiz etmek için Renderdoc ile uyumluluk sunar. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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 + + + Delete File + Dosyayı Sil + + + No files selected. + Hiçbir dosya seçilmedi. + + + 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ı 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. Yamanın görünmemesi durumunda, belirli seri numarası ve oyun sürümü için mevcut olmayabilir. + + + Failed to parse JSON data from HTML. + HTML'den JSON verileri ayrıştırılamadı. + + + Failed to retrieve HTML page. + HTML sayfası alınamadı. + + + The game is in version: %1 + Oyun sürümde: %1 + + + The downloaded patch only works on version: %1 + İndirilen yamanın sadece sürümde çalışıyor: %1 + + + You may need to update your game. + Oyunuzu güncellemeniz gerekebilir. + + + Incompatibility Notice + Uyumsuzluk Bildirimi + + + 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: + + + Can't apply cheats before the game is started + Hileleri oyuna başlamadan önce uygulayamazsınız. + + GameListFrame - Icon Simge - Name Ad - Serial Seri Numarası - Compatibility Compatibility - Region Bölge - Firmware Yazılım - Size Boyut - Version Sürüm - Path Yol - Play Time Oynama Süresi - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Otomatik Güncelleyici - Error Hata - Network error: Ağ hatası: - Failed to parse update information. Güncelleme bilgilerini ayrıştırma başarısız oldu. - No pre-releases found. Ön sürüm bulunamadı. - Invalid release data. Geçersiz sürüm verisi. - No download URL found for the specified asset. Belirtilen varlık için hiçbir indirme URL'si bulunamadı. - Your version is already up to date! Versiyonunuz zaten güncel! - Update Available Güncelleme Mevcut - Update Channel Güncelleme Kanalı - Current Version Mevcut Versiyon - Latest Version Son Versiyon - Do you want to update? Güncellemek istiyor musunuz? - Show Changelog Değişiklik Günlüğünü Göster - Check for Updates at Startup Başlangıçta güncellemeleri kontrol et - Update Güncelle - No Hayır - Hide Changelog Değişiklik Günlüğünü Gizle - Changes Değişiklikler - Network error occurred while trying to access the URL URL'ye erişmeye çalışırken bir ağ hatası oluştu - Download Complete İndirme Tamamlandı - The update has been downloaded, press OK to install. Güncelleme indirildi, yüklemek için Tamam'a basın. - Failed to save the update file at Güncelleme dosyası kaydedilemedi - Starting Update... Güncelleme Başlatılıyor... - Failed to create the update script file Güncelleme betiği dosyası oluşturulamadı + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/qt_gui/translations/uk_UA.ts b/src/qt_gui/translations/uk_UA.ts index 88d852474..5b260050e 100644 --- a/src/qt_gui/translations/uk_UA.ts +++ b/src/qt_gui/translations/uk_UA.ts @@ -6,22 +6,18 @@ 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. Це програмне забезпечення не повинно використовуватися для запуску ігор, котрі ви отримали не легально. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Відкрити папку @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Завантажуємо список ігор, будь ласка, зачекайте :3 - Cancel Відмінити - Loading... Завантаження... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Виберіть папку - Select which directory you want to install to. Виберіть папку, до якої ви хочете встановити. @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - Виберіть папку - Directory to install games Папка для встановлення ігор - Browse Обрати - Error Помилка - The value for location to install games is not valid. Не коректне значення розташування для встановлення ігор. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Створити Ярлик - Cheats / Patches Чити та Патчі - SFO Viewer Перегляд SFO - Trophy Viewer Перегляд трофеїв - Open Folder... Відкрити Папку... - Open Game Folder Відкрити папку з грою - Open Save Data Folder Відкрити Папку Збережених Даних - Open Log Folder Відкрити Папку Логів - Copy info... Копіювати інформацію... - Copy Name Копіювати Ім’я - Copy Serial Копіювати серійний номер - Copy All Копіювати все - Delete... Видалення... - Delete Game Видалити гру - Delete Update Видалити оновлення - Delete DLC Видалити DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Створення ярлика - - Shortcut created successfully!\n %1 - Ярлик створений успішно!\n %1 + Shortcut created successfully! + Ярлик створений успішно! - Error Помилка - - Error creating shortcut!\n %1 - Помилка при створенні ярлика!\n %1 + Error creating shortcut! + Помилка при створенні ярлика! - Install PKG Встановити PKG - Game Ігри - requiresEnableSeparateUpdateFolder_MSG Ця функція потребує увімкнути опцію 'Окрема папка оновлень'. Якщо ви хочете використовувати цю функцію, будь ласка, увімкніть її. - This game has no update to delete! Ця гра не має оновлень для видалення! - - + Update Оновлення - This game has no DLC to delete! Ця гра не має DLC для видалення! - DLC DLC - Delete %1 Видалити %1 - Are you sure you want to delete %1's %2 directory? Ви впевнені, що хочете видалити папку %1 з папки %2?? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Відкрити/Додати папку Elf - Install Packages (PKG) Встановити пакети (PKG) - Boot Game Запустити гру - Check for Updates Перевити наявність оновлень - 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 Теми - Help Допомога - Dark Темна - Light Світла - Green Зелена - Blue Синя - Violet Фіолетова - toolBar Панель інструментів + + Game List + Список ігор + + + * 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 - це патч, будь ласка, спочатку встановіть гру! + + + 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 Відкрити папку @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Трофеї @@ -458,989 +509,704 @@ SettingsDialog - Settings Налаштування - General Загальні - System Система - Console Language Мова консолі - Emulator Language Мова емулятора - Emulator Емулятор - Enable Fullscreen Увімкнути повноекранний режим - Enable Separate Update Folder Увімкнути окрему папку оновлень - Show Splash Показувати заставку - Is PS4 Pro Режим PS4 Pro - Enable Discord Rich Presence Увімкнути Discord Rich Presence - Username Ім'я користувача - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Логування - Log Type Тип логів - Log Filter Фільтр логів - + Open Log Location + Відкрити місце розташування журналу + + Input Введення - Cursor Курсор миші - Hide Cursor Приховати курсор - Hide Cursor Idle Timeout Тайм-аут приховування курсора при бездіяльності - + s + s + + Controller Контролер - Back Button Behavior Поведінка кнопки назад - Graphics Графіка - Graphics Device Графічний пристрій - Width Ширина - Height Висота - Vblank Divider Розділювач Vblank - Advanced Розширені - Enable Shaders Dumping Увімкнути дамп шейдерів - Enable NULL GPU Увімкнути NULL GPU - Paths Шляхи - Game Folders Ігрові папки - Add... Додати... - Remove Видалити - Debug Налагодження - Enable Debug Dumping Увімкнути налагоджувальні дампи - Enable Vulkan Validation Layers Увімкнути шари валідації Vulkan - Enable Vulkan Synchronization Validation Увімкнути валідацію синхронізації Vulkan - Enable RenderDoc Debugging Увімкнути налагодження RenderDoc - Update Оновлення - Check for Updates at Startup Перевірка оновлень під час запуску - Update Channel Канал оновлення - Check for Updates Перевірити оновлення - GUI Settings Інтерфейс - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Програвати заголовну музику - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Гучність - - - MainWindow - - Game List - Список ігор + Audio Backend + Audio Backend - - * 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 - це патч, будь ласка, спочатку встановіть гру! - - - - 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 for - Cheats / Patches for - - - - 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. - Не вдалося розібрати JSON-дані з HTML. - - - - Failed to retrieve HTML page. - Не вдалося отримати HTML-сторінку. - - - - The game is in version: %1 - Гра у версії: %1 - - - - The downloaded patch only works on version: %1 - Завантажений патч працює лише на версії: %1 - - - - You may need to update your game. - Можливо, вам потрібно оновити гру. - - - - Incompatibility Notice - Повідомлення про несумісність - - - - 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: - Ім'я: - - - - Can't apply cheats before the game is started - Неможливо застосовувати чити до початку гри. - - - - SettingsDialog - - - Save - Зберегти - - - Apply Застосувати - Restore Defaults За замовчуванням - Close Закрити - Point your mouse at an option to display its description. Наведіть курсор миші на опцію, щоб відобразити її опис. - consoleLanguageGroupBox Мова консолі:\nВстановіть мову, яка буде використовуватись у іграх PS4.\nРекомендується встановити мову котра підтримується грою, оскільки вона може відрізнятися в залежності від регіону. - emulatorLanguageGroupBox Мова емулятора:\nВстановіть мову користувацького інтерфейсу емулятора. - fullscreenCheckBox Повноекранний режим:\nАвтоматично переводить вікно гри у повноекранний режим.\nВи можете відключити це, натиснувши клавішу F11. - separateUpdatesCheckBox Окрема папка для оновлень:\nДає змогу встановлювати оновлення гри в окрему папку для зручності. - showSplashCheckBox Показувати заставку:\nВідображає заставку гри (спеціальне зображення) під час запуску гри. - ps4proCheckBox Режим PS4 Pro:\nЗмушує емулятор працювати як PS4 Pro, що може ввімкнути спеціальні функції в іграх, які підтримують це. - discordRPCCheckbox Увімкнути Discord Rich Presence:\nВідображає значок емулятора та відповідну інформацію у вашому профілі Discord. - userName Ім'я користувача:\nВстановіть ім'я користувача акаунта PS4. Це може відображатися в деяких іграх. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Тип логів:\nВстановіть, чи синхронізувати виведення вікна логів заради продуктивності. Це може негативно вплинути на емуляцію. - logFilter Фільтр логів:\nФільтрує логи, щоб показувати тільки певну інформацію.\nПриклади: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Рівні: Trace, Debug, Info, Warning, Error, Critical - у цьому порядку, конкретний рівень глушить усі попередні рівні у списку і показує всі наступні рівні. - updaterGroupBox Оновлення:\nRelease: Офіційні версії, які випускаються щомісяця і можуть бути дуже старими, але вони більш надійні та перевірені.\nNightly: Версії для розробників, які мають усі найновіші функції та виправлення, але можуть містити помилки та є менш стабільними. - GUIgroupBox Грати заголовну музику:\nВмикає відтворення спеціальної музики під час вибору гри в списку, якщо вона це підтримує. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Приховувати курсор:\nВиберіть, коли курсор зникне:\nНіколи: Ви завжди будете бачити мишу.\nПри бездіяльності: Встановіть час, через який курсор зникне в разі бездіяльності.\nЗавжди: Ви ніколи не будете бачити мишу. - idleTimeoutGroupBox Встановіть час, через який курсор зникне в разі бездіяльності. - backButtonBehaviorGroupBox Поведінка кнопки «Назад»:\nНалаштовує кнопку «Назад» контролера на емуляцію натискання на зазначену область на сенсорній панелі контролера PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Ніколи - Idle При бездіяльності - Always Завжди - Touchpad Left Тачпад ліворуч - Touchpad Right Тачпад праворуч - Touchpad Center Тачпад по центру - None Ні - graphicsAdapterGroupBox Графічний пристрій:\nУ системах із кількома GPU виберіть з випадаючого списку GPU, який буде використовувати емулятор,\nабо виберіть "Auto Select", щоб визначити його автоматично. - resolutionLayout Ширина/Висота:\nВстановіть розмір вікна емулятора під час запуску, який може бути змінений під час гри.\nЦе відрізняється від роздільної здатності в грі. - heightDivider Розділювач Vblank:\nЧастота кадрів, з якою оновлюється емулятор, множиться на це число. Зміна цього параметра може мати негативні наслідки, такі як збільшення швидкості гри або порушення критичних функцій гри, які цього не очікують! - dumpShadersCheckBox Увімкнути дамп шейдерів:\nДля технічного налагодження зберігає шейдери ігор у папку під час рендерингу. - nullGpuCheckBox Увімкнути NULL GPU:\nДля технічного налагодження відключає рендеринг гри так, ніби графічної карти немає. - gameFoldersBox Ігрові папки:\nСписок папок для перевірки встановлених ігор. - addFolderButton Додати:\nДодати папку в список. - removeFolderButton Видалити:\nВидалити папку зі списку. - debugDump Увімкнути налагоджувальні дампи:\nЗберігає символи імпорту, експорту та інформацію про заголовок файлу поточної виконуваної програми PS4 у папку. - vkValidationCheckBox Увімкнути шари валідації Vulkan:\nВключає систему, яка перевіряє стан рендерера Vulkan і логує інформацію про його внутрішній стан. Це знизить продуктивність і, ймовірно, змінить поведінку емуляції. - vkSyncValidationCheckBox Увімкнути валідацію синхронізації Vulkan:\nВключає систему, яка перевіряє таймінг завдань рендерингу Vulkan. Це знизить продуктивність і, ймовірно, змінить поведінку емуляції. - rdocCheckBox Увімкнути налагодження RenderDoc:\nЯкщо увімкнено, емулятор забезпечить сумісність із Renderdoc, даючи змогу захоплювати й аналізувати поточні кадри під час рендерингу. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. + Не вдалося розібрати JSON-дані з HTML. + + + Failed to retrieve HTML page. + Не вдалося отримати HTML-сторінку. + + + The game is in version: %1 + Гра у версії: %1 + + + The downloaded patch only works on version: %1 + Завантажений патч працює лише на версії: %1 + + + You may need to update your game. + Можливо, вам потрібно оновити гру. + + + Incompatibility Notice + Повідомлення про несумісність + + + 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: + Ім'я: + + + Can't apply cheats before the game is started + Неможливо застосовувати чити до початку гри. + + GameListFrame - Icon Значок - Name Назва - Serial Серійний номер - Compatibility Compatibility - Region Регіон - Firmware Прошивка - Size Розмір - Version Версія - Path Шлях - Play Time Час у грі - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Автооновлення - Error Помилка - Network error: Мережева помилка: - Failed to parse update information. Не вдалося розібрати інформацію про оновлення. - No pre-releases found. Попередніх версій не знайдено. - Invalid release data. Неприпустимі дані релізу. - No download URL found for the specified asset. Не знайдено URL для завантаження зазначеного ресурсу. - Your version is already up to date! Вашу версію вже оновлено! - Update Available Доступне оновлення - Update Channel Канал оновлення - Current Version Поточна версія - Latest Version Остання версія - Do you want to update? Ви хочете оновитися? - Show Changelog Показати журнал змін - Check for Updates at Startup Перевірка оновлень під час запуску - Update Оновитись - No Ні - Hide Changelog Приховати журнал змін - Changes Журнал змін - Network error occurred while trying to access the URL Сталася мережева помилка під час спроби доступу до URL - Download Complete Завантаження завершено - The update has been downloaded, press OK to install. Оновлення завантажено, натисніть OK для встановлення. - Failed to save the update file at Не вдалося зберегти файл оновлення в - Starting Update... Початок оновлення... - Failed to create the update script file Не вдалося створити файл скрипта оновлення + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 a0a316df3..7fcac6d7e 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Mẹo / Bản vá - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... Mở Thư Mục... - Open Game Folder Mở Thư Mục Trò Chơi - Open Save Data Folder Mở Thư Mục Dữ Liệu Lưu - Open Log Folder Mở Thư Mục Nhật Ký - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates Kiểm tra bản cập nhật - 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 - Download Cheats/Patches Tải Mẹo / Bản vá - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help Giúp đỡ - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + Danh sách trò chơi + + + * 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! + Đã phát hiện bản vá! + + + PKG and Game versions match: + Các phiên bản PKG và trò chơi khớp nhau: + + + Would you like to overwrite? + Bạn có muốn ghi đè không? + + + PKG Version %1 is older than installed version: + Phiên bản PKG %1 cũ hơn phiên bản đã cài đặt: + + + Game is installed: + Trò chơi đã được cài đặt: + + + Would you like to install Patch: + Bạn có muốn cài đặt bản vá: + + + DLC Installation + Cài đặt DLC + + + 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! + 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ệ + PKGViewer - Open Folder Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence Bật Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + Mở vị trí nhật ký + + Input Đầu vào - Cursor Con trỏ - Hide Cursor Ẩn con trỏ - Hide Cursor Idle Timeout Thời gian chờ ẩn con trỏ - + s + s + + Controller Điều khiển - Back Button Behavior Hành vi nút quay lại - 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 - Paths Đường dẫn - Game Folders Thư mục trò chơi - Add... Thêm... - Remove Xóa - 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 - Update Cập nhật - Check for Updates at Startup Kiểm tra cập nhật khi khởi động - Update Channel Kênh Cập Nhật - Check for Updates Kiểm tra cập nhật - GUI Settings Cài đặt GUI - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music Phát nhạc tiêu đề - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume Âm lượng - - - MainWindow - - Game List - Danh sách trò chơi + Audio Backend + Audio Backend - - * 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! - Đã phát hiện bản vá! - - - - PKG and Game versions match: - Các phiên bản PKG và trò chơi khớp nhau: - - - - Would you like to overwrite? - Bạn có muốn ghi đè không? - - - - PKG Version %1 is older than installed version: - Phiên bản PKG %1 cũ hơn phiên bản đã cài đặt: - - - - Game is installed: - Trò chơi đã được cài đặt: - - - - Would you like to install Patch: - Bạn có muốn cài đặt bản vá: - - - - DLC Installation - Cài đặt DLC - - - - 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! - 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 for - Cheats / Patches for - - - - 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. Nếu bản vá không xuất hiện, có thể là nó không tồn tại cho số seri và phiên bản cụ thể của trò chơi. - - - - 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. - - - - The game is in version: %1 - Trò chơi đang ở phiên bản: %1 - - - - The downloaded patch only works on version: %1 - Patch đã tải về chỉ hoạt động trên phiên bản: %1 - - - - You may need to update your game. - Bạn có thể cần cập nhật trò chơi của mình. - - - - Incompatibility Notice - Thông báo không tương thích - - - - 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: - - - - Can't apply cheats before the game is started - Không thể áp dụng cheat trước khi trò chơi bắt đầu. - - - - SettingsDialog - - - Save - Lưu - - - Apply Áp dụng - Restore Defaults Khôi phục cài đặt mặc định - Close Đóng - Point your mouse at an option to display its description. Di chuyển chuột đến tùy chọn để hiển thị mô tả của nó. - consoleLanguageGroupBox Ngôn ngữ console:\nChọn ngôn ngữ mà trò chơi PS4 sẽ sử dụng.\nKhuyên bạn nên đặt tùy chọn này thành một ngôn ngữ mà trò chơi hỗ trợ, có thể thay đổi tùy theo vùng. - emulatorLanguageGroupBox Ngôn ngữ của trình giả lập:\nChọn ngôn ngữ của giao diện người dùng của trình giả lập. - fullscreenCheckBox Bật chế độ toàn màn hình:\nTự động đặt cửa sổ trò chơi ở chế độ toàn màn hình.\nĐiều này có thể bị vô hiệu hóa bằng cách nhấn phím F11. - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox Hiển thị màn hình khởi động:\nHiển thị màn hình khởi động của trò chơi (một hình ảnh đặc biệt) trong khi trò chơi khởi động. - ps4proCheckBox Là PS4 Pro:\nKhiến trình giả lập hoạt động như một PS4 PRO, điều này có thể kích hoạt các tính năng đặc biệt trong các trò chơi hỗ trợ điều này. - discordRPCCheckbox Bật Discord Rich Presence:\nHiển thị biểu tượng trình giả lập và thông tin liên quan trên hồ sơ Discord của bạn. - userName Tên người dùng:\nChọn tên người dùng của tài khoản PS4, có thể được một số trò chơi hiển thị. - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox Loại nhật ký:\nChọn xem có đồng bộ hóa đầu ra cửa sổ nhật ký cho hiệu suất hay không. Điều này có thể có tác động tiêu cực đến việc giả lập. - logFilter Bộ lọc nhật ký:\nLọc nhật ký để in chỉ thông tin cụ thể.\nVí dụ: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Các mức: Trace, Debug, Info, Warning, Error, Critical - theo thứ tự này, một mức cụ thể làm tắt tất cả các mức trước trong danh sách và ghi lại tất cả các mức sau đó. - updaterGroupBox Cập nhật:\nRelease: Các phiên bản chính thức được phát hành hàng tháng; có thể khá cũ nhưng đáng tin cậy hơn và đã được thử nghiệm.\nNightly: Các phiên bản phát triển có tất cả các tính năng và sửa lỗi mới nhất; có thể có lỗi và ít ổn định hơn. - GUIgroupBox Phát nhạc tiêu đề trò chơi:\nNếu một trò chơi hỗ trợ điều này, hãy kích hoạt phát nhạc đặc biệt khi bạn chọn trò chơi trong GUI. - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox Ẩn con trỏ:\nChọn khi nào con trỏ sẽ biến mất:\nKhông bao giờ: Bạn sẽ luôn thấy chuột.\nKhông hoạt động: Đặt một khoảng thời gian để nó biến mất sau khi không hoạt động.\nLuôn luôn: bạn sẽ không bao giờ thấy chuột. - idleTimeoutGroupBox Đặt thời gian để chuột biến mất sau khi không hoạt động. - backButtonBehaviorGroupBox Hành vi nút quay lại:\nĐặt nút quay lại của tay cầm để mô phỏng việc chạm vào vị trí đã chỉ định trên touchpad của PS4. - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never Không bao giờ - Idle Nhàn rỗi - Always Luôn luôn - Touchpad Left Touchpad Trái - Touchpad Right Touchpad Phải - Touchpad Center Giữa Touchpad - None Không có - graphicsAdapterGroupBox Thiết bị đồ họa:\nTrên các hệ thống có GPU đa năng, hãy chọn GPU mà trình giả lập sẽ sử dụng từ danh sách thả xuống,\hoặc chọn "Auto Select" để tự động xác định. - resolutionLayout Chiều rộng/Cao:\nChọn kích thước cửa sổ của trình giả lập khi khởi động, có thể điều chỉnh trong quá trình chơi.\nĐiều này khác với độ phân giải trong trò chơi. - heightDivider Bộ chia Vblank:\nTốc độ khung hình mà trình giả lập làm mới được nhân với số này. Thay đổi này có thể có tác động tiêu cực như tăng tốc độ trò chơi hoặc làm hỏng chức năng quan trọng mà trò chơi không mong đợi thay đổi điều này! - dumpShadersCheckBox Bật xuất shader:\nĐể mục đích gỡ lỗi kỹ thuật, lưu shader của trò chơi vào một thư mục khi chúng được kết xuất. - nullGpuCheckBox Bật GPU Null:\nĐể mục đích gỡ lỗi kỹ thuật, vô hiệu hóa việc kết xuất trò chơi như thể không có card đồ họa. - gameFoldersBox Thư mục trò chơi:\nDanh sách các thư mục để kiểm tra các trò chơi đã cài đặt. - addFolderButton Thêm:\nThêm một thư mục vào danh sách. - removeFolderButton Xóa:\nXóa một thư mục khỏi danh sách. - debugDump Bật xuất gỡ lỗi:\nLưu biểu tượng nhập và xuất và thông tin tiêu đề tệp cho ứng dụng PS4 hiện đang chạy vào một thư mục. - vkValidationCheckBox Bật lớp xác thực Vulkan:\nKích hoạt một hệ thống xác thực trạng thái của bộ kết xuất Vulkan và ghi lại thông tin về trạng thái nội bộ của nó. Điều này sẽ giảm hiệu suất và có thể thay đổi hành vi của việc giả lập. - vkSyncValidationCheckBox Bật xác thực đồng bộ Vulkan:\nKích hoạt một hệ thống xác thực thời gian của nhiệm vụ kết xuất Vulkan. Điều này sẽ giảm hiệu suất và có thể thay đổi hành vi của việc giả lập. - rdocCheckBox Bật gỡ lỗi RenderDoc:\nNếu được kích hoạt, trình giả lập sẽ cung cấp tính tương thích với Renderdoc để cho phép bắt và phân tích khung hình hiện tại đang được kết xuất. + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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. Nếu bản vá không xuất hiện, có thể là nó không tồn tại cho số seri và phiên bản cụ thể của trò chơi. + + + 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. + + + The game is in version: %1 + Trò chơi đang ở phiên bản: %1 + + + The downloaded patch only works on version: %1 + Patch đã tải về chỉ hoạt động trên phiên bản: %1 + + + You may need to update your game. + Bạn có thể cần cập nhật trò chơi của mình. + + + Incompatibility Notice + Thông báo không tương thích + + + 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: + + + Can't apply cheats before the game is started + Không thể áp dụng cheat trước khi trò chơi bắt đầu. + + GameListFrame - Icon Biểu tượng - Name Tên - Serial Số seri - Compatibility Compatibility - Region Khu vực - Firmware Phần mềm - Size Kích thước - Version Phiên bản - Path Đường dẫn - Play Time Thời gian chơi - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater Trình cập nhật tự động - Error Lỗi - Network error: Lỗi mạng: - Failed to parse update information. Không thể phân tích thông tin cập nhật. - No pre-releases found. Không tìm thấy bản phát hành trước. - Invalid release data. Dữ liệu bản phát hành không hợp lệ. - No download URL found for the specified asset. Không tìm thấy URL tải xuống cho tài sản đã chỉ định. - Your version is already up to date! Phiên bản của bạn đã được cập nhật! - Update Available Có bản cập nhật - Update Channel Kênh Cập Nhật - Current Version Phiên bản hiện tại - Latest Version Phiên bản mới nhất - Do you want to update? Bạn có muốn cập nhật không? - Show Changelog Hiện nhật ký thay đổi - Check for Updates at Startup Kiểm tra cập nhật khi khởi động - Update Cập nhật - No Không - Hide Changelog Ẩn nhật ký thay đổi - Changes Thay đổi - Network error occurred while trying to access the URL Xảy ra lỗi mạng khi cố gắng truy cập URL - Download Complete Tải xuống hoàn tất - The update has been downloaded, press OK to install. Bản cập nhật đã được tải xuống, nhấn OK để cài đặt. - Failed to save the update file at Không thể lưu tệp cập nhật tại - Starting Update... Đang bắt đầu cập nhật... - Failed to create the update script file Không thể tạo tệp kịch bản cập nhật + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 fb95ba935..e71180729 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -2,26 +2,22 @@ + SPDX-License-Identifier: GPL-2.0-or-later --> AboutDialog - About shadPS4 关于 shadPS4 - shadPS4 shadPS4 - shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 是一款实验性质的开源 PlayStation 4模拟器软件。 + shadPS4 是一款实验性质的开源 PlayStation 4 模拟器软件。 - This software should not be used to play games you have not legally obtained. 本软件不得用于运行未经合法授权而获得的游戏。 @@ -29,7 +25,6 @@ ElfViewer - Open Folder 打开文件夹 @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 加载游戏列表中, 请稍等 :3 - Cancel 取消 - Loading... 加载中... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - 选择文件目录 - Select which directory you want to install to. 选择你想要安装到的目录。 @@ -68,27 +58,22 @@ GameInstallDialog - shadPS4 - Choose directory shadPS4 - 选择文件目录 - Directory to install games 要安装游戏的目录 - Browse 浏览 - Error 错误 - The value for location to install games is not valid. 游戏安装位置无效。 @@ -96,353 +81,420 @@ GuiContextMenus - Create Shortcut 创建快捷方式 - Cheats / Patches - 作弊码 / 补丁 + 作弊码/补丁 - SFO Viewer SFO 查看器 - Trophy Viewer - Trophy 查看器 + 奖杯查看器 - Open Folder... 打开文件夹... - Open Game Folder 打开游戏文件夹 - Open Save Data Folder - 打开保存数据文件夹 + 打开存档数据文件夹 - Open Log Folder 打开日志文件夹 - Copy info... 复制信息... - Copy Name 复制名称 - Copy Serial 复制序列号 - Copy All 复制全部 - Delete... 删除... - Delete Game 删除游戏 - Delete Update 删除更新 - Delete DLC - 删除DLC + 删除 DLC + + + Compatibility... + 兼容性... + + + Update database + 更新数据库 + + + View report + 查看报告 + + + Submit a report + 提交报告 - Shortcut creation 创建快捷方式 - - Shortcut created successfully!\n %1 - 创建快捷方式成功!\n %1 + Shortcut created successfully! + 创建快捷方式成功! - Error 错误 - - Error creating shortcut!\n %1 - 创建快捷方式出错!\n %1 + Error creating shortcut! + 创建快捷方式出错! - Install PKG 安装 PKG - Game 游戏 - requiresEnableSeparateUpdateFolder_MSG - 这个功能需要‘启用单独的更新目录’配置选项才能正常运行,如果你想要使用这个功能,请启用它。 + 这个功能需要“启用单独的更新目录”配置选项才能正常运行,如果你想要使用这个功能,请启用它。 - This game has no update to delete! 这个游戏没有更新可以删除! - - + Update 更新 - This game has no DLC to delete! - 这个游戏没有DLC可以删除! + 这个游戏没有 DLC 可以删除! - DLC DLC - Delete %1 删除 %1 - Are you sure you want to delete %1's %2 directory? - 你确定要删除 %1 的 %2 目录? + 你确定要删除 %1 的%2目录? MainWindow - Open/Add Elf Folder - 打开/添加Elf文件夹 + 打开/添加 Elf 文件夹 - Install Packages (PKG) 安装 Packages (PKG) - Boot Game 启动游戏 - Check for Updates 检查更新 - 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 主题 - Help 帮助 - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar 工具栏 + + Game List + 游戏列表 + + + * 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 是一个补丁,请先安装游戏! + + + 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 打开文件夹 @@ -450,1127 +502,839 @@ TrophyViewer - Trophy Viewer - Trophy 查看器 + 奖杯查看器 SettingsDialog - Settings 设置 - General - 通用 + 常规 - System 系统 - Console Language 主机语言 - Emulator Language 模拟器语言 - Emulator 模拟器 - Enable Fullscreen 启用全屏 - Enable Separate Update Folder 启用单独的更新目录 - Show Splash - 显示Splash + 显示启动画面 - Is PS4 Pro - 是否是 PS4 Pro + 模拟 PS4 Pro - Enable Discord Rich Presence 启用 Discord Rich Presence - Username 用户名 - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger 日志 - Log Type 日志类型 - Log Filter 日志过滤 - + Open Log Location + 打开日志位置 + + Input 输入 - Cursor 光标 - Hide Cursor 隐藏光标 - Hide Cursor Idle Timeout - 光标空闲超时隐藏 + 光标隐藏闲置时长 + + + s + - Controller - 控制器 + 手柄 - Back Button Behavior 返回按钮行为 - Graphics 图像 - Graphics Device - 图像设备 + 图形设备 - Width 宽度 - Height 高度 - Vblank Divider Vblank Divider - Advanced 高级 - Enable Shaders Dumping 启用着色器转储 - Enable NULL GPU 启用 NULL GPU - Paths 路径 - Game Folders 游戏文件夹 - Add... 添加... - Remove 删除 - Debug 调试 - Enable Debug Dumping 启用调试转储 - Enable Vulkan Validation Layers 启用 Vulkan 验证层 - Enable Vulkan Synchronization Validation 启用 Vulkan 同步验证 - Enable RenderDoc Debugging 启用 RenderDoc 调试 - Update 更新 - Check for Updates at Startup 启动时检查更新 - Update Channel 更新频道 - Check for Updates 检查更新 - GUI Settings 界面设置 - Disable Trophy Pop-ups - Disable Trophy Pop-ups + 禁止弹出奖杯 - Play title music 播放标题音乐 - Update Compatibility Database On Startup - Update Compatibility Database On Startup + 启动时更新兼容性数据库 - Game Compatibility - Game Compatibility + 游戏兼容性 - Display Compatibility Data - Display Compatibility Data + 显示兼容性数据 - Update Compatibility Database - Update Compatibility Database + 更新兼容性数据库 - Volume 音量 - - - MainWindow - - Game List - 游戏列表 + Audio Backend + 音频后端 - - * Unsupported Vulkan Version - * 不支持的 Vulkan 版本 + Save + 保存 - - Download Cheats For All Installed Games - 下载所有已安装游戏的作弊码 + Apply + 应用 - - Download Patches For All Games - 下载所有游戏的补丁 + Restore Defaults + 恢复默认 - - Download Complete - 下载完成 + Close + 关闭 - - You have downloaded cheats for all the games you have installed. - 您已下载了所有已安装游戏的作弊码。 + Point your mouse at an option to display its description. + 将鼠标指针指向选项以显示其描述。 - - Patches Downloaded Successfully! - 补丁下载成功! + consoleLanguageGroupBox + 主机语言:\n设置 PS4 游戏中使用的语言。\n建议设置为支持的语言,这将因地区而异。 - - All Patches available for all games have been downloaded. - 所有游戏的所有补丁都已下载。 + emulatorLanguageGroupBox + 模拟器语言:\n设置模拟器用户界面的语言。 - - Games: - 游戏: + fullscreenCheckBox + 启用全屏:\n以全屏模式启动游戏。\n您可以按 F11 键切换回窗口模式。 - - PKG File (*.PKG) - PKG 文件 (*.PKG) + separateUpdatesCheckBox + 启用单独的更新目录:\n启用安装游戏更新到一个单独的目录中以更便于管理。 - - ELF files (*.bin *.elf *.oelf) - ELF 文件 (*.bin *.elf *.oelf) + showSplashCheckBox + 显示启动画面:\n在游戏启动时显示游戏的启动画面(特殊图像)。 - - Game Boot - 游戏启动 + ps4proCheckBox + 模拟 PS4 Pro:\n使模拟器作为 PS4 Pro 运行,可以在支持的游戏中激活特殊功能。 - - Only one file can be selected! - 只能选择一个文件! + discordRPCCheckbox + 启用 Discord Rich Presence:\n在您的 Discord 个人资料上显示模拟器图标和相关信息。 - - PKG Extraction - PKG 解压 + userName + 用户名:\n设置 PS4 帐户的用户名,某些游戏中可能会显示此名称。 - - Patch detected! - 检测到补丁! + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - - PKG and Game versions match: - PKG 和游戏版本匹配: + logTypeGroupBox + 日志类型:\n设置日志窗口输出的同步方式以提高性能。可能会对模拟产生不良影响。 - - Would you like to overwrite? - 您想要覆盖吗? + logFilter + 日志过滤器:\n过滤日志,仅打印特定信息。\n例如:"Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" 级别: Trace, Debug, Info, Warning, Error, Critical - 按此顺序,特定级别将静默列表中所有先前的级别,并记录所有后续级别。 - - PKG Version %1 is older than installed version: - PKG 版本 %1 比已安装版本更旧: + updaterGroupBox + 更新:\nRelease:每月发布的官方版本可能非常过时,但更可靠且经过测试。\nNightly:包含所有最新功能和修复的开发版本,但可能包含错误且稳定性较低。 - - Game is installed: - 游戏已安装: + GUIgroupBox + 播放标题音乐:\n如果游戏支持,在图形界面选择游戏时播放特殊音乐。 - - Would you like to install Patch: - 您想安装补丁吗: + disableTrophycheckBox + 禁止弹出奖杯:\n禁用游戏内奖杯通知。可以在奖杯查看器中继续跟踪奖杯进度(在主窗口中右键点击游戏)。 - - DLC Installation - DLC 安装 + hideCursorGroupBox + 隐藏光标:\n选择光标何时消失:\n从不: 始终显示光标。\闲置: 光标在闲置若干秒后消失。\n始终: 始终显示光标。 - - Would you like to install DLC: %1? - 您想安装 DLC: %1 吗? + idleTimeoutGroupBox + 光标隐藏闲置时长:\n光标自动隐藏之前的闲置时长。 - - DLC already installed: - DLC 已经安装: + backButtonBehaviorGroupBox + 返回按钮行为:\n设置手柄的返回按钮模拟在 PS4 触控板上指定位置的点击。 - - Game already installed - 游戏已经安装 + enableCompatibilityCheckBox + 显示兼容性数据:\n在列表视图中显示游戏兼容性信息。启用“启动时更新兼容性数据库”以获取最新信息。 - - PKG is a patch, please install the game first! - PKG 是一个补丁,请先安装游戏! + checkCompatibilityOnStartupCheckBox + 启动时更新兼容性数据库:\n当 shadPS4 启动时自动更新兼容性数据库。 - - PKG ERROR - PKG 错误 + updateCompatibilityButton + 更新兼容性数据库:\n立即更新兼容性数据库。 - - Extracting PKG %1/%2 - 正在解压 PKG %1/%2 + Never + 从不 - - Extraction Finished - 解压完成 + Idle + 闲置 - - Game successfully installed at %1 - 游戏成功安装在 %1 + Always + 始终 - - File doesn't appear to be a valid PKG file - 文件似乎不是有效的 PKG 文件 + Touchpad Left + 触控板左侧 + + + Touchpad Right + 触控板右侧 + + + Touchpad Center + 触控板中间 + + + None + + + + graphicsAdapterGroupBox + 图形设备:\n在具有多个 GPU 的系统中,从下拉列表中选择要使用的 GPU,\n或者选择“自动选择”由模拟器决定。 + + + resolutionLayout + 宽度/高度:\n设置启动游戏时的窗口大小,游戏过程中可以调整。\n这与游戏内的分辨率不同。 + + + heightDivider + Vblank Divider:\n模拟器刷新的帧率会乘以此数字。改变此项可能会导致游戏速度加快,或破坏游戏中不期望此变化的关键功能! + + + dumpShadersCheckBox + 启用着色器转储:\n用于技术调试,在渲染期间将游戏着色器保存到文件夹中。 + + + nullGpuCheckBox + 启用 NULL GPU:\n用于技术调试,禁用游戏渲染,就像没有显卡一样。 + + + gameFoldersBox + 游戏文件夹:\n检查已安装游戏的文件夹列表。 + + + addFolderButton + 添加:\n将文件夹添加到列表。 + + + removeFolderButton + 移除:\n从列表中移除文件夹。 + + + debugDump + 启用调试转储:\n将当前正在运行的 PS4 程序的导入和导出符号及文件头信息保存到目录中。 + + + vkValidationCheckBox + 启用 Vulkan 验证层:\n启用一个系统来验证 Vulkan 渲染器的状态并记录其内部状态的信息。\n这将降低性能并可能改变模拟的行为。 + + + vkSyncValidationCheckBox + 启用 Vulkan 同步验证:\n启用一个系统来验证 Vulkan 渲染任务的时间。\n这将降低性能并可能改变模拟的行为。 + + + rdocCheckBox + 启用 RenderDoc 调试:\n启用后模拟器将提供与 Renderdoc 的兼容性,允许在渲染过程中捕获和分析当前渲染的帧。 CheatsPatches - Cheats / Patches for - Cheats / Patches for + 作弊码/补丁: - defaultTextEdit_MSG - 作弊/补丁是实验性的。\n请小心使用。\n\n通过选择存储库并点击下载按钮,单独下载作弊程序。\n在“补丁”选项卡中,您可以一次性下载所有补丁,选择要使用的补丁并保存选择。\n\n由于我们不开发作弊程序/补丁,\n请将问题报告给作弊程序的作者。\n\n创建了新的作弊程序?访问:\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 - 没有可用的图像 + 没有可用的图片 - 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 失败: + 解析 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 页面。 - The game is in version: %1 - 游戏版本: %1 + 游戏版本:%1 - The downloaded patch only works on version: %1 - 下载的补丁仅适用于版本: %1 + 下载的补丁仅适用于版本:%1 - You may need to update your game. 您可能需要更新您的游戏。 - Incompatibility Notice 不兼容通知 - Failed to open file: - 无法打开文件: + 无法打开文件: - XML ERROR: - XML 错误: + 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: - 名称: + 名称: - Can't apply cheats before the game is started - 在游戏开始之前无法应用作弊。 - - - - SettingsDialog - - - Save - 保存 - - - - Apply - 应用 - - - - Restore Defaults - 恢复默认 - - - - Close - 关闭 - - - - Point your mouse at an option to display its description. - 将鼠标指针指向选项以显示其描述。 - - - - consoleLanguageGroupBox - 控制台语言:\n设置 PS4 游戏中使用的语言。\n建议设置为支持的语言,因为可能因地区而异。 - - - - emulatorLanguageGroupBox - 模拟器语言:\n设置模拟器用户界面的语言。 - - - - fullscreenCheckBox - 启用全屏模式:\n自动将游戏窗口设置为全屏模式。\n您可以按 F11 键禁用此选项。 - - - - separateUpdatesCheckBox - 启用单独的更新目录:\n启用安装游戏更新到一个单独的目录中以更便于管理。 - - - - showSplashCheckBox - 显示启动画面:\n在游戏启动时显示游戏的启动画面(特殊图像)。 - - - - ps4proCheckBox - 这是 PS4 Pro:\n使模拟器作为 PS4 PRO 运行,可以在支持的游戏中激活特殊功能。 - - - - discordRPCCheckbox - 启用 Discord Rich Presence:\n在您的 Discord 个人资料上显示仿真器图标和相关信息。 - - - - userName - 用户名:\n设置 PS4 帐户的用户名。某些游戏中可能会显示此名称。 - - - - logTypeGroupBox - 日志类型:\n设置是否同步日志窗口的输出以提高性能。这可能会对模拟产生负面影响。 - - - - logFilter - 日志过滤器:\n过滤日志,仅打印特定信息。\n例如:"Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" 级别: Trace, Debug, Info, Warning, Error, Critical - 按此顺序,特定级别将静默列表中所有先前的级别,并记录所有后续级别。 - - - - updaterGroupBox - 更新:\nRelease: 官方版本,可能非常旧,并且每月发布,但更可靠且经过测试。\nNightly: 开发版本,包含所有最新功能和修复,但可能包含错误且不够稳定。 - - - - GUIgroupBox - 播放标题音乐:\n如果游戏支持,在图形界面选择游戏时启用播放特殊音乐。 - - - - disableTrophycheckBox - Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - - - - hideCursorGroupBox - 隐藏光标:\n选择光标何时消失:\n从不: 您将始终看到鼠标。\n空闲: 设置光标在空闲后消失的时间。\n始终: 您将永远看不到鼠标。 - - - - idleTimeoutGroupBox - 设置鼠标在空闲后消失的时间。 - - - - backButtonBehaviorGroupBox - 返回按钮行为:\n设置控制器的返回按钮以模拟在 PS4 触控板上指定位置的点击。 - - - - enableCompatibilityCheckBox - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - - - - checkCompatibilityOnStartupCheckBox - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - - - - updateCompatibilityButton - Update Compatibility Database:\nImmediately update the compatibility database. - - - - Never - 从不 - - - - Idle - 空闲 - - - - Always - 始终 - - - - Touchpad Left - 触控板左侧 - - - - Touchpad Right - 触控板右侧 - - - - Touchpad Center - 触控板中间 - - - - None - - - - - graphicsAdapterGroupBox - 图形设备:\n在具有多个 GPU 的系统中,从下拉列表中选择要使用的 GPU,\n或者选择“自动检测”以自动确定。 - - - - resolutionLayout - 宽度/高度:\n设置启动时模拟器的窗口大小,该大小可以在游戏中更改。\n这与游戏中的分辨率不同。 - - - - heightDivider - Vblank 除数:\n模拟器更新的帧速率乘以此数字。改变此项可能会导致游戏速度加快,或破坏游戏中不期望此变化的关键功能! - - - - dumpShadersCheckBox - 启用着色器转储:\n为了技术调试,在渲染期间将游戏着色器保存到文件夹中。 - - - - nullGpuCheckBox - 启用空 GPU:\n为了技术调试,将游戏渲染禁用,仿佛没有图形卡。 - - - - gameFoldersBox - 游戏文件夹:\n检查已安装游戏的文件夹列表。 - - - - addFolderButton - 添加:\n将文件夹添加到列表。 - - - - removeFolderButton - 移除:\n从列表中移除文件夹。 - - - - debugDump - 启用调试转储:\n将当前正在运行的 PS4 程序的导入和导出符号及文件头信息保存到目录中。 - - - - vkValidationCheckBox - 启用 Vulkan 验证层:\n启用验证 Vulkan 渲染器状态并记录内部状态信息的系统。这可能会降低性能,并可能更改模拟行为。 - - - - vkSyncValidationCheckBox - 启用 Vulkan 同步验证:\n启用验证 Vulkan 渲染任务时间的系统。这可能会降低性能,并可能更改模拟行为。 - - - - rdocCheckBox - 启用 RenderDoc 调试:\n如果启用,模拟器将提供与 Renderdoc 的兼容性,允许在渲染过程中捕获和分析当前渲染的帧。 + 在游戏启动之前无法应用作弊码。 GameListFrame - Icon 图标 - Name 名称 - Serial 序列号 - Compatibility - Compatibility + 兼容性 - Region 区域 - Firmware 固件 - Size 大小 - Version 版本 - Path 路径 - Play Time 游戏时间 - Never Played - Never Played + 未玩过 + + + h + 小时 + + + m + 分钟 + + + s + - Compatibility is untested - Compatibility is untested + 兼容性未经测试 - Game does not initialize properly / crashes the emulator - Game does not initialize properly / crashes the emulator + 游戏无法正确初始化/模拟器崩溃 - Game boots, but only displays a blank screen - Game boots, but only displays a blank screen + 游戏启动,但只显示白屏 - Game displays an image but does not go past the menu - Game displays an image but does not go past the menu + 游戏显示图像但无法通过菜单页面 - Game has game-breaking glitches or unplayable performance - Game has game-breaking glitches or unplayable performance + 游戏有严重的 Bug 或太卡无法游玩 - Game can be completed with playable performance and no major glitches - Game can be completed with playable performance and no major glitches + 游戏能在可玩的性能下完成且没有重大 Bug CheckUpdate - Auto Updater 自动更新程序 - Error 错误 - Network error: 网络错误: - Failed to parse update information. 无法解析更新信息。 - No pre-releases found. 未找到预发布版本。 - Invalid release data. 无效的发布数据。 - No download URL found for the specified asset. - 未找到指定资产的下载 URL。 + 未找到指定资源的下载地址。 - Your version is already up to date! 您的版本已经是最新的! - Update Available 可用更新 - Update Channel 更新频道 - Current Version 当前版本 - Latest Version 最新版本 - Do you want to update? 您想要更新吗? - Show Changelog - 显示变更日志 + 显示更新日志 - Check for Updates at Startup 启动时检查更新 - Update 更新 - No - Hide Changelog - 隐藏变更日志 + 隐藏更新日志 - Changes - 变更 + 更新日志 - Network error occurred while trying to access the URL - 尝试访问 URL 时发生网络错误 + 尝试访问网址时发生网络错误 - Download Complete 下载完成 - The update has been downloaded, press OK to install. 更新已下载,请按 OK 安装。 - Failed to save the update file at 无法保存更新文件到 - Starting Update... 正在开始更新... - Failed to create the update script file 无法创建更新脚本文件 + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ 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 77734bf26..49d419d8b 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -6,22 +6,18 @@ 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. @@ -29,7 +25,6 @@ ElfViewer - Open Folder Open Folder @@ -37,17 +32,14 @@ GameInfoClass - Loading game list, please wait :3 Loading game list, please wait :3 - Cancel Cancel - Loading... Loading... @@ -55,12 +47,10 @@ InstallDirSelect - shadPS4 - Choose directory shadPS4 - Choose directory - Select which directory you want to install to. Select which directory you want to install to. @@ -68,27 +58,22 @@ 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. @@ -96,147 +81,134 @@ GuiContextMenus - Create Shortcut Create Shortcut - Cheats / Patches Zuòbì / Xiūbǔ chéngshì - SFO Viewer SFO Viewer - Trophy Viewer Trophy Viewer - Open Folder... 打開資料夾... - Open Game Folder 打開遊戲資料夾 - Open Save Data Folder 打開存檔資料夾 - Open Log Folder 打開日誌資料夾 - Copy info... Copy info... - Copy Name Copy Name - Copy Serial Copy Serial - Copy All Copy All - Delete... Delete... - Delete Game Delete Game - Delete Update Delete Update - Delete DLC Delete DLC - + Compatibility... + Compatibility... + + + Update database + Update database + + + View report + View report + + + Submit a report + Submit a report + + Shortcut creation Shortcut creation - - Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Shortcut created successfully! + Shortcut created successfully! - Error Error - - Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Error creating shortcut! + Error creating shortcut! - Install PKG Install PKG - Game Game - requiresEnableSeparateUpdateFolder_MSG This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. - This game has no update to delete! This game has no update to delete! - - + Update Update - This game has no DLC to delete! This game has no DLC to delete! - DLC DLC - Delete %1 Delete %1 - Are you sure you want to delete %1's %2 directory? Are you sure you want to delete %1's %2 directory? @@ -244,205 +216,285 @@ MainWindow - Open/Add Elf Folder Open/Add Elf Folder - Install Packages (PKG) Install Packages (PKG) - Boot Game Boot Game - Check for Updates 檢查更新 - About shadPS4 About shadPS4 - Configure... Configure... - Install application from a .pkg file Install application from a .pkg file - Recent Games Recent Games - Exit Exit - Exit shadPS4 Exit shadPS4 - Exit the application. Exit the application. - Show Game List Show Game List - Game List Refresh Game List Refresh - Tiny Tiny - Small Small - Medium Medium - Large Large - List View List View - Grid View Grid View - Elf Viewer Elf Viewer - Game Install Directory Game Install Directory - Download Cheats/Patches Xiàzài Zuòbì / Xiūbǔ chéngshì - Dump Game List Dump Game List - PKG Viewer PKG Viewer - Search... Search... - File File - View View - Game List Icons Game List Icons - Game List Mode Game List Mode - Settings Settings - Utils Utils - Themes Themes - Help 幫助 - Dark Dark - Light Light - Green Green - Blue Blue - Violet Violet - toolBar toolBar + + Game List + 遊戲列表 + + + * 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 是修補檔,請先安裝遊戲! + + + 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 Open Folder @@ -450,7 +502,6 @@ TrophyViewer - Trophy Viewer Trophy Viewer @@ -458,989 +509,704 @@ SettingsDialog - Settings Settings - General General - System System - Console Language Console Language - Emulator Language Emulator Language - Emulator Emulator - Enable Fullscreen Enable Fullscreen - Enable Separate Update Folder Enable Separate Update Folder - Show Splash Show Splash - Is PS4 Pro Is PS4 Pro - Enable Discord Rich Presence 啟用 Discord Rich Presence - Username Username - + Trophy Key + Trophy Key + + + Trophy + Trophy + + Logger Logger - Log Type Log Type - Log Filter Log Filter - + Open Log Location + 開啟日誌位置 + + Input 輸入 - Cursor 游標 - Hide Cursor 隱藏游標 - Hide Cursor Idle Timeout 游標空閒超時隱藏 - + s + s + + Controller 控制器 - Back Button Behavior 返回按鈕行為 - 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 - Paths 路徑 - Game Folders 遊戲資料夾 - Add... 添加... - Remove 刪除 - Debug Debug - Enable Debug Dumping Enable Debug Dumping - Enable Vulkan Validation Layers Enable Vulkan Validation Layers - Enable Vulkan Synchronization Validation Enable Vulkan Synchronization Validation - Enable RenderDoc Debugging Enable RenderDoc Debugging - Update 更新 - Check for Updates at Startup 啟動時檢查更新 - Update Channel 更新頻道 - Check for Updates 檢查更新 - GUI Settings 介面設置 - Disable Trophy Pop-ups Disable Trophy Pop-ups - Play title music 播放標題音樂 - Update Compatibility Database On Startup Update Compatibility Database On Startup - Game Compatibility Game Compatibility - Display Compatibility Data Display Compatibility Data - Update Compatibility Database Update Compatibility Database - Volume 音量 - - - MainWindow - - Game List - 遊戲列表 + Audio Backend + Audio Backend - - * 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 是修補檔,請先安裝遊戲! - - - - 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 for - Cheats / Patches for - - - - 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 頁面。 - - - - The game is in version: %1 - 遊戲版本: %1 - - - - The downloaded patch only works on version: %1 - 下載的補丁僅適用於版本: %1 - - - - You may need to update your game. - 您可能需要更新遊戲。 - - - - Incompatibility Notice - 不相容通知 - - - - 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: - 名稱: - - - - Can't apply cheats before the game is started - 在遊戲開始之前無法應用作弊。 - - - - SettingsDialog - - - Save - 儲存 - - - Apply 應用 - Restore Defaults 還原預設值 - Close 關閉 - Point your mouse at an option to display its description. 將鼠標指向選項以顯示其描述。 - consoleLanguageGroupBox 主機語言:\n設定PS4遊戲使用的語言。\n建議將其設置為遊戲支持的語言,這會因地區而異。 - emulatorLanguageGroupBox 模擬器語言:\n設定模擬器的用戶介面的語言。 - fullscreenCheckBox 啟用全螢幕:\n自動將遊戲視窗設置為全螢幕模式。\n可以按F11鍵進行切換。 - separateUpdatesCheckBox Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - showSplashCheckBox 顯示啟動畫面:\n在遊戲啟動時顯示遊戲的啟動畫面(特殊圖片)。 - ps4proCheckBox 為PS4 Pro:\n讓模擬器像PS4 PRO一樣運作,這可能啟用支持此功能的遊戲中的特殊功能。 - discordRPCCheckbox 啟用 Discord Rich Presence:\n在您的 Discord 個人檔案上顯示模擬器圖標和相關信息。 - userName 用戶名:\n設定PS4帳號的用戶名,某些遊戲中可能會顯示。 - + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + + logTypeGroupBox 日誌類型:\n設定是否同步日誌窗口的輸出以提高性能。可能對模擬產生不良影響。 - logFilter 日誌過濾器:\n過濾日誌以僅打印特定信息。\n範例:"Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" 等級: Trace, Debug, Info, Warning, Error, Critical - 以此順序,特定級別靜音所有前面的級別,並記錄其後的每個級別。 - updaterGroupBox 更新:\nRelease: 每月發布的官方版本,可能非常舊,但更可靠且經過測試。\nNightly: 開發版本,擁有所有最新的功能和修復,但可能包含錯誤,穩定性較差。 - GUIgroupBox 播放標題音樂:\n如果遊戲支持,啟用在GUI中選擇遊戲時播放特殊音樂。 - disableTrophycheckBox Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - hideCursorGroupBox 隱藏游標:\n選擇游標何時消失:\n從不: 您將始終看到滑鼠。\n閒置: 設定在閒置後消失的時間。\n始終: 您將永遠看不到滑鼠。 - idleTimeoutGroupBox 設定滑鼠在閒置後消失的時間。 - backButtonBehaviorGroupBox 返回按鈕行為:\n設定控制器的返回按鈕模擬在 PS4 觸控板上指定位置的觸碰。 - enableCompatibilityCheckBox Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - checkCompatibilityOnStartupCheckBox Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - updateCompatibilityButton Update Compatibility Database:\nImmediately update the compatibility database. - Never 從不 - Idle 閒置 - Always 始終 - Touchpad Left 觸控板左側 - Touchpad Right 觸控板右側 - Touchpad Center 觸控板中間 - None - graphicsAdapterGroupBox 圖形設備:\n在多GPU系統中,從下拉列表中選擇模擬器將使用的GPU,\n或選擇「自動選擇」以自動確定。 - resolutionLayout 寬度/高度:\n設定模擬器啟動時的窗口大小,可以在遊戲過程中調整。\n這與遊戲內解析度不同。 - heightDivider Vblank分隔符:\n模擬器的幀速率將乘以這個數字。更改此數字可能會有不良影響,例如增加遊戲速度,或破壞不預期此變化的關鍵遊戲功能! - dumpShadersCheckBox 啟用著色器轉儲:\n為了技術調試,將遊戲的著色器在渲染時保存到文件夾中。 - nullGpuCheckBox 啟用空GPU:\n為了技術調試,禁用遊戲渲染,彷彿沒有顯示卡。 - gameFoldersBox 遊戲資料夾:\n檢查已安裝遊戲的資料夾列表。 - addFolderButton 添加:\n將資料夾添加到列表。 - removeFolderButton 移除:\n從列表中移除資料夾。 - debugDump 啟用調試轉儲:\n將當前運行的PS4程序的輸入和輸出符號及文件頭信息保存到目錄中。 - vkValidationCheckBox 啟用Vulkan驗證層:\n啟用一個系統來驗證Vulkan渲染器的狀態並記錄其內部狀態的信息。這將降低性能並可能改變模擬行為。 - vkSyncValidationCheckBox 啟用Vulkan同步驗證:\n啟用一個系統來驗證Vulkan渲染任務的時間。這將降低性能並可能改變模擬行為。 - rdocCheckBox 啟用RenderDoc調試:\n如果啟用,模擬器將提供與Renderdoc的兼容性,以允許捕獲和分析當前渲染的幀。 + + CheatsPatches + + Cheats / Patches for + Cheats / Patches for + + + 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 頁面。 + + + The game is in version: %1 + 遊戲版本: %1 + + + The downloaded patch only works on version: %1 + 下載的補丁僅適用於版本: %1 + + + You may need to update your game. + 您可能需要更新遊戲。 + + + Incompatibility Notice + 不相容通知 + + + 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: + 名稱: + + + Can't apply cheats before the game is started + 在遊戲開始之前無法應用作弊。 + + GameListFrame - Icon 圖示 - Name 名稱 - Serial 序號 - Compatibility Compatibility - Region 區域 - Firmware 固件 - Size 大小 - Version 版本 - Path 路徑 - Play Time 遊玩時間 - Never Played Never Played - + h + h + + + m + m + + + s + s + + Compatibility is untested Compatibility is untested - Game does not initialize properly / crashes the emulator Game does not initialize properly / crashes the emulator - Game boots, but only displays a blank screen Game boots, but only displays a blank screen - Game displays an image but does not go past the menu Game displays an image but does not go past the menu - Game has game-breaking glitches or unplayable performance Game has game-breaking glitches or unplayable performance - Game can be completed with playable performance and no major glitches Game can be completed with playable performance and no major glitches @@ -1448,129 +1214,127 @@ CheckUpdate - Auto Updater 自動更新程式 - Error 錯誤 - Network error: 網路錯誤: - Failed to parse update information. 無法解析更新資訊。 - No pre-releases found. 未找到預發布版本。 - Invalid release data. 無效的發行數據。 - No download URL found for the specified asset. 未找到指定資產的下載 URL。 - Your version is already up to date! 您的版本已經是最新的! - Update Available 可用更新 - Update Channel 更新頻道 - Current Version 當前版本 - Latest Version 最新版本 - Do you want to update? 您想要更新嗎? - Show Changelog 顯示變更日誌 - Check for Updates at Startup 啟動時檢查更新 - Update 更新 - No - Hide Changelog 隱藏變更日誌 - Changes 變更 - Network error occurred while trying to access the URL 嘗試訪問 URL 時發生網路錯誤 - Download Complete 下載完成 - The update has been downloaded, press OK to install. 更新已下載,按 OK 安裝。 - Failed to save the update file at 無法將更新文件保存到 - Starting Update... 正在開始更新... - Failed to create the update script file 無法創建更新腳本文件 + + GameListUtils + + B + B + + + KB + KB + + + MB + MB + + + GB + GB + + + TB + TB + + \ No newline at end of file diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 4f8e051e7..e7746f5cb 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -57,7 +57,24 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_ UNREACHABLE_MSG("Failed to create window handle: {}", SDL_GetError()); } - SDL_SetWindowFullscreen(window, Config::isFullscreenMode()); + SDL_SetWindowMinimumSize(window, 640, 360); + + bool error = false; + const SDL_DisplayID displayIndex = SDL_GetDisplayForWindow(window); + if (displayIndex < 0) { + LOG_ERROR(Frontend, "Error getting display index: {}", SDL_GetError()); + error = true; + } + const SDL_DisplayMode* displayMode; + if ((displayMode = SDL_GetCurrentDisplayMode(displayIndex)) == 0) { + LOG_ERROR(Frontend, "Error getting display mode: {}", SDL_GetError()); + error = true; + } + if (!error) { + SDL_SetWindowFullscreenMode(window, + Config::getFullscreenMode() == "True" ? displayMode : NULL); + } + SDL_SetWindowFullscreen(window, Config::getIsFullscreen()); SDL_InitSubSystem(SDL_INIT_GAMEPAD); controller->TryOpenSDLController(); @@ -138,6 +155,20 @@ void WindowSDL::WaitEvent() { case SDL_EVENT_GAMEPAD_AXIS_MOTION: OnGamepadEvent(&event); break; + // i really would have appreciated ANY KIND OF DOCUMENTATION ON THIS + // AND IT DOESN'T EVEN USE PROPER ENUMS + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: + switch ((SDL_SensorType)event.gsensor.sensor) { + case SDL_SENSOR_GYRO: + controller->Gyro(0, event.gsensor.data); + break; + case SDL_SENSOR_ACCEL: + controller->Acceleration(0, event.gsensor.data); + break; + default: + break; + } + break; case SDL_EVENT_QUIT: is_open = false; break; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 0ce9eea7c..f0cf15af0 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -24,9 +24,11 @@ static constexpr spv::ExecutionMode GetInputPrimitiveType(AmdGpu::PrimitiveType case AmdGpu::PrimitiveType::PointList: return spv::ExecutionMode::InputPoints; case AmdGpu::PrimitiveType::LineList: + case AmdGpu::PrimitiveType::LineStrip: return spv::ExecutionMode::InputLines; case AmdGpu::PrimitiveType::TriangleList: case AmdGpu::PrimitiveType::TriangleStrip: + case AmdGpu::PrimitiveType::RectList: return spv::ExecutionMode::Triangles; case AmdGpu::PrimitiveType::AdjTriangleList: return spv::ExecutionMode::InputTrianglesAdjacency; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp index 74e736cf6..d064b5d05 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp @@ -6,16 +6,22 @@ namespace Shader::Backend::SPIRV { -Id EmitCompositeConstructU32x2(EmitContext& ctx, Id e1, Id e2) { - return ctx.OpCompositeConstruct(ctx.U32[2], e1, e2); +template +Id EmitCompositeConstruct(EmitContext& ctx, IR::Inst* inst, Args&&... args) { + return inst->AreAllArgsImmediates() ? ctx.ConstantComposite(args...) + : ctx.OpCompositeConstruct(args...); } -Id EmitCompositeConstructU32x3(EmitContext& ctx, Id e1, Id e2, Id e3) { - return ctx.OpCompositeConstruct(ctx.U32[3], e1, e2, e3); +Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) { + return EmitCompositeConstruct(ctx, inst, ctx.U32[2], e1, e2); } -Id EmitCompositeConstructU32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4) { - return ctx.OpCompositeConstruct(ctx.U32[4], e1, e2, e3, e4); +Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3) { + return EmitCompositeConstruct(ctx, inst, ctx.U32[3], e1, e2, e3); +} + +Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4) { + return EmitCompositeConstruct(ctx, inst, ctx.U32[4], e1, e2, e3, e4); } Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index) { @@ -42,16 +48,30 @@ Id EmitCompositeInsertU32x4(EmitContext& ctx, Id composite, Id object, u32 index return ctx.OpCompositeInsert(ctx.U32[4], object, composite, index); } -Id EmitCompositeConstructF16x2(EmitContext& ctx, Id e1, Id e2) { - return ctx.OpCompositeConstruct(ctx.F16[2], e1, e2); +Id EmitCompositeShuffleU32x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1) { + return ctx.OpVectorShuffle(ctx.U32[2], composite1, composite2, comp0, comp1); } -Id EmitCompositeConstructF16x3(EmitContext& ctx, Id e1, Id e2, Id e3) { - return ctx.OpCompositeConstruct(ctx.F16[3], e1, e2, e3); +Id EmitCompositeShuffleU32x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2) { + return ctx.OpVectorShuffle(ctx.U32[3], composite1, composite2, comp0, comp1, comp2); } -Id EmitCompositeConstructF16x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4) { - return ctx.OpCompositeConstruct(ctx.F16[4], e1, e2, e3, e4); +Id EmitCompositeShuffleU32x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3) { + return ctx.OpVectorShuffle(ctx.U32[4], composite1, composite2, comp0, comp1, comp2, comp3); +} + +Id EmitCompositeConstructF16x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) { + return EmitCompositeConstruct(ctx, inst, ctx.F16[2], e1, e2); +} + +Id EmitCompositeConstructF16x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3) { + return EmitCompositeConstruct(ctx, inst, ctx.F16[3], e1, e2, e3); +} + +Id EmitCompositeConstructF16x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4) { + return EmitCompositeConstruct(ctx, inst, ctx.F16[4], e1, e2, e3, e4); } Id EmitCompositeExtractF16x2(EmitContext& ctx, Id composite, u32 index) { @@ -78,16 +98,30 @@ Id EmitCompositeInsertF16x4(EmitContext& ctx, Id composite, Id object, u32 index return ctx.OpCompositeInsert(ctx.F16[4], object, composite, index); } -Id EmitCompositeConstructF32x2(EmitContext& ctx, Id e1, Id e2) { - return ctx.OpCompositeConstruct(ctx.F32[2], e1, e2); +Id EmitCompositeShuffleF16x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1) { + return ctx.OpVectorShuffle(ctx.F16[2], composite1, composite2, comp0, comp1); } -Id EmitCompositeConstructF32x3(EmitContext& ctx, Id e1, Id e2, Id e3) { - return ctx.OpCompositeConstruct(ctx.F32[3], e1, e2, e3); +Id EmitCompositeShuffleF16x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2) { + return ctx.OpVectorShuffle(ctx.F16[3], composite1, composite2, comp0, comp1, comp2); } -Id EmitCompositeConstructF32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4) { - return ctx.OpCompositeConstruct(ctx.F32[4], e1, e2, e3, e4); +Id EmitCompositeShuffleF16x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3) { + return ctx.OpVectorShuffle(ctx.F16[4], composite1, composite2, comp0, comp1, comp2, comp3); +} + +Id EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) { + return EmitCompositeConstruct(ctx, inst, ctx.F32[2], e1, e2); +} + +Id EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3) { + return EmitCompositeConstruct(ctx, inst, ctx.F32[3], e1, e2, e3); +} + +Id EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4) { + return EmitCompositeConstruct(ctx, inst, ctx.F32[4], e1, e2, e3, e4); } Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index) { @@ -114,6 +148,20 @@ Id EmitCompositeInsertF32x4(EmitContext& ctx, Id composite, Id object, u32 index return ctx.OpCompositeInsert(ctx.F32[4], object, composite, index); } +Id EmitCompositeShuffleF32x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1) { + return ctx.OpVectorShuffle(ctx.F32[2], composite1, composite2, comp0, comp1); +} + +Id EmitCompositeShuffleF32x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2) { + return ctx.OpVectorShuffle(ctx.F32[3], composite1, composite2, comp0, comp1, comp2); +} + +Id EmitCompositeShuffleF32x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3) { + return ctx.OpVectorShuffle(ctx.F32[4], composite1, composite2, comp0, comp1, comp2, comp3); +} + void EmitCompositeConstructF64x2(EmitContext&) { UNREACHABLE_MSG("SPIR-V Instruction"); } @@ -150,4 +198,18 @@ Id EmitCompositeInsertF64x4(EmitContext& ctx, Id composite, Id object, u32 index return ctx.OpCompositeInsert(ctx.F64[4], object, composite, index); } +Id EmitCompositeShuffleF64x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1) { + return ctx.OpVectorShuffle(ctx.F64[2], composite1, composite2, comp0, comp1); +} + +Id EmitCompositeShuffleF64x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2) { + return ctx.OpVectorShuffle(ctx.F64[3], composite1, composite2, comp0, comp1, comp2); +} + +Id EmitCompositeShuffleF64x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3) { + return ctx.OpVectorShuffle(ctx.F64[4], composite1, composite2, comp0, comp1, comp2, comp3); +} + } // 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 f3db6af56..4550440bb 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 @@ -217,14 +217,6 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, Id index) { const auto pointer{ ctx.OpAccessChain(component_ptr, ctx.tess_coord, ctx.ConstU32(component))}; return ctx.OpLoad(ctx.F32[1], pointer); - } else if (IR::IsParam(attr)) { - const u32 param_id{u32(attr) - u32(IR::Attribute::Param0)}; - const auto param = ctx.input_params.at(param_id).id; - const auto param_arr_ptr = ctx.TypePointer(spv::StorageClass::Input, ctx.F32[4]); - const auto pointer{ctx.OpAccessChain(param_arr_ptr, param, index)}; - const auto position_comp_ptr = ctx.TypePointer(spv::StorageClass::Input, ctx.F32[1]); - return ctx.OpLoad(ctx.F32[1], - ctx.OpAccessChain(position_comp_ptr, pointer, ctx.ConstU32(comp))); } UNREACHABLE(); } @@ -351,6 +343,13 @@ Id EmitGetTessGenericAttribute(EmitContext& ctx, Id vertex_index, Id attr_index, vertex_index, attr_index, comp_index)); } +Id EmitReadTcsGenericOuputAttribute(EmitContext& ctx, Id vertex_index, Id attr_index, + Id comp_index) { + const auto attr_comp_ptr = ctx.TypePointer(spv::StorageClass::Output, ctx.F32[1]); + return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(attr_comp_ptr, ctx.output_attr_array, + vertex_index, attr_index, comp_index)); +} + void EmitSetTcsGenericAttribute(EmitContext& ctx, Id value, Id attr_index, Id comp_index) { // Implied vertex index is invocation_id const auto component_ptr = ctx.TypePointer(spv::StorageClass::Output, ctx.F32[1]); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 2946edab3..b5ae507a0 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -172,20 +172,18 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); const auto sharp = ctx.info.images[handle & 0xFFFF].GetSharp(ctx.info); - const auto type = sharp.GetBoundType(); const Id zero = ctx.u32_zero_value; const auto mips{[&] { return has_mips ? ctx.OpImageQueryLevels(ctx.U32[1], image) : zero; }}; - const bool uses_lod{type != AmdGpu::ImageType::Color2DMsaa && !texture.is_storage}; + const bool uses_lod{texture.view_type != AmdGpu::ImageType::Color2DMsaa && !texture.is_storage}; const auto query{[&](Id type) { return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod) : ctx.OpImageQuerySize(type, image); }}; - switch (type) { + switch (texture.view_type) { case AmdGpu::ImageType::Color1D: return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); case AmdGpu::ImageType::Color1DArray: case AmdGpu::ImageType::Color2D: - case AmdGpu::ImageType::Cube: case AmdGpu::ImageType::Color2DMsaa: return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips()); case AmdGpu::ImageType::Color2DArray: @@ -238,7 +236,7 @@ Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod } texel = ctx.OpImageRead(color_type, image, coords, operands.mask, operands.operands); } - return !texture.is_integer ? ctx.OpBitcast(ctx.U32[4], texel) : texel; + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texel) : texel; } void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms, @@ -253,8 +251,24 @@ void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id } else if (Sirit::ValidId(lod)) { LOG_WARNING(Render, "Image write with LOD not supported by driver"); } - ctx.OpImageWrite(image, coords, ctx.OpBitcast(color_type, color), operands.mask, - operands.operands); + const Id texel = texture.is_integer ? ctx.OpBitcast(color_type, color) : color; + ctx.OpImageWrite(image, coords, texel, operands.mask, operands.operands); +} + +Id EmitCubeFaceCoord(EmitContext& ctx, IR::Inst* inst, Id cube_coords) { + if (ctx.profile.supports_native_cube_calc) { + return ctx.OpCubeFaceCoordAMD(ctx.F32[2], cube_coords); + } else { + UNREACHABLE_MSG("SPIR-V Instruction"); + } +} + +Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id cube_coords) { + if (ctx.profile.supports_native_cube_calc) { + return ctx.OpCubeFaceIndexAMD(ctx.F32[1], cube_coords); + } else { + UNREACHABLE_MSG("SPIR-V Instruction"); + } } } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 2f606eb45..37b6f7786 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -89,6 +89,8 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp); void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, u32 comp); Id EmitGetTessGenericAttribute(EmitContext& ctx, Id vertex_index, Id attr_index, Id comp_index); void EmitSetTcsGenericAttribute(EmitContext& ctx, Id value, Id attr_index, Id comp_index); +Id EmitReadTcsGenericOuputAttribute(EmitContext& ctx, Id vertex_index, Id attr_index, + Id comp_index); Id EmitGetPatch(EmitContext& ctx, IR::Patch patch); void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value); void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value); @@ -118,33 +120,48 @@ Id EmitSharedAtomicSMin32(EmitContext& ctx, Id offset, Id value); Id EmitSharedAtomicAnd32(EmitContext& ctx, Id offset, Id value); Id EmitSharedAtomicOr32(EmitContext& ctx, Id offset, Id value); Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value); -Id EmitCompositeConstructU32x2(EmitContext& ctx, Id e1, Id e2); -Id EmitCompositeConstructU32x3(EmitContext& ctx, Id e1, Id e2, Id e3); -Id EmitCompositeConstructU32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4); +Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); +Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3); +Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4); Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeExtractU32x3(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeExtractU32x4(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeInsertU32x2(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertU32x3(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertU32x4(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeConstructF16x2(EmitContext& ctx, Id e1, Id e2); -Id EmitCompositeConstructF16x3(EmitContext& ctx, Id e1, Id e2, Id e3); -Id EmitCompositeConstructF16x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4); +Id EmitCompositeShuffleU32x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1); +Id EmitCompositeShuffleU32x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2); +Id EmitCompositeShuffleU32x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3); +Id EmitCompositeConstructF16x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); +Id EmitCompositeConstructF16x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3); +Id EmitCompositeConstructF16x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4); Id EmitCompositeExtractF16x2(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeExtractF16x3(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeExtractF16x4(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeInsertF16x2(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertF16x3(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertF16x4(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeConstructF32x2(EmitContext& ctx, Id e1, Id e2); -Id EmitCompositeConstructF32x3(EmitContext& ctx, Id e1, Id e2, Id e3); -Id EmitCompositeConstructF32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4); +Id EmitCompositeShuffleF16x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1); +Id EmitCompositeShuffleF16x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2); +Id EmitCompositeShuffleF16x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3); +Id EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); +Id EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3); +Id EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4); Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeExtractF32x3(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeExtractF32x4(EmitContext& ctx, Id composite, u32 index); Id EmitCompositeInsertF32x2(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertF32x3(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertF32x4(EmitContext& ctx, Id composite, Id object, u32 index); +Id EmitCompositeShuffleF32x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1); +Id EmitCompositeShuffleF32x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2); +Id EmitCompositeShuffleF32x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3); void EmitCompositeConstructF64x2(EmitContext& ctx); void EmitCompositeConstructF64x3(EmitContext& ctx); void EmitCompositeConstructF64x4(EmitContext& ctx); @@ -154,6 +171,11 @@ void EmitCompositeExtractF64x4(EmitContext& ctx); Id EmitCompositeInsertF64x2(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertF64x3(EmitContext& ctx, Id composite, Id object, u32 index); Id EmitCompositeInsertF64x4(EmitContext& ctx, Id composite, Id object, u32 index); +Id EmitCompositeShuffleF64x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1); +Id EmitCompositeShuffleF64x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2); +Id EmitCompositeShuffleF64x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, + u32 comp2, u32 comp3); Id EmitSelectU1(EmitContext& ctx, Id cond, Id true_value, Id false_value); Id EmitSelectU8(EmitContext& ctx, Id cond, Id true_value, Id false_value); Id EmitSelectU16(EmitContext& ctx, Id cond, Id true_value, Id false_value); @@ -304,10 +326,12 @@ Id EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, Id base, Id offset, Id Id EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, Id base, Id offset, Id count); Id EmitBitReverse32(EmitContext& ctx, Id value); Id EmitBitCount32(EmitContext& ctx, Id value); +Id EmitBitCount64(EmitContext& ctx, Id value); Id EmitBitwiseNot32(EmitContext& ctx, Id value); Id EmitFindSMsb32(EmitContext& ctx, Id value); Id EmitFindUMsb32(EmitContext& ctx, Id value); Id EmitFindILsb32(EmitContext& ctx, Id value); +Id EmitFindILsb64(EmitContext& ctx, Id value); Id EmitSMin32(EmitContext& ctx, Id a, Id b); Id EmitUMin32(EmitContext& ctx, Id a, Id b); Id EmitSMax32(EmitContext& ctx, Id a, Id b); @@ -318,7 +342,8 @@ Id EmitSLessThan32(EmitContext& ctx, Id lhs, Id rhs); Id EmitSLessThan64(EmitContext& ctx, Id lhs, Id rhs); Id EmitULessThan32(EmitContext& ctx, Id lhs, Id rhs); Id EmitULessThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs); +Id EmitIEqual32(EmitContext& ctx, Id lhs, Id rhs); +Id EmitIEqual64(EmitContext& ctx, Id lhs, Id rhs); Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs); Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs); Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); @@ -414,6 +439,8 @@ Id EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); Id EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); +Id EmitCubeFaceCoord(EmitContext& ctx, IR::Inst* inst, Id cube_coords); +Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id cube_coords); Id EmitLaneId(EmitContext& ctx); Id EmitWarpId(EmitContext& ctx); Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index 02af92385..70411ecec 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -201,6 +201,17 @@ Id EmitBitCount32(EmitContext& ctx, Id value) { return ctx.OpBitCount(ctx.U32[1], value); } +Id EmitBitCount64(EmitContext& ctx, Id value) { + // Vulkan restricts some bitwise operations to 32-bit only, so decompose into + // two 32-bit values and add the result. + const Id unpacked{ctx.OpBitcast(ctx.U32[2], value)}; + const Id lo{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 0U)}; + const Id hi{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 1U)}; + const Id lo_count{ctx.OpBitCount(ctx.U32[1], lo)}; + const Id hi_count{ctx.OpBitCount(ctx.U32[1], hi)}; + return ctx.OpIAdd(ctx.U32[1], lo_count, hi_count); +} + Id EmitBitwiseNot32(EmitContext& ctx, Id value) { return ctx.OpNot(ctx.U32[1], value); } @@ -217,6 +228,18 @@ Id EmitFindILsb32(EmitContext& ctx, Id value) { return ctx.OpFindILsb(ctx.U32[1], value); } +Id EmitFindILsb64(EmitContext& ctx, Id value) { + // Vulkan restricts some bitwise operations to 32-bit only, so decompose into + // two 32-bit values and select the correct result. + const Id unpacked{ctx.OpBitcast(ctx.U32[2], value)}; + const Id lo{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 0U)}; + const Id hi{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 1U)}; + const Id lo_lsb{ctx.OpFindILsb(ctx.U32[1], lo)}; + const Id hi_lsb{ctx.OpFindILsb(ctx.U32[1], hi)}; + const Id found_lo{ctx.OpINotEqual(ctx.U32[1], lo_lsb, ctx.ConstU32(u32(-1)))}; + return ctx.OpSelect(ctx.U32[1], found_lo, lo_lsb, hi_lsb); +} + Id EmitSMin32(EmitContext& ctx, Id a, Id b) { return ctx.OpSMin(ctx.U32[1], a, b); } @@ -277,7 +300,11 @@ Id EmitULessThan64(EmitContext& ctx, Id lhs, Id rhs) { return ctx.OpULessThan(ctx.U1[1], lhs, rhs); } -Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs) { +Id EmitIEqual32(EmitContext& ctx, Id lhs, Id rhs) { + return ctx.OpIEqual(ctx.U1[1], lhs, rhs); +} + +Id EmitIEqual64(EmitContext& ctx, Id lhs, Id rhs) { return ctx.OpIEqual(ctx.U1[1], lhs, rhs); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index d8bafccd9..7e86dfb4b 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -43,9 +43,11 @@ static constexpr u32 NumVertices(AmdGpu::PrimitiveType type) { case AmdGpu::PrimitiveType::PointList: return 1u; case AmdGpu::PrimitiveType::LineList: + case AmdGpu::PrimitiveType::LineStrip: return 2u; case AmdGpu::PrimitiveType::TriangleList: case AmdGpu::PrimitiveType::TriangleStrip: + case AmdGpu::PrimitiveType::RectList: return 3u; case AmdGpu::PrimitiveType::AdjTriangleList: return 6u; @@ -771,8 +773,8 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { const auto image = desc.GetSharp(ctx.info); const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown; - const auto type = image.GetBoundType(); - const u32 sampled = desc.IsStorage(image) ? 2 : 1; + const auto type = image.GetViewType(desc.is_array); + const u32 sampled = desc.is_written ? 2 : 1; switch (type) { case AmdGpu::ImageType::Color1D: return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, sampled, format); @@ -786,9 +788,6 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, true, sampled, format); case AmdGpu::ImageType::Color3D: return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, sampled, format); - case AmdGpu::ImageType::Cube: - return ctx.TypeImage(sampled_type, spv::Dim::Cube, false, desc.is_array, false, sampled, - format); default: break; } @@ -800,7 +799,7 @@ void EmitContext::DefineImagesAndSamplers() { const auto sharp = image_desc.GetSharp(info); const auto nfmt = sharp.GetNumberFmt(); const bool is_integer = AmdGpu::IsInteger(nfmt); - const bool is_storage = image_desc.IsStorage(sharp); + const bool is_storage = image_desc.is_written; const VectorIds& data_types = GetAttributeType(*this, nfmt); const Id sampled_type = data_types[1]; const Id image_type{ImageType(*this, image_desc, sampled_type)}; @@ -815,6 +814,7 @@ void EmitContext::DefineImagesAndSamplers() { .sampled_type = is_storage ? sampled_type : TypeSampledImage(image_type), .pointer_type = pointer_type, .image_type = image_type, + .view_type = sharp.GetViewType(image_desc.is_array), .is_integer = is_integer, .is_storage = is_storage, }); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 583d96b99..f552055c0 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -222,6 +222,7 @@ public: Id sampled_type; Id pointer_type; Id image_type; + AmdGpu::ImageType view_type; bool is_integer = false; bool is_storage = false; }; diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp index 0816ec088..ec5c117f7 100644 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ b/src/shader_recompiler/frontend/control_flow_graph.cpp @@ -47,13 +47,26 @@ static IR::Condition MakeCondition(const GcnInst& inst) { } } -static bool IgnoresExecMask(Opcode opcode) { - switch (opcode) { - case Opcode::V_WRITELANE_B32: +static bool IgnoresExecMask(const GcnInst& inst) { + // EXEC mask does not affect scalar instructions or branches. + switch (inst.category) { + case InstCategory::ScalarALU: + case InstCategory::ScalarMemory: + case InstCategory::FlowControl: return true; default: - return false; + break; } + // Read/Write Lane instructions are not affected either. + switch (inst.opcode) { + case Opcode::V_READLANE_B32: + case Opcode::V_WRITELANE_B32: + case Opcode::V_READFIRSTLANE_B32: + return true; + default: + break; + } + return false; } static constexpr size_t LabelReserveSize = 32; @@ -147,8 +160,7 @@ void CFG::EmitDivergenceLabels() { // If all instructions in the scope ignore exec masking, we shouldn't insert a // scope. const auto start = inst_list.begin() + curr_begin + 1; - if (!std::ranges::all_of(start, inst_list.begin() + index, IgnoresExecMask, - &GcnInst::opcode)) { + if (!std::ranges::all_of(start, inst_list.begin() + index, IgnoresExecMask)) { // Add a label to the instruction right after the open scope call. // It is the start of a new basic block. const auto& save_inst = inst_list[curr_begin]; diff --git a/src/shader_recompiler/frontend/format.cpp b/src/shader_recompiler/frontend/format.cpp index 4f0922e2e..9677be3e5 100644 --- a/src/shader_recompiler/frontend/format.cpp +++ b/src/shader_recompiler/frontend/format.cpp @@ -3565,8 +3565,8 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, ScalarType::Float32}, // 64 = IMAGE_GATHER4 - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 65 = IMAGE_GATHER4_CL {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, @@ -3603,10 +3603,10 @@ constexpr std::array InstructionFormatMIMG = {{ ScalarType::Undefined}, // 79 = IMAGE_GATHER4_C_LZ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, + ScalarType::Float32}, // 80 = IMAGE_GATHER4_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 81 = IMAGE_GATHER4_CL_O {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index 4408cae28..62c0423dd 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -205,7 +205,6 @@ void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool strid addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0))); ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0); } - emit_ds_read_barrier = true; } void Translator::DS_SWIZZLE_B32(const GcnInst& inst) { @@ -222,11 +221,6 @@ void Translator::DS_SWIZZLE_B32(const GcnInst& inst) { void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst) { - if (emit_ds_read_barrier && profile.needs_lds_barriers) { - ir.Barrier(); - emit_ds_read_barrier = false; - } - const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; IR::VectorReg dst_reg{inst.dst[0].code}; if (is_pair) { diff --git a/src/shader_recompiler/frontend/translate/export.cpp b/src/shader_recompiler/frontend/translate/export.cpp index 5927aa696..38ff9ae14 100644 --- a/src/shader_recompiler/frontend/translate/export.cpp +++ b/src/shader_recompiler/frontend/translate/export.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "shader_recompiler/frontend/translate/translate.h" +#include "shader_recompiler/ir/reinterpret.h" #include "shader_recompiler/runtime_info.h" namespace Shader::Gcn { @@ -25,34 +26,30 @@ void Translator::EmitExport(const GcnInst& inst) { IR::VectorReg(inst.src[3].code), }; - const auto swizzle = [&](u32 comp) { + const auto set_attribute = [&](u32 comp, IR::F32 value) { if (!IR::IsMrt(attrib)) { - return comp; + ir.SetAttribute(attrib, value, comp); + return; } const u32 index = u32(attrib) - u32(IR::Attribute::RenderTarget0); - switch (runtime_info.fs_info.color_buffers[index].mrt_swizzle) { - case MrtSwizzle::Identity: - return comp; - case MrtSwizzle::Alt: - static constexpr std::array AltSwizzle = {2, 1, 0, 3}; - return AltSwizzle[comp]; - case MrtSwizzle::Reverse: - static constexpr std::array RevSwizzle = {3, 2, 1, 0}; - return RevSwizzle[comp]; - case MrtSwizzle::ReverseAlt: - static constexpr std::array AltRevSwizzle = {3, 0, 1, 2}; - return AltRevSwizzle[comp]; - default: - UNREACHABLE(); + const auto col_buf = runtime_info.fs_info.color_buffers[index]; + const auto converted = IR::ApplyWriteNumberConversion(ir, value, col_buf.num_conversion); + const auto [r, g, b, a] = col_buf.swizzle; + const std::array swizzle_array = {r, g, b, a}; + const auto swizzled_comp = swizzle_array[comp]; + if (u32(swizzled_comp) < u32(AmdGpu::CompSwizzle::Red)) { + ir.SetAttribute(attrib, converted, comp); + return; } + ir.SetAttribute(attrib, converted, u32(swizzled_comp) - u32(AmdGpu::CompSwizzle::Red)); }; const auto unpack = [&](u32 idx) { const IR::Value value = ir.UnpackHalf2x16(ir.GetVectorReg(vsrc[idx])); const IR::F32 r = IR::F32{ir.CompositeExtract(value, 0)}; const IR::F32 g = IR::F32{ir.CompositeExtract(value, 1)}; - ir.SetAttribute(attrib, r, swizzle(idx * 2)); - ir.SetAttribute(attrib, g, swizzle(idx * 2 + 1)); + set_attribute(idx * 2, r); + set_attribute(idx * 2 + 1, g); }; // Components are float16 packed into a VGPR @@ -73,7 +70,7 @@ void Translator::EmitExport(const GcnInst& inst) { continue; } const IR::F32 comp = ir.GetVectorReg(vsrc[i]); - ir.SetAttribute(attrib, comp, swizzle(i)); + set_attribute(i, comp); } } if (IR::IsMrt(attrib)) { diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index f96fd0f40..7f34126f5 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -100,8 +100,16 @@ void Translator::EmitScalarAlu(const GcnInst& inst) { return S_BREV_B32(inst); case Opcode::S_BCNT1_I32_B32: return S_BCNT1_I32_B32(inst); + case Opcode::S_BCNT1_I32_B64: + return S_BCNT1_I32_B64(inst); case Opcode::S_FF1_I32_B32: return S_FF1_I32_B32(inst); + case Opcode::S_FF1_I32_B64: + return S_FF1_I32_B64(inst); + case Opcode::S_BITSET0_B32: + return S_BITSET_B32(inst, 0); + case Opcode::S_BITSET1_B32: + return S_BITSET_B32(inst, 1); case Opcode::S_AND_SAVEEXEC_B64: return S_SAVEEXEC_B64(NegateMode::None, false, inst); case Opcode::S_ORN2_SAVEEXEC_B64: @@ -585,9 +593,28 @@ void Translator::S_BCNT1_I32_B32(const GcnInst& inst) { ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); } +void Translator::S_BCNT1_I32_B64(const GcnInst& inst) { + const IR::U32 result = ir.BitCount(GetSrc64(inst.src[0])); + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + void Translator::S_FF1_I32_B32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 result{ir.Select(ir.IEqual(src0, ir.Imm32(0U)), ir.Imm32(-1), ir.FindILsb(src0))}; + const IR::U32 result{ir.FindILsb(src0)}; + SetDst(inst.dst[0], result); +} + +void Translator::S_FF1_I32_B64(const GcnInst& inst) { + const IR::U64 src0{GetSrc64(inst.src[0])}; + const IR::U32 result{ir.FindILsb(src0)}; + SetDst(inst.dst[0], result); +} + +void Translator::S_BITSET_B32(const GcnInst& inst, u32 bit_value) { + const IR::U32 old_value{GetSrc(inst.dst[0])}; + const IR::U32 offset{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0U), ir.Imm32(5U))}; + const IR::U32 result{ir.BitFieldInsert(old_value, ir.Imm32(bit_value), offset, ir.Imm32(1U))}; SetDst(inst.dst[0], result); } diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index a14bff706..7f5504663 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -10,6 +10,7 @@ #include "shader_recompiler/info.h" #include "shader_recompiler/ir/attribute.h" #include "shader_recompiler/ir/reg.h" +#include "shader_recompiler/ir/reinterpret.h" #include "shader_recompiler/runtime_info.h" #include "video_core/amdgpu/resource.h" #include "video_core/amdgpu/types.h" @@ -124,12 +125,12 @@ void Translator::EmitPrologue() { } break; case LogicalStage::TessellationControl: { + ir.SetVectorReg(IR::VectorReg::V0, ir.GetAttributeU32(IR::Attribute::PrimitiveId)); // Should be laid out like: // [0:8]: patch id within VGT // [8:12]: output control point id ir.SetVectorReg(IR::VectorReg::V1, ir.GetAttributeU32(IR::Attribute::PackedHullInvocationInfo)); - // TODO PrimitiveId is probably V2 but haven't seen it yet break; } case LogicalStage::TessellationEval: @@ -475,26 +476,12 @@ void Translator::EmitFetch(const GcnInst& inst) { // Read the V# of the attribute to figure out component number and type. const auto buffer = info.ReadUdReg(attrib.sgpr_base, attrib.dword_offset); + const auto values = + ir.CompositeConstruct(ir.GetAttribute(attr, 0), ir.GetAttribute(attr, 1), + ir.GetAttribute(attr, 2), ir.GetAttribute(attr, 3)); + const auto swizzled = ApplySwizzle(ir, values, buffer.DstSelect()); for (u32 i = 0; i < 4; i++) { - const IR::F32 comp = [&] { - switch (buffer.GetSwizzle(i)) { - case AmdGpu::CompSwizzle::One: - return ir.Imm32(1.f); - case AmdGpu::CompSwizzle::Zero: - return ir.Imm32(0.f); - case AmdGpu::CompSwizzle::Red: - return ir.GetAttribute(attr, 0); - case AmdGpu::CompSwizzle::Green: - return ir.GetAttribute(attr, 1); - case AmdGpu::CompSwizzle::Blue: - return ir.GetAttribute(attr, 2); - case AmdGpu::CompSwizzle::Alpha: - return ir.GetAttribute(attr, 3); - default: - UNREACHABLE(); - } - }(); - ir.SetVectorReg(dst_reg++, comp); + ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(swizzled, i)}); } // In case of programmable step rates we need to fallback to instance data pulling in diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index fd4d8d86a..bef61f997 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -111,7 +111,10 @@ public: void S_NOT_B64(const GcnInst& inst); void S_BREV_B32(const GcnInst& inst); void S_BCNT1_I32_B32(const GcnInst& inst); + void S_BCNT1_I32_B64(const GcnInst& inst); void S_FF1_I32_B32(const GcnInst& inst); + void S_FF1_I32_B64(const GcnInst& inst); + void S_BITSET_B32(const GcnInst& inst, u32 bit_value); void S_GETPC_B64(u32 pc, const GcnInst& inst); void S_SAVEEXEC_B64(NegateMode negate, bool is_or, const GcnInst& inst); void S_ABS_I32(const GcnInst& inst); @@ -298,6 +301,9 @@ private: IR::U32 VMovRelSHelper(u32 src_vgprno, const IR::U32 m0); void VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, const IR::U32 m0); + IR::F32 SelectCubeResult(const IR::F32& x, const IR::F32& y, const IR::F32& z, + const IR::F32& x_res, const IR::F32& y_res, const IR::F32& z_res); + void LogMissingOpcode(const GcnInst& inst); private: @@ -306,7 +312,6 @@ private: const RuntimeInfo& runtime_info; const Profile& profile; bool opcode_missing = false; - bool emit_ds_read_barrier = false; }; void Translate(IR::Block* block, u32 block_base, std::span inst_list, Info& info, diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 2b32ca2ce..375c5f078 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -3,6 +3,7 @@ #include "shader_recompiler/frontend/opcodes.h" #include "shader_recompiler/frontend/translate/translate.h" +#include "shader_recompiler/profile.h" namespace Shader::Gcn { @@ -904,7 +905,7 @@ void Translator::V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst) { case ConditionOp::GE: return ir.FPGreaterThanEqual(src0, src1); case ConditionOp::U: - return ir.LogicalNot(ir.LogicalAnd(ir.FPIsNan(src0), ir.FPIsNan(src1))); + return ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)); default: UNREACHABLE(); } @@ -1042,20 +1043,92 @@ void Translator::V_MAD_U32_U24(const GcnInst& inst) { V_MAD_I32_I24(inst, false); } +IR::F32 Translator::SelectCubeResult(const IR::F32& x, const IR::F32& y, const IR::F32& z, + const IR::F32& x_res, const IR::F32& y_res, + const IR::F32& z_res) { + const auto abs_x = ir.FPAbs(x); + const auto abs_y = ir.FPAbs(y); + const auto abs_z = ir.FPAbs(z); + + const auto z_face_cond{ + ir.LogicalAnd(ir.FPGreaterThanEqual(abs_z, abs_x), ir.FPGreaterThanEqual(abs_z, abs_y))}; + const auto y_face_cond{ir.FPGreaterThanEqual(abs_y, abs_x)}; + + return IR::F32{ir.Select(z_face_cond, z_res, ir.Select(y_face_cond, y_res, x_res))}; +} + void Translator::V_CUBEID_F32(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[2])); + const auto x = GetSrc(inst.src[0]); + const auto y = GetSrc(inst.src[1]); + const auto z = GetSrc(inst.src[2]); + + IR::F32 result; + if (profile.supports_native_cube_calc) { + result = ir.CubeFaceIndex(ir.CompositeConstruct(x, y, z)); + } else { + const auto x_neg_cond{ir.FPLessThan(x, ir.Imm32(0.f))}; + const auto y_neg_cond{ir.FPLessThan(y, ir.Imm32(0.f))}; + const auto z_neg_cond{ir.FPLessThan(z, ir.Imm32(0.f))}; + const IR::F32 x_face{ir.Select(x_neg_cond, ir.Imm32(5.f), ir.Imm32(4.f))}; + const IR::F32 y_face{ir.Select(y_neg_cond, ir.Imm32(3.f), ir.Imm32(2.f))}; + const IR::F32 z_face{ir.Select(z_neg_cond, ir.Imm32(1.f), ir.Imm32(0.f))}; + + result = SelectCubeResult(x, y, z, x_face, y_face, z_face); + } + SetDst(inst.dst[0], result); } void Translator::V_CUBESC_F32(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[0])); + const auto x = GetSrc(inst.src[0]); + const auto y = GetSrc(inst.src[1]); + const auto z = GetSrc(inst.src[2]); + + IR::F32 result; + if (profile.supports_native_cube_calc) { + const auto coords{ir.CubeFaceCoord(ir.CompositeConstruct(x, y, z))}; + result = IR::F32{ir.CompositeExtract(coords, 0)}; + } else { + const auto x_neg_cond{ir.FPLessThan(x, ir.Imm32(0.f))}; + const auto z_neg_cond{ir.FPLessThan(z, ir.Imm32(0.f))}; + const IR::F32 x_sc{ir.Select(x_neg_cond, ir.FPNeg(x), x)}; + const IR::F32 z_sc{ir.Select(z_neg_cond, z, ir.FPNeg(z))}; + + result = SelectCubeResult(x, y, z, x_sc, x, z_sc); + } + SetDst(inst.dst[0], result); } void Translator::V_CUBETC_F32(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[1])); + const auto x = GetSrc(inst.src[0]); + const auto y = GetSrc(inst.src[1]); + const auto z = GetSrc(inst.src[2]); + + IR::F32 result; + if (profile.supports_native_cube_calc) { + const auto coords{ir.CubeFaceCoord(ir.CompositeConstruct(x, y, z))}; + result = IR::F32{ir.CompositeExtract(coords, 1)}; + } else { + const auto y_neg_cond{ir.FPLessThan(y, ir.Imm32(0.f))}; + const IR::F32 x_z_sc{ir.FPNeg(y)}; + const IR::F32 y_sc{ir.Select(y_neg_cond, ir.FPNeg(z), z)}; + + result = SelectCubeResult(x, y, z, x_z_sc, y_sc, x_z_sc); + } + SetDst(inst.dst[0], result); } void Translator::V_CUBEMA_F32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.Imm32(1.f)); + const auto x = GetSrc(inst.src[0]); + const auto y = GetSrc(inst.src[1]); + const auto z = GetSrc(inst.src[2]); + + const auto two{ir.Imm32(4.f)}; + const IR::F32 x_major_axis{ir.FPMul(x, two)}; + const IR::F32 y_major_axis{ir.FPMul(y, two)}; + const IR::F32 z_major_axis{ir.FPMul(z, two)}; + + const auto result{SelectCubeResult(x, y, z, x_major_axis, y_major_axis, z_major_axis)}; + SetDst(inst.dst[0], result); } void Translator::V_BFE_U32(bool is_signed, const GcnInst& inst) { diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 48cb79610..a5b54dff7 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -144,8 +144,10 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { return IMAGE_SAMPLE(inst); // Image gather operations + case Opcode::IMAGE_GATHER4: case Opcode::IMAGE_GATHER4_LZ: case Opcode::IMAGE_GATHER4_C: + case Opcode::IMAGE_GATHER4_O: case Opcode::IMAGE_GATHER4_C_O: case Opcode::IMAGE_GATHER4_C_LZ: case Opcode::IMAGE_GATHER4_LZ_O: @@ -253,10 +255,6 @@ void Translator::BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst "Non immediate offset not supported"); } - if (info.stage == Stage::Hull) { - // printf("here\n"); // break - } - IR::Value address = [&] -> IR::Value { if (is_ring) { return ir.CompositeConstruct(ir.GetVectorReg(vaddr), soffset); @@ -328,7 +326,7 @@ void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst) { const IR::VectorReg src_reg{inst.src[1].code}; - std::array comps{}; + std::array comps{}; for (u32 i = 0; i < num_dwords; i++) { comps[i] = ir.GetVectorReg(src_reg + i); } @@ -420,13 +418,14 @@ void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) { IR::TextureInstInfo info{}; info.has_lod.Assign(has_mip); + info.is_array.Assign(mimg.da); const IR::Value texel = ir.ImageRead(handle, body, {}, {}, info); for (u32 i = 0; i < 4; i++) { if (((mimg.dmask >> i) & 1) == 0) { continue; } - IR::U32 value = IR::U32{ir.CompositeExtract(texel, i)}; + IR::F32 value = IR::F32{ir.CompositeExtract(texel, i)}; ir.SetVectorReg(dest_reg++, value); } } @@ -444,6 +443,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) { IR::TextureInstInfo info{}; info.has_lod.Assign(has_mip); + info.is_array.Assign(mimg.da); boost::container::static_vector comps; for (u32 i = 0; i < 4; i++) { @@ -458,13 +458,18 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) { } void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { + const auto& mimg = inst.control.mimg; IR::VectorReg dst_reg{inst.dst[0].code}; const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; const auto flags = ImageResFlags(inst.control.mimg.dmask); const bool has_mips = flags.test(ImageResComponent::MipCount); const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code)); const IR::Value tsharp = ir.GetScalarReg(tsharp_reg); - const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips)); + + IR::TextureInstInfo info{}; + info.is_array.Assign(mimg.da); + + const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips), info); if (flags.test(ImageResComponent::Width)) { ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)}); @@ -486,6 +491,9 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) { IR::VectorReg addr_reg{inst.src[0].code}; const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; + IR::TextureInstInfo info{}; + info.is_array.Assign(mimg.da); + const IR::Value value = ir.GetVectorReg(val_reg); const IR::Value handle = ir.GetScalarReg(tsharp_reg); const IR::Value body = @@ -496,25 +504,25 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) { case AtomicOp::Swap: return ir.ImageAtomicExchange(handle, body, value, {}); case AtomicOp::Add: - return ir.ImageAtomicIAdd(handle, body, value, {}); + return ir.ImageAtomicIAdd(handle, body, value, info); case AtomicOp::Smin: - return ir.ImageAtomicIMin(handle, body, value, true, {}); + return ir.ImageAtomicIMin(handle, body, value, true, info); case AtomicOp::Umin: - return ir.ImageAtomicUMin(handle, body, value, {}); + return ir.ImageAtomicUMin(handle, body, value, info); case AtomicOp::Smax: - return ir.ImageAtomicIMax(handle, body, value, true, {}); + return ir.ImageAtomicIMax(handle, body, value, true, info); case AtomicOp::Umax: - return ir.ImageAtomicUMax(handle, body, value, {}); + return ir.ImageAtomicUMax(handle, body, value, info); case AtomicOp::And: - return ir.ImageAtomicAnd(handle, body, value, {}); + return ir.ImageAtomicAnd(handle, body, value, info); case AtomicOp::Or: - return ir.ImageAtomicOr(handle, body, value, {}); + return ir.ImageAtomicOr(handle, body, value, info); case AtomicOp::Xor: - return ir.ImageAtomicXor(handle, body, value, {}); + return ir.ImageAtomicXor(handle, body, value, info); case AtomicOp::Inc: - return ir.ImageAtomicInc(handle, body, value, {}); + return ir.ImageAtomicInc(handle, body, value, info); case AtomicOp::Dec: - return ir.ImageAtomicDec(handle, body, value, {}); + return ir.ImageAtomicDec(handle, body, value, info); default: UNREACHABLE(); } @@ -645,11 +653,14 @@ void Translator::IMAGE_GET_LOD(const GcnInst& inst) { IR::VectorReg addr_reg{inst.src[0].code}; const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; + IR::TextureInstInfo info{}; + info.is_array.Assign(mimg.da); + const IR::Value handle = ir.GetScalarReg(tsharp_reg); const IR::Value body = ir.CompositeConstruct( ir.GetVectorReg(addr_reg), ir.GetVectorReg(addr_reg + 1), ir.GetVectorReg(addr_reg + 2), ir.GetVectorReg(addr_reg + 3)); - const IR::Value lod = ir.ImageQueryLod(handle, body, {}); + const IR::Value lod = ir.ImageQueryLod(handle, body, info); ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 0)}); ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)}); } diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h index b6ac12785..aeff346fa 100644 --- a/src/shader_recompiler/info.h +++ b/src/shader_recompiler/info.h @@ -70,14 +70,8 @@ struct ImageResource { bool is_depth{}; bool is_atomic{}; bool is_array{}; - bool is_read{}; bool is_written{}; - [[nodiscard]] bool IsStorage(const AmdGpu::Image& image) const noexcept { - // Need cube as storage when used with ImageRead. - return is_written || (is_read && image.GetBoundType() == AmdGpu::ImageType::Cube); - } - [[nodiscard]] constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; }; using ImageResourceList = boost::container::small_vector; diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index c241ec984..8626bdfd1 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -288,6 +288,12 @@ void IREmitter::SetTcsGenericAttribute(const F32& value, const U32& attr_index, Inst(Opcode::SetTcsGenericAttribute, value, attr_index, comp_index); } +F32 IREmitter::ReadTcsGenericOuputAttribute(const U32& vertex_index, const U32& attr_index, + const U32& comp_index) { + return Inst(IR::Opcode::ReadTcsGenericOuputAttribute, vertex_index, attr_index, + comp_index); +} + F32 IREmitter::GetPatch(Patch patch) { return Inst(Opcode::GetPatch, patch); } @@ -657,6 +663,86 @@ Value IREmitter::CompositeInsert(const Value& vector, const Value& object, size_ } } +Value IREmitter::CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, + size_t comp1) { + if (vector1.Type() != vector2.Type()) { + UNREACHABLE_MSG("Mismatching types {} and {}", vector1.Type(), vector2.Type()); + } + if (comp0 >= 4 || comp1 >= 4) { + UNREACHABLE_MSG("One or more out of bounds elements {}, {}", comp0, comp1); + } + const auto shuffle{[&](Opcode opcode) -> Value { + return Inst(opcode, vector1, vector2, Value{static_cast(comp0)}, + Value{static_cast(comp1)}); + }}; + switch (vector1.Type()) { + case Type::U32x4: + return shuffle(Opcode::CompositeShuffleU32x2); + case Type::F16x4: + return shuffle(Opcode::CompositeShuffleF16x2); + case Type::F32x4: + return shuffle(Opcode::CompositeShuffleF32x2); + case Type::F64x4: + return shuffle(Opcode::CompositeShuffleF64x2); + default: + ThrowInvalidType(vector1.Type()); + } +} + +Value IREmitter::CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, + size_t comp1, size_t comp2) { + if (vector1.Type() != vector2.Type()) { + UNREACHABLE_MSG("Mismatching types {} and {}", vector1.Type(), vector2.Type()); + } + if (comp0 >= 6 || comp1 >= 6 || comp2 >= 6) { + UNREACHABLE_MSG("One or more out of bounds elements {}, {}, {}", comp0, comp1, comp2); + } + const auto shuffle{[&](Opcode opcode) -> Value { + return Inst(opcode, vector1, vector2, Value{static_cast(comp0)}, + Value{static_cast(comp1)}, Value{static_cast(comp2)}); + }}; + switch (vector1.Type()) { + case Type::U32x4: + return shuffle(Opcode::CompositeShuffleU32x3); + case Type::F16x4: + return shuffle(Opcode::CompositeShuffleF16x3); + case Type::F32x4: + return shuffle(Opcode::CompositeShuffleF32x3); + case Type::F64x4: + return shuffle(Opcode::CompositeShuffleF64x3); + default: + ThrowInvalidType(vector1.Type()); + } +} + +Value IREmitter::CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, + size_t comp1, size_t comp2, size_t comp3) { + if (vector1.Type() != vector2.Type()) { + UNREACHABLE_MSG("Mismatching types {} and {}", vector1.Type(), vector2.Type()); + } + if (comp0 >= 8 || comp1 >= 8 || comp2 >= 8 || comp3 >= 8) { + UNREACHABLE_MSG("One or more out of bounds elements {}, {}, {}, {}", comp0, comp1, comp2, + comp3); + } + const auto shuffle{[&](Opcode opcode) -> Value { + return Inst(opcode, vector1, vector2, Value{static_cast(comp0)}, + Value{static_cast(comp1)}, Value{static_cast(comp2)}, + Value{static_cast(comp3)}); + }}; + switch (vector1.Type()) { + case Type::U32x4: + return shuffle(Opcode::CompositeShuffleU32x4); + case Type::F16x4: + return shuffle(Opcode::CompositeShuffleF16x4); + case Type::F32x4: + return shuffle(Opcode::CompositeShuffleF32x4); + case Type::F64x4: + return shuffle(Opcode::CompositeShuffleF64x4); + default: + ThrowInvalidType(vector1.Type()); + } +} + Value IREmitter::Select(const U1& condition, const Value& true_value, const Value& false_value) { if (true_value.Type() != false_value.Type()) { UNREACHABLE_MSG("Mismatching types {} and {}", true_value.Type(), false_value.Type()); @@ -1273,8 +1359,15 @@ U32 IREmitter::BitReverse(const U32& value) { return Inst(Opcode::BitReverse32, value); } -U32 IREmitter::BitCount(const U32& value) { - return Inst(Opcode::BitCount32, value); +U32 IREmitter::BitCount(const U32U64& value) { + switch (value.Type()) { + case Type::U32: + return Inst(Opcode::BitCount32, value); + case Type::U64: + return Inst(Opcode::BitCount64, value); + default: + ThrowInvalidType(value.Type()); + } } U32 IREmitter::BitwiseNot(const U32& value) { @@ -1289,8 +1382,15 @@ U32 IREmitter::FindUMsb(const U32& value) { return Inst(Opcode::FindUMsb32, value); } -U32 IREmitter::FindILsb(const U32& value) { - return Inst(Opcode::FindILsb32, value); +U32 IREmitter::FindILsb(const U32U64& value) { + switch (value.Type()) { + case Type::U32: + return Inst(Opcode::FindILsb32, value); + case Type::U64: + return Inst(Opcode::FindILsb64, value); + default: + ThrowInvalidType(value.Type()); + } } U32 IREmitter::SMin(const U32& a, const U32& b) { @@ -1345,7 +1445,9 @@ U1 IREmitter::IEqual(const U32U64& lhs, const U32U64& rhs) { } switch (lhs.Type()) { case Type::U32: - return Inst(Opcode::IEqual, lhs, rhs); + return Inst(Opcode::IEqual32, lhs, rhs); + case Type::U64: + return Inst(Opcode::IEqual64, lhs, rhs); default: ThrowInvalidType(lhs.Type()); } @@ -1630,11 +1732,6 @@ Value IREmitter::ImageGatherDref(const Value& handle, const Value& coords, const return Inst(Opcode::ImageGatherDref, Flags{info}, handle, coords, offset, dref); } -Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, - const IR::U1& skip_mips) { - return Inst(Opcode::ImageQueryDimensions, handle, lod, skip_mips); -} - Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, const IR::U1& skip_mips, TextureInstInfo info) { return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips); @@ -1661,6 +1758,14 @@ void IREmitter::ImageWrite(const Value& handle, const Value& coords, const U32& Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, multisampling, color); } +[[nodiscard]] Value IREmitter::CubeFaceCoord(const Value& cube_coords) { + return Inst(Opcode::CubeFaceCoord, cube_coords); +} + +[[nodiscard]] F32 IREmitter::CubeFaceIndex(const Value& cube_coords) { + return Inst(Opcode::CubeFaceIndex, cube_coords); +} + // Debug print maps to SPIRV's NonSemantic DebugPrintf instruction // Renderdoc will hook in its own implementation of the SPIRV instruction // Renderdoc accepts format specifiers, e.g. %u, listed here: diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 4cf44107e..783709775 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -90,6 +90,9 @@ public: const U32& comp_index); void SetTcsGenericAttribute(const F32& value, const U32& attr_index, const U32& comp_index); + [[nodiscard]] F32 ReadTcsGenericOuputAttribute(const U32& vertex_index, const U32& attr_index, + const U32& comp_index); + [[nodiscard]] F32 GetPatch(Patch patch); void SetPatch(Patch patch, const F32& value); @@ -152,6 +155,13 @@ public: [[nodiscard]] Value CompositeExtract(const Value& vector, size_t element); [[nodiscard]] Value CompositeInsert(const Value& vector, const Value& object, size_t element); + [[nodiscard]] Value CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, + size_t comp1); + [[nodiscard]] Value CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, + size_t comp1, size_t comp2); + [[nodiscard]] Value CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, + size_t comp1, size_t comp2, size_t comp3); + [[nodiscard]] Value Select(const U1& condition, const Value& true_value, const Value& false_value); @@ -229,12 +239,12 @@ public: [[nodiscard]] U32 BitFieldExtract(const U32& base, const U32& offset, const U32& count, bool is_signed = false); [[nodiscard]] U32 BitReverse(const U32& value); - [[nodiscard]] U32 BitCount(const U32& value); + [[nodiscard]] U32 BitCount(const U32U64& value); [[nodiscard]] U32 BitwiseNot(const U32& value); [[nodiscard]] U32 FindSMsb(const U32& value); [[nodiscard]] U32 FindUMsb(const U32& value); - [[nodiscard]] U32 FindILsb(const U32& value); + [[nodiscard]] U32 FindILsb(const U32U64& value); [[nodiscard]] U32 SMin(const U32& a, const U32& b); [[nodiscard]] U32 UMin(const U32& a, const U32& b); [[nodiscard]] U32 IMin(const U32& a, const U32& b, bool is_signed); @@ -314,8 +324,6 @@ public: const F32& dref, const F32& lod, const Value& offset, TextureInstInfo info); - [[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod, - const U1& skip_mips); [[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod, const U1& skip_mips, TextureInstInfo info); @@ -334,6 +342,9 @@ public: void ImageWrite(const Value& handle, const Value& coords, const U32& lod, const U32& multisampling, const Value& color, TextureInstInfo info); + [[nodiscard]] Value CubeFaceCoord(const Value& cube_coords); + [[nodiscard]] F32 CubeFaceIndex(const Value& cube_coords); + void EmitVertex(); void EmitPrimitive(); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index aafd43ea8..19f45418f 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -64,6 +64,8 @@ OPCODE(GetPatch, F32, Patc OPCODE(SetPatch, Void, Patch, F32, ) OPCODE(GetTessGenericAttribute, F32, U32, U32, U32, ) OPCODE(SetTcsGenericAttribute, Void, F32, U32, U32, ) +OPCODE(ReadTcsGenericOuputAttribute, F32, U32, U32, U32, ) + // Flags OPCODE(GetScc, U1, Void, ) @@ -97,7 +99,7 @@ OPCODE(StoreBufferU32, Void, Opaq OPCODE(StoreBufferU32x2, Void, Opaque, Opaque, U32x2, ) OPCODE(StoreBufferU32x3, Void, Opaque, Opaque, U32x3, ) OPCODE(StoreBufferU32x4, Void, Opaque, Opaque, U32x4, ) -OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, U32x4, ) +OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32x4, ) // Buffer atomic operations OPCODE(BufferAtomicIAdd32, U32, Opaque, Opaque, U32 ) @@ -122,6 +124,9 @@ OPCODE(CompositeExtractU32x4, U32, U32x OPCODE(CompositeInsertU32x2, U32x2, U32x2, U32, U32, ) OPCODE(CompositeInsertU32x3, U32x3, U32x3, U32, U32, ) OPCODE(CompositeInsertU32x4, U32x4, U32x4, U32, U32, ) +OPCODE(CompositeShuffleU32x2, U32x2, U32x2, U32x2, U32, U32, ) +OPCODE(CompositeShuffleU32x3, U32x3, U32x3, U32x3, U32, U32, U32, ) +OPCODE(CompositeShuffleU32x4, U32x4, U32x4, U32x4, U32, U32, U32, U32, ) OPCODE(CompositeConstructF16x2, F16x2, F16, F16, ) OPCODE(CompositeConstructF16x3, F16x3, F16, F16, F16, ) OPCODE(CompositeConstructF16x4, F16x4, F16, F16, F16, F16, ) @@ -131,6 +136,9 @@ OPCODE(CompositeExtractF16x4, F16, F16x OPCODE(CompositeInsertF16x2, F16x2, F16x2, F16, U32, ) OPCODE(CompositeInsertF16x3, F16x3, F16x3, F16, U32, ) OPCODE(CompositeInsertF16x4, F16x4, F16x4, F16, U32, ) +OPCODE(CompositeShuffleF16x2, F16x2, F16x2, F16x2, U32, U32, ) +OPCODE(CompositeShuffleF16x3, F16x3, F16x3, F16x3, U32, U32, U32, ) +OPCODE(CompositeShuffleF16x4, F16x4, F16x4, F16x4, U32, U32, U32, U32, ) OPCODE(CompositeConstructF32x2, F32x2, F32, F32, ) OPCODE(CompositeConstructF32x3, F32x3, F32, F32, F32, ) OPCODE(CompositeConstructF32x4, F32x4, F32, F32, F32, F32, ) @@ -140,6 +148,9 @@ OPCODE(CompositeExtractF32x4, F32, F32x OPCODE(CompositeInsertF32x2, F32x2, F32x2, F32, U32, ) OPCODE(CompositeInsertF32x3, F32x3, F32x3, F32, U32, ) OPCODE(CompositeInsertF32x4, F32x4, F32x4, F32, U32, ) +OPCODE(CompositeShuffleF32x2, F32x2, F32x2, F32x2, U32, U32, ) +OPCODE(CompositeShuffleF32x3, F32x3, F32x3, F32x3, U32, U32, U32, ) +OPCODE(CompositeShuffleF32x4, F32x4, F32x4, F32x4, U32, U32, U32, U32, ) OPCODE(CompositeConstructF64x2, F64x2, F64, F64, ) OPCODE(CompositeConstructF64x3, F64x3, F64, F64, F64, ) OPCODE(CompositeConstructF64x4, F64x4, F64, F64, F64, F64, ) @@ -149,6 +160,9 @@ OPCODE(CompositeExtractF64x4, F64, F64x OPCODE(CompositeInsertF64x2, F64x2, F64x2, F64, U32, ) OPCODE(CompositeInsertF64x3, F64x3, F64x3, F64, U32, ) OPCODE(CompositeInsertF64x4, F64x4, F64x4, F64, U32, ) +OPCODE(CompositeShuffleF64x2, F64x2, F64x2, F64x2, U32, U32, ) +OPCODE(CompositeShuffleF64x3, F64x3, F64x3, F64x3, U32, U32, U32, ) +OPCODE(CompositeShuffleF64x4, F64x4, F64x4, F64x4, U32, U32, U32, U32, ) // Select operations OPCODE(SelectU1, U1, U1, U1, U1, ) @@ -284,11 +298,13 @@ OPCODE(BitFieldSExtract, U32, U32, OPCODE(BitFieldUExtract, U32, U32, U32, U32, ) OPCODE(BitReverse32, U32, U32, ) OPCODE(BitCount32, U32, U32, ) +OPCODE(BitCount64, U32, U64, ) OPCODE(BitwiseNot32, U32, U32, ) OPCODE(FindSMsb32, U32, U32, ) OPCODE(FindUMsb32, U32, U32, ) OPCODE(FindILsb32, U32, U32, ) +OPCODE(FindILsb64, U32, U64, ) OPCODE(SMin32, U32, U32, U32, ) OPCODE(UMin32, U32, U32, U32, ) OPCODE(SMax32, U32, U32, U32, ) @@ -299,7 +315,8 @@ OPCODE(SLessThan32, U1, U32, OPCODE(SLessThan64, U1, U64, U64, ) OPCODE(ULessThan32, U1, U32, U32, ) OPCODE(ULessThan64, U1, U64, U64, ) -OPCODE(IEqual, U1, U32, U32, ) +OPCODE(IEqual32, U1, U32, U32, ) +OPCODE(IEqual64, U1, U64, U64, ) OPCODE(SLessThanEqual, U1, U32, U32, ) OPCODE(ULessThanEqual, U1, U32, U32, ) OPCODE(SGreaterThan, U1, U32, U32, ) @@ -341,8 +358,8 @@ OPCODE(ImageGatherDref, F32x4, Opaq OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, F32, ) -OPCODE(ImageRead, U32x4, Opaque, Opaque, U32, U32, ) -OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32, U32x4, ) +OPCODE(ImageRead, F32x4, Opaque, Opaque, U32, U32, ) +OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32, F32x4, ) // Image atomic operations OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) @@ -357,6 +374,10 @@ OPCODE(ImageAtomicOr32, U32, Opaq OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, ) +// Cube operations - optional, usable if profile.supports_native_cube_calc +OPCODE(CubeFaceCoord, F32x2, F32x3, ) +OPCODE(CubeFaceIndex, F32, F32x3, ) + // Warp operations OPCODE(LaneId, U32, ) OPCODE(WarpId, U32, ) diff --git a/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp index 16b07e1a1..fcf2f7d9f 100644 --- a/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp @@ -391,9 +391,12 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { case IR::Opcode::UGreaterThanEqual: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a >= b; }); return; - case IR::Opcode::IEqual: + case IR::Opcode::IEqual32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a == b; }); return; + case IR::Opcode::IEqual64: + FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a == b; }); + return; case IR::Opcode::INotEqual: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a != b; }); return; diff --git a/src/shader_recompiler/ir/passes/hull_shader_transform.cpp b/src/shader_recompiler/ir/passes/hull_shader_transform.cpp index 895c9823e..6164fec12 100644 --- a/src/shader_recompiler/ir/passes/hull_shader_transform.cpp +++ b/src/shader_recompiler/ir/passes/hull_shader_transform.cpp @@ -343,8 +343,8 @@ static IR::U32 TryOptimizeAddressModulo(IR::U32 addr, u32 stride, IR::IREmitter& // TODO: can optimize div in control point index similarly to mod // Read a TCS input (InputCP region) or TES input (OutputCP region) -static IR::F32 ReadTessInputComponent(IR::U32 addr, const u32 stride, IR::IREmitter& ir, - u32 off_dw) { +static IR::F32 ReadTessControlPointAttribute(IR::U32 addr, const u32 stride, IR::IREmitter& ir, + u32 off_dw, bool is_output_read_in_tcs) { if (off_dw > 0) { addr = ir.IAdd(addr, ir.Imm32(off_dw)); } @@ -354,7 +354,11 @@ static IR::F32 ReadTessInputComponent(IR::U32 addr, const u32 stride, IR::IREmit ir.ShiftRightLogical(ir.IMod(addr_for_attrs, ir.Imm32(stride)), ir.Imm32(4u)); const IR::U32 comp_index = ir.ShiftRightLogical(ir.BitwiseAnd(addr_for_attrs, ir.Imm32(0xFU)), ir.Imm32(2u)); - return ir.GetTessGenericAttribute(control_point_index, attr_index, comp_index); + if (is_output_read_in_tcs) { + return ir.ReadTcsGenericOuputAttribute(control_point_index, attr_index, comp_index); + } else { + return ir.GetTessGenericAttribute(control_point_index, attr_index, comp_index); + } } } // namespace @@ -481,21 +485,25 @@ void HullShaderTransform(IR::Program& program, RuntimeInfo& runtime_info) { case IR::Opcode::LoadSharedU128: IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; const IR::U32 addr{inst.Arg(0)}; - AttributeRegion region = GetAttributeRegionKind(&inst, info, runtime_info); + const AttributeRegion region = GetAttributeRegionKind(&inst, info, runtime_info); const u32 num_dwords = opcode == IR::Opcode::LoadSharedU32 ? 1 : (opcode == IR::Opcode::LoadSharedU64 ? 2 : 4); - ASSERT_MSG(region == AttributeRegion::InputCP, - "Unhandled read of output or patchconst attribute in hull shader"); + ASSERT_MSG(region == AttributeRegion::InputCP || + region == AttributeRegion::OutputCP, + "Unhandled read of patchconst attribute in hull shader"); + const bool is_tcs_output_read = region == AttributeRegion::OutputCP; + const u32 stride = is_tcs_output_read ? runtime_info.hs_info.hs_output_cp_stride + : runtime_info.hs_info.ls_stride; IR::Value attr_read; if (num_dwords == 1) { attr_read = ir.BitCast( - ReadTessInputComponent(addr, runtime_info.hs_info.ls_stride, ir, 0)); + ReadTessControlPointAttribute(addr, stride, ir, 0, is_tcs_output_read)); } else { boost::container::static_vector read_components; for (auto i = 0; i < num_dwords; i++) { const IR::F32 component = - ReadTessInputComponent(addr, runtime_info.hs_info.ls_stride, ir, i); + ReadTessControlPointAttribute(addr, stride, ir, i, is_tcs_output_read); read_components.push_back(ir.BitCast(component)); } attr_read = ir.CompositeConstruct(read_components); @@ -565,8 +573,8 @@ void DomainShaderTransform(IR::Program& program, RuntimeInfo& runtime_info) { : (opcode == IR::Opcode::LoadSharedU64 ? 2 : 4); const auto GetInput = [&](IR::U32 addr, u32 off_dw) -> IR::F32 { if (region == AttributeRegion::OutputCP) { - return ReadTessInputComponent( - addr, runtime_info.vs_info.hs_output_cp_stride, ir, off_dw); + return ReadTessControlPointAttribute( + addr, runtime_info.vs_info.hs_output_cp_stride, ir, off_dw, false); } else { ASSERT(region == AttributeRegion::PatchConst); return ir.GetPatch(IR::PatchGeneric((addr.U32() >> 2) + off_dw)); diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index db1a2edd2..10d685ed1 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -8,6 +8,7 @@ #include "shader_recompiler/ir/breadth_first_search.h" #include "shader_recompiler/ir/ir_emitter.h" #include "shader_recompiler/ir/program.h" +#include "shader_recompiler/ir/reinterpret.h" #include "video_core/amdgpu/resource.h" namespace Shader::Optimization { @@ -128,35 +129,6 @@ bool IsImageInstruction(const IR::Inst& inst) { } } -IR::Value SwizzleVector(IR::IREmitter& ir, auto sharp, IR::Value texel) { - boost::container::static_vector comps; - for (u32 i = 0; i < 4; i++) { - switch (sharp.GetSwizzle(i)) { - case AmdGpu::CompSwizzle::Zero: - comps.emplace_back(ir.Imm32(0.f)); - break; - case AmdGpu::CompSwizzle::One: - comps.emplace_back(ir.Imm32(1.f)); - break; - case AmdGpu::CompSwizzle::Red: - comps.emplace_back(ir.CompositeExtract(texel, 0)); - break; - case AmdGpu::CompSwizzle::Green: - comps.emplace_back(ir.CompositeExtract(texel, 1)); - break; - case AmdGpu::CompSwizzle::Blue: - comps.emplace_back(ir.CompositeExtract(texel, 2)); - break; - case AmdGpu::CompSwizzle::Alpha: - comps.emplace_back(ir.CompositeExtract(texel, 3)); - break; - default: - UNREACHABLE(); - } - } - return ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]); -}; - class Descriptors { public: explicit Descriptors(Info& info_) @@ -189,10 +161,9 @@ public: u32 Add(const ImageResource& desc) { const u32 index{Add(image_resources, desc, [&desc](const auto& existing) { - return desc.sharp_idx == existing.sharp_idx; + return desc.sharp_idx == existing.sharp_idx && desc.is_array == existing.is_array; })}; auto& image = image_resources[index]; - image.is_read |= desc.is_read; image.is_written |= desc.is_written; return index; } @@ -249,7 +220,7 @@ std::pair TryDisableAnisoLod0(const IR::Inst* inst) { // Select should be based on zero check const auto* prod0 = inst->Arg(0).InstRecursive(); - if (prod0->GetOpcode() != IR::Opcode::IEqual || + if (prod0->GetOpcode() != IR::Opcode::IEqual32 || !(prod0->Arg(1).IsImmediate() && prod0->Arg(1).U32() == 0u)) { return not_found; } @@ -329,8 +300,7 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, }); } -void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, - Descriptors& descriptors) { +void PatchBufferSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { s32 binding{}; AmdGpu::Buffer buffer; if (binding = TryHandleInlineCbuf(inst, info, descriptors, buffer); binding == -1) { @@ -345,19 +315,189 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, }); } - // Update buffer descriptor format. - const auto inst_info = inst.Flags(); - // Replace handle with binding index in buffer resource list. IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; inst.SetArg(0, ir.Imm32(binding)); +} + +void PatchTextureBufferSharp(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, info); + const s32 binding = descriptors.Add(TextureBufferResource{ + .sharp_idx = sharp, + .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)); +} + +void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { + const auto pred = [](const IR::Inst* inst) -> std::optional { + const auto opcode = inst->GetOpcode(); + if (opcode == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler) + opcode == IR::Opcode::ReadConst || // IMAGE_LOAD (image only) + opcode == IR::Opcode::GetUserData) { + return inst; + } + return std::nullopt; + }; + const auto result = IR::BreadthFirstSearch(&inst, pred); + ASSERT_MSG(result, "Unable to find image sharp source"); + const IR::Inst* producer = result.value(); + const bool has_sampler = producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2; + const auto tsharp_handle = has_sampler ? producer->Arg(0).InstRecursive() : producer; + + // Read image sharp. + const auto tsharp = TrackSharp(tsharp_handle, info); + const auto inst_info = inst.Flags(); + auto image = info.ReadUdSharp(tsharp); + if (!image.Valid()) { + LOG_ERROR(Render_Vulkan, "Shader compiled with unbound image!"); + image = AmdGpu::Image::Null(); + } + ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); + const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite; + + // Patch image instruction if image is FMask. + if (image.IsFmask()) { + ASSERT_MSG(!is_written, "FMask storage instructions are not supported"); + + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + switch (inst.GetOpcode()) { + case IR::Opcode::ImageRead: + case IR::Opcode::ImageSampleRaw: { + IR::F32 fmaskx = ir.BitCast(ir.Imm32(0x76543210)); + IR::F32 fmasky = ir.BitCast(ir.Imm32(0xfedcba98)); + inst.ReplaceUsesWith(ir.CompositeConstruct(fmaskx, fmasky)); + return; + } + case IR::Opcode::ImageQueryLod: + inst.ReplaceUsesWith(ir.Imm32(1)); + return; + case IR::Opcode::ImageQueryDimensions: { + IR::Value dims = ir.CompositeConstruct(ir.Imm32(static_cast(image.width)), // x + ir.Imm32(static_cast(image.width)), // y + ir.Imm32(1), ir.Imm32(1)); // depth, mip + inst.ReplaceUsesWith(dims); + + // Track FMask resource to do specialization. + descriptors.Add(FMaskResource{ + .sharp_idx = tsharp, + }); + return; + } + default: + UNREACHABLE_MSG("Can't patch fmask instruction {}", inst.GetOpcode()); + } + } + + u32 image_binding = descriptors.Add(ImageResource{ + .sharp_idx = tsharp, + .is_depth = bool(inst_info.is_depth), + .is_atomic = IsImageAtomicInstruction(inst), + .is_array = bool(inst_info.is_array), + .is_written = is_written, + }); + + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + + if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) { + // Read sampler sharp. + const auto [sampler_binding, sampler] = [&] -> std::pair { + ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2); + const IR::Value& handle = producer->Arg(1); + // Inline sampler resource. + if (handle.IsImmediate()) { + LOG_WARNING(Render_Vulkan, "Inline sampler detected"); + const auto inline_sampler = AmdGpu::Sampler{.raw0 = handle.U32()}; + const auto binding = descriptors.Add(SamplerResource{ + .sharp_idx = std::numeric_limits::max(), + .inline_sampler = inline_sampler, + }); + return {binding, inline_sampler}; + } + // Normal sampler resource. + const auto ssharp_handle = handle.InstRecursive(); + const auto& [ssharp_ud, disable_aniso] = TryDisableAnisoLod0(ssharp_handle); + const auto ssharp = TrackSharp(ssharp_ud, info); + const auto binding = descriptors.Add(SamplerResource{ + .sharp_idx = ssharp, + .associated_image = image_binding, + .disable_aniso = disable_aniso, + }); + return {binding, info.ReadUdSharp(ssharp)}; + }(); + // Patch image and sampler handle. + inst.SetArg(0, ir.Imm32(image_binding | sampler_binding << 16)); + } else { + // Patch image handle. + inst.SetArg(0, ir.Imm32(image_binding)); + } +} + +void PatchDataRingAccess(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { + // Insert gds binding in the shader if it doesn't exist already. + // The buffer is used for append/consume counters. + constexpr static AmdGpu::Buffer GdsSharp{.base_address = 1}; + const u32 binding = descriptors.Add(BufferResource{ + .used_types = IR::Type::U32, + .inline_cbuf = GdsSharp, + .is_gds_buffer = true, + .is_written = true, + }); + + const auto pred = [](const IR::Inst* inst) -> std::optional { + if (inst->GetOpcode() == IR::Opcode::GetUserData) { + return inst; + } + return std::nullopt; + }; + + // Attempt to deduce the GDS address of counter at compile time. + const u32 gds_addr = [&] { + const IR::Value& gds_offset = inst.Arg(0); + if (gds_offset.IsImmediate()) { + // Nothing to do, offset is known. + return gds_offset.U32() & 0xFFFF; + } + const auto result = IR::BreadthFirstSearch(&inst, pred); + ASSERT_MSG(result, "Unable to track M0 source"); + + // M0 must be set by some user data register. + const IR::Inst* prod = gds_offset.InstRecursive(); + const u32 ud_reg = u32(result.value()->Arg(0).ScalarReg()); + u32 m0_val = info.user_data[ud_reg] >> 16; + if (prod->GetOpcode() == IR::Opcode::IAdd32) { + m0_val += prod->Arg(1).U32(); + } + return m0_val & 0xFFFF; + }(); + + // Patch instruction. + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + inst.SetArg(0, ir.Imm32(gds_addr >> 2)); + inst.SetArg(1, ir.Imm32(binding)); +} + +void PatchBufferArgs(IR::Block& block, IR::Inst& inst, Info& info) { + const auto handle = inst.Arg(0); + const auto buffer_res = info.buffers[handle.U32()]; + const auto buffer = buffer_res.GetSharp(info); + ASSERT(!buffer.add_tid_enable); - // Address of constant buffer reads can be calculated at IR emittion time. + // Address of constant buffer reads can be calculated at IR emission time. if (inst.GetOpcode() == IR::Opcode::ReadConstBuffer) { return; } + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto inst_info = inst.Flags(); + const IR::U32 index_stride = ir.Imm32(buffer.index_stride); const IR::U32 element_size = ir.Imm32(buffer.element_size); @@ -394,91 +534,38 @@ 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, info); - const auto buffer = info.ReadUdSharp(sharp); - const s32 binding = descriptors.Add(TextureBufferResource{ - .sharp_idx = sharp, - .is_written = inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32, - }); +void PatchTextureBufferArgs(IR::Block& block, IR::Inst& inst, Info& info) { + const auto handle = inst.Arg(0); + const auto buffer_res = info.texture_buffers[handle.U32()]; + const auto buffer = buffer_res.GetSharp(info); - // 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::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - // Apply dst_sel swizzle on formatted buffer instructions if (inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32) { - inst.SetArg(2, SwizzleVector(ir, buffer, inst.Arg(2))); - } else { + const auto swizzled = ApplySwizzle(ir, inst.Arg(2), buffer.DstSelect()); + const auto converted = + ApplyWriteNumberConversionVec4(ir, swizzled, buffer.GetNumberConversion()); + inst.SetArg(2, converted); + } else if (inst.GetOpcode() == IR::Opcode::LoadBufferFormatF32) { const auto inst_info = inst.Flags(); const auto texel = ir.LoadBufferFormat(inst.Arg(0), inst.Arg(1), inst_info); - inst.ReplaceUsesWith(SwizzleVector(ir, buffer, texel)); + const auto swizzled = ApplySwizzle(ir, texel, buffer.DstSelect()); + const auto converted = + ApplyReadNumberConversionVec4(ir, swizzled, buffer.GetNumberConversion()); + inst.ReplaceUsesWith(converted); } } -IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t, - const IR::Value& z, bool is_written, bool is_array) { - // When cubemap is written with imageStore it is treated like 2DArray. - if (is_written) { - return ir.CompositeConstruct(s, t, z); - } - - ASSERT(s.Type() == IR::Type::F32); // in case of fetched image need to adjust the code below - - // 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, - // here we subtract 1.5 to recover the original value. - const IR::Value x = ir.FPSub(IR::F32{s}, ir.Imm32(1.5f)); - const IR::Value y = ir.FPSub(IR::F32{t}, ir.Imm32(1.5f)); - if (is_array) { - const IR::U32 array_index = ir.ConvertFToU(32, IR::F32{z}); - const IR::U32 face_id = ir.BitwiseAnd(array_index, ir.Imm32(7u)); - const IR::U32 slice_id = ir.ShiftRightLogical(array_index, ir.Imm32(3u)); - return ir.CompositeConstruct(x, y, ir.ConvertIToF(32, 32, false, face_id), - ir.ConvertIToF(32, 32, false, slice_id)); - } else { - return ir.CompositeConstruct(x, y, z); - } -} - -void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, - Descriptors& descriptors, const IR::Inst* producer, - const u32 image_binding, const AmdGpu::Image& image) { - // Read sampler sharp. This doesn't exist for IMAGE_LOAD/IMAGE_STORE instructions - const auto [sampler_binding, sampler] = [&] -> std::pair { - ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2); - const IR::Value& handle = producer->Arg(1); - // Inline sampler resource. - if (handle.IsImmediate()) { - LOG_WARNING(Render_Vulkan, "Inline sampler detected"); - const auto inline_sampler = AmdGpu::Sampler{.raw0 = handle.U32()}; - const auto binding = descriptors.Add(SamplerResource{ - .sharp_idx = std::numeric_limits::max(), - .inline_sampler = inline_sampler, - }); - return {binding, inline_sampler}; - } - // Normal sampler resource. - const auto ssharp_handle = handle.InstRecursive(); - const auto& [ssharp_ud, disable_aniso] = TryDisableAnisoLod0(ssharp_handle); - const auto ssharp = TrackSharp(ssharp_ud, info); - const auto binding = descriptors.Add(SamplerResource{ - .sharp_idx = ssharp, - .associated_image = image_binding, - .disable_aniso = disable_aniso, - }); - return {binding, info.ReadUdSharp(ssharp)}; - }(); +void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info, + const ImageResource& image_res, const AmdGpu::Image& image) { + const auto handle = inst.Arg(0); + const auto sampler_res = info.samplers[(handle.U32() >> 16) & 0xFFFF]; + auto sampler = sampler_res.GetSharp(info); IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - const auto inst_info = inst.Flags(); - const IR::U32 handle = ir.Imm32(image_binding | sampler_binding << 16); + const auto view_type = image.GetViewType(image_res.is_array); IR::Inst* body1 = inst.Arg(1).InstRecursive(); IR::Inst* body2 = inst.Arg(2).InstRecursive(); @@ -525,7 +612,7 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, return ir.BitFieldExtract(IR::U32{arg}, ir.Imm32(off), ir.Imm32(6), true); }; - switch (image.GetType()) { + switch (view_type) { case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1DArray: return read(0); @@ -534,7 +621,6 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, case AmdGpu::ImageType::Color2DMsaa: return ir.CompositeConstruct(read(0), read(8)); case AmdGpu::ImageType::Color3D: - case AmdGpu::ImageType::Cube: return ir.CompositeConstruct(read(0), read(8), read(16)); default: UNREACHABLE(); @@ -546,7 +632,7 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, if (!inst_info.has_derivatives) { return {}; } - switch (image.GetType()) { + switch (view_type) { case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1DArray: // du/dx, du/dy @@ -560,7 +646,6 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, return {ir.CompositeConstruct(get_addr_reg(addr_reg - 4), get_addr_reg(addr_reg - 3)), ir.CompositeConstruct(get_addr_reg(addr_reg - 2), get_addr_reg(addr_reg - 1))}; case AmdGpu::ImageType::Color3D: - case AmdGpu::ImageType::Cube: // (du/dx, dv/dx, dw/dx), (du/dy, dv/dy, dw/dy) addr_reg = addr_reg + 6; return {ir.CompositeConstruct(get_addr_reg(addr_reg - 6), get_addr_reg(addr_reg - 5), @@ -576,7 +661,7 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, // Query dimensions of image if needed for normalization. // We can't use the image sharp because it could be bound to a different image later. const auto dimensions = - unnormalized ? ir.ImageQueryDimension(ir.Imm32(image_binding), ir.Imm32(0u), ir.Imm1(false)) + unnormalized ? ir.ImageQueryDimension(handle, ir.Imm32(0u), ir.Imm1(false), inst_info) : IR::Value{}; const auto get_coord = [&](u32 coord_idx, u32 dim_idx) -> IR::Value { const auto coord = get_addr_reg(coord_idx); @@ -591,7 +676,7 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, // Now we can load body components as noted in Table 8.9 Image Opcodes with Sampler const IR::Value coords = [&] -> IR::Value { - switch (image.GetType()) { + switch (view_type) { case AmdGpu::ImageType::Color1D: // x addr_reg = addr_reg + 1; return get_coord(addr_reg - 1, 0); @@ -610,10 +695,6 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, addr_reg = addr_reg + 3; return ir.CompositeConstruct(get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1), get_coord(addr_reg - 1, 2)); - case AmdGpu::ImageType::Cube: // x, y, face - addr_reg = addr_reg + 3; - return PatchCubeCoord(ir, get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1), - get_addr_reg(addr_reg - 1), false, inst_info.is_array); default: UNREACHABLE(); } @@ -626,7 +707,7 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, : IR::F32{}; const IR::F32 lod_clamp = inst_info.has_lod_clamp ? get_addr_reg(addr_reg++) : IR::F32{}; - auto new_inst = [&] -> IR::Value { + auto texel = [&] -> IR::Value { if (inst_info.is_gather) { if (inst_info.is_depth) { return ir.ImageGatherDref(handle, coords, offset, dref, inst_info); @@ -648,98 +729,35 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, } return ir.ImageSampleImplicitLod(handle, coords, bias, offset, inst_info); }(); - inst.ReplaceUsesWithAndRemove(new_inst); + + const auto converted = ApplyReadNumberConversionVec4(ir, texel, image.GetNumberConversion()); + inst.ReplaceUsesWith(converted); } -void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { - const auto pred = [](const IR::Inst* inst) -> std::optional { - const auto opcode = inst->GetOpcode(); - if (opcode == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler) - opcode == IR::Opcode::ReadConst || // IMAGE_LOAD (image only) - opcode == IR::Opcode::GetUserData) { - return inst; - } - return std::nullopt; - }; - const auto result = IR::BreadthFirstSearch(&inst, pred); - ASSERT_MSG(result, "Unable to find image sharp source"); - const IR::Inst* producer = result.value(); - const bool has_sampler = producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2; - const auto tsharp_handle = has_sampler ? producer->Arg(0).InstRecursive() : producer; - - // Read image sharp. - const auto tsharp = TrackSharp(tsharp_handle, info); - const auto inst_info = inst.Flags(); - auto image = info.ReadUdSharp(tsharp); - if (!image.Valid()) { - LOG_ERROR(Render_Vulkan, "Shader compiled with unbound image!"); - image = AmdGpu::Image::Null(); - } - ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); - const bool is_read = inst.GetOpcode() == IR::Opcode::ImageRead; - const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite; - - // Patch image instruction if image is FMask. - if (image.IsFmask()) { - ASSERT_MSG(!is_written, "FMask storage instructions are not supported"); - - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - switch (inst.GetOpcode()) { - case IR::Opcode::ImageRead: - case IR::Opcode::ImageSampleRaw: { - IR::F32 fmaskx = ir.BitCast(ir.Imm32(0x76543210)); - IR::F32 fmasky = ir.BitCast(ir.Imm32(0xfedcba98)); - inst.ReplaceUsesWith(ir.CompositeConstruct(fmaskx, fmasky)); - return; - } - case IR::Opcode::ImageQueryLod: - inst.ReplaceUsesWith(ir.Imm32(1)); - return; - case IR::Opcode::ImageQueryDimensions: { - IR::Value dims = ir.CompositeConstruct(ir.Imm32(static_cast(image.width)), // x - ir.Imm32(static_cast(image.width)), // y - ir.Imm32(1), ir.Imm32(1)); // depth, mip - inst.ReplaceUsesWith(dims); - - // Track FMask resource to do specialization. - descriptors.Add(FMaskResource{ - .sharp_idx = tsharp, - }); - return; - } - default: - UNREACHABLE_MSG("Can't patch fmask instruction {}", inst.GetOpcode()); - } - } - - u32 image_binding = descriptors.Add(ImageResource{ - .sharp_idx = tsharp, - .is_depth = bool(inst_info.is_depth), - .is_atomic = IsImageAtomicInstruction(inst), - .is_array = bool(inst_info.is_array), - .is_read = is_read, - .is_written = is_written, - }); - - // Sample instructions must be resolved into a new instruction using address register data. - if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) { - PatchImageSampleInstruction(block, inst, info, descriptors, producer, image_binding, image); - return; - } - - // Patch image handle - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - inst.SetArg(0, ir.Imm32(image_binding)); - - // No need to patch coordinates if we are just querying. +void PatchImageArgs(IR::Block& block, IR::Inst& inst, Info& info) { + // Nothing to patch for dimension query. if (inst.GetOpcode() == IR::Opcode::ImageQueryDimensions) { return; } + const auto handle = inst.Arg(0); + const auto image_res = info.images[handle.U32() & 0xFFFF]; + auto image = image_res.GetSharp(info); + + // Sample instructions must be handled separately using address register data. + if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) { + PatchImageSampleArgs(block, inst, info, image_res, image); + return; + } + + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto inst_info = inst.Flags(); + const auto view_type = image.GetViewType(image_res.is_array); + // Now that we know the image type, adjust texture coordinate vector. IR::Inst* body = inst.Arg(1).InstRecursive(); const auto [coords, arg] = [&] -> std::pair { - switch (image.GetType()) { + switch (view_type) { case AmdGpu::ImageType::Color1D: // x, [lod] return {body->Arg(0), body->Arg(1)}; case AmdGpu::ImageType::Color1DArray: // x, slice, [lod] @@ -755,100 +773,74 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip [[fallthrough]]; case AmdGpu::ImageType::Color3D: // x, y, z, [lod] return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; - case AmdGpu::ImageType::Cube: // x, y, face, [lod] - return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_written, - inst_info.is_array), - body->Arg(3)}; default: - UNREACHABLE_MSG("Unknown image type {}", image.GetType()); + UNREACHABLE_MSG("Unknown image type {}", view_type); } }(); - inst.SetArg(1, coords); - if (inst.GetOpcode() == IR::Opcode::ImageWrite) { - inst.SetArg(4, SwizzleVector(ir, image, inst.Arg(4))); + const auto has_ms = view_type == AmdGpu::ImageType::Color2DMsaa || + view_type == AmdGpu::ImageType::Color2DMsaaArray; + ASSERT(!inst_info.has_lod || !has_ms); + const auto lod = inst_info.has_lod ? IR::U32{arg} : IR::U32{}; + const auto ms = has_ms ? IR::U32{arg} : IR::U32{}; + + const auto is_storage = image_res.is_written; + if (inst.GetOpcode() == IR::Opcode::ImageRead) { + auto texel = ir.ImageRead(handle, coords, lod, ms, inst_info); + if (is_storage) { + // Storage image requires shader swizzle. + texel = ApplySwizzle(ir, texel, image.DstSelect()); + } + const auto converted = + ApplyReadNumberConversionVec4(ir, texel, image.GetNumberConversion()); + inst.ReplaceUsesWith(converted); + } else { + inst.SetArg(1, coords); + if (inst.GetOpcode() == IR::Opcode::ImageWrite) { + inst.SetArg(2, lod); + inst.SetArg(3, ms); + + auto texel = inst.Arg(4); + if (is_storage) { + // Storage image requires shader swizzle. + texel = ApplySwizzle(ir, texel, image.DstSelect()); + } + const auto converted = + ApplyWriteNumberConversionVec4(ir, texel, image.GetNumberConversion()); + inst.SetArg(4, converted); + } } - - if (inst_info.has_lod) { - ASSERT(inst.GetOpcode() == IR::Opcode::ImageRead || - inst.GetOpcode() == IR::Opcode::ImageWrite); - ASSERT(image.GetType() != AmdGpu::ImageType::Color2DMsaa && - image.GetType() != AmdGpu::ImageType::Color2DMsaaArray); - inst.SetArg(2, arg); - } else if ((image.GetType() == AmdGpu::ImageType::Color2DMsaa || - image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) && - (inst.GetOpcode() == IR::Opcode::ImageRead || - inst.GetOpcode() == IR::Opcode::ImageWrite)) { - inst.SetArg(3, arg); - } -} - -void PatchDataRingInstruction(IR::Block& block, IR::Inst& inst, Info& info, - Descriptors& descriptors) { - // Insert gds binding in the shader if it doesn't exist already. - // The buffer is used for append/consume counters. - constexpr static AmdGpu::Buffer GdsSharp{.base_address = 1}; - const u32 binding = descriptors.Add(BufferResource{ - .used_types = IR::Type::U32, - .inline_cbuf = GdsSharp, - .is_gds_buffer = true, - .is_written = true, - }); - - const auto pred = [](const IR::Inst* inst) -> std::optional { - if (inst->GetOpcode() == IR::Opcode::GetUserData) { - return inst; - } - return std::nullopt; - }; - - // Attempt to deduce the GDS address of counter at compile time. - const u32 gds_addr = [&] { - const IR::Value& gds_offset = inst.Arg(0); - if (gds_offset.IsImmediate()) { - // Nothing to do, offset is known. - return gds_offset.U32() & 0xFFFF; - } - const auto result = IR::BreadthFirstSearch(&inst, pred); - ASSERT_MSG(result, "Unable to track M0 source"); - - // M0 must be set by some user data register. - const IR::Inst* prod = gds_offset.InstRecursive(); - const u32 ud_reg = u32(result.value()->Arg(0).ScalarReg()); - u32 m0_val = info.user_data[ud_reg] >> 16; - if (prod->GetOpcode() == IR::Opcode::IAdd32) { - m0_val += prod->Arg(1).U32(); - } - return m0_val & 0xFFFF; - }(); - - // Patch instruction. - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - inst.SetArg(0, ir.Imm32(gds_addr >> 2)); - inst.SetArg(1, ir.Imm32(binding)); } void ResourceTrackingPass(IR::Program& program) { // Iterate resource instructions and patch them after finding the sharp. auto& info = program.info; + // Pass 1: Track resource sharps Descriptors descriptors{info}; for (IR::Block* const block : program.blocks) { for (IR::Inst& inst : block->Instructions()) { if (IsBufferInstruction(inst)) { - PatchBufferInstruction(*block, inst, info, descriptors); - continue; + PatchBufferSharp(*block, inst, info, descriptors); + } else if (IsTextureBufferInstruction(inst)) { + PatchTextureBufferSharp(*block, inst, info, descriptors); + } else if (IsImageInstruction(inst)) { + PatchImageSharp(*block, inst, info, descriptors); + } else if (IsDataRingInstruction(inst)) { + PatchDataRingAccess(*block, inst, info, descriptors); } - if (IsTextureBufferInstruction(inst)) { - PatchTextureBufferInstruction(*block, inst, info, descriptors); - continue; - } - if (IsImageInstruction(inst)) { - PatchImageInstruction(*block, inst, info, descriptors); - continue; - } - if (IsDataRingInstruction(inst)) { - PatchDataRingInstruction(*block, inst, info, descriptors); + } + } + + // Pass 2: Patch instruction args + for (IR::Block* const block : program.blocks) { + for (IR::Inst& inst : block->Instructions()) { + if (IsBufferInstruction(inst)) { + PatchBufferArgs(*block, inst, info); + } else if (IsTextureBufferInstruction(inst)) { + PatchTextureBufferArgs(*block, inst, info); + } else if (IsImageInstruction(inst)) { + PatchImageArgs(*block, inst, info); } } } 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 c34b59b88..7fd5b75ff 100644 --- a/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp +++ b/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp @@ -5,7 +5,7 @@ namespace Shader::Optimization { -void Visit(Info& info, IR::Inst& inst) { +void Visit(Info& info, const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::GetAttribute: case IR::Opcode::GetAttributeU32: diff --git a/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp b/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp index aad8fb148..ec7d7e986 100644 --- a/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp +++ b/src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp @@ -8,6 +8,54 @@ namespace Shader::Optimization { +static void EmitBarrierInBlock(IR::Block* block) { + // This is inteded to insert a barrier when shared memory write and read + // occur in the same basic block. Also checks if branch depth is zero as + // we don't want to insert barrier in potentially divergent code. + bool emit_barrier_on_write = false; + bool emit_barrier_on_read = false; + const auto emit_barrier = [block](bool& emit_cond, IR::Inst& inst) { + if (emit_cond) { + IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; + ir.Barrier(); + emit_cond = false; + } + }; + for (IR::Inst& inst : block->Instructions()) { + if (inst.GetOpcode() == IR::Opcode::LoadSharedU32 || + inst.GetOpcode() == IR::Opcode::LoadSharedU64) { + emit_barrier(emit_barrier_on_read, inst); + emit_barrier_on_write = true; + } + if (inst.GetOpcode() == IR::Opcode::WriteSharedU32 || + inst.GetOpcode() == IR::Opcode::WriteSharedU64) { + emit_barrier(emit_barrier_on_write, inst); + emit_barrier_on_read = true; + } + } +} + +static void EmitBarrierInMergeBlock(const IR::AbstractSyntaxNode::Data& data) { + // Insert a barrier after divergent conditional blocks. + // This avoids potential softlocks and crashes when some threads + // initialize shared memory and others read from it. + const IR::U1 cond = data.if_node.cond; + const auto insert_barrier = + IR::BreadthFirstSearch(cond, [](IR::Inst* inst) -> std::optional { + if (inst->GetOpcode() == IR::Opcode::GetAttributeU32 && + inst->Arg(0).Attribute() == IR::Attribute::LocalInvocationId) { + return true; + } + return std::nullopt; + }); + if (insert_barrier) { + IR::Block* const merge = data.if_node.merge; + auto insert_point = std::ranges::find_if_not(merge->Instructions(), IR::IsPhi); + IR::IREmitter ir{*merge, insert_point}; + ir.Barrier(); + } +} + void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) { if (!program.info.uses_shared || !profile.needs_lds_barriers) { return; @@ -19,27 +67,12 @@ void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) { --branch_depth; continue; } - if (node.type != Type::If) { + if (node.type == Type::If && branch_depth++ == 0) { + EmitBarrierInMergeBlock(node.data); continue; } - u32 curr_depth = branch_depth++; - if (curr_depth != 0) { - continue; - } - const IR::U1 cond = node.data.if_node.cond; - const auto insert_barrier = - IR::BreadthFirstSearch(cond, [](IR::Inst* inst) -> std::optional { - if (inst->GetOpcode() == IR::Opcode::GetAttributeU32 && - inst->Arg(0).Attribute() == IR::Attribute::LocalInvocationId) { - return true; - } - return std::nullopt; - }); - if (insert_barrier) { - IR::Block* const merge = node.data.if_node.merge; - auto insert_point = std::ranges::find_if_not(merge->Instructions(), IR::IsPhi); - IR::IREmitter ir{*merge, insert_point}; - ir.Barrier(); + if (node.type == Type::Block && branch_depth == 0) { + EmitBarrierInBlock(node.data.block); } } } diff --git a/src/shader_recompiler/ir/reinterpret.h b/src/shader_recompiler/ir/reinterpret.h new file mode 100644 index 000000000..b65b19928 --- /dev/null +++ b/src/shader_recompiler/ir/reinterpret.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "shader_recompiler/ir/ir_emitter.h" +#include "video_core/amdgpu/types.h" + +namespace Shader::IR { + +/// Applies a component swizzle to a vec4. +inline Value ApplySwizzle(IREmitter& ir, const Value& vector, const AmdGpu::CompMapping& swizzle) { + // Constants are indexed as 0 and 1, and components are 4-7. Thus we can apply a swizzle + // using two vectors and a shuffle, using one vector of constants and one of the components. + const auto zero = ir.Imm32(0.f); + const auto one = ir.Imm32(1.f); + const auto constants_vec = ir.CompositeConstruct(zero, one, zero, zero); + const auto swizzled = + ir.CompositeShuffle(constants_vec, vector, size_t(swizzle.r), size_t(swizzle.g), + size_t(swizzle.b), size_t(swizzle.a)); + return swizzled; +} + +/// Applies a number conversion in the read direction. +inline F32 ApplyReadNumberConversion(IREmitter& ir, const F32& value, + const AmdGpu::NumberConversion& conversion) { + switch (conversion) { + case AmdGpu::NumberConversion::None: + return value; + case AmdGpu::NumberConversion::UintToUscaled: + return ir.ConvertUToF(32, 32, ir.BitCast(value)); + case AmdGpu::NumberConversion::SintToSscaled: + return ir.ConvertSToF(32, 32, ir.BitCast(value)); + case AmdGpu::NumberConversion::UnormToUbnorm: + // Convert 0...1 to -1...1 + return ir.FPSub(ir.FPMul(value, ir.Imm32(2.f)), ir.Imm32(1.f)); + default: + UNREACHABLE(); + } +} + +inline Value ApplyReadNumberConversionVec4(IREmitter& ir, const Value& value, + const AmdGpu::NumberConversion& conversion) { + if (conversion == AmdGpu::NumberConversion::None) { + return value; + } + const auto x = ApplyReadNumberConversion(ir, F32{ir.CompositeExtract(value, 0)}, conversion); + const auto y = ApplyReadNumberConversion(ir, F32{ir.CompositeExtract(value, 1)}, conversion); + const auto z = ApplyReadNumberConversion(ir, F32{ir.CompositeExtract(value, 2)}, conversion); + const auto w = ApplyReadNumberConversion(ir, F32{ir.CompositeExtract(value, 3)}, conversion); + return ir.CompositeConstruct(x, y, z, w); +} + +/// Applies a number conversion in the write direction. +inline F32 ApplyWriteNumberConversion(IREmitter& ir, const F32& value, + const AmdGpu::NumberConversion& conversion) { + switch (conversion) { + case AmdGpu::NumberConversion::None: + return value; + case AmdGpu::NumberConversion::UintToUscaled: + // Need to return float type to maintain IR semantics. + return ir.BitCast(U32{ir.ConvertFToU(32, value)}); + case AmdGpu::NumberConversion::SintToSscaled: + // Need to return float type to maintain IR semantics. + return ir.BitCast(U32{ir.ConvertFToS(32, value)}); + case AmdGpu::NumberConversion::UnormToUbnorm: + // Convert -1...1 to 0...1 + return ir.FPDiv(ir.FPAdd(value, ir.Imm32(1.f)), ir.Imm32(2.f)); + default: + UNREACHABLE(); + } +} + +inline Value ApplyWriteNumberConversionVec4(IREmitter& ir, const Value& value, + const AmdGpu::NumberConversion& conversion) { + if (conversion == AmdGpu::NumberConversion::None) { + return value; + } + const auto x = ApplyWriteNumberConversion(ir, F32{ir.CompositeExtract(value, 0)}, conversion); + const auto y = ApplyWriteNumberConversion(ir, F32{ir.CompositeExtract(value, 1)}, conversion); + const auto z = ApplyWriteNumberConversion(ir, F32{ir.CompositeExtract(value, 2)}, conversion); + const auto w = ApplyWriteNumberConversion(ir, F32{ir.CompositeExtract(value, 3)}, conversion); + return ir.CompositeConstruct(x, y, z, w); +} + +} // namespace Shader::IR diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index fc8c5956e..f8878d442 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -24,6 +24,7 @@ struct Profile { bool support_explicit_workgroup_layout{}; bool support_legacy_vertex_attributes{}; bool supports_image_load_store_lod{}; + bool supports_native_cube_calc{}; bool has_broken_spirv_clamp{}; bool lower_left_origin_mode{}; bool needs_manual_interpolation{}; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index bbf74f5d3..cf49b0879 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -180,7 +180,8 @@ struct FragmentRuntimeInfo { std::array inputs; struct PsColorBuffer { AmdGpu::NumberFormat num_format; - MrtSwizzle mrt_swizzle; + AmdGpu::NumberConversion num_conversion; + AmdGpu::CompMapping swizzle; auto operator<=>(const PsColorBuffer&) const noexcept = default; }; diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h index 5bf97ee51..18b1df1f9 100644 --- a/src/shader_recompiler/specialization.h +++ b/src/shader_recompiler/specialization.h @@ -31,7 +31,8 @@ struct BufferSpecialization { struct TextureBufferSpecialization { bool is_integer = false; - u32 dst_select = 0; + AmdGpu::CompMapping dst_select{}; + AmdGpu::NumberConversion num_conversion{}; auto operator<=>(const TextureBufferSpecialization&) const = default; }; @@ -40,13 +41,10 @@ struct ImageSpecialization { AmdGpu::ImageType type = AmdGpu::ImageType::Color2D; bool is_integer = false; bool is_storage = false; - u32 dst_select = 0; + AmdGpu::CompMapping dst_select{}; + AmdGpu::NumberConversion num_conversion{}; - bool operator==(const ImageSpecialization& other) const { - return type == other.type && is_integer == other.is_integer && - is_storage == other.is_storage && - (dst_select != 0 ? dst_select == other.dst_select : true); - } + auto operator<=>(const ImageSpecialization&) const = default; }; struct FMaskSpecialization { @@ -111,15 +109,17 @@ struct StageSpecialization { [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); spec.dst_select = sharp.DstSelect(); + spec.num_conversion = sharp.GetNumberConversion(); }); ForEachSharp(binding, images, info->images, [](auto& spec, const auto& desc, AmdGpu::Image sharp) { - spec.type = sharp.GetBoundType(); + spec.type = sharp.GetViewType(desc.is_array); spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); - spec.is_storage = desc.IsStorage(sharp); + spec.is_storage = desc.is_written; if (spec.is_storage) { spec.dst_select = sharp.DstSelect(); } + spec.num_conversion = sharp.GetNumberConversion(); }); ForEachSharp(binding, fmasks, info->fmasks, [](auto& spec, const auto& desc, AmdGpu::Image sharp) { diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 5dd3edd6d..16ed84f74 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -454,7 +454,6 @@ 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(DrawIndirectArgs); if (DebugState.DumpingCurrentReg()) { DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); @@ -462,7 +461,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndirect", cmd_address)); - rasterizer->DrawIndirect(false, ib_address, offset, size, 1, 0); + rasterizer->DrawIndirect(false, indirect_args_addr, offset, size, 1, 0); rasterizer->ScopeMarkerEnd(); } break; @@ -471,7 +470,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); const auto offset = draw_index_indirect->data_offset; - const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; const auto size = sizeof(DrawIndexedIndirectArgs); if (DebugState.DumpingCurrentReg()) { DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); @@ -480,7 +478,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); rasterizer->ScopeMarkerBegin( fmt::format("dcb:{}:DrawIndexIndirect", cmd_address)); - rasterizer->DrawIndirect(true, ib_address, offset, size, 1, 0); + rasterizer->DrawIndirect(true, indirect_args_addr, offset, size, 1, 0); rasterizer->ScopeMarkerEnd(); } break; @@ -489,7 +487,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); const auto offset = draw_index_indirect->data_offset; - const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; if (DebugState.DumpingCurrentReg()) { DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); } @@ -497,9 +494,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); rasterizer->ScopeMarkerBegin( fmt::format("dcb:{}:DrawIndexIndirectCountMulti", cmd_address)); - rasterizer->DrawIndirect(true, ib_address, offset, draw_index_indirect->stride, - draw_index_indirect->count, - draw_index_indirect->countAddr); + rasterizer->DrawIndirect( + true, indirect_args_addr, offset, draw_index_indirect->stride, + draw_index_indirect->count, draw_index_indirect->countAddr); rasterizer->ScopeMarkerEnd(); } break; @@ -528,7 +525,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); auto& cs_program = GetCsRegs(); const auto offset = dispatch_indirect->data_offset; - const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; const auto size = sizeof(PM4CmdDispatchIndirect::GroupDimensions); if (DebugState.DumpingCurrentReg()) { DebugState.PushRegsDumpCompute(base_addr, reinterpret_cast(header), @@ -538,7 +534,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); rasterizer->ScopeMarkerBegin( fmt::format("dcb:{}:DispatchIndirect", cmd_address)); - rasterizer->DispatchIndirect(ib_address, offset, size); + rasterizer->DispatchIndirect(indirect_args_addr, offset, size); rasterizer->ScopeMarkerEnd(); } break; @@ -562,7 +558,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); ASSERT(set_base->base_index == PM4CmdSetBase::BaseIndex::DrawIndexIndirPatchTable); - mapped_queues[GfxQueueId].indirect_args_addr = set_base->Address(); + indirect_args_addr = set_base->Address(); break; } case PM4ItOpcode::EventWrite: { @@ -815,12 +811,31 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, u32 vqid) { } if (rasterizer && (cs_program.dispatch_initiator & 1)) { const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("acb[{}]:{}:Dispatch", vqid, cmd_address)); + rasterizer->ScopeMarkerBegin( + fmt::format("acb[{}]:{}:DispatchIndirect", vqid, cmd_address)); rasterizer->DispatchDirect(); rasterizer->ScopeMarkerEnd(); } break; } + case PM4ItOpcode::DispatchIndirect: { + const auto* dispatch_indirect = + reinterpret_cast(header); + auto& cs_program = GetCsRegs(); + const auto ib_address = dispatch_indirect->Address(); + const auto size = sizeof(PM4CmdDispatchIndirect::GroupDimensions); + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDumpCompute(base_addr, reinterpret_cast(header), + cs_program); + } + if (rasterizer && (cs_program.dispatch_initiator & 1)) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("acb[{}]:{}:Dispatch", vqid, cmd_address)); + rasterizer->DispatchIndirect(ib_address, 0, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } case PM4ItOpcode::WriteData: { const auto* write_data = reinterpret_cast(header); ASSERT(write_data->dst_sel.Value() == 2 || write_data->dst_sel.Value() == 5); @@ -845,6 +860,10 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, u32 vqid) { release_mem->SignalFence(static_cast(queue.pipe_id)); break; } + case PM4ItOpcode::EventWrite: { + // const auto* event = reinterpret_cast(header); + break; + } default: UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", static_cast(opcode), count); diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 83271a82d..070253ca9 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -20,9 +20,9 @@ #include "common/types.h" #include "common/unique_function.h" #include "shader_recompiler/params.h" -#include "types.h" #include "video_core/amdgpu/pixel_format.h" #include "video_core/amdgpu/resource.h" +#include "video_core/amdgpu/types.h" namespace Vulkan { class Rasterizer; @@ -814,7 +814,9 @@ struct Liverpool { BitField<26, 1, u32> fmask_compression_disable_ci; BitField<27, 1, u32> fmask_compress_1frag_only; BitField<28, 1, u32> dcc_enable; - BitField<29, 1, u32> cmask_addr_type; + BitField<29, 2, u32> cmask_addr_type; + /// Neo-mode only + BitField<31, 1, u32> alt_tile_mode; u32 u32all; } info; @@ -889,10 +891,59 @@ struct Liverpool { return !info.linear_general; } - NumberFormat NumFormat() const { + [[nodiscard]] DataFormat GetDataFmt() const { + return RemapDataFormat(info.format); + } + + [[nodiscard]] NumberFormat GetNumberFmt() const { // There is a small difference between T# and CB number types, account for it. - return info.number_type == AmdGpu::NumberFormat::SnormNz ? AmdGpu::NumberFormat::Srgb - : info.number_type.Value(); + return RemapNumberFormat(info.number_type == NumberFormat::SnormNz + ? NumberFormat::Srgb + : info.number_type.Value(), + info.format); + } + + [[nodiscard]] NumberConversion GetNumberConversion() const { + return MapNumberConversion(info.number_type); + } + + [[nodiscard]] CompMapping Swizzle() const { + // clang-format off + static constexpr std::array, 4> mrt_swizzles{{ + // Standard + std::array{{ + {.r = CompSwizzle::Red, .g = CompSwizzle::Zero, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Blue, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Blue, .a = CompSwizzle::Alpha}, + }}, + // Alternate + std::array{{ + {.r = CompSwizzle::Green, .g = CompSwizzle::Zero, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Red, .g = CompSwizzle::Alpha, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Red, .g = CompSwizzle::Green, .b = CompSwizzle::Alpha, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Blue, .g = CompSwizzle::Green, .b = CompSwizzle::Red, .a = CompSwizzle::Alpha}, + }}, + // StandardReverse + std::array{{ + {.r = CompSwizzle::Blue, .g = CompSwizzle::Zero, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Green, .g = CompSwizzle::Red, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Blue, .g = CompSwizzle::Green, .b = CompSwizzle::Red, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Alpha, .g = CompSwizzle::Blue, .b = CompSwizzle::Green, .a = CompSwizzle::Red}, + }}, + // AlternateReverse + std::array{{ + {.r = CompSwizzle::Alpha, .g = CompSwizzle::Zero, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Alpha, .g = CompSwizzle::Red, .b = CompSwizzle::Zero, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Alpha, .g = CompSwizzle::Green, .b = CompSwizzle::Red, .a = CompSwizzle::Zero}, + {.r = CompSwizzle::Alpha, .g = CompSwizzle::Red, .b = CompSwizzle::Green, .a = CompSwizzle::Blue}, + }}, + }}; + // clang-format on + const auto swap_idx = static_cast(info.comp_swap.Value()); + const auto components_idx = NumComponents(info.format) - 1; + const auto mrt_swizzle = mrt_swizzles[swap_idx][components_idx]; + return RemapSwizzle(info.format, mrt_swizzle); } }; @@ -1433,11 +1484,12 @@ private: std::vector ccb_buffer; std::queue submits{}; ComputeProgram cs_state{}; - VAddr indirect_args_addr{}; }; std::array mapped_queues{}; u32 num_mapped_queues{1u}; // GFX is always available + VAddr indirect_args_addr{}; + struct ConstantEngine { void Reset() { ce_count = 0; diff --git a/src/video_core/amdgpu/pixel_format.cpp b/src/video_core/amdgpu/pixel_format.cpp index b13fc2d11..881c33e44 100644 --- a/src/video_core/amdgpu/pixel_format.cpp +++ b/src/video_core/amdgpu/pixel_format.cpp @@ -100,7 +100,7 @@ std::string_view NameOf(NumberFormat fmt) { return "Srgb"; case NumberFormat::Ubnorm: return "Ubnorm"; - case NumberFormat::UbnromNz: + case NumberFormat::UbnormNz: return "UbnormNz"; case NumberFormat::Ubint: return "Ubint"; diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 238e09fad..311f4d4d0 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -204,6 +204,11 @@ struct PM4CmdSetData { static constexpr u32* SetShReg(u32* cmdbuf, Args... data) { return WritePacket(cmdbuf, type, data...); } + + template + static constexpr u32* SetUconfigReg(u32* cmdbuf, Args... data) { + return WritePacket(cmdbuf, type, data...); + } }; struct PM4CmdNop { @@ -791,6 +796,18 @@ struct PM4CmdDispatchIndirect { u32 dispatch_initiator; ///< Dispatch Initiator Register }; +struct PM4CmdDispatchIndirectMec { + PM4Type3Header header; + u32 address0; + u32 address1; + u32 dispatch_initiator; ///< Dispatch Initiator Register + + template + T Address() const { + return std::bit_cast(address0 | (u64(address1 & 0xffff) << 32u)); + } +}; + struct DrawIndirectArgs { u32 vertex_count_per_instance; u32 instance_count; diff --git a/src/video_core/amdgpu/resource.h b/src/video_core/amdgpu/resource.h index d9a8b7cac..744aacdc5 100644 --- a/src/video_core/amdgpu/resource.h +++ b/src/video_core/amdgpu/resource.h @@ -11,15 +11,6 @@ namespace AmdGpu { -enum class CompSwizzle : u32 { - Zero = 0, - One = 1, - Red = 4, - Green = 5, - Blue = 6, - Alpha = 7, -}; - // Table 8.5 Buffer Resource Descriptor [Sea Islands Series Instruction Set Architecture] struct Buffer { u64 base_address : 44; @@ -52,21 +43,26 @@ struct Buffer { return std::memcmp(this, &other, sizeof(Buffer)) == 0; } - u32 DstSelect() const { - return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9); - } - - CompSwizzle GetSwizzle(u32 comp) const noexcept { - const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w}; - return static_cast(select[comp]); + CompMapping DstSelect() const { + const CompMapping dst_sel{ + .r = CompSwizzle(dst_sel_x), + .g = CompSwizzle(dst_sel_y), + .b = CompSwizzle(dst_sel_z), + .a = CompSwizzle(dst_sel_w), + }; + return RemapSwizzle(DataFormat(data_format), dst_sel); } NumberFormat GetNumberFmt() const noexcept { - return static_cast(num_format); + return RemapNumberFormat(NumberFormat(num_format), DataFormat(data_format)); } DataFormat GetDataFmt() const noexcept { - return static_cast(data_format); + return RemapDataFormat(DataFormat(data_format)); + } + + NumberConversion GetNumberConversion() const noexcept { + return MapNumberConversion(NumberFormat(num_format)); } u32 GetStride() const noexcept { @@ -181,15 +177,24 @@ struct Image { u64 min_lod_warn : 12; u64 counter_bank_id : 8; u64 lod_hw_cnt_en : 1; - u64 : 43; + /// Neo-mode only + u64 compression_en : 1; + /// Neo-mode only + u64 alpha_is_on_msb : 1; + /// Neo-mode only + u64 color_transform : 1; + /// Neo-mode only + u64 alt_tile_mode : 1; + u64 : 39; static constexpr Image Null() { Image image{}; image.data_format = u64(DataFormat::Format8_8_8_8); - image.dst_sel_x = 4; - image.dst_sel_y = 5; - image.dst_sel_z = 6; - image.dst_sel_w = 7; + image.num_format = u64(NumberFormat::Unorm); + image.dst_sel_x = u64(CompSwizzle::Red); + image.dst_sel_y = u64(CompSwizzle::Green); + image.dst_sel_z = u64(CompSwizzle::Blue); + image.dst_sel_w = u64(CompSwizzle::Alpha); image.tiling_index = u64(TilingMode::Texture_MicroTiled); image.type = u64(ImageType::Color2D); return image; @@ -207,58 +212,29 @@ struct Image { return base_address != 0; } - u32 DstSelect() const { - return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9); - } - - CompSwizzle GetSwizzle(u32 comp) const noexcept { - const std::array select{dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w}; - return static_cast(select[comp]); - } - - static char SelectComp(u32 sel) { - switch (sel) { - case 0: - return '0'; - case 1: - return '1'; - case 4: - return 'R'; - case 5: - return 'G'; - case 6: - return 'B'; - case 7: - return 'A'; - default: - UNREACHABLE(); - } - } - - std::string DstSelectName() const { - std::string result = "["; - u32 dst_sel = DstSelect(); - for (u32 i = 0; i < 4; i++) { - result += SelectComp(dst_sel & 7); - dst_sel >>= 3; - } - result += ']'; - return result; + CompMapping DstSelect() const { + const CompMapping dst_sel{ + .r = CompSwizzle(dst_sel_x), + .g = CompSwizzle(dst_sel_y), + .b = CompSwizzle(dst_sel_z), + .a = CompSwizzle(dst_sel_w), + }; + return RemapSwizzle(DataFormat(data_format), dst_sel); } u32 Pitch() const { return pitch + 1; } - u32 NumLayers(bool is_array) const { - u32 slices = GetType() == ImageType::Color3D ? 1 : depth + 1; - if (GetType() == ImageType::Cube) { - if (is_array) { - slices = last_array + 1; - ASSERT(slices % 6 == 0); - } else { - slices = 6; - } + [[nodiscard]] u32 NumLayers() const noexcept { + // Depth is the number of layers for Array images. + u32 slices = depth + 1; + if (GetType() == ImageType::Color3D) { + // Depth is the actual texture depth for 3D images. + slices = 1; + } else if (IsCube()) { + // Depth is the number of full cubes for Cube images. + slices *= 6; } if (pow2pad) { slices = std::bit_ceil(slices); @@ -280,16 +256,24 @@ struct Image { return 1; } + bool IsCube() const noexcept { + return static_cast(type) == ImageType::Cube; + } + ImageType GetType() const noexcept { - return static_cast(type); + return IsCube() ? ImageType::Color2DArray : static_cast(type); } DataFormat GetDataFmt() const noexcept { - return static_cast(data_format); + return RemapDataFormat(DataFormat(data_format)); } NumberFormat GetNumberFmt() const noexcept { - return static_cast(num_format); + return RemapNumberFormat(NumberFormat(num_format), DataFormat(data_format)); + } + + NumberConversion GetNumberConversion() const noexcept { + return MapNumberConversion(NumberFormat(num_format)); } TilingMode GetTilingMode() const { @@ -309,13 +293,48 @@ struct Image { GetDataFmt() <= DataFormat::FormatFmask64_8; } - bool IsPartialCubemap() const { - const auto viewed_slice = last_array - base_array + 1; - return GetType() == ImageType::Cube && viewed_slice < 6; + [[nodiscard]] ImageType GetViewType(const bool is_array) const noexcept { + const auto base_type = GetType(); + if (IsCube()) { + // Cube needs to remain array type regardless of instruction array specifier. + return base_type; + } + if (base_type == ImageType::Color1DArray && !is_array) { + return ImageType::Color1D; + } + if (base_type == ImageType::Color2DArray && !is_array) { + return ImageType::Color2D; + } + if (base_type == ImageType::Color2DMsaaArray && !is_array) { + return ImageType::Color2DMsaa; + } + return base_type; } - ImageType GetBoundType() const noexcept { - return IsPartialCubemap() ? ImageType::Color2DArray : GetType(); + [[nodiscard]] u32 NumViewLevels(const bool is_array) const noexcept { + switch (GetViewType(is_array)) { + case ImageType::Color2DMsaa: + case ImageType::Color2DMsaaArray: + return 1; + default: + // Constrain to actual number of available levels. + const auto max_level = std::min(last_level + 1, NumLevels()); + return max_level > base_level ? max_level - base_level : 1; + } + } + + [[nodiscard]] u32 NumViewLayers(const bool is_array) const noexcept { + switch (GetViewType(is_array)) { + case ImageType::Color1D: + case ImageType::Color2D: + case ImageType::Color2DMsaa: + case ImageType::Color3D: + return 1; + default: + // Constrain to actual number of available layers. + const auto max_array = std::min(last_array + 1, NumLayers()); + return max_array > base_array ? max_array - base_array : 1; + } } }; static_assert(sizeof(Image) == 32); // 256bits @@ -364,6 +383,16 @@ enum class Filter : u64 { AnisoLinear = 3, }; +constexpr bool IsAnisoFilter(const Filter filter) { + switch (filter) { + case Filter::AnisoPoint: + case Filter::AnisoLinear: + return true; + default: + return false; + } +} + enum class MipFilter : u64 { None = 0, Point = 1, @@ -435,6 +464,23 @@ struct Sampler { float MaxLod() const noexcept { return static_cast(max_lod.Value()) / 256.0f; } + + float MaxAniso() const { + switch (max_aniso.Value()) { + case AnisoRatio::One: + return 1.0f; + case AnisoRatio::Two: + return 2.0f; + case AnisoRatio::Four: + return 4.0f; + case AnisoRatio::Eight: + return 8.0f; + case AnisoRatio::Sixteen: + return 16.0f; + default: + UNREACHABLE(); + } + } }; } // namespace AmdGpu diff --git a/src/video_core/amdgpu/types.h b/src/video_core/amdgpu/types.h index fa8491665..57f97418a 100644 --- a/src/video_core/amdgpu/types.h +++ b/src/video_core/amdgpu/types.h @@ -5,6 +5,7 @@ #include #include +#include "common/assert.h" #include "common/types.h" namespace AmdGpu { @@ -177,11 +178,138 @@ enum class NumberFormat : u32 { Float = 7, Srgb = 9, Ubnorm = 10, - UbnromNz = 11, + UbnormNz = 11, Ubint = 12, Ubscaled = 13, }; +enum class CompSwizzle : u32 { + Zero = 0, + One = 1, + Red = 4, + Green = 5, + Blue = 6, + Alpha = 7, +}; + +enum class NumberConversion : u32 { + None, + UintToUscaled, + SintToSscaled, + UnormToUbnorm, +}; + +struct CompMapping { + CompSwizzle r : 3; + CompSwizzle g : 3; + CompSwizzle b : 3; + CompSwizzle a : 3; + + auto operator<=>(const CompMapping& other) const = default; + + template + [[nodiscard]] std::array Apply(const std::array& data) const { + return { + ApplySingle(data, r), + ApplySingle(data, g), + ApplySingle(data, b), + ApplySingle(data, a), + }; + } + +private: + template + T ApplySingle(const std::array& data, const CompSwizzle swizzle) const { + switch (swizzle) { + case CompSwizzle::Zero: + return T(0); + case CompSwizzle::One: + return T(1); + case CompSwizzle::Red: + return data[0]; + case CompSwizzle::Green: + return data[1]; + case CompSwizzle::Blue: + return data[2]; + case CompSwizzle::Alpha: + return data[3]; + default: + UNREACHABLE(); + } + } +}; + +inline DataFormat RemapDataFormat(const DataFormat format) { + switch (format) { + case DataFormat::Format11_11_10: + return DataFormat::Format10_11_11; + case DataFormat::Format10_10_10_2: + return DataFormat::Format2_10_10_10; + case DataFormat::Format5_5_5_1: + return DataFormat::Format1_5_5_5; + default: + return format; + } +} + +inline NumberFormat RemapNumberFormat(const NumberFormat format, const DataFormat data_format) { + switch (format) { + case NumberFormat::Uscaled: + return NumberFormat::Uint; + case NumberFormat::Sscaled: + return NumberFormat::Sint; + case NumberFormat::Ubnorm: + return NumberFormat::Unorm; + case NumberFormat::Float: + if (data_format == DataFormat::Format8) { + // Games may ask for 8-bit float when they want to access the stencil component + // of a depth-stencil image. Change to unsigned int to match the stencil format. + // This is also the closest approximation to pass the bits through unconverted. + return NumberFormat::Uint; + } + [[fallthrough]]; + default: + return format; + } +} + +inline CompMapping RemapSwizzle(const DataFormat format, const CompMapping swizzle) { + switch (format) { + case DataFormat::Format11_11_10: { + CompMapping result; + result.r = swizzle.b; + result.g = swizzle.g; + result.b = swizzle.r; + result.a = swizzle.a; + return result; + } + case DataFormat::Format10_10_10_2: + case DataFormat::Format5_5_5_1: { + CompMapping result; + result.r = swizzle.a; + result.g = swizzle.b; + result.b = swizzle.g; + result.a = swizzle.r; + return result; + } + default: + return swizzle; + } +} + +inline NumberConversion MapNumberConversion(const NumberFormat format) { + switch (format) { + case NumberFormat::Uscaled: + return NumberConversion::UintToUscaled; + case NumberFormat::Sscaled: + return NumberConversion::SintToSscaled; + case NumberFormat::Ubnorm: + return NumberConversion::UnormToUbnorm; + default: + return NumberConversion::None; + } +} + } // namespace AmdGpu template <> diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index feeafd9bd..63391a180 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -119,19 +119,23 @@ public: return buffer; } - std::optional GetBarrier(vk::AccessFlagBits2 dst_acess_mask, - vk::PipelineStageFlagBits2 dst_stage) { + std::optional GetBarrier( + vk::Flags dst_acess_mask, vk::PipelineStageFlagBits2 dst_stage, + u32 offset = 0) { if (dst_acess_mask == access_mask && stage == dst_stage) { return {}; } + DEBUG_ASSERT(offset < size_bytes); + auto barrier = vk::BufferMemoryBarrier2{ .srcStageMask = stage, .srcAccessMask = access_mask, .dstStageMask = dst_stage, .dstAccessMask = dst_acess_mask, .buffer = buffer.buffer, - .size = size_bytes, + .offset = offset, + .size = size_bytes - offset, }; access_mask = dst_acess_mask; stage = dst_stage; @@ -150,8 +154,10 @@ public: Vulkan::Scheduler* scheduler; MemoryUsage usage; UniqueBuffer buffer; - vk::AccessFlagBits2 access_mask{vk::AccessFlagBits2::eNone}; - vk::PipelineStageFlagBits2 stage{vk::PipelineStageFlagBits2::eNone}; + vk::Flags access_mask{ + vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite | + vk::AccessFlagBits2::eTransferRead | vk::AccessFlagBits2::eTransferWrite}; + vk::PipelineStageFlagBits2 stage{vk::PipelineStageFlagBits2::eAllCommands}; }; class StreamBuffer : public Buffer { diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 59c1e0bc3..487544a21 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -10,13 +10,13 @@ #include "video_core/amdgpu/liverpool.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" +#include "video_core/renderer_vulkan/vk_graphics_pipeline.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/texture_cache/texture_cache.h" namespace VideoCore { -static constexpr size_t NumVertexBuffers = 32; static constexpr size_t GdsBufferSize = 64_KB; static constexpr size_t StagingBufferSize = 1_GB; static constexpr size_t UboStreamBufferSize = 64_MB; @@ -34,38 +34,19 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s // Ensure the first slot is used for the null buffer const auto null_id = - slot_buffers.insert(instance, scheduler, MemoryUsage::DeviceLocal, 0, ReadFlags, 1); + slot_buffers.insert(instance, scheduler, MemoryUsage::DeviceLocal, 0, ReadFlags, 16); ASSERT(null_id.index == 0); const vk::Buffer& null_buffer = slot_buffers[null_id].buffer; Vulkan::SetObjectName(instance.GetDevice(), null_buffer, "Null Buffer"); - - const vk::BufferViewCreateInfo null_view_ci = { - .buffer = null_buffer, - .format = vk::Format::eR8Unorm, - .offset = 0, - .range = VK_WHOLE_SIZE, - }; - const auto [null_view_result, null_view] = instance.GetDevice().createBufferView(null_view_ci); - ASSERT_MSG(null_view_result == vk::Result::eSuccess, "Failed to create null buffer view."); - null_buffer_view = null_view; - Vulkan::SetObjectName(instance.GetDevice(), null_buffer_view, "Null Buffer View"); } BufferCache::~BufferCache() = default; void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) { - std::scoped_lock lk{mutex}; const bool is_tracked = IsRegionRegistered(device_addr, size); - if (!is_tracked) { - return; - } - // Mark the page as CPU modified to stop tracking writes. - SCOPE_EXIT { + if (is_tracked) { + // Mark the page as CPU modified to stop tracking writes. memory_tracker.MarkRegionAsCpuModified(device_addr, size); - }; - if (!memory_tracker.IsRegionGpuModified(device_addr, size)) { - // Page has not been modified by the GPU, nothing to do. - return; } } @@ -108,35 +89,22 @@ void BufferCache::DownloadBufferMemory(Buffer& buffer, VAddr device_addr, u64 si } } -bool BufferCache::BindVertexBuffers( - const Shader::Info& vs_info, const std::optional& fetch_shader) { - boost::container::small_vector attributes; - boost::container::small_vector bindings; - SCOPE_EXIT { - if (instance.IsVertexInputDynamicState()) { - const auto cmdbuf = scheduler.CommandBuffer(); - cmdbuf.setVertexInputEXT(bindings, attributes); - } else if (bindings.empty()) { - // Required to call bindVertexBuffers2EXT at least once in the current command buffer - // with non-null strides without a non-dynamic stride pipeline in between. Thus even - // when nothing is bound we still need to make a dummy call. Non-null strides in turn - // requires a count greater than 0. - const auto cmdbuf = scheduler.CommandBuffer(); - const std::array null_buffers = {GetBuffer(NULL_BUFFER_ID).buffer.buffer}; - constexpr std::array null_offsets = {static_cast(0)}; - cmdbuf.bindVertexBuffers2EXT(0, null_buffers, null_offsets, null_offsets, null_offsets); - } - }; +void BufferCache::BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline) { + Vulkan::VertexInputs attributes; + Vulkan::VertexInputs bindings; + Vulkan::VertexInputs guest_buffers; + pipeline.GetVertexInputs(attributes, bindings, guest_buffers); - if (!fetch_shader || fetch_shader->attributes.empty()) { - return false; + if (instance.IsVertexInputDynamicState()) { + // Update current vertex inputs. + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.setVertexInputEXT(bindings, attributes); } - std::array host_buffers; - std::array host_offsets; - std::array host_sizes; - std::array host_strides; - boost::container::static_vector guest_buffers; + if (bindings.empty()) { + // If there are no bindings, there is nothing further to do. + return; + } struct BufferRange { VAddr base_address; @@ -144,61 +112,37 @@ bool BufferCache::BindVertexBuffers( vk::Buffer vk_buffer; u64 offset; - size_t GetSize() const { + [[nodiscard]] size_t GetSize() const { return end_address - base_address; } }; - // Calculate buffers memory overlaps - bool has_step_rate = false; - boost::container::static_vector ranges{}; - for (const auto& attrib : fetch_shader->attributes) { - if (attrib.UsesStepRates()) { - has_step_rate = true; - continue; + // Build list of ranges covering the requested buffers + Vulkan::VertexInputs ranges{}; + for (const auto& buffer : guest_buffers) { + if (buffer.GetSize() > 0) { + ranges.emplace_back(buffer.base_address, buffer.base_address + buffer.GetSize()); } + } - const auto& buffer = attrib.GetSharp(vs_info); - if (buffer.GetSize() == 0) { - continue; - } - guest_buffers.emplace_back(buffer); - ranges.emplace_back(buffer.base_address, buffer.base_address + buffer.GetSize()); - attributes.push_back({ - .location = attrib.semantic, - .binding = attrib.semantic, - .format = - Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()), - .offset = 0, + // Merge connecting ranges together + Vulkan::VertexInputs ranges_merged{}; + if (!ranges.empty()) { + std::ranges::sort(ranges, [](const BufferRange& lhv, const BufferRange& rhv) { + return lhv.base_address < rhv.base_address; }); - bindings.push_back({ - .binding = attrib.semantic, - .stride = buffer.GetStride(), - .inputRate = attrib.GetStepRate() == Shader::Gcn::VertexAttribute::InstanceIdType::None - ? vk::VertexInputRate::eVertex - : vk::VertexInputRate::eInstance, - .divisor = 1, - }); - } - if (ranges.empty()) { - return false; - } - - std::ranges::sort(ranges, [](const BufferRange& lhv, const BufferRange& rhv) { - return lhv.base_address < rhv.base_address; - }); - - boost::container::static_vector ranges_merged{ranges[0]}; - for (auto range : ranges) { - auto& prev_range = ranges_merged.back(); - if (prev_range.end_address < range.base_address) { - ranges_merged.emplace_back(range); - } else { - prev_range.end_address = std::max(prev_range.end_address, range.end_address); + ranges_merged.emplace_back(ranges[0]); + for (auto range : ranges) { + auto& prev_range = ranges_merged.back(); + if (prev_range.end_address < range.base_address) { + ranges_merged.emplace_back(range); + } else { + prev_range.end_address = std::max(prev_range.end_address, range.end_address); + } } } - // Map buffers + // Map buffers for merged ranges for (auto& range : ranges_merged) { const auto [buffer, offset] = ObtainBuffer(range.base_address, range.GetSize(), false); range.vk_buffer = buffer->buffer; @@ -206,74 +150,57 @@ bool BufferCache::BindVertexBuffers( } // Bind vertex buffers - const size_t num_buffers = guest_buffers.size(); - for (u32 i = 0; i < num_buffers; ++i) { - const auto& buffer = guest_buffers[i]; - const auto host_buffer = std::ranges::find_if(ranges_merged, [&](const BufferRange& range) { - return (buffer.base_address >= range.base_address && - buffer.base_address < range.end_address); - }); - ASSERT(host_buffer != ranges_merged.cend()); - - host_buffers[i] = host_buffer->vk_buffer; - host_offsets[i] = host_buffer->offset + buffer.base_address - host_buffer->base_address; - host_sizes[i] = buffer.GetSize(); - host_strides[i] = buffer.GetStride(); - } - - if (num_buffers > 0) { - const auto cmdbuf = scheduler.CommandBuffer(); - if (instance.IsVertexInputDynamicState()) { - cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data()); + Vulkan::VertexInputs host_buffers; + Vulkan::VertexInputs host_offsets; + Vulkan::VertexInputs host_sizes; + Vulkan::VertexInputs host_strides; + const auto null_buffer = + instance.IsNullDescriptorSupported() ? VK_NULL_HANDLE : GetBuffer(NULL_BUFFER_ID).Handle(); + for (const auto& buffer : guest_buffers) { + if (buffer.GetSize() > 0) { + const auto host_buffer_info = + std::ranges::find_if(ranges_merged, [&](const BufferRange& range) { + return buffer.base_address >= range.base_address && + buffer.base_address < range.end_address; + }); + ASSERT(host_buffer_info != ranges_merged.cend()); + host_buffers.emplace_back(host_buffer_info->vk_buffer); + host_offsets.push_back(host_buffer_info->offset + buffer.base_address - + host_buffer_info->base_address); } else { - cmdbuf.bindVertexBuffers2EXT(0, num_buffers, host_buffers.data(), host_offsets.data(), - host_sizes.data(), host_strides.data()); + host_buffers.emplace_back(null_buffer); + host_offsets.push_back(0); } + host_sizes.push_back(buffer.GetSize()); + host_strides.push_back(buffer.GetStride()); } - return has_step_rate; + const auto cmdbuf = scheduler.CommandBuffer(); + const auto num_buffers = guest_buffers.size(); + if (instance.IsVertexInputDynamicState()) { + cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data()); + } else { + cmdbuf.bindVertexBuffers2EXT(0, num_buffers, host_buffers.data(), host_offsets.data(), + host_sizes.data(), host_strides.data()); + } } -u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { - // Emulate QuadList and Polygon primitive types with CPU made index buffer. +void BufferCache::BindIndexBuffer(u32 index_offset) { const auto& regs = liverpool->regs; - if (!is_indexed) { - if (regs.primitive_type != AmdGpu::PrimitiveType::Polygon) { - return regs.num_indices; - } - - // Emit indices. - const u32 index_size = 3 * regs.num_indices; - const auto [data, offset] = stream_buffer.Map(index_size); - Vulkan::LiverpoolToVK::EmitPolygonToTriangleListIndices(data, regs.num_indices); - stream_buffer.Commit(); - - // Bind index buffer. - is_indexed = true; - - const auto cmdbuf = scheduler.CommandBuffer(); - cmdbuf.bindIndexBuffer(stream_buffer.Handle(), offset, vk::IndexType::eUint16); - return index_size / sizeof(u16); - } // Figure out index type and size. const bool is_index16 = regs.index_buffer_type.index_type == AmdGpu::Liverpool::IndexType::Index16; const vk::IndexType index_type = is_index16 ? vk::IndexType::eUint16 : vk::IndexType::eUint32; const u32 index_size = is_index16 ? sizeof(u16) : sizeof(u32); - VAddr index_address = regs.index_base_address.Address(); - index_address += index_offset * index_size; - - if (regs.primitive_type == AmdGpu::PrimitiveType::Polygon) { - UNREACHABLE(); - } + const VAddr index_address = + regs.index_base_address.Address() + index_offset * index_size; // Bind index buffer. const u32 index_buffer_size = regs.num_indices * index_size; const auto [vk_buffer, offset] = ObtainBuffer(index_address, index_buffer_size, false); const auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.bindIndexBuffer(vk_buffer->Handle(), offset, index_type); - return regs.num_indices; } void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds) { @@ -291,7 +218,16 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo const BufferId buffer_id = FindBuffer(address, num_bytes); return &slot_buffers[buffer_id]; }(); - const vk::BufferMemoryBarrier2 buf_barrier = { + const vk::BufferMemoryBarrier2 pre_barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .srcAccessMask = vk::AccessFlagBits2::eMemoryRead, + .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, + .dstAccessMask = vk::AccessFlagBits2::eTransferWrite, + .buffer = buffer->Handle(), + .offset = buffer->Offset(address), + .size = num_bytes, + }; + const vk::BufferMemoryBarrier2 post_barrier = { .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, @@ -303,9 +239,14 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo cmdbuf.pipelineBarrier2(vk::DependencyInfo{ .dependencyFlags = vk::DependencyFlagBits::eByRegion, .bufferMemoryBarrierCount = 1, - .pBufferMemoryBarriers = &buf_barrier, + .pBufferMemoryBarriers = &pre_barrier, + }); + cmdbuf.updateBuffer(buffer->Handle(), buffer->Offset(address), num_bytes, value); + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &post_barrier, }); - cmdbuf.updateBuffer(buffer->Handle(), buf_barrier.offset, num_bytes, value); } std::pair BufferCache::ObtainHostUBO(std::span data) { @@ -370,6 +311,7 @@ bool BufferCache::IsRegionRegistered(VAddr addr, size_t size) { ++page; continue; } + std::shared_lock lk{mutex}; Buffer& buffer = slot_buffers[buffer_id]; const VAddr buf_start_addr = buffer.CpuAddr(); const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); @@ -496,21 +438,41 @@ void BufferCache::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, }; scheduler.EndRendering(); const auto cmdbuf = scheduler.CommandBuffer(); - static constexpr vk::MemoryBarrier READ_BARRIER{ - .srcAccessMask = vk::AccessFlagBits::eMemoryWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite, - }; - static constexpr vk::MemoryBarrier WRITE_BARRIER{ - .srcAccessMask = vk::AccessFlagBits::eTransferWrite, - .dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite, - }; - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, - READ_BARRIER, {}, {}); - cmdbuf.copyBuffer(overlap.buffer, new_buffer.buffer, copy); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, - vk::PipelineStageFlagBits::eAllCommands, - vk::DependencyFlagBits::eByRegion, WRITE_BARRIER, {}, {}); + + boost::container::static_vector pre_barriers{}; + if (auto src_barrier = overlap.GetBarrier(vk::AccessFlagBits2::eTransferRead, + vk::PipelineStageFlagBits2::eTransfer)) { + pre_barriers.push_back(*src_barrier); + } + if (auto dst_barrier = + new_buffer.GetBarrier(vk::AccessFlagBits2::eTransferWrite, + vk::PipelineStageFlagBits2::eTransfer, dst_base_offset)) { + pre_barriers.push_back(*dst_barrier); + } + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = static_cast(pre_barriers.size()), + .pBufferMemoryBarriers = pre_barriers.data(), + }); + + cmdbuf.copyBuffer(overlap.Handle(), new_buffer.Handle(), copy); + + boost::container::static_vector post_barriers{}; + if (auto src_barrier = + overlap.GetBarrier(vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + vk::PipelineStageFlagBits2::eAllCommands)) { + post_barriers.push_back(*src_barrier); + } + if (auto dst_barrier = new_buffer.GetBarrier( + vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + vk::PipelineStageFlagBits2::eAllCommands, dst_base_offset)) { + post_barriers.push_back(*dst_barrier); + } + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = static_cast(post_barriers.size()), + .pBufferMemoryBarriers = post_barriers.data(), + }); DeleteBuffer(overlap_id); } @@ -520,8 +482,11 @@ BufferId BufferCache::CreateBuffer(VAddr device_addr, u32 wanted_size) { wanted_size = static_cast(device_addr_end - device_addr); 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, scheduler, MemoryUsage::DeviceLocal, overlap.begin, AllFlags, size); + const BufferId new_buffer_id = [&] { + std::scoped_lock lk{mutex}; + return slot_buffers.insert(instance, scheduler, 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(); @@ -561,10 +526,8 @@ void BufferCache::ChangeRegister(BufferId buffer_id) { void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, bool is_texel_buffer) { - std::scoped_lock lk{mutex}; boost::container::small_vector copies; u64 total_size_bytes = 0; - u64 largest_copy = 0; VAddr buffer_start = buffer.CpuAddr(); memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) { copies.push_back(vk::BufferCopy{ @@ -573,7 +536,6 @@ void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, .size = range_size, }); total_size_bytes += range_size; - largest_copy = std::max(largest_copy, range_size); }); SCOPE_EXIT { if (is_texel_buffer) { @@ -614,21 +576,36 @@ void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, } scheduler.EndRendering(); const auto cmdbuf = scheduler.CommandBuffer(); - static constexpr vk::MemoryBarrier READ_BARRIER{ - .srcAccessMask = vk::AccessFlagBits::eMemoryWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite, + const vk::BufferMemoryBarrier2 pre_barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .srcAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite | + vk::AccessFlagBits2::eTransferRead | vk::AccessFlagBits2::eTransferWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, + .dstAccessMask = vk::AccessFlagBits2::eTransferWrite, + .buffer = buffer.Handle(), + .offset = 0, + .size = buffer.SizeBytes(), }; - static constexpr vk::MemoryBarrier WRITE_BARRIER{ - .srcAccessMask = vk::AccessFlagBits::eTransferWrite, - .dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite, + const vk::BufferMemoryBarrier2 post_barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, + .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .dstAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + .buffer = buffer.Handle(), + .offset = 0, + .size = buffer.SizeBytes(), }; - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, - READ_BARRIER, {}, {}); + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &pre_barrier, + }); cmdbuf.copyBuffer(src_buffer, buffer.buffer, copies); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, - vk::PipelineStageFlagBits::eAllCommands, - vk::DependencyFlagBits::eByRegion, WRITE_BARRIER, {}, {}); + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &post_barrier, + }); } bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, u32 size) { @@ -636,7 +613,7 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, FindFlags::NoCreate | FindFlags::RelaxDim | FindFlags::RelaxFmt | FindFlags::RelaxSize; TextureCache::BaseDesc desc{}; desc.info.guest_address = device_addr; - desc.info.guest_size_bytes = size; + desc.info.guest_size = size; const ImageId image_id = texture_cache.FindImage(desc, find_flags); if (!image_id) { return false; @@ -678,10 +655,42 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, } if (!copies.empty()) { scheduler.EndRendering(); - image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {}); + const vk::BufferMemoryBarrier2 pre_barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .srcAccessMask = vk::AccessFlagBits2::eMemoryRead, + .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, + .dstAccessMask = vk::AccessFlagBits2::eTransferWrite, + .buffer = buffer.Handle(), + .offset = max_offset - size, + .size = size, + }; + const vk::BufferMemoryBarrier2 post_barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, + .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .dstAccessMask = vk::AccessFlagBits2::eMemoryRead, + .buffer = buffer.Handle(), + .offset = max_offset - size, + .size = size, + }; + auto barriers = image.GetBarriers(vk::ImageLayout::eTransferSrcOptimal, + vk::AccessFlagBits2::eTransferRead, + vk::PipelineStageFlagBits2::eTransfer, {}); const auto cmdbuf = scheduler.CommandBuffer(); - cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.buffer, + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &pre_barrier, + .imageMemoryBarrierCount = static_cast(barriers.size()), + .pImageMemoryBarriers = barriers.data(), + }); + cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.Handle(), copies); + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &post_barrier, + }); } return true; } diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index bcbaa45dc..575ee2c60 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -3,10 +3,8 @@ #pragma once -#include +#include #include -#include -#include #include "common/div_ceil.h" #include "common/slot_vector.h" #include "common/types.h" @@ -26,6 +24,10 @@ struct FetchShaderData; struct Info; } // namespace Shader +namespace Vulkan { +class GraphicsPipeline; +} + namespace VideoCore { using BufferId = Common::SlotId; @@ -71,19 +73,14 @@ public: return slot_buffers[id]; } - [[nodiscard]] vk::BufferView& NullBufferView() { - return null_buffer_view; - } - /// Invalidates any buffer in the logical page range. void InvalidateMemory(VAddr device_addr, u64 size); /// Binds host vertex buffers for the current draw. - bool BindVertexBuffers(const Shader::Info& vs_info, - const std::optional& fetch_shader); + void BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline); /// Bind host index buffer for the current draw. - u32 BindIndexBuffer(bool& is_indexed, u32 index_offset); + void BindIndexBuffer(u32 index_offset); /// Writes a value to GPU buffer. void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds); @@ -157,10 +154,9 @@ private: StreamBuffer staging_buffer; StreamBuffer stream_buffer; Buffer gds_buffer; - std::mutex mutex; + std::shared_mutex mutex; Common::SlotVector slot_buffers; RangeSet gpu_modified_ranges; - vk::BufferView null_buffer_view; MemoryTracker memory_tracker; PageTable page_table; }; diff --git a/src/video_core/buffer_cache/memory_tracker_base.h b/src/video_core/buffer_cache/memory_tracker_base.h index ae61b55f2..d9166b11c 100644 --- a/src/video_core/buffer_cache/memory_tracker_base.h +++ b/src/video_core/buffer_cache/memory_tracker_base.h @@ -15,13 +15,8 @@ namespace VideoCore { class MemoryTracker { public: static constexpr size_t MAX_CPU_PAGE_BITS = 40; - static constexpr size_t HIGHER_PAGE_BITS = 22; - static constexpr size_t HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS; - static constexpr size_t HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL; static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS); static constexpr size_t MANAGER_POOL_SIZE = 32; - static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD; - using Manager = WordManager; public: explicit MemoryTracker(PageManager* tracker_) : tracker{tracker_} {} @@ -30,7 +25,7 @@ public: /// Returns true if a region has been modified from the CPU [[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept { return IteratePages( - query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) { + query_cpu_addr, query_size, [](RegionManager* manager, u64 offset, size_t size) { return manager->template IsRegionModified(offset, size); }); } @@ -38,52 +33,34 @@ public: /// Returns true if a region has been modified from the GPU [[nodiscard]] bool IsRegionGpuModified(VAddr query_cpu_addr, u64 query_size) noexcept { return IteratePages( - query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) { + query_cpu_addr, query_size, [](RegionManager* manager, u64 offset, size_t size) { return manager->template IsRegionModified(offset, size); }); } /// Mark region as CPU modified, notifying the device_tracker about this change void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); - } - - /// Unmark region as CPU modified, notifying the device_tracker about this change - void UnmarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); + IteratePages(dirty_cpu_addr, query_size, + [](RegionManager* manager, u64 offset, size_t size) { + manager->template ChangeRegionState( + manager->GetCpuAddr() + offset, size); + }); } /// Mark region as modified from the host GPU void MarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); - } - - /// Unmark region as modified from the host GPU - void UnmarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); + IteratePages(dirty_cpu_addr, query_size, + [](RegionManager* manager, u64 offset, size_t size) { + manager->template ChangeRegionState( + manager->GetCpuAddr() + offset, size); + }); } /// Call 'func' for each CPU modified range and unmark those pages as CPU modified template void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) { IteratePages(query_cpu_range, query_size, - [&func](Manager* manager, u64 offset, size_t size) { + [&func](RegionManager* manager, u64 offset, size_t size) { manager->template ForEachModifiedRange( manager->GetCpuAddr() + offset, size, func); }); @@ -93,7 +70,7 @@ public: template void ForEachDownloadRange(VAddr query_cpu_range, u64 query_size, Func&& func) { IteratePages(query_cpu_range, query_size, - [&func](Manager* manager, u64 offset, size_t size) { + [&func](RegionManager* manager, u64 offset, size_t size) { if constexpr (clear) { manager->template ForEachModifiedRange( manager->GetCpuAddr() + offset, size, func); @@ -114,7 +91,7 @@ private: */ template bool IteratePages(VAddr cpu_address, size_t size, Func&& func) { - using FuncReturn = typename std::invoke_result::type; + using FuncReturn = typename std::invoke_result::type; static constexpr bool BOOL_BREAK = std::is_same_v; std::size_t remaining_size{size}; std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS}; @@ -155,7 +132,7 @@ private: manager_pool.emplace_back(); auto& last_pool = manager_pool.back(); for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) { - std::construct_at(&last_pool[i], tracker, 0, HIGHER_PAGE_SIZE); + std::construct_at(&last_pool[i], tracker, 0); free_managers.push_back(&last_pool[i]); } } @@ -167,9 +144,9 @@ private: } PageManager* tracker; - std::deque> manager_pool; - std::vector free_managers; - std::array top_tier{}; + std::deque> manager_pool; + std::vector free_managers; + std::array top_tier{}; }; } // namespace VideoCore diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h index ae85d1eb1..7ad33d7a6 100644 --- a/src/video_core/buffer_cache/word_manager.h +++ b/src/video_core/buffer_cache/word_manager.h @@ -3,10 +3,12 @@ #pragma once -#include +#include +#include #include #include -#include "common/div_ceil.h" + +#include "common/spin_lock.h" #include "common/types.h" #include "video_core/page_manager.h" @@ -16,135 +18,32 @@ constexpr u64 PAGES_PER_WORD = 64; constexpr u64 BYTES_PER_PAGE = 4_KB; constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE; +constexpr u64 HIGHER_PAGE_BITS = 22; +constexpr u64 HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS; +constexpr u64 HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL; +constexpr u64 NUM_REGION_WORDS = HIGHER_PAGE_SIZE / BYTES_PER_WORD; + enum class Type { CPU, GPU, Untracked, }; -/// Vector tracking modified pages tightly packed with small vector optimization -template -struct WordsArray { - /// Returns the pointer to the words state - [[nodiscard]] const u64* Pointer(bool is_short) const noexcept { - return is_short ? stack.data() : heap; - } +using WordsArray = std::array; - /// Returns the pointer to the words state - [[nodiscard]] u64* Pointer(bool is_short) noexcept { - return is_short ? stack.data() : heap; - } - - std::array stack{}; ///< Small buffers storage - u64* heap; ///< Not-small buffers pointer to the storage -}; - -template -struct Words { - explicit Words() = default; - explicit Words(u64 size_bytes_) : size_bytes{size_bytes_} { - num_words = Common::DivCeil(size_bytes, BYTES_PER_WORD); - if (IsShort()) { - cpu.stack.fill(~u64{0}); - gpu.stack.fill(0); - untracked.stack.fill(~u64{0}); - } else { - // Share allocation between CPU and GPU pages and set their default values - u64* const alloc = new u64[num_words * 3]; - cpu.heap = alloc; - gpu.heap = alloc + num_words; - untracked.heap = alloc + num_words * 2; - std::fill_n(cpu.heap, num_words, ~u64{0}); - std::fill_n(gpu.heap, num_words, 0); - std::fill_n(untracked.heap, num_words, ~u64{0}); - } - // Clean up tailing bits - const u64 last_word_size = size_bytes % BYTES_PER_WORD; - const u64 last_local_page = Common::DivCeil(last_word_size, BYTES_PER_PAGE); - const u64 shift = (PAGES_PER_WORD - last_local_page) % PAGES_PER_WORD; - const u64 last_word = (~u64{0} << shift) >> shift; - cpu.Pointer(IsShort())[NumWords() - 1] = last_word; - untracked.Pointer(IsShort())[NumWords() - 1] = last_word; - } - - ~Words() { - Release(); - } - - Words& operator=(Words&& rhs) noexcept { - Release(); - size_bytes = rhs.size_bytes; - num_words = rhs.num_words; - cpu = rhs.cpu; - gpu = rhs.gpu; - untracked = rhs.untracked; - rhs.cpu.heap = nullptr; - return *this; - } - - Words(Words&& rhs) noexcept - : size_bytes{rhs.size_bytes}, num_words{rhs.num_words}, cpu{rhs.cpu}, gpu{rhs.gpu}, - untracked{rhs.untracked} { - rhs.cpu.heap = nullptr; - } - - Words& operator=(const Words&) = delete; - Words(const Words&) = delete; - - /// Returns true when the buffer fits in the small vector optimization - [[nodiscard]] bool IsShort() const noexcept { - return num_words <= stack_words; - } - - /// Returns the number of words of the buffer - [[nodiscard]] size_t NumWords() const noexcept { - return num_words; - } - - /// Release buffer resources - void Release() { - if (!IsShort()) { - // CPU written words is the base for the heap allocation - delete[] cpu.heap; - } - } - - template - std::span Span() noexcept { - if constexpr (type == Type::CPU) { - return std::span(cpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::GPU) { - return std::span(gpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::Untracked) { - return std::span(untracked.Pointer(IsShort()), num_words); - } - } - - template - std::span Span() const noexcept { - if constexpr (type == Type::CPU) { - return std::span(cpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::GPU) { - return std::span(gpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::Untracked) { - return std::span(untracked.Pointer(IsShort()), num_words); - } - } - - u64 size_bytes = 0; - size_t num_words = 0; - WordsArray cpu; - WordsArray gpu; - WordsArray untracked; -}; - -template -class WordManager { +/** + * Allows tracking CPU and GPU modification of pages in a contigious 4MB virtual address region. + * Information is stored in bitsets for spacial locality and fast update of single pages. + */ +class RegionManager { public: - explicit WordManager(PageManager* tracker_, VAddr cpu_addr_, u64 size_bytes) - : tracker{tracker_}, cpu_addr{cpu_addr_}, words{size_bytes} {} - - explicit WordManager() = default; + explicit RegionManager(PageManager* tracker_, VAddr cpu_addr_) + : tracker{tracker_}, cpu_addr{cpu_addr_} { + cpu.fill(~u64{0}); + gpu.fill(0); + untracked.fill(~u64{0}); + } + explicit RegionManager() = default; void SetCpuAddress(VAddr new_cpu_addr) { cpu_addr = new_cpu_addr; @@ -175,12 +74,12 @@ public: static constexpr bool BOOL_BREAK = std::is_same_v; const size_t start = static_cast(std::max(static_cast(offset), 0LL)); const size_t end = static_cast(std::max(static_cast(offset + size), 0LL)); - if (start >= SizeBytes() || end <= start) { + if (start >= HIGHER_PAGE_SIZE || end <= start) { return; } auto [start_word, start_page] = GetWordPage(start); auto [end_word, end_page] = GetWordPage(end + BYTES_PER_PAGE - 1ULL); - const size_t num_words = NumWords(); + constexpr size_t num_words = NUM_REGION_WORDS; start_word = std::min(start_word, num_words); end_word = std::min(end_word, num_words); const size_t diff = end_word - start_word; @@ -225,21 +124,21 @@ public: */ template void ChangeRegionState(u64 dirty_addr, u64 size) noexcept(type == Type::GPU) { - std::span state_words = words.template Span(); - [[maybe_unused]] std::span untracked_words = words.template Span(); + std::scoped_lock lk{lock}; + std::span state_words = Span(); IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) { if constexpr (type == Type::CPU) { - NotifyPageTracker(index, untracked_words[index], mask); + UpdateProtection(index, untracked[index], mask); } if constexpr (enable) { state_words[index] |= mask; if constexpr (type == Type::CPU) { - untracked_words[index] |= mask; + untracked[index] |= mask; } } else { state_words[index] &= ~mask; if constexpr (type == Type::CPU) { - untracked_words[index] &= ~mask; + untracked[index] &= ~mask; } } }); @@ -255,10 +154,10 @@ public: */ template void ForEachModifiedRange(VAddr query_cpu_range, s64 size, Func&& func) { + std::scoped_lock lk{lock}; static_assert(type != Type::Untracked); - std::span state_words = words.template Span(); - [[maybe_unused]] std::span untracked_words = words.template Span(); + std::span state_words = Span(); const size_t offset = query_cpu_range - cpu_addr; bool pending = false; size_t pending_offset{}; @@ -269,16 +168,16 @@ public: }; IterateWords(offset, size, [&](size_t index, u64 mask) { if constexpr (type == Type::GPU) { - mask &= ~untracked_words[index]; + mask &= ~untracked[index]; } const u64 word = state_words[index] & mask; if constexpr (clear) { if constexpr (type == Type::CPU) { - NotifyPageTracker(index, untracked_words[index], mask); + UpdateProtection(index, untracked[index], mask); } state_words[index] &= ~mask; if constexpr (type == Type::CPU) { - untracked_words[index] &= ~mask; + untracked[index] &= ~mask; } } const size_t base_offset = index * PAGES_PER_WORD; @@ -315,13 +214,11 @@ public: [[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept { static_assert(type != Type::Untracked); - const std::span state_words = words.template Span(); - [[maybe_unused]] const std::span untracked_words = - words.template Span(); + const std::span state_words = Span(); bool result = false; IterateWords(offset, size, [&](size_t index, u64 mask) { if constexpr (type == Type::GPU) { - mask &= ~untracked_words[index]; + mask &= ~untracked[index]; } const u64 word = state_words[index] & mask; if (word != 0) { @@ -333,44 +230,7 @@ public: return result; } - /// Returns the number of words of the manager - [[nodiscard]] size_t NumWords() const noexcept { - return words.NumWords(); - } - - /// Returns the size in bytes of the manager - [[nodiscard]] u64 SizeBytes() const noexcept { - return words.size_bytes; - } - - /// Returns true when the buffer fits in the small vector optimization - [[nodiscard]] bool IsShort() const noexcept { - return words.IsShort(); - } - private: - template - u64* Array() noexcept { - if constexpr (type == Type::CPU) { - return words.cpu.Pointer(IsShort()); - } else if constexpr (type == Type::GPU) { - return words.gpu.Pointer(IsShort()); - } else if constexpr (type == Type::Untracked) { - return words.untracked.Pointer(IsShort()); - } - } - - template - const u64* Array() const noexcept { - if constexpr (type == Type::CPU) { - return words.cpu.Pointer(IsShort()); - } else if constexpr (type == Type::GPU) { - return words.gpu.Pointer(IsShort()); - } else if constexpr (type == Type::Untracked) { - return words.untracked.Pointer(IsShort()); - } - } - /** * Notify tracker about changes in the CPU tracking state of a word in the buffer * @@ -381,7 +241,7 @@ private: * @tparam add_to_tracker True when the tracker should start tracking the new pages */ template - void NotifyPageTracker(u64 word_index, u64 current_bits, u64 new_bits) const { + void UpdateProtection(u64 word_index, u64 current_bits, u64 new_bits) const { u64 changed_bits = (add_to_tracker ? current_bits : ~current_bits) & new_bits; VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; IteratePages(changed_bits, [&](size_t offset, size_t size) { @@ -390,9 +250,34 @@ private: }); } + template + std::span Span() noexcept { + if constexpr (type == Type::CPU) { + return cpu; + } else if constexpr (type == Type::GPU) { + return gpu; + } else if constexpr (type == Type::Untracked) { + return untracked; + } + } + + template + std::span Span() const noexcept { + if constexpr (type == Type::CPU) { + return cpu; + } else if constexpr (type == Type::GPU) { + return gpu; + } else if constexpr (type == Type::Untracked) { + return untracked; + } + } + + Common::SpinLock lock; PageManager* tracker; VAddr cpu_addr = 0; - Words words; + WordsArray cpu; + WordsArray gpu; + WordsArray untracked; }; } // namespace VideoCore diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index c2a3b53fd..a9c2964ad 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -2,13 +2,14 @@ # SPDX-License-Identifier: GPL-2.0-or-later set(SHADER_FILES - detile_m8x1.comp - detile_m8x2.comp - detile_m32x1.comp - detile_m32x2.comp - detile_m32x4.comp - detile_macro32x1.comp - detile_macro32x2.comp + detilers/macro_32bpp.comp + detilers/macro_64bpp.comp + detilers/macro_8bpp.comp + detilers/micro_128bpp.comp + detilers/micro_16bpp.comp + detilers/micro_32bpp.comp + detilers/micro_64bpp.comp + detilers/micro_8bpp.comp fs_tri.vert post_process.frag ) diff --git a/src/video_core/host_shaders/detile_macro32x1.comp b/src/video_core/host_shaders/detile_macro32x1.comp deleted file mode 100644 index 086fbcfb5..000000000 --- a/src/video_core/host_shaders/detile_macro32x1.comp +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#version 450 - -layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; - -layout(std430, binding = 0) buffer input_buf { - uint in_data[]; -}; -layout(std430, binding = 1) buffer output_buf { - uint out_data[]; -}; - -layout(push_constant) uniform image_info { - uint num_levels; - uint pitch; - uint height; - uint c0; - uint c1; -} info; - -// Each LUT is 64 bytes, so should fit into K$ given tiled slices locality -const uint lut_32bpp[][64] = { - { - 0x00, 0x01, 0x04, 0x05, 0x40, 0x41, 0x44, 0x45, - 0x02, 0x03, 0x06, 0x07, 0x42, 0x43, 0x46, 0x47, - 0x10, 0x11, 0x14, 0x15, 0x50, 0x51, 0x54, 0x55, - 0x12, 0x13, 0x16, 0x17, 0x52, 0x53, 0x56, 0x57, - 0x80, 0x81, 0x84, 0x85, 0xc0, 0xc1, 0xc4, 0xc5, - 0x82, 0x83, 0x86, 0x87, 0xc2, 0xc3, 0xc6, 0xc7, - 0x90, 0x91, 0x94, 0x95, 0xd0, 0xd1, 0xd4, 0xd5, - 0x92, 0x93, 0x96, 0x97, 0xd2, 0xd3, 0xd6, 0xd7, - }, - { - 0x08, 0x09, 0x0c, 0x0d, 0x48, 0x49, 0x4c, 0x4d, - 0x0a, 0x0b, 0x0e, 0x0f, 0x4a, 0x4b, 0x4e, 0x4f, - 0x18, 0x19, 0x1c, 0x1d, 0x58, 0x59, 0x5c, 0x5d, - 0x1a, 0x1b, 0x1e, 0x1f, 0x5a, 0x5b, 0x5e, 0x5f, - 0x88, 0x89, 0x8c, 0x8d, 0xc8, 0xc9, 0xcc, 0xcd, - 0x8a, 0x8b, 0x8e, 0x8f, 0xca, 0xcb, 0xce, 0xcf, - 0x98, 0x99, 0x9c, 0x9d, 0xd8, 0xd9, 0xdc, 0xdd, - 0x9a, 0x9b, 0x9e, 0x9f, 0xda, 0xdb, 0xde, 0xdf, - }, - { - 0x20, 0x21, 0x24, 0x25, 0x60, 0x61, 0x64, 0x65, - 0x22, 0x23, 0x26, 0x27, 0x62, 0x63, 0x66, 0x67, - 0x30, 0x31, 0x34, 0x35, 0x70, 0x71, 0x74, 0x75, - 0x32, 0x33, 0x36, 0x37, 0x72, 0x73, 0x76, 0x77, - 0xa0, 0xa1, 0xa4, 0xa5, 0xe0, 0xe1, 0xe4, 0xe5, - 0xa2, 0xa3, 0xa6, 0xa7, 0xe2, 0xe3, 0xe6, 0xe7, - 0xb0, 0xb1, 0xb4, 0xb5, 0xf0, 0xf1, 0xf4, 0xf5, - 0xb2, 0xb3, 0xb6, 0xb7, 0xf2, 0xf3, 0xf6, 0xf7, - }, - { - 0x28, 0x29, 0x2c, 0x2d, 0x68, 0x69, 0x6c, 0x6d, - 0x2a, 0x2b, 0x2e, 0x2f, 0x6a, 0x6b, 0x6e, 0x6f, - 0x38, 0x39, 0x3c, 0x3d, 0x78, 0x79, 0x7c, 0x7d, - 0x3a, 0x3b, 0x3e, 0x3f, 0x7a, 0x7b, 0x7e, 0x7f, - 0xa8, 0xa9, 0xac, 0xad, 0xe8, 0xe9, 0xec, 0xed, - 0xaa, 0xab, 0xae, 0xaf, 0xea, 0xeb, 0xee, 0xef, - 0xb8, 0xb9, 0xbc, 0xbd, 0xf8, 0xf9, 0xfc, 0xfd, - 0xba, 0xbb, 0xbe, 0xbf, 0xfa, 0xfb, 0xfe, 0xff, - } -}; - -#define MICRO_TILE_DIM (8) -#define MICRO_TILE_SZ (1024) -#define TEXELS_PER_ELEMENT (1) -#define BPP (32) - -void main() { - uint x = gl_GlobalInvocationID.x % info.pitch; - uint y = (gl_GlobalInvocationID.x / info.pitch) % info.height; - uint z = gl_GlobalInvocationID.x / (info.pitch * info.height); - - uint col = bitfieldExtract(x, 0, 3); - uint row = bitfieldExtract(y, 0, 3); - uint lut = bitfieldExtract(z, 0, 2); - uint idx = lut_32bpp[lut][col + row * MICRO_TILE_DIM]; - - uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ; - uint tile_row = y / MICRO_TILE_DIM; - uint tile_column = x / MICRO_TILE_DIM; - uint tile_offs = ((tile_row * info.c0) + tile_column) * MICRO_TILE_SZ; - uint offs = slice_offs + tile_offs + (idx * BPP / 8); - - uint p0 = in_data[offs >> 2u]; - out_data[gl_GlobalInvocationID.x] = p0; -} diff --git a/src/video_core/host_shaders/detile_macro32x2.comp b/src/video_core/host_shaders/detile_macro32x2.comp deleted file mode 100644 index 296311c7a..000000000 --- a/src/video_core/host_shaders/detile_macro32x2.comp +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#version 450 - -layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; - -layout(std430, binding = 0) buffer input_buf { - uint in_data[]; -}; -layout(std430, binding = 1) buffer output_buf { - uint out_data[]; -}; - -layout(push_constant) uniform image_info { - uint num_levels; - uint pitch; - uint height; - uint c0; - uint c1; -} info; - -const uint lut_64bpp[][64] = { - { - 0x00, 0x01, 0x08, 0x09, 0x40, 0x41, 0x48, 0x49, - 0x02, 0x03, 0x0a, 0x0b, 0x42, 0x43, 0x4a, 0x4b, - 0x10, 0x11, 0x18, 0x19, 0x50, 0x51, 0x58, 0x59, - 0x12, 0x13, 0x1a, 0x1b, 0x52, 0x53, 0x5a, 0x5b, - 0x80, 0x81, 0x88, 0x89, 0xc0, 0xc1, 0xc8, 0xc9, - 0x82, 0x83, 0x8a, 0x8b, 0xc2, 0xc3, 0xca, 0xcb, - 0x90, 0x91, 0x98, 0x99, 0xd0, 0xd1, 0xd8, 0xd9, - 0x92, 0x93, 0x9a, 0x9b, 0xd2, 0xd3, 0xda, 0xdb, - }, - { - 0x04, 0x05, 0x0c, 0x0d, 0x44, 0x45, 0x4c, 0x4d, - 0x06, 0x07, 0x0e, 0x0f, 0x46, 0x47, 0x4e, 0x4f, - 0x14, 0x15, 0x1c, 0x1d, 0x54, 0x55, 0x5c, 0x5d, - 0x16, 0x17, 0x1e, 0x1f, 0x56, 0x57, 0x5e, 0x5f, - 0x84, 0x85, 0x8c, 0x8d, 0xc4, 0xc5, 0xcc, 0xcd, - 0x86, 0x87, 0x8e, 0x8f, 0xc6, 0xc7, 0xce, 0xcf, - 0x94, 0x95, 0x9c, 0x9d, 0xd4, 0xd5, 0xdc, 0xdd, - 0x96, 0x97, 0x9e, 0x9f, 0xd6, 0xd7, 0xde, 0xdf, - }, - { - 0x20, 0x21, 0x28, 0x29, 0x60, 0x61, 0x68, 0x69, - 0x22, 0x23, 0x2a, 0x2b, 0x62, 0x63, 0x6a, 0x6b, - 0x30, 0x31, 0x38, 0x39, 0x70, 0x71, 0x78, 0x79, - 0x32, 0x33, 0x3a, 0x3b, 0x72, 0x73, 0x7a, 0x7b, - 0xa0, 0xa1, 0xa8, 0xa9, 0xe0, 0xe1, 0xe8, 0xe9, - 0xa2, 0xa3, 0xaa, 0xab, 0xe2, 0xe3, 0xea, 0xeb, - 0xb0, 0xb1, 0xb8, 0xb9, 0xf0, 0xf1, 0xf8, 0xf9, - 0xb2, 0xb3, 0xba, 0xbb, 0xf2, 0xf3, 0xfa, 0xfb, - }, - { - 0x24, 0x25, 0x2c, 0x2d, 0x64, 0x65, 0x6c, 0x6d, - 0x26, 0x27, 0x2e, 0x2f, 0x66, 0x67, 0x6e, 0x6f, - 0x34, 0x35, 0x3c, 0x3d, 0x74, 0x75, 0x7c, 0x7d, - 0x36, 0x37, 0x3e, 0x3f, 0x76, 0x77, 0x7e, 0x7f, - 0xa4, 0xa5, 0xac, 0xad, 0xe4, 0xe5, 0xec, 0xed, - 0xa6, 0xa7, 0xae, 0xaf, 0xe6, 0xe7, 0xee, 0xef, - 0xb4, 0xb5, 0xbc, 0xbd, 0xf4, 0xf5, 0xfc, 0xfd, - 0xb6, 0xb7, 0xbe, 0xbf, 0xf6, 0xf7, 0xfe, 0xff, - }, -}; - -#define MICRO_TILE_DIM (8) -#define MICRO_TILE_SZ (2048) -#define TEXELS_PER_ELEMENT (1) -#define BPP (64) - -void main() { - uint x = gl_GlobalInvocationID.x % info.pitch; - uint y = (gl_GlobalInvocationID.x / info.pitch) % info.height; - uint z = gl_GlobalInvocationID.x / (info.pitch * info.height); - - uint col = bitfieldExtract(x, 0, 3); - uint row = bitfieldExtract(y, 0, 3); - uint lut = bitfieldExtract(z, 0, 2); - uint idx = lut_64bpp[lut][col + row * MICRO_TILE_DIM]; - - uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ; - uint tile_row = y / MICRO_TILE_DIM; - uint tile_column = x / MICRO_TILE_DIM; - uint tile_offs = ((tile_row * info.c0) + tile_column) * MICRO_TILE_SZ; - uint offs = slice_offs + tile_offs + (idx * BPP / 8); - - uint p0 = in_data[(offs >> 2) + 0]; - uint p1 = in_data[(offs >> 2) + 1]; - out_data[2 * gl_GlobalInvocationID.x + 0] = p0; - out_data[2 * gl_GlobalInvocationID.x + 1] = p1; -} diff --git a/src/video_core/host_shaders/detilers/macro_32bpp.comp b/src/video_core/host_shaders/detilers/macro_32bpp.comp new file mode 100644 index 000000000..ecac47d1c --- /dev/null +++ b/src/video_core/host_shaders/detilers/macro_32bpp.comp @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 450 + +layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(std430, binding = 0) buffer input_buf { + uint in_data[]; +}; +layout(std430, binding = 1) buffer output_buf { + uint out_data[]; +}; + +layout(push_constant) uniform image_info { + uint num_levels; + uint pitch; + uint height; + uint c0; + uint c1; +} info; + +// Each LUT is 64 bytes, so should fit into K$ given tiled slices locality +const uint lut_32bpp[][16] = { + { + 0x05040100, 0x45444140, + 0x07060302, 0x47464342, + 0x15141110, 0x55545150, + 0x17161312, 0x57565352, + 0x85848180, 0xc5c4c1c0, + 0x87868382, 0xc7c6c3c2, + 0x95949190, 0xd5d4d1d0, + 0x97969392, 0xd7d6d3d2, + }, + { + 0x0d0c0908, 0x4d4c4948, + 0x0f0e0b0a, 0x4f4e4b4a, + 0x1d1c1918, 0x5d5c5958, + 0x1f1e1b1a, 0x5f5e5b5a, + 0x8d8c8988, 0xcdccc9c8, + 0x8f8e8b8a, 0xcfcecbca, + 0x9d9c9998, 0xdddcd9d8, + 0x9f9e9b9a, 0xdfdedbda, + }, + { + 0x25242120, 0x65646160, + 0x27262322, 0x67666362, + 0x35343130, 0x75747170, + 0x37363332, 0x77767372, + 0xa5a4a1a0, 0xe5e4e1e0, + 0xa7a6a3a2, 0xe7e6e3e2, + 0xb5b4b1b0, 0xf5f4f1f0, + 0xb7b6b3b2, 0xf7f6f3f2, + }, + { + 0x2d2c2928, 0x6d6c6968, + 0x2f2e2b2a, 0x6f6e6b6a, + 0x3d3c3938, 0x7d7c7978, + 0x3f3e3b3a, 0x7f7e7b7a, + 0xadaca9a8, 0xedece9e8, + 0xafaeabaa, 0xefeeebea, + 0xbdbcb9b8, 0xfdfcf9f8, + 0xbfbebbba, 0xfffefbfa, + } +}; + +#define MICRO_TILE_DIM (8) +#define MICRO_TILE_SZ (1024) +#define TEXELS_PER_ELEMENT (1) +#define BPP (32) + +void main() { + uint x = gl_GlobalInvocationID.x % info.pitch; + uint y = (gl_GlobalInvocationID.x / info.pitch) % info.height; + uint z = gl_GlobalInvocationID.x / (info.pitch * info.height); + + uint col = bitfieldExtract(x, 0, 3); + uint row = bitfieldExtract(y, 0, 3); + uint lut = bitfieldExtract(z, 0, 2); + uint idx_dw = lut_32bpp[lut][(col + row * MICRO_TILE_DIM) >> 2u]; + uint byte_ofs = gl_LocalInvocationID.x & 3u; + uint idx = bitfieldExtract(idx_dw >> (8 * byte_ofs), 0, 8); + + uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ; + uint tile_row = y / MICRO_TILE_DIM; + uint tile_column = x / MICRO_TILE_DIM; + uint tile_offs = ((tile_row * info.c0) + tile_column) * MICRO_TILE_SZ; + uint offs = slice_offs + tile_offs + (idx * BPP / 8); + + uint p0 = in_data[offs >> 2u]; + out_data[gl_GlobalInvocationID.x] = p0; +} diff --git a/src/video_core/host_shaders/detilers/macro_64bpp.comp b/src/video_core/host_shaders/detilers/macro_64bpp.comp new file mode 100644 index 000000000..986acc963 --- /dev/null +++ b/src/video_core/host_shaders/detilers/macro_64bpp.comp @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 450 + +layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(std430, binding = 0) buffer input_buf { + uint in_data[]; +}; +layout(std430, binding = 1) buffer output_buf { + uint out_data[]; +}; + +layout(push_constant) uniform image_info { + uint num_levels; + uint pitch; + uint height; + uint c0; + uint c1; +} info; + +const uint lut_64bpp[][16] = { + { + 0x09080100, 0x49484140, + 0x0b0a0302, 0x4a4b4342, + 0x19181110, 0x59585150, + 0x1b1a1312, 0x5a5b5352, + 0x89888180, 0xc9c8c1c0, + 0x8b8a8382, 0xcacbc3c2, + 0x99989190, 0xd9d8d1d0, + 0x9b9a9392, 0xdbdad3d2, + }, + { + 0x0d0c0504, 0x4d4c4544, + 0x0f0e0706, 0x4f4e4746, + 0x1d1c1514, 0x5d5c5554, + 0x1f1e1716, 0x5f5e5756, + 0x8d8c8584, 0xcdccc5c4, + 0x8f8e8786, 0xcfcec7c6, + 0x9d9c9594, 0xdddcd5d4, + 0x9f9e9796, 0xdfded7d6, + }, + { + 0x29282120, 0x69686160, + 0x2b2a2322, 0x6b6a6362, + 0x39383130, 0x79787170, + 0x3b3a3332, 0x7b7a7372, + 0xa9a8a1a0, 0xe9e8e1e0, + 0xabaaa3a2, 0xebeae3e2, + 0xb9b8b1b0, 0xf9f8f1f0, + 0xbbbab3b2, 0xfbfaf3f2, + }, + { + 0x2d2c2524, 0x6d6c6564, + 0x2f2e2726, 0x6f6e6766, + 0x3d3c3534, 0x7d7c7574, + 0x3f3e3736, 0x7f7e7776, + 0xadaca5a4, 0xedece5e4, + 0xafaea7a6, 0xefeee7e6, + 0xbdbcb5b4, 0xfdfcf5f4, + 0xbfbeb7b6, 0xfffef7f6, + }, +}; + +#define MICRO_TILE_DIM (8) +#define MICRO_TILE_SZ (2048) +#define TEXELS_PER_ELEMENT (1) +#define BPP (64) + +void main() { + uint x = gl_GlobalInvocationID.x % info.pitch; + uint y = (gl_GlobalInvocationID.x / info.pitch) % info.height; + uint z = gl_GlobalInvocationID.x / (info.pitch * info.height); + + uint col = bitfieldExtract(x, 0, 3); + uint row = bitfieldExtract(y, 0, 3); + uint lut = bitfieldExtract(z, 0, 2); + uint idx_dw = lut_64bpp[lut][(col + row * MICRO_TILE_DIM) >> 2u]; + uint byte_ofs = gl_LocalInvocationID.x & 3u; + uint idx = bitfieldExtract(idx_dw >> (8 * byte_ofs), 0, 8); + + uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ; + uint tile_row = y / MICRO_TILE_DIM; + uint tile_column = x / MICRO_TILE_DIM; + uint tile_offs = ((tile_row * info.c0) + tile_column) * MICRO_TILE_SZ; + uint offs = slice_offs + tile_offs + (idx * BPP / 8); + + uint p0 = in_data[(offs >> 2) + 0]; + uint p1 = in_data[(offs >> 2) + 1]; + out_data[2 * gl_GlobalInvocationID.x + 0] = p0; + out_data[2 * gl_GlobalInvocationID.x + 1] = p1; +} diff --git a/src/video_core/host_shaders/detilers/macro_8bpp.comp b/src/video_core/host_shaders/detilers/macro_8bpp.comp new file mode 100644 index 000000000..cddc8af5b --- /dev/null +++ b/src/video_core/host_shaders/detilers/macro_8bpp.comp @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 450 + +layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(std430, binding = 0) buffer input_buf { + uint in_data[]; +}; +layout(std430, binding = 1) buffer output_buf { + uint out_data[]; +}; + +layout(push_constant) uniform image_info { + uint num_levels; + uint pitch; + uint height; + uint c0; + uint c1; +} info; + +const uint lut_8bpp[][16] = { + { + 0x05040100, 0x45444140, + 0x07060302, 0x47464342, + 0x0d0c0908, 0x4d4c4948, + 0x0f0e0b0a, 0x4f4e4b4a, + 0x85848180, 0xc5c4c1c0, + 0x87868382, 0xc7c6c3c2, + 0x8d8c8988, 0xcdccc9c8, + 0x8f8e8b8a, 0xcfcecbca, + }, + { + 0x15141110, 0x55545150, + 0x17161312, 0x57565352, + 0x1d1c1918, 0x5d5c5958, + 0x1f1e1b1a, 0x5f5e5b5a, + 0x95949190, 0xd5d4d1d0, + 0x97969392, 0xd7d6d3d2, + 0x9d9c9998, 0xdddcd9d8, + 0x9f9e9b9a, 0xdfdedbda, + }, + { + 0x25242120, 0x65646160, + 0x27262322, 0x67666362, + 0x2d2c2928, 0x6d6c6968, + 0x2f2e2b2a, 0x6f6e6b6a, + 0xa5a4a1a0, 0xe5e4e1e0, + 0xa7a6a3a2, 0xe7e6e3e2, + 0xadaca9a8, 0xedece9e8, + 0xafaeabaa, 0xefeeebea, + }, + { + 0x35343130, 0x75747170, + 0x37363332, 0x77767372, + 0x3d3c3938, 0x7d7c7978, + 0x3f3e3b3a, 0x7f7e7b7a, + 0xb5b4b1b0, 0xf5f4f1f0, + 0xb7b6b3b2, 0xf7f6f3f2, + 0xbdbcb9b8, 0xfdfcf9f8, + 0xbfbebbba, 0xfffefbfa, + }, +}; + +#define MICRO_TILE_DIM (8) +#define MICRO_TILE_SZ (256) +#define TEXELS_PER_ELEMENT (1) +#define BPP (8) + +shared uint scratch[16]; + +void main() { + uint slot = gl_LocalInvocationID.x >> 2u; + atomicAnd(scratch[slot], 0); + + uint x = gl_GlobalInvocationID.x % info.pitch; + uint y = (gl_GlobalInvocationID.x / info.pitch) % info.height; + uint z = gl_GlobalInvocationID.x / (info.pitch * info.height); + + uint col = bitfieldExtract(x, 0, 3); + uint row = bitfieldExtract(y, 0, 3); + uint lut = bitfieldExtract(z, 0, 2); + uint idx_dw = lut_8bpp[lut][(col + row * MICRO_TILE_DIM) >> 2u]; + uint byte_ofs = (gl_LocalInvocationID.x & 3u) * 8; + uint idx = bitfieldExtract(idx_dw >> byte_ofs, 0, 8); + + uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ; + uint tile_row = y / MICRO_TILE_DIM; + uint tile_column = x / MICRO_TILE_DIM; + uint tile_offs = ((tile_row * info.c0) + tile_column) * MICRO_TILE_SZ; + uint offs = (slice_offs + tile_offs) + (idx * BPP / 8); + + uint p0 = in_data[offs >> 2u]; + uint byte = bitfieldExtract(p0 >> (offs * 8), 0, 8); + atomicOr(scratch[slot], byte << byte_ofs); + + if (byte_ofs == 0) { + out_data[gl_GlobalInvocationID.x >> 2u] = scratch[slot]; + } +} diff --git a/src/video_core/host_shaders/detile_m32x4.comp b/src/video_core/host_shaders/detilers/micro_128bpp.comp similarity index 98% rename from src/video_core/host_shaders/detile_m32x4.comp rename to src/video_core/host_shaders/detilers/micro_128bpp.comp index e1b988172..a09a0b4c4 100644 --- a/src/video_core/host_shaders/detile_m32x4.comp +++ b/src/video_core/host_shaders/detilers/micro_128bpp.comp @@ -20,7 +20,7 @@ layout(push_constant) uniform image_info { } info; // Inverse morton LUT, small enough to fit into K$ -uint rmort[16] = { +const uint rmort[16] = { 0x11011000, 0x31213020, 0x13031202, 0x33233222, 0x51415040, 0x71617060, diff --git a/src/video_core/host_shaders/detile_m8x2.comp b/src/video_core/host_shaders/detilers/micro_16bpp.comp similarity index 98% rename from src/video_core/host_shaders/detile_m8x2.comp rename to src/video_core/host_shaders/detilers/micro_16bpp.comp index 3f8e5ab33..909a14acc 100644 --- a/src/video_core/host_shaders/detile_m8x2.comp +++ b/src/video_core/host_shaders/detilers/micro_16bpp.comp @@ -25,7 +25,7 @@ layout(push_constant) uniform image_info { #define TEXELS_PER_ELEMENT 2 // Inverse morton LUT, small enough to fit into K$ -uint rmort[16] = { +const uint rmort[16] = { 0x11011000, 0x31213020, 0x13031202, 0x33233222, 0x51415040, 0x71617060, diff --git a/src/video_core/host_shaders/detile_m32x1.comp b/src/video_core/host_shaders/detilers/micro_32bpp.comp similarity index 98% rename from src/video_core/host_shaders/detile_m32x1.comp rename to src/video_core/host_shaders/detilers/micro_32bpp.comp index 802f5f531..cdc8d0018 100644 --- a/src/video_core/host_shaders/detile_m32x1.comp +++ b/src/video_core/host_shaders/detilers/micro_32bpp.comp @@ -20,7 +20,7 @@ layout(push_constant) uniform image_info { } info; // Inverse morton LUT, small enough to fit into K$ -uint rmort[16] = { +const uint rmort[16] = { 0x11011000, 0x31213020, 0x13031202, 0x33233222, 0x51415040, 0x71617060, diff --git a/src/video_core/host_shaders/detile_m32x2.comp b/src/video_core/host_shaders/detilers/micro_64bpp.comp similarity index 98% rename from src/video_core/host_shaders/detile_m32x2.comp rename to src/video_core/host_shaders/detilers/micro_64bpp.comp index 90063a185..c128ba5a1 100644 --- a/src/video_core/host_shaders/detile_m32x2.comp +++ b/src/video_core/host_shaders/detilers/micro_64bpp.comp @@ -20,7 +20,7 @@ layout(push_constant) uniform image_info { } info; // Inverse morton LUT, small enough to fit into K$ -uint rmort[16] = { +const uint rmort[16] = { 0x11011000, 0x31213020, 0x13031202, 0x33233222, 0x51415040, 0x71617060, diff --git a/src/video_core/host_shaders/detile_m8x1.comp b/src/video_core/host_shaders/detilers/micro_8bpp.comp similarity index 99% rename from src/video_core/host_shaders/detile_m8x1.comp rename to src/video_core/host_shaders/detilers/micro_8bpp.comp index 39d0aaeb1..ecf706450 100644 --- a/src/video_core/host_shaders/detile_m8x1.comp +++ b/src/video_core/host_shaders/detilers/micro_8bpp.comp @@ -48,4 +48,4 @@ void main() { uint dw_ofs_x = target_tile_x * 2 + col; // 2 = uints uint dw_ofs_y = (target_tile_y * MICRO_TILE_DIM + row) * tiles_per_pitch * 2; // 2 = uints out_data[dw_ofs_x + dw_ofs_y] = dst_tx; -} \ No newline at end of file +} diff --git a/src/video_core/multi_level_page_table.h b/src/video_core/multi_level_page_table.h index 527476f3b..7f3205e1a 100644 --- a/src/video_core/multi_level_page_table.h +++ b/src/video_core/multi_level_page_table.h @@ -39,6 +39,15 @@ public: return &(*first_level_map[l1_page])[l2_page]; } + [[nodiscard]] const Entry* find(size_t page) const { + const size_t l1_page = page >> SecondLevelBits; + const size_t l2_page = page & (NumEntriesPerL1Page - 1); + if (!first_level_map[l1_page]) { + return nullptr; + } + return &(*first_level_map[l1_page])[l2_page]; + } + [[nodiscard]] const Entry& operator[](size_t page) const { const size_t l1_page = page >> SecondLevelBits; const size_t l2_page = page & (NumEntriesPerL1Page - 1); diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index 556555c25..47ed9e543 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -185,7 +185,7 @@ void PageManager::OnGpuUnmap(VAddr address, size_t size) { void PageManager::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) { static constexpr u64 PageShift = 12; - std::scoped_lock lk{mutex}; + std::scoped_lock lk{lock}; const u64 num_pages = ((addr + size - 1) >> PageShift) - (addr >> PageShift) + 1; const u64 page_start = addr >> PageShift; const u64 page_end = page_start + num_pages; diff --git a/src/video_core/page_manager.h b/src/video_core/page_manager.h index 29a946a8f..f44307f92 100644 --- a/src/video_core/page_manager.h +++ b/src/video_core/page_manager.h @@ -4,8 +4,8 @@ #pragma once #include -#include #include +#include "common/spin_lock.h" #include "common/types.h" namespace Vulkan { @@ -35,8 +35,8 @@ private: struct Impl; std::unique_ptr impl; Vulkan::Rasterizer* rasterizer; - std::mutex mutex; boost::icl::interval_map cached_pages; + Common::SpinLock lock; }; } // namespace VideoCore diff --git a/src/video_core/renderdoc.cpp b/src/video_core/renderdoc.cpp index 7e0994992..b082fd1ca 100644 --- a/src/video_core/renderdoc.cpp +++ b/src/video_core/renderdoc.cpp @@ -65,11 +65,18 @@ void LoadRenderDoc() { #else static constexpr const char RENDERDOC_LIB[] = "librenderdoc.so"; #endif - if (void* mod = dlopen(RENDERDOC_LIB, RTLD_NOW | RTLD_NOLOAD)) { - const auto RENDERDOC_GetAPI = - reinterpret_cast(dlsym(mod, "RENDERDOC_GetAPI")); - const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api); - ASSERT(ret == 1); + // Check if we are running by RDoc GUI + void* mod = dlopen(RENDERDOC_LIB, RTLD_NOW | RTLD_NOLOAD); + if (!mod && Config::isRdocEnabled()) { + // If enabled in config, try to load RDoc runtime in offline mode + if ((mod = dlopen(RENDERDOC_LIB, RTLD_NOW))) { + const auto RENDERDOC_GetAPI = + reinterpret_cast(dlsym(mod, "RENDERDOC_GetAPI")); + const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api); + ASSERT(ret == 1); + } else { + LOG_ERROR(Render, "Cannot load RenderDoc: {}", dlerror()); + } } #endif if (rdoc_api) { diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 25ff88b9d..9695e127f 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -103,6 +103,7 @@ vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type) { case AmdGpu::PrimitiveType::TriangleList: return vk::PrimitiveTopology::eTriangleList; case AmdGpu::PrimitiveType::TriangleFan: + case AmdGpu::PrimitiveType::Polygon: return vk::PrimitiveTopology::eTriangleFan; case AmdGpu::PrimitiveType::TriangleStrip: return vk::PrimitiveTopology::eTriangleStrip; @@ -116,9 +117,6 @@ vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type) { return vk::PrimitiveTopology::eTriangleStripWithAdjacency; case AmdGpu::PrimitiveType::PatchPrimitive: return vk::PrimitiveTopology::ePatchList; - case AmdGpu::PrimitiveType::Polygon: - // Needs to generate index buffer on the fly. - return vk::PrimitiveTopology::eTriangleList; case AmdGpu::PrimitiveType::QuadList: case AmdGpu::PrimitiveType::RectList: return vk::PrimitiveTopology::ePatchList; @@ -326,6 +324,34 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) { } } +vk::ComponentSwizzle ComponentSwizzle(AmdGpu::CompSwizzle comp_swizzle) { + switch (comp_swizzle) { + case AmdGpu::CompSwizzle::Zero: + return vk::ComponentSwizzle::eZero; + case AmdGpu::CompSwizzle::One: + return vk::ComponentSwizzle::eOne; + case AmdGpu::CompSwizzle::Red: + return vk::ComponentSwizzle::eR; + case AmdGpu::CompSwizzle::Green: + return vk::ComponentSwizzle::eG; + case AmdGpu::CompSwizzle::Blue: + return vk::ComponentSwizzle::eB; + case AmdGpu::CompSwizzle::Alpha: + return vk::ComponentSwizzle::eA; + default: + UNREACHABLE(); + } +} + +vk::ComponentMapping ComponentMapping(AmdGpu::CompMapping comp_mapping) { + return vk::ComponentMapping{ + .r = ComponentSwizzle(comp_mapping.r), + .g = ComponentSwizzle(comp_mapping.g), + .b = ComponentSwizzle(comp_mapping.b), + .a = ComponentSwizzle(comp_mapping.a), + }; +} + static constexpr vk::FormatFeatureFlags2 BufferRead = vk::FormatFeatureFlagBits2::eUniformTexelBuffer | vk::FormatFeatureFlagBits2::eVertexBuffer; static constexpr vk::FormatFeatureFlags2 BufferWrite = @@ -421,7 +447,7 @@ static constexpr vk::FormatFeatureFlags2 GetNumberFormatFeatureFlags( case AmdGpu::NumberFormat::Srgb: return ImageRead | Mrt; case AmdGpu::NumberFormat::Ubnorm: - case AmdGpu::NumberFormat::UbnromNz: + case AmdGpu::NumberFormat::UbnormNz: case AmdGpu::NumberFormat::Ubint: case AmdGpu::NumberFormat::Ubscaled: return ImageRead; @@ -442,6 +468,7 @@ static constexpr SurfaceFormatInfo CreateSurfaceFormatInfo(const AmdGpu::DataFor } std::span SurfaceFormats() { + // Uscaled, Sscaled, and Ubnorm formats are automatically remapped and handled in shader. static constexpr std::array formats{ // Invalid CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Unorm, @@ -464,7 +491,7 @@ std::span SurfaceFormats() { vk::Format::eUndefined), CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubnorm, vk::Format::eUndefined), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::UbnromNz, + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::UbnormNz, vk::Format::eUndefined), CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubint, vk::Format::eUndefined), @@ -475,10 +502,6 @@ std::span SurfaceFormats() { vk::Format::eR8Unorm), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Snorm, vk::Format::eR8Snorm), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Uscaled, - vk::Format::eR8Uscaled), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Sscaled, - vk::Format::eR8Sscaled), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Uint, vk::Format::eR8Uint), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Sint, @@ -490,10 +513,6 @@ std::span SurfaceFormats() { vk::Format::eR16Unorm), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Snorm, vk::Format::eR16Snorm), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Uscaled, - vk::Format::eR16Uscaled), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Sscaled, - vk::Format::eR16Sscaled), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Uint, vk::Format::eR16Uint), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Sint, @@ -505,10 +524,6 @@ std::span SurfaceFormats() { vk::Format::eR8G8Unorm), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Snorm, vk::Format::eR8G8Snorm), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Uscaled, - vk::Format::eR8G8Uscaled), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Sscaled, - vk::Format::eR8G8Sscaled), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Uint, vk::Format::eR8G8Uint), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Sint, @@ -527,10 +542,6 @@ std::span SurfaceFormats() { vk::Format::eR16G16Unorm), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Snorm, vk::Format::eR16G16Snorm), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Uscaled, - vk::Format::eR16G16Uscaled), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Sscaled, - vk::Format::eR16G16Sscaled), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Uint, vk::Format::eR16G16Uint), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Sint, @@ -540,19 +551,13 @@ std::span SurfaceFormats() { // 10_11_11 CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format10_11_11, AmdGpu::NumberFormat::Float, vk::Format::eB10G11R11UfloatPack32), - // 11_11_10 - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format11_11_10, AmdGpu::NumberFormat::Float, - vk::Format::eB10G11R11UfloatPack32), - // 10_10_10_2 + // 11_11_10 - Remapped to 10_11_11. + // 10_10_10_2 - Remapped to 2_10_10_10. // 2_10_10_10 CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Unorm, vk::Format::eA2B10G10R10UnormPack32), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Snorm, vk::Format::eA2B10G10R10SnormPack32), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Uscaled, - vk::Format::eA2B10G10R10UscaledPack32), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Sscaled, - vk::Format::eA2B10G10R10SscaledPack32), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Uint, vk::Format::eA2B10G10R10UintPack32), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Sint, @@ -562,10 +567,6 @@ std::span SurfaceFormats() { vk::Format::eR8G8B8A8Unorm), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Snorm, vk::Format::eR8G8B8A8Snorm), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Uscaled, - vk::Format::eR8G8B8A8Uscaled), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Sscaled, - vk::Format::eR8G8B8A8Sscaled), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Uint, vk::Format::eR8G8B8A8Uint), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Sint, @@ -584,10 +585,6 @@ std::span SurfaceFormats() { vk::Format::eR16G16B16A16Unorm), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Snorm, vk::Format::eR16G16B16A16Snorm), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, - AmdGpu::NumberFormat::Uscaled, vk::Format::eR16G16B16A16Uscaled), - CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, - AmdGpu::NumberFormat::Sscaled, vk::Format::eR16G16B16A16Sscaled), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Uint, vk::Format::eR16G16B16A16Uint), CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Sint, @@ -616,7 +613,7 @@ std::span SurfaceFormats() { // 1_5_5_5 CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm, vk::Format::eR5G5B5A1UnormPack16), - // 5_5_5_1 + // 5_5_5_1 - Remapped to 1_5_5_5. // 4_4_4_4 CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format4_4_4_4, AmdGpu::NumberFormat::Unorm, vk::Format::eR4G4B4A4UnormPack16), @@ -667,41 +664,40 @@ std::span SurfaceFormats() { return formats; } -vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { - const auto& formats = SurfaceFormats(); - const auto format = - std::find_if(formats.begin(), formats.end(), [&](const SurfaceFormatInfo& format_info) { - return format_info.data_format == data_format && - format_info.number_format == num_format; - }); - ASSERT_MSG(format != formats.end(), "Unknown data_format={} and num_format={}", - static_cast(data_format), static_cast(num_format)); - return format->vk_format; +// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] +static const size_t amd_gpu_data_format_bit_size = 6; // All values are under 64 +static const size_t amd_gpu_number_format_bit_size = 4; // All values are under 16 + +static size_t GetSurfaceFormatTableIndex(AmdGpu::DataFormat data_format, + AmdGpu::NumberFormat num_format) { + DEBUG_ASSERT(u32(data_format) < 1 << amd_gpu_data_format_bit_size); + DEBUG_ASSERT(u32(num_format) < 1 << amd_gpu_number_format_bit_size); + size_t result = static_cast(num_format) | + (static_cast(data_format) << amd_gpu_number_format_bit_size); + return result; } -vk::Format AdjustColorBufferFormat(vk::Format base_format, - Liverpool::ColorBuffer::SwapMode comp_swap) { - const bool comp_swap_alt = comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate; - const bool comp_swap_reverse = comp_swap == Liverpool::ColorBuffer::SwapMode::StandardReverse; - const bool comp_swap_alt_reverse = - comp_swap == Liverpool::ColorBuffer::SwapMode::AlternateReverse; - if (comp_swap_alt) { - switch (base_format) { - case vk::Format::eR8G8B8A8Unorm: - return vk::Format::eB8G8R8A8Unorm; - case vk::Format::eB8G8R8A8Unorm: - return vk::Format::eR8G8B8A8Unorm; - case vk::Format::eR8G8B8A8Srgb: - return vk::Format::eB8G8R8A8Srgb; - case vk::Format::eB8G8R8A8Srgb: - return vk::Format::eR8G8B8A8Srgb; - case vk::Format::eA2B10G10R10UnormPack32: - return vk::Format::eA2R10G10B10UnormPack32; - default: - break; - } +static auto surface_format_table = []() constexpr { + std::array + result; + for (auto& entry : result) { + entry = vk::Format::eUndefined; } - return base_format; + for (const auto& supported_format : SurfaceFormats()) { + result[GetSurfaceFormatTableIndex(supported_format.data_format, + supported_format.number_format)] = + supported_format.vk_format; + } + return result; +}(); + +vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { + vk::Format result = surface_format_table[GetSurfaceFormatTableIndex(data_format, num_format)]; + bool found = + result != vk::Format::eUndefined || data_format == AmdGpu::DataFormat::FormatInvalid; + ASSERT_MSG(found, "Unknown data_format={} and num_format={}", static_cast(data_format), + static_cast(num_format)); + return result; } static constexpr DepthFormatInfo CreateDepthFormatInfo( @@ -746,21 +742,12 @@ vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat } vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) { - const auto comp_swap = color_buffer.info.comp_swap.Value(); - const auto format = color_buffer.info.format.Value(); - const auto number_type = color_buffer.info.number_type.Value(); + const auto comp_swizzle = color_buffer.Swizzle(); + const auto format = color_buffer.GetDataFmt(); + const auto number_type = color_buffer.GetNumberFmt(); const auto& c0 = color_buffer.clear_word0; const auto& c1 = color_buffer.clear_word1; - const auto num_bits = AmdGpu::NumBits(color_buffer.info.format); - const auto num_components = AmdGpu::NumComponents(format); - - const bool comp_swap_alt = - comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::Alternate || - comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::AlternateReverse; - const bool comp_swap_reverse = - comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::StandardReverse || - comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::AlternateReverse; vk::ClearColorValue color{}; @@ -1081,26 +1068,7 @@ vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color break; } - if (num_components == 1) { - if (comp_swap != Liverpool::ColorBuffer::SwapMode::Standard) { - color.float32[static_cast(comp_swap)] = color.float32[0]; - color.float32[0] = 0.0f; - } - } else { - if (comp_swap_alt && num_components == 4) { - std::swap(color.float32[0], color.float32[2]); - } - - if (comp_swap_reverse) { - std::reverse(std::begin(color.float32), std::begin(color.float32) + num_components); - } - - if (comp_swap_alt && num_components != 4) { - color.float32[3] = color.float32[num_components - 1]; - color.float32[num_components - 1] = 0.0f; - } - } - + color.float32 = comp_swizzle.Apply(color.float32); return {.color = color}; } diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index d5f8e693b..a68280e7d 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -42,6 +42,10 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter); vk::BorderColor BorderColor(AmdGpu::BorderColor color); +vk::ComponentSwizzle ComponentSwizzle(AmdGpu::CompSwizzle comp_swizzle); + +vk::ComponentMapping ComponentMapping(AmdGpu::CompMapping comp_mapping); + struct SurfaceFormatInfo { AmdGpu::DataFormat data_format; AmdGpu::NumberFormat number_format; @@ -52,9 +56,6 @@ std::span SurfaceFormats(); vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format); -vk::Format AdjustColorBufferFormat(vk::Format base_format, - Liverpool::ColorBuffer::SwapMode comp_swap); - struct DepthFormatInfo { Liverpool::DepthBuffer::ZFormat z_format; Liverpool::DepthBuffer::StencilFormat stencil_format; @@ -70,15 +71,6 @@ vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags); -inline void EmitPolygonToTriangleListIndices(u8* out_ptr, u32 num_vertices) { - u16* out_data = reinterpret_cast(out_ptr); - for (u16 i = 1; i < num_vertices - 1; i++) { - *out_data++ = 0; - *out_data++ = i; - *out_data++ = i + 1; - } -} - static inline vk::Format PromoteFormatToDepth(vk::Format fmt) { if (fmt == vk::Format::eR32Sfloat) { return vk::Format::eD32Sfloat; diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 71659c06c..23faacfc2 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -18,6 +18,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler : Pipeline{instance_, scheduler_, desc_heap_, pipeline_cache, true}, compute_key{compute_key_} { auto& info = stages[int(Shader::LogicalStage::Compute)]; info = &info_; + const auto debug_str = GetDebugString(); const vk::PipelineShaderStageCreateInfo shader_ci = { .stage = vk::ShaderStageFlagBits::eCompute, @@ -58,9 +59,8 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler for (const auto& image : info->images) { bindings.push_back({ .binding = binding++, - .descriptorType = image.IsStorage(image.GetSharp(*info)) - ? vk::DescriptorType::eStorageImage - : vk::DescriptorType::eSampledImage, + .descriptorType = image.is_written ? vk::DescriptorType::eStorageImage + : vk::DescriptorType::eSampledImage, .descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute, }); @@ -89,8 +89,9 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler .bindingCount = static_cast(bindings.size()), .pBindings = bindings.data(), }; + const auto device = instance.GetDevice(); auto [descriptor_set_result, descriptor_set] = - instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci); + device.createDescriptorSetLayoutUnique(desc_layout_ci); ASSERT_MSG(descriptor_set_result == vk::Result::eSuccess, "Failed to create compute descriptor set layout: {}", vk::to_string(descriptor_set_result)); @@ -107,6 +108,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler ASSERT_MSG(layout_result == vk::Result::eSuccess, "Failed to create compute pipeline layout: {}", vk::to_string(layout_result)); pipeline_layout = std::move(layout); + SetObjectName(device, *pipeline_layout, "Compute PipelineLayout {}", debug_str); const vk::ComputePipelineCreateInfo compute_pipeline_ci = { .stage = shader_ci, @@ -117,6 +119,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler ASSERT_MSG(pipeline_result == vk::Result::eSuccess, "Failed to create compute pipeline: {}", vk::to_string(pipeline_result)); pipeline = std::move(pipe); + SetObjectName(device, *pipeline, "Compute Pipeline {}", debug_str); } ComputePipeline::~ComputePipeline() = default; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index ffa474a1c..4ca3a7f27 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -8,7 +8,6 @@ #include "common/assert.h" #include "common/io_file.h" -#include "common/scope_exit.h" #include "shader_recompiler/backend/spirv/emit_spirv_quad_rect.h" #include "shader_recompiler/frontend/fetch_shader.h" #include "shader_recompiler/runtime_info.h" @@ -16,6 +15,7 @@ #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" #include "video_core/renderer_vulkan/vk_instance.h" +#include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/texture_cache/texture_cache.h" @@ -36,6 +36,7 @@ GraphicsPipeline::GraphicsPipeline( const vk::Device device = instance.GetDevice(); std::ranges::copy(infos, stages.begin()); BuildDescSetLayout(); + const auto debug_str = GetDebugString(); const vk::PushConstantRange push_constants = { .stageFlags = gp_stage_flags, @@ -54,36 +55,13 @@ GraphicsPipeline::GraphicsPipeline( ASSERT_MSG(layout_result == vk::Result::eSuccess, "Failed to create graphics pipeline layout: {}", vk::to_string(layout_result)); pipeline_layout = std::move(layout); + SetObjectName(device, *pipeline_layout, "Graphics PipelineLayout {}", debug_str); - boost::container::static_vector vertex_bindings; - boost::container::static_vector vertex_attributes; - if (fetch_shader && !instance.IsVertexInputDynamicState()) { - const auto& vs_info = GetStage(Shader::LogicalStage::Vertex); - for (const auto& attrib : fetch_shader->attributes) { - if (attrib.UsesStepRates()) { - // Skip attribute binding as the data will be pulled by shader - continue; - } - - const auto buffer = attrib.GetSharp(vs_info); - if (buffer.GetSize() == 0) { - continue; - } - vertex_attributes.push_back({ - .location = attrib.semantic, - .binding = attrib.semantic, - .format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()), - .offset = 0, - }); - vertex_bindings.push_back({ - .binding = attrib.semantic, - .stride = buffer.GetStride(), - .inputRate = - attrib.GetStepRate() == Shader::Gcn::VertexAttribute::InstanceIdType::None - ? vk::VertexInputRate::eVertex - : vk::VertexInputRate::eInstance, - }); - } + VertexInputs vertex_attributes; + VertexInputs vertex_bindings; + VertexInputs guest_buffers; + if (!instance.IsVertexInputDynamicState()) { + GetVertexInputs(vertex_attributes, vertex_bindings, guest_buffers); } const vk::PipelineVertexInputStateCreateInfo vertex_input_info = { @@ -159,7 +137,7 @@ GraphicsPipeline::GraphicsPipeline( } if (instance.IsVertexInputDynamicState()) { dynamic_states.push_back(vk::DynamicState::eVertexInputEXT); - } else { + } else if (!vertex_bindings.empty()) { dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT); } @@ -322,10 +300,56 @@ GraphicsPipeline::GraphicsPipeline( ASSERT_MSG(pipeline_result == vk::Result::eSuccess, "Failed to create graphics pipeline: {}", vk::to_string(pipeline_result)); pipeline = std::move(pipe); + SetObjectName(device, *pipeline, "Graphics Pipeline {}", debug_str); } GraphicsPipeline::~GraphicsPipeline() = default; +template +void GraphicsPipeline::GetVertexInputs(VertexInputs& attributes, + VertexInputs& bindings, + VertexInputs& guest_buffers) const { + if (!fetch_shader || fetch_shader->attributes.empty()) { + return; + } + const auto& vs_info = GetStage(Shader::LogicalStage::Vertex); + for (const auto& attrib : fetch_shader->attributes) { + if (attrib.UsesStepRates()) { + // Skip attribute binding as the data will be pulled by shader. + continue; + } + + const auto& buffer = attrib.GetSharp(vs_info); + attributes.push_back(Attribute{ + .location = attrib.semantic, + .binding = attrib.semantic, + .format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()), + .offset = 0, + }); + bindings.push_back(Binding{ + .binding = attrib.semantic, + .stride = buffer.GetStride(), + .inputRate = attrib.GetStepRate() == Shader::Gcn::VertexAttribute::InstanceIdType::None + ? vk::VertexInputRate::eVertex + : vk::VertexInputRate::eInstance, + }); + if constexpr (std::is_same_v) { + bindings.back().divisor = 1; + } + guest_buffers.emplace_back(buffer); + } +} + +// Declare templated GetVertexInputs for necessary types. +template void GraphicsPipeline::GetVertexInputs( + VertexInputs& attributes, + VertexInputs& bindings, + VertexInputs& guest_buffers) const; +template void GraphicsPipeline::GetVertexInputs( + VertexInputs& attributes, + VertexInputs& bindings, + VertexInputs& guest_buffers) const; + void GraphicsPipeline::BuildDescSetLayout() { boost::container::small_vector bindings; u32 binding{}; @@ -364,9 +388,8 @@ void GraphicsPipeline::BuildDescSetLayout() { for (const auto& image : stage->images) { bindings.push_back({ .binding = binding++, - .descriptorType = image.IsStorage(image.GetSharp(*stage)) - ? vk::DescriptorType::eStorageImage - : vk::DescriptorType::eSampledImage, + .descriptorType = image.is_written ? vk::DescriptorType::eStorageImage + : vk::DescriptorType::eSampledImage, .descriptorCount = 1, .stageFlags = gp_stage_flags, }); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index ee8afa3e6..f696c1f72 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include "common/types.h" @@ -27,12 +28,16 @@ class DescriptorHeap; using Liverpool = AmdGpu::Liverpool; +template +using VertexInputs = boost::container::static_vector; + struct GraphicsPipelineKey { std::array stage_hashes; u32 num_color_attachments; std::array color_formats; std::array color_num_formats; - std::array mrt_swizzles; + std::array color_num_conversions; + std::array color_swizzles; vk::Format depth_format; vk::Format stencil_format; @@ -99,6 +104,11 @@ public: key.prim_type == AmdGpu::PrimitiveType::QuadList; } + /// Gets the attributes and bindings for vertex inputs. + template + void GetVertexInputs(VertexInputs& attributes, VertexInputs& bindings, + VertexInputs& guest_buffers) const; + private: void BuildDescSetLayout(); diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 790e76400..6c3e066c6 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -92,13 +92,15 @@ std::string GetReadableVersion(u32 version) { Instance::Instance(bool enable_validation, bool enable_crash_diagnostic) : instance{CreateInstance(Frontend::WindowSystemType::Headless, enable_validation, enable_crash_diagnostic)}, - physical_devices{EnumeratePhysicalDevices(instance)} {} + physical_devices{EnumeratePhysicalDevices(instance)}, + crash_diagnostic{enable_crash_diagnostic} {} Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index, bool enable_validation /*= false*/, bool enable_crash_diagnostic /*= false*/) : instance{CreateInstance(window.GetWindowInfo().type, enable_validation, enable_crash_diagnostic)}, - physical_devices{EnumeratePhysicalDevices(instance)} { + physical_devices{EnumeratePhysicalDevices(instance)}, + crash_diagnostic{enable_crash_diagnostic} { if (enable_validation) { debug_callback = CreateDebugCallback(*instance); } @@ -269,6 +271,7 @@ bool Instance::CreateDevice() { maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME); image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME); + amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME); // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 // with extensions. diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 54a9b9873..8928b4267 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -81,7 +81,7 @@ public: /// Returns true when a known debugging tool is attached. bool HasDebuggingToolAttached() const { - return has_renderdoc || has_nsight_graphics; + return crash_diagnostic || has_renderdoc || has_nsight_graphics; } /// Returns true if anisotropic filtering is supported @@ -159,6 +159,11 @@ public: return image_load_store_lod; } + /// Returns true when VK_AMD_gcn_shader is supported. + bool IsAmdGcnShaderSupported() const { + return amd_gcn_shader; + } + /// Returns true when geometry shaders are supported by the device bool IsGeometryStageSupported() const { return features.geometryShader; @@ -249,6 +254,11 @@ public: return properties.limits.maxSamplerLodBias; } + /// Returns the maximum sampler anisotropy. + float MaxSamplerAnisotropy() const { + return properties.limits.maxSamplerAnisotropy; + } + /// Returns the maximum number of push descriptors. u32 MaxPushDescriptors() const { return push_descriptor_props.maxPushDescriptors; @@ -329,10 +339,12 @@ private: bool list_restart{}; bool legacy_vertex_attributes{}; bool image_load_store_lod{}; + bool amd_gcn_shader{}; u64 min_imported_host_pointer_alignment{}; u32 subgroup_size{}; bool tooling_info{}; bool debug_utils_supported{}; + bool crash_diagnostic{}; bool has_nsight_graphics{}; bool has_renderdoc{}; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 74ae6b61c..f93494389 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -168,7 +168,8 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS for (u32 i = 0; i < Shader::MaxColorBuffers; i++) { info.fs_info.color_buffers[i] = { .num_format = graphics_key.color_num_formats[i], - .mrt_swizzle = static_cast(graphics_key.mrt_swizzles[i]), + .num_conversion = graphics_key.color_num_conversions[i], + .swizzle = graphics_key.color_swizzles[i], }; } break; @@ -203,6 +204,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, .support_explicit_workgroup_layout = true, .support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(), .supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(), + .supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(), .needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() && instance.GetDriverID() == vk::DriverId::eNvidiaProprietary, .needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary || @@ -302,9 +304,10 @@ bool PipelineCache::RefreshGraphicsKey() { key.num_color_attachments = 0; key.color_formats.fill(vk::Format::eUndefined); key.color_num_formats.fill(AmdGpu::NumberFormat::Unorm); + key.color_num_conversions.fill(AmdGpu::NumberConversion::None); key.blend_controls.fill({}); key.write_masks.fill({}); - key.mrt_swizzles.fill(Liverpool::ColorBuffer::SwapMode::Standard); + key.color_swizzles.fill({}); key.vertex_buffer_formats.fill(vk::Format::eUndefined); key.patch_control_points = 0; @@ -327,14 +330,11 @@ bool PipelineCache::RefreshGraphicsKey() { continue; } - const auto base_format = - LiverpoolToVK::SurfaceFormat(col_buf.info.format, col_buf.NumFormat()); key.color_formats[remapped_cb] = - LiverpoolToVK::AdjustColorBufferFormat(base_format, col_buf.info.comp_swap.Value()); - key.color_num_formats[remapped_cb] = col_buf.NumFormat(); - if (base_format == key.color_formats[remapped_cb]) { - key.mrt_swizzles[remapped_cb] = col_buf.info.comp_swap.Value(); - } + LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt()); + key.color_num_formats[remapped_cb] = col_buf.GetNumberFmt(); + key.color_num_conversions[remapped_cb] = col_buf.GetNumberConversion(); + key.color_swizzles[remapped_cb] = col_buf.Swizzle(); } fetch_shader = std::nullopt; @@ -420,17 +420,17 @@ bool PipelineCache::RefreshGraphicsKey() { } } - const auto vs_info = infos[static_cast(Shader::LogicalStage::Vertex)]; + const auto* vs_info = infos[static_cast(Shader::LogicalStage::Vertex)]; if (vs_info && fetch_shader && !instance.IsVertexInputDynamicState()) { + // Without vertex input dynamic state, the pipeline needs to specialize on format. + // Stride will still be handled outside the pipeline using dynamic state. u32 vertex_binding = 0; for (const auto& attrib : fetch_shader->attributes) { if (attrib.UsesStepRates()) { + // Skip attribute binding as the data will be pulled by shader. continue; } const auto& buffer = attrib.GetSharp(*vs_info); - if (buffer.GetSize() == 0) { - continue; - } ASSERT(vertex_binding < MaxVertexBufferCount); key.vertex_buffer_formats[vertex_binding++] = Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()); @@ -450,7 +450,7 @@ bool PipelineCache::RefreshGraphicsKey() { // of the latter we need to change format to undefined, and either way we need to // increment the index for the null attachment binding. key.color_formats[remapped_cb] = vk::Format::eUndefined; - key.mrt_swizzles[remapped_cb] = Liverpool::ColorBuffer::SwapMode::Standard; + key.color_swizzles[remapped_cb] = {}; ++remapped_cb; continue; } @@ -497,7 +497,7 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim module = CompileSPV(spv, instance.GetDevice()); } - const auto name = fmt::format("{}_{:#018x}_{}", info.stage, info.pgm_hash, perm_idx); + const auto name = GetShaderName(info.stage, info.pgm_hash, perm_idx); Vulkan::SetObjectName(instance.GetDevice(), module, name); if (Config::collectShadersForDebug()) { DebugState.CollectShader(name, info.l_stage, module, spv, code, @@ -572,6 +572,14 @@ std::optional PipelineCache::ReplaceShader(vk::ShaderModule mo return new_module; } +std::string PipelineCache::GetShaderName(Shader::Stage stage, u64 hash, + std::optional perm) { + if (perm) { + return fmt::format("{}_{:#018x}_{}", stage, hash, *perm); + } + return fmt::format("{}_{:#018x}", stage, hash); +} + void PipelineCache::DumpShader(std::span code, u64 hash, Shader::Stage stage, size_t perm_idx, std::string_view ext) { if (!Config::dumpShaders()) { @@ -583,7 +591,7 @@ void PipelineCache::DumpShader(std::span code, u64 hash, Shader::Stag 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 filename = fmt::format("{}.{}", GetShaderName(stage, hash, perm_idx), ext); const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; file.WriteSpan(code); } @@ -597,7 +605,7 @@ std::optional> PipelineCache::GetShaderPatch(u64 hash, Shader:: if (!std::filesystem::exists(patch_dir)) { std::filesystem::create_directories(patch_dir); } - const auto filename = fmt::format("{}_{:#018x}_{}.{}", stage, hash, perm_idx, ext); + const auto filename = fmt::format("{}.{}", GetShaderName(stage, hash, perm_idx), ext); const auto filepath = patch_dir / filename; if (!std::filesystem::exists(filepath)) { return {}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index d4a51efdb..b3bccd513 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -65,6 +65,9 @@ public: std::optional ReplaceShader(vk::ShaderModule module, std::span spv_code); + static std::string GetShaderName(Shader::Stage stage, u64 hash, + std::optional perm = {}); + private: bool RefreshGraphicsKey(); bool RefreshComputeKey(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_common.cpp b/src/video_core/renderer_vulkan/vk_pipeline_common.cpp index 6b48a40a0..91f53109e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_common.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_common.cpp @@ -6,6 +6,7 @@ #include "shader_recompiler/info.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/vk_instance.h" +#include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_pipeline_common.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/texture_cache/texture_cache.h" @@ -55,4 +56,19 @@ void Pipeline::BindResources(DescriptorWrites& set_writes, const BufferBarriers& cmdbuf.bindDescriptorSets(bind_point, *pipeline_layout, 0, desc_set, {}); } +std::string Pipeline::GetDebugString() const { + std::string stage_desc; + for (const auto& stage : stages) { + if (stage) { + const auto shader_name = PipelineCache::GetShaderName(stage->stage, stage->pgm_hash); + if (stage_desc.empty()) { + stage_desc = shader_name; + } else { + stage_desc = fmt::format("{},{}", stage_desc, shader_name); + } + } + } + return stage_desc; +} + } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_common.h b/src/video_core/renderer_vulkan/vk_pipeline_common.h index 1b13a1797..f71631da0 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_common.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_common.h @@ -61,6 +61,8 @@ public: const Shader::PushData& push_data) const; protected: + [[nodiscard]] std::string GetDebugString() const; + const Instance& instance; Scheduler& scheduler; DescriptorHeap& desc_heap; diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index dbdabe0d9..7f0bcb5d2 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -137,6 +137,7 @@ std::vector GetInstanceExtensions(Frontend::WindowSystemType window // Add the windowing system specific extension std::vector extensions; extensions.reserve(7); + extensions.push_back(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME); switch (window_type) { case Frontend::WindowSystemType::Headless: @@ -282,6 +283,9 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e Common::FS::GetUserPathString(Common::FS::PathType::LogDir); const char* log_path = crash_diagnostic_path.c_str(); vk::Bool32 enable_force_barriers = vk::True; +#ifdef __APPLE__ + const vk::Bool32 mvk_debug_mode = enable_crash_diagnostic ? vk::True : vk::False; +#endif const std::array layer_setings = { vk::LayerSettingEXT{ @@ -347,6 +351,17 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e .valueCount = 1, .pValues = &enable_force_barriers, }, +#ifdef __APPLE__ + // MoltenVK debug mode turns on additional device loss error details, so + // use the crash diagnostic setting as an indicator of whether to turn it on. + vk::LayerSettingEXT{ + .pLayerName = "MoltenVK", + .pSettingName = "MVK_CONFIG_DEBUG", + .type = vk::LayerSettingTypeEXT::eBool32, + .valueCount = 1, + .pValues = &mvk_debug_mode, + } +#endif }; vk::StructureChain instance_ci_chain = { diff --git a/src/video_core/renderer_vulkan/vk_presenter.cpp b/src/video_core/renderer_vulkan/vk_presenter.cpp index bc55cde23..1679aa691 100644 --- a/src/video_core/renderer_vulkan/vk_presenter.cpp +++ b/src/video_core/renderer_vulkan/vk_presenter.cpp @@ -427,7 +427,7 @@ bool Presenter::ShowSplash(Frame* frame /*= nullptr*/) { VideoCore::Extent3D{splash->GetImageInfo().width, splash->GetImageInfo().height, 1}; info.pitch = splash->GetImageInfo().width; info.guest_address = VAddr(splash->GetImageData().data()); - info.guest_size_bytes = splash->GetImageData().size(); + info.guest_size = splash->GetImageData().size(); info.mips_layout.emplace_back(splash->GetImageData().size(), splash->GetImageInfo().width, splash->GetImageInfo().height, 0); @@ -628,6 +628,13 @@ Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop) } void Presenter::Present(Frame* frame) { + // Free the frame for reuse + const auto free_frame = [&] { + std::scoped_lock fl{free_mutex}; + free_queue.push(frame); + free_cv.notify_one(); + }; + // Recreate the swapchain if the window was resized. if (window.GetWidth() != swapchain.GetExtent().width || window.GetHeight() != swapchain.GetExtent().height) { @@ -636,8 +643,19 @@ void Presenter::Present(Frame* frame) { if (!swapchain.AcquireNextImage()) { swapchain.Recreate(window.GetWidth(), window.GetHeight()); + if (!swapchain.AcquireNextImage()) { + // User resizes the window too fast and GPU can't keep up. Skip this frame. + LOG_WARNING(Render_Vulkan, "Skipping frame!"); + free_frame(); + return; + } } + // Reset fence for queue submission. Do it here instead of GetRenderFrame() because we may + // skip frame because of slow swapchain recreation. If a frame skip occurs, we skip signal + // the frame's present fence and future GetRenderFrame() call will hang waiting for this frame. + instance.GetDevice().resetFences(frame->present_done); + ImGui::Core::NewFrame(); const vk::Image swapchain_image = swapchain.Image(); @@ -737,11 +755,7 @@ void Presenter::Present(Frame* frame) { swapchain.Recreate(window.GetWidth(), window.GetHeight()); } - // Free the frame for reuse - std::scoped_lock fl{free_mutex}; - free_queue.push(frame); - free_cv.notify_one(); - + free_frame(); DebugState.IncFlipFrameNum(); } @@ -776,9 +790,6 @@ Frame* Presenter::GetRenderFrame() { } } - // Reset fence for next queue submission. - device.resetFences(frame->present_done); - // 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_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index d458fa124..920e09131 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -12,7 +12,6 @@ #include "video_core/renderer_vulkan/vk_shader_hle.h" #include "video_core/texture_cache/image_view.h" #include "video_core/texture_cache/texture_cache.h" -#include "vk_rasterizer.h" #ifdef MemoryBarrier #undef MemoryBarrier @@ -249,24 +248,27 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { return; } - const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex); - const auto& fetch_shader = pipeline->GetFetchShader(); - buffer_cache.BindVertexBuffers(vs_info, fetch_shader); - const u32 num_indices = buffer_cache.BindIndexBuffer(is_indexed, index_offset); + buffer_cache.BindVertexBuffers(*pipeline); + if (is_indexed) { + buffer_cache.BindIndexBuffer(index_offset); + } BeginRendering(*pipeline, state); UpdateDynamicState(*pipeline); + const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex); + const auto& fetch_shader = pipeline->GetFetchShader(); const auto [vertex_offset, instance_offset] = GetDrawOffsets(regs, vs_info, fetch_shader); const auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->Handle()); if (is_indexed) { - cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, s32(vertex_offset), - instance_offset); + cmdbuf.drawIndexed(regs.num_indices, regs.num_instances.NumInstances(), 0, + s32(vertex_offset), instance_offset); } else { - cmdbuf.draw(num_indices, regs.num_instances.NumInstances(), vertex_offset, instance_offset); + cmdbuf.draw(regs.num_indices, regs.num_instances.NumInstances(), vertex_offset, + instance_offset); } ResetBindings(); @@ -280,30 +282,20 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3 return; } - const auto& regs = liverpool->regs; - if (regs.primitive_type == AmdGpu::PrimitiveType::Polygon) { - // We use a generated index buffer to convert polygons to triangles. Since it - // changes type of the draw, arguments are not valid for this case. We need to run a - // conversion pass to repack the indirect arguments buffer first. - LOG_WARNING(Render_Vulkan, "Primitive type is not supported for indirect draw"); - return; - } - const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline(); if (!pipeline) { return; } auto state = PrepareRenderState(pipeline->GetMrtMask()); - if (!BindResources(pipeline)) { return; } - const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex); - const auto& fetch_shader = pipeline->GetFetchShader(); - buffer_cache.BindVertexBuffers(vs_info, fetch_shader); - buffer_cache.BindIndexBuffer(is_indexed, 0); + buffer_cache.BindVertexBuffers(*pipeline); + if (is_indexed) { + buffer_cache.BindIndexBuffer(0); + } const auto& [buffer, base] = buffer_cache.ObtainBuffer(arg_address + offset, stride * max_count, false); @@ -543,6 +535,7 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding } // Second pass to re-bind buffers that were updated after binding + auto& null_buffer = buffer_cache.GetBuffer(VideoCore::NULL_BUFFER_ID); for (u32 i = 0; i < buffer_bindings.size(); i++) { const auto& [buffer_id, vsharp] = buffer_bindings[i]; const auto& desc = stage.buffers[i]; @@ -554,7 +547,6 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding } else if (instance.IsNullDescriptorSupported()) { buffer_infos.emplace_back(VK_NULL_HANDLE, 0, VK_WHOLE_SIZE); } else { - auto& null_buffer = buffer_cache.GetBuffer(VideoCore::NULL_BUFFER_ID); buffer_infos.emplace_back(null_buffer.Handle(), 0, VK_WHOLE_SIZE); } } else { @@ -568,6 +560,12 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding push_data.AddOffset(binding.buffer, adjust); buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, vsharp.GetSize() + adjust); + if (auto barrier = + vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite + : vk::AccessFlagBits2::eShaderRead, + vk::PipelineStageFlagBits2::eAllCommands)) { + buffer_barriers.emplace_back(*barrier); + } } set_writes.push_back({ @@ -582,17 +580,19 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding ++binding.buffer; } - const auto null_buffer_view = - instance.IsNullDescriptorSupported() ? VK_NULL_HANDLE : buffer_cache.NullBufferView(); for (u32 i = 0; i < texbuffer_bindings.size(); i++) { const auto& [buffer_id, vsharp] = texbuffer_bindings[i]; const auto& desc = stage.texture_buffers[i]; - vk::BufferView& buffer_view = buffer_views.emplace_back(null_buffer_view); + // Fallback format for null buffer view; never used in valid buffer case. + const auto data_fmt = vsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid + ? vsharp.GetDataFmt() + : AmdGpu::DataFormat::Format8; + const u32 fmt_stride = AmdGpu::NumBits(data_fmt) >> 3; + vk::BufferView buffer_view; if (buffer_id) { const u32 alignment = instance.TexelBufferMinAlignment(); const auto [vk_buffer, offset] = buffer_cache.ObtainBuffer( vsharp.base_address, vsharp.GetSize(), desc.is_written, true, buffer_id); - const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; const u32 buf_stride = vsharp.GetStride(); ASSERT_MSG(buf_stride % fmt_stride == 0, "Texel buffer stride must match format stride"); @@ -600,18 +600,22 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding const u32 adjust = offset - offset_aligned; ASSERT(adjust % fmt_stride == 0); push_data.AddTexelOffset(binding.buffer, buf_stride / fmt_stride, adjust / fmt_stride); - buffer_view = - vk_buffer->View(offset_aligned, vsharp.GetSize() + adjust, desc.is_written, - vsharp.GetDataFmt(), vsharp.GetNumberFmt()); + buffer_view = vk_buffer->View(offset_aligned, vsharp.GetSize() + adjust, + desc.is_written, data_fmt, vsharp.GetNumberFmt()); if (auto barrier = vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite : vk::AccessFlagBits2::eShaderRead, - vk::PipelineStageFlagBits2::eComputeShader)) { + vk::PipelineStageFlagBits2::eAllCommands)) { buffer_barriers.emplace_back(*barrier); } if (desc.is_written) { texture_cache.InvalidateMemoryFromGPU(vsharp.base_address, vsharp.GetSize()); } + } else if (instance.IsNullDescriptorSupported()) { + buffer_view = VK_NULL_HANDLE; + } else { + buffer_view = + null_buffer.View(0, fmt_stride, desc.is_written, data_fmt, vsharp.GetNumberFmt()); } set_writes.push_back({ @@ -621,7 +625,7 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding .descriptorCount = 1, .descriptorType = desc.is_written ? vk::DescriptorType::eStorageTexelBuffer : vk::DescriptorType::eUniformTexelBuffer, - .pTexelBufferView = &buffer_view, + .pTexelBufferView = &buffer_views.emplace_back(buffer_view), }); ++binding.buffer; } @@ -655,7 +659,7 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin if (image->binding.is_bound) { // The image is already bound. In case if it is about to be used as storage we need // to force general layout on it. - image->binding.force_general |= image_desc.IsStorage(tsharp); + image->binding.force_general |= image_desc.is_written; } if (image->binding.is_target) { // The image is already bound as target. Since we read and output to it need to force diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 1bbb90b6c..2905c5ddb 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -108,7 +108,7 @@ private: std::pair, 8> cb_descs; std::optional> db_desc; - boost::container::static_vector image_infos; + boost::container::static_vector image_infos; boost::container::static_vector buffer_views; boost::container::static_vector buffer_infos; boost::container::static_vector bound_images; @@ -121,7 +121,7 @@ private: using TexBufferBindingInfo = std::pair; boost::container::static_vector texbuffer_bindings; using ImageBindingInfo = std::pair; - boost::container::static_vector image_bindings; + boost::container::static_vector image_bindings; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_resource_pool.cpp b/src/video_core/renderer_vulkan/vk_resource_pool.cpp index 25a134528..dba603e71 100644 --- a/src/video_core/renderer_vulkan/vk_resource_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_resource_pool.cpp @@ -153,7 +153,8 @@ vk::DescriptorSet DescriptorHeap::Commit(vk::DescriptorSetLayout set_layout) { } // The pool has run out. Record current tick and place it in pending list. - ASSERT_MSG(result == vk::Result::eErrorOutOfPoolMemory, + ASSERT_MSG(result == vk::Result::eErrorOutOfPoolMemory || + result == vk::Result::eErrorFragmentedPool, "Unexpected error during descriptor set allocation {}", vk::to_string(result)); pending_pools.emplace_back(curr_pool, master_semaphore->CurrentTick()); if (const auto [pool, tick] = pending_pools.front(); master_semaphore->IsFree(tick)) { diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 380660a2f..44f4be6dd 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -84,6 +84,7 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) { } void Swapchain::Recreate(u32 width_, u32 height_) { + LOG_DEBUG(Render_Vulkan, "Recreate the swapchain: width={} height={}", width_, height_); Create(width_, height_, surface); } diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 03339d280..96881c564 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -153,13 +153,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, // the texture cache should re-create the resource with the usage requested vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat | vk::ImageCreateFlagBits::eExtendedUsage}; - const bool can_be_cube = - (info.type == vk::ImageType::e2D) && - ((info.props.is_pow2 ? (info.resources.layers % 8) : (info.resources.layers % 6)) == 0) && - (info.size.width == info.size.height); - if (info.props.is_cube || can_be_cube) { - flags |= vk::ImageCreateFlagBits::eCubeCompatible; - } else if (info.props.is_volume) { + if (info.props.is_volume) { flags |= vk::ImageCreateFlagBits::e2DArrayCompatible; } @@ -210,7 +204,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, Vulkan::SetObjectName(instance->GetDevice(), (vk::Image)image, "Image {}x{}x{} {:#x}:{:#x}", info.size.width, info.size.height, info.size.depth, info.guest_address, - info.guest_size_bytes); + info.guest_size); } boost::container::small_vector Image::GetBarriers( diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index 473dd731e..b04fd188c 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -80,7 +80,7 @@ struct Image { [[nodiscard]] bool Overlaps(VAddr overlap_cpu_addr, size_t overlap_size) const noexcept { const VAddr overlap_end = overlap_cpu_addr + overlap_size; const auto image_addr = info.guest_address; - const auto image_end = info.guest_address + info.guest_size_bytes; + const auto image_end = info.guest_address + info.guest_size; return image_addr < overlap_end && overlap_cpu_addr < image_end; } diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 2cc4aab38..58c2a8e23 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -3,8 +3,10 @@ #include "common/assert.h" #include "common/config.h" +#include "core/libraries/kernel/process.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/texture_cache/image_info.h" +#include "video_core/texture_cache/tile.h" namespace VideoCore { @@ -35,7 +37,6 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { return vk::ImageType::e1D; case AmdGpu::ImageType::Color2D: case AmdGpu::ImageType::Color2DMsaa: - case AmdGpu::ImageType::Cube: case AmdGpu::ImageType::Color2DArray: return vk::ImageType::e2D; case AmdGpu::ImageType::Color3D: @@ -45,195 +46,6 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { } } -// clang-format off -// The table of macro tiles parameters for given tiling index (row) and bpp (column) -static constexpr std::array macro_tile_extents_x1{ - std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 04 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 07 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0A - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0B - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0C - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0E - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0F - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 10 - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 11 - std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 12 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A -}; - -static constexpr std::array macro_tile_extents_x2{ - std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 04 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 07 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0A - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0B - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0C - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0E - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0F - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 10 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 11 - std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 12 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A -}; - -static constexpr std::array macro_tile_extents_x4{ - std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 04 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 07 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0A - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0B - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0C - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0E - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0F - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 10 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 11 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 12 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A -}; - -static constexpr std::array macro_tile_extents_x8{ - std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 04 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 07 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0A - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0B - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0C - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0E - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0F - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 10 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 11 - std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 12 - std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 - std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 - std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 - std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A -}; - -static constexpr std::array macro_tile_extents{ - macro_tile_extents_x1, - macro_tile_extents_x2, - macro_tile_extents_x4, - macro_tile_extents_x8, -}; -// clang-format on - -static constexpr std::pair micro_tile_extent{8u, 8u}; -static constexpr auto hw_pipe_interleave = 256u; - -static constexpr std::pair GetMacroTileExtents(u32 tiling_idx, u32 bpp, u32 num_samples) { - ASSERT(num_samples <= 8); - const auto row = tiling_idx * 5; - const auto column = std::bit_width(bpp) - 4; // bpps are 8, 16, 32, 64, 128 - return (macro_tile_extents[std::log2(num_samples)])[row + column]; -} - -static constexpr std::pair ImageSizeLinearAligned(u32 pitch, u32 height, u32 bpp, - u32 num_samples) { - const auto pitch_align = std::max(8u, 64u / ((bpp + 7) / 8)); - auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); - const auto height_aligned = height; - size_t log_sz = pitch_aligned * height_aligned * num_samples; - const auto slice_align = std::max(64u, 256u / ((bpp + 7) / 8)); - while (log_sz % slice_align) { - pitch_aligned += pitch_align; - log_sz = pitch_aligned * height_aligned * num_samples; - } - return {pitch_aligned, (log_sz * bpp + 7) / 8}; -} - -static constexpr std::pair ImageSizeMicroTiled(u32 pitch, u32 height, u32 bpp, - u32 num_samples) { - const auto& [pitch_align, height_align] = micro_tile_extent; - auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); - const auto height_aligned = (height + height_align - 1) & ~(height_align - 1); - size_t log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8; - while (log_sz % 256) { - pitch_aligned += 8; - log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8; - } - return {pitch_aligned, log_sz}; -} - -static constexpr std::pair ImageSizeMacroTiled(u32 pitch, u32 height, u32 bpp, - u32 num_samples, u32 tiling_idx, - u32 mip_n) { - const auto& [pitch_align, height_align] = GetMacroTileExtents(tiling_idx, bpp, num_samples); - ASSERT(pitch_align != 0 && height_align != 0); - bool downgrade_to_micro = false; - if (mip_n > 0) { - const bool is_less_than_tile = pitch < pitch_align || height < height_align; - // TODO: threshold check - downgrade_to_micro = is_less_than_tile; - } - - if (downgrade_to_micro) { - return ImageSizeMicroTiled(pitch, height, bpp, num_samples); - } - - const auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); - const auto height_aligned = (height + height_align - 1) & ~(height_align - 1); - const auto log_sz = pitch_aligned * height_aligned * num_samples; - return {pitch_aligned, (log_sz * bpp + 7) / 8}; -} - ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group, VAddr cpu_address) noexcept { const auto& attrib = group.attrib; @@ -250,24 +62,24 @@ ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group, guest_address = cpu_address; if (!props.is_tiled) { - guest_size_bytes = pitch * size.height * 4; + guest_size = pitch * size.height * 4; } else { - if (Config::isNeoMode()) { - guest_size_bytes = pitch * ((size.height + 127) & (~127)) * 4; + if (Libraries::Kernel::sceKernelIsNeoMode()) { + guest_size = pitch * ((size.height + 127) & (~127)) * 4; } else { - guest_size_bytes = pitch * ((size.height + 63) & (~63)) * 4; + guest_size = pitch * ((size.height + 63) & (~63)) * 4; } } - mips_layout.emplace_back(guest_size_bytes, pitch, 0); + mips_layout.emplace_back(guest_size, pitch, 0); } ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, const AmdGpu::Liverpool::CbDbExtent& hint /*= {}*/) noexcept { props.is_tiled = buffer.IsTiled(); tiling_mode = buffer.GetTilingMode(); - pixel_format = LiverpoolToVK::SurfaceFormat(buffer.info.format, buffer.NumFormat()); + pixel_format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()); num_samples = buffer.NumSamples(); - num_bits = NumBits(buffer.info.format); + num_bits = NumBits(buffer.GetDataFmt()); type = vk::ImageType::e2D; size.width = hint.Valid() ? hint.width : buffer.Pitch(); size.height = hint.Valid() ? hint.height : buffer.Height(); @@ -279,9 +91,10 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, guest_address = buffer.Address(); const auto color_slice_sz = buffer.GetColorSliceSize(); - guest_size_bytes = color_slice_sz * buffer.NumSlices(); + guest_size = color_slice_sz * buffer.NumSlices(); mips_layout.emplace_back(color_slice_sz, pitch, 0); tiling_idx = static_cast(buffer.attrib.tile_mode_index.Value()); + alt_tile = Libraries::Kernel::sceKernelIsNeoMode() && buffer.info.alt_tile_mode; } ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slices, @@ -303,7 +116,7 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slice guest_address = buffer.Address(); const auto depth_slice_sz = buffer.GetDepthSliceSize(); - guest_size_bytes = depth_slice_sz * num_slices; + guest_size = depth_slice_sz * num_slices; mips_layout.emplace_back(depth_slice_sz, pitch, 0); } @@ -316,7 +129,6 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de } type = ConvertImageType(image.GetType()); props.is_tiled = image.IsTiled(); - props.is_cube = image.GetType() == AmdGpu::ImageType::Cube; props.is_volume = image.GetType() == AmdGpu::ImageType::Color3D; props.is_pow2 = image.pow2pad; props.is_block = IsBlockCoded(); @@ -325,7 +137,7 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de size.depth = props.is_volume ? image.depth + 1 : 1; pitch = image.Pitch(); resources.levels = image.NumLevels(); - resources.layers = image.NumLayers(desc.is_array); + resources.layers = image.NumLayers(); num_samples = image.NumSamples(); num_bits = NumBits(image.GetDataFmt()); @@ -333,13 +145,14 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de mips_layout.reserve(resources.levels); tiling_idx = image.tiling_index; + alt_tile = Libraries::Kernel::sceKernelIsNeoMode() && image.alt_tile_mode; UpdateSize(); } void ImageInfo::UpdateSize() { mips_layout.clear(); MipInfo mip_info{}; - guest_size_bytes = 0; + guest_size = 0; for (auto mip = 0u; mip < resources.levels; ++mip) { auto bpp = num_bits; auto mip_w = pitch >> mip; @@ -384,7 +197,7 @@ void ImageInfo::UpdateSize() { case AmdGpu::TilingMode::Depth_MacroTiled: { ASSERT(!props.is_block); std::tie(mip_info.pitch, mip_info.size) = - ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, tiling_idx, mip); + ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, tiling_idx, mip, alt_tile); break; } default: { @@ -392,11 +205,11 @@ void ImageInfo::UpdateSize() { } } mip_info.size *= mip_d; - mip_info.offset = guest_size_bytes; + mip_info.offset = guest_size; mips_layout.emplace_back(mip_info); - guest_size_bytes += mip_info.size; + guest_size += mip_info.size; } - guest_size_bytes *= resources.layers; + guest_size *= resources.layers; } int ImageInfo::IsMipOf(const ImageInfo& info) const { @@ -468,18 +281,18 @@ int ImageInfo::IsSliceOf(const ImageInfo& info) const { } // Check for size alignment. - const bool slice_size = info.guest_size_bytes / info.resources.layers; - if (guest_size_bytes % slice_size != 0) { + const bool slice_size = info.guest_size / info.resources.layers; + if (guest_size % slice_size != 0) { return -1; } // Ensure that address is aligned too. const auto addr_diff = guest_address - info.guest_address; - if ((addr_diff % guest_size_bytes) != 0) { + if ((addr_diff % guest_size) != 0) { return -1; } - return addr_diff / guest_size_bytes; + return addr_diff / guest_size; } } // namespace VideoCore diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index a657310a8..123540c1e 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -61,7 +61,6 @@ struct ImageInfo { } meta_info{}; struct { - u32 is_cube : 1; u32 is_volume : 1; u32 is_tiled : 1; u32 is_pow2 : 1; @@ -84,8 +83,9 @@ struct ImageInfo { }; boost::container::small_vector mips_layout; VAddr guest_address{0}; - u32 guest_size_bytes{0}; + u32 guest_size{0}; u32 tiling_idx{0}; // TODO: merge with existing! + bool alt_tile{false}; VAddr stencil_addr{0}; u32 stencil_size{0}; diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 9e67b7f73..d90b78c67 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -20,8 +20,6 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) { case AmdGpu::ImageType::Color2D: case AmdGpu::ImageType::Color2DMsaa: return vk::ImageViewType::e2D; - case AmdGpu::ImageType::Cube: - return vk::ImageViewType::eCube; case AmdGpu::ImageType::Color2DArray: return vk::ImageViewType::e2DArray; case AmdGpu::ImageType::Color3D: @@ -31,27 +29,8 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) { } } -vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) { - switch (dst_sel) { - case 0: - return vk::ComponentSwizzle::eZero; - case 1: - return vk::ComponentSwizzle::eOne; - case 4: - return vk::ComponentSwizzle::eR; - case 5: - return vk::ComponentSwizzle::eG; - case 6: - return vk::ComponentSwizzle::eB; - case 7: - return vk::ComponentSwizzle::eA; - default: - UNREACHABLE(); - } -} - ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept - : is_storage{desc.IsStorage(image)} { + : is_storage{desc.is_written} { const auto dfmt = image.GetDataFmt(); auto nfmt = image.GetNumberFmt(); if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) { @@ -61,47 +40,24 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso if (desc.is_depth) { format = Vulkan::LiverpoolToVK::PromoteFormatToDepth(format); } + range.base.level = image.base_level; range.base.layer = image.base_array; - if (image.GetType() == AmdGpu::ImageType::Color2DMsaa || - image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) { - range.extent.levels = 1; - } else { - range.extent.levels = image.last_level - image.base_level + 1; - } - range.extent.layers = image.last_array - image.base_array + 1; - type = ConvertImageViewType(image.GetBoundType()); - - // Adjust view type for arrays - if (type == vk::ImageViewType::eCube) { - if (desc.is_array) { - type = vk::ImageViewType::eCubeArray; - } else { - // Some games try to bind an array of cubemaps while shader reads only single one. - range.extent.layers = std::min(range.extent.layers, 6u); - } - } - if (type == vk::ImageViewType::e3D && range.extent.layers > 1) { - // Some games pass incorrect layer count for 3D textures so we need to fixup it. - range.extent.layers = 1; - } + range.extent.levels = image.NumViewLevels(desc.is_array); + range.extent.layers = image.NumViewLayers(desc.is_array); + type = ConvertImageViewType(image.GetViewType(desc.is_array)); if (!is_storage) { - mapping.r = ConvertComponentSwizzle(image.dst_sel_x); - mapping.g = ConvertComponentSwizzle(image.dst_sel_y); - mapping.b = ConvertComponentSwizzle(image.dst_sel_z); - mapping.a = ConvertComponentSwizzle(image.dst_sel_w); + mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect()); } } ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) noexcept { - const auto base_format = - Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.info.format, col_buffer.NumFormat()); range.base.layer = col_buffer.view.slice_start; range.extent.layers = col_buffer.NumSlices() - range.base.layer; type = range.extent.layers > 1 ? vk::ImageViewType::e2DArray : vk::ImageViewType::e2D; - format = Vulkan::LiverpoolToVK::AdjustColorBufferFormat(base_format, - col_buffer.info.comp_swap.Value()); + format = + Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.GetDataFmt(), col_buffer.GetNumberFmt()); } ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::DepthBuffer& depth_buffer, diff --git a/src/video_core/texture_cache/sampler.cpp b/src/video_core/texture_cache/sampler.cpp index 9f4bc7a7e..8dbdd2912 100644 --- a/src/video_core/texture_cache/sampler.cpp +++ b/src/video_core/texture_cache/sampler.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include "video_core/amdgpu/resource.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/texture_cache/sampler.h" @@ -12,6 +14,12 @@ Sampler::Sampler(const Vulkan::Instance& instance, const AmdGpu::Sampler& sample LOG_WARNING(Render_Vulkan, "Texture requires gamma correction"); } using namespace Vulkan; + const bool anisotropyEnable = instance.IsAnisotropicFilteringSupported() && + (AmdGpu::IsAnisoFilter(sampler.xy_mag_filter) || + AmdGpu::IsAnisoFilter(sampler.xy_min_filter)); + const float maxAnisotropy = + anisotropyEnable ? std::clamp(sampler.MaxAniso(), 1.0f, instance.MaxSamplerAnisotropy()) + : 1.0f; const vk::SamplerCreateInfo sampler_ci = { .magFilter = LiverpoolToVK::Filter(sampler.xy_mag_filter), .minFilter = LiverpoolToVK::Filter(sampler.xy_min_filter), @@ -20,6 +28,8 @@ Sampler::Sampler(const Vulkan::Instance& instance, const AmdGpu::Sampler& sample .addressModeV = LiverpoolToVK::ClampMode(sampler.clamp_y), .addressModeW = LiverpoolToVK::ClampMode(sampler.clamp_z), .mipLodBias = std::min(sampler.LodBias(), instance.MaxSamplerLodBias()), + .anisotropyEnable = anisotropyEnable, + .maxAnisotropy = maxAnisotropy, .compareEnable = sampler.depth_compare_func != AmdGpu::DepthCompare::Never, .compareOp = LiverpoolToVK::DepthCompare(sampler.depth_compare_func), .minLod = sampler.MinLod(), diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 897d6f67e..bef083d1a 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -3,7 +3,9 @@ #include #include + #include "common/assert.h" +#include "common/debug.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/page_manager.h" #include "video_core/renderer_vulkan/vk_instance.h" @@ -34,7 +36,7 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& Vulkan::SetObjectName(instance.GetDevice(), null_image, "Null Image"); img.flags = ImageFlagBits::Empty; img.track_addr = img.info.guest_address; - img.track_addr_end = img.info.guest_address + img.info.guest_size_bytes; + img.track_addr_end = img.info.guest_address + img.info.guest_size; ImageViewInfo view_info; const auto null_view_id = @@ -50,7 +52,7 @@ void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) { if (image.hash == 0) { // Initialize hash const u8* addr = std::bit_cast(image.info.guest_address); - image.hash = XXH3_64bits(addr, image.info.guest_size_bytes); + image.hash = XXH3_64bits(addr, image.info.guest_size); } image.flags |= ImageFlagBits::MaybeCpuDirty; UntrackImage(image_id); @@ -63,7 +65,7 @@ void TextureCache::InvalidateMemory(VAddr addr, size_t size) { const auto pages_end = PageManager::GetNextPageAddr(addr + size - 1); ForEachImageInRegion(pages_start, pages_end - pages_start, [&](ImageId image_id, Image& image) { const auto image_begin = image.info.guest_address; - const auto image_end = image.info.guest_address + image.info.guest_size_bytes; + const auto image_end = image.info.guest_address + image.info.guest_size; if (image_begin < end && addr < image_end) { // Start or end of the modified region is in the image, or the image is entirely within // the modified region, so the image was definitely accessed by this page fault. @@ -201,7 +203,7 @@ std::tuple TextureCache::ResolveOverlap(const ImageInfo& imag } if (image_info.pixel_format != tex_cache_image.info.pixel_format || - image_info.guest_size_bytes <= tex_cache_image.info.guest_size_bytes) { + image_info.guest_size <= tex_cache_image.info.guest_size) { auto result_id = merged_image_id ? merged_image_id : cache_image_id; const auto& result_image = slot_images[result_id]; return { @@ -302,7 +304,7 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { std::scoped_lock lock{mutex}; boost::container::small_vector image_ids; - ForEachImageInRegion(info.guest_address, info.guest_size_bytes, + ForEachImageInRegion(info.guest_address, info.guest_size, [&](ImageId image_id, Image& image) { image_ids.push_back(image_id); }); ImageId image_id{}; @@ -313,8 +315,7 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { if (cache_image.info.guest_address != info.guest_address) { continue; } - if (False(flags & FindFlags::RelaxSize) && - cache_image.info.guest_size_bytes != info.guest_size_bytes) { + if (False(flags & FindFlags::RelaxSize) && cache_image.info.guest_size != info.guest_size) { continue; } if (False(flags & FindFlags::RelaxDim) && cache_image.info.size != info.size) { @@ -455,7 +456,7 @@ ImageView& TextureCache::FindDepthTarget(BaseDesc& desc) { if (!stencil_id) { ImageInfo info{}; info.guest_address = desc.info.stencil_addr; - info.guest_size_bytes = desc.info.stencil_size; + info.guest_size = desc.info.stencil_size; info.size = desc.info.size; stencil_id = slot_images.insert(instance, scheduler, info); RegisterImage(stencil_id); @@ -468,6 +469,9 @@ ImageView& TextureCache::FindDepthTarget(BaseDesc& desc) { } void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_scheduler /*= nullptr*/) { + RENDERER_TRACE; + TRACE_HINT(fmt::format("{:x}:{:x}", image.info.guest_address, image.info.guest_size)); + if (False(image.flags & ImageFlagBits::Dirty)) { return; } @@ -542,31 +546,62 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule sched_ptr->EndRendering(); const auto cmdbuf = sched_ptr->CommandBuffer(); - image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {}, - cmdbuf); - const VAddr image_addr = image.info.guest_address; - const size_t image_size = image.info.guest_size_bytes; + const size_t image_size = image.info.guest_size; const auto [vk_buffer, buf_offset] = buffer_cache.ObtainViewBuffer(image_addr, image_size, is_gpu_dirty); + // The obtained buffer may be written by a shader so we need to emit a barrier to prevent RAW // hazard if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead, vk::PipelineStageFlagBits2::eTransfer)) { - const auto dependencies = vk::DependencyInfo{ + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ .dependencyFlags = vk::DependencyFlagBits::eByRegion, .bufferMemoryBarrierCount = 1, .pBufferMemoryBarriers = &barrier.value(), - }; - cmdbuf.pipelineBarrier2(dependencies); + }); } - const auto [buffer, offset] = tile_manager.TryDetile(vk_buffer->Handle(), buf_offset, image); + const auto [buffer, offset] = + tile_manager.TryDetile(vk_buffer->Handle(), buf_offset, image.info); for (auto& copy : image_copy) { copy.bufferOffset += offset; } + const vk::BufferMemoryBarrier2 pre_barrier{ + .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .srcAccessMask = vk::AccessFlagBits2::eMemoryWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, + .dstAccessMask = vk::AccessFlagBits2::eTransferRead, + .buffer = buffer, + .offset = offset, + .size = image_size, + }; + const vk::BufferMemoryBarrier2 post_barrier{ + .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, + .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .dstAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + .buffer = buffer, + .offset = offset, + .size = image_size, + }; + const auto image_barriers = + image.GetBarriers(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, + vk::PipelineStageFlagBits2::eTransfer, {}); + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &pre_barrier, + .imageMemoryBarrierCount = static_cast(image_barriers.size()), + .pImageMemoryBarriers = image_barriers.data(), + }); cmdbuf.copyBufferToImage(buffer, image.image, vk::ImageLayout::eTransferDstOptimal, image_copy); + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &post_barrier, + }); image.flags &= ~ImageFlagBits::Dirty; } @@ -581,7 +616,7 @@ void TextureCache::RegisterImage(ImageId image_id) { ASSERT_MSG(False(image.flags & ImageFlagBits::Registered), "Trying to register an already registered image"); image.flags |= ImageFlagBits::Registered; - ForEachPage(image.info.guest_address, image.info.guest_size_bytes, + ForEachPage(image.info.guest_address, image.info.guest_size, [this, image_id](u64 page) { page_table[page].push_back(image_id); }); } @@ -590,7 +625,7 @@ void TextureCache::UnregisterImage(ImageId image_id) { ASSERT_MSG(True(image.flags & ImageFlagBits::Registered), "Trying to unregister an already unregistered image"); image.flags &= ~ImageFlagBits::Registered; - ForEachPage(image.info.guest_address, image.info.guest_size_bytes, [this, image_id](u64 page) { + ForEachPage(image.info.guest_address, image.info.guest_size, [this, image_id](u64 page) { const auto page_it = page_table.find(page); if (page_it == nullptr) { UNREACHABLE_MSG("Unregistering unregistered page=0x{:x}", page << PageShift); @@ -609,7 +644,7 @@ void TextureCache::UnregisterImage(ImageId image_id) { void TextureCache::TrackImage(ImageId image_id) { auto& image = slot_images[image_id]; const auto image_begin = image.info.guest_address; - const auto image_end = image.info.guest_address + image.info.guest_size_bytes; + const auto image_end = image.info.guest_address + image.info.guest_size; if (image_begin == image.track_addr && image_end == image.track_addr_end) { return; } @@ -618,7 +653,7 @@ void TextureCache::TrackImage(ImageId image_id) { // Re-track the whole image image.track_addr = image_begin; image.track_addr_end = image_end; - tracker.UpdatePagesCachedCount(image_begin, image.info.guest_size_bytes, 1); + tracker.UpdatePagesCachedCount(image_begin, image.info.guest_size, 1); } else { if (image_begin < image.track_addr) { TrackImageHead(image_id); @@ -643,7 +678,7 @@ void TextureCache::TrackImageHead(ImageId image_id) { void TextureCache::TrackImageTail(ImageId image_id) { auto& image = slot_images[image_id]; - const auto image_end = image.info.guest_address + image.info.guest_size_bytes; + const auto image_end = image.info.guest_address + image.info.guest_size; if (image_end == image.track_addr_end) { return; } @@ -688,7 +723,7 @@ void TextureCache::UntrackImageHead(ImageId image_id) { void TextureCache::UntrackImageTail(ImageId image_id) { auto& image = slot_images[image_id]; - const auto image_end = image.info.guest_address + image.info.guest_size_bytes; + const auto image_end = image.info.guest_address + image.info.guest_size; if (!image.IsTracked() || image.track_addr_end < image_end) { return; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 944f021df..69907f000 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -65,7 +65,7 @@ public: struct TextureDesc : public BaseDesc { TextureDesc() = default; TextureDesc(const AmdGpu::Image& image, const Shader::ImageResource& desc) - : BaseDesc{desc.IsStorage(image) ? BindingType::Storage : BindingType::Texture, + : BaseDesc{desc.is_written ? BindingType::Storage : BindingType::Texture, ImageInfo{image, desc}, ImageViewInfo{image, desc}} {} }; diff --git a/src/video_core/texture_cache/tile.h b/src/video_core/texture_cache/tile.h new file mode 100644 index 000000000..532bf3d88 --- /dev/null +++ b/src/video_core/texture_cache/tile.h @@ -0,0 +1,347 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/assert.h" +#include "common/types.h" + +namespace VideoCore { + +// clang-format off +// The table of macro tiles parameters for given tiling index (row) and bpp (column) +/* Calculation: + * - Inputs: + * TileMode, BytesPerPixel, NumFragments + * - Constants: + * MicroTileWidth = 8, MicroTileHeight = 8, + * Tile Mode LUTs: IsDepth(), IsPrt(), TileThickness(), TileSplit(), SampleSplit(), NumPipes() + * Macro Tile Mode LUTs: BankWidth(), BankHeight(), NumBanks(), MacroTileAspect() + * - Determine the macro tile mode: + * TileBytes = MicroTileWidth * MicroTileHeight * TileThickness(TileMode) * BytesPerPixel + * TileSplit = min(IsDepth(TileMode) ? TileSplit(TileMode) : max(TileBytes * SampleSplit(TileMode), 256), NumFragments * TileBytes, 1024) + * MacroTileModeIndex = log2(TileSplit / 64) + * MacroTileMode = IsPrt(TileMode) ? MacroTileModeIndex + 8 : MacroTileModeIndex + * - Calculate macro tile width and height: + * Width = NumPipes(TileMode) * BankWidth(MacroTileMode) * MicroTileWidth * MacroTileAspect(MacroTileMode, AltTileMode) + * Height = NumBanks(MacroTileMode, AltTileMode) * BankHeight(MacroTileMode, AltTileMode) * MicroTileHeight / MacroTileAspect(MacroTileMode, AltTileMode) + */ + +constexpr std::array macro_tile_extents_x1{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0A + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0B + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0E + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 0F + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 10 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 11 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_x2{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0A + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0B + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0E + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0F + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 10 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 11 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_x4{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0A + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0B + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0E + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0F + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 10 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 11 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_x8{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 01 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 02 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 03 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0A + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0B + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0E + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 0F + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 10 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 11 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 14 + std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 18 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 19 + std::pair{128u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, std::pair{64u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_alt_x1{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 01 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 02 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 03 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, // 0A + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, // 0B + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, // 0E + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, // 0F + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, // 10 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, // 11 + std::pair{256u, 256u}, std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 14 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 18 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 19 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_alt_x2{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 01 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 02 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 03 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0A + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 0B + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0E + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0F + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 10 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 11 + std::pair{256u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 14 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 18 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 19 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_alt_x4{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 01 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 02 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 03 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0A + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 0B + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0E + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0F + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 10 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 11 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 14 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 18 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 19 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents_alt_x8{ + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 00 + std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, std::pair{256u, 128u}, // 01 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 02 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 03 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 04 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 05 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, // 06 + std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 07 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 08 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 09 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0A + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 0B + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 0C + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 0D + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0E + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 0F + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 10 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 11 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 12 + std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, std::pair{0u, 0u}, // 13 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 14 + std::pair{128u, 128u}, std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 15 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 16 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 17 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 32u}, std::pair{128u, 32u}, std::pair{128u, 32u}, // 18 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 19 + std::pair{128u, 128u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, std::pair{128u, 64u}, // 1A +}; + +constexpr std::array macro_tile_extents{ + macro_tile_extents_x1, + macro_tile_extents_x2, + macro_tile_extents_x4, + macro_tile_extents_x8, +}; + +constexpr std::array macro_tile_extents_alt{ + macro_tile_extents_alt_x1, + macro_tile_extents_alt_x2, + macro_tile_extents_alt_x4, + macro_tile_extents_alt_x8, +}; +// clang-format on + +constexpr std::pair micro_tile_extent{8u, 8u}; +constexpr auto hw_pipe_interleave = 256u; + +constexpr std::pair GetMacroTileExtents(u32 tiling_idx, u32 bpp, u32 num_samples, + bool alt) { + ASSERT(num_samples <= 8); + const auto samples_log = static_cast(std::log2(num_samples)); + const auto row = tiling_idx * 5; + const auto column = std::bit_width(bpp) - 4; // bpps are 8, 16, 32, 64, 128 + return (alt ? macro_tile_extents_alt : macro_tile_extents)[samples_log][row + column]; +} + +constexpr std::pair ImageSizeLinearAligned(u32 pitch, u32 height, u32 bpp, + u32 num_samples) { + const auto pitch_align = std::max(8u, 64u / ((bpp + 7) / 8)); + auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); + const auto height_aligned = height; + size_t log_sz = pitch_aligned * height_aligned * num_samples; + const auto slice_align = std::max(64u, 256u / ((bpp + 7) / 8)); + while (log_sz % slice_align) { + pitch_aligned += pitch_align; + log_sz = pitch_aligned * height_aligned * num_samples; + } + return {pitch_aligned, (log_sz * bpp + 7) / 8}; +} + +constexpr std::pair ImageSizeMicroTiled(u32 pitch, u32 height, u32 bpp, + u32 num_samples) { + const auto& [pitch_align, height_align] = micro_tile_extent; + auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); + const auto height_aligned = (height + height_align - 1) & ~(height_align - 1); + size_t log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8; + while (log_sz % 256) { + pitch_aligned += 8; + log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8; + } + return {pitch_aligned, log_sz}; +} + +constexpr std::pair ImageSizeMacroTiled(u32 pitch, u32 height, u32 bpp, + u32 num_samples, u32 tiling_idx, u32 mip_n, + bool alt) { + const auto& [pitch_align, height_align] = + GetMacroTileExtents(tiling_idx, bpp, num_samples, alt); + ASSERT(pitch_align != 0 && height_align != 0); + bool downgrade_to_micro = false; + if (mip_n > 0) { + const bool is_less_than_tile = pitch < pitch_align || height < height_align; + // TODO: threshold check + downgrade_to_micro = is_less_than_tile; + } + + if (downgrade_to_micro) { + return ImageSizeMicroTiled(pitch, height, bpp, num_samples); + } + + const auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); + const auto height_aligned = (height + height_align - 1) & ~(height_align - 1); + const auto log_sz = pitch_aligned * height_aligned * num_samples; + return {pitch_aligned, (log_sz * bpp + 7) / 8}; +} + +} // namespace VideoCore diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index f6b2e2beb..aba255ce5 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -4,110 +4,51 @@ #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" +#include "video_core/texture_cache/image_info.h" #include "video_core/texture_cache/image_view.h" #include "video_core/texture_cache/tile_manager.h" -#include "video_core/host_shaders/detile_m32x1_comp.h" -#include "video_core/host_shaders/detile_m32x2_comp.h" -#include "video_core/host_shaders/detile_m32x4_comp.h" -#include "video_core/host_shaders/detile_m8x1_comp.h" -#include "video_core/host_shaders/detile_m8x2_comp.h" -#include "video_core/host_shaders/detile_macro32x1_comp.h" -#include "video_core/host_shaders/detile_macro32x2_comp.h" +#include "video_core/host_shaders/detilers/macro_32bpp_comp.h" +#include "video_core/host_shaders/detilers/macro_64bpp_comp.h" +#include "video_core/host_shaders/detilers/macro_8bpp_comp.h" +#include "video_core/host_shaders/detilers/micro_128bpp_comp.h" +#include "video_core/host_shaders/detilers/micro_16bpp_comp.h" +#include "video_core/host_shaders/detilers/micro_32bpp_comp.h" +#include "video_core/host_shaders/detilers/micro_64bpp_comp.h" +#include "video_core/host_shaders/detilers/micro_8bpp_comp.h" -#include +// #include #include #include namespace VideoCore { -static vk::Format DemoteImageFormatForDetiling(vk::Format format) { - switch (format) { - case vk::Format::eR8Uint: - case vk::Format::eR8Unorm: - return vk::Format::eR8Uint; - case vk::Format::eR4G4B4A4UnormPack16: - case vk::Format::eB5G6R5UnormPack16: - case vk::Format::eR5G5B5A1UnormPack16: - case vk::Format::eR8G8Unorm: - case vk::Format::eR16Sfloat: - case vk::Format::eR16Unorm: - case vk::Format::eD16Unorm: - return vk::Format::eR8G8Uint; - case vk::Format::eR8G8B8A8Srgb: - case vk::Format::eB8G8R8A8Srgb: - case vk::Format::eB8G8R8A8Unorm: - case vk::Format::eR8G8B8A8Unorm: - case vk::Format::eR8G8B8A8Snorm: - case vk::Format::eR8G8B8A8Uint: - case vk::Format::eR32Sfloat: - case vk::Format::eR32Uint: - case vk::Format::eR16G16Sfloat: - case vk::Format::eR16G16Unorm: - case vk::Format::eR16G16Snorm: - case vk::Format::eB10G11R11UfloatPack32: - case vk::Format::eA2B10G10R10UnormPack32: - return vk::Format::eR32Uint; - case vk::Format::eBc1RgbaSrgbBlock: - case vk::Format::eBc1RgbaUnormBlock: - case vk::Format::eBc4UnormBlock: - case vk::Format::eR32G32Sfloat: - case vk::Format::eR32G32Uint: - case vk::Format::eR16G16B16A16Unorm: - case vk::Format::eR16G16B16A16Uint: - case vk::Format::eR16G16B16A16Sfloat: - return vk::Format::eR32G32Uint; - case vk::Format::eBc2SrgbBlock: - case vk::Format::eBc2UnormBlock: - 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: - case vk::Format::eR32G32B32A32Uint: - case vk::Format::eR32G32B32A32Sfloat: - return vk::Format::eR32G32B32A32Uint; - default: - break; - } - - // Log missing formats only once to avoid spamming the log. - static constexpr size_t MaxFormatIndex = 256; - static std::array logged_formats{}; - if (const u32 index = u32(format); !logged_formats[index]) { - LOG_ERROR(Render_Vulkan, "Unexpected format for demotion {}", vk::to_string(format)); - logged_formats[index] = true; - } - return format; -} - -const DetilerContext* TileManager::GetDetiler(const Image& image) const { - const auto format = DemoteImageFormatForDetiling(image.info.pixel_format); - - switch (image.info.tiling_mode) { +const DetilerContext* TileManager::GetDetiler(const ImageInfo& info) const { + const auto bpp = info.num_bits * (info.props.is_block ? 16 : 1); + switch (info.tiling_mode) { case AmdGpu::TilingMode::Texture_MicroTiled: - switch (format) { - case vk::Format::eR8Uint: - return &detilers[DetilerType::Micro8x1]; - case vk::Format::eR8G8Uint: - return &detilers[DetilerType::Micro8x2]; - case vk::Format::eR32Uint: - return &detilers[DetilerType::Micro32x1]; - case vk::Format::eR32G32Uint: - return &detilers[DetilerType::Micro32x2]; - case vk::Format::eR32G32B32A32Uint: - return &detilers[DetilerType::Micro32x4]; + switch (bpp) { + case 8: + return &detilers[DetilerType::Micro8]; + case 16: + return &detilers[DetilerType::Micro16]; + case 32: + return &detilers[DetilerType::Micro32]; + case 64: + return &detilers[DetilerType::Micro64]; + case 128: + return &detilers[DetilerType::Micro128]; default: return nullptr; } case AmdGpu::TilingMode::Texture_Volume: - switch (format) { - case vk::Format::eR32Uint: - return &detilers[DetilerType::Macro32x1]; - case vk::Format::eR32G32Uint: - return &detilers[DetilerType::Macro32x2]; + switch (bpp) { + case 8: + return &detilers[DetilerType::Macro8]; + case 32: + return &detilers[DetilerType::Macro32]; + case 64: + return &detilers[DetilerType::Macro64]; default: return nullptr; } @@ -127,10 +68,10 @@ struct DetilerParams { TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler) : instance{instance}, scheduler{scheduler} { static const std::array detiler_shaders{ - HostShaders::DETILE_M8X1_COMP, HostShaders::DETILE_M8X2_COMP, - HostShaders::DETILE_M32X1_COMP, HostShaders::DETILE_M32X2_COMP, - HostShaders::DETILE_M32X4_COMP, HostShaders::DETILE_MACRO32X1_COMP, - HostShaders::DETILE_MACRO32X2_COMP, + HostShaders::MICRO_8BPP_COMP, HostShaders::MICRO_16BPP_COMP, + HostShaders::MICRO_32BPP_COMP, HostShaders::MICRO_64BPP_COMP, + HostShaders::MICRO_128BPP_COMP, HostShaders::MACRO_8BPP_COMP, + HostShaders::MACRO_32BPP_COMP, HostShaders::MACRO_64BPP_COMP, }; boost::container::static_vector bindings{ @@ -255,23 +196,23 @@ void TileManager::FreeBuffer(ScratchBuffer buffer) { } std::pair TileManager::TryDetile(vk::Buffer in_buffer, u32 in_offset, - Image& image) { - if (!image.info.props.is_tiled) { + const ImageInfo& info) { + if (!info.props.is_tiled) { return {in_buffer, in_offset}; } - const auto* detiler = GetDetiler(image); + const auto* detiler = GetDetiler(info); if (!detiler) { - if (image.info.tiling_mode != AmdGpu::TilingMode::Texture_MacroTiled && - image.info.tiling_mode != AmdGpu::TilingMode::Display_MacroTiled && - image.info.tiling_mode != AmdGpu::TilingMode::Depth_MacroTiled) { + if (info.tiling_mode != AmdGpu::TilingMode::Texture_MacroTiled && + info.tiling_mode != AmdGpu::TilingMode::Display_MacroTiled && + info.tiling_mode != AmdGpu::TilingMode::Depth_MacroTiled) { LOG_ERROR(Render_Vulkan, "Unsupported tiled image: {} ({})", - vk::to_string(image.info.pixel_format), NameOf(image.info.tiling_mode)); + vk::to_string(info.pixel_format), NameOf(info.tiling_mode)); } return {in_buffer, in_offset}; } - const u32 image_size = image.info.guest_size_bytes; + const u32 image_size = info.guest_size; // Prepare output buffer auto out_buffer = AllocBuffer(image_size, true); @@ -314,22 +255,20 @@ std::pair TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o set_writes); DetilerParams params; - params.num_levels = image.info.resources.levels; - params.pitch0 = image.info.pitch >> (image.info.props.is_block ? 2u : 0u); - params.height = image.info.size.height; - if (image.info.tiling_mode == AmdGpu::TilingMode::Texture_Volume) { - ASSERT(image.info.resources.levels == 1); - ASSERT(image.info.num_bits >= 32); - const auto tiles_per_row = image.info.pitch / 8u; - const auto tiles_per_slice = tiles_per_row * ((image.info.size.height + 7u) / 8u); + params.num_levels = info.resources.levels; + params.pitch0 = info.pitch >> (info.props.is_block ? 2u : 0u); + params.height = info.size.height; + if (info.tiling_mode == AmdGpu::TilingMode::Texture_Volume) { + ASSERT(info.resources.levels == 1); + const auto tiles_per_row = info.pitch / 8u; + const auto tiles_per_slice = tiles_per_row * ((info.size.height + 7u) / 8u); params.sizes[0] = tiles_per_row; params.sizes[1] = tiles_per_slice; } else { - - ASSERT(image.info.resources.levels <= 14); + ASSERT(info.resources.levels <= 14); std::memset(¶ms.sizes, 0, sizeof(params.sizes)); - for (int m = 0; m < image.info.resources.levels; ++m) { - params.sizes[m] = image.info.mips_layout[m].size * image.info.resources.layers + + for (int m = 0; m < info.resources.levels; ++m) { + params.sizes[m] = info.mips_layout[m].size * info.resources.layers + (m > 0 ? params.sizes[m - 1] : 0); } } @@ -338,20 +277,9 @@ std::pair TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o ¶ms); ASSERT((image_size % 64) == 0); - const auto bpp = image.info.num_bits * (image.info.props.is_block ? 16u : 1u); + const auto bpp = info.num_bits * (info.props.is_block ? 16u : 1u); const auto num_tiles = image_size / (64 * (bpp / 8)); cmdbuf.dispatch(num_tiles, 1, 1); - - const vk::BufferMemoryBarrier post_barrier{ - .srcAccessMask = vk::AccessFlagBits::eShaderWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead, - .buffer = out_buffer.first, - .size = image_size, - }; - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, - vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, - {}, post_barrier, {}); - return {out_buffer.first, 0}; } diff --git a/src/video_core/texture_cache/tile_manager.h b/src/video_core/texture_cache/tile_manager.h index 72860bca0..4eae7be9e 100644 --- a/src/video_core/texture_cache/tile_manager.h +++ b/src/video_core/texture_cache/tile_manager.h @@ -5,21 +5,22 @@ #include "common/types.h" #include "video_core/buffer_cache/buffer.h" -#include "video_core/texture_cache/image.h" namespace VideoCore { class TextureCache; +struct ImageInfo; enum DetilerType : u32 { - Micro8x1, - Micro8x2, - Micro32x1, - Micro32x2, - Micro32x4, + Micro8, + Micro16, + Micro32, + Micro64, + Micro128, - Macro32x1, - Macro32x2, + Macro8, + Macro32, + Macro64, Max }; @@ -36,14 +37,15 @@ public: TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler); ~TileManager(); - std::pair TryDetile(vk::Buffer in_buffer, u32 in_offset, Image& image); + std::pair TryDetile(vk::Buffer in_buffer, u32 in_offset, + const ImageInfo& info); ScratchBuffer AllocBuffer(u32 size, bool is_storage = false); void Upload(ScratchBuffer buffer, const void* data, size_t size); void FreeBuffer(ScratchBuffer buffer); private: - const DetilerContext* GetDetiler(const Image& image) const; + const DetilerContext* GetDetiler(const ImageInfo& info) const; private: const Vulkan::Instance& instance;