diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..263762bd6 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +ko_fi: shadps4 diff --git a/.github/linux-appimage-qt.sh b/.github/linux-appimage-qt.sh index 870172457..06d5cbc11 100755 --- a/.github/linux-appimage-qt.sh +++ b/.github/linux-appimage-qt.sh @@ -9,6 +9,8 @@ fi export Qt6_DIR="/usr/lib/qt6" export PATH="$Qt6_DIR/bin:$PATH" +export EXTRA_QT_PLUGINS="waylandcompositor" +export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" # Prepare Tools for building the AppImage wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage @@ -22,5 +24,10 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh # Build AppImage ./linuxdeploy-x86_64.AppImage --appdir AppDir ./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir -./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --plugin qt --output appimage + +cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin + +./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --plugin qt +rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so +./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage mv Shadps4-x86_64.AppImage Shadps4-qt.AppImage diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..6b87ec418 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,481 @@ +# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +name: Build and Release + +on: [push, pull_request] + +concurrency: + group: ci-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'push' }} + +env: + BUILD_TYPE: Release + +jobs: + reuse: + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v4 + - uses: fsfe/reuse-action@v4 + + clang-format: + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install + run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main' + sudo apt update + sudo apt install clang-format-17 + - name: Build + env: + COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} + run: ./.ci/clang-format.sh + + get-info: + runs-on: ubuntu-latest + outputs: + date: ${{ steps.vars.outputs.date }} + shorthash: ${{ steps.vars.outputs.shorthash }} + steps: + - uses: actions/checkout@v4 + - name: Get date and git hash + id: vars + run: | + echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + windows-sdl: + runs-on: windows-latest + needs: get-info + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Cache CMake Configuration + uses: actions/cache@v4 + env: + cache-name: ${{ runner.os }}-sdl-ninja-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: Setup VS Environment + uses: ilammy/msvc-dev-cmd@v1.13.0 + with: + arch: amd64 + + - name: Configure CMake + run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + + - name: Upload Windows SDL artifact + uses: actions/upload-artifact@v4 + with: + name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: ${{github.workspace}}/build/shadPS4.exe + + windows-qt: + runs-on: windows-latest + needs: get-info + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Qt + uses: jurplel/install-qt-action@v4 + with: + version: 6.7.3 + host: windows + target: desktop + arch: win64_msvc2019_64 + archives: qtbase qttools + modules: qtmultimedia + + - name: Cache CMake Configuration + uses: actions/cache@v4 + env: + cache-name: ${{ runner.os }}-qt-ninja-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: Setup VS Environment + uses: ilammy/msvc-dev-cmd@v1.13.0 + with: + arch: amd64 + + - name: Configure CMake + run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + + - name: Deploy and Package + run: | + mkdir upload + move build/shadPS4.exe upload + windeployqt --no-compiler-runtime --no-system-d3d-compiler --no-system-dxc-compiler --dir upload upload/shadPS4.exe + Compress-Archive -Path upload/* -DestinationPath shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}.zip + + - name: Upload Windows Qt artifact + uses: actions/upload-artifact@v4 + with: + name: shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: upload/ + + macos-sdl: + runs-on: macos-latest + needs: get-info + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup latest Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest + + - name: Install MoltenVK + run: | + arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + arch -x86_64 /usr/local/bin/brew install molten-vk + + - 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 + create-symlink: true + key: ${{env.cache-name}}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + variant: sccache + + - name: Configure CMake + run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu) + + - name: Package and Upload macOS SDL artifact + run: | + mkdir upload + mv ${{github.workspace}}/build/shadps4 upload + cp $(arch -x86_64 /usr/local/bin/brew --prefix)/opt/molten-vk/lib/libMoltenVK.dylib upload + tar cf shadps4-macos-sdl.tar.gz -C upload . + - uses: actions/upload-artifact@v4 + with: + name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: shadps4-macos-sdl.tar.gz + + macos-qt: + runs-on: macos-latest + needs: get-info + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup latest Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest + + - name: Install MoltenVK and Setup Qt + run: | + arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + arch -x86_64 /usr/local/bin/brew install molten-vk + - uses: jurplel/install-qt-action@v4 + with: + version: 6.7.3 + host: mac + target: desktop + arch: clang_64 + archives: qtbase qttools + modules: qtmultimedia + + - 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 + create-symlink: true + key: ${{env.cache-name}}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + variant: sccache + + - name: Configure CMake + run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu) + + - name: Package and Upload macOS Qt artifact + run: | + mkdir upload + mv ${{github.workspace}}/build/shadps4.app upload + macdeployqt upload/shadps4.app + tar cf shadps4-macos-qt.tar.gz -C upload . + - uses: actions/upload-artifact@v4 + with: + name: shadps4-macos-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: shadps4-macos-qt.tar.gz + + linux-sdl: + 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 clang build-essential libasound2-dev libpulse-dev libopenal-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_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + + - name: Package and Upload Linux(ubuntu64) SDL artifact + run: | + ls -la ${{ github.workspace }}/build/shadps4 + + - uses: actions/upload-artifact@v4 + with: + name: shadps4-ubuntu64-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: ${{ github.workspace }}/build/shadps4 + + - name: Run AppImage packaging script + run: ./.github/linux-appimage-sdl.sh + + - name: Package and Upload Linux SDL artifact + run: | + tar cf shadps4-linux-sdl.tar.gz -C ${{github.workspace}}/build shadps4 + - uses: actions/upload-artifact@v4 + with: + name: shadps4-linux-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: Shadps4-sdl.AppImage + + linux-qt: + 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 clang build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-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_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel3 + + - name: Run AppImage packaging script + run: ./.github/linux-appimage-qt.sh + + - name: Package and Upload Linux Qt artifact + run: | + tar cf shadps4-linux-qt.tar.gz -C ${{github.workspace}}/build shadps4 + - uses: actions/upload-artifact@v4 + with: + name: shadps4-linux-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} + path: Shadps4-qt.AppImage + + 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] + runs-on: ubuntu-latest + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Compress individual directories (without parent directory) + run: | + cd ./artifacts + for dir in */; do + if [ -d "$dir" ]; then + dir_name=${dir%/} + echo "Creating zip for $dir_name" + (cd "$dir_name" && zip -r "../${dir_name}.zip" .) + fi + done + + - name: Get latest release information + id: get_latest_release + env: + GITHUB_TOKEN: ${{ secrets.SHADPS4_TOKEN_REPO }} + run: | + api_url="https://api.github.com/repos/${{ github.repository }}" + latest_release_info=$(curl -H "Authorization: token $GITHUB_TOKEN" "$api_url/releases/latest") + echo "last_release_tag=$(echo "$latest_release_info" | jq -r '.tag_name')" >> $GITHUB_ENV + + - name: Create Pre-Release on GitHub + id: create_release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.SHADPS4_TOKEN_REPO }} + name: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}" + tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}" + draft: false + prerelease: true + body: "Full Changelog: [${{ env.last_release_tag }}...${{ needs.get-info.outputs.shorthash }}](https://github.com/shadps4-emu/shadPS4/compare/${{ env.last_release_tag }}...${{ needs.get-info.outputs.shorthash }})" + artifacts: ./artifacts/*.zip + + - name: Get current pre-release information + env: + GITHUB_TOKEN: ${{ secrets.SHADPS4_TOKEN_REPO }} + run: | + api_url="https://api.github.com/repos/${{ github.repository }}/releases" + + # Get all releases (sorted by date) + releases=$(curl -H "Authorization: token $GITHUB_TOKEN" "$api_url") + + # Capture the most recent pre-release (assuming the first one is the latest) + current_release=$(echo "$releases" | jq -c '.[] | select(.prerelease == true) | .published_at' | sort -r | head -n 1) + + # Remove extra quotes from captured date + current_release=$(echo $current_release | tr -d '"') + + # Export the current published_at to be available for the next step + echo "CURRENT_PUBLISHED_AT=$current_release" >> $GITHUB_ENV + + - name: Delete old pre-releases and tags + env: + GITHUB_TOKEN: ${{ secrets.SHADPS4_TOKEN_REPO }} + run: | + api_url="https://api.github.com/repos/${{ github.repository }}/releases" + + # Get current pre-releases + releases=$(curl -H "Authorization: token $GITHUB_TOKEN" "$api_url") + + # Remove extra quotes from captured date + CURRENT_PUBLISHED_AT=$(echo $CURRENT_PUBLISHED_AT | tr -d '"') + + # Convert CURRENT_PUBLISHED_AT para timestamp Unix + current_published_ts=$(date -d "$CURRENT_PUBLISHED_AT" +%s) + + # Identify pre-releases + echo "$releases" | jq -c '.[] | select(.prerelease == true)' | while read -r release; do + release_date=$(echo "$release" | jq -r '.published_at') + release_id=$(echo "$release" | jq -r '.id') + release_tag=$(echo "$release" | jq -r '.tag_name') + + # Remove extra quotes from captured date + release_date=$(echo $release_date | tr -d '"') + + # Convert release_date para timestamp Unix + release_date_ts=$(date -d "$release_date" +%s) + + # Compare timestamps and delete old pre-releases + if [[ "$release_date_ts" -lt "$current_published_ts" ]]; then + echo "Deleting old pre-release: $release_id from $release_date with tag: $release_tag" + # Delete the pre-release + curl -X DELETE -H "Authorization: token $GITHUB_TOKEN" "$api_url/$release_id" + # Delete the tag + curl -X DELETE -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/${{ github.repository }}/git/refs/tags/$release_tag" + else + echo "Skipping pre-release: $release_id (newer or same date)" + fi + done diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 123c7f3f8..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-FileCopyrightText: 2021 yuzu Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: Reuse - -on: - push: - branches: [ main ] - tags: [ "*" ] - pull_request: - branches: [ main ] -jobs: - reuse: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: fsfe/reuse-action@v4 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml deleted file mode 100644 index b9887ccac..000000000 --- a/.github/workflows/format.yml +++ /dev/null @@ -1,28 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: Clang Format - -on: - push: - branches: [ "*" ] - pull_request: - branches: [ main ] - -jobs: - clang-format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install - run: | - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main' - sudo apt update - sudo apt install clang-format-17 - - name: Build - env: - COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} - run: ./.ci/clang-format.sh \ No newline at end of file diff --git a/.github/workflows/linux-qt.yml b/.github/workflows/linux-qt.yml deleted file mode 100644 index 5611ae50f..000000000 --- a/.github/workflows/linux-qt.yml +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: Linux-Qt - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install misc packages - run: > - sudo apt-get update && sudo apt install libx11-dev libxext-dev libwayland-dev libfuse2 clang build-essential qt6-base-dev - - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - - - name: Run AppImage packaging script - run: ./.github/linux-appimage-qt.sh - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-linux-qt - path: Shadps4-qt.AppImage \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index ef77a16c8..000000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: Linux - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install misc packages - run: > - sudo apt-get update && sudo apt install libx11-dev libxext-dev libwayland-dev libfuse2 clang build-essential - - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-ubuntu64 - path: | - ${{github.workspace}}/build/shadps4 - - - name: Run AppImage packaging script - run: ./.github/linux-appimage-sdl.sh - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-sdl-appimage - path: Shadps4-sdl.AppImage diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml deleted file mode 100644 index 4b3672dff..000000000 --- a/.github/workflows/macos-qt.yml +++ /dev/null @@ -1,60 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: macOS-Qt - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Setup latest Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest - - - name: Install MoltenVK - run: | - arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - arch -x86_64 /usr/local/bin/brew install molten-vk - - - name: Setup Qt - uses: jurplel/install-qt-action@v4 - with: - version: 6.7.2 - host: mac - target: desktop - arch: clang_64 - archives: qtbase - - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu) - - - name: Package - run: | - mkdir upload - mv ${{github.workspace}}/build/shadps4.app upload - macdeployqt upload/shadps4.app - tar cf shadps4-macos-qt.tar.gz -C upload . - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-macos-qt - path: shadps4-macos-qt.tar.gz diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml deleted file mode 100644 index 1a2a6eff6..000000000 --- a/.github/workflows/macos.yml +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: macOS - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Setup latest Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest - - - name: Install MoltenVK - run: | - arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - arch -x86_64 /usr/local/bin/brew install molten-vk - - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu) - - - name: Package - run: | - mkdir upload - mv ${{github.workspace}}/build/shadps4 upload - cp $(arch -x86_64 /usr/local/bin/brew --prefix)/opt/molten-vk/lib/libMoltenVK.dylib upload - install_name_tool -add_rpath "@loader_path" upload/shadps4 - tar cf shadps4-macos-sdl.tar.gz -C upload . - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-macos-sdl - path: shadps4-macos-sdl.tar.gz diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml deleted file mode 100644 index 06a16eb5b..000000000 --- a/.github/workflows/windows-qt.yml +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: Windows-Qt - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Setup Qt - uses: jurplel/install-qt-action@v4 - with: - version: 6.7.2 - host: windows - target: desktop - arch: win64_msvc2019_64 - archives: qtbase - - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T ClangCL -DENABLE_QT_GUI=ON - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - - - name: Deploy - run: | - mkdir upload - move build/Release/shadPS4.exe upload - windeployqt --dir upload upload/shadPS4.exe - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-win64-qt - path: upload diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 499124863..000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -name: Windows - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T ClangCL - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - - - name: Upload executable - uses: actions/upload-artifact@v4 - with: - name: shadps4-win64-sdl - path: | - ${{github.workspace}}/build/Release/shadPS4.exe diff --git a/.gitignore b/.gitignore index 2a3145085..9abc4aae4 100644 --- a/.gitignore +++ b/.gitignore @@ -387,6 +387,8 @@ FodyWeavers.xsd !.vscode/launch.json !.vscode/extensions.json *.code-workspace +/CMakeUserPresets.json +/compile_commands.json # Local History for Visual Studio Code .history/ @@ -409,3 +411,6 @@ FodyWeavers.xsd /out/* /third-party/out/* /src/common/scm_rev.cpp + +# for macOS +**/.DS_Store diff --git a/.gitmodules b/.gitmodules index 949965866..88635e645 100644 --- a/.gitmodules +++ b/.gitmodules @@ -81,4 +81,21 @@ [submodule "externals/ffmpeg-core"] path = externals/ffmpeg-core url = https://github.com/shadps4-emu/ext-ffmpeg-core.git + shallow = true +[submodule "externals/half"] + path = externals/half + url = https://github.com/ROCm/half.git + shallow = true +[submodule "externals/dear_imgui"] + path = externals/dear_imgui + url = https://github.com/shadps4-emu/ext-imgui.git + shallow = true + branch = docking +[submodule "externals/pugixml"] + path = externals/pugixml + url = https://github.com/zeux/pugixml.git + shallow = true +[submodule "externals/discord-rpc"] + path = externals/discord-rpc + url = https://github.com/shadps4-emu/ext-discord-rpc.git shallow = true \ No newline at end of file diff --git a/.reuse/dep5 b/.reuse/dep5 deleted file mode 100644 index 0140c0c02..000000000 --- a/.reuse/dep5 +++ /dev/null @@ -1,60 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Comment: It is best to use this file to record copyright information about - generated, binary and third party files - -Files: CMakeSettings.json - .github/shadps4.desktop - .github/shadps4.png - .gitmodules - documents/changelog.txt - documents/readme.txt - documents/Quickstart/1.png - documents/Quickstart/2.png - documents/Screenshots/Bloodborne.png - documents/Screenshots/Sonic Mania.png - documents/Screenshots/Undertale.png - documents/Screenshots/We are DOOMED.png - scripts/ps4_names.txt - src/images/about_icon.png - src/images/controller_icon.png - src/images/exit_icon.png - src/images/file_icon.png - src/images/flag_china.png - src/images/flag_eu.png - src/images/flag_jp.png - src/images/flag_unk.png - src/images/flag_us.png - src/images/flag_world.png - src/images/folder_icon.png - src/images/grid_icon.png - src/images/iconsize_icon.png - src/images/list_icon.png - src/images/list_mode_icon.png - src/images/pause_icon.png - src/images/play_icon.png - src/images/refresh_icon.png - src/images/settings_icon.png - src/images/stop_icon.png - src/images/shadPS4.icns - src/images/shadps4.ico - src/images/themes_icon.png - src/shadps4.qrc - src/shadps4.rc -Copyright: shadPS4 Emulator Project -License: GPL-2.0-or-later - -Files: externals/cmake-modules/* -Copyright: 2009-2010 Iowa State University -License: BSL-1.0 - -Files: externals/renderdoc/* -Copyright: 2019-2024 Baldur Karlsson -License: MIT - -Files: externals/stb_image.h -Copyright: 2017 Sean Barrett -License: MIT - -Files: externals/tracy/* -Copyright: 2017-2024 Bartosz Taudul -License: BSD-3-Clause diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 8e349e588..9cfc0d8ef --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) if(APPLE) enable_language(OBJC) - set(CMAKE_OSX_DEPLOYMENT_TARGET 11) + set(CMAKE_OSX_DEPLOYMENT_TARGET 14) endif() if (NOT CMAKE_BUILD_TYPE) @@ -17,8 +17,47 @@ endif() project(shadPS4) +# Forcing PIE makes sure that the base address is high enough so that it doesn't clash with the PS4 memory. +if(UNIX AND NOT APPLE) + set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) + + # check PIE support at link time + include(CheckPIESupported) + check_pie_supported(OUTPUT_VARIABLE pie_check LANGUAGES C CXX) + if(NOT CMAKE_C_LINK_PIE_SUPPORTED OR NOT CMAKE_CXX_LINK_PIE_SUPPORTED) + message(WARNING "PIE is not supported at link time: ${pie_check}") + endif() +endif() + option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF) +# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR. +if (APPLE AND CMAKE_OSX_ARCHITECTURES) + set(BASE_ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}") +else() + set(BASE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}") +endif() + +# Next, match common architecture strings down to a known common value. +if (BASE_ARCHITECTURE MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + set(ARCHITECTURE "x86_64") +elseif (BASE_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)") + set(ARCHITECTURE "arm64") +else() + message(FATAL_ERROR "Unsupported CPU architecture: ${BASE_ARCHITECTURE}") +endif() + +if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + # Exclude ARM homebrew path to avoid conflicts when cross compiling. + list(APPEND CMAKE_IGNORE_PREFIX_PATH "/opt/homebrew") + + # Need to reconfigure pkg-config to use the right architecture library paths. + # It's not ideal to override these but otherwise the build breaks just by having pkg-config installed. + set(ENV{PKG_CONFIG_DIR} "") + set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig:${CMAKE_SYSROOT}/usr/local/lib/pkgconfig:${CMAKE_SYSROOT}/usr/local/share/pkgconfig") + set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT}) +endif() + # This function should be passed a list of all files in a target. It will automatically generate file groups # following the directory hierarchy, so that the layout of the files in IDEs matches the one in the filesystem. function(create_target_directory_groups target_name) @@ -62,14 +101,15 @@ include(GetGitRevisionDescription) get_git_head_revision(GIT_REF_SPEC GIT_REV) 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) find_package(Boost 1.84.0 CONFIG) -find_package(cryptopp 8.9.0 MODULE) find_package(FFmpeg 5.1.2 MODULE) -find_package(fmt 10.2.1 CONFIG) +find_package(fmt 10.2.0 CONFIG) find_package(glslang 14.2.0 CONFIG) +find_package(half 1.12.0 MODULE) find_package(magic_enum 0.9.6 CONFIG) find_package(RenderDoc 1.6.0 MODULE) find_package(SDL3 3.1.2 CONFIG) @@ -79,8 +119,13 @@ find_package(VulkanHeaders 1.3.289 CONFIG) find_package(VulkanMemoryAllocator 3.1.0 CONFIG) find_package(xbyak 7.07 CONFIG) find_package(xxHash 0.8.2 MODULE) -find_package(zlib-ng 2.2.0 MODULE) -find_package(Zydis 4.1.0 CONFIG) +find_package(zlib-ng 2.1.7 MODULE) +find_package(Zydis 5.0.0 CONFIG) +find_package(pugixml 1.14 CONFIG) + +if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC) + find_package(cryptopp 8.9.0 MODULE) +endif() if (APPLE) find_package(date 3.0.1 CONFIG) @@ -92,10 +137,6 @@ check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMED if(HAVE_PTHREAD_MUTEX_TIMEDLOCK OR WIN32) add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK) endif() -check_symbol_exists(sem_timedwait "semaphore.h" HAVE_SEM_TIMEDWAIT) -if(HAVE_SEM_TIMEDWAIT OR WIN32) - add_compile_options(-DHAVE_SEM_TIMEDWAIT) -endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") # libc++ requires -fexperimental-library to enable std::jthread and std::stop_token support. @@ -110,11 +151,27 @@ add_subdirectory(externals) include_directories(src) if(ENABLE_QT_GUI) - find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent) + find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia) qt_standard_project_setup() set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) + + set(QT_TRANSLATIONS "${PROJECT_SOURCE_DIR}/src/qt_gui/translations") + file(GLOB_RECURSE TRANSLATIONS_TS ${QT_TRANSLATIONS}/*.ts) + + set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations") + qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS}) + + set(TRANSLATIONS_QRC ${CMAKE_CURRENT_BINARY_DIR}/translations/translations.qrc) + file(WRITE ${TRANSLATIONS_QRC} "\n") + foreach (QM ${TRANSLATIONS_QM}) + get_filename_component(QM_FILE ${QM} NAME) + file(APPEND ${TRANSLATIONS_QRC} "${QM_FILE}\n") + endforeach (QM) + file(APPEND ${TRANSLATIONS_QRC} "") + + qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC}) endif() set(AUDIO_CORE src/audio_core/sdl_audio.cpp @@ -133,9 +190,10 @@ set(AUDIO_LIB src/core/libraries/audio/audioin.cpp set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp src/core/libraries/gnmdriver/gnmdriver.h + src/core/libraries/gnmdriver/gnm_error.h ) -set(KERNEL_LIB +set(KERNEL_LIB src/core/libraries/kernel/event_flag/event_flag.cpp src/core/libraries/kernel/event_flag/event_flag.h src/core/libraries/kernel/event_flag/event_flag_obj.cpp @@ -167,6 +225,9 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp src/core/libraries/network/net.cpp src/core/libraries/network/netctl.cpp src/core/libraries/network/netctl.h + src/core/libraries/network/net_ctl_obj.cpp + src/core/libraries/network/net_ctl_obj.h + src/core/libraries/network/net_ctl_codes.h src/core/libraries/network/net.h src/core/libraries/network/ssl.cpp src/core/libraries/network/ssl.h @@ -176,13 +237,21 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/system/commondialog.h src/core/libraries/system/msgdialog.cpp src/core/libraries/system/msgdialog.h + src/core/libraries/system/msgdialog_ui.cpp src/core/libraries/system/posix.cpp src/core/libraries/system/posix.h - src/core/libraries/save_data/error_codes.h + src/core/libraries/save_data/save_backup.cpp + src/core/libraries/save_data/save_backup.h + src/core/libraries/save_data/save_instance.cpp + src/core/libraries/save_data/save_instance.h + src/core/libraries/save_data/save_memory.cpp + src/core/libraries/save_data/save_memory.h src/core/libraries/save_data/savedata.cpp src/core/libraries/save_data/savedata.h - src/core/libraries/system/savedatadialog.cpp - src/core/libraries/system/savedatadialog.h + src/core/libraries/save_data/dialog/savedatadialog.cpp + src/core/libraries/save_data/dialog/savedatadialog.h + src/core/libraries/save_data/dialog/savedatadialog_ui.cpp + src/core/libraries/save_data/dialog/savedatadialog_ui.h src/core/libraries/system/sysmodule.cpp src/core/libraries/system/sysmodule.h src/core/libraries/system/systemservice.cpp @@ -214,6 +283,20 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/ngs2/ngs2_error.h src/core/libraries/ngs2/ngs2_impl.cpp src/core/libraries/ngs2/ngs2_impl.h + src/core/libraries/ajm/ajm_error.h + src/core/libraries/audio3d/audio3d.cpp + src/core/libraries/audio3d/audio3d.h + src/core/libraries/audio3d/audio3d_error.h + src/core/libraries/audio3d/audio3d_impl.cpp + src/core/libraries/audio3d/audio3d_impl.h + src/core/libraries/ime/ime.cpp + src/core/libraries/ime/ime.h + src/core/libraries/game_live_streaming/gamelivestreaming.cpp + src/core/libraries/game_live_streaming/gamelivestreaming.h + src/core/libraries/remote_play/remoteplay.cpp + src/core/libraries/remote_play/remoteplay.h + src/core/libraries/share_play/shareplay.cpp + src/core/libraries/share_play/shareplay.h ) set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h @@ -229,6 +312,8 @@ set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp set(DIALOGS_LIB src/core/libraries/dialogs/error_dialog.cpp src/core/libraries/dialogs/error_dialog.h + src/core/libraries/dialogs/ime_dialog_ui.cpp + src/core/libraries/dialogs/ime_dialog_ui.h src/core/libraries/dialogs/ime_dialog.cpp src/core/libraries/dialogs/ime_dialog.h src/core/libraries/dialogs/error_codes.h @@ -249,24 +334,54 @@ set(PLAYGO_LIB src/core/libraries/playgo/playgo.cpp set(RANDOM_LIB src/core/libraries/random/random.cpp src/core/libraries/random/random.h + src/core/libraries/random/random_error.h ) set(USBD_LIB src/core/libraries/usbd/usbd.cpp src/core/libraries/usbd/usbd.h ) +set(FIBER_LIB src/core/libraries/fiber/fiber.cpp + src/core/libraries/fiber/fiber.h +) + set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp src/core/libraries/np_manager/np_manager.h src/core/libraries/np_score/np_score.cpp src/core/libraries/np_score/np_score.h src/core/libraries/np_trophy/np_trophy.cpp src/core/libraries/np_trophy/np_trophy.h + src/core/libraries/np_trophy/trophy_ui.cpp + src/core/libraries/np_trophy/trophy_ui.h ) set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp src/core/libraries/screenshot/screenshot.h ) +set(DEV_TOOLS src/core/devtools/layer.cpp + src/core/devtools/layer.h + src/core/devtools/options.cpp + src/core/devtools/options.h + src/core/devtools/gcn/gcn_context_regs.cpp + src/core/devtools/gcn/gcn_op_names.cpp + src/core/devtools/gcn/gcn_shader_regs.cpp + src/core/devtools/widget/cmd_list.cpp + src/core/devtools/widget/cmd_list.h + src/core/devtools/widget/common.h + src/core/devtools/widget/frame_dump.cpp + src/core/devtools/widget/frame_dump.h + src/core/devtools/widget/frame_graph.cpp + src/core/devtools/widget/frame_graph.h + src/core/devtools/widget/imgui_memory_editor.h + src/core/devtools/widget/reg_popup.cpp + src/core/devtools/widget/reg_popup.h + src/core/devtools/widget/reg_view.cpp + src/core/devtools/widget/reg_view.h + src/core/devtools/widget/text_editor.cpp + src/core/devtools/widget/text_editor.h +) + set(COMMON src/common/logging/backend.cpp src/common/logging/backend.h src/common/logging/filter.cpp @@ -278,6 +393,7 @@ set(COMMON src/common/logging/backend.cpp src/common/logging/text_formatter.h src/common/logging/types.h src/common/alignment.h + src/common/arch.h src/common/assert.cpp src/common/assert.h src/common/bit_field.h @@ -285,9 +401,13 @@ set(COMMON src/common/logging/backend.cpp src/common/concepts.h src/common/config.cpp src/common/config.h + src/common/cstring.h src/common/debug.h - src/common/disassembler.cpp - src/common/disassembler.h + src/common/decoder.cpp + src/common/decoder.h + src/common/discord_rpc_handler.cpp + src/common/discord_rpc_handler.h + src/common/elf_info.h src/common/endian.h src/common/enum.h src/common/io_file.cpp @@ -295,6 +415,7 @@ set(COMMON src/common/logging/backend.cpp src/common/error.cpp src/common/error.h src/common/scope_exit.h + src/common/fixed_value.h src/common/func_traits.h src/common/native_clock.cpp src/common/native_clock.h @@ -304,6 +425,8 @@ set(COMMON src/common/logging/backend.cpp src/common/polyfill_thread.h src/common/rdtsc.cpp src/common/rdtsc.h + src/common/signal_context.h + src/common/signal_context.cpp src/common/singleton.h src/common/slot_vector.h src/common/string_util.cpp @@ -316,6 +439,10 @@ set(COMMON src/common/logging/backend.cpp src/common/version.h src/common/ntapi.h src/common/ntapi.cpp + src/common/number_utils.h + src/common/number_utils.cpp + src/common/memory_patcher.h + src/common/memory_patcher.cpp src/common/scm_rev.cpp src/common/scm_rev.h ) @@ -326,10 +453,8 @@ set(CORE src/core/aerolib/stubs.cpp src/core/aerolib/aerolib.h src/core/address_space.cpp src/core/address_space.h - src/core/cpu_patches.cpp - src/core/cpu_patches.h src/core/crypto/crypto.cpp - src/core/crypto/crypto.h + src/core/crypto/crypto.h src/core/crypto/keys.h src/core/file_format/pfs.h src/core/file_format/pkg.cpp @@ -354,7 +479,7 @@ set(CORE src/core/aerolib/stubs.cpp src/core/loader/elf.h src/core/loader/symbols_resolver.h src/core/loader/symbols_resolver.cpp - src/core/libraries/error_codes.h + src/core/libraries/error_codes.h src/core/libraries/libs.h src/core/libraries/libs.cpp ${AUDIO_LIB} @@ -372,6 +497,10 @@ set(CORE src/core/aerolib/stubs.cpp ${USBD_LIB} ${MISC_LIBS} ${DIALOGS_LIB} + ${FIBER_LIB} + ${DEV_TOOLS} + src/core/debug_state.cpp + src/core/debug_state.h src/core/linker.cpp src/core/linker.h src/core/memory.cpp @@ -379,17 +508,29 @@ set(CORE src/core/aerolib/stubs.cpp src/core/module.cpp src/core/module.h src/core/platform.h + src/core/signals.cpp + src/core/signals.h src/core/tls.cpp src/core/tls.h src/core/virtual_memory.cpp src/core/virtual_memory.h ) +if (ARCHITECTURE STREQUAL "x86_64") + set(CORE ${CORE} + src/core/cpu_patches.cpp + src/core/cpu_patches.h) +endif() + set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/profile.h src/shader_recompiler/recompiler.cpp src/shader_recompiler/recompiler.h + src/shader_recompiler/info.h + src/shader_recompiler/params.h src/shader_recompiler/runtime_info.h + src/shader_recompiler/specialization.h + src/shader_recompiler/backend/bindings.h src/shader_recompiler/backend/spirv/emit_spirv.cpp src/shader_recompiler/backend/spirv/emit_spirv.h src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -413,6 +554,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/frontend/translate/data_share.cpp src/shader_recompiler/frontend/translate/export.cpp src/shader_recompiler/frontend/translate/scalar_alu.cpp + src/shader_recompiler/frontend/translate/scalar_flow.cpp src/shader_recompiler/frontend/translate/scalar_memory.cpp src/shader_recompiler/frontend/translate/translate.cpp src/shader_recompiler/frontend/translate/translate.h @@ -421,6 +563,8 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/frontend/translate/vector_memory.cpp src/shader_recompiler/frontend/control_flow_graph.cpp src/shader_recompiler/frontend/control_flow_graph.h + src/shader_recompiler/frontend/copy_shader.cpp + src/shader_recompiler/frontend/copy_shader.h src/shader_recompiler/frontend/decode.cpp src/shader_recompiler/frontend/decode.h src/shader_recompiler/frontend/fetch_shader.cpp @@ -431,12 +575,13 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h src/shader_recompiler/frontend/opcodes.h src/shader_recompiler/frontend/structured_control_flow.cpp src/shader_recompiler/frontend/structured_control_flow.h - src/shader_recompiler/ir/passes/constant_propogation_pass.cpp + src/shader_recompiler/ir/passes/constant_propagation_pass.cpp src/shader_recompiler/ir/passes/dead_code_elimination_pass.cpp src/shader_recompiler/ir/passes/identity_removal_pass.cpp src/shader_recompiler/ir/passes/ir_passes.h src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp src/shader_recompiler/ir/passes/resource_tracking_pass.cpp + src/shader_recompiler/ir/passes/ring_access_elimination.cpp src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp src/shader_recompiler/ir/abstract_syntax_list.h @@ -469,6 +614,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/amdgpu/pm4_cmds.h src/video_core/amdgpu/pm4_opcodes.h src/video_core/amdgpu/resource.h + src/video_core/amdgpu/types.h + src/video_core/amdgpu/default_context.cpp src/video_core/buffer_cache/buffer.cpp src/video_core/buffer_cache/buffer.h src/video_core/buffer_cache/buffer_cache.cpp @@ -494,6 +641,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/renderer_vulkan/vk_master_semaphore.h src/video_core/renderer_vulkan/vk_pipeline_cache.cpp src/video_core/renderer_vulkan/vk_pipeline_cache.h + src/video_core/renderer_vulkan/vk_pipeline_common.cpp + src/video_core/renderer_vulkan/vk_pipeline_common.h src/video_core/renderer_vulkan/vk_platform.cpp src/video_core/renderer_vulkan/vk_platform.h src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -519,6 +668,7 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/texture_cache/tile_manager.cpp src/video_core/texture_cache/tile_manager.h src/video_core/texture_cache/types.h + src/video_core/texture_cache/host_compatibility.h src/video_core/page_manager.cpp src/video_core/page_manager.h src/video_core/multi_level_page_table.h @@ -526,6 +676,20 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/renderdoc.h ) +set(IMGUI src/imgui/imgui_config.h + src/imgui/imgui_layer.h + src/imgui/imgui_std.h + src/imgui/imgui_texture.h + src/imgui/renderer/imgui_core.cpp + src/imgui/renderer/imgui_core.h + src/imgui/renderer/imgui_impl_sdl3.cpp + src/imgui/renderer/imgui_impl_sdl3.h + src/imgui/renderer/imgui_impl_vulkan.cpp + src/imgui/renderer/imgui_impl_vulkan.h + src/imgui/renderer/texture_manager.cpp + src/imgui/renderer/texture_manager.h +) + set(INPUT src/input/controller.cpp src/input/controller.h ) @@ -544,6 +708,12 @@ qt_add_resources(RESOURCE_FILES src/shadps4.qrc) set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/about_dialog.h src/qt_gui/about_dialog.ui + src/qt_gui/background_music_player.cpp + src/qt_gui/background_music_player.h + src/qt_gui/cheats_patches.cpp + src/qt_gui/cheats_patches.h + src/qt_gui/check_update.cpp + src/qt_gui/check_update.h src/qt_gui/main_window_ui.h src/qt_gui/main_window.cpp src/qt_gui/main_window.h @@ -557,6 +727,8 @@ set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/game_grid_frame.h src/qt_gui/game_install_dialog.cpp src/qt_gui/game_install_dialog.h + src/qt_gui/install_dir_select.cpp + src/qt_gui/install_dir_select.h src/qt_gui/pkg_viewer.cpp src/qt_gui/pkg_viewer.h src/qt_gui/trophy_viewer.cpp @@ -571,12 +743,14 @@ set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/main.cpp ${EMULATOR} ${RESOURCE_FILES} + ${TRANSLATIONS} ) endif() if (ENABLE_QT_GUI) qt_add_executable(shadps4 ${AUDIO_CORE} + ${IMGUI} ${INPUT} ${QT_GUI} ${COMMON} @@ -589,6 +763,7 @@ if (ENABLE_QT_GUI) else() add_executable(shadps4 ${AUDIO_CORE} + ${IMGUI} ${INPUT} ${COMMON} ${CORE} @@ -605,16 +780,26 @@ endif() create_target_directory_groups(shadps4) -target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg) -target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3) +target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half) +target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3 pugixml::pugixml) + +target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h") +target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h") if (APPLE) - # Reserve system-managed memory space. - target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x400000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x10000000000) + option(USE_SYSTEM_VULKAN_LOADER "Enables using the system Vulkan loader instead of directly linking with MoltenVK. Useful for loading validation layers." OFF) + if (USE_SYSTEM_VULKAN_LOADER) + target_compile_definitions(shadps4 PRIVATE USE_SYSTEM_VULKAN_LOADER=1) + else() + # Link MoltenVK for Vulkan support + find_library(MOLTENVK MoltenVK REQUIRED) + target_link_libraries(shadps4 PRIVATE ${MOLTENVK}) + endif() - # Link MoltenVK for Vulkan support - find_library(MOLTENVK MoltenVK REQUIRED) - target_link_libraries(shadps4 PRIVATE ${MOLTENVK}) + if (ARCHITECTURE STREQUAL "x86_64") + # Reserve system-managed memory space. + target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x20000000000) + endif() # Replacement for std::chrono::time_zone target_link_libraries(shadps4 PRIVATE date::date-tz) @@ -631,7 +816,8 @@ else() endif() if (ENABLE_QT_GUI) - target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent) + target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia) + add_definitions(-DENABLE_QT_GUI) endif() if (WIN32) @@ -686,6 +872,11 @@ add_subdirectory(${HOST_SHADERS_INCLUDE}) add_dependencies(shadps4 host_shaders) target_include_directories(shadps4 PRIVATE ${HOST_SHADERS_INCLUDE}) +# ImGui resources +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/imgui/renderer) +add_dependencies(shadps4 ImGui_Resources) +target_include_directories(shadps4 PRIVATE ${IMGUI_RESOURCES_INCLUDE}) + if (ENABLE_QT_GUI) set_target_properties(shadps4 PROPERTIES # WIN32_EXECUTABLE ON @@ -695,3 +886,21 @@ if (ENABLE_QT_GUI) set_source_files_properties(src/images/shadPS4.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) endif() + +if (UNIX AND NOT APPLE) + if (ENABLE_QT_GUI) + find_package(OpenSSL REQUIRED) + target_link_libraries(shadps4 PRIVATE ${OPENSSL_LIBRARIES}) + endif() +endif() + +# Discord RPC +target_link_libraries(shadps4 PRIVATE discord-rpc) + +# Install rules +install(TARGETS shadps4 BUNDLE DESTINATION .) + +if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux") + install(FILES ".github/shadps4.desktop" DESTINATION "share/applications") + install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps") +endif() diff --git a/CMakeSettings.json b/CMakeSettings.json index 9242e0808..bb522fcfc 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -9,7 +9,8 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", - "inheritEnvironments": [ "clang_cl_x64_x64" ] + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "intelliSenseMode": "windows-clang-x64" }, { "name": "x64-Clang-Debug", @@ -20,7 +21,8 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", - "inheritEnvironments": [ "clang_cl_x64_x64" ] + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "intelliSenseMode": "windows-clang-x64" }, { "name": "x64-Clang-RelWithDebInfo", @@ -31,7 +33,8 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", - "inheritEnvironments": [ "clang_cl_x64_x64" ] + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "intelliSenseMode": "windows-clang-x64" } ] } \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a428598c7..cdda7c8c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ enum class SomeEnum { * Note that the asterisks are indented by one space to align to the first line. */ struct Position { - // Always intitialize member variables! + // Always initialize member variables! int x{}; int y{}; }; diff --git a/LICENSES/OFL-1.1.txt b/LICENSES/OFL-1.1.txt new file mode 100644 index 000000000..6fe84ee21 --- /dev/null +++ b/LICENSES/OFL-1.1.txt @@ -0,0 +1,43 @@ +SIL OPEN FONT LICENSE + +Version 1.1 - 26 February 2007 + +PREAMBLE + +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS + +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION + +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/README.md b/README.md index 542acca9e..18e69546c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ SPDX-License-Identifier: GPL-2.0-or-later

- + @@ -26,33 +26,34 @@ SPDX-License-Identifier: GPL-2.0-or-later

- - - - + + + +

-# shadPS4 +# General information -shadPS4 is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++ +**shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++. -If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/Quickstart.md). - -To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility). - -To discuss shadPS4 development or suggest ideas, join the [**Discord server**](https://discord.gg/MyZRaBngxA). - -To get the latest news, go to our [**X (twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/). +If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/Quickstart.md).\ +To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).\ +To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\ +To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).\ +For those who'd like to donate to the project, we now have a [**Kofi page**](https://ko-fi.com/shadps4)! # Status -In development, small games are working like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4), [**Dysmantle**](https://youtu.be/b9xzhLBdESE) and others... +> [!IMPORTANT] +> shadPS4 is early in development, don't expect a flawless experience. + +Currently, the emulator can successfully run games like [**Bloodborne**](https://www.youtube.com/watch?v=wC6s0avpQRE), [**Dark Souls Remastered**](https://www.youtube.com/watch?v=-3PA-Xwszts), [**Red Dead Redemption**](https://www.youtube.com/watch?v=Al7yz_5nLag) and many other games. # Why -The project started as a fun project. Due to limited free time, it will probably take a while before shadPS4 is able to run anything decent, but we're trying to make small, regular commits. +This project began as a fun project. Given our limited free time, it may take some time before shadPS4 can run more complex games, but we're committed to making small, regular updates. -# Build +# Building ## Windows @@ -62,42 +63,23 @@ Check the build instructions for [**Windows**](https://github.com/shadps4-emu/sh Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-linux.md). -## Build status +## macOS -
-Windows +Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-macos.md). -| Windows | Build status | -|--------|--------| -|Windows SDL Build|[![Windows-sdl](https://github.com/shadps4-emu/shadPS4/actions/workflows/windows.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/windows.yml) -|Windows Qt Build|[![Windows-qt](https://github.com/shadps4-emu/shadPS4/actions/workflows/windows-qt.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/windows-qt.yml) -
- -
-Linux - -| Linux | Build status | -|--------|--------| -|Linux SDL Build|[![Linux-sdl](https://github.com/shadps4-emu/shadPS4/actions/workflows/linux.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/linux.yml) -|Linux Qt Build|[![Linux-qt](https://github.com/shadps4-emu/shadPS4/actions/workflows/linux-qt.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/linux-qt.yml) -
- -
-macOS - -| macOS | Build status | -|--------|--------| -|macOS SDL Build|[![macOS-sdl](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos.yml) -|macOS Qt Build|[![macOS-qt](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos-qt.yml/badge.svg)](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos-qt.yml) -
+> [!IMPORTANT] +> macOS users need at least macOS 15 on Apple Silicon-based Mac devices and at least macOS 14 on Intel-based Mac devices. # Debugging and reporting issues -For more information on how to test, debug and report issues with the emulator or games, read the [Debugging documentation](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md). +For more information on how to test, debug and report issues with the emulator or games, read the [**Debugging documentation**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md). -# Keyboard Mapping +# Keyboard mapping -| Controller button | Keyboard | +> [!NOTE] +> Xbox and DualShock controllers work out of the box. + +| Controller button | Keyboard equivelant | |-------------|-------------| LEFT AXIS UP | W | LEFT AXIS DOWN | S | @@ -116,7 +98,7 @@ PAD DOWN | DOWN | PAD LEFT | LEFT | PAD RIGHT | RIGHT | OPTIONS | RETURN | -TOUCH PAD | SPACE | +BACK BUTTON / TOUCH PAD | SPACE | L1 | Q | R1 | U | L2 | E | @@ -137,8 +119,7 @@ Logo is done by [**Xphalnos**](https://github.com/Xphalnos) # Contributing -If you want to contribute, please look the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file. - +If you want to contribute, please look the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file.\ Open a PR and we'll check it :) # Contributors @@ -147,11 +128,19 @@ Open a PR and we'll check it :)
-# Sister Projects -- [**Panda3DS**](https://github.com/wheremyfoodat/Panda3DS): A multiplatform 3DS emulator from our co-author wheremyfoodat. +# Special Thanks + +A few noteworthy teams/projects who've helped us along the way are: + +- [**Panda3DS**](https://github.com/wheremyfoodat/Panda3DS): A multiplatform 3DS emulator from our co-author wheremyfoodat. They have been incredibly helpful in understanding and solving problems that came up from natively executing the x64 code of PS4 binaries + +- [**fpPS4**](https://github.com/red-prig/fpPS4): The fpPS4 team has assisted massively with understanding some of the more complex parts of the PS4 operating system and libraries, by helping with reverse engineering work and research. + +- **yuzu**: Our shader compiler has been designed with yuzu's Hades compiler as a blueprint. This allowed us to focus on the challenges of emulating a modern AMD GPU while having a high-quality optimizing shader compiler implementation as a base. + - [**hydra**](https://github.com/hydra-emu/hydra): A multisystem, multiplatform emulator (chip-8, GB, NES, N64) from Paris. # License -- [**GPL-2.0 license**](https://github.com/shadps4-emu/shadPS4/blob/main/LICENSE) \ No newline at end of file +- [**GPL-2.0 license**](https://github.com/shadps4-emu/shadPS4/blob/main/LICENSE) diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 000000000..e1a266030 --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,87 @@ +version = 1 + +[[annotations]] +path = [ + "REUSE.toml", + "CMakeSettings.json", + ".github/FUNDING.yml", + ".github/shadps4.desktop", + ".github/shadps4.png", + ".gitmodules", + "documents/changelog.txt", + "documents/Quickstart/2.png", + "documents/Screenshots/*", + "scripts/ps4_names.txt", + "src/images/about_icon.png", + "src/images/controller_icon.png", + "src/images/dump_icon.png", + "src/images/exit_icon.png", + "src/images/file_icon.png", + "src/images/flag_china.png", + "src/images/flag_eu.png", + "src/images/flag_jp.png", + "src/images/flag_unk.png", + "src/images/flag_us.png", + "src/images/flag_world.png", + "src/images/folder_icon.png", + "src/images/grid_icon.png", + "src/images/iconsize_icon.png", + "src/images/list_icon.png", + "src/images/list_mode_icon.png", + "src/images/pause_icon.png", + "src/images/play_icon.png", + "src/images/refresh_icon.png", + "src/images/settings_icon.png", + "src/images/stop_icon.png", + "src/images/shadPS4.icns", + "src/images/shadps4.ico", + "src/images/themes_icon.png", + "src/images/update_icon.png", + "src/shadps4.qrc", + "src/shadps4.rc", +] +precedence = "aggregate" +SPDX-FileCopyrightText = "shadPS4 Emulator Project" +SPDX-License-Identifier = "GPL-2.0-or-later" + +[[annotations]] +path = "externals/cmake-modules/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2009-2010 Iowa State University" +SPDX-License-Identifier = "BSL-1.0" + +[[annotations]] +path = "externals/renderdoc/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2019-2024 Baldur Karlsson" +SPDX-License-Identifier = "MIT" + +[[annotations]] +path = "externals/stb_image.h" +precedence = "aggregate" +SPDX-FileCopyrightText = "2017 Sean Barrett" +SPDX-License-Identifier = "MIT" + +[[annotations]] +path = "externals/tracy/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2017-2024 Bartosz Taudul " +SPDX-License-Identifier = "BSD-3-Clause" + +[[annotations]] +path = "src/imgui/renderer/fonts/NotoSansJP-Regular.ttf" +precedence = "aggregate" +SPDX-FileCopyrightText = "2012 Google Inc. All Rights Reserved." +SPDX-License-Identifier = "OFL-1.1" + +[[annotations]] +path = "src/imgui/renderer/fonts/ProggyVector-Regular.ttf" +precedence = "aggregate" +SPDX-FileCopyrightText = "Copyright (c) 2004, 2005 Tristan Grimmer" +SPDX-License-Identifier = "MIT" + +[[annotations]] +path = "externals/gcn/include/**" +SPDX-FileCopyrightText = "NONE" +SPDX-License-Identifier = "CC0-1.0" + diff --git a/cmake/Findhalf.cmake b/cmake/Findhalf.cmake new file mode 100644 index 000000000..f95a791df --- /dev/null +++ b/cmake/Findhalf.cmake @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +find_path(half_INCLUDE_DIR NAMES half.hpp PATH_SUFFIXES half) + +if (half_INCLUDE_DIR) + file(STRINGS "${half_INCLUDE_DIR}/half.hpp" _ver_line + REGEX "^// Version [0-9.]+$" + LIMIT_COUNT 1 + ) + string(REGEX MATCH "[0-9.]+" half_VERSION "${_ver_line}") + unset(_ver_line) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(half + REQUIRED_VARS half_INCLUDE_DIR + VERSION_VAR half_VERSION +) + +if (half_FOUND AND NOT TARGET half::half) + add_library(half::half INTERFACE IMPORTED) + set_target_properties(half::half PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${half_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced(half_INCLUDE_DIR) diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md index 4dd897d85..b2931e51e 100644 --- a/documents/Quickstart/Quickstart.md +++ b/documents/Quickstart/Quickstart.md @@ -7,21 +7,22 @@ SPDX-License-Identifier: GPL-2.0-or-later ## Summary -- [PC Requirements](#pc-requirements) - - [CPU](#cpu) - - [GPU](#gpu) - - [RAM](#ram) - - [OS](#os) -- [Have the latest WIP version](#have-the-latest-wip-version) -- [Install PKG files (Games and Updates)](#install-pkg-files) -- [Configure the emulator](#configure-the-emulator) +- [**PC Requirements**](#minimum-pc-requirements) + - [**CPU**](#cpu) + - [**GPU**](#gpu) + - [**RAM**](#ram) + - [**OS**](#os) +- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4) +- [**Install PKG files (Games and Updates)**](#install-pkg-files) +- [**Configure the emulator**](#configure-the-emulator) -## PC Requirements +## Minimum PC requirements ### CPU - A processor with at least 4 cores and 6 threads - Above 2.5 GHz frequency +- required support AVX2 extension or Rosetta 2 on ARM ### GPU @@ -37,45 +38,25 @@ SPDX-License-Identifier: GPL-2.0-or-later - Windows 10 or Ubuntu 22.04 -## How to run the latest Work-in-Progress builds of ShadPS4 +## How to run the latest Work-in-Progress builds of shadPS4 -1. Go to and make sure you are logged into your GitHub account (important!) -2. On the left side of the page, select your operating system of choice (the "**qt**" versions have a user interface, which is probably the one you want. The others are SDL versions, which can only be run via command line). ![image](https://github.com/user-attachments/assets/43f01bbf-236c-4d6d-98ac-f5a5badd4ce8) +1. Go to In the release identified as 'pre-release' click on the down arrow(Assets), select your operating system of choice (the "**qt**" versions have a user interface, which is probably the one you want. The others are SDL versions, which can only be run via command line). +![image](https://github.com/user-attachments/assets/af520c77-797c-41a0-8f67-d87f5de3e3df) -3. In the workflow list, select the latest entry with a green :white_check_mark: icon in front of it. (or the latest entry for whatever pull request you wish to test). ![image](https://github.com/user-attachments/assets/6365f407-867c-44ae-bf00-944f8d84a349) +2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder. -4. On the bottom of this page, select the name of the file, and it should start downloading. (If there is no file here, double check that you are indeed logged into a GitHub account, and that there is a green :white_check_mark: icon. ![image](https://github.com/user-attachments/assets/97924500-3911-4f90-ab63-ffae7e52700b) - -5. Once downloaded, extract to its own folder, and run ShadPS4's executable from the extracted folder. - -6. Upon first launch, ShadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that ShadPS4 can use to install your PKG files to. +3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that shadPS4 can use to install your PKG files to. ## Install PKG files To install PKG files (game and updates), you will need the Qt application (with UI). You will have to go to "File" then to "Install Packages (PKG)", a window will open then you will have to select the files. You can install multiple PKG files at once. Once finished, the game should appear in the application. - + ## Configure the emulator -You can configure the emulator by editing the `config.toml` file found in the `user` folder created after starting the application.\ -Some settings may be related to more technical development and debugging. For more information on those, see [Debugging](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration). +To configure the emulator, you can go through the interface and go to "settings". -Here's a list of configuration entries that are worth changing: - -- `[General]` - - - `Fullscreen`: Display the game in a full screen borderless window. - - - `logType`: Configures logging synchronization (`sync`/`async`) - - It can be beneficial to set this to `sync` in order for the log to accurately maintain message order, at the cost of performance. - - Use when sending logs to developers. See more about [reporting issues](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#reporting-and-communicating-about-issues). - - `logFilter`: Sets the logging category for various logging classes. - - Format: `: ...`, `: <*:level> ...` - - Valid log levels: `Trace, Debug, Info, Warning, Error, Critical` - in this order, setting a level silences all levels preceding it and logs every level after it. - - Examples: - - If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages. - - If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Error Render.Vulkan:Info` - -- `[GPU]` - - `screenWidth` and `screenHeight`: Configures the game window width and height. \ No newline at end of file +You can also configure the emulator by editing the `config.toml` file located in the `user` folder created after the application is started (Mostly useful if you are using the SDL version). +Some settings may be related to more technical development and debugging.\ +For more information on this, see [**Debugging**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration). \ No newline at end of file diff --git a/documents/Screenshots/1.png b/documents/Screenshots/1.png new file mode 100644 index 000000000..f5a5299e6 Binary files /dev/null and b/documents/Screenshots/1.png differ diff --git a/documents/Screenshots/2.png b/documents/Screenshots/2.png new file mode 100644 index 000000000..c80ff04f7 Binary files /dev/null and b/documents/Screenshots/2.png differ diff --git a/documents/Screenshots/3.png b/documents/Screenshots/3.png new file mode 100644 index 000000000..c41d71c8c Binary files /dev/null and b/documents/Screenshots/3.png differ diff --git a/documents/Screenshots/4.png b/documents/Screenshots/4.png new file mode 100644 index 000000000..e5aaa66e2 Binary files /dev/null and b/documents/Screenshots/4.png differ diff --git a/documents/Screenshots/Bloodborne.png b/documents/Screenshots/Bloodborne.png deleted file mode 100644 index b66222b47..000000000 Binary files a/documents/Screenshots/Bloodborne.png and /dev/null differ diff --git a/documents/Screenshots/Sonic Mania.png b/documents/Screenshots/Sonic Mania.png deleted file mode 100644 index 70bdacec3..000000000 Binary files a/documents/Screenshots/Sonic Mania.png and /dev/null differ diff --git a/documents/Screenshots/Undertale.png b/documents/Screenshots/Undertale.png deleted file mode 100644 index c3e7745d0..000000000 Binary files a/documents/Screenshots/Undertale.png and /dev/null differ diff --git a/documents/Screenshots/We are DOOMED.png b/documents/Screenshots/We are DOOMED.png deleted file mode 100644 index 757160e5b..000000000 Binary files a/documents/Screenshots/We are DOOMED.png and /dev/null differ diff --git a/documents/building-linux.md b/documents/building-linux.md index 9645d8b4f..989669f4f 100644 --- a/documents/building-linux.md +++ b/documents/building-linux.md @@ -3,28 +3,28 @@ SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project SPDX-License-Identifier: GPL-2.0-or-later --> -## Build shadPS4 for Linux +## Build shadPS4 for Linux ### Install the necessary tools to build shadPS4: #### Debian & Ubuntu ``` -sudo apt-get install build-essential libasound2-dev libpulse-dev libopenal-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git libevdev-dev libsdl2-2.0 libsdl2-dev libjack-dev libsndio-dev +sudo apt install build-essential clang git cmake libasound2-dev libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev vulkan-validationlayers ``` #### Fedora ``` -sudo dnf install alsa-lib-devel cmake libatomic libevdev-devel libudev-devel openal-devel qt6-qtbase-devel qt6-qtbase-private-devel vulkan-devel pipewire-jack-audio-connection-kit-devel qt6-qtmultimedia-devel qt6-qtsvg-devel +sudo dnf install clang git cmake libatomic alsa-lib-devel pipewire-jack-audio-connection-kit-devel openal-devel openssl-devel libevdev-devel libudev-devel libXext-devel qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel vulkan-devel vulkan-validation-layers ``` #### Arch Linux ``` -sudo pacman -S openal cmake vulkan-validation-layers qt6-base qt6-declarative qt6-multimedia sdl2 sndio jack2 base-devel +sudo pacman -S base-devel clang git cmake sndio jack2 openal qt6-base qt6-declarative qt6-multimedia sdl2 vulkan-validation-layers ``` #### OpenSUSE ``` -sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt6-qtbase-devel libqt6-qtmultimedia-devel libqt6-qtsvg-devel libQt6Gui-private-headers-devel libevdev-devel libsndio7_1 libjack-devel +sudo zypper install clang git cmake libasound2 libpulse-devel libsndio7 libjack-devel openal-soft-devel libopenssl-devel zlib-devel libedit-devel systemd-devel libevdev-devel qt6-base-devel qt6-multimedia-devel qt6-svg-devel qt6-linguist-devel qt6-gui-private-devel vulkan-devel vulkan-validationlayers ``` ### Cloning and compiling: @@ -34,9 +34,11 @@ git clone --recursive https://github.com/shadps4-emu/shadPS4.git cd shadPS4 ``` -Generate the build directory in the shadPS4 directory: +Generate the build directory in the shadPS4 directory. To disable the QT GUI, remove the ```-DENABLE_QT_GUI=ON``` flag: + +**Note**: Clang is the compiler used for official builds and CI. If you build with GCC, you might encounter issues—please report any you find. If you choose to use GCC, we recommend building with Clang at least once before submitting a pull request. ``` -cmake -S . -B build/ +cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ``` Enter the directory: @@ -49,8 +51,11 @@ Use make to build the project: cmake --build . --parallel$(nproc) ``` -Now run the emulator: - +Now run the emulator. If QT is enabled: +``` +./shadps4 +``` +Otherwise, specify the path to your PKG's boot file: ``` ./shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin ``` diff --git a/documents/building-macos.md b/documents/building-macos.md new file mode 100644 index 000000000..d8cc414e2 --- /dev/null +++ b/documents/building-macos.md @@ -0,0 +1,73 @@ + + +## Build shadPS4 for macOS + +### Install the necessary tools to build shadPS4: + +First, make sure you have **Xcode 16.0 or newer** installed. + +For installing other tools and library dependencies we will be using [Homebrew](https://brew.sh/). + +On an ARM system, we will need the native ARM Homebrew to install tools and x86_64 Homebrew to install libraries. + +First, install native Homebrew and tools: +``` +# Installs native Homebrew to /opt/homebrew +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +# Adds Homebrew to your path +echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> ~/.zprofile +eval $(/opt/homebrew/bin/brew shellenv) +# Installs tools. +brew install clang-format cmake +``` + +Next, install x86_64 Homebrew and libraries. + +**If you are on an ARM Mac:** +``` +# Installs x86_64 Homebrew to /usr/local +arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +# Installs libraries. +arch -x86_64 /usr/local/bin/brew install molten-vk qt@6 +``` + +**If you are on an x86_64 Mac:** +``` +brew install molten-vk qt@6 +``` + +If you don't need the Qt GUI you can remove `qt@6` from the last command. + +### Cloning and compiling: + +Clone the repository recursively: +``` +git clone --recursive https://github.com/shadps4-emu/shadPS4.git +cd shadPS4 +``` + +Generate the build directory in the shadPS4 directory: +``` +cmake -S . -B build/ -DCMAKE_OSX_ARCHITECTURES=x86_64 +``` + +If you want to build the Qt GUI, add `-DENABLE_QT_GUI=ON` to the end of this command as well. + +Enter the directory: +``` +cd build/ +``` + +Use make to build the project: +``` +cmake --build . --parallel$(sysctl -n hw.ncpu) +``` + +Now run the emulator: + +``` +./shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin +``` diff --git a/documents/building-windows.md b/documents/building-windows.md index 684e5fe95..48fd09c41 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -6,7 +6,7 @@ SPDX-License-Identifier: GPL-2.0-or-later # Build shadPS4 for Windows This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation. -If you are building to contribute to the project, please omit `--depth 1` from the git invokations. +If you are building to contribute to the project, please omit `--depth 1` from the git invocations. Note: **ARM64 is not supported!** As of writing, it will not build nor run. The instructions with respect to ARM64 are for developers only. @@ -15,36 +15,57 @@ Note: **ARM64 is not supported!** As of writing, it will not build nor run. The ### (Prerequisite) Download the Community edition from [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/) Once you are within the installer: + 1. Select `Desktop development with C++` 2. Go to "Individual Components" tab -3. Make sure `C++ Clang Compiler for Windows`, `MSBuild support for LLVM` and `C++ CMake Tools for Windows` are selected +3. Search and select `C++ Clang Compiler for Windows` and `MSBuild support for LLVM` 4. Continue the installation ### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html) Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead. -1. Select Qt for Visual Studio plugin -2. Select `msvc2019_64` option or similar. If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `msvc2019_arm64` +1. Under the current, non beta version of Qt (at the time of writing 6.7.2), select the option `MSVC 2019 64-bit` or similar. + If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `MSVC 2019 ARM64` instead. -Go through the installation normally. If you do not know what components to select, just select the newest Qt version it gives you. -If you know what you are doing, you may unselect individual components that eat up too much disk space. + Go through the installation normally. If you know what you are doing, you may unselect individual components that eat up too much disk space. + +2. Download and install [Qt Visual Studio Tools](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022) Once you are finished, you will have to configure Qt within Visual Studio: + 1. Tools -> Options -> Qt -> Versions -2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.1\msvc2019_64` -3. Enable the default checkmark on the new version you just created. +2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.2\msvc2019_64` +3. Enable the default checkmark on the new version you just created. ### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win) Go through the Git for Windows installation as normal -### Compiling with Visual Studio GUI +### Cloning the source code 1. Open Git for Windows, navigate to a place where you want to store the shadPS4 source code folder -2. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` -3. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` -4. Build -> Build All +2. Clone the repository by running + `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` + +### Compiling with Visual Studio GUI + +1. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` +2. Change x64-Clang-Debug to x64-Clang-Release if you want a regular, non-debug build. +3. If you want to build shadPS4 with the Qt Gui: + 1. Click x64-Clang-Release and select "Manage Configurations" + 2. Look for "CMake command arguments" and add to the text field + `-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.7.2\msvc2019_64` + (Change Qt path if you've installed it to non-default path) + 3. Press CTRL+S to save and wait a moment for CMake generation +4. Change the project to build to shadps4.exe +5. Build -> Build All + +Your shadps4.exe will be in `c:\path\to\source\Build\x64-Clang-Release\` + +To automatically populate the necessary files to run shadPS4.exe, run in a command prompt or terminal: +`C:\Qt\6.7.2\msvc2019_64\bin\windeployqt.exe "c:\path\to\shadps4.exe"` +(Change Qt path if you've installed it to non-default path) ## Option 2: MSYS2/MinGW @@ -55,27 +76,35 @@ Go through the MSYS2 installation as normal If you are building to distribute, please omit `-DCMAKE_CXX_FLAGS="-O2 -march=native"` within the build configuration step. Normal x86-based computers, follow: + 1. Open "MSYS2 MINGW64" from your new applications 2. Run `pacman -Syu`, let it complete; -3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-qt6-base` +3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg` + 1. Optional (Qt only): run `pacman -S --needed mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-tools mingw-w64-x86_64-qt6-multimedia` 4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` 5. Run `cd shadPS4` -6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` +6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` + 1. Optional (Qt only): add `-DENABLE_QT_GUI=ON` 7. Run `cmake --build build` + 1. Optional (Qt only): run `windeployqt6 build/shadps4.exe` 8. To run the finished product, run `./build/shadPS4.exe` ARM64-based computers, follow: + 1. Open "MSYS2 CLANGARM64" from your new applications 2. Run `pacman -Syu`, let it complete; -3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-qt6-base` +3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-ffmpeg` + 1. Optional (Qt only): run `pacman -S --needed mingw-w64-clang-aarch64-qt6-base mingw-w64-clang-aarch64-qt6-tools mingw-w64-clang-aarch64-qt6-multimedia` 4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4` 5. Run `cd shadPS4` -6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` +6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"` + 1. Optional (Qt only): add `-DENABLE_QT_GUI=ON` 7. Run `cmake --build build` + 1. Optional (Qt only): run `windeployqt6 build/shadps4.exe` 8. To run the finished product, run `./build/shadPS4.exe` ## Note on MSYS2 builds These builds may not be easily copyable to people who do not also have a MSYS2 installation. If you want to distribute these builds, you need to copy over the correct DLLs into a distribution folder. -In order to run them, you must be within the MSYS2 shell environment. \ No newline at end of file +In order to run them, you must be within the MSYS2 shell environment. diff --git a/documents/changelog.txt b/documents/changelog.txt index 0e189f58d..6df09472d 100644 --- a/documents/changelog.txt +++ b/documents/changelog.txt @@ -1,3 +1,14 @@ +v0.3.0 23/09/2024 - codename broamic +================= + +- Cheat/Patching support +- DLC support +- New translations support (26 languages) +- Support for unlocking trophies +- Support for more controllers (Dualshock and Xbox) +- Many GUI improvements +- AVplayer + v0.2.0 15/08/2024 - codename validptr ================= - Adding macOS support diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 6fe73a29a..80f49f527 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -3,7 +3,10 @@ set(BUILD_SHARED_LIBS OFF) set(BUILD_TESTING OFF) -set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL ON) +set_directory_properties(PROPERTIES + EXCLUDE_FROM_ALL ON + SYSTEM ON +) if (MSVC) # Silence "deprecation" warnings @@ -13,11 +16,8 @@ endif() # Boost if (NOT TARGET Boost::headers) set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/ext-boost" CACHE STRING "") - set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/ext-boost" CACHE STRING "") set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "") - add_library(boost INTERFACE) - target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR}) - add_library(Boost::headers ALIAS boost) + add_subdirectory(ext-boost) endif() # fmtlib @@ -43,7 +43,6 @@ else() endif() if (NOT TARGET FFmpeg::ffmpeg) - set(ARCHITECTURE "x86_64") add_subdirectory(ffmpeg-core) add_library(FFmpeg::ffmpeg ALIAS ffmpeg) endif() @@ -78,7 +77,7 @@ endif() # RenderDoc if (NOT TARGET RenderDoc::API) add_library(renderdoc INTERFACE) - target_include_directories(renderdoc SYSTEM INTERFACE ./renderdoc) + target_include_directories(renderdoc INTERFACE ./renderdoc) add_library(RenderDoc::API ALIAS renderdoc) endif() @@ -142,13 +141,33 @@ if (WIN32) target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument") endif() -# date -if (APPLE AND NOT TARGET date::date-tz) - option(BUILD_TZ_LIB "" ON) - option(USE_SYSTEM_TZ_DB "" ON) - add_subdirectory(date) +# half +if (NOT TARGET half::half) + add_library(half INTERFACE) + target_include_directories(half INTERFACE half/include) + add_library(half::half ALIAS half) endif() +if (APPLE) + # date + if (NOT TARGET date::date-tz) + option(BUILD_TZ_LIB "" ON) + option(USE_SYSTEM_TZ_DB "" ON) + add_subdirectory(date) + endif() +endif() + +# Dear ImGui +add_library(Dear_ImGui + dear_imgui/imgui.cpp + dear_imgui/imgui_demo.cpp + dear_imgui/imgui_draw.cpp + dear_imgui/imgui_internal.h + dear_imgui/imgui_tables.cpp + dear_imgui/imgui_widgets.cpp +) +target_include_directories(Dear_ImGui INTERFACE dear_imgui/) + # Tracy option(TRACY_ENABLE "" ON) option(TRACY_NO_CRASH_HANDLER "" ON) # Otherwise texture cache exceptions will be treaten as a crash @@ -162,3 +181,16 @@ option(TRACY_NO_SAMPLING "" ON) option(TRACY_ONLY_LOCALHOST "" ON) option(TRACY_NO_CONTEXT_SWITCH "" ON) add_subdirectory(tracy) + +# pugixml +if (NOT TARGET pugixml::pugixml) + add_subdirectory(pugixml) +endif() + +# Discord RPC +set(BUILD_EXAMPLES OFF) +add_subdirectory(discord-rpc/) +target_include_directories(discord-rpc INTERFACE discord-rpc/include) + +# GCN Headers +add_subdirectory(gcn) diff --git a/externals/date b/externals/date index 1ead6715d..dd8affc6d 160000 --- a/externals/date +++ b/externals/date @@ -1 +1 @@ -Subproject commit 1ead6715dec030d340a316c927c877a3c4e5a00c +Subproject commit dd8affc6de5755e07638bf0a14382d29549d6ee9 diff --git a/externals/dear_imgui b/externals/dear_imgui new file mode 160000 index 000000000..636cd4a7d --- /dev/null +++ b/externals/dear_imgui @@ -0,0 +1 @@ +Subproject commit 636cd4a7d623a2bc9bf59bb3acbb4ca075befba3 diff --git a/externals/discord-rpc b/externals/discord-rpc new file mode 160000 index 000000000..4ec218155 --- /dev/null +++ b/externals/discord-rpc @@ -0,0 +1 @@ +Subproject commit 4ec218155d73bcb8022f8f7ca72305d801f84beb diff --git a/externals/ext-boost b/externals/ext-boost index a04136add..f2474e1b5 160000 --- a/externals/ext-boost +++ b/externals/ext-boost @@ -1 +1 @@ -Subproject commit a04136add1e469f46d8ae8d3e8307779240a5c53 +Subproject commit f2474e1b584fb7a3ed6f85ba875e6eacd742ec8a diff --git a/externals/fmt b/externals/fmt index c98518351..8ee89546f 160000 --- a/externals/fmt +++ b/externals/fmt @@ -1 +1 @@ -Subproject commit c98518351efd5a46f5d448e947e0b7242d197d07 +Subproject commit 8ee89546ffcf046309d1f0d38c0393f02fde56c8 diff --git a/externals/gcn/CMakeLists.txt b/externals/gcn/CMakeLists.txt new file mode 100644 index 000000000..592f28d0d --- /dev/null +++ b/externals/gcn/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +project(gcn LANGUAGES CXX) + +add_library(gcn dummy.cpp) + +target_include_directories(gcn INTERFACE include) diff --git a/externals/gcn/dummy.cpp b/externals/gcn/dummy.cpp new file mode 100644 index 000000000..4fd1bb62d --- /dev/null +++ b/externals/gcn/dummy.cpp @@ -0,0 +1,2 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later diff --git a/externals/gcn/include/gcn/si_ci_vi_merged_offset.h b/externals/gcn/include/gcn/si_ci_vi_merged_offset.h new file mode 100644 index 000000000..589a58bfe --- /dev/null +++ b/externals/gcn/include/gcn/si_ci_vi_merged_offset.h @@ -0,0 +1,15339 @@ +/* + *********************************************************************************************************************** + * + * Copyright (c) 2014-2021 Advanced Micro Devices, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************************************************************************/ + +#if !defined __SI__CI__VIoffset_HEADER +#define __SI__CI__VIoffset_HEADER + +namespace Pal +{ +namespace Gfx6 +{ +inline namespace Chip +{ + +#define SI_CI_offset_HEADER__SI__CI +constexpr unsigned int cfgADAPTER_ID = 0x000B; +constexpr unsigned int cfgADAPTER_ID_W = 0x0013; +constexpr unsigned int cfgBASE_ADDR_1 = 0x0004; +constexpr unsigned int cfgBASE_ADDR_2 = 0x0005; +constexpr unsigned int cfgBASE_ADDR_3 = 0x0006; +constexpr unsigned int cfgBASE_ADDR_4 = 0x0007; +constexpr unsigned int cfgBASE_ADDR_5 = 0x0008; +constexpr unsigned int cfgBASE_ADDR_6 = 0x0009; +constexpr unsigned int cfgBASE_CLASS = 0x0002; +constexpr unsigned int cfgBIST = 0x0003; +constexpr unsigned int cfgCACHE_LINE = 0x0003; +constexpr unsigned int cfgCAP_PTR = 0x000D; +constexpr unsigned int cfgCOMMAND = 0x0001; +constexpr unsigned int cfgDEVICE_CAP = 0x0017; +constexpr unsigned int cfgDEVICE_CAP2 = 0x001F; +constexpr unsigned int cfgDEVICE_CNTL = 0x0018; +constexpr unsigned int cfgDEVICE_CNTL2 = 0x0020; +constexpr unsigned int cfgDEVICE_ID = 0x0000; +constexpr unsigned int cfgDEVICE_STATUS = 0x0018; +constexpr unsigned int cfgDEVICE_STATUS2 = 0x0020; +constexpr unsigned int cfgHEADER = 0x0003; +constexpr unsigned int cfgINTERRUPT_LINE = 0x000F; +constexpr unsigned int cfgINTERRUPT_PIN = 0x000F; +constexpr unsigned int cfgLATENCY = 0x0003; +constexpr unsigned int cfgLINK_CAP = 0x0019; +constexpr unsigned int cfgLINK_CAP2 = 0x0021; +constexpr unsigned int cfgLINK_CNTL = 0x001A; +constexpr unsigned int cfgLINK_CNTL2 = 0x0022; +constexpr unsigned int cfgLINK_STATUS = 0x001A; +constexpr unsigned int cfgLINK_STATUS2 = 0x0022; +constexpr unsigned int cfgMAX_LATENCY = 0x000F; +constexpr unsigned int cfgMIN_GRANT = 0x000F; +constexpr unsigned int cfgMSI_CAP_LIST = 0x0028; +constexpr unsigned int cfgMSI_MSG_ADDR_HI = 0x002A; +constexpr unsigned int cfgMSI_MSG_ADDR_LO = 0x0029; +constexpr unsigned int cfgMSI_MSG_CNTL = 0x0028; +constexpr unsigned int cfgMSI_MSG_DATA = 0x002A; +constexpr unsigned int cfgMSI_MSG_DATA_64 = 0x002B; +constexpr unsigned int cfgPCIE_ACS_CAP__CI__VI = 0x00A9; +constexpr unsigned int cfgPCIE_ACS_CNTL__CI__VI = 0x00A9; +constexpr unsigned int cfgPCIE_ACS_ENH_CAP_LIST__CI__VI = 0x00A8; +constexpr unsigned int cfgPCIE_ADV_ERR_CAP_CNTL = 0x005A; +constexpr unsigned int cfgPCIE_ADV_ERR_RPT_ENH_CAP_LIST = 0x0054; +constexpr unsigned int cfgPCIE_ATS_CAP__CI__VI = 0x00AD; +constexpr unsigned int cfgPCIE_ATS_CNTL__CI__VI = 0x00AD; +constexpr unsigned int cfgPCIE_ATS_ENH_CAP_LIST__CI__VI = 0x00AC; +constexpr unsigned int cfgPCIE_BAR1_CAP__CI__VI = 0x0081; +constexpr unsigned int cfgPCIE_BAR1_CNTL__CI__VI = 0x0082; +constexpr unsigned int cfgPCIE_BAR2_CAP__CI__VI = 0x0083; +constexpr unsigned int cfgPCIE_BAR2_CNTL__CI__VI = 0x0084; +constexpr unsigned int cfgPCIE_BAR3_CAP__CI__VI = 0x0085; +constexpr unsigned int cfgPCIE_BAR3_CNTL__CI__VI = 0x0086; +constexpr unsigned int cfgPCIE_BAR4_CAP__CI__VI = 0x0087; +constexpr unsigned int cfgPCIE_BAR4_CNTL__CI__VI = 0x0088; +constexpr unsigned int cfgPCIE_BAR5_CAP__CI__VI = 0x0089; +constexpr unsigned int cfgPCIE_BAR5_CNTL__CI__VI = 0x008A; +constexpr unsigned int cfgPCIE_BAR6_CAP__CI__VI = 0x008B; +constexpr unsigned int cfgPCIE_BAR6_CNTL__CI__VI = 0x008C; +constexpr unsigned int cfgPCIE_BAR_ENH_CAP_LIST__CI__VI = 0x0080; +constexpr unsigned int cfgPCIE_CAP = 0x0016; +constexpr unsigned int cfgPCIE_CAP_LIST = 0x0016; +constexpr unsigned int cfgPCIE_CORR_ERR_MASK = 0x0059; +constexpr unsigned int cfgPCIE_CORR_ERR_STATUS = 0x0058; +constexpr unsigned int cfgPCIE_DEV_SERIAL_NUM_DW1 = 0x0051; +constexpr unsigned int cfgPCIE_DEV_SERIAL_NUM_DW2 = 0x0052; +constexpr unsigned int cfgPCIE_DEV_SERIAL_NUM_ENH_CAP_LIST = 0x0050; +constexpr unsigned int cfgPCIE_DPA_CAP__CI__VI = 0x0095; +constexpr unsigned int cfgPCIE_DPA_CNTL__CI__VI = 0x0097; +constexpr unsigned int cfgPCIE_DPA_ENH_CAP_LIST__CI__VI = 0x0094; +constexpr unsigned int cfgPCIE_DPA_LATENCY_INDICATOR__CI__VI = 0x0096; +constexpr unsigned int cfgPCIE_DPA_STATUS__CI__VI = 0x0097; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_0__CI__VI = 0x0098; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_1__CI__VI = 0x0098; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_2__CI__VI = 0x0098; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_3__CI__VI = 0x0098; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_4__CI__VI = 0x0099; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_5__CI__VI = 0x0099; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_6__CI__VI = 0x0099; +constexpr unsigned int cfgPCIE_DPA_SUBSTATE_PWR_ALLOC_7__CI__VI = 0x0099; +constexpr unsigned int cfgPCIE_HDR_LOG0 = 0x005B; +constexpr unsigned int cfgPCIE_HDR_LOG1 = 0x005C; +constexpr unsigned int cfgPCIE_HDR_LOG2 = 0x005D; +constexpr unsigned int cfgPCIE_HDR_LOG3 = 0x005E; +constexpr unsigned int cfgPCIE_LANE_0_EQUALIZATION_CNTL__CI__VI = 0x009F; +constexpr unsigned int cfgPCIE_LANE_10_EQUALIZATION_CNTL__CI__VI = 0x00A4; +constexpr unsigned int cfgPCIE_LANE_11_EQUALIZATION_CNTL__CI__VI = 0x00A4; +constexpr unsigned int cfgPCIE_LANE_12_EQUALIZATION_CNTL__CI__VI = 0x00A5; +constexpr unsigned int cfgPCIE_LANE_13_EQUALIZATION_CNTL__CI__VI = 0x00A5; +constexpr unsigned int cfgPCIE_LANE_14_EQUALIZATION_CNTL__CI__VI = 0x00A6; +constexpr unsigned int cfgPCIE_LANE_15_EQUALIZATION_CNTL__CI__VI = 0x00A6; +constexpr unsigned int cfgPCIE_LANE_1_EQUALIZATION_CNTL__CI__VI = 0x009F; +constexpr unsigned int cfgPCIE_LANE_2_EQUALIZATION_CNTL__CI__VI = 0x00A0; +constexpr unsigned int cfgPCIE_LANE_3_EQUALIZATION_CNTL__CI__VI = 0x00A0; +constexpr unsigned int cfgPCIE_LANE_4_EQUALIZATION_CNTL__CI__VI = 0x00A1; +constexpr unsigned int cfgPCIE_LANE_5_EQUALIZATION_CNTL__CI__VI = 0x00A1; +constexpr unsigned int cfgPCIE_LANE_6_EQUALIZATION_CNTL__CI__VI = 0x00A2; +constexpr unsigned int cfgPCIE_LANE_7_EQUALIZATION_CNTL__CI__VI = 0x00A2; +constexpr unsigned int cfgPCIE_LANE_8_EQUALIZATION_CNTL__CI__VI = 0x00A3; +constexpr unsigned int cfgPCIE_LANE_9_EQUALIZATION_CNTL__CI__VI = 0x00A3; +constexpr unsigned int cfgPCIE_LANE_ERROR_STATUS__CI__VI = 0x009E; +constexpr unsigned int cfgPCIE_LINK_CNTL3__CI__VI = 0x009D; +constexpr unsigned int cfgPCIE_OUTSTAND_PAGE_REQ_ALLOC__CI__VI = 0x00B3; +constexpr unsigned int cfgPCIE_OUTSTAND_PAGE_REQ_CAPACITY__CI__VI = 0x00B2; +constexpr unsigned int cfgPCIE_PAGE_REQ_CNTL__CI__VI = 0x00B1; +constexpr unsigned int cfgPCIE_PAGE_REQ_ENH_CAP_LIST__CI__VI = 0x00B0; +constexpr unsigned int cfgPCIE_PAGE_REQ_STATUS__CI__VI = 0x00B1; +constexpr unsigned int cfgPCIE_PASID_CAP__CI__VI = 0x00B5; +constexpr unsigned int cfgPCIE_PASID_CNTL__CI__VI = 0x00B5; +constexpr unsigned int cfgPCIE_PASID_ENH_CAP_LIST__CI__VI = 0x00B4; +constexpr unsigned int cfgPCIE_PORT_VC_CAP_REG1 = 0x0045; +constexpr unsigned int cfgPCIE_PORT_VC_CAP_REG2 = 0x0046; +constexpr unsigned int cfgPCIE_PORT_VC_CNTL = 0x0047; +constexpr unsigned int cfgPCIE_PORT_VC_STATUS = 0x0047; +constexpr unsigned int cfgPCIE_PWR_BUDGET_CAP__CI__VI = 0x0093; +constexpr unsigned int cfgPCIE_PWR_BUDGET_DATA_SELECT__CI__VI = 0x0091; +constexpr unsigned int cfgPCIE_PWR_BUDGET_DATA__CI__VI = 0x0092; +constexpr unsigned int cfgPCIE_PWR_BUDGET_ENH_CAP_LIST__CI__VI = 0x0090; +constexpr unsigned int cfgPCIE_SECONDARY_ENH_CAP_LIST__CI__VI = 0x009C; +constexpr unsigned int cfgPCIE_TLP_PREFIX_LOG0__CI__VI = 0x0062; +constexpr unsigned int cfgPCIE_TLP_PREFIX_LOG1__CI__VI = 0x0063; +constexpr unsigned int cfgPCIE_TLP_PREFIX_LOG2__CI__VI = 0x0064; +constexpr unsigned int cfgPCIE_TLP_PREFIX_LOG3__CI__VI = 0x0065; +constexpr unsigned int cfgPCIE_UNCORR_ERR_MASK = 0x0056; +constexpr unsigned int cfgPCIE_UNCORR_ERR_SEVERITY = 0x0057; +constexpr unsigned int cfgPCIE_UNCORR_ERR_STATUS = 0x0055; +constexpr unsigned int cfgPCIE_VC0_RESOURCE_CAP = 0x0048; +constexpr unsigned int cfgPCIE_VC0_RESOURCE_CNTL = 0x0049; +constexpr unsigned int cfgPCIE_VC0_RESOURCE_STATUS = 0x004A; +constexpr unsigned int cfgPCIE_VC1_RESOURCE_CAP = 0x004B; +constexpr unsigned int cfgPCIE_VC1_RESOURCE_CNTL = 0x004C; +constexpr unsigned int cfgPCIE_VC1_RESOURCE_STATUS = 0x004D; +constexpr unsigned int cfgPCIE_VC_ENH_CAP_LIST = 0x0044; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC1 = 0x0042; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC2 = 0x0043; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC_ENH_CAP_LIST = 0x0040; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC_HDR = 0x0041; +constexpr unsigned int cfgPMI_CAP = 0x0014; +constexpr unsigned int cfgPMI_CAP_LIST = 0x0014; +constexpr unsigned int cfgPMI_STATUS_CNTL = 0x0015; +constexpr unsigned int cfgPROG_INTERFACE = 0x0002; +constexpr unsigned int cfgREVISION_ID = 0x0002; +constexpr unsigned int cfgROM_BASE_ADDR = 0x000C; +constexpr unsigned int cfgSTATUS = 0x0001; +constexpr unsigned int cfgSUB_CLASS = 0x0002; +constexpr unsigned int cfgVENDOR_CAP_LIST__CI__VI = 0x0012; +constexpr unsigned int cfgVENDOR_ID = 0x0000; +constexpr unsigned int ioATTRDR__SI__VI = 0x00F0; +constexpr unsigned int ioATTRDW__SI__VI = 0x00F0; +constexpr unsigned int ioATTRX__SI__VI = 0x00F0; +constexpr unsigned int ioBIF_RFE_SNOOP_REG__CI__VI = 0x0027; +constexpr unsigned int ioCRTC8_DATA__SI__VI = 0x00ED; +constexpr unsigned int ioCRTC8_IDX__SI__VI = 0x00ED; +constexpr unsigned int ioDAC_DATA__SI__VI = 0x00F2; +constexpr unsigned int ioDAC_MASK__SI__VI = 0x00F1; +constexpr unsigned int ioDAC_R_INDEX__SI__VI = 0x00F1; +constexpr unsigned int ioDAC_W_INDEX__SI__VI = 0x00F2; +constexpr unsigned int ioGENENB__SI__VI = 0x00F0; +constexpr unsigned int ioGENFC_RD__SI__VI = 0x00F2; +constexpr unsigned int ioGENFC_WT__SI__VI = 0x00EE; +constexpr unsigned int ioGENMO_RD__SI__VI = 0x00F3; +constexpr unsigned int ioGENMO_WT__SI__VI = 0x00F0; +constexpr unsigned int ioGENS0__SI__VI = 0x00F0; +constexpr unsigned int ioGENS1__SI__VI = 0x00EE; +constexpr unsigned int ioGRPH8_DATA__SI__VI = 0x00F3; +constexpr unsigned int ioGRPH8_IDX__SI__VI = 0x00F3; +constexpr unsigned int ioMM_DATA = 0x0001; +constexpr unsigned int ioMM_INDEX = 0x0000; +constexpr unsigned int ioMM_INDEX_HI__CI__VI = 0x0006; +constexpr unsigned int ioPCIE_DATA_2__CI__VI = 0x000D; +constexpr unsigned int ioPCIE_DATA__CI__VI = 0x000F; +constexpr unsigned int ioPCIE_DATA__SI = 0x000D; +constexpr unsigned int ioPCIE_INDEX_2__CI__VI = 0x000C; +constexpr unsigned int ioPCIE_INDEX__CI__VI = 0x000E; +constexpr unsigned int ioPCIE_INDEX__SI = 0x000C; +constexpr unsigned int ioROM_DATA__SI = 0x002B; +constexpr unsigned int ioROM_INDEX__SI = 0x002A; +constexpr unsigned int ioSEQ8_DATA__SI__VI = 0x00F1; +constexpr unsigned int ioSEQ8_IDX__SI__VI = 0x00F1; +constexpr unsigned int ioVGA_MEM_READ_PAGE_ADDR__SI__VI = 0x0013; +constexpr unsigned int ioVGA_MEM_WRITE_PAGE_ADDR__SI__VI = 0x0012; +constexpr unsigned int mmABM_TEST_DEBUG_DATA__SI__VI = 0x169F; +constexpr unsigned int mmABM_TEST_DEBUG_INDEX__SI__VI = 0x169E; +constexpr unsigned int mmACP_CONFIG__CI = 0x0F95; +constexpr unsigned int mmAFMT_60958_0__SI = 0x1C41; +constexpr unsigned int mmAFMT_60958_1__SI = 0x1C42; +constexpr unsigned int mmAFMT_60958_2__SI = 0x1C48; +constexpr unsigned int mmAFMT_AUDIO_CRC_CONTROL__SI = 0x1C43; +constexpr unsigned int mmAFMT_AUDIO_CRC_RESULT__SI = 0x1C49; +constexpr unsigned int mmAFMT_AUDIO_INFO0__SI = 0x1C3F; +constexpr unsigned int mmAFMT_AUDIO_INFO1__SI = 0x1C40; +constexpr unsigned int mmAFMT_AUDIO_PACKET_CONTROL2__SI = 0x1C17; +constexpr unsigned int mmAFMT_AUDIO_PACKET_CONTROL__SI = 0x1C4B; +constexpr unsigned int mmAFMT_AVI_INFO0__SI = 0x1C21; +constexpr unsigned int mmAFMT_AVI_INFO1__SI = 0x1C22; +constexpr unsigned int mmAFMT_AVI_INFO2__SI = 0x1C23; +constexpr unsigned int mmAFMT_AVI_INFO3__SI = 0x1C24; +constexpr unsigned int mmAFMT_INFOFRAME_CONTROL0__SI = 0x1C4D; +constexpr unsigned int mmAFMT_ISRC1_0__SI = 0x1C18; +constexpr unsigned int mmAFMT_ISRC1_1__SI = 0x1C19; +constexpr unsigned int mmAFMT_ISRC1_2__SI = 0x1C1A; +constexpr unsigned int mmAFMT_ISRC1_3__SI = 0x1C1B; +constexpr unsigned int mmAFMT_ISRC1_4__SI = 0x1C1C; +constexpr unsigned int mmAFMT_ISRC2_0__SI = 0x1C1D; +constexpr unsigned int mmAFMT_ISRC2_1__SI = 0x1C1E; +constexpr unsigned int mmAFMT_ISRC2_2__SI = 0x1C1F; +constexpr unsigned int mmAFMT_ISRC2_3__SI = 0x1C20; +constexpr unsigned int mmAFMT_MPEG_INFO0__SI = 0x1C25; +constexpr unsigned int mmAFMT_MPEG_INFO1__SI = 0x1C26; +constexpr unsigned int mmAFMT_RAMP_CONTROL0__SI = 0x1C44; +constexpr unsigned int mmAFMT_RAMP_CONTROL1__SI = 0x1C45; +constexpr unsigned int mmAFMT_RAMP_CONTROL2__SI = 0x1C46; +constexpr unsigned int mmAFMT_RAMP_CONTROL3__SI = 0x1C47; +constexpr unsigned int mmAFMT_STATUS__SI = 0x1C4A; +constexpr unsigned int mmAFMT_VBI_PACKET_CONTROL__SI = 0x1C4C; +constexpr unsigned int mmATC_ATS_CNTL__CI__VI = 0x0CC9; +constexpr unsigned int mmATC_ATS_DEBUG__CI__VI = 0x0CCA; +constexpr unsigned int mmATC_ATS_DEFAULT_PAGE_CNTL__CI__VI = 0x0CD1; +constexpr unsigned int mmATC_ATS_DEFAULT_PAGE_LOW__CI__VI = 0x0CD0; +constexpr unsigned int mmATC_ATS_FAULT_CNTL__CI__VI = 0x0CCD; +constexpr unsigned int mmATC_ATS_FAULT_DEBUG__CI__VI = 0x0CCB; +constexpr unsigned int mmATC_ATS_FAULT_STATUS_ADDR__CI__VI = 0x0CCF; +constexpr unsigned int mmATC_ATS_FAULT_STATUS_INFO__CI__VI = 0x0CCE; +constexpr unsigned int mmATC_ATS_STATUS__CI__VI = 0x0CCC; +constexpr unsigned int mmATC_L1RD_DEBUG_TLB__CI__VI = 0x0CDE; +constexpr unsigned int mmATC_L1RD_STATUS__CI__VI = 0x0CE0; +constexpr unsigned int mmATC_L1WR_DEBUG_TLB__CI__VI = 0x0CDF; +constexpr unsigned int mmATC_L1WR_STATUS__CI__VI = 0x0CE1; +constexpr unsigned int mmATC_L1_ADDRESS_OFFSET__CI__VI = 0x0CDD; +constexpr unsigned int mmATC_L1_CNTL__CI__VI = 0x0CDC; +constexpr unsigned int mmATC_L2_CNTL2__CI__VI = 0x0CD6; +constexpr unsigned int mmATC_L2_CNTL__CI__VI = 0x0CD5; +constexpr unsigned int mmATC_L2_DEBUG2__CI__VI = 0x0CD8; +constexpr unsigned int mmATC_L2_DEBUG__CI__VI = 0x0CD7; +constexpr unsigned int mmATC_MISC_CG__CI__VI = 0x0CD4; +constexpr unsigned int mmATC_PERFCOUNTER0_CFG__CI__VI = 0x07C8; +constexpr unsigned int mmATC_PERFCOUNTER1_CFG__CI__VI = 0x07C9; +constexpr unsigned int mmATC_PERFCOUNTER2_CFG__CI__VI = 0x07CA; +constexpr unsigned int mmATC_PERFCOUNTER3_CFG__CI__VI = 0x07CB; +constexpr unsigned int mmATC_PERFCOUNTER_HI__CI__VI = 0x07AF; +constexpr unsigned int mmATC_PERFCOUNTER_LO__CI__VI = 0x07A7; +constexpr unsigned int mmATC_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07D5; +constexpr unsigned int mmATC_VMID0_PASID_MAPPING__CI__VI = 0x0CE7; +constexpr unsigned int mmATC_VMID10_PASID_MAPPING__CI__VI = 0x0CF1; +constexpr unsigned int mmATC_VMID11_PASID_MAPPING__CI__VI = 0x0CF2; +constexpr unsigned int mmATC_VMID12_PASID_MAPPING__CI__VI = 0x0CF3; +constexpr unsigned int mmATC_VMID13_PASID_MAPPING__CI__VI = 0x0CF4; +constexpr unsigned int mmATC_VMID14_PASID_MAPPING__CI__VI = 0x0CF5; +constexpr unsigned int mmATC_VMID15_PASID_MAPPING__CI__VI = 0x0CF6; +constexpr unsigned int mmATC_VMID1_PASID_MAPPING__CI__VI = 0x0CE8; +constexpr unsigned int mmATC_VMID2_PASID_MAPPING__CI__VI = 0x0CE9; +constexpr unsigned int mmATC_VMID3_PASID_MAPPING__CI__VI = 0x0CEA; +constexpr unsigned int mmATC_VMID4_PASID_MAPPING__CI__VI = 0x0CEB; +constexpr unsigned int mmATC_VMID5_PASID_MAPPING__CI__VI = 0x0CEC; +constexpr unsigned int mmATC_VMID6_PASID_MAPPING__CI__VI = 0x0CED; +constexpr unsigned int mmATC_VMID7_PASID_MAPPING__CI__VI = 0x0CEE; +constexpr unsigned int mmATC_VMID8_PASID_MAPPING__CI__VI = 0x0CEF; +constexpr unsigned int mmATC_VMID9_PASID_MAPPING__CI__VI = 0x0CF0; +constexpr unsigned int mmATC_VMID_PASID_MAPPING_UPDATE_STATUS__CI__VI = 0x0CE6; +constexpr unsigned int mmATC_VM_APERTURE0_CNTL2__CI__VI = 0x0CC6; +constexpr unsigned int mmATC_VM_APERTURE0_CNTL__CI__VI = 0x0CC4; +constexpr unsigned int mmATC_VM_APERTURE0_HIGH_ADDR__CI__VI = 0x0CC2; +constexpr unsigned int mmATC_VM_APERTURE0_LOW_ADDR__CI__VI = 0x0CC0; +constexpr unsigned int mmATC_VM_APERTURE1_CNTL2__CI__VI = 0x0CC7; +constexpr unsigned int mmATC_VM_APERTURE1_CNTL__CI__VI = 0x0CC5; +constexpr unsigned int mmATC_VM_APERTURE1_HIGH_ADDR__CI__VI = 0x0CC3; +constexpr unsigned int mmATC_VM_APERTURE1_LOW_ADDR__CI__VI = 0x0CC1; +constexpr unsigned int mmATTRDR__SI__VI = 0x00F0; +constexpr unsigned int mmATTRDW__SI__VI = 0x00F0; +constexpr unsigned int mmATTRX__SI__VI = 0x00F0; +constexpr unsigned int mmAUXN_IMPCAL__SI = 0x194B; +constexpr unsigned int mmAUXP_IMPCAL__SI = 0x194A; +constexpr unsigned int mmAUX_ARB_CONTROL__SI = 0x1882; +constexpr unsigned int mmAUX_CONTROL__SI = 0x1880; +constexpr unsigned int mmAUX_DPHY_RX_CONTROL0__SI = 0x188A; +constexpr unsigned int mmAUX_DPHY_RX_CONTROL1__SI = 0x188B; +constexpr unsigned int mmAUX_DPHY_RX_STATUS__SI = 0x188D; +constexpr unsigned int mmAUX_DPHY_TX_CONTROL__SI = 0x1889; +constexpr unsigned int mmAUX_DPHY_TX_REF_CONTROL__SI = 0x1888; +constexpr unsigned int mmAUX_DPHY_TX_STATUS__SI = 0x188C; +constexpr unsigned int mmAUX_INTERRUPT_CONTROL__SI = 0x1883; +constexpr unsigned int mmAUX_LS_DATA__SI = 0x1887; +constexpr unsigned int mmAUX_LS_STATUS__SI = 0x1885; +constexpr unsigned int mmAUX_SW_CONTROL__SI = 0x1881; +constexpr unsigned int mmAUX_SW_DATA__SI = 0x1886; +constexpr unsigned int mmAUX_SW_STATUS__SI = 0x1884; +constexpr unsigned int mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__SI = 0x17F6; +constexpr unsigned int mmAZALIA_AUDIO_DTO_CONTROL__SI = 0x173D; +constexpr unsigned int mmAZALIA_AUDIO_DTO__SI = 0x173C; +constexpr unsigned int mmAZALIA_BDL_DMA_CONTROL__SI = 0x1730; +constexpr unsigned int mmAZALIA_CORB_DMA_CONTROL__SI = 0x172F; +constexpr unsigned int mmAZALIA_CUMULATIVE_LATENCY_COUNT__SI = 0x1737; +constexpr unsigned int mmAZALIA_CUMULATIVE_REQUEST_COUNT__SI = 0x1738; +constexpr unsigned int mmAZALIA_CYCLIC_BUFFER_SYNC__SI = 0x17F7; +constexpr unsigned int mmAZALIA_DATA_DMA_CONTROL__SI = 0x1731; +constexpr unsigned int mmAZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__SI = 0x174F; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__SI = 0x174C; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__SI = 0x174D; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SI = 0x1750; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SI = 0x1742; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__SI = 0x1745; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SI = 0x1744; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__SI = 0x1743; +constexpr unsigned int mmAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__SI = 0x174B; +constexpr unsigned int mmAZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__SI = 0x1753; +constexpr unsigned int mmAZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__SI = 0x173F; +constexpr unsigned int mmAZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SI = 0x173E; +constexpr unsigned int mmAZALIA_LATENCY_COUNTER_CONTROL__SI = 0x1735; +constexpr unsigned int mmAZALIA_RIRB_AND_DP_CONTROL__SI = 0x172D; +constexpr unsigned int mmAZALIA_UNDERFLOW_FILLER_SAMPLE__SI = 0x1732; +constexpr unsigned int mmAZALIA_WORSTCASE_LATENCY_COUNT__SI = 0x1736; +constexpr unsigned int mmAZ_TEST_DEBUG_DATA__SI = 0x1756; +constexpr unsigned int mmAZ_TEST_DEBUG_INDEX__SI = 0x1755; +constexpr unsigned int mmBACO_CNTL_MISC__CI__VI = 0x14DB; +constexpr unsigned int mmBACO_CNTL__CI__VI = 0x14E5; +constexpr unsigned int mmBCI_DEBUG_READ__CI__VI = 0x24EB; +constexpr unsigned int mmBCI_DEBUG_READ__SI = 0x24E3; +constexpr unsigned int mmBIF_BACO_DEBUG_LATCH__CI__VI = 0x14DC; +constexpr unsigned int mmBIF_BACO_DEBUG__CI__VI = 0x14DF; +constexpr unsigned int mmBIF_BACO_MSIC__CI = 0x1480; +constexpr unsigned int mmBIF_BUSNUM_CNTL1 = 0x1525; +constexpr unsigned int mmBIF_BUSNUM_CNTL2 = 0x152B; +constexpr unsigned int mmBIF_BUSNUM_LIST0 = 0x1526; +constexpr unsigned int mmBIF_BUSNUM_LIST1 = 0x1527; +constexpr unsigned int mmBIF_BUSY_DELAY_CNTR = 0x1529; +constexpr unsigned int mmBIF_CC_RFE_IMP_OVERRIDECNTL__CI__VI = 0x1455; +constexpr unsigned int mmBIF_CLK_PDWN_DELAY_TIMER__CI = 0x1483; +constexpr unsigned int mmBIF_CLK_PDWN_DELAY_TIMER__SI = 0x151F; +constexpr unsigned int mmBIF_DEBUG_CNTL = 0x151C; +constexpr unsigned int mmBIF_DEBUG_MUX = 0x151D; +constexpr unsigned int mmBIF_DEBUG_OUT = 0x151E; +constexpr unsigned int mmBIF_DEVFUNCNUM_LIST0__CI__VI = 0x14E8; +constexpr unsigned int mmBIF_DEVFUNCNUM_LIST1__CI__VI = 0x14E7; +constexpr unsigned int mmBIF_DOORBELL_CNTL__CI__VI = 0x14C3; +constexpr unsigned int mmBIF_FB_EN = 0x1524; +constexpr unsigned int mmBIF_FEATURES_CONTROL_MISC__CI__VI = 0x14C2; +constexpr unsigned int mmBIF_IMPCTL_CONTINUOUS_CALIBRATION_PERIOD__CI__VI = 0x1454; +constexpr unsigned int mmBIF_IMPCTL_RXCNTL__CI__VI = 0x1451; +constexpr unsigned int mmBIF_IMPCTL_SMPLCNTL__CI__VI = 0x1450; +constexpr unsigned int mmBIF_IMPCTL_TXCNTL_pd__CI__VI = 0x1452; +constexpr unsigned int mmBIF_IMPCTL_TXCNTL_pu__CI__VI = 0x1453; +constexpr unsigned int mmBIF_LNCNT_RESET__CI = 0x1488; +constexpr unsigned int mmBIF_PERFCOUNTER0_RESULT__CI__VI = 0x152D; +constexpr unsigned int mmBIF_PERFCOUNTER1_RESULT__CI__VI = 0x152E; +constexpr unsigned int mmBIF_PERFMON_CNTL__CI__VI = 0x152C; +constexpr unsigned int mmBIF_PIF_TXCLK_SWITCH_TIMER__CI = 0x1481; +constexpr unsigned int mmBIF_PWDN_COMMAND__CI__VI = 0x1444; +constexpr unsigned int mmBIF_PWDN_STATUS__CI__VI = 0x1445; +constexpr unsigned int mmBIF_RESET_CNTL__CI = 0x1486; +constexpr unsigned int mmBIF_RESET_EN__CI = 0x1482; +constexpr unsigned int mmBIF_RESET_EN__SI = 0x1511; +constexpr unsigned int mmBIF_RFE_CLIENT_SOFTRST_TRIGGER__CI__VI = 0x1442; +constexpr unsigned int mmBIF_RFE_IMPRST_CNTL__CI__VI = 0x1458; +constexpr unsigned int mmBIF_RFE_MASTER_SOFTRST_TRIGGER__CI__VI = 0x1443; +constexpr unsigned int mmBIF_RFE_MMCFG_CNTL__CI__VI = 0x144C; +constexpr unsigned int mmBIF_RFE_MST_BU_CMDSTATUS__CI__VI = 0x1446; +constexpr unsigned int mmBIF_RFE_MST_BX_CMDSTATUS__CI = 0x1448; +constexpr unsigned int mmBIF_RFE_MST_RWREG_RFEWDBIF_CMDSTATUS__CI__VI = 0x1447; +constexpr unsigned int mmBIF_RFE_MST_TMOUT_STATUS__CI__VI = 0x144B; +constexpr unsigned int mmBIF_RFE_SNOOP_REG__CI__VI = 0x0027; +constexpr unsigned int mmBIF_RFE_SOFTRST_CNTL__CI__VI = 0x1441; +constexpr unsigned int mmBIF_SCRATCH0 = 0x150E; +constexpr unsigned int mmBIF_SCRATCH1 = 0x150F; +constexpr unsigned int mmBIF_SLVARB_MODE__CI__VI = 0x14C4; +constexpr unsigned int mmBIF_SSA_DISP_LOWER__CI = 0x14D2; +constexpr unsigned int mmBIF_SSA_DISP_UPPER__CI = 0x14D3; +constexpr unsigned int mmBIF_SSA_GFX0_LOWER__CI = 0x14CA; +constexpr unsigned int mmBIF_SSA_GFX0_UPPER__CI = 0x14CB; +constexpr unsigned int mmBIF_SSA_GFX1_LOWER__CI = 0x14CC; +constexpr unsigned int mmBIF_SSA_GFX1_UPPER__CI = 0x14CD; +constexpr unsigned int mmBIF_SSA_GFX2_LOWER__CI = 0x14CE; +constexpr unsigned int mmBIF_SSA_GFX2_UPPER__CI = 0x14CF; +constexpr unsigned int mmBIF_SSA_GFX3_LOWER__CI = 0x14D0; +constexpr unsigned int mmBIF_SSA_GFX3_UPPER__CI = 0x14D1; +constexpr unsigned int mmBIF_SSA_MC_LOWER__CI = 0x14D4; +constexpr unsigned int mmBIF_SSA_MC_UPPER__CI = 0x14D5; +constexpr unsigned int mmBIF_SSA_PWR_STATUS__CI = 0x14C8; +constexpr unsigned int mmBIF_XDMA_HI__CI__VI = 0x14C1; +constexpr unsigned int mmBIF_XDMA_LO__CI__VI = 0x14C0; +constexpr unsigned int mmBIOS_SCRATCH_0 = 0x05C9; +constexpr unsigned int mmBIOS_SCRATCH_1 = 0x05CA; +constexpr unsigned int mmBIOS_SCRATCH_10 = 0x05D3; +constexpr unsigned int mmBIOS_SCRATCH_11 = 0x05D4; +constexpr unsigned int mmBIOS_SCRATCH_12 = 0x05D5; +constexpr unsigned int mmBIOS_SCRATCH_13 = 0x05D6; +constexpr unsigned int mmBIOS_SCRATCH_14 = 0x05D7; +constexpr unsigned int mmBIOS_SCRATCH_15 = 0x05D8; +constexpr unsigned int mmBIOS_SCRATCH_2 = 0x05CB; +constexpr unsigned int mmBIOS_SCRATCH_3 = 0x05CC; +constexpr unsigned int mmBIOS_SCRATCH_4 = 0x05CD; +constexpr unsigned int mmBIOS_SCRATCH_5 = 0x05CE; +constexpr unsigned int mmBIOS_SCRATCH_6 = 0x05CF; +constexpr unsigned int mmBIOS_SCRATCH_7 = 0x05D0; +constexpr unsigned int mmBIOS_SCRATCH_8 = 0x05D1; +constexpr unsigned int mmBIOS_SCRATCH_9 = 0x05D2; +constexpr unsigned int mmBL1_PWM_ABM_CNTL__SI__VI = 0x162E; +constexpr unsigned int mmBL1_PWM_AMBIENT_LIGHT_LEVEL__SI__VI = 0x1628; +constexpr unsigned int mmBL1_PWM_BL_UPDATE_SAMPLE_RATE__SI__VI = 0x162F; +constexpr unsigned int mmBL1_PWM_CURRENT_ABM_LEVEL__SI__VI = 0x162B; +constexpr unsigned int mmBL1_PWM_FINAL_DUTY_CYCLE__SI__VI = 0x162C; +constexpr unsigned int mmBL1_PWM_GRP2_REG_LOCK__SI__VI = 0x1630; +constexpr unsigned int mmBL1_PWM_MINIMUM_DUTY_CYCLE__SI__VI = 0x162D; +constexpr unsigned int mmBL1_PWM_TARGET_ABM_LEVEL__SI__VI = 0x162A; +constexpr unsigned int mmBL1_PWM_USER_LEVEL__SI__VI = 0x1629; +constexpr unsigned int mmBL_PWM_CNTL2__SI = 0x1968; +constexpr unsigned int mmBL_PWM_CNTL__SI = 0x1967; +constexpr unsigned int mmBL_PWM_GRP1_REG_LOCK__SI = 0x196A; +constexpr unsigned int mmBL_PWM_PERIOD_CNTL__SI = 0x1969; +constexpr unsigned int mmBUS_CNTL = 0x1508; +constexpr unsigned int mmBX_RESET_EN__CI__VI = 0x1514; +constexpr unsigned int mmCAPTURE_HOST_BUSNUM = 0x153C; +constexpr unsigned int mmCB_BLEND0_CONTROL = 0xA1E0; +constexpr unsigned int mmCB_BLEND1_CONTROL = 0xA1E1; +constexpr unsigned int mmCB_BLEND2_CONTROL = 0xA1E2; +constexpr unsigned int mmCB_BLEND3_CONTROL = 0xA1E3; +constexpr unsigned int mmCB_BLEND4_CONTROL = 0xA1E4; +constexpr unsigned int mmCB_BLEND5_CONTROL = 0xA1E5; +constexpr unsigned int mmCB_BLEND6_CONTROL = 0xA1E6; +constexpr unsigned int mmCB_BLEND7_CONTROL = 0xA1E7; +constexpr unsigned int mmCB_BLEND_ALPHA = 0xA108; +constexpr unsigned int mmCB_BLEND_BLUE = 0xA107; +constexpr unsigned int mmCB_BLEND_GREEN = 0xA106; +constexpr unsigned int mmCB_BLEND_RED = 0xA105; +constexpr unsigned int mmCB_CGTT_SCLK_CTRL__CI__VI = 0xF0A8; +constexpr unsigned int mmCB_CGTT_SCLK_CTRL__SI = 0x2698; +constexpr unsigned int mmCB_COLOR0_ATTRIB = 0xA31D; +constexpr unsigned int mmCB_COLOR0_BASE = 0xA318; +constexpr unsigned int mmCB_COLOR0_CLEAR_WORD0 = 0xA323; +constexpr unsigned int mmCB_COLOR0_CLEAR_WORD1 = 0xA324; +constexpr unsigned int mmCB_COLOR0_CMASK = 0xA31F; +constexpr unsigned int mmCB_COLOR0_CMASK_SLICE = 0xA320; +constexpr unsigned int mmCB_COLOR0_FMASK = 0xA321; +constexpr unsigned int mmCB_COLOR0_FMASK_SLICE = 0xA322; +constexpr unsigned int mmCB_COLOR0_INFO = 0xA31C; +constexpr unsigned int mmCB_COLOR0_PITCH = 0xA319; +constexpr unsigned int mmCB_COLOR0_SLICE = 0xA31A; +constexpr unsigned int mmCB_COLOR0_VIEW = 0xA31B; +constexpr unsigned int mmCB_COLOR1_ATTRIB = 0xA32C; +constexpr unsigned int mmCB_COLOR1_BASE = 0xA327; +constexpr unsigned int mmCB_COLOR1_CLEAR_WORD0 = 0xA332; +constexpr unsigned int mmCB_COLOR1_CLEAR_WORD1 = 0xA333; +constexpr unsigned int mmCB_COLOR1_CMASK = 0xA32E; +constexpr unsigned int mmCB_COLOR1_CMASK_SLICE = 0xA32F; +constexpr unsigned int mmCB_COLOR1_FMASK = 0xA330; +constexpr unsigned int mmCB_COLOR1_FMASK_SLICE = 0xA331; +constexpr unsigned int mmCB_COLOR1_INFO = 0xA32B; +constexpr unsigned int mmCB_COLOR1_PITCH = 0xA328; +constexpr unsigned int mmCB_COLOR1_SLICE = 0xA329; +constexpr unsigned int mmCB_COLOR1_VIEW = 0xA32A; +constexpr unsigned int mmCB_COLOR2_ATTRIB = 0xA33B; +constexpr unsigned int mmCB_COLOR2_BASE = 0xA336; +constexpr unsigned int mmCB_COLOR2_CLEAR_WORD0 = 0xA341; +constexpr unsigned int mmCB_COLOR2_CLEAR_WORD1 = 0xA342; +constexpr unsigned int mmCB_COLOR2_CMASK = 0xA33D; +constexpr unsigned int mmCB_COLOR2_CMASK_SLICE = 0xA33E; +constexpr unsigned int mmCB_COLOR2_FMASK = 0xA33F; +constexpr unsigned int mmCB_COLOR2_FMASK_SLICE = 0xA340; +constexpr unsigned int mmCB_COLOR2_INFO = 0xA33A; +constexpr unsigned int mmCB_COLOR2_PITCH = 0xA337; +constexpr unsigned int mmCB_COLOR2_SLICE = 0xA338; +constexpr unsigned int mmCB_COLOR2_VIEW = 0xA339; +constexpr unsigned int mmCB_COLOR3_ATTRIB = 0xA34A; +constexpr unsigned int mmCB_COLOR3_BASE = 0xA345; +constexpr unsigned int mmCB_COLOR3_CLEAR_WORD0 = 0xA350; +constexpr unsigned int mmCB_COLOR3_CLEAR_WORD1 = 0xA351; +constexpr unsigned int mmCB_COLOR3_CMASK = 0xA34C; +constexpr unsigned int mmCB_COLOR3_CMASK_SLICE = 0xA34D; +constexpr unsigned int mmCB_COLOR3_FMASK = 0xA34E; +constexpr unsigned int mmCB_COLOR3_FMASK_SLICE = 0xA34F; +constexpr unsigned int mmCB_COLOR3_INFO = 0xA349; +constexpr unsigned int mmCB_COLOR3_PITCH = 0xA346; +constexpr unsigned int mmCB_COLOR3_SLICE = 0xA347; +constexpr unsigned int mmCB_COLOR3_VIEW = 0xA348; +constexpr unsigned int mmCB_COLOR4_ATTRIB = 0xA359; +constexpr unsigned int mmCB_COLOR4_BASE = 0xA354; +constexpr unsigned int mmCB_COLOR4_CLEAR_WORD0 = 0xA35F; +constexpr unsigned int mmCB_COLOR4_CLEAR_WORD1 = 0xA360; +constexpr unsigned int mmCB_COLOR4_CMASK = 0xA35B; +constexpr unsigned int mmCB_COLOR4_CMASK_SLICE = 0xA35C; +constexpr unsigned int mmCB_COLOR4_FMASK = 0xA35D; +constexpr unsigned int mmCB_COLOR4_FMASK_SLICE = 0xA35E; +constexpr unsigned int mmCB_COLOR4_INFO = 0xA358; +constexpr unsigned int mmCB_COLOR4_PITCH = 0xA355; +constexpr unsigned int mmCB_COLOR4_SLICE = 0xA356; +constexpr unsigned int mmCB_COLOR4_VIEW = 0xA357; +constexpr unsigned int mmCB_COLOR5_ATTRIB = 0xA368; +constexpr unsigned int mmCB_COLOR5_BASE = 0xA363; +constexpr unsigned int mmCB_COLOR5_CLEAR_WORD0 = 0xA36E; +constexpr unsigned int mmCB_COLOR5_CLEAR_WORD1 = 0xA36F; +constexpr unsigned int mmCB_COLOR5_CMASK = 0xA36A; +constexpr unsigned int mmCB_COLOR5_CMASK_SLICE = 0xA36B; +constexpr unsigned int mmCB_COLOR5_FMASK = 0xA36C; +constexpr unsigned int mmCB_COLOR5_FMASK_SLICE = 0xA36D; +constexpr unsigned int mmCB_COLOR5_INFO = 0xA367; +constexpr unsigned int mmCB_COLOR5_PITCH = 0xA364; +constexpr unsigned int mmCB_COLOR5_SLICE = 0xA365; +constexpr unsigned int mmCB_COLOR5_VIEW = 0xA366; +constexpr unsigned int mmCB_COLOR6_ATTRIB = 0xA377; +constexpr unsigned int mmCB_COLOR6_BASE = 0xA372; +constexpr unsigned int mmCB_COLOR6_CLEAR_WORD0 = 0xA37D; +constexpr unsigned int mmCB_COLOR6_CLEAR_WORD1 = 0xA37E; +constexpr unsigned int mmCB_COLOR6_CMASK = 0xA379; +constexpr unsigned int mmCB_COLOR6_CMASK_SLICE = 0xA37A; +constexpr unsigned int mmCB_COLOR6_FMASK = 0xA37B; +constexpr unsigned int mmCB_COLOR6_FMASK_SLICE = 0xA37C; +constexpr unsigned int mmCB_COLOR6_INFO = 0xA376; +constexpr unsigned int mmCB_COLOR6_PITCH = 0xA373; +constexpr unsigned int mmCB_COLOR6_SLICE = 0xA374; +constexpr unsigned int mmCB_COLOR6_VIEW = 0xA375; +constexpr unsigned int mmCB_COLOR7_ATTRIB = 0xA386; +constexpr unsigned int mmCB_COLOR7_BASE = 0xA381; +constexpr unsigned int mmCB_COLOR7_CLEAR_WORD0 = 0xA38C; +constexpr unsigned int mmCB_COLOR7_CLEAR_WORD1 = 0xA38D; +constexpr unsigned int mmCB_COLOR7_CMASK = 0xA388; +constexpr unsigned int mmCB_COLOR7_CMASK_SLICE = 0xA389; +constexpr unsigned int mmCB_COLOR7_FMASK = 0xA38A; +constexpr unsigned int mmCB_COLOR7_FMASK_SLICE = 0xA38B; +constexpr unsigned int mmCB_COLOR7_INFO = 0xA385; +constexpr unsigned int mmCB_COLOR7_PITCH = 0xA382; +constexpr unsigned int mmCB_COLOR7_SLICE = 0xA383; +constexpr unsigned int mmCB_COLOR7_VIEW = 0xA384; +constexpr unsigned int mmCB_COLOR_CONTROL = 0xA202; +constexpr unsigned int mmCB_DEBUG_BUS_1 = 0x2699; +constexpr unsigned int mmCB_DEBUG_BUS_13 = 0x26A5; +constexpr unsigned int mmCB_DEBUG_BUS_14 = 0x26A6; +constexpr unsigned int mmCB_DEBUG_BUS_15 = 0x26A7; +constexpr unsigned int mmCB_DEBUG_BUS_16 = 0x26A8; +constexpr unsigned int mmCB_DEBUG_BUS_17 = 0x26A9; +constexpr unsigned int mmCB_DEBUG_BUS_18 = 0x26AA; +constexpr unsigned int mmCB_DEBUG_BUS_2 = 0x269A; +constexpr unsigned int mmCB_HW_CONTROL = 0x2684; +constexpr unsigned int mmCB_HW_CONTROL_1 = 0x2685; +constexpr unsigned int mmCB_HW_CONTROL_2 = 0x2686; +constexpr unsigned int mmCB_HW_CONTROL_3__CI__VI = 0x2683; +constexpr unsigned int mmCB_PERFCOUNTER0_HI__CI__VI = 0xD407; +constexpr unsigned int mmCB_PERFCOUNTER0_HI__SI = 0x2691; +constexpr unsigned int mmCB_PERFCOUNTER0_LO__CI__VI = 0xD406; +constexpr unsigned int mmCB_PERFCOUNTER0_LO__SI = 0x2690; +constexpr unsigned int mmCB_PERFCOUNTER0_SELECT0__SI = 0x2688; +constexpr unsigned int mmCB_PERFCOUNTER0_SELECT1__CI__VI = 0xDC02; +constexpr unsigned int mmCB_PERFCOUNTER0_SELECT1__SI = 0x2689; +constexpr unsigned int mmCB_PERFCOUNTER0_SELECT__CI__VI = 0xDC01; +constexpr unsigned int mmCB_PERFCOUNTER1_HI__CI__VI = 0xD409; +constexpr unsigned int mmCB_PERFCOUNTER1_HI__SI = 0x2693; +constexpr unsigned int mmCB_PERFCOUNTER1_LO__CI__VI = 0xD408; +constexpr unsigned int mmCB_PERFCOUNTER1_LO__SI = 0x2692; +constexpr unsigned int mmCB_PERFCOUNTER1_SELECT0__SI = 0x268A; +constexpr unsigned int mmCB_PERFCOUNTER1_SELECT1__SI = 0x268B; +constexpr unsigned int mmCB_PERFCOUNTER1_SELECT__CI__VI = 0xDC03; +constexpr unsigned int mmCB_PERFCOUNTER2_HI__CI__VI = 0xD40B; +constexpr unsigned int mmCB_PERFCOUNTER2_HI__SI = 0x2695; +constexpr unsigned int mmCB_PERFCOUNTER2_LO__CI__VI = 0xD40A; +constexpr unsigned int mmCB_PERFCOUNTER2_LO__SI = 0x2694; +constexpr unsigned int mmCB_PERFCOUNTER2_SELECT0__SI = 0x268C; +constexpr unsigned int mmCB_PERFCOUNTER2_SELECT1__SI = 0x268D; +constexpr unsigned int mmCB_PERFCOUNTER2_SELECT__CI__VI = 0xDC04; +constexpr unsigned int mmCB_PERFCOUNTER3_HI__CI__VI = 0xD40D; +constexpr unsigned int mmCB_PERFCOUNTER3_HI__SI = 0x2697; +constexpr unsigned int mmCB_PERFCOUNTER3_LO__CI__VI = 0xD40C; +constexpr unsigned int mmCB_PERFCOUNTER3_LO__SI = 0x2696; +constexpr unsigned int mmCB_PERFCOUNTER3_SELECT0__SI = 0x268E; +constexpr unsigned int mmCB_PERFCOUNTER3_SELECT1__SI = 0x268F; +constexpr unsigned int mmCB_PERFCOUNTER3_SELECT__CI__VI = 0xDC05; +constexpr unsigned int mmCB_PERFCOUNTER_FILTER__CI__VI = 0xDC00; +constexpr unsigned int mmCB_SHADER_MASK = 0xA08F; +constexpr unsigned int mmCB_TARGET_MASK = 0xA08E; +constexpr unsigned int mmCC_DRM_ID_STRAPS = 0x1559; +constexpr unsigned int mmCC_GC_EDC_CONFIG__CI__VI = 0x3098; +constexpr unsigned int mmCC_GC_PRIM_CONFIG__CI__VI = 0x2240; +constexpr unsigned int mmCC_GC_SHADER_ARRAY_CONFIG = 0x226F; +constexpr unsigned int mmCC_MC_MAX_CHANNEL = 0x096E; +constexpr unsigned int mmCC_RB_BACKEND_DISABLE = 0x263D; +constexpr unsigned int mmCC_RB_DAISY_CHAIN = 0x2641; +constexpr unsigned int mmCC_RB_REDUNDANCY = 0x263C; +constexpr unsigned int mmCC_SQC_BANK_DISABLE = 0x2307; +constexpr unsigned int mmCC_SYS_RB_BACKEND_DISABLE = 0x03A0; +constexpr unsigned int mmCC_SYS_RB_REDUNDANCY = 0x039F; +constexpr unsigned int mmCGTS_CU0_LDS_SQ_CTRL_REG__CI__VI = 0xF009; +constexpr unsigned int mmCGTS_CU0_SP0_CTRL_REG__CI__VI = 0xF008; +constexpr unsigned int mmCGTS_CU0_SP1_CTRL_REG__CI__VI = 0xF00B; +constexpr unsigned int mmCGTS_CU0_TA_SQC_CTRL_REG__CI__VI = 0xF00A; +constexpr unsigned int mmCGTS_CU0_TD_TCP_CTRL_REG__CI__VI = 0xF00C; +constexpr unsigned int mmCGTS_CU10_LDS_SQ_CTRL_REG__CI__VI = 0xF03B; +constexpr unsigned int mmCGTS_CU10_SP0_CTRL_REG__CI__VI = 0xF03A; +constexpr unsigned int mmCGTS_CU10_SP1_CTRL_REG__CI__VI = 0xF03D; +constexpr unsigned int mmCGTS_CU10_TA_CTRL_REG__CI__VI = 0xF03C; +constexpr unsigned int mmCGTS_CU10_TD_TCP_CTRL_REG__CI__VI = 0xF03E; +constexpr unsigned int mmCGTS_CU11_LDS_SQ_CTRL_REG__CI__VI = 0xF040; +constexpr unsigned int mmCGTS_CU11_SP0_CTRL_REG__CI__VI = 0xF03F; +constexpr unsigned int mmCGTS_CU11_SP1_CTRL_REG__CI__VI = 0xF042; +constexpr unsigned int mmCGTS_CU11_TA_CTRL_REG__CI__VI = 0xF041; +constexpr unsigned int mmCGTS_CU11_TD_TCP_CTRL_REG__CI__VI = 0xF043; +constexpr unsigned int mmCGTS_CU12_LDS_SQ_CTRL_REG__CI__VI = 0xF045; +constexpr unsigned int mmCGTS_CU12_SP0_CTRL_REG__CI__VI = 0xF044; +constexpr unsigned int mmCGTS_CU12_SP1_CTRL_REG__CI__VI = 0xF047; +constexpr unsigned int mmCGTS_CU12_TA_SQC_CTRL_REG__CI__VI = 0xF046; +constexpr unsigned int mmCGTS_CU12_TD_TCP_CTRL_REG__CI__VI = 0xF048; +constexpr unsigned int mmCGTS_CU13_LDS_SQ_CTRL_REG__CI__VI = 0xF04A; +constexpr unsigned int mmCGTS_CU13_SP0_CTRL_REG__CI__VI = 0xF049; +constexpr unsigned int mmCGTS_CU13_SP1_CTRL_REG__CI__VI = 0xF04C; +constexpr unsigned int mmCGTS_CU13_TA_CTRL_REG__CI__VI = 0xF04B; +constexpr unsigned int mmCGTS_CU13_TD_TCP_CTRL_REG__CI__VI = 0xF04D; +constexpr unsigned int mmCGTS_CU14_LDS_SQ_CTRL_REG__CI__VI = 0xF04F; +constexpr unsigned int mmCGTS_CU14_SP0_CTRL_REG__CI__VI = 0xF04E; +constexpr unsigned int mmCGTS_CU14_SP1_CTRL_REG__CI__VI = 0xF051; +constexpr unsigned int mmCGTS_CU14_TA_CTRL_REG__CI__VI = 0xF050; +constexpr unsigned int mmCGTS_CU14_TD_TCP_CTRL_REG__CI__VI = 0xF052; +constexpr unsigned int mmCGTS_CU15_LDS_SQ_CTRL_REG__CI__VI = 0xF054; +constexpr unsigned int mmCGTS_CU15_SP0_CTRL_REG__CI__VI = 0xF053; +constexpr unsigned int mmCGTS_CU15_SP1_CTRL_REG__CI__VI = 0xF056; +constexpr unsigned int mmCGTS_CU15_TA_CTRL_REG__CI__VI = 0xF055; +constexpr unsigned int mmCGTS_CU15_TD_TCP_CTRL_REG__CI__VI = 0xF057; +constexpr unsigned int mmCGTS_CU1_LDS_SQ_CTRL_REG__CI__VI = 0xF00E; +constexpr unsigned int mmCGTS_CU1_SP0_CTRL_REG__CI__VI = 0xF00D; +constexpr unsigned int mmCGTS_CU1_SP1_CTRL_REG__CI__VI = 0xF010; +constexpr unsigned int mmCGTS_CU1_TA_CTRL_REG__CI__VI = 0xF00F; +constexpr unsigned int mmCGTS_CU1_TD_TCP_CTRL_REG__CI__VI = 0xF011; +constexpr unsigned int mmCGTS_CU2_LDS_SQ_CTRL_REG__CI__VI = 0xF013; +constexpr unsigned int mmCGTS_CU2_SP0_CTRL_REG__CI__VI = 0xF012; +constexpr unsigned int mmCGTS_CU2_SP1_CTRL_REG__CI__VI = 0xF015; +constexpr unsigned int mmCGTS_CU2_TA_CTRL_REG__CI__VI = 0xF014; +constexpr unsigned int mmCGTS_CU2_TD_TCP_CTRL_REG__CI__VI = 0xF016; +constexpr unsigned int mmCGTS_CU3_LDS_SQ_CTRL_REG__CI__VI = 0xF018; +constexpr unsigned int mmCGTS_CU3_SP0_CTRL_REG__CI__VI = 0xF017; +constexpr unsigned int mmCGTS_CU3_SP1_CTRL_REG__CI__VI = 0xF01A; +constexpr unsigned int mmCGTS_CU3_TA_CTRL_REG__CI__VI = 0xF019; +constexpr unsigned int mmCGTS_CU3_TD_TCP_CTRL_REG__CI__VI = 0xF01B; +constexpr unsigned int mmCGTS_CU4_LDS_SQ_CTRL_REG__CI__VI = 0xF01D; +constexpr unsigned int mmCGTS_CU4_SP0_CTRL_REG__CI__VI = 0xF01C; +constexpr unsigned int mmCGTS_CU4_SP1_CTRL_REG__CI__VI = 0xF01F; +constexpr unsigned int mmCGTS_CU4_TA_SQC_CTRL_REG__CI__VI = 0xF01E; +constexpr unsigned int mmCGTS_CU4_TD_TCP_CTRL_REG__CI__VI = 0xF020; +constexpr unsigned int mmCGTS_CU5_LDS_SQ_CTRL_REG__CI__VI = 0xF022; +constexpr unsigned int mmCGTS_CU5_SP0_CTRL_REG__CI__VI = 0xF021; +constexpr unsigned int mmCGTS_CU5_SP1_CTRL_REG__CI__VI = 0xF024; +constexpr unsigned int mmCGTS_CU5_TA_CTRL_REG__CI__VI = 0xF023; +constexpr unsigned int mmCGTS_CU5_TD_TCP_CTRL_REG__CI__VI = 0xF025; +constexpr unsigned int mmCGTS_CU6_LDS_SQ_CTRL_REG__CI__VI = 0xF027; +constexpr unsigned int mmCGTS_CU6_SP0_CTRL_REG__CI__VI = 0xF026; +constexpr unsigned int mmCGTS_CU6_SP1_CTRL_REG__CI__VI = 0xF029; +constexpr unsigned int mmCGTS_CU6_TA_CTRL_REG__CI__VI = 0xF028; +constexpr unsigned int mmCGTS_CU6_TD_TCP_CTRL_REG__CI__VI = 0xF02A; +constexpr unsigned int mmCGTS_CU7_LDS_SQ_CTRL_REG__CI__VI = 0xF02C; +constexpr unsigned int mmCGTS_CU7_SP0_CTRL_REG__CI__VI = 0xF02B; +constexpr unsigned int mmCGTS_CU7_SP1_CTRL_REG__CI__VI = 0xF02E; +constexpr unsigned int mmCGTS_CU7_TA_CTRL_REG__CI__VI = 0xF02D; +constexpr unsigned int mmCGTS_CU7_TD_TCP_CTRL_REG__CI__VI = 0xF02F; +constexpr unsigned int mmCGTS_CU8_LDS_SQ_CTRL_REG__CI__VI = 0xF031; +constexpr unsigned int mmCGTS_CU8_SP0_CTRL_REG__CI__VI = 0xF030; +constexpr unsigned int mmCGTS_CU8_SP1_CTRL_REG__CI__VI = 0xF033; +constexpr unsigned int mmCGTS_CU8_TA_SQC_CTRL_REG__CI__VI = 0xF032; +constexpr unsigned int mmCGTS_CU8_TD_TCP_CTRL_REG__CI__VI = 0xF034; +constexpr unsigned int mmCGTS_CU9_LDS_SQ_CTRL_REG__CI__VI = 0xF036; +constexpr unsigned int mmCGTS_CU9_SP0_CTRL_REG__CI__VI = 0xF035; +constexpr unsigned int mmCGTS_CU9_SP1_CTRL_REG__CI__VI = 0xF038; +constexpr unsigned int mmCGTS_CU9_TA_CTRL_REG__CI__VI = 0xF037; +constexpr unsigned int mmCGTS_CU9_TD_TCP_CTRL_REG__CI__VI = 0xF039; +constexpr unsigned int mmCGTS_RD_CTRL_REG__CI__VI = 0xF001; +constexpr unsigned int mmCGTS_RD_CTRL_REG__SI = 0x2455; +constexpr unsigned int mmCGTS_RD_REG__CI__VI = 0xF002; +constexpr unsigned int mmCGTS_RD_REG__SI = 0x2456; +constexpr unsigned int mmCGTS_SM_CTRL_REG__CI__VI = 0xF000; +constexpr unsigned int mmCGTS_SM_CTRL_REG__SI = 0x2454; +constexpr unsigned int mmCGTS_TCC_DISABLE__CI__VI = 0xF003; +constexpr unsigned int mmCGTS_TCC_DISABLE__SI = 0x2452; +constexpr unsigned int mmCGTS_USER_TCC_DISABLE__CI__VI = 0xF004; +constexpr unsigned int mmCGTS_USER_TCC_DISABLE__SI = 0x2453; +constexpr unsigned int mmCGTT_BCI_CLK_CTRL__CI__VI = 0xF082; +constexpr unsigned int mmCGTT_BCI_CLK_CTRL__SI = 0x24A9; +constexpr unsigned int mmCGTT_CPC_CLK_CTRL__CI__VI = 0xF0B2; +constexpr unsigned int mmCGTT_CPF_CLK_CTRL__CI__VI = 0xF0B1; +constexpr unsigned int mmCGTT_CP_CLK_CTRL__CI__VI = 0xF0B0; +constexpr unsigned int mmCGTT_CP_CLK_CTRL__SI = 0x3059; +constexpr unsigned int mmCGTT_GDS_CLK_CTRL__CI__VI = 0xF0A0; +constexpr unsigned int mmCGTT_GDS_CLK_CTRL__SI = 0x25DD; +constexpr unsigned int mmCGTT_IA_CLK_CTRL__CI__VI = 0xF085; +constexpr unsigned int mmCGTT_IA_CLK_CTRL__SI = 0x2261; +constexpr unsigned int mmCGTT_PA_CLK_CTRL__CI__VI = 0xF088; +constexpr unsigned int mmCGTT_PA_CLK_CTRL__SI = 0x2286; +constexpr unsigned int mmCGTT_PC_CLK_CTRL__CI__VI = 0xF081; +constexpr unsigned int mmCGTT_PC_CLK_CTRL__SI = 0x24A8; +constexpr unsigned int mmCGTT_RLC_CLK_CTRL__CI__VI = 0xF0B8; +constexpr unsigned int mmCGTT_RLC_CLK_CTRL__SI = 0x30E0; +constexpr unsigned int mmCGTT_ROM_CLK_CTRL0__SI = 0x0583; +constexpr unsigned int mmCGTT_SC_CLK_CTRL__CI__VI = 0xF089; +constexpr unsigned int mmCGTT_SC_CLK_CTRL__SI = 0x22CA; +constexpr unsigned int mmCGTT_SPI_CLK_CTRL__CI__VI = 0xF080; +constexpr unsigned int mmCGTT_SPI_CLK_CTRL__SI = 0x2451; +constexpr unsigned int mmCGTT_SQG_CLK_CTRL__CI__VI = 0xF08D; +constexpr unsigned int mmCGTT_SQG_CLK_CTRL__SI = 0x2363; +constexpr unsigned int mmCGTT_SQ_CLK_CTRL__CI__VI = 0xF08C; +constexpr unsigned int mmCGTT_SQ_CLK_CTRL__SI = 0x2362; +constexpr unsigned int mmCGTT_SX_CLK_CTRL0__CI__VI = 0xF094; +constexpr unsigned int mmCGTT_SX_CLK_CTRL0__SI = 0x240C; +constexpr unsigned int mmCGTT_SX_CLK_CTRL1__CI__VI = 0xF095; +constexpr unsigned int mmCGTT_SX_CLK_CTRL1__SI = 0x240D; +constexpr unsigned int mmCGTT_SX_CLK_CTRL2__CI__VI = 0xF096; +constexpr unsigned int mmCGTT_SX_CLK_CTRL2__SI = 0x240E; +constexpr unsigned int mmCGTT_SX_CLK_CTRL3__CI__VI = 0xF097; +constexpr unsigned int mmCGTT_SX_CLK_CTRL3__SI = 0x240F; +constexpr unsigned int mmCGTT_SX_CLK_CTRL4__CI__VI = 0xF098; +constexpr unsigned int mmCGTT_SX_CLK_CTRL4__SI = 0x2410; +constexpr unsigned int mmCGTT_TCI_CLK_CTRL__CI__VI = 0xF09F; +constexpr unsigned int mmCGTT_TCI_CLK_CTRL__SI = 0x2B60; +constexpr unsigned int mmCGTT_TCP_CLK_CTRL__CI__VI = 0xF09E; +constexpr unsigned int mmCGTT_TCP_CLK_CTRL__SI = 0x2B15; +constexpr unsigned int mmCGTT_VGT_CLK_CTRL__CI__VI = 0xF084; +constexpr unsigned int mmCGTT_VGT_CLK_CTRL__SI = 0x225F; +constexpr unsigned int mmCGTT_WD_CLK_CTRL__CI__VI = 0xF086; +constexpr unsigned int mmCG_CLKPIN_CNTL__SI = 0x0198; +constexpr unsigned int mmCG_DISPLAY_GAP_CNTL__SI = 0x020A; +constexpr unsigned int mmCG_FDO_CTRL0__SI = 0x01D5; +constexpr unsigned int mmCG_FDO_CTRL1__SI = 0x01D6; +constexpr unsigned int mmCG_FDO_CTRL2__SI = 0x01D7; +constexpr unsigned int mmCG_FPS_CNT__CI = 0x0194; +constexpr unsigned int mmCG_FREQ_TRAN_VOTING__SI = 0x01EF; +constexpr unsigned int mmCG_MULT_THERMAL_CTRL__SI = 0x01C4; +constexpr unsigned int mmCG_MULT_THERMAL_STATUS__SI = 0x01C5; +constexpr unsigned int mmCG_SPLL_FUNC_CNTL_2__SI = 0x0181; +constexpr unsigned int mmCG_SPLL_FUNC_CNTL_3__SI = 0x0182; +constexpr unsigned int mmCG_SPLL_FUNC_CNTL_4__SI = 0x0183; +constexpr unsigned int mmCG_SPLL_FUNC_CNTL_5__SI = 0x0184; +constexpr unsigned int mmCG_SPLL_FUNC_CNTL__SI = 0x0180; +constexpr unsigned int mmCG_SPLL_SPREAD_SPECTRUM_2__SI = 0x0189; +constexpr unsigned int mmCG_SPLL_SPREAD_SPECTRUM__SI = 0x0188; +constexpr unsigned int mmCG_STATIC_SCREEN_PARAMETER__SI = 0x0203; +constexpr unsigned int mmCG_TACH_CTRL__SI = 0x01DC; +constexpr unsigned int mmCG_TACH_STATUS__SI = 0x01DD; +constexpr unsigned int mmCG_THERMAL_CTRL__SI = 0x01C0; +constexpr unsigned int mmCG_THERMAL_INT__SI = 0x01C2; +constexpr unsigned int mmCG_THERMAL_STATUS__SI = 0x01C1; +constexpr unsigned int mmCG_ULV_PARAMETER__SI = 0x021F; +constexpr unsigned int mmCHUB_ATC_PERFCOUNTER0_CFG__CI__VI = 0x07D8; +constexpr unsigned int mmCHUB_ATC_PERFCOUNTER1_CFG__CI__VI = 0x07D9; +constexpr unsigned int mmCHUB_ATC_PERFCOUNTER_HI__CI__VI = 0x07D7; +constexpr unsigned int mmCHUB_ATC_PERFCOUNTER_LO__CI__VI = 0x07D6; +constexpr unsigned int mmCHUB_ATC_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07DA; +constexpr unsigned int mmCLKREQB_PAD_CNTL__CI__VI = 0x1521; +constexpr unsigned int mmCOHER_DEST_BASE_0 = 0xA092; +constexpr unsigned int mmCOHER_DEST_BASE_1 = 0xA093; +constexpr unsigned int mmCOHER_DEST_BASE_2 = 0xA07E; +constexpr unsigned int mmCOHER_DEST_BASE_3 = 0xA07F; +constexpr unsigned int mmCOHER_DEST_BASE_HI_0__CI__VI = 0xA07A; +constexpr unsigned int mmCOHER_DEST_BASE_HI_1__CI__VI = 0xA07B; +constexpr unsigned int mmCOHER_DEST_BASE_HI_2__CI__VI = 0xA07C; +constexpr unsigned int mmCOHER_DEST_BASE_HI_3__CI__VI = 0xA07D; +constexpr unsigned int mmCOMPUTE_DIM_X = 0x2E01; +constexpr unsigned int mmCOMPUTE_DIM_Y = 0x2E02; +constexpr unsigned int mmCOMPUTE_DIM_Z = 0x2E03; +constexpr unsigned int mmCOMPUTE_DISPATCH_INITIATOR = 0x2E00; +constexpr unsigned int mmCOMPUTE_MISC_RESERVED__CI__VI = 0x2E1F; +constexpr unsigned int mmCOMPUTE_NUM_THREAD_X = 0x2E07; +constexpr unsigned int mmCOMPUTE_NUM_THREAD_Y = 0x2E08; +constexpr unsigned int mmCOMPUTE_NUM_THREAD_Z = 0x2E09; +constexpr unsigned int mmCOMPUTE_PERFCOUNT_ENABLE__CI__VI = 0x2E0B; +constexpr unsigned int mmCOMPUTE_PGM_HI = 0x2E0D; +constexpr unsigned int mmCOMPUTE_PGM_LO = 0x2E0C; +constexpr unsigned int mmCOMPUTE_PGM_RSRC1 = 0x2E12; +constexpr unsigned int mmCOMPUTE_PGM_RSRC2 = 0x2E13; +constexpr unsigned int mmCOMPUTE_PIPELINESTAT_ENABLE__CI__VI = 0x2E0A; +constexpr unsigned int mmCOMPUTE_RESOURCE_LIMITS = 0x2E15; +constexpr unsigned int mmCOMPUTE_RESTART_X__CI__VI = 0x2E1B; +constexpr unsigned int mmCOMPUTE_RESTART_Y__CI__VI = 0x2E1C; +constexpr unsigned int mmCOMPUTE_RESTART_Z__CI__VI = 0x2E1D; +constexpr unsigned int mmCOMPUTE_START_X = 0x2E04; +constexpr unsigned int mmCOMPUTE_START_Y = 0x2E05; +constexpr unsigned int mmCOMPUTE_START_Z = 0x2E06; +constexpr unsigned int mmCOMPUTE_STATIC_THREAD_MGMT_SE0 = 0x2E16; +constexpr unsigned int mmCOMPUTE_STATIC_THREAD_MGMT_SE1 = 0x2E17; +constexpr unsigned int mmCOMPUTE_STATIC_THREAD_MGMT_SE2__CI__VI = 0x2E19; +constexpr unsigned int mmCOMPUTE_STATIC_THREAD_MGMT_SE3__CI__VI = 0x2E1A; +constexpr unsigned int mmCOMPUTE_TBA_HI = 0x2E0F; +constexpr unsigned int mmCOMPUTE_TBA_LO = 0x2E0E; +constexpr unsigned int mmCOMPUTE_THREAD_TRACE_ENABLE__CI__VI = 0x2E1E; +constexpr unsigned int mmCOMPUTE_TMA_HI = 0x2E11; +constexpr unsigned int mmCOMPUTE_TMA_LO = 0x2E10; +constexpr unsigned int mmCOMPUTE_TMPRING_SIZE = 0x2E18; +constexpr unsigned int mmCOMPUTE_USER_DATA_0 = 0x2E40; +constexpr unsigned int mmCOMPUTE_USER_DATA_1 = 0x2E41; +constexpr unsigned int mmCOMPUTE_USER_DATA_10 = 0x2E4A; +constexpr unsigned int mmCOMPUTE_USER_DATA_11 = 0x2E4B; +constexpr unsigned int mmCOMPUTE_USER_DATA_12 = 0x2E4C; +constexpr unsigned int mmCOMPUTE_USER_DATA_13 = 0x2E4D; +constexpr unsigned int mmCOMPUTE_USER_DATA_14 = 0x2E4E; +constexpr unsigned int mmCOMPUTE_USER_DATA_15 = 0x2E4F; +constexpr unsigned int mmCOMPUTE_USER_DATA_2 = 0x2E42; +constexpr unsigned int mmCOMPUTE_USER_DATA_3 = 0x2E43; +constexpr unsigned int mmCOMPUTE_USER_DATA_4 = 0x2E44; +constexpr unsigned int mmCOMPUTE_USER_DATA_5 = 0x2E45; +constexpr unsigned int mmCOMPUTE_USER_DATA_6 = 0x2E46; +constexpr unsigned int mmCOMPUTE_USER_DATA_7 = 0x2E47; +constexpr unsigned int mmCOMPUTE_USER_DATA_8 = 0x2E48; +constexpr unsigned int mmCOMPUTE_USER_DATA_9 = 0x2E49; +constexpr unsigned int mmCOMPUTE_VMID = 0x2E14; +constexpr unsigned int mmCONFIG_APER_SIZE = 0x150C; +constexpr unsigned int mmCONFIG_CNTL = 0x1509; +constexpr unsigned int mmCONFIG_F0_BASE = 0x150B; +constexpr unsigned int mmCONFIG_MEMSIZE = 0x150A; +constexpr unsigned int mmCONFIG_REG_APER_SIZE = 0x150D; +constexpr unsigned int mmCPC1_CONFIG__CI = 0x0F97; +constexpr unsigned int mmCPC2_CONFIG__CI = 0x0F98; +constexpr unsigned int mmCPC_INT_CNTL__CI__VI = 0x30B4; +constexpr unsigned int mmCPC_INT_CNTX_ID__CI__VI = 0x30B7; +constexpr unsigned int mmCPC_INT_STATUS__CI__VI = 0x30B5; +constexpr unsigned int mmCPC_PERFCOUNTER0_HI__CI__VI = 0xD007; +constexpr unsigned int mmCPC_PERFCOUNTER0_LO__CI__VI = 0xD006; +constexpr unsigned int mmCPC_PERFCOUNTER0_SELECT1__CI__VI = 0xD804; +constexpr unsigned int mmCPC_PERFCOUNTER0_SELECT__CI__VI = 0xD809; +constexpr unsigned int mmCPC_PERFCOUNTER1_HI__CI__VI = 0xD005; +constexpr unsigned int mmCPC_PERFCOUNTER1_LO__CI__VI = 0xD004; +constexpr unsigned int mmCPC_PERFCOUNTER1_SELECT__CI__VI = 0xD803; +constexpr unsigned int mmCPF_PERFCOUNTER0_HI__CI__VI = 0xD00B; +constexpr unsigned int mmCPF_PERFCOUNTER0_LO__CI__VI = 0xD00A; +constexpr unsigned int mmCPF_PERFCOUNTER0_SELECT1__CI__VI = 0xD806; +constexpr unsigned int mmCPF_PERFCOUNTER0_SELECT__CI__VI = 0xD807; +constexpr unsigned int mmCPF_PERFCOUNTER1_HI__CI__VI = 0xD009; +constexpr unsigned int mmCPF_PERFCOUNTER1_LO__CI__VI = 0xD008; +constexpr unsigned int mmCPF_PERFCOUNTER1_SELECT__CI__VI = 0xD805; +constexpr unsigned int mmCPG_CONFIG__CI = 0x0F96; +constexpr unsigned int mmCPG_PERFCOUNTER0_HI__CI__VI = 0xD003; +constexpr unsigned int mmCPG_PERFCOUNTER0_LO__CI__VI = 0xD002; +constexpr unsigned int mmCPG_PERFCOUNTER0_SELECT1__CI__VI = 0xD801; +constexpr unsigned int mmCPG_PERFCOUNTER0_SELECT__CI__VI = 0xD802; +constexpr unsigned int mmCPG_PERFCOUNTER1_HI__CI__VI = 0xD001; +constexpr unsigned int mmCPG_PERFCOUNTER1_LO__CI__VI = 0xD000; +constexpr unsigned int mmCPG_PERFCOUNTER1_SELECT__CI__VI = 0xD800; +constexpr unsigned int mmCP_APPEND_ADDR_HI__CI__VI = 0xC059; +constexpr unsigned int mmCP_APPEND_ADDR_HI__SI = 0x2159; +constexpr unsigned int mmCP_APPEND_ADDR_LO__CI__VI = 0xC058; +constexpr unsigned int mmCP_APPEND_ADDR_LO__SI = 0x2158; +constexpr unsigned int mmCP_APPEND_DATA__CI__VI = 0xC05A; +constexpr unsigned int mmCP_APPEND_DATA__SI = 0x215A; +constexpr unsigned int mmCP_APPEND_LAST_CS_FENCE__CI__VI = 0xC05B; +constexpr unsigned int mmCP_APPEND_LAST_CS_FENCE__SI = 0x215B; +constexpr unsigned int mmCP_APPEND_LAST_PS_FENCE__CI__VI = 0xC05C; +constexpr unsigned int mmCP_APPEND_LAST_PS_FENCE__SI = 0x215C; +constexpr unsigned int mmCP_ATOMIC_PREOP_HI__CI__VI = 0xC05E; +constexpr unsigned int mmCP_ATOMIC_PREOP_HI__SI = 0x215E; +constexpr unsigned int mmCP_ATOMIC_PREOP_LO__CI__VI = 0xC05D; +constexpr unsigned int mmCP_ATOMIC_PREOP_LO__SI = 0x215D; +constexpr unsigned int mmCP_BUSY_STAT = 0x219F; +constexpr unsigned int mmCP_CEQ1_AVAIL = 0x21E6; +constexpr unsigned int mmCP_CEQ2_AVAIL = 0x21E7; +constexpr unsigned int mmCP_CE_COMPARE_COUNT__CI__VI = 0x20C0; +constexpr unsigned int mmCP_CE_COUNTER__CI__VI = 0xC09A; +constexpr unsigned int mmCP_CE_DE_COUNT__CI__VI = 0x20C1; +constexpr unsigned int mmCP_CE_HEADER_DUMP = 0x21A4; +constexpr unsigned int mmCP_CE_IB1_BASE_HI__CI__VI = 0xC0C7; +constexpr unsigned int mmCP_CE_IB1_BASE_HI__SI = 0x21C7; +constexpr unsigned int mmCP_CE_IB1_BASE_LO__CI__VI = 0xC0C6; +constexpr unsigned int mmCP_CE_IB1_BASE_LO__SI = 0x21C6; +constexpr unsigned int mmCP_CE_IB1_BUFSZ__CI__VI = 0xC0C8; +constexpr unsigned int mmCP_CE_IB1_BUFSZ__SI = 0x21C8; +constexpr unsigned int mmCP_CE_IB1_OFFSET__CI__VI = 0xC098; +constexpr unsigned int mmCP_CE_IB2_BASE_HI__CI__VI = 0xC0CA; +constexpr unsigned int mmCP_CE_IB2_BASE_HI__SI = 0x21CA; +constexpr unsigned int mmCP_CE_IB2_BASE_LO__CI__VI = 0xC0C9; +constexpr unsigned int mmCP_CE_IB2_BASE_LO__SI = 0x21C9; +constexpr unsigned int mmCP_CE_IB2_BUFSZ__CI__VI = 0xC0CB; +constexpr unsigned int mmCP_CE_IB2_BUFSZ__SI = 0x21CB; +constexpr unsigned int mmCP_CE_IB2_OFFSET__CI__VI = 0xC099; +constexpr unsigned int mmCP_CE_INIT_BASE_HI__CI__VI = 0xC0C4; +constexpr unsigned int mmCP_CE_INIT_BASE_HI__SI = 0x21C4; +constexpr unsigned int mmCP_CE_INIT_BASE_LO__CI__VI = 0xC0C3; +constexpr unsigned int mmCP_CE_INIT_BASE_LO__SI = 0x21C3; +constexpr unsigned int mmCP_CE_INIT_BUFSZ__CI__VI = 0xC0C5; +constexpr unsigned int mmCP_CE_INIT_BUFSZ__SI = 0x21C5; +constexpr unsigned int mmCP_CE_INTR_ROUTINE_START__CI__VI = 0x30A8; +constexpr unsigned int mmCP_CE_PRGRM_CNTR_START__CI__VI = 0x30A3; +constexpr unsigned int mmCP_CE_ROQ_IB1_STAT = 0x21E9; +constexpr unsigned int mmCP_CE_ROQ_IB2_STAT = 0x21EA; +constexpr unsigned int mmCP_CE_ROQ_RB_STAT = 0x21E8; +constexpr unsigned int mmCP_CMD_DATA = 0x21DF; +constexpr unsigned int mmCP_CMD_INDEX = 0x21DE; +constexpr unsigned int mmCP_CNTX_STAT = 0x21B8; +constexpr unsigned int mmCP_COHER_BASE_HI__CI__VI = 0xC079; +constexpr unsigned int mmCP_COHER_BASE__CI__VI = 0xC07E; +constexpr unsigned int mmCP_COHER_BASE__SI = 0x217E; +constexpr unsigned int mmCP_COHER_CNTL__CI__VI = 0xC07C; +constexpr unsigned int mmCP_COHER_CNTL__SI = 0x217C; +constexpr unsigned int mmCP_COHER_SIZE_HI__CI__VI = 0xC08C; +constexpr unsigned int mmCP_COHER_SIZE__CI__VI = 0xC07D; +constexpr unsigned int mmCP_COHER_SIZE__SI = 0x217D; +constexpr unsigned int mmCP_COHER_START_DELAY__CI__VI = 0xC07B; +constexpr unsigned int mmCP_COHER_START_DELAY__SI = 0x217B; +constexpr unsigned int mmCP_COHER_STATUS__CI__VI = 0xC07F; +constexpr unsigned int mmCP_COHER_STATUS__SI = 0x217F; +constexpr unsigned int mmCP_CONFIG__SI = 0x0F92; +constexpr unsigned int mmCP_CONTEXT_CNTL__CI__VI = 0x30AD; +constexpr unsigned int mmCP_CPC_BUSY_STAT__CI__VI = 0x2085; +constexpr unsigned int mmCP_CPC_GRBM_FREE_COUNT__CI__VI = 0x208B; +constexpr unsigned int mmCP_CPC_HALT_HYST_COUNT__CI__VI = 0x20A7; +constexpr unsigned int mmCP_CPC_MC_CNTL__CI = 0x208A; +constexpr unsigned int mmCP_CPC_SCRATCH_DATA__CI__VI = 0x2091; +constexpr unsigned int mmCP_CPC_SCRATCH_INDEX__CI__VI = 0x2090; +constexpr unsigned int mmCP_CPC_STALLED_STAT1__CI__VI = 0x2086; +constexpr unsigned int mmCP_CPC_STATUS__CI__VI = 0x2084; +constexpr unsigned int mmCP_CPF_BUSY_STAT__CI__VI = 0x2088; +constexpr unsigned int mmCP_CPF_STALLED_STAT1__CI__VI = 0x2089; +constexpr unsigned int mmCP_CPF_STATUS__CI__VI = 0x2087; +constexpr unsigned int mmCP_CSF_CNTL = 0x21B5; +constexpr unsigned int mmCP_CSF_STAT = 0x21B4; +constexpr unsigned int mmCP_DEBUG = 0x307F; +constexpr unsigned int mmCP_DEVICE_ID__CI__VI = 0x304B; +constexpr unsigned int mmCP_DE_CE_COUNT__CI__VI = 0x20C2; +constexpr unsigned int mmCP_DE_DE_COUNT__CI__VI = 0x20C4; +constexpr unsigned int mmCP_DE_LAST_INVAL_COUNT__CI__VI = 0x20C3; +constexpr unsigned int mmCP_DFY_ADDR_HI__CI__VI = 0x3022; +constexpr unsigned int mmCP_DFY_ADDR_LO__CI__VI = 0x3023; +constexpr unsigned int mmCP_DFY_CNTL__CI__VI = 0x3020; +constexpr unsigned int mmCP_DFY_DATA_0__CI__VI = 0x3024; +constexpr unsigned int mmCP_DFY_DATA_10__CI__VI = 0x302E; +constexpr unsigned int mmCP_DFY_DATA_11__CI__VI = 0x302F; +constexpr unsigned int mmCP_DFY_DATA_12__CI__VI = 0x3030; +constexpr unsigned int mmCP_DFY_DATA_13__CI__VI = 0x3031; +constexpr unsigned int mmCP_DFY_DATA_14__CI__VI = 0x3032; +constexpr unsigned int mmCP_DFY_DATA_15__CI__VI = 0x3033; +constexpr unsigned int mmCP_DFY_DATA_1__CI__VI = 0x3025; +constexpr unsigned int mmCP_DFY_DATA_2__CI__VI = 0x3026; +constexpr unsigned int mmCP_DFY_DATA_3__CI__VI = 0x3027; +constexpr unsigned int mmCP_DFY_DATA_4__CI__VI = 0x3028; +constexpr unsigned int mmCP_DFY_DATA_5__CI__VI = 0x3029; +constexpr unsigned int mmCP_DFY_DATA_6__CI__VI = 0x302A; +constexpr unsigned int mmCP_DFY_DATA_7__CI__VI = 0x302B; +constexpr unsigned int mmCP_DFY_DATA_8__CI__VI = 0x302C; +constexpr unsigned int mmCP_DFY_DATA_9__CI__VI = 0x302D; +constexpr unsigned int mmCP_DFY_STAT__CI__VI = 0x3021; +constexpr unsigned int mmCP_DMA_CNTL__CI__VI = 0xC08A; +constexpr unsigned int mmCP_DMA_CNTL__SI = 0x218A; +constexpr unsigned int mmCP_DMA_ME_COMMAND__CI__VI = 0xC084; +constexpr unsigned int mmCP_DMA_ME_COMMAND__SI = 0x2184; +constexpr unsigned int mmCP_DMA_ME_CONTROL__CI__VI = 0xC078; +constexpr unsigned int mmCP_DMA_ME_DST_ADDR_HI__CI__VI = 0xC083; +constexpr unsigned int mmCP_DMA_ME_DST_ADDR_HI__SI = 0x2183; +constexpr unsigned int mmCP_DMA_ME_DST_ADDR__CI__VI = 0xC082; +constexpr unsigned int mmCP_DMA_ME_DST_ADDR__SI = 0x2182; +constexpr unsigned int mmCP_DMA_ME_SRC_ADDR_HI__CI__VI = 0xC081; +constexpr unsigned int mmCP_DMA_ME_SRC_ADDR_HI__SI = 0x2181; +constexpr unsigned int mmCP_DMA_ME_SRC_ADDR__CI__VI = 0xC080; +constexpr unsigned int mmCP_DMA_ME_SRC_ADDR__SI = 0x2180; +constexpr unsigned int mmCP_DMA_PFP_COMMAND__CI__VI = 0xC089; +constexpr unsigned int mmCP_DMA_PFP_COMMAND__SI = 0x2189; +constexpr unsigned int mmCP_DMA_PFP_CONTROL__CI__VI = 0xC077; +constexpr unsigned int mmCP_DMA_PFP_DST_ADDR_HI__CI__VI = 0xC088; +constexpr unsigned int mmCP_DMA_PFP_DST_ADDR_HI__SI = 0x2188; +constexpr unsigned int mmCP_DMA_PFP_DST_ADDR__CI__VI = 0xC087; +constexpr unsigned int mmCP_DMA_PFP_DST_ADDR__SI = 0x2187; +constexpr unsigned int mmCP_DMA_PFP_SRC_ADDR_HI__CI__VI = 0xC086; +constexpr unsigned int mmCP_DMA_PFP_SRC_ADDR_HI__SI = 0x2186; +constexpr unsigned int mmCP_DMA_PFP_SRC_ADDR__CI__VI = 0xC085; +constexpr unsigned int mmCP_DMA_PFP_SRC_ADDR__SI = 0x2185; +constexpr unsigned int mmCP_DMA_READ_TAGS__CI__VI = 0xC08B; +constexpr unsigned int mmCP_DMA_READ_TAGS__SI = 0x218B; +constexpr unsigned int mmCP_ECC_FIRSTOCCURRENCE = 0x307A; +constexpr unsigned int mmCP_ECC_FIRSTOCCURRENCE_RING0 = 0x307B; +constexpr unsigned int mmCP_ECC_FIRSTOCCURRENCE_RING1 = 0x307C; +constexpr unsigned int mmCP_ECC_FIRSTOCCURRENCE_RING2 = 0x307D; +constexpr unsigned int mmCP_ENDIAN_SWAP__CI__VI = 0x3050; +constexpr unsigned int mmCP_EOP_DONE_ADDR_HI__CI__VI = 0xC001; +constexpr unsigned int mmCP_EOP_DONE_ADDR_HI__SI = 0x2101; +constexpr unsigned int mmCP_EOP_DONE_ADDR_LO__CI__VI = 0xC000; +constexpr unsigned int mmCP_EOP_DONE_ADDR_LO__SI = 0x2100; +constexpr unsigned int mmCP_EOP_DONE_DATA_CNTL__CI__VI = 0xC0D6; +constexpr unsigned int mmCP_EOP_DONE_DATA_HI__CI__VI = 0xC003; +constexpr unsigned int mmCP_EOP_DONE_DATA_HI__SI = 0x2103; +constexpr unsigned int mmCP_EOP_DONE_DATA_LO__CI__VI = 0xC002; +constexpr unsigned int mmCP_EOP_DONE_DATA_LO__SI = 0x2102; +constexpr unsigned int mmCP_EOP_DONE_EVENT_CNTL__CI__VI = 0xC0D5; +constexpr unsigned int mmCP_EOP_LAST_FENCE_HI__CI__VI = 0xC005; +constexpr unsigned int mmCP_EOP_LAST_FENCE_HI__SI = 0x2105; +constexpr unsigned int mmCP_EOP_LAST_FENCE_LO__CI__VI = 0xC004; +constexpr unsigned int mmCP_EOP_LAST_FENCE_LO__SI = 0x2104; +constexpr unsigned int mmCP_FETCHER_SOURCE__CI = 0x3082; +constexpr unsigned int mmCP_GDS_ATOMIC0_PREOP_HI__CI__VI = 0xC060; +constexpr unsigned int mmCP_GDS_ATOMIC0_PREOP_HI__SI = 0x2160; +constexpr unsigned int mmCP_GDS_ATOMIC0_PREOP_LO__CI__VI = 0xC05F; +constexpr unsigned int mmCP_GDS_ATOMIC0_PREOP_LO__SI = 0x215F; +constexpr unsigned int mmCP_GDS_ATOMIC1_PREOP_HI__CI__VI = 0xC062; +constexpr unsigned int mmCP_GDS_ATOMIC1_PREOP_HI__SI = 0x2162; +constexpr unsigned int mmCP_GDS_ATOMIC1_PREOP_LO__CI__VI = 0xC061; +constexpr unsigned int mmCP_GDS_ATOMIC1_PREOP_LO__SI = 0x2161; +constexpr unsigned int mmCP_GRBM_FREE_COUNT = 0x21A3; +constexpr unsigned int mmCP_HPD_EOP_BASE_ADDR_HI__CI = 0x3242; +constexpr unsigned int mmCP_HPD_EOP_BASE_ADDR__CI = 0x3241; +constexpr unsigned int mmCP_HPD_EOP_CONTROL__CI = 0x3244; +constexpr unsigned int mmCP_HPD_EOP_VMID__CI = 0x3243; +constexpr unsigned int mmCP_HPD_ROQ_OFFSETS__CI__VI = 0x3240; +constexpr unsigned int mmCP_HQD_ACTIVE__CI__VI = 0x3247; +constexpr unsigned int mmCP_HQD_ATOMIC0_PREOP_HI__CI__VI = 0x3262; +constexpr unsigned int mmCP_HQD_ATOMIC0_PREOP_LO__CI__VI = 0x3261; +constexpr unsigned int mmCP_HQD_ATOMIC1_PREOP_HI__CI__VI = 0x3264; +constexpr unsigned int mmCP_HQD_ATOMIC1_PREOP_LO__CI__VI = 0x3263; +constexpr unsigned int mmCP_HQD_DEQUEUE_REQUEST__CI__VI = 0x325D; +constexpr unsigned int mmCP_HQD_DMA_OFFLOAD__CI__VI = 0x325E; +constexpr unsigned int mmCP_HQD_HQ_SCHEDULER0__CI__VI = 0x3265; +constexpr unsigned int mmCP_HQD_HQ_SCHEDULER1__CI__VI = 0x3266; +constexpr unsigned int mmCP_HQD_IB_BASE_ADDR_HI__CI__VI = 0x3258; +constexpr unsigned int mmCP_HQD_IB_BASE_ADDR__CI__VI = 0x3257; +constexpr unsigned int mmCP_HQD_IB_CONTROL__CI__VI = 0x325A; +constexpr unsigned int mmCP_HQD_IB_RPTR__CI__VI = 0x3259; +constexpr unsigned int mmCP_HQD_IQ_RPTR__CI__VI = 0x325C; +constexpr unsigned int mmCP_HQD_IQ_TIMER__CI__VI = 0x325B; +constexpr unsigned int mmCP_HQD_MSG_TYPE__CI__VI = 0x3260; +constexpr unsigned int mmCP_HQD_PERSISTENT_STATE__CI__VI = 0x3249; +constexpr unsigned int mmCP_HQD_PIPE_PRIORITY__CI__VI = 0x324A; +constexpr unsigned int mmCP_HQD_PQ_BASE_HI__CI__VI = 0x324E; +constexpr unsigned int mmCP_HQD_PQ_BASE__CI__VI = 0x324D; +constexpr unsigned int mmCP_HQD_PQ_CONTROL__CI__VI = 0x3256; +constexpr unsigned int mmCP_HQD_PQ_DOORBELL_CONTROL__CI__VI = 0x3254; +constexpr unsigned int mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI__CI__VI = 0x3251; +constexpr unsigned int mmCP_HQD_PQ_RPTR_REPORT_ADDR__CI__VI = 0x3250; +constexpr unsigned int mmCP_HQD_PQ_RPTR__CI__VI = 0x324F; +constexpr unsigned int mmCP_HQD_PQ_WPTR_POLL_ADDR_HI__CI__VI = 0x3253; +constexpr unsigned int mmCP_HQD_PQ_WPTR_POLL_ADDR__CI__VI = 0x3252; +constexpr unsigned int mmCP_HQD_PQ_WPTR__CI__VI = 0x3255; +constexpr unsigned int mmCP_HQD_QUANTUM__CI__VI = 0x324C; +constexpr unsigned int mmCP_HQD_QUEUE_PRIORITY__CI__VI = 0x324B; +constexpr unsigned int mmCP_HQD_SEMA_CMD__CI__VI = 0x325F; +constexpr unsigned int mmCP_HQD_VMID__CI__VI = 0x3248; +constexpr unsigned int mmCP_IB1_BASE_HI__CI__VI = 0xC0CD; +constexpr unsigned int mmCP_IB1_BASE_HI__SI = 0x21CD; +constexpr unsigned int mmCP_IB1_BASE_LO__CI__VI = 0xC0CC; +constexpr unsigned int mmCP_IB1_BASE_LO__SI = 0x21CC; +constexpr unsigned int mmCP_IB1_BUFSZ__CI__VI = 0xC0CE; +constexpr unsigned int mmCP_IB1_BUFSZ__SI = 0x21CE; +constexpr unsigned int mmCP_IB1_OFFSET__CI__VI = 0xC092; +constexpr unsigned int mmCP_IB1_OFFSET__SI = 0x2192; +constexpr unsigned int mmCP_IB1_PREAMBLE_BEGIN__CI__VI = 0xC094; +constexpr unsigned int mmCP_IB1_PREAMBLE_BEGIN__SI = 0x2194; +constexpr unsigned int mmCP_IB1_PREAMBLE_END__CI__VI = 0xC095; +constexpr unsigned int mmCP_IB1_PREAMBLE_END__SI = 0x2195; +constexpr unsigned int mmCP_IB2_BASE_HI__CI__VI = 0xC0D0; +constexpr unsigned int mmCP_IB2_BASE_HI__SI = 0x21D0; +constexpr unsigned int mmCP_IB2_BASE_LO__CI__VI = 0xC0CF; +constexpr unsigned int mmCP_IB2_BASE_LO__SI = 0x21CF; +constexpr unsigned int mmCP_IB2_BUFSZ__CI__VI = 0xC0D1; +constexpr unsigned int mmCP_IB2_BUFSZ__SI = 0x21D1; +constexpr unsigned int mmCP_IB2_OFFSET__CI__VI = 0xC093; +constexpr unsigned int mmCP_IB2_OFFSET__SI = 0x2193; +constexpr unsigned int mmCP_IB2_PREAMBLE_BEGIN__CI__VI = 0xC096; +constexpr unsigned int mmCP_IB2_PREAMBLE_BEGIN__SI = 0x2196; +constexpr unsigned int mmCP_IB2_PREAMBLE_END__CI__VI = 0xC097; +constexpr unsigned int mmCP_IB2_PREAMBLE_END__SI = 0x2197; +constexpr unsigned int mmCP_INT_CNTL = 0x3049; +constexpr unsigned int mmCP_INT_CNTL_RING0 = 0x306A; +constexpr unsigned int mmCP_INT_CNTL_RING1 = 0x306B; +constexpr unsigned int mmCP_INT_CNTL_RING2 = 0x306C; +constexpr unsigned int mmCP_INT_STATUS = 0x304A; +constexpr unsigned int mmCP_INT_STATUS_RING0 = 0x306D; +constexpr unsigned int mmCP_INT_STATUS_RING1 = 0x306E; +constexpr unsigned int mmCP_INT_STATUS_RING2 = 0x306F; +constexpr unsigned int mmCP_INT_STAT_DEBUG = 0x21F7; +constexpr unsigned int mmCP_IQ_WAIT_TIME1__CI__VI = 0x30AF; +constexpr unsigned int mmCP_IQ_WAIT_TIME2__CI__VI = 0x30B0; +constexpr unsigned int mmCP_MAX_CONTEXT__CI__VI = 0x30AE; +constexpr unsigned int mmCP_MC_PACK_DELAY_CNT__SI__CI = 0x21A7; +constexpr unsigned int mmCP_MC_TAG_CNTL__CI = 0x21A8; +constexpr unsigned int mmCP_MC_TAG_DATA__CI = 0x21A9; +constexpr unsigned int mmCP_ME0_PIPE0_PRIORITY__CI__VI = 0x304D; +constexpr unsigned int mmCP_ME0_PIPE0_VMID__CI__VI = 0x3052; +constexpr unsigned int mmCP_ME0_PIPE1_PRIORITY__CI__VI = 0x304E; +constexpr unsigned int mmCP_ME0_PIPE1_VMID__CI__VI = 0x3053; +constexpr unsigned int mmCP_ME0_PIPE2_PRIORITY__CI__VI = 0x304F; +constexpr unsigned int mmCP_ME0_PIPE_PRIORITY_CNTS__CI__VI = 0x304C; +constexpr unsigned int mmCP_ME1_INT_STAT_DEBUG__CI__VI = 0x3095; +constexpr unsigned int mmCP_ME1_PIPE0_INT_CNTL__CI__VI = 0x3085; +constexpr unsigned int mmCP_ME1_PIPE0_INT_STATUS__CI__VI = 0x308D; +constexpr unsigned int mmCP_ME1_PIPE0_PRIORITY__CI__VI = 0x309A; +constexpr unsigned int mmCP_ME1_PIPE1_INT_CNTL__CI__VI = 0x3086; +constexpr unsigned int mmCP_ME1_PIPE1_INT_STATUS__CI__VI = 0x308E; +constexpr unsigned int mmCP_ME1_PIPE1_PRIORITY__CI__VI = 0x309B; +constexpr unsigned int mmCP_ME1_PIPE2_INT_CNTL__CI__VI = 0x3087; +constexpr unsigned int mmCP_ME1_PIPE2_INT_STATUS__CI__VI = 0x308F; +constexpr unsigned int mmCP_ME1_PIPE2_PRIORITY__CI__VI = 0x309C; +constexpr unsigned int mmCP_ME1_PIPE3_INT_CNTL__CI__VI = 0x3088; +constexpr unsigned int mmCP_ME1_PIPE3_INT_STATUS__CI__VI = 0x3090; +constexpr unsigned int mmCP_ME1_PIPE3_PRIORITY__CI__VI = 0x309D; +constexpr unsigned int mmCP_ME1_PIPE_PRIORITY_CNTS__CI__VI = 0x3099; +constexpr unsigned int mmCP_ME2_INT_STAT_DEBUG__CI__VI = 0x3096; +constexpr unsigned int mmCP_ME2_PIPE0_INT_CNTL__CI__VI = 0x3089; +constexpr unsigned int mmCP_ME2_PIPE0_INT_STATUS__CI__VI = 0x3091; +constexpr unsigned int mmCP_ME2_PIPE0_PRIORITY__CI__VI = 0x309F; +constexpr unsigned int mmCP_ME2_PIPE1_INT_CNTL__CI__VI = 0x308A; +constexpr unsigned int mmCP_ME2_PIPE1_INT_STATUS__CI__VI = 0x3092; +constexpr unsigned int mmCP_ME2_PIPE1_PRIORITY__CI__VI = 0x30A0; +constexpr unsigned int mmCP_ME2_PIPE2_INT_CNTL__CI__VI = 0x308B; +constexpr unsigned int mmCP_ME2_PIPE2_INT_STATUS__CI__VI = 0x3093; +constexpr unsigned int mmCP_ME2_PIPE2_PRIORITY__CI__VI = 0x30A1; +constexpr unsigned int mmCP_ME2_PIPE3_INT_CNTL__CI__VI = 0x308C; +constexpr unsigned int mmCP_ME2_PIPE3_INT_STATUS__CI__VI = 0x3094; +constexpr unsigned int mmCP_ME2_PIPE3_PRIORITY__CI__VI = 0x30A2; +constexpr unsigned int mmCP_ME2_PIPE_PRIORITY_CNTS__CI__VI = 0x309E; +constexpr unsigned int mmCP_MEC1_INTR_ROUTINE_START__CI__VI = 0x30AB; +constexpr unsigned int mmCP_MEC1_PRGRM_CNTR_START__CI__VI = 0x30A6; +constexpr unsigned int mmCP_MEC2_INTR_ROUTINE_START__CI__VI = 0x30AC; +constexpr unsigned int mmCP_MEC2_PRGRM_CNTR_START__CI__VI = 0x30A7; +constexpr unsigned int mmCP_MEC_CNTL__CI__VI = 0x208D; +constexpr unsigned int mmCP_MEC_ME1_HEADER_DUMP__CI__VI = 0x208E; +constexpr unsigned int mmCP_MEC_ME1_UCODE_ADDR__CI = 0x305C; +constexpr unsigned int mmCP_MEC_ME1_UCODE_DATA__CI = 0x305D; +constexpr unsigned int mmCP_MEC_ME2_HEADER_DUMP__CI__VI = 0x208F; +constexpr unsigned int mmCP_MEC_ME2_UCODE_ADDR__CI = 0x305E; +constexpr unsigned int mmCP_MEC_ME2_UCODE_DATA__CI = 0x305F; +constexpr unsigned int mmCP_MEM_SLP_CNTL = 0x3079; +constexpr unsigned int mmCP_MEQ_AVAIL = 0x21DD; +constexpr unsigned int mmCP_MEQ_STAT = 0x21E5; +constexpr unsigned int mmCP_MEQ_STQ_THRESHOLD__CI__VI = 0x21BD; +constexpr unsigned int mmCP_MEQ_THRESHOLDS = 0x21D9; +constexpr unsigned int mmCP_ME_ATOMIC_PREOP_HI__CI__VI = 0xC05E; +constexpr unsigned int mmCP_ME_ATOMIC_PREOP_LO__CI__VI = 0xC05D; +constexpr unsigned int mmCP_ME_CNTL = 0x21B6; +constexpr unsigned int mmCP_ME_GDS_ATOMIC0_PREOP_HI__CI__VI = 0xC060; +constexpr unsigned int mmCP_ME_GDS_ATOMIC0_PREOP_LO__CI__VI = 0xC05F; +constexpr unsigned int mmCP_ME_GDS_ATOMIC1_PREOP_HI__CI__VI = 0xC062; +constexpr unsigned int mmCP_ME_GDS_ATOMIC1_PREOP_LO__CI__VI = 0xC061; +constexpr unsigned int mmCP_ME_HEADER_DUMP = 0x21A1; +constexpr unsigned int mmCP_ME_INTR_ROUTINE_START__CI__VI = 0x30AA; +constexpr unsigned int mmCP_ME_MC_RADDR_HI__CI__VI = 0xC06E; +constexpr unsigned int mmCP_ME_MC_RADDR_HI__SI = 0x216E; +constexpr unsigned int mmCP_ME_MC_RADDR_LO__CI__VI = 0xC06D; +constexpr unsigned int mmCP_ME_MC_RADDR_LO__SI = 0x216D; +constexpr unsigned int mmCP_ME_MC_WADDR_HI__CI__VI = 0xC06A; +constexpr unsigned int mmCP_ME_MC_WADDR_HI__SI = 0x216A; +constexpr unsigned int mmCP_ME_MC_WADDR_LO__CI__VI = 0xC069; +constexpr unsigned int mmCP_ME_MC_WADDR_LO__SI = 0x2169; +constexpr unsigned int mmCP_ME_MC_WDATA_HI__CI__VI = 0xC06C; +constexpr unsigned int mmCP_ME_MC_WDATA_HI__SI = 0x216C; +constexpr unsigned int mmCP_ME_MC_WDATA_LO__CI__VI = 0xC06B; +constexpr unsigned int mmCP_ME_MC_WDATA_LO__SI = 0x216B; +constexpr unsigned int mmCP_ME_PREEMPTION = 0x21B9; +constexpr unsigned int mmCP_ME_PRGRM_CNTR_START__CI__VI = 0x30A5; +constexpr unsigned int mmCP_MQD_BASE_ADDR_HI__CI__VI = 0x3246; +constexpr unsigned int mmCP_MQD_BASE_ADDR__CI__VI = 0x3245; +constexpr unsigned int mmCP_MQD_CONTROL__CI__VI = 0x3267; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT0_HI__CI__VI = 0xC00B; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT0_HI__SI = 0x210B; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT0_LO__CI__VI = 0xC00A; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT0_LO__SI = 0x210A; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT1_HI__CI__VI = 0xC00F; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT1_HI__SI = 0x210F; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT1_LO__CI__VI = 0xC00E; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT1_LO__SI = 0x210E; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT2_HI__CI__VI = 0xC013; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT2_HI__SI = 0x2113; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT2_LO__CI__VI = 0xC012; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT2_LO__SI = 0x2112; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT3_HI__CI__VI = 0xC017; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT3_HI__SI = 0x2117; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT3_LO__CI__VI = 0xC016; +constexpr unsigned int mmCP_NUM_PRIM_NEEDED_COUNT3_LO__SI = 0x2116; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT0_HI__CI__VI = 0xC009; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT0_HI__SI = 0x2109; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT0_LO__CI__VI = 0xC008; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT0_LO__SI = 0x2108; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT1_HI__CI__VI = 0xC00D; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT1_HI__SI = 0x210D; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT1_LO__CI__VI = 0xC00C; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT1_LO__SI = 0x210C; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT2_HI__CI__VI = 0xC011; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT2_HI__SI = 0x2111; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT2_LO__CI__VI = 0xC010; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT2_LO__SI = 0x2110; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT3_HI__CI__VI = 0xC015; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT3_HI__SI = 0x2115; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT3_LO__CI__VI = 0xC014; +constexpr unsigned int mmCP_NUM_PRIM_WRITTEN_COUNT3_LO__SI = 0x2114; +constexpr unsigned int mmCP_PA_CINVOC_COUNT_HI__CI__VI = 0xC029; +constexpr unsigned int mmCP_PA_CINVOC_COUNT_HI__SI = 0x2129; +constexpr unsigned int mmCP_PA_CINVOC_COUNT_LO__CI__VI = 0xC028; +constexpr unsigned int mmCP_PA_CINVOC_COUNT_LO__SI = 0x2128; +constexpr unsigned int mmCP_PA_CPRIM_COUNT_HI__CI__VI = 0xC02B; +constexpr unsigned int mmCP_PA_CPRIM_COUNT_HI__SI = 0x212B; +constexpr unsigned int mmCP_PA_CPRIM_COUNT_LO__CI__VI = 0xC02A; +constexpr unsigned int mmCP_PA_CPRIM_COUNT_LO__SI = 0x212A; +constexpr unsigned int mmCP_PERFCOUNTER_HI__SI = 0x21FE; +constexpr unsigned int mmCP_PERFCOUNTER_LO__SI = 0x21FD; +constexpr unsigned int mmCP_PERFCOUNTER_SELECT__SI = 0x21FC; +constexpr unsigned int mmCP_PERFMON_CNTL__CI__VI = 0xD808; +constexpr unsigned int mmCP_PERFMON_CNTL__SI = 0x21FF; +constexpr unsigned int mmCP_PERFMON_CNTX_CNTL = 0xA0D8; +constexpr unsigned int mmCP_PFP_ATOMIC_PREOP_HI__CI__VI = 0xC053; +constexpr unsigned int mmCP_PFP_ATOMIC_PREOP_LO__CI__VI = 0xC052; +constexpr unsigned int mmCP_PFP_GDS_ATOMIC0_PREOP_HI__CI__VI = 0xC055; +constexpr unsigned int mmCP_PFP_GDS_ATOMIC0_PREOP_LO__CI__VI = 0xC054; +constexpr unsigned int mmCP_PFP_GDS_ATOMIC1_PREOP_HI__CI__VI = 0xC057; +constexpr unsigned int mmCP_PFP_GDS_ATOMIC1_PREOP_LO__CI__VI = 0xC056; +constexpr unsigned int mmCP_PFP_HEADER_DUMP = 0x21A2; +constexpr unsigned int mmCP_PFP_IB_CONTROL__CI__VI = 0xC08D; +constexpr unsigned int mmCP_PFP_IB_CONTROL__SI = 0x218D; +constexpr unsigned int mmCP_PFP_INTR_ROUTINE_START__CI__VI = 0x30A9; +constexpr unsigned int mmCP_PFP_LOAD_CONTROL__CI__VI = 0xC08E; +constexpr unsigned int mmCP_PFP_LOAD_CONTROL__SI = 0x218E; +constexpr unsigned int mmCP_PFP_PRGRM_CNTR_START__CI__VI = 0x30A4; +constexpr unsigned int mmCP_PIPEID__CI__VI = 0xA0D9; +constexpr unsigned int mmCP_PIPE_STATS_ADDR_HI__CI__VI = 0xC019; +constexpr unsigned int mmCP_PIPE_STATS_ADDR_HI__SI = 0x2119; +constexpr unsigned int mmCP_PIPE_STATS_ADDR_LO__CI__VI = 0xC018; +constexpr unsigned int mmCP_PIPE_STATS_ADDR_LO__SI = 0x2118; +constexpr unsigned int mmCP_PQ_WPTR_POLL_CNTL1__CI__VI = 0x3084; +constexpr unsigned int mmCP_PQ_WPTR_POLL_CNTL__CI__VI = 0x3083; +constexpr unsigned int mmCP_PRT_LOD_STATS_CNTL0__CI__VI = 0x20AD; +constexpr unsigned int mmCP_PRT_LOD_STATS_CNTL1__CI__VI = 0x20AE; +constexpr unsigned int mmCP_PRT_LOD_STATS_CNTL2__CI__VI = 0x20AF; +constexpr unsigned int mmCP_PWR_CNTL = 0x3078; +constexpr unsigned int mmCP_QUEUE_THRESHOLDS = 0x21D8; +constexpr unsigned int mmCP_RB0_BASE = 0x3040; +constexpr unsigned int mmCP_RB0_BASE_HI__CI__VI = 0x30B1; +constexpr unsigned int mmCP_RB0_CNTL = 0x3041; +constexpr unsigned int mmCP_RB0_RPTR = 0x21C0; +constexpr unsigned int mmCP_RB0_RPTR_ADDR = 0x3043; +constexpr unsigned int mmCP_RB0_RPTR_ADDR_HI = 0x3044; +constexpr unsigned int mmCP_RB0_WPTR = 0x3045; +constexpr unsigned int mmCP_RB1_BASE = 0x3060; +constexpr unsigned int mmCP_RB1_BASE_HI__CI__VI = 0x30B2; +constexpr unsigned int mmCP_RB1_CNTL = 0x3061; +constexpr unsigned int mmCP_RB1_RPTR = 0x21BF; +constexpr unsigned int mmCP_RB1_RPTR_ADDR = 0x3062; +constexpr unsigned int mmCP_RB1_RPTR_ADDR_HI = 0x3063; +constexpr unsigned int mmCP_RB1_WPTR = 0x3064; +constexpr unsigned int mmCP_RB2_BASE = 0x3065; +constexpr unsigned int mmCP_RB2_CNTL = 0x3066; +constexpr unsigned int mmCP_RB2_RPTR = 0x21BE; +constexpr unsigned int mmCP_RB2_RPTR_ADDR = 0x3067; +constexpr unsigned int mmCP_RB2_RPTR_ADDR_HI = 0x3068; +constexpr unsigned int mmCP_RB2_WPTR = 0x3069; +constexpr unsigned int mmCP_RB_BASE = 0x3040; +constexpr unsigned int mmCP_RB_CNTL = 0x3041; +constexpr unsigned int mmCP_RB_OFFSET__CI__VI = 0xC091; +constexpr unsigned int mmCP_RB_OFFSET__SI = 0x2191; +constexpr unsigned int mmCP_RB_RPTR = 0x21C0; +constexpr unsigned int mmCP_RB_RPTR_ADDR = 0x3043; +constexpr unsigned int mmCP_RB_RPTR_ADDR_HI = 0x3044; +constexpr unsigned int mmCP_RB_RPTR_WR = 0x3042; +constexpr unsigned int mmCP_RB_VMID = 0x3051; +constexpr unsigned int mmCP_RB_WPTR = 0x3045; +constexpr unsigned int mmCP_RB_WPTR_DELAY = 0x21C1; +constexpr unsigned int mmCP_RB_WPTR_POLL_ADDR_HI = 0x3047; +constexpr unsigned int mmCP_RB_WPTR_POLL_ADDR_LO = 0x3046; +constexpr unsigned int mmCP_RB_WPTR_POLL_CNTL = 0x21C2; +constexpr unsigned int mmCP_RING0_PRIORITY = 0x304D; +constexpr unsigned int mmCP_RING1_PRIORITY = 0x304E; +constexpr unsigned int mmCP_RING2_PRIORITY = 0x304F; +constexpr unsigned int mmCP_RINGID = 0xA0D9; +constexpr unsigned int mmCP_RING_PRIORITY_CNTS = 0x304C; +constexpr unsigned int mmCP_ROQ1_THRESHOLDS = 0x21D5; +constexpr unsigned int mmCP_ROQ2_AVAIL = 0x21DC; +constexpr unsigned int mmCP_ROQ2_THRESHOLDS = 0x21D6; +constexpr unsigned int mmCP_ROQ_AVAIL = 0x21DA; +constexpr unsigned int mmCP_ROQ_IB1_STAT = 0x21E1; +constexpr unsigned int mmCP_ROQ_IB2_STAT = 0x21E2; +constexpr unsigned int mmCP_ROQ_RB_STAT = 0x21E0; +constexpr unsigned int mmCP_ROQ_THRESHOLDS__CI__VI = 0x21BC; +constexpr unsigned int mmCP_SCRATCH_DATA__CI__VI = 0xC090; +constexpr unsigned int mmCP_SCRATCH_DATA__SI = 0x2190; +constexpr unsigned int mmCP_SCRATCH_INDEX__CI__VI = 0xC08F; +constexpr unsigned int mmCP_SCRATCH_INDEX__SI = 0x218F; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT0_HI__CI__VI = 0xC02D; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT0_HI__SI = 0x212D; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT0_LO__CI__VI = 0xC02C; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT0_LO__SI = 0x212C; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT1_HI__CI__VI = 0xC02F; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT1_HI__SI = 0x212F; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT1_LO__CI__VI = 0xC02E; +constexpr unsigned int mmCP_SC_PSINVOC_COUNT1_LO__SI = 0x212E; +constexpr unsigned int mmCP_SEM_WAIT_TIMER__CI__VI = 0xC06F; +constexpr unsigned int mmCP_SEM_WAIT_TIMER__SI = 0x216F; +constexpr unsigned int mmCP_SIG_SEM_ADDR_HI__CI__VI = 0xC071; +constexpr unsigned int mmCP_SIG_SEM_ADDR_HI__SI = 0x2171; +constexpr unsigned int mmCP_SIG_SEM_ADDR_LO__CI__VI = 0xC070; +constexpr unsigned int mmCP_SIG_SEM_ADDR_LO__SI = 0x2170; +constexpr unsigned int mmCP_STALLED_STAT1 = 0x219D; +constexpr unsigned int mmCP_STALLED_STAT2 = 0x219E; +constexpr unsigned int mmCP_STALLED_STAT3 = 0x219C; +constexpr unsigned int mmCP_STAT = 0x21A0; +constexpr unsigned int mmCP_STQ_AVAIL = 0x21DB; +constexpr unsigned int mmCP_STQ_STAT = 0x21E3; +constexpr unsigned int mmCP_STQ_THRESHOLDS = 0x21D7; +constexpr unsigned int mmCP_STQ_WR_STAT__CI__VI = 0x21E4; +constexpr unsigned int mmCP_STREAM_OUT_ADDR_HI__CI__VI = 0xC007; +constexpr unsigned int mmCP_STREAM_OUT_ADDR_HI__SI = 0x2107; +constexpr unsigned int mmCP_STREAM_OUT_ADDR_LO__CI__VI = 0xC006; +constexpr unsigned int mmCP_STREAM_OUT_ADDR_LO__SI = 0x2106; +constexpr unsigned int mmCP_STRMOUT_CNTL__CI__VI = 0xC03F; +constexpr unsigned int mmCP_STRMOUT_CNTL__SI = 0x213F; +constexpr unsigned int mmCP_ST_BASE_HI__CI__VI = 0xC0D3; +constexpr unsigned int mmCP_ST_BASE_HI__SI = 0x21D3; +constexpr unsigned int mmCP_ST_BASE_LO__CI__VI = 0xC0D2; +constexpr unsigned int mmCP_ST_BASE_LO__SI = 0x21D2; +constexpr unsigned int mmCP_ST_BUFSZ__CI__VI = 0xC0D4; +constexpr unsigned int mmCP_ST_BUFSZ__SI = 0x21D4; +constexpr unsigned int mmCP_VGT_CSINVOC_COUNT_HI__CI__VI = 0xC031; +constexpr unsigned int mmCP_VGT_CSINVOC_COUNT_HI__SI = 0x2131; +constexpr unsigned int mmCP_VGT_CSINVOC_COUNT_LO__CI__VI = 0xC030; +constexpr unsigned int mmCP_VGT_CSINVOC_COUNT_LO__SI = 0x2130; +constexpr unsigned int mmCP_VGT_DSINVOC_COUNT_HI__CI__VI = 0xC027; +constexpr unsigned int mmCP_VGT_DSINVOC_COUNT_HI__SI = 0x2127; +constexpr unsigned int mmCP_VGT_DSINVOC_COUNT_LO__CI__VI = 0xC026; +constexpr unsigned int mmCP_VGT_DSINVOC_COUNT_LO__SI = 0x2126; +constexpr unsigned int mmCP_VGT_GSINVOC_COUNT_HI__CI__VI = 0xC023; +constexpr unsigned int mmCP_VGT_GSINVOC_COUNT_HI__SI = 0x2123; +constexpr unsigned int mmCP_VGT_GSINVOC_COUNT_LO__CI__VI = 0xC022; +constexpr unsigned int mmCP_VGT_GSINVOC_COUNT_LO__SI = 0x2122; +constexpr unsigned int mmCP_VGT_GSPRIM_COUNT_HI__CI__VI = 0xC01F; +constexpr unsigned int mmCP_VGT_GSPRIM_COUNT_HI__SI = 0x211F; +constexpr unsigned int mmCP_VGT_GSPRIM_COUNT_LO__CI__VI = 0xC01E; +constexpr unsigned int mmCP_VGT_GSPRIM_COUNT_LO__SI = 0x211E; +constexpr unsigned int mmCP_VGT_HSINVOC_COUNT_HI__CI__VI = 0xC025; +constexpr unsigned int mmCP_VGT_HSINVOC_COUNT_HI__SI = 0x2125; +constexpr unsigned int mmCP_VGT_HSINVOC_COUNT_LO__CI__VI = 0xC024; +constexpr unsigned int mmCP_VGT_HSINVOC_COUNT_LO__SI = 0x2124; +constexpr unsigned int mmCP_VGT_IAPRIM_COUNT_HI__CI__VI = 0xC01D; +constexpr unsigned int mmCP_VGT_IAPRIM_COUNT_HI__SI = 0x211D; +constexpr unsigned int mmCP_VGT_IAPRIM_COUNT_LO__CI__VI = 0xC01C; +constexpr unsigned int mmCP_VGT_IAPRIM_COUNT_LO__SI = 0x211C; +constexpr unsigned int mmCP_VGT_IAVERT_COUNT_HI__CI__VI = 0xC01B; +constexpr unsigned int mmCP_VGT_IAVERT_COUNT_HI__SI = 0x211B; +constexpr unsigned int mmCP_VGT_IAVERT_COUNT_LO__CI__VI = 0xC01A; +constexpr unsigned int mmCP_VGT_IAVERT_COUNT_LO__SI = 0x211A; +constexpr unsigned int mmCP_VGT_VSINVOC_COUNT_HI__CI__VI = 0xC021; +constexpr unsigned int mmCP_VGT_VSINVOC_COUNT_HI__SI = 0x2121; +constexpr unsigned int mmCP_VGT_VSINVOC_COUNT_LO__CI__VI = 0xC020; +constexpr unsigned int mmCP_VGT_VSINVOC_COUNT_LO__SI = 0x2120; +constexpr unsigned int mmCP_VMID = 0xA0DA; +constexpr unsigned int mmCP_VMID_PREEMPT__CI__VI = 0x30B6; +constexpr unsigned int mmCP_VMID_RESET__CI__VI = 0x30B3; +constexpr unsigned int mmCP_WAIT_REG_MEM_TIMEOUT__CI__VI = 0xC074; +constexpr unsigned int mmCP_WAIT_REG_MEM_TIMEOUT__SI = 0x2174; +constexpr unsigned int mmCP_WAIT_SEM_ADDR_HI__CI__VI = 0xC076; +constexpr unsigned int mmCP_WAIT_SEM_ADDR_HI__SI = 0x2176; +constexpr unsigned int mmCP_WAIT_SEM_ADDR_LO__CI__VI = 0xC075; +constexpr unsigned int mmCP_WAIT_SEM_ADDR_LO__SI = 0x2175; +constexpr unsigned int mmCRTC0_CRTC_ALLOW_STOP_OFF_V_CNT__SI__VI = 0x1BC3; +constexpr unsigned int mmCRTC0_CRTC_BLACK_COLOR__SI = 0x1BA2; +constexpr unsigned int mmCRTC0_CRTC_BLANK_CONTROL = 0x1B9D; +constexpr unsigned int mmCRTC0_CRTC_BLANK_DATA_COLOR__SI = 0x1BA1; +constexpr unsigned int mmCRTC0_CRTC_CONTROL__SI__VI = 0x1B9C; +constexpr unsigned int mmCRTC0_CRTC_COUNT_CONTROL__SI__VI = 0x1BA9; +constexpr unsigned int mmCRTC0_CRTC_COUNT_RESET__SI__VI = 0x1BAA; +constexpr unsigned int mmCRTC0_CRTC_DOUBLE_BUFFER_CONTROL__SI__VI = 0x1BB6; +constexpr unsigned int mmCRTC0_CRTC_DTMTEST_CNTL__SI__VI = 0x1B92; +constexpr unsigned int mmCRTC0_CRTC_DTMTEST_STATUS_POSITION__SI__VI = 0x1B93; +constexpr unsigned int mmCRTC0_CRTC_FLOW_CONTROL__SI__VI = 0x1B99; +constexpr unsigned int mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL__SI__VI = 0x1B98; +constexpr unsigned int mmCRTC0_CRTC_H_BLANK_START_END__SI__VI = 0x1B81; +constexpr unsigned int mmCRTC0_CRTC_H_SYNC_A_CNTL__SI__VI = 0x1B83; +constexpr unsigned int mmCRTC0_CRTC_H_SYNC_A__SI__VI = 0x1B82; +constexpr unsigned int mmCRTC0_CRTC_H_SYNC_B_CNTL__SI__VI = 0x1B85; +constexpr unsigned int mmCRTC0_CRTC_H_SYNC_B__SI__VI = 0x1B84; +constexpr unsigned int mmCRTC0_CRTC_H_TOTAL__SI__VI = 0x1B80; +constexpr unsigned int mmCRTC0_CRTC_INTERLACE_CONTROL__SI__VI = 0x1B9E; +constexpr unsigned int mmCRTC0_CRTC_INTERLACE_STATUS__SI__VI = 0x1B9F; +constexpr unsigned int mmCRTC0_CRTC_INTERRUPT_CONTROL__SI__VI = 0x1BB4; +constexpr unsigned int mmCRTC0_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI__VI = 0x1BAB; +constexpr unsigned int mmCRTC0_CRTC_MASTER_EN__SI__VI = 0x1BC2; +constexpr unsigned int mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI__VI = 0x1BC0; +constexpr unsigned int mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT__SI__VI = 0x1BBF; +constexpr unsigned int mmCRTC0_CRTC_MVP_STATUS__SI__VI = 0x1BC1; +constexpr unsigned int mmCRTC0_CRTC_NOM_VERT_POSITION__SI__VI = 0x1BA5; +constexpr unsigned int mmCRTC0_CRTC_OVERSCAN_COLOR__SI = 0x1BA0; +constexpr unsigned int mmCRTC0_CRTC_PIXEL_DATA_READBACK__SI = 0x1B9A; +constexpr unsigned int mmCRTC0_CRTC_SNAPSHOT_CONTROL__SI__VI = 0x1BB0; +constexpr unsigned int mmCRTC0_CRTC_SNAPSHOT_FRAME__SI__VI = 0x1BB2; +constexpr unsigned int mmCRTC0_CRTC_SNAPSHOT_POSITION__SI__VI = 0x1BB1; +constexpr unsigned int mmCRTC0_CRTC_SNAPSHOT_STATUS__SI__VI = 0x1BAF; +constexpr unsigned int mmCRTC0_CRTC_START_LINE_CONTROL__SI__VI = 0x1BB3; +constexpr unsigned int mmCRTC0_CRTC_STATUS = 0x1BA3; +constexpr unsigned int mmCRTC0_CRTC_STATUS_FRAME_COUNT__SI__VI = 0x1BA6; +constexpr unsigned int mmCRTC0_CRTC_STATUS_HV_COUNT__SI__VI = 0x1BA8; +constexpr unsigned int mmCRTC0_CRTC_STATUS_POSITION = 0x1BA4; +constexpr unsigned int mmCRTC0_CRTC_STATUS_VF_COUNT__SI__VI = 0x1BA7; +constexpr unsigned int mmCRTC0_CRTC_STEREO_CONTROL__SI__VI = 0x1BAE; +constexpr unsigned int mmCRTC0_CRTC_STEREO_FORCE_NEXT_EYE__SI = 0x1B9B; +constexpr unsigned int mmCRTC0_CRTC_STEREO_STATUS__SI__VI = 0x1BAD; +constexpr unsigned int mmCRTC0_CRTC_TEST_DEBUG_DATA__SI__VI = 0x1BC7; +constexpr unsigned int mmCRTC0_CRTC_TEST_DEBUG_INDEX__SI__VI = 0x1BC6; +constexpr unsigned int mmCRTC0_CRTC_TEST_PATTERN_COLOR__SI__VI = 0x1BBC; +constexpr unsigned int mmCRTC0_CRTC_TEST_PATTERN_CONTROL__SI__VI = 0x1BBA; +constexpr unsigned int mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS__SI__VI = 0x1BBB; +constexpr unsigned int mmCRTC0_CRTC_TRIGA_CNTL__SI__VI = 0x1B94; +constexpr unsigned int mmCRTC0_CRTC_TRIGA_MANUAL_TRIG__SI__VI = 0x1B95; +constexpr unsigned int mmCRTC0_CRTC_TRIGB_CNTL__SI__VI = 0x1B96; +constexpr unsigned int mmCRTC0_CRTC_TRIGB_MANUAL_TRIG__SI__VI = 0x1B97; +constexpr unsigned int mmCRTC0_CRTC_UPDATE_LOCK__SI__VI = 0x1BB5; +constexpr unsigned int mmCRTC0_CRTC_VBI_END__SI__VI = 0x1B86; +constexpr unsigned int mmCRTC0_CRTC_VERT_SYNC_CONTROL__SI__VI = 0x1BAC; +constexpr unsigned int mmCRTC0_CRTC_VGA_PARAMETER_CAPTURE_MODE__SI__VI = 0x1BB7; +constexpr unsigned int mmCRTC0_CRTC_VSYNC_NOM_INT_STATUS__SI__VI = 0x1B8C; +constexpr unsigned int mmCRTC0_CRTC_V_BLANK_START_END__SI__VI = 0x1B8D; +constexpr unsigned int mmCRTC0_CRTC_V_SYNC_A_CNTL__SI__VI = 0x1B8F; +constexpr unsigned int mmCRTC0_CRTC_V_SYNC_A__SI__VI = 0x1B8E; +constexpr unsigned int mmCRTC0_CRTC_V_SYNC_B_CNTL__SI__VI = 0x1B91; +constexpr unsigned int mmCRTC0_CRTC_V_SYNC_B__SI__VI = 0x1B90; +constexpr unsigned int mmCRTC0_CRTC_V_TOTAL_CONTROL__SI__VI = 0x1B8A; +constexpr unsigned int mmCRTC0_CRTC_V_TOTAL_INT_STATUS__SI__VI = 0x1B8B; +constexpr unsigned int mmCRTC0_CRTC_V_TOTAL_MAX__SI__VI = 0x1B89; +constexpr unsigned int mmCRTC0_CRTC_V_TOTAL_MIN__SI__VI = 0x1B88; +constexpr unsigned int mmCRTC0_CRTC_V_TOTAL__SI__VI = 0x1B87; +constexpr unsigned int mmCRTC0_CRTC_V_UPDATE_INT_STATUS__SI__VI = 0x1BC4; +constexpr unsigned int mmCRTC0_MASTER_UPDATE_LOCK__SI__VI = 0x1BBD; +constexpr unsigned int mmCRTC0_MASTER_UPDATE_MODE = 0x1BBE; +constexpr unsigned int mmCRTC0_PIXEL_RATE_CNTL__SI = 0x0120; +constexpr unsigned int mmCRTC1_CRTC_ALLOW_STOP_OFF_V_CNT__SI = 0x1EC3; +constexpr unsigned int mmCRTC1_CRTC_BLACK_COLOR__SI = 0x1EA2; +constexpr unsigned int mmCRTC1_CRTC_BLANK_DATA_COLOR__SI = 0x1EA1; +constexpr unsigned int mmCRTC1_CRTC_CONTROL__SI = 0x1E9C; +constexpr unsigned int mmCRTC1_CRTC_COUNT_CONTROL__SI = 0x1EA9; +constexpr unsigned int mmCRTC1_CRTC_COUNT_RESET__SI = 0x1EAA; +constexpr unsigned int mmCRTC1_CRTC_DOUBLE_BUFFER_CONTROL__SI = 0x1EB6; +constexpr unsigned int mmCRTC1_CRTC_DTMTEST_CNTL__SI = 0x1E92; +constexpr unsigned int mmCRTC1_CRTC_DTMTEST_STATUS_POSITION__SI = 0x1E93; +constexpr unsigned int mmCRTC1_CRTC_FLOW_CONTROL__SI = 0x1E99; +constexpr unsigned int mmCRTC1_CRTC_FORCE_COUNT_NOW_CNTL__SI = 0x1E98; +constexpr unsigned int mmCRTC1_CRTC_H_BLANK_START_END__SI = 0x1E81; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_A_CNTL__SI = 0x1E83; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_A__SI = 0x1E82; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_B_CNTL__SI = 0x1E85; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_B__SI = 0x1E84; +constexpr unsigned int mmCRTC1_CRTC_H_TOTAL__SI = 0x1E80; +constexpr unsigned int mmCRTC1_CRTC_INTERLACE_CONTROL__SI = 0x1E9E; +constexpr unsigned int mmCRTC1_CRTC_INTERLACE_STATUS__SI = 0x1E9F; +constexpr unsigned int mmCRTC1_CRTC_INTERRUPT_CONTROL__SI = 0x1EB4; +constexpr unsigned int mmCRTC1_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI = 0x1EAB; +constexpr unsigned int mmCRTC1_CRTC_MASTER_EN__SI = 0x1EC2; +constexpr unsigned int mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI = 0x1EC0; +constexpr unsigned int mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT__SI = 0x1EBF; +constexpr unsigned int mmCRTC1_CRTC_MVP_STATUS__SI = 0x1EC1; +constexpr unsigned int mmCRTC1_CRTC_NOM_VERT_POSITION__SI = 0x1EA5; +constexpr unsigned int mmCRTC1_CRTC_OVERSCAN_COLOR__SI = 0x1EA0; +constexpr unsigned int mmCRTC1_CRTC_PIXEL_DATA_READBACK__SI = 0x1E9A; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_CONTROL__SI = 0x1EB0; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_FRAME__SI = 0x1EB2; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_POSITION__SI = 0x1EB1; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_STATUS__SI = 0x1EAF; +constexpr unsigned int mmCRTC1_CRTC_START_LINE_CONTROL__SI = 0x1EB3; +constexpr unsigned int mmCRTC1_CRTC_STATUS_FRAME_COUNT__SI = 0x1EA6; +constexpr unsigned int mmCRTC1_CRTC_STATUS_HV_COUNT__SI = 0x1EA8; +constexpr unsigned int mmCRTC1_CRTC_STATUS_VF_COUNT__SI = 0x1EA7; +constexpr unsigned int mmCRTC1_CRTC_STEREO_CONTROL__SI = 0x1EAE; +constexpr unsigned int mmCRTC1_CRTC_STEREO_FORCE_NEXT_EYE__SI = 0x1E9B; +constexpr unsigned int mmCRTC1_CRTC_STEREO_STATUS__SI = 0x1EAD; +constexpr unsigned int mmCRTC1_CRTC_TEST_DEBUG_DATA__SI = 0x1EC7; +constexpr unsigned int mmCRTC1_CRTC_TEST_DEBUG_INDEX__SI = 0x1EC6; +constexpr unsigned int mmCRTC1_CRTC_TEST_PATTERN_COLOR__SI = 0x1EBC; +constexpr unsigned int mmCRTC1_CRTC_TEST_PATTERN_CONTROL__SI = 0x1EBA; +constexpr unsigned int mmCRTC1_CRTC_TEST_PATTERN_PARAMETERS__SI = 0x1EBB; +constexpr unsigned int mmCRTC1_CRTC_TRIGA_CNTL__SI = 0x1E94; +constexpr unsigned int mmCRTC1_CRTC_TRIGA_MANUAL_TRIG__SI = 0x1E95; +constexpr unsigned int mmCRTC1_CRTC_TRIGB_CNTL__SI = 0x1E96; +constexpr unsigned int mmCRTC1_CRTC_TRIGB_MANUAL_TRIG__SI = 0x1E97; +constexpr unsigned int mmCRTC1_CRTC_UPDATE_LOCK__SI = 0x1EB5; +constexpr unsigned int mmCRTC1_CRTC_VBI_END__SI = 0x1E86; +constexpr unsigned int mmCRTC1_CRTC_VERT_SYNC_CONTROL__SI = 0x1EAC; +constexpr unsigned int mmCRTC1_CRTC_VGA_PARAMETER_CAPTURE_MODE__SI = 0x1EB7; +constexpr unsigned int mmCRTC1_CRTC_VSYNC_NOM_INT_STATUS__SI = 0x1E8C; +constexpr unsigned int mmCRTC1_CRTC_V_BLANK_START_END__SI = 0x1E8D; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_A_CNTL__SI = 0x1E8F; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_A__SI = 0x1E8E; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_B_CNTL__SI = 0x1E91; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_B__SI = 0x1E90; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_CONTROL__SI = 0x1E8A; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_INT_STATUS__SI = 0x1E8B; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_MAX__SI = 0x1E89; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_MIN__SI = 0x1E88; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL__SI = 0x1E87; +constexpr unsigned int mmCRTC1_CRTC_V_UPDATE_INT_STATUS__SI = 0x1EC4; +constexpr unsigned int mmCRTC1_MASTER_UPDATE_LOCK__SI = 0x1EBD; +constexpr unsigned int mmCRTC1_PIXEL_RATE_CNTL__SI = 0x0121; +constexpr unsigned int mmCRTC2_CRTC_ALLOW_STOP_OFF_V_CNT__SI = 0x41C3; +constexpr unsigned int mmCRTC2_CRTC_BLACK_COLOR__SI = 0x41A2; +constexpr unsigned int mmCRTC2_CRTC_BLANK_DATA_COLOR__SI = 0x41A1; +constexpr unsigned int mmCRTC2_CRTC_CONTROL__SI = 0x419C; +constexpr unsigned int mmCRTC2_CRTC_COUNT_CONTROL__SI = 0x41A9; +constexpr unsigned int mmCRTC2_CRTC_COUNT_RESET__SI = 0x41AA; +constexpr unsigned int mmCRTC2_CRTC_DOUBLE_BUFFER_CONTROL__SI = 0x41B6; +constexpr unsigned int mmCRTC2_CRTC_DTMTEST_CNTL__SI = 0x4192; +constexpr unsigned int mmCRTC2_CRTC_DTMTEST_STATUS_POSITION__SI = 0x4193; +constexpr unsigned int mmCRTC2_CRTC_FLOW_CONTROL__SI = 0x4199; +constexpr unsigned int mmCRTC2_CRTC_FORCE_COUNT_NOW_CNTL__SI = 0x4198; +constexpr unsigned int mmCRTC2_CRTC_H_BLANK_START_END__SI = 0x4181; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_A_CNTL__SI = 0x4183; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_A__SI = 0x4182; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_B_CNTL__SI = 0x4185; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_B__SI = 0x4184; +constexpr unsigned int mmCRTC2_CRTC_H_TOTAL__SI = 0x4180; +constexpr unsigned int mmCRTC2_CRTC_INTERLACE_CONTROL__SI = 0x419E; +constexpr unsigned int mmCRTC2_CRTC_INTERLACE_STATUS__SI = 0x419F; +constexpr unsigned int mmCRTC2_CRTC_INTERRUPT_CONTROL__SI = 0x41B4; +constexpr unsigned int mmCRTC2_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI = 0x41AB; +constexpr unsigned int mmCRTC2_CRTC_MASTER_EN__SI = 0x41C2; +constexpr unsigned int mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI = 0x41C0; +constexpr unsigned int mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT__SI = 0x41BF; +constexpr unsigned int mmCRTC2_CRTC_MVP_STATUS__SI = 0x41C1; +constexpr unsigned int mmCRTC2_CRTC_NOM_VERT_POSITION__SI = 0x41A5; +constexpr unsigned int mmCRTC2_CRTC_OVERSCAN_COLOR__SI = 0x41A0; +constexpr unsigned int mmCRTC2_CRTC_PIXEL_DATA_READBACK__SI = 0x419A; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_CONTROL__SI = 0x41B0; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_FRAME__SI = 0x41B2; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_POSITION__SI = 0x41B1; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_STATUS__SI = 0x41AF; +constexpr unsigned int mmCRTC2_CRTC_START_LINE_CONTROL__SI = 0x41B3; +constexpr unsigned int mmCRTC2_CRTC_STATUS_FRAME_COUNT__SI = 0x41A6; +constexpr unsigned int mmCRTC2_CRTC_STATUS_HV_COUNT__SI = 0x41A8; +constexpr unsigned int mmCRTC2_CRTC_STATUS_VF_COUNT__SI = 0x41A7; +constexpr unsigned int mmCRTC2_CRTC_STEREO_CONTROL__SI = 0x41AE; +constexpr unsigned int mmCRTC2_CRTC_STEREO_FORCE_NEXT_EYE__SI = 0x419B; +constexpr unsigned int mmCRTC2_CRTC_STEREO_STATUS__SI = 0x41AD; +constexpr unsigned int mmCRTC2_CRTC_TEST_DEBUG_DATA__SI = 0x41C7; +constexpr unsigned int mmCRTC2_CRTC_TEST_DEBUG_INDEX__SI = 0x41C6; +constexpr unsigned int mmCRTC2_CRTC_TEST_PATTERN_COLOR__SI = 0x41BC; +constexpr unsigned int mmCRTC2_CRTC_TEST_PATTERN_CONTROL__SI = 0x41BA; +constexpr unsigned int mmCRTC2_CRTC_TEST_PATTERN_PARAMETERS__SI = 0x41BB; +constexpr unsigned int mmCRTC2_CRTC_TRIGA_CNTL__SI = 0x4194; +constexpr unsigned int mmCRTC2_CRTC_TRIGA_MANUAL_TRIG__SI = 0x4195; +constexpr unsigned int mmCRTC2_CRTC_TRIGB_CNTL__SI = 0x4196; +constexpr unsigned int mmCRTC2_CRTC_TRIGB_MANUAL_TRIG__SI = 0x4197; +constexpr unsigned int mmCRTC2_CRTC_UPDATE_LOCK__SI = 0x41B5; +constexpr unsigned int mmCRTC2_CRTC_VBI_END__SI = 0x4186; +constexpr unsigned int mmCRTC2_CRTC_VERT_SYNC_CONTROL__SI = 0x41AC; +constexpr unsigned int mmCRTC2_CRTC_VGA_PARAMETER_CAPTURE_MODE__SI = 0x41B7; +constexpr unsigned int mmCRTC2_CRTC_VSYNC_NOM_INT_STATUS__SI = 0x418C; +constexpr unsigned int mmCRTC2_CRTC_V_BLANK_START_END__SI = 0x418D; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_A_CNTL__SI = 0x418F; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_A__SI = 0x418E; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_B_CNTL__SI = 0x4191; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_B__SI = 0x4190; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_CONTROL__SI = 0x418A; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_INT_STATUS__SI = 0x418B; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_MAX__SI = 0x4189; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_MIN__SI = 0x4188; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL__SI = 0x4187; +constexpr unsigned int mmCRTC2_CRTC_V_UPDATE_INT_STATUS__SI = 0x41C4; +constexpr unsigned int mmCRTC2_MASTER_UPDATE_LOCK__SI = 0x41BD; +constexpr unsigned int mmCRTC2_PIXEL_RATE_CNTL__SI = 0x0122; +constexpr unsigned int mmCRTC3_CRTC_ALLOW_STOP_OFF_V_CNT__SI = 0x44C3; +constexpr unsigned int mmCRTC3_CRTC_BLACK_COLOR__SI = 0x44A2; +constexpr unsigned int mmCRTC3_CRTC_BLANK_DATA_COLOR__SI = 0x44A1; +constexpr unsigned int mmCRTC3_CRTC_CONTROL__SI = 0x449C; +constexpr unsigned int mmCRTC3_CRTC_COUNT_CONTROL__SI = 0x44A9; +constexpr unsigned int mmCRTC3_CRTC_COUNT_RESET__SI = 0x44AA; +constexpr unsigned int mmCRTC3_CRTC_DOUBLE_BUFFER_CONTROL__SI = 0x44B6; +constexpr unsigned int mmCRTC3_CRTC_DTMTEST_CNTL__SI = 0x4492; +constexpr unsigned int mmCRTC3_CRTC_DTMTEST_STATUS_POSITION__SI = 0x4493; +constexpr unsigned int mmCRTC3_CRTC_FLOW_CONTROL__SI = 0x4499; +constexpr unsigned int mmCRTC3_CRTC_FORCE_COUNT_NOW_CNTL__SI = 0x4498; +constexpr unsigned int mmCRTC3_CRTC_H_BLANK_START_END__SI = 0x4481; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_A_CNTL__SI = 0x4483; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_A__SI = 0x4482; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_B_CNTL__SI = 0x4485; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_B__SI = 0x4484; +constexpr unsigned int mmCRTC3_CRTC_H_TOTAL__SI = 0x4480; +constexpr unsigned int mmCRTC3_CRTC_INTERLACE_CONTROL__SI = 0x449E; +constexpr unsigned int mmCRTC3_CRTC_INTERLACE_STATUS__SI = 0x449F; +constexpr unsigned int mmCRTC3_CRTC_INTERRUPT_CONTROL__SI = 0x44B4; +constexpr unsigned int mmCRTC3_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI = 0x44AB; +constexpr unsigned int mmCRTC3_CRTC_MASTER_EN__SI = 0x44C2; +constexpr unsigned int mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI = 0x44C0; +constexpr unsigned int mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT__SI = 0x44BF; +constexpr unsigned int mmCRTC3_CRTC_MVP_STATUS__SI = 0x44C1; +constexpr unsigned int mmCRTC3_CRTC_NOM_VERT_POSITION__SI = 0x44A5; +constexpr unsigned int mmCRTC3_CRTC_OVERSCAN_COLOR__SI = 0x44A0; +constexpr unsigned int mmCRTC3_CRTC_PIXEL_DATA_READBACK__SI = 0x449A; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_CONTROL__SI = 0x44B0; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_FRAME__SI = 0x44B2; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_POSITION__SI = 0x44B1; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_STATUS__SI = 0x44AF; +constexpr unsigned int mmCRTC3_CRTC_START_LINE_CONTROL__SI = 0x44B3; +constexpr unsigned int mmCRTC3_CRTC_STATUS_FRAME_COUNT__SI = 0x44A6; +constexpr unsigned int mmCRTC3_CRTC_STATUS_HV_COUNT__SI = 0x44A8; +constexpr unsigned int mmCRTC3_CRTC_STATUS_VF_COUNT__SI = 0x44A7; +constexpr unsigned int mmCRTC3_CRTC_STEREO_CONTROL__SI = 0x44AE; +constexpr unsigned int mmCRTC3_CRTC_STEREO_FORCE_NEXT_EYE__SI = 0x449B; +constexpr unsigned int mmCRTC3_CRTC_STEREO_STATUS__SI = 0x44AD; +constexpr unsigned int mmCRTC3_CRTC_TEST_DEBUG_DATA__SI = 0x44C7; +constexpr unsigned int mmCRTC3_CRTC_TEST_DEBUG_INDEX__SI = 0x44C6; +constexpr unsigned int mmCRTC3_CRTC_TEST_PATTERN_COLOR__SI = 0x44BC; +constexpr unsigned int mmCRTC3_CRTC_TEST_PATTERN_CONTROL__SI = 0x44BA; +constexpr unsigned int mmCRTC3_CRTC_TEST_PATTERN_PARAMETERS__SI = 0x44BB; +constexpr unsigned int mmCRTC3_CRTC_TRIGA_CNTL__SI = 0x4494; +constexpr unsigned int mmCRTC3_CRTC_TRIGA_MANUAL_TRIG__SI = 0x4495; +constexpr unsigned int mmCRTC3_CRTC_TRIGB_CNTL__SI = 0x4496; +constexpr unsigned int mmCRTC3_CRTC_TRIGB_MANUAL_TRIG__SI = 0x4497; +constexpr unsigned int mmCRTC3_CRTC_UPDATE_LOCK__SI = 0x44B5; +constexpr unsigned int mmCRTC3_CRTC_VBI_END__SI = 0x4486; +constexpr unsigned int mmCRTC3_CRTC_VERT_SYNC_CONTROL__SI = 0x44AC; +constexpr unsigned int mmCRTC3_CRTC_VGA_PARAMETER_CAPTURE_MODE__SI = 0x44B7; +constexpr unsigned int mmCRTC3_CRTC_VSYNC_NOM_INT_STATUS__SI = 0x448C; +constexpr unsigned int mmCRTC3_CRTC_V_BLANK_START_END__SI = 0x448D; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_A_CNTL__SI = 0x448F; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_A__SI = 0x448E; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_B_CNTL__SI = 0x4491; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_B__SI = 0x4490; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_CONTROL__SI = 0x448A; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_INT_STATUS__SI = 0x448B; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_MAX__SI = 0x4489; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_MIN__SI = 0x4488; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL__SI = 0x4487; +constexpr unsigned int mmCRTC3_CRTC_V_UPDATE_INT_STATUS__SI = 0x44C4; +constexpr unsigned int mmCRTC3_MASTER_UPDATE_LOCK__SI = 0x44BD; +constexpr unsigned int mmCRTC3_PIXEL_RATE_CNTL__SI = 0x0123; +constexpr unsigned int mmCRTC4_CRTC_ALLOW_STOP_OFF_V_CNT__SI = 0x47C3; +constexpr unsigned int mmCRTC4_CRTC_BLACK_COLOR__SI = 0x47A2; +constexpr unsigned int mmCRTC4_CRTC_BLANK_DATA_COLOR__SI = 0x47A1; +constexpr unsigned int mmCRTC4_CRTC_CONTROL__SI = 0x479C; +constexpr unsigned int mmCRTC4_CRTC_COUNT_CONTROL__SI = 0x47A9; +constexpr unsigned int mmCRTC4_CRTC_COUNT_RESET__SI = 0x47AA; +constexpr unsigned int mmCRTC4_CRTC_DOUBLE_BUFFER_CONTROL__SI = 0x47B6; +constexpr unsigned int mmCRTC4_CRTC_DTMTEST_CNTL__SI = 0x4792; +constexpr unsigned int mmCRTC4_CRTC_DTMTEST_STATUS_POSITION__SI = 0x4793; +constexpr unsigned int mmCRTC4_CRTC_FLOW_CONTROL__SI = 0x4799; +constexpr unsigned int mmCRTC4_CRTC_FORCE_COUNT_NOW_CNTL__SI = 0x4798; +constexpr unsigned int mmCRTC4_CRTC_H_BLANK_START_END__SI = 0x4781; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_A_CNTL__SI = 0x4783; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_A__SI = 0x4782; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_B_CNTL__SI = 0x4785; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_B__SI = 0x4784; +constexpr unsigned int mmCRTC4_CRTC_H_TOTAL__SI = 0x4780; +constexpr unsigned int mmCRTC4_CRTC_INTERLACE_CONTROL__SI = 0x479E; +constexpr unsigned int mmCRTC4_CRTC_INTERLACE_STATUS__SI = 0x479F; +constexpr unsigned int mmCRTC4_CRTC_INTERRUPT_CONTROL__SI = 0x47B4; +constexpr unsigned int mmCRTC4_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI = 0x47AB; +constexpr unsigned int mmCRTC4_CRTC_MASTER_EN__SI = 0x47C2; +constexpr unsigned int mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI = 0x47C0; +constexpr unsigned int mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT__SI = 0x47BF; +constexpr unsigned int mmCRTC4_CRTC_MVP_STATUS__SI = 0x47C1; +constexpr unsigned int mmCRTC4_CRTC_NOM_VERT_POSITION__SI = 0x47A5; +constexpr unsigned int mmCRTC4_CRTC_OVERSCAN_COLOR__SI = 0x47A0; +constexpr unsigned int mmCRTC4_CRTC_PIXEL_DATA_READBACK__SI = 0x479A; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_CONTROL__SI = 0x47B0; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_FRAME__SI = 0x47B2; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_POSITION__SI = 0x47B1; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_STATUS__SI = 0x47AF; +constexpr unsigned int mmCRTC4_CRTC_START_LINE_CONTROL__SI = 0x47B3; +constexpr unsigned int mmCRTC4_CRTC_STATUS_FRAME_COUNT__SI = 0x47A6; +constexpr unsigned int mmCRTC4_CRTC_STATUS_HV_COUNT__SI = 0x47A8; +constexpr unsigned int mmCRTC4_CRTC_STATUS_VF_COUNT__SI = 0x47A7; +constexpr unsigned int mmCRTC4_CRTC_STEREO_CONTROL__SI = 0x47AE; +constexpr unsigned int mmCRTC4_CRTC_STEREO_FORCE_NEXT_EYE__SI = 0x479B; +constexpr unsigned int mmCRTC4_CRTC_STEREO_STATUS__SI = 0x47AD; +constexpr unsigned int mmCRTC4_CRTC_TEST_DEBUG_DATA__SI = 0x47C7; +constexpr unsigned int mmCRTC4_CRTC_TEST_DEBUG_INDEX__SI = 0x47C6; +constexpr unsigned int mmCRTC4_CRTC_TEST_PATTERN_COLOR__SI = 0x47BC; +constexpr unsigned int mmCRTC4_CRTC_TEST_PATTERN_CONTROL__SI = 0x47BA; +constexpr unsigned int mmCRTC4_CRTC_TEST_PATTERN_PARAMETERS__SI = 0x47BB; +constexpr unsigned int mmCRTC4_CRTC_TRIGA_CNTL__SI = 0x4794; +constexpr unsigned int mmCRTC4_CRTC_TRIGA_MANUAL_TRIG__SI = 0x4795; +constexpr unsigned int mmCRTC4_CRTC_TRIGB_CNTL__SI = 0x4796; +constexpr unsigned int mmCRTC4_CRTC_TRIGB_MANUAL_TRIG__SI = 0x4797; +constexpr unsigned int mmCRTC4_CRTC_UPDATE_LOCK__SI = 0x47B5; +constexpr unsigned int mmCRTC4_CRTC_VBI_END__SI = 0x4786; +constexpr unsigned int mmCRTC4_CRTC_VERT_SYNC_CONTROL__SI = 0x47AC; +constexpr unsigned int mmCRTC4_CRTC_VGA_PARAMETER_CAPTURE_MODE__SI = 0x47B7; +constexpr unsigned int mmCRTC4_CRTC_VSYNC_NOM_INT_STATUS__SI = 0x478C; +constexpr unsigned int mmCRTC4_CRTC_V_BLANK_START_END__SI = 0x478D; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_A_CNTL__SI = 0x478F; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_A__SI = 0x478E; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_B_CNTL__SI = 0x4791; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_B__SI = 0x4790; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_CONTROL__SI = 0x478A; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_INT_STATUS__SI = 0x478B; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_MAX__SI = 0x4789; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_MIN__SI = 0x4788; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL__SI = 0x4787; +constexpr unsigned int mmCRTC4_CRTC_V_UPDATE_INT_STATUS__SI = 0x47C4; +constexpr unsigned int mmCRTC4_MASTER_UPDATE_LOCK__SI = 0x47BD; +constexpr unsigned int mmCRTC4_PIXEL_RATE_CNTL__SI = 0x0124; +constexpr unsigned int mmCRTC5_CRTC_ALLOW_STOP_OFF_V_CNT__SI = 0x4AC3; +constexpr unsigned int mmCRTC5_CRTC_BLACK_COLOR__SI = 0x4AA2; +constexpr unsigned int mmCRTC5_CRTC_BLANK_DATA_COLOR__SI = 0x4AA1; +constexpr unsigned int mmCRTC5_CRTC_CONTROL__SI = 0x4A9C; +constexpr unsigned int mmCRTC5_CRTC_COUNT_CONTROL__SI = 0x4AA9; +constexpr unsigned int mmCRTC5_CRTC_COUNT_RESET__SI = 0x4AAA; +constexpr unsigned int mmCRTC5_CRTC_DOUBLE_BUFFER_CONTROL__SI = 0x4AB6; +constexpr unsigned int mmCRTC5_CRTC_DTMTEST_CNTL__SI = 0x4A92; +constexpr unsigned int mmCRTC5_CRTC_DTMTEST_STATUS_POSITION__SI = 0x4A93; +constexpr unsigned int mmCRTC5_CRTC_FLOW_CONTROL__SI = 0x4A99; +constexpr unsigned int mmCRTC5_CRTC_FORCE_COUNT_NOW_CNTL__SI = 0x4A98; +constexpr unsigned int mmCRTC5_CRTC_H_BLANK_START_END__SI = 0x4A81; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_A_CNTL__SI = 0x4A83; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_A__SI = 0x4A82; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_B_CNTL__SI = 0x4A85; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_B__SI = 0x4A84; +constexpr unsigned int mmCRTC5_CRTC_H_TOTAL__SI = 0x4A80; +constexpr unsigned int mmCRTC5_CRTC_INTERLACE_CONTROL__SI = 0x4A9E; +constexpr unsigned int mmCRTC5_CRTC_INTERLACE_STATUS__SI = 0x4A9F; +constexpr unsigned int mmCRTC5_CRTC_INTERRUPT_CONTROL__SI = 0x4AB4; +constexpr unsigned int mmCRTC5_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI = 0x4AAB; +constexpr unsigned int mmCRTC5_CRTC_MASTER_EN__SI = 0x4AC2; +constexpr unsigned int mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI = 0x4AC0; +constexpr unsigned int mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT__SI = 0x4ABF; +constexpr unsigned int mmCRTC5_CRTC_MVP_STATUS__SI = 0x4AC1; +constexpr unsigned int mmCRTC5_CRTC_NOM_VERT_POSITION__SI = 0x4AA5; +constexpr unsigned int mmCRTC5_CRTC_OVERSCAN_COLOR__SI = 0x4AA0; +constexpr unsigned int mmCRTC5_CRTC_PIXEL_DATA_READBACK__SI = 0x4A9A; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_CONTROL__SI = 0x4AB0; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_FRAME__SI = 0x4AB2; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_POSITION__SI = 0x4AB1; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_STATUS__SI = 0x4AAF; +constexpr unsigned int mmCRTC5_CRTC_START_LINE_CONTROL__SI = 0x4AB3; +constexpr unsigned int mmCRTC5_CRTC_STATUS_FRAME_COUNT__SI = 0x4AA6; +constexpr unsigned int mmCRTC5_CRTC_STATUS_HV_COUNT__SI = 0x4AA8; +constexpr unsigned int mmCRTC5_CRTC_STATUS_VF_COUNT__SI = 0x4AA7; +constexpr unsigned int mmCRTC5_CRTC_STEREO_CONTROL__SI = 0x4AAE; +constexpr unsigned int mmCRTC5_CRTC_STEREO_FORCE_NEXT_EYE__SI = 0x4A9B; +constexpr unsigned int mmCRTC5_CRTC_STEREO_STATUS__SI = 0x4AAD; +constexpr unsigned int mmCRTC5_CRTC_TEST_DEBUG_DATA__SI = 0x4AC7; +constexpr unsigned int mmCRTC5_CRTC_TEST_DEBUG_INDEX__SI = 0x4AC6; +constexpr unsigned int mmCRTC5_CRTC_TEST_PATTERN_COLOR__SI = 0x4ABC; +constexpr unsigned int mmCRTC5_CRTC_TEST_PATTERN_CONTROL__SI = 0x4ABA; +constexpr unsigned int mmCRTC5_CRTC_TEST_PATTERN_PARAMETERS__SI = 0x4ABB; +constexpr unsigned int mmCRTC5_CRTC_TRIGA_CNTL__SI = 0x4A94; +constexpr unsigned int mmCRTC5_CRTC_TRIGA_MANUAL_TRIG__SI = 0x4A95; +constexpr unsigned int mmCRTC5_CRTC_TRIGB_CNTL__SI = 0x4A96; +constexpr unsigned int mmCRTC5_CRTC_TRIGB_MANUAL_TRIG__SI = 0x4A97; +constexpr unsigned int mmCRTC5_CRTC_UPDATE_LOCK__SI = 0x4AB5; +constexpr unsigned int mmCRTC5_CRTC_VBI_END__SI = 0x4A86; +constexpr unsigned int mmCRTC5_CRTC_VERT_SYNC_CONTROL__SI = 0x4AAC; +constexpr unsigned int mmCRTC5_CRTC_VGA_PARAMETER_CAPTURE_MODE__SI = 0x4AB7; +constexpr unsigned int mmCRTC5_CRTC_VSYNC_NOM_INT_STATUS__SI = 0x4A8C; +constexpr unsigned int mmCRTC5_CRTC_V_BLANK_START_END__SI = 0x4A8D; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_A_CNTL__SI = 0x4A8F; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_A__SI = 0x4A8E; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_B_CNTL__SI = 0x4A91; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_B__SI = 0x4A90; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_CONTROL__SI = 0x4A8A; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_INT_STATUS__SI = 0x4A8B; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_MAX__SI = 0x4A89; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_MIN__SI = 0x4A88; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL__SI = 0x4A87; +constexpr unsigned int mmCRTC5_CRTC_V_UPDATE_INT_STATUS__SI = 0x4AC4; +constexpr unsigned int mmCRTC5_MASTER_UPDATE_LOCK__SI = 0x4ABD; +constexpr unsigned int mmCRTC5_PIXEL_RATE_CNTL__SI = 0x0125; +constexpr unsigned int mmCRTC8_DATA__SI__VI = 0x00ED; +constexpr unsigned int mmCRTC8_IDX__SI__VI = 0x00ED; +constexpr unsigned int mmCRTC_ALLOW_STOP_OFF_V_CNT__SI__VI = 0x1BC3; +constexpr unsigned int mmCRTC_BLACK_COLOR__SI = 0x1BA2; +constexpr unsigned int mmCRTC_BLANK_CONTROL = 0x1B9D; +constexpr unsigned int mmCRTC_BLANK_DATA_COLOR__SI = 0x1BA1; +constexpr unsigned int mmCRTC_CONTROL__SI__VI = 0x1B9C; +constexpr unsigned int mmCRTC_COUNT_CONTROL__SI__VI = 0x1BA9; +constexpr unsigned int mmCRTC_COUNT_RESET__SI__VI = 0x1BAA; +constexpr unsigned int mmCRTC_DOUBLE_BUFFER_CONTROL__SI__VI = 0x1BB6; +constexpr unsigned int mmCRTC_DTMTEST_CNTL__SI__VI = 0x1B92; +constexpr unsigned int mmCRTC_DTMTEST_STATUS_POSITION__SI__VI = 0x1B93; +constexpr unsigned int mmCRTC_FLOW_CONTROL__SI__VI = 0x1B99; +constexpr unsigned int mmCRTC_FORCE_COUNT_NOW_CNTL__SI__VI = 0x1B98; +constexpr unsigned int mmCRTC_H_BLANK_START_END__SI__VI = 0x1B81; +constexpr unsigned int mmCRTC_H_SYNC_A_CNTL__SI__VI = 0x1B83; +constexpr unsigned int mmCRTC_H_SYNC_A__SI__VI = 0x1B82; +constexpr unsigned int mmCRTC_H_SYNC_B_CNTL__SI__VI = 0x1B85; +constexpr unsigned int mmCRTC_H_SYNC_B__SI__VI = 0x1B84; +constexpr unsigned int mmCRTC_H_TOTAL__SI__VI = 0x1B80; +constexpr unsigned int mmCRTC_INTERLACE_CONTROL__SI__VI = 0x1B9E; +constexpr unsigned int mmCRTC_INTERLACE_STATUS__SI__VI = 0x1B9F; +constexpr unsigned int mmCRTC_INTERRUPT_CONTROL__SI__VI = 0x1BB4; +constexpr unsigned int mmCRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SI__VI = 0x1BAB; +constexpr unsigned int mmCRTC_MASTER_EN__SI__VI = 0x1BC2; +constexpr unsigned int mmCRTC_MVP_INBAND_CNTL_INSERT_TIMER__SI__VI = 0x1BC0; +constexpr unsigned int mmCRTC_MVP_INBAND_CNTL_INSERT__SI__VI = 0x1BBF; +constexpr unsigned int mmCRTC_MVP_STATUS__SI__VI = 0x1BC1; +constexpr unsigned int mmCRTC_NOM_VERT_POSITION__SI__VI = 0x1BA5; +constexpr unsigned int mmCRTC_OVERSCAN_COLOR__SI = 0x1BA0; +constexpr unsigned int mmCRTC_PIXEL_DATA_READBACK__SI = 0x1B9A; +constexpr unsigned int mmCRTC_SNAPSHOT_CONTROL__SI__VI = 0x1BB0; +constexpr unsigned int mmCRTC_SNAPSHOT_FRAME__SI__VI = 0x1BB2; +constexpr unsigned int mmCRTC_SNAPSHOT_POSITION__SI__VI = 0x1BB1; +constexpr unsigned int mmCRTC_SNAPSHOT_STATUS__SI__VI = 0x1BAF; +constexpr unsigned int mmCRTC_START_LINE_CONTROL__SI__VI = 0x1BB3; +constexpr unsigned int mmCRTC_STATUS = 0x1BA3; +constexpr unsigned int mmCRTC_STATUS_FRAME_COUNT__SI__VI = 0x1BA6; +constexpr unsigned int mmCRTC_STATUS_HV_COUNT__SI__VI = 0x1BA8; +constexpr unsigned int mmCRTC_STATUS_POSITION__SI__VI = 0x1BA4; +constexpr unsigned int mmCRTC_STATUS_VF_COUNT__SI__VI = 0x1BA7; +constexpr unsigned int mmCRTC_STEREO_CONTROL__SI__VI = 0x1BAE; +constexpr unsigned int mmCRTC_STEREO_FORCE_NEXT_EYE__SI = 0x1B9B; +constexpr unsigned int mmCRTC_STEREO_STATUS__SI__VI = 0x1BAD; +constexpr unsigned int mmCRTC_TEST_DEBUG_DATA__SI__VI = 0x1BC7; +constexpr unsigned int mmCRTC_TEST_DEBUG_INDEX__SI__VI = 0x1BC6; +constexpr unsigned int mmCRTC_TEST_PATTERN_COLOR__SI__VI = 0x1BBC; +constexpr unsigned int mmCRTC_TEST_PATTERN_CONTROL__SI__VI = 0x1BBA; +constexpr unsigned int mmCRTC_TEST_PATTERN_PARAMETERS__SI__VI = 0x1BBB; +constexpr unsigned int mmCRTC_TRIGA_CNTL__SI__VI = 0x1B94; +constexpr unsigned int mmCRTC_TRIGA_MANUAL_TRIG__SI__VI = 0x1B95; +constexpr unsigned int mmCRTC_TRIGB_CNTL__SI__VI = 0x1B96; +constexpr unsigned int mmCRTC_TRIGB_MANUAL_TRIG__SI__VI = 0x1B97; +constexpr unsigned int mmCRTC_UPDATE_LOCK__SI__VI = 0x1BB5; +constexpr unsigned int mmCRTC_VBI_END__SI__VI = 0x1B86; +constexpr unsigned int mmCRTC_VERT_SYNC_CONTROL__SI__VI = 0x1BAC; +constexpr unsigned int mmCRTC_VGA_PARAMETER_CAPTURE_MODE__SI__VI = 0x1BB7; +constexpr unsigned int mmCRTC_VSYNC_NOM_INT_STATUS__SI__VI = 0x1B8C; +constexpr unsigned int mmCRTC_V_BLANK_START_END__SI__VI = 0x1B8D; +constexpr unsigned int mmCRTC_V_SYNC_A_CNTL__SI__VI = 0x1B8F; +constexpr unsigned int mmCRTC_V_SYNC_A__SI__VI = 0x1B8E; +constexpr unsigned int mmCRTC_V_SYNC_B_CNTL__SI__VI = 0x1B91; +constexpr unsigned int mmCRTC_V_SYNC_B__SI__VI = 0x1B90; +constexpr unsigned int mmCRTC_V_TOTAL_CONTROL__SI__VI = 0x1B8A; +constexpr unsigned int mmCRTC_V_TOTAL_INT_STATUS__SI__VI = 0x1B8B; +constexpr unsigned int mmCRTC_V_TOTAL_MAX__SI__VI = 0x1B89; +constexpr unsigned int mmCRTC_V_TOTAL_MIN__SI__VI = 0x1B88; +constexpr unsigned int mmCRTC_V_TOTAL__SI__VI = 0x1B87; +constexpr unsigned int mmCRTC_V_UPDATE_INT_STATUS__SI__VI = 0x1BC4; +constexpr unsigned int mmCS_COPY_STATE = 0xA1F3; +constexpr unsigned int mmCUR_COLOR1__SI__VI = 0x1A6C; +constexpr unsigned int mmCUR_COLOR2__SI__VI = 0x1A6D; +constexpr unsigned int mmCUR_CONTROL__SI__VI = 0x1A66; +constexpr unsigned int mmCUR_HOT_SPOT__SI__VI = 0x1A6B; +constexpr unsigned int mmCUR_POSITION__SI__VI = 0x1A6A; +constexpr unsigned int mmCUR_SIZE__SI__VI = 0x1A68; +constexpr unsigned int mmCUR_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A69; +constexpr unsigned int mmCUR_SURFACE_ADDRESS__SI__VI = 0x1A67; +constexpr unsigned int mmCUR_UPDATE__SI__VI = 0x1A6E; +constexpr unsigned int mmD1VGA_CONTROL__SI__VI = 0x00CC; +constexpr unsigned int mmD2VGA_CONTROL__SI__VI = 0x00CE; +constexpr unsigned int mmD3VGA_CONTROL__SI__VI = 0x00F8; +constexpr unsigned int mmD4VGA_CONTROL__SI__VI = 0x00F9; +constexpr unsigned int mmD5VGA_CONTROL__SI__VI = 0x00FA; +constexpr unsigned int mmD6VGA_CONTROL__SI__VI = 0x00FB; +constexpr unsigned int mmDAC_AUTODETECT_CONTROL2__SI = 0x19AF; +constexpr unsigned int mmDAC_AUTODETECT_CONTROL3__SI = 0x19B0; +constexpr unsigned int mmDAC_AUTODETECT_CONTROL__SI = 0x19AE; +constexpr unsigned int mmDAC_AUTODETECT_INT_CONTROL__SI = 0x19B2; +constexpr unsigned int mmDAC_AUTODETECT_STATUS__SI = 0x19B1; +constexpr unsigned int mmDAC_COMPARATOR_ENABLE__SI = 0x19B7; +constexpr unsigned int mmDAC_COMPARATOR_OUTPUT__SI = 0x19B8; +constexpr unsigned int mmDAC_CONTROL__SI = 0x19B6; +constexpr unsigned int mmDAC_CRC_CONTROL__SI = 0x19A7; +constexpr unsigned int mmDAC_CRC_EN__SI = 0x19A6; +constexpr unsigned int mmDAC_CRC_SIG_CONTROL_MASK__SI = 0x19A9; +constexpr unsigned int mmDAC_CRC_SIG_CONTROL__SI = 0x19AB; +constexpr unsigned int mmDAC_CRC_SIG_RGB_MASK__SI = 0x19A8; +constexpr unsigned int mmDAC_CRC_SIG_RGB__SI = 0x19AA; +constexpr unsigned int mmDAC_DATA__SI__VI = 0x00F2; +constexpr unsigned int mmDAC_DFT_CONFIG__SI = 0x19BA; +constexpr unsigned int mmDAC_ENABLE__SI = 0x19A4; +constexpr unsigned int mmDAC_FORCE_DATA__SI = 0x19B4; +constexpr unsigned int mmDAC_FORCE_OUTPUT_CNTL__SI = 0x19B3; +constexpr unsigned int mmDAC_MACRO_CNTL__SI = 0x1939; +constexpr unsigned int mmDAC_MASK__SI__VI = 0x00F1; +constexpr unsigned int mmDAC_POWERDOWN__SI = 0x19B5; +constexpr unsigned int mmDAC_PWR_CNTL__SI = 0x19B9; +constexpr unsigned int mmDAC_R_INDEX__SI__VI = 0x00F1; +constexpr unsigned int mmDAC_SOURCE_SELECT__SI = 0x19A5; +constexpr unsigned int mmDAC_STEREOSYNC_SELECT__SI = 0x19AD; +constexpr unsigned int mmDAC_SYNC_TRISTATE_CONTROL__SI = 0x19AC; +constexpr unsigned int mmDAC_W_INDEX__SI__VI = 0x00F2; +constexpr unsigned int mmDATA_FORMAT__SI = 0x1AC0; +constexpr unsigned int mmDBG_BYPASS_SRBM_ACCESS__CI = 0x14EB; +constexpr unsigned int mmDB_ALPHA_TO_MASK = 0xA2DC; +constexpr unsigned int mmDB_CGTT_CLK_CTRL_0__CI__VI = 0xF0A4; +constexpr unsigned int mmDB_CGTT_CLK_CTRL_0__SI = 0x261A; +constexpr unsigned int mmDB_COUNT_CONTROL = 0xA001; +constexpr unsigned int mmDB_CREDIT_LIMIT = 0x2614; +constexpr unsigned int mmDB_DEBUG = 0x260C; +constexpr unsigned int mmDB_DEBUG2 = 0x260D; +constexpr unsigned int mmDB_DEBUG3 = 0x260E; +constexpr unsigned int mmDB_DEBUG4 = 0x260F; +constexpr unsigned int mmDB_DEPTH_BOUNDS_MAX = 0xA009; +constexpr unsigned int mmDB_DEPTH_BOUNDS_MIN = 0xA008; +constexpr unsigned int mmDB_DEPTH_CLEAR = 0xA00B; +constexpr unsigned int mmDB_DEPTH_CONTROL = 0xA200; +constexpr unsigned int mmDB_DEPTH_INFO = 0xA00F; +constexpr unsigned int mmDB_DEPTH_SIZE = 0xA016; +constexpr unsigned int mmDB_DEPTH_SLICE = 0xA017; +constexpr unsigned int mmDB_DEPTH_VIEW = 0xA002; +constexpr unsigned int mmDB_EQAA = 0xA201; +constexpr unsigned int mmDB_FIFO_DEPTH1 = 0x2618; +constexpr unsigned int mmDB_FIFO_DEPTH2 = 0x2619; +constexpr unsigned int mmDB_FREE_CACHELINES = 0x2617; +constexpr unsigned int mmDB_HTILE_DATA_BASE = 0xA005; +constexpr unsigned int mmDB_HTILE_SURFACE = 0xA2AF; +constexpr unsigned int mmDB_OCCLUSION_COUNT0_HI__CI__VI = 0xC3C1; +constexpr unsigned int mmDB_OCCLUSION_COUNT0_LOW__CI__VI = 0xC3C0; +constexpr unsigned int mmDB_OCCLUSION_COUNT1_HI__CI__VI = 0xC3C3; +constexpr unsigned int mmDB_OCCLUSION_COUNT1_LOW__CI__VI = 0xC3C2; +constexpr unsigned int mmDB_OCCLUSION_COUNT2_HI__CI__VI = 0xC3C5; +constexpr unsigned int mmDB_OCCLUSION_COUNT2_LOW__CI__VI = 0xC3C4; +constexpr unsigned int mmDB_OCCLUSION_COUNT3_HI__CI__VI = 0xC3C7; +constexpr unsigned int mmDB_OCCLUSION_COUNT3_LOW__CI__VI = 0xC3C6; +constexpr unsigned int mmDB_PERFCOUNTER0_HI__CI__VI = 0xD441; +constexpr unsigned int mmDB_PERFCOUNTER0_HI__SI = 0x2602; +constexpr unsigned int mmDB_PERFCOUNTER0_LO__CI__VI = 0xD440; +constexpr unsigned int mmDB_PERFCOUNTER0_LO__SI = 0x2601; +constexpr unsigned int mmDB_PERFCOUNTER0_SELECT1__CI__VI = 0xDC41; +constexpr unsigned int mmDB_PERFCOUNTER0_SELECT__CI__VI = 0xDC40; +constexpr unsigned int mmDB_PERFCOUNTER0_SELECT__SI = 0x2600; +constexpr unsigned int mmDB_PERFCOUNTER1_HI__CI__VI = 0xD443; +constexpr unsigned int mmDB_PERFCOUNTER1_HI__SI = 0x2605; +constexpr unsigned int mmDB_PERFCOUNTER1_LO__CI__VI = 0xD442; +constexpr unsigned int mmDB_PERFCOUNTER1_LO__SI = 0x2604; +constexpr unsigned int mmDB_PERFCOUNTER1_SELECT1__CI__VI = 0xDC43; +constexpr unsigned int mmDB_PERFCOUNTER1_SELECT__CI__VI = 0xDC42; +constexpr unsigned int mmDB_PERFCOUNTER1_SELECT__SI = 0x2603; +constexpr unsigned int mmDB_PERFCOUNTER2_HI__CI__VI = 0xD445; +constexpr unsigned int mmDB_PERFCOUNTER2_HI__SI = 0x2608; +constexpr unsigned int mmDB_PERFCOUNTER2_LO__CI__VI = 0xD444; +constexpr unsigned int mmDB_PERFCOUNTER2_LO__SI = 0x2607; +constexpr unsigned int mmDB_PERFCOUNTER2_SELECT__CI__VI = 0xDC44; +constexpr unsigned int mmDB_PERFCOUNTER2_SELECT__SI = 0x2606; +constexpr unsigned int mmDB_PERFCOUNTER3_HI__CI__VI = 0xD447; +constexpr unsigned int mmDB_PERFCOUNTER3_HI__SI = 0x260B; +constexpr unsigned int mmDB_PERFCOUNTER3_LO__CI__VI = 0xD446; +constexpr unsigned int mmDB_PERFCOUNTER3_LO__SI = 0x260A; +constexpr unsigned int mmDB_PERFCOUNTER3_SELECT__CI__VI = 0xDC46; +constexpr unsigned int mmDB_PERFCOUNTER3_SELECT__SI = 0x2609; +constexpr unsigned int mmDB_PRELOAD_CONTROL = 0xA2B2; +constexpr unsigned int mmDB_READ_DEBUG_0 = 0x2620; +constexpr unsigned int mmDB_READ_DEBUG_1 = 0x2621; +constexpr unsigned int mmDB_READ_DEBUG_2 = 0x2622; +constexpr unsigned int mmDB_READ_DEBUG_3 = 0x2623; +constexpr unsigned int mmDB_READ_DEBUG_4 = 0x2624; +constexpr unsigned int mmDB_READ_DEBUG_5 = 0x2625; +constexpr unsigned int mmDB_READ_DEBUG_6 = 0x2626; +constexpr unsigned int mmDB_READ_DEBUG_7 = 0x2627; +constexpr unsigned int mmDB_READ_DEBUG_8 = 0x2628; +constexpr unsigned int mmDB_READ_DEBUG_9 = 0x2629; +constexpr unsigned int mmDB_READ_DEBUG_A = 0x262A; +constexpr unsigned int mmDB_READ_DEBUG_B = 0x262B; +constexpr unsigned int mmDB_READ_DEBUG_C = 0x262C; +constexpr unsigned int mmDB_READ_DEBUG_D = 0x262D; +constexpr unsigned int mmDB_READ_DEBUG_E = 0x262E; +constexpr unsigned int mmDB_READ_DEBUG_F = 0x262F; +constexpr unsigned int mmDB_RENDER_CONTROL = 0xA000; +constexpr unsigned int mmDB_RENDER_OVERRIDE = 0xA003; +constexpr unsigned int mmDB_RENDER_OVERRIDE2 = 0xA004; +constexpr unsigned int mmDB_RING_CONTROL__CI__VI = 0x261B; +constexpr unsigned int mmDB_SHADER_CONTROL = 0xA203; +constexpr unsigned int mmDB_SRESULTS_COMPARE_STATE0 = 0xA2B0; +constexpr unsigned int mmDB_SRESULTS_COMPARE_STATE1 = 0xA2B1; +constexpr unsigned int mmDB_STENCILREFMASK = 0xA10C; +constexpr unsigned int mmDB_STENCILREFMASK_BF = 0xA10D; +constexpr unsigned int mmDB_STENCIL_CLEAR = 0xA00A; +constexpr unsigned int mmDB_STENCIL_CONTROL = 0xA10B; +constexpr unsigned int mmDB_STENCIL_INFO = 0xA011; +constexpr unsigned int mmDB_STENCIL_READ_BASE = 0xA013; +constexpr unsigned int mmDB_STENCIL_WRITE_BASE = 0xA015; +constexpr unsigned int mmDB_SUBTILE_CONTROL = 0x2616; +constexpr unsigned int mmDB_WATERMARKS = 0x2615; +constexpr unsigned int mmDB_ZPASS_COUNT_HI__CI__VI = 0xC3FF; +constexpr unsigned int mmDB_ZPASS_COUNT_HI__SI = 0x261D; +constexpr unsigned int mmDB_ZPASS_COUNT_LOW__CI__VI = 0xC3FE; +constexpr unsigned int mmDB_ZPASS_COUNT_LOW__SI = 0x261C; +constexpr unsigned int mmDB_Z_INFO = 0xA010; +constexpr unsigned int mmDB_Z_READ_BASE = 0xA012; +constexpr unsigned int mmDB_Z_WRITE_BASE = 0xA014; +constexpr unsigned int mmDCCG_AUDIO_DTO0_MODULE__SI = 0x0154; +constexpr unsigned int mmDCCG_AUDIO_DTO0_PHASE__SI = 0x0153; +constexpr unsigned int mmDCCG_GATE_DISABLE_CNTL__SI = 0x011F; +constexpr unsigned int mmDCCG_TEST_CLK_SEL__SI = 0x0147; +constexpr unsigned int mmDCCG_TEST_DEBUG_DATA__SI = 0x0159; +constexpr unsigned int mmDCCG_TEST_DEBUG_INDEX__SI = 0x0158; +constexpr unsigned int mmDCCG_VPCLK_CNTL__SI = 0x015E; +constexpr unsigned int mmDCDEBUG_BUS_CLK1_SEL__SI = 0x1860; +constexpr unsigned int mmDCDEBUG_BUS_CLK2_SEL__SI = 0x1861; +constexpr unsigned int mmDCDEBUG_BUS_CLK3_SEL__SI = 0x1862; +constexpr unsigned int mmDCDEBUG_BUS_CLK4_SEL__SI = 0x1863; +constexpr unsigned int mmDCDEBUG_OUT_CNTL__SI = 0x186B; +constexpr unsigned int mmDCDEBUG_OUT_PIN_OVERRIDE__SI = 0x186A; +constexpr unsigned int mmDCIO_DEBUG__SI = 0x196F; +constexpr unsigned int mmDCIO_IMPCAL_CNTL_AB__SI = 0x194C; +constexpr unsigned int mmDCIO_IMPCAL_CNTL_CD__SI = 0x194F; +constexpr unsigned int mmDCIO_IMPCAL_CNTL_EF__SI = 0x1952; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_DATA_SYNCHRONIZATION__SI = 0x1984; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_REG_TEST_OUTPUT__SI = 0x1986; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_DATA_SYNCHRONIZATION__SI = 0x1990; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_REG_TEST_OUTPUT__SI = 0x1992; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_DATA_SYNCHRONIZATION__SI = 0x199C; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_REG_TEST_OUTPUT__SI = 0x199E; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_DATA_SYNCHRONIZATION__SI = 0x19C4; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_REG_TEST_OUTPUT__SI = 0x19C6; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_DATA_SYNCHRONIZATION__SI = 0x19D0; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_REG_TEST_OUTPUT__SI = 0x19D2; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_DATA_SYNCHRONIZATION__SI = 0x19DC; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_REG_TEST_OUTPUT__SI = 0x19DE; +constexpr unsigned int mmDCI_TEST_DEBUG_DATA__SI = 0x0321; +constexpr unsigned int mmDCI_TEST_DEBUG_INDEX__SI = 0x0320; +constexpr unsigned int mmDCP0_CUR_COLOR1__SI__VI = 0x1A6C; +constexpr unsigned int mmDCP0_CUR_COLOR2__SI__VI = 0x1A6D; +constexpr unsigned int mmDCP0_CUR_CONTROL__SI__VI = 0x1A66; +constexpr unsigned int mmDCP0_CUR_HOT_SPOT__SI__VI = 0x1A6B; +constexpr unsigned int mmDCP0_CUR_POSITION__SI__VI = 0x1A6A; +constexpr unsigned int mmDCP0_CUR_SIZE__SI__VI = 0x1A68; +constexpr unsigned int mmDCP0_CUR_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A69; +constexpr unsigned int mmDCP0_CUR_SURFACE_ADDRESS__SI__VI = 0x1A67; +constexpr unsigned int mmDCP0_CUR_UPDATE__SI__VI = 0x1A6E; +constexpr unsigned int mmDCP0_DCP_CRC_CONTROL__SI__VI = 0x1A87; +constexpr unsigned int mmDCP0_DCP_CRC_CURRENT__SI__VI = 0x1A89; +constexpr unsigned int mmDCP0_DCP_CRC_LAST__SI__VI = 0x1A8B; +constexpr unsigned int mmDCP0_DCP_CRC_MASK__SI__VI = 0x1A88; +constexpr unsigned int mmDCP0_DCP_DEBUG__SI__VI = 0x1A8D; +constexpr unsigned int mmDCP0_DCP_LB_DATA_GAP_BETWEEN_CHUNK__SI__VI = 0x1A91; +constexpr unsigned int mmDCP0_DCP_TEST_DEBUG_DATA__SI__VI = 0x1A96; +constexpr unsigned int mmDCP0_DCP_TEST_DEBUG_INDEX__SI__VI = 0x1A95; +constexpr unsigned int mmDCP0_DC_LUT_30_COLOR__SI__VI = 0x1A7C; +constexpr unsigned int mmDCP0_DC_LUT_AUTOFILL__SI__VI = 0x1A7F; +constexpr unsigned int mmDCP0_DC_LUT_BLACK_OFFSET_BLUE__SI__VI = 0x1A81; +constexpr unsigned int mmDCP0_DC_LUT_BLACK_OFFSET_GREEN__SI__VI = 0x1A82; +constexpr unsigned int mmDCP0_DC_LUT_BLACK_OFFSET_RED__SI__VI = 0x1A83; +constexpr unsigned int mmDCP0_DC_LUT_CONTROL__SI__VI = 0x1A80; +constexpr unsigned int mmDCP0_DC_LUT_PWL_DATA__SI__VI = 0x1A7B; +constexpr unsigned int mmDCP0_DC_LUT_RW_INDEX__SI__VI = 0x1A79; +constexpr unsigned int mmDCP0_DC_LUT_RW_MODE__SI__VI = 0x1A78; +constexpr unsigned int mmDCP0_DC_LUT_SEQ_COLOR__SI__VI = 0x1A7A; +constexpr unsigned int mmDCP0_DC_LUT_WHITE_OFFSET_BLUE__SI__VI = 0x1A84; +constexpr unsigned int mmDCP0_DC_LUT_WHITE_OFFSET_GREEN__SI__VI = 0x1A85; +constexpr unsigned int mmDCP0_DC_LUT_WHITE_OFFSET_RED__SI__VI = 0x1A86; +constexpr unsigned int mmDCP0_DC_LUT_WRITE_EN_MASK__SI__VI = 0x1A7E; +constexpr unsigned int mmDCP0_GRPH_COMPRESS_PITCH__SI__VI = 0x1A1A; +constexpr unsigned int mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A1B; +constexpr unsigned int mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS__SI__VI = 0x1A19; +constexpr unsigned int mmDCP0_GRPH_CONTROL = 0x1A01; +constexpr unsigned int mmDCP0_GRPH_DFQ_CONTROL__SI__VI = 0x1A14; +constexpr unsigned int mmDCP0_GRPH_DFQ_STATUS__SI__VI = 0x1A15; +constexpr unsigned int mmDCP0_GRPH_ENABLE__SI__VI = 0x1A00; +constexpr unsigned int mmDCP0_GRPH_FLIP_CONTROL = 0x1A12; +constexpr unsigned int mmDCP0_GRPH_INTERRUPT_CONTROL__SI__VI = 0x1A17; +constexpr unsigned int mmDCP0_GRPH_INTERRUPT_STATUS__SI__VI = 0x1A16; +constexpr unsigned int mmDCP0_GRPH_LUT_10BIT_BYPASS__SI__VI = 0x1A02; +constexpr unsigned int mmDCP0_GRPH_PITCH = 0x1A06; +constexpr unsigned int mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS = 0x1A04; +constexpr unsigned int mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH = 0x1A07; +constexpr unsigned int mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A08; +constexpr unsigned int mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS__SI__VI = 0x1A05; +constexpr unsigned int mmDCP0_GRPH_SURFACE_ADDRESS_HIGH_INUSE__SI__VI = 0x1A18; +constexpr unsigned int mmDCP0_GRPH_SURFACE_ADDRESS_INUSE__SI__VI = 0x1A13; +constexpr unsigned int mmDCP0_GRPH_SURFACE_OFFSET_X__SI__VI = 0x1A09; +constexpr unsigned int mmDCP0_GRPH_SURFACE_OFFSET_Y__SI__VI = 0x1A0A; +constexpr unsigned int mmDCP0_GRPH_SWAP_CNTL__SI__VI = 0x1A03; +constexpr unsigned int mmDCP0_GRPH_UPDATE = 0x1A11; +constexpr unsigned int mmDCP0_GRPH_X_END__SI__VI = 0x1A0D; +constexpr unsigned int mmDCP0_GRPH_X_START__SI__VI = 0x1A0B; +constexpr unsigned int mmDCP0_GRPH_Y_END__SI__VI = 0x1A0E; +constexpr unsigned int mmDCP0_GRPH_Y_START__SI__VI = 0x1A0C; +constexpr unsigned int mmDCP0_OVLSCL_EDGE_PIXEL_CNTL__SI__VI = 0x1A2C; +constexpr unsigned int mmDCP0_OVL_CONTROL1__SI__VI = 0x1A1D; +constexpr unsigned int mmDCP0_OVL_CONTROL2__SI__VI = 0x1A1E; +constexpr unsigned int mmDCP0_OVL_DFQ_CONTROL__SI__VI = 0x1A29; +constexpr unsigned int mmDCP0_OVL_DFQ_STATUS__SI__VI = 0x1A2A; +constexpr unsigned int mmDCP0_OVL_ENABLE__SI__VI = 0x1A1C; +constexpr unsigned int mmDCP0_OVL_END__SI__VI = 0x1A26; +constexpr unsigned int mmDCP0_OVL_PITCH__SI__VI = 0x1A21; +constexpr unsigned int mmDCP0_OVL_START__SI__VI = 0x1A25; +constexpr unsigned int mmDCP0_OVL_SURFACE_ADDRESS = 0x1A20; +constexpr unsigned int mmDCP0_OVL_SURFACE_ADDRESS_HIGH = 0x1A22; +constexpr unsigned int mmDCP0_OVL_SURFACE_ADDRESS_HIGH_INUSE__SI__VI = 0x1A2B; +constexpr unsigned int mmDCP0_OVL_SURFACE_ADDRESS_INUSE__SI__VI = 0x1A28; +constexpr unsigned int mmDCP0_OVL_SURFACE_OFFSET_X__SI__VI = 0x1A23; +constexpr unsigned int mmDCP0_OVL_SURFACE_OFFSET_Y__SI__VI = 0x1A24; +constexpr unsigned int mmDCP0_OVL_SWAP_CNTL__SI__VI = 0x1A1F; +constexpr unsigned int mmDCP0_OVL_UPDATE__SI__VI = 0x1A27; +constexpr unsigned int mmDCP1_CUR_COLOR1__SI = 0x1D6C; +constexpr unsigned int mmDCP1_CUR_COLOR2__SI = 0x1D6D; +constexpr unsigned int mmDCP1_CUR_CONTROL__SI = 0x1D66; +constexpr unsigned int mmDCP1_CUR_HOT_SPOT__SI = 0x1D6B; +constexpr unsigned int mmDCP1_CUR_POSITION__SI = 0x1D6A; +constexpr unsigned int mmDCP1_CUR_SIZE__SI = 0x1D68; +constexpr unsigned int mmDCP1_CUR_SURFACE_ADDRESS_HIGH__SI = 0x1D69; +constexpr unsigned int mmDCP1_CUR_SURFACE_ADDRESS__SI = 0x1D67; +constexpr unsigned int mmDCP1_CUR_UPDATE__SI = 0x1D6E; +constexpr unsigned int mmDCP1_DCP_CRC_CONTROL__SI = 0x1D87; +constexpr unsigned int mmDCP1_DCP_CRC_CURRENT__SI = 0x1D89; +constexpr unsigned int mmDCP1_DCP_CRC_LAST__SI = 0x1D8B; +constexpr unsigned int mmDCP1_DCP_CRC_MASK__SI = 0x1D88; +constexpr unsigned int mmDCP1_DCP_DEBUG__SI = 0x1D8D; +constexpr unsigned int mmDCP1_DCP_LB_DATA_GAP_BETWEEN_CHUNK__SI = 0x1D91; +constexpr unsigned int mmDCP1_DCP_TEST_DEBUG_DATA__SI = 0x1D96; +constexpr unsigned int mmDCP1_DCP_TEST_DEBUG_INDEX__SI = 0x1D95; +constexpr unsigned int mmDCP1_DC_LUT_30_COLOR__SI = 0x1D7C; +constexpr unsigned int mmDCP1_DC_LUT_AUTOFILL__SI = 0x1D7F; +constexpr unsigned int mmDCP1_DC_LUT_BLACK_OFFSET_BLUE__SI = 0x1D81; +constexpr unsigned int mmDCP1_DC_LUT_BLACK_OFFSET_GREEN__SI = 0x1D82; +constexpr unsigned int mmDCP1_DC_LUT_BLACK_OFFSET_RED__SI = 0x1D83; +constexpr unsigned int mmDCP1_DC_LUT_CONTROL__SI = 0x1D80; +constexpr unsigned int mmDCP1_DC_LUT_PWL_DATA__SI = 0x1D7B; +constexpr unsigned int mmDCP1_DC_LUT_RW_INDEX__SI = 0x1D79; +constexpr unsigned int mmDCP1_DC_LUT_RW_MODE__SI = 0x1D78; +constexpr unsigned int mmDCP1_DC_LUT_SEQ_COLOR__SI = 0x1D7A; +constexpr unsigned int mmDCP1_DC_LUT_WHITE_OFFSET_BLUE__SI = 0x1D84; +constexpr unsigned int mmDCP1_DC_LUT_WHITE_OFFSET_GREEN__SI = 0x1D85; +constexpr unsigned int mmDCP1_DC_LUT_WHITE_OFFSET_RED__SI = 0x1D86; +constexpr unsigned int mmDCP1_DC_LUT_WRITE_EN_MASK__SI = 0x1D7E; +constexpr unsigned int mmDCP1_GRPH_COMPRESS_PITCH__SI = 0x1D1A; +constexpr unsigned int mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI = 0x1D1B; +constexpr unsigned int mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS__SI = 0x1D19; +constexpr unsigned int mmDCP1_GRPH_DFQ_CONTROL__SI = 0x1D14; +constexpr unsigned int mmDCP1_GRPH_DFQ_STATUS__SI = 0x1D15; +constexpr unsigned int mmDCP1_GRPH_ENABLE__SI = 0x1D00; +constexpr unsigned int mmDCP1_GRPH_INTERRUPT_CONTROL__SI = 0x1D17; +constexpr unsigned int mmDCP1_GRPH_INTERRUPT_STATUS__SI = 0x1D16; +constexpr unsigned int mmDCP1_GRPH_LUT_10BIT_BYPASS__SI = 0x1D02; +constexpr unsigned int mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SI = 0x1D07; +constexpr unsigned int mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI = 0x1D08; +constexpr unsigned int mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS__SI = 0x1D05; +constexpr unsigned int mmDCP1_GRPH_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x1D18; +constexpr unsigned int mmDCP1_GRPH_SURFACE_ADDRESS_INUSE__SI = 0x1D13; +constexpr unsigned int mmDCP1_GRPH_SURFACE_OFFSET_X__SI = 0x1D09; +constexpr unsigned int mmDCP1_GRPH_SURFACE_OFFSET_Y__SI = 0x1D0A; +constexpr unsigned int mmDCP1_GRPH_SWAP_CNTL__SI = 0x1D03; +constexpr unsigned int mmDCP1_GRPH_X_END__SI = 0x1D0D; +constexpr unsigned int mmDCP1_GRPH_X_START__SI = 0x1D0B; +constexpr unsigned int mmDCP1_GRPH_Y_END__SI = 0x1D0E; +constexpr unsigned int mmDCP1_GRPH_Y_START__SI = 0x1D0C; +constexpr unsigned int mmDCP1_OVLSCL_EDGE_PIXEL_CNTL__SI = 0x1D2C; +constexpr unsigned int mmDCP1_OVL_CONTROL1__SI = 0x1D1D; +constexpr unsigned int mmDCP1_OVL_CONTROL2__SI = 0x1D1E; +constexpr unsigned int mmDCP1_OVL_DFQ_CONTROL__SI = 0x1D29; +constexpr unsigned int mmDCP1_OVL_DFQ_STATUS__SI = 0x1D2A; +constexpr unsigned int mmDCP1_OVL_ENABLE__SI = 0x1D1C; +constexpr unsigned int mmDCP1_OVL_END__SI = 0x1D26; +constexpr unsigned int mmDCP1_OVL_PITCH__SI = 0x1D21; +constexpr unsigned int mmDCP1_OVL_START__SI = 0x1D25; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x1D2B; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS_HIGH__SI = 0x1D22; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS_INUSE__SI = 0x1D28; +constexpr unsigned int mmDCP1_OVL_SURFACE_OFFSET_X__SI = 0x1D23; +constexpr unsigned int mmDCP1_OVL_SURFACE_OFFSET_Y__SI = 0x1D24; +constexpr unsigned int mmDCP1_OVL_SWAP_CNTL__SI = 0x1D1F; +constexpr unsigned int mmDCP1_OVL_UPDATE__SI = 0x1D27; +constexpr unsigned int mmDCP2_CUR_COLOR1__SI = 0x406C; +constexpr unsigned int mmDCP2_CUR_COLOR2__SI = 0x406D; +constexpr unsigned int mmDCP2_CUR_CONTROL__SI = 0x4066; +constexpr unsigned int mmDCP2_CUR_HOT_SPOT__SI = 0x406B; +constexpr unsigned int mmDCP2_CUR_POSITION__SI = 0x406A; +constexpr unsigned int mmDCP2_CUR_SIZE__SI = 0x4068; +constexpr unsigned int mmDCP2_CUR_SURFACE_ADDRESS_HIGH__SI = 0x4069; +constexpr unsigned int mmDCP2_CUR_SURFACE_ADDRESS__SI = 0x4067; +constexpr unsigned int mmDCP2_CUR_UPDATE__SI = 0x406E; +constexpr unsigned int mmDCP2_DCP_CRC_CONTROL__SI = 0x4087; +constexpr unsigned int mmDCP2_DCP_CRC_CURRENT__SI = 0x4089; +constexpr unsigned int mmDCP2_DCP_CRC_LAST__SI = 0x408B; +constexpr unsigned int mmDCP2_DCP_CRC_MASK__SI = 0x4088; +constexpr unsigned int mmDCP2_DCP_DEBUG__SI = 0x408D; +constexpr unsigned int mmDCP2_DCP_LB_DATA_GAP_BETWEEN_CHUNK__SI = 0x4091; +constexpr unsigned int mmDCP2_DCP_TEST_DEBUG_DATA__SI = 0x4096; +constexpr unsigned int mmDCP2_DCP_TEST_DEBUG_INDEX__SI = 0x4095; +constexpr unsigned int mmDCP2_DC_LUT_30_COLOR__SI = 0x407C; +constexpr unsigned int mmDCP2_DC_LUT_AUTOFILL__SI = 0x407F; +constexpr unsigned int mmDCP2_DC_LUT_BLACK_OFFSET_BLUE__SI = 0x4081; +constexpr unsigned int mmDCP2_DC_LUT_BLACK_OFFSET_GREEN__SI = 0x4082; +constexpr unsigned int mmDCP2_DC_LUT_BLACK_OFFSET_RED__SI = 0x4083; +constexpr unsigned int mmDCP2_DC_LUT_CONTROL__SI = 0x4080; +constexpr unsigned int mmDCP2_DC_LUT_PWL_DATA__SI = 0x407B; +constexpr unsigned int mmDCP2_DC_LUT_RW_INDEX__SI = 0x4079; +constexpr unsigned int mmDCP2_DC_LUT_RW_MODE__SI = 0x4078; +constexpr unsigned int mmDCP2_DC_LUT_SEQ_COLOR__SI = 0x407A; +constexpr unsigned int mmDCP2_DC_LUT_WHITE_OFFSET_BLUE__SI = 0x4084; +constexpr unsigned int mmDCP2_DC_LUT_WHITE_OFFSET_GREEN__SI = 0x4085; +constexpr unsigned int mmDCP2_DC_LUT_WHITE_OFFSET_RED__SI = 0x4086; +constexpr unsigned int mmDCP2_DC_LUT_WRITE_EN_MASK__SI = 0x407E; +constexpr unsigned int mmDCP2_GRPH_COMPRESS_PITCH__SI = 0x401A; +constexpr unsigned int mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI = 0x401B; +constexpr unsigned int mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS__SI = 0x4019; +constexpr unsigned int mmDCP2_GRPH_DFQ_CONTROL__SI = 0x4014; +constexpr unsigned int mmDCP2_GRPH_DFQ_STATUS__SI = 0x4015; +constexpr unsigned int mmDCP2_GRPH_ENABLE__SI = 0x4000; +constexpr unsigned int mmDCP2_GRPH_INTERRUPT_CONTROL__SI = 0x4017; +constexpr unsigned int mmDCP2_GRPH_INTERRUPT_STATUS__SI = 0x4016; +constexpr unsigned int mmDCP2_GRPH_LUT_10BIT_BYPASS__SI = 0x4002; +constexpr unsigned int mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SI = 0x4007; +constexpr unsigned int mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI = 0x4008; +constexpr unsigned int mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS__SI = 0x4005; +constexpr unsigned int mmDCP2_GRPH_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x4018; +constexpr unsigned int mmDCP2_GRPH_SURFACE_ADDRESS_INUSE__SI = 0x4013; +constexpr unsigned int mmDCP2_GRPH_SURFACE_OFFSET_X__SI = 0x4009; +constexpr unsigned int mmDCP2_GRPH_SURFACE_OFFSET_Y__SI = 0x400A; +constexpr unsigned int mmDCP2_GRPH_SWAP_CNTL__SI = 0x4003; +constexpr unsigned int mmDCP2_GRPH_X_END__SI = 0x400D; +constexpr unsigned int mmDCP2_GRPH_X_START__SI = 0x400B; +constexpr unsigned int mmDCP2_GRPH_Y_END__SI = 0x400E; +constexpr unsigned int mmDCP2_GRPH_Y_START__SI = 0x400C; +constexpr unsigned int mmDCP2_OVLSCL_EDGE_PIXEL_CNTL__SI = 0x402C; +constexpr unsigned int mmDCP2_OVL_CONTROL1__SI = 0x401D; +constexpr unsigned int mmDCP2_OVL_CONTROL2__SI = 0x401E; +constexpr unsigned int mmDCP2_OVL_DFQ_CONTROL__SI = 0x4029; +constexpr unsigned int mmDCP2_OVL_DFQ_STATUS__SI = 0x402A; +constexpr unsigned int mmDCP2_OVL_ENABLE__SI = 0x401C; +constexpr unsigned int mmDCP2_OVL_END__SI = 0x4026; +constexpr unsigned int mmDCP2_OVL_PITCH__SI = 0x4021; +constexpr unsigned int mmDCP2_OVL_START__SI = 0x4025; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x402B; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS_HIGH__SI = 0x4022; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS_INUSE__SI = 0x4028; +constexpr unsigned int mmDCP2_OVL_SURFACE_OFFSET_X__SI = 0x4023; +constexpr unsigned int mmDCP2_OVL_SURFACE_OFFSET_Y__SI = 0x4024; +constexpr unsigned int mmDCP2_OVL_SWAP_CNTL__SI = 0x401F; +constexpr unsigned int mmDCP2_OVL_UPDATE__SI = 0x4027; +constexpr unsigned int mmDCP3_CUR_COLOR1__SI = 0x436C; +constexpr unsigned int mmDCP3_CUR_COLOR2__SI = 0x436D; +constexpr unsigned int mmDCP3_CUR_CONTROL__SI = 0x4366; +constexpr unsigned int mmDCP3_CUR_HOT_SPOT__SI = 0x436B; +constexpr unsigned int mmDCP3_CUR_POSITION__SI = 0x436A; +constexpr unsigned int mmDCP3_CUR_SIZE__SI = 0x4368; +constexpr unsigned int mmDCP3_CUR_SURFACE_ADDRESS_HIGH__SI = 0x4369; +constexpr unsigned int mmDCP3_CUR_SURFACE_ADDRESS__SI = 0x4367; +constexpr unsigned int mmDCP3_CUR_UPDATE__SI = 0x436E; +constexpr unsigned int mmDCP3_DCP_CRC_CONTROL__SI = 0x4387; +constexpr unsigned int mmDCP3_DCP_CRC_CURRENT__SI = 0x4389; +constexpr unsigned int mmDCP3_DCP_CRC_LAST__SI = 0x438B; +constexpr unsigned int mmDCP3_DCP_CRC_MASK__SI = 0x4388; +constexpr unsigned int mmDCP3_DCP_DEBUG__SI = 0x438D; +constexpr unsigned int mmDCP3_DCP_LB_DATA_GAP_BETWEEN_CHUNK__SI = 0x4391; +constexpr unsigned int mmDCP3_DCP_TEST_DEBUG_DATA__SI = 0x4396; +constexpr unsigned int mmDCP3_DCP_TEST_DEBUG_INDEX__SI = 0x4395; +constexpr unsigned int mmDCP3_DC_LUT_30_COLOR__SI = 0x437C; +constexpr unsigned int mmDCP3_DC_LUT_AUTOFILL__SI = 0x437F; +constexpr unsigned int mmDCP3_DC_LUT_BLACK_OFFSET_BLUE__SI = 0x4381; +constexpr unsigned int mmDCP3_DC_LUT_BLACK_OFFSET_GREEN__SI = 0x4382; +constexpr unsigned int mmDCP3_DC_LUT_BLACK_OFFSET_RED__SI = 0x4383; +constexpr unsigned int mmDCP3_DC_LUT_CONTROL__SI = 0x4380; +constexpr unsigned int mmDCP3_DC_LUT_PWL_DATA__SI = 0x437B; +constexpr unsigned int mmDCP3_DC_LUT_RW_INDEX__SI = 0x4379; +constexpr unsigned int mmDCP3_DC_LUT_RW_MODE__SI = 0x4378; +constexpr unsigned int mmDCP3_DC_LUT_SEQ_COLOR__SI = 0x437A; +constexpr unsigned int mmDCP3_DC_LUT_WHITE_OFFSET_BLUE__SI = 0x4384; +constexpr unsigned int mmDCP3_DC_LUT_WHITE_OFFSET_GREEN__SI = 0x4385; +constexpr unsigned int mmDCP3_DC_LUT_WHITE_OFFSET_RED__SI = 0x4386; +constexpr unsigned int mmDCP3_DC_LUT_WRITE_EN_MASK__SI = 0x437E; +constexpr unsigned int mmDCP3_GRPH_COMPRESS_PITCH__SI = 0x431A; +constexpr unsigned int mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI = 0x431B; +constexpr unsigned int mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS__SI = 0x4319; +constexpr unsigned int mmDCP3_GRPH_DFQ_CONTROL__SI = 0x4314; +constexpr unsigned int mmDCP3_GRPH_DFQ_STATUS__SI = 0x4315; +constexpr unsigned int mmDCP3_GRPH_ENABLE__SI = 0x4300; +constexpr unsigned int mmDCP3_GRPH_INTERRUPT_CONTROL__SI = 0x4317; +constexpr unsigned int mmDCP3_GRPH_INTERRUPT_STATUS__SI = 0x4316; +constexpr unsigned int mmDCP3_GRPH_LUT_10BIT_BYPASS__SI = 0x4302; +constexpr unsigned int mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SI = 0x4307; +constexpr unsigned int mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI = 0x4308; +constexpr unsigned int mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS__SI = 0x4305; +constexpr unsigned int mmDCP3_GRPH_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x4318; +constexpr unsigned int mmDCP3_GRPH_SURFACE_ADDRESS_INUSE__SI = 0x4313; +constexpr unsigned int mmDCP3_GRPH_SURFACE_OFFSET_X__SI = 0x4309; +constexpr unsigned int mmDCP3_GRPH_SURFACE_OFFSET_Y__SI = 0x430A; +constexpr unsigned int mmDCP3_GRPH_SWAP_CNTL__SI = 0x4303; +constexpr unsigned int mmDCP3_GRPH_X_END__SI = 0x430D; +constexpr unsigned int mmDCP3_GRPH_X_START__SI = 0x430B; +constexpr unsigned int mmDCP3_GRPH_Y_END__SI = 0x430E; +constexpr unsigned int mmDCP3_GRPH_Y_START__SI = 0x430C; +constexpr unsigned int mmDCP3_OVLSCL_EDGE_PIXEL_CNTL__SI = 0x432C; +constexpr unsigned int mmDCP3_OVL_CONTROL1__SI = 0x431D; +constexpr unsigned int mmDCP3_OVL_CONTROL2__SI = 0x431E; +constexpr unsigned int mmDCP3_OVL_DFQ_CONTROL__SI = 0x4329; +constexpr unsigned int mmDCP3_OVL_DFQ_STATUS__SI = 0x432A; +constexpr unsigned int mmDCP3_OVL_ENABLE__SI = 0x431C; +constexpr unsigned int mmDCP3_OVL_END__SI = 0x4326; +constexpr unsigned int mmDCP3_OVL_PITCH__SI = 0x4321; +constexpr unsigned int mmDCP3_OVL_START__SI = 0x4325; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x432B; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS_HIGH__SI = 0x4322; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS_INUSE__SI = 0x4328; +constexpr unsigned int mmDCP3_OVL_SURFACE_OFFSET_X__SI = 0x4323; +constexpr unsigned int mmDCP3_OVL_SURFACE_OFFSET_Y__SI = 0x4324; +constexpr unsigned int mmDCP3_OVL_SWAP_CNTL__SI = 0x431F; +constexpr unsigned int mmDCP3_OVL_UPDATE__SI = 0x4327; +constexpr unsigned int mmDCP4_CUR_COLOR1__SI = 0x466C; +constexpr unsigned int mmDCP4_CUR_COLOR2__SI = 0x466D; +constexpr unsigned int mmDCP4_CUR_CONTROL__SI = 0x4666; +constexpr unsigned int mmDCP4_CUR_HOT_SPOT__SI = 0x466B; +constexpr unsigned int mmDCP4_CUR_POSITION__SI = 0x466A; +constexpr unsigned int mmDCP4_CUR_SIZE__SI = 0x4668; +constexpr unsigned int mmDCP4_CUR_SURFACE_ADDRESS_HIGH__SI = 0x4669; +constexpr unsigned int mmDCP4_CUR_SURFACE_ADDRESS__SI = 0x4667; +constexpr unsigned int mmDCP4_CUR_UPDATE__SI = 0x466E; +constexpr unsigned int mmDCP4_DCP_CRC_CONTROL__SI = 0x4687; +constexpr unsigned int mmDCP4_DCP_CRC_CURRENT__SI = 0x4689; +constexpr unsigned int mmDCP4_DCP_CRC_LAST__SI = 0x468B; +constexpr unsigned int mmDCP4_DCP_CRC_MASK__SI = 0x4688; +constexpr unsigned int mmDCP4_DCP_DEBUG__SI = 0x468D; +constexpr unsigned int mmDCP4_DCP_LB_DATA_GAP_BETWEEN_CHUNK__SI = 0x4691; +constexpr unsigned int mmDCP4_DCP_TEST_DEBUG_DATA__SI = 0x4696; +constexpr unsigned int mmDCP4_DCP_TEST_DEBUG_INDEX__SI = 0x4695; +constexpr unsigned int mmDCP4_DC_LUT_30_COLOR__SI = 0x467C; +constexpr unsigned int mmDCP4_DC_LUT_AUTOFILL__SI = 0x467F; +constexpr unsigned int mmDCP4_DC_LUT_BLACK_OFFSET_BLUE__SI = 0x4681; +constexpr unsigned int mmDCP4_DC_LUT_BLACK_OFFSET_GREEN__SI = 0x4682; +constexpr unsigned int mmDCP4_DC_LUT_BLACK_OFFSET_RED__SI = 0x4683; +constexpr unsigned int mmDCP4_DC_LUT_CONTROL__SI = 0x4680; +constexpr unsigned int mmDCP4_DC_LUT_PWL_DATA__SI = 0x467B; +constexpr unsigned int mmDCP4_DC_LUT_RW_INDEX__SI = 0x4679; +constexpr unsigned int mmDCP4_DC_LUT_RW_MODE__SI = 0x4678; +constexpr unsigned int mmDCP4_DC_LUT_SEQ_COLOR__SI = 0x467A; +constexpr unsigned int mmDCP4_DC_LUT_WHITE_OFFSET_BLUE__SI = 0x4684; +constexpr unsigned int mmDCP4_DC_LUT_WHITE_OFFSET_GREEN__SI = 0x4685; +constexpr unsigned int mmDCP4_DC_LUT_WHITE_OFFSET_RED__SI = 0x4686; +constexpr unsigned int mmDCP4_DC_LUT_WRITE_EN_MASK__SI = 0x467E; +constexpr unsigned int mmDCP4_GRPH_COMPRESS_PITCH__SI = 0x461A; +constexpr unsigned int mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI = 0x461B; +constexpr unsigned int mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS__SI = 0x4619; +constexpr unsigned int mmDCP4_GRPH_DFQ_CONTROL__SI = 0x4614; +constexpr unsigned int mmDCP4_GRPH_DFQ_STATUS__SI = 0x4615; +constexpr unsigned int mmDCP4_GRPH_ENABLE__SI = 0x4600; +constexpr unsigned int mmDCP4_GRPH_INTERRUPT_CONTROL__SI = 0x4617; +constexpr unsigned int mmDCP4_GRPH_INTERRUPT_STATUS__SI = 0x4616; +constexpr unsigned int mmDCP4_GRPH_LUT_10BIT_BYPASS__SI = 0x4602; +constexpr unsigned int mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SI = 0x4607; +constexpr unsigned int mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI = 0x4608; +constexpr unsigned int mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS__SI = 0x4605; +constexpr unsigned int mmDCP4_GRPH_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x4618; +constexpr unsigned int mmDCP4_GRPH_SURFACE_ADDRESS_INUSE__SI = 0x4613; +constexpr unsigned int mmDCP4_GRPH_SURFACE_OFFSET_X__SI = 0x4609; +constexpr unsigned int mmDCP4_GRPH_SURFACE_OFFSET_Y__SI = 0x460A; +constexpr unsigned int mmDCP4_GRPH_SWAP_CNTL__SI = 0x4603; +constexpr unsigned int mmDCP4_GRPH_X_END__SI = 0x460D; +constexpr unsigned int mmDCP4_GRPH_X_START__SI = 0x460B; +constexpr unsigned int mmDCP4_GRPH_Y_END__SI = 0x460E; +constexpr unsigned int mmDCP4_GRPH_Y_START__SI = 0x460C; +constexpr unsigned int mmDCP4_OVLSCL_EDGE_PIXEL_CNTL__SI = 0x462C; +constexpr unsigned int mmDCP4_OVL_CONTROL1__SI = 0x461D; +constexpr unsigned int mmDCP4_OVL_CONTROL2__SI = 0x461E; +constexpr unsigned int mmDCP4_OVL_DFQ_CONTROL__SI = 0x4629; +constexpr unsigned int mmDCP4_OVL_DFQ_STATUS__SI = 0x462A; +constexpr unsigned int mmDCP4_OVL_ENABLE__SI = 0x461C; +constexpr unsigned int mmDCP4_OVL_END__SI = 0x4626; +constexpr unsigned int mmDCP4_OVL_PITCH__SI = 0x4621; +constexpr unsigned int mmDCP4_OVL_START__SI = 0x4625; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x462B; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS_HIGH__SI = 0x4622; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS_INUSE__SI = 0x4628; +constexpr unsigned int mmDCP4_OVL_SURFACE_OFFSET_X__SI = 0x4623; +constexpr unsigned int mmDCP4_OVL_SURFACE_OFFSET_Y__SI = 0x4624; +constexpr unsigned int mmDCP4_OVL_SWAP_CNTL__SI = 0x461F; +constexpr unsigned int mmDCP4_OVL_UPDATE__SI = 0x4627; +constexpr unsigned int mmDCP5_CUR_COLOR1__SI = 0x496C; +constexpr unsigned int mmDCP5_CUR_COLOR2__SI = 0x496D; +constexpr unsigned int mmDCP5_CUR_CONTROL__SI = 0x4966; +constexpr unsigned int mmDCP5_CUR_HOT_SPOT__SI = 0x496B; +constexpr unsigned int mmDCP5_CUR_POSITION__SI = 0x496A; +constexpr unsigned int mmDCP5_CUR_SIZE__SI = 0x4968; +constexpr unsigned int mmDCP5_CUR_SURFACE_ADDRESS_HIGH__SI = 0x4969; +constexpr unsigned int mmDCP5_CUR_SURFACE_ADDRESS__SI = 0x4967; +constexpr unsigned int mmDCP5_CUR_UPDATE__SI = 0x496E; +constexpr unsigned int mmDCP5_DCP_CRC_CONTROL__SI = 0x4987; +constexpr unsigned int mmDCP5_DCP_CRC_CURRENT__SI = 0x4989; +constexpr unsigned int mmDCP5_DCP_CRC_LAST__SI = 0x498B; +constexpr unsigned int mmDCP5_DCP_CRC_MASK__SI = 0x4988; +constexpr unsigned int mmDCP5_DCP_DEBUG__SI = 0x498D; +constexpr unsigned int mmDCP5_DCP_LB_DATA_GAP_BETWEEN_CHUNK__SI = 0x4991; +constexpr unsigned int mmDCP5_DCP_TEST_DEBUG_DATA__SI = 0x4996; +constexpr unsigned int mmDCP5_DCP_TEST_DEBUG_INDEX__SI = 0x4995; +constexpr unsigned int mmDCP5_DC_LUT_30_COLOR__SI = 0x497C; +constexpr unsigned int mmDCP5_DC_LUT_AUTOFILL__SI = 0x497F; +constexpr unsigned int mmDCP5_DC_LUT_BLACK_OFFSET_BLUE__SI = 0x4981; +constexpr unsigned int mmDCP5_DC_LUT_BLACK_OFFSET_GREEN__SI = 0x4982; +constexpr unsigned int mmDCP5_DC_LUT_BLACK_OFFSET_RED__SI = 0x4983; +constexpr unsigned int mmDCP5_DC_LUT_CONTROL__SI = 0x4980; +constexpr unsigned int mmDCP5_DC_LUT_PWL_DATA__SI = 0x497B; +constexpr unsigned int mmDCP5_DC_LUT_RW_INDEX__SI = 0x4979; +constexpr unsigned int mmDCP5_DC_LUT_RW_MODE__SI = 0x4978; +constexpr unsigned int mmDCP5_DC_LUT_SEQ_COLOR__SI = 0x497A; +constexpr unsigned int mmDCP5_DC_LUT_WHITE_OFFSET_BLUE__SI = 0x4984; +constexpr unsigned int mmDCP5_DC_LUT_WHITE_OFFSET_GREEN__SI = 0x4985; +constexpr unsigned int mmDCP5_DC_LUT_WHITE_OFFSET_RED__SI = 0x4986; +constexpr unsigned int mmDCP5_DC_LUT_WRITE_EN_MASK__SI = 0x497E; +constexpr unsigned int mmDCP5_GRPH_COMPRESS_PITCH__SI = 0x491A; +constexpr unsigned int mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI = 0x491B; +constexpr unsigned int mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS__SI = 0x4919; +constexpr unsigned int mmDCP5_GRPH_DFQ_CONTROL__SI = 0x4914; +constexpr unsigned int mmDCP5_GRPH_DFQ_STATUS__SI = 0x4915; +constexpr unsigned int mmDCP5_GRPH_ENABLE__SI = 0x4900; +constexpr unsigned int mmDCP5_GRPH_INTERRUPT_CONTROL__SI = 0x4917; +constexpr unsigned int mmDCP5_GRPH_INTERRUPT_STATUS__SI = 0x4916; +constexpr unsigned int mmDCP5_GRPH_LUT_10BIT_BYPASS__SI = 0x4902; +constexpr unsigned int mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SI = 0x4907; +constexpr unsigned int mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI = 0x4908; +constexpr unsigned int mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS__SI = 0x4905; +constexpr unsigned int mmDCP5_GRPH_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x4918; +constexpr unsigned int mmDCP5_GRPH_SURFACE_ADDRESS_INUSE__SI = 0x4913; +constexpr unsigned int mmDCP5_GRPH_SURFACE_OFFSET_X__SI = 0x4909; +constexpr unsigned int mmDCP5_GRPH_SURFACE_OFFSET_Y__SI = 0x490A; +constexpr unsigned int mmDCP5_GRPH_SWAP_CNTL__SI = 0x4903; +constexpr unsigned int mmDCP5_GRPH_X_END__SI = 0x490D; +constexpr unsigned int mmDCP5_GRPH_X_START__SI = 0x490B; +constexpr unsigned int mmDCP5_GRPH_Y_END__SI = 0x490E; +constexpr unsigned int mmDCP5_GRPH_Y_START__SI = 0x490C; +constexpr unsigned int mmDCP5_OVLSCL_EDGE_PIXEL_CNTL__SI = 0x492C; +constexpr unsigned int mmDCP5_OVL_CONTROL1__SI = 0x491D; +constexpr unsigned int mmDCP5_OVL_CONTROL2__SI = 0x491E; +constexpr unsigned int mmDCP5_OVL_DFQ_CONTROL__SI = 0x4929; +constexpr unsigned int mmDCP5_OVL_DFQ_STATUS__SI = 0x492A; +constexpr unsigned int mmDCP5_OVL_ENABLE__SI = 0x491C; +constexpr unsigned int mmDCP5_OVL_END__SI = 0x4926; +constexpr unsigned int mmDCP5_OVL_PITCH__SI = 0x4921; +constexpr unsigned int mmDCP5_OVL_START__SI = 0x4925; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS_HIGH_INUSE__SI = 0x492B; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS_HIGH__SI = 0x4922; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS_INUSE__SI = 0x4928; +constexpr unsigned int mmDCP5_OVL_SURFACE_OFFSET_X__SI = 0x4923; +constexpr unsigned int mmDCP5_OVL_SURFACE_OFFSET_Y__SI = 0x4924; +constexpr unsigned int mmDCP5_OVL_SWAP_CNTL__SI = 0x491F; +constexpr unsigned int mmDCP5_OVL_UPDATE__SI = 0x4927; +constexpr unsigned int mmDCP_CRC_CONTROL__SI__VI = 0x1A87; +constexpr unsigned int mmDCP_CRC_CURRENT__SI__VI = 0x1A89; +constexpr unsigned int mmDCP_CRC_LAST__SI__VI = 0x1A8B; +constexpr unsigned int mmDCP_CRC_MASK__SI__VI = 0x1A88; +constexpr unsigned int mmDCP_DEBUG__SI__VI = 0x1A8D; +constexpr unsigned int mmDCP_LB_DATA_GAP_BETWEEN_CHUNK__SI__VI = 0x1A91; +constexpr unsigned int mmDCP_TEST_DEBUG_DATA__SI__VI = 0x1A96; +constexpr unsigned int mmDCP_TEST_DEBUG_INDEX__SI__VI = 0x1A95; +constexpr unsigned int mmDC_ABM1_ACE_CNTL_MISC__SI__VI = 0x1641; +constexpr unsigned int mmDC_ABM1_ACE_OFFSET_SLOPE_0__SI__VI = 0x163A; +constexpr unsigned int mmDC_ABM1_ACE_OFFSET_SLOPE_1__SI__VI = 0x163B; +constexpr unsigned int mmDC_ABM1_ACE_OFFSET_SLOPE_2__SI__VI = 0x163C; +constexpr unsigned int mmDC_ABM1_ACE_OFFSET_SLOPE_3__SI__VI = 0x163D; +constexpr unsigned int mmDC_ABM1_ACE_OFFSET_SLOPE_4__SI__VI = 0x163E; +constexpr unsigned int mmDC_ABM1_ACE_THRES_12__SI__VI = 0x163F; +constexpr unsigned int mmDC_ABM1_ACE_THRES_34__SI__VI = 0x1640; +constexpr unsigned int mmDC_ABM1_BL_MASTER_LOCK__SI__VI = 0x169C; +constexpr unsigned int mmDC_ABM1_CNTL__SI__VI = 0x1638; +constexpr unsigned int mmDC_ABM1_DEBUG_MISC__SI__VI = 0x1649; +constexpr unsigned int mmDC_ABM1_HGLS_REG_READ_PROGRESS__SI__VI = 0x164A; +constexpr unsigned int mmDC_ABM1_HG_BIN_17_24_SHIFT_INDEX__SI__VI = 0x1659; +constexpr unsigned int mmDC_ABM1_HG_BIN_1_32_SHIFT_FLAG__SI__VI = 0x1656; +constexpr unsigned int mmDC_ABM1_HG_BIN_1_8_SHIFT_INDEX__SI__VI = 0x1657; +constexpr unsigned int mmDC_ABM1_HG_BIN_25_32_SHIFT_INDEX__SI__VI = 0x165A; +constexpr unsigned int mmDC_ABM1_HG_BIN_9_16_SHIFT_INDEX__SI__VI = 0x1658; +constexpr unsigned int mmDC_ABM1_HG_MISC_CTRL__SI__VI = 0x164B; +constexpr unsigned int mmDC_ABM1_HG_RESULT_10__SI__VI = 0x1664; +constexpr unsigned int mmDC_ABM1_HG_RESULT_11__SI__VI = 0x1665; +constexpr unsigned int mmDC_ABM1_HG_RESULT_12__SI__VI = 0x1666; +constexpr unsigned int mmDC_ABM1_HG_RESULT_13__SI__VI = 0x1667; +constexpr unsigned int mmDC_ABM1_HG_RESULT_14__SI__VI = 0x1668; +constexpr unsigned int mmDC_ABM1_HG_RESULT_15__SI__VI = 0x1669; +constexpr unsigned int mmDC_ABM1_HG_RESULT_16__SI__VI = 0x166A; +constexpr unsigned int mmDC_ABM1_HG_RESULT_17__SI__VI = 0x166B; +constexpr unsigned int mmDC_ABM1_HG_RESULT_18__SI__VI = 0x166C; +constexpr unsigned int mmDC_ABM1_HG_RESULT_19__SI__VI = 0x166D; +constexpr unsigned int mmDC_ABM1_HG_RESULT_1__SI__VI = 0x165B; +constexpr unsigned int mmDC_ABM1_HG_RESULT_20__SI__VI = 0x166E; +constexpr unsigned int mmDC_ABM1_HG_RESULT_21__SI__VI = 0x166F; +constexpr unsigned int mmDC_ABM1_HG_RESULT_22__SI__VI = 0x1670; +constexpr unsigned int mmDC_ABM1_HG_RESULT_23__SI__VI = 0x1671; +constexpr unsigned int mmDC_ABM1_HG_RESULT_24__SI__VI = 0x1672; +constexpr unsigned int mmDC_ABM1_HG_RESULT_2__SI__VI = 0x165C; +constexpr unsigned int mmDC_ABM1_HG_RESULT_3__SI__VI = 0x165D; +constexpr unsigned int mmDC_ABM1_HG_RESULT_4__SI__VI = 0x165E; +constexpr unsigned int mmDC_ABM1_HG_RESULT_5__SI__VI = 0x165F; +constexpr unsigned int mmDC_ABM1_HG_RESULT_6__SI__VI = 0x1660; +constexpr unsigned int mmDC_ABM1_HG_RESULT_7__SI__VI = 0x1661; +constexpr unsigned int mmDC_ABM1_HG_RESULT_8__SI__VI = 0x1662; +constexpr unsigned int mmDC_ABM1_HG_RESULT_9__SI__VI = 0x1663; +constexpr unsigned int mmDC_ABM1_HG_SAMPLE_RATE__SI__VI = 0x1654; +constexpr unsigned int mmDC_ABM1_IPCSC_COEFF_SEL__SI__VI = 0x1639; +constexpr unsigned int mmDC_ABM1_LS_FILTERED_MIN_MAX_LUMA__SI__VI = 0x164E; +constexpr unsigned int mmDC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__SI__VI = 0x1653; +constexpr unsigned int mmDC_ABM1_LS_MIN_MAX_LUMA__SI__VI = 0x164D; +constexpr unsigned int mmDC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__SI__VI = 0x1651; +constexpr unsigned int mmDC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__SI__VI = 0x1652; +constexpr unsigned int mmDC_ABM1_LS_OVR_SCAN_BIN__SI__VI = 0x1650; +constexpr unsigned int mmDC_ABM1_LS_PIXEL_COUNT__SI__VI = 0x164F; +constexpr unsigned int mmDC_ABM1_LS_SAMPLE_RATE__SI__VI = 0x1655; +constexpr unsigned int mmDC_ABM1_LS_SUM_OF_LUMA__SI__VI = 0x164C; +constexpr unsigned int mmDC_DMCU_SCRATCH__SI__VI = 0x1618; +constexpr unsigned int mmDC_GENERICA__SI = 0x1900; +constexpr unsigned int mmDC_GENERICB__SI = 0x1901; +constexpr unsigned int mmDC_GPIO_DDC1_A__SI = 0x190D; +constexpr unsigned int mmDC_GPIO_DDC1_EN__SI = 0x190E; +constexpr unsigned int mmDC_GPIO_DDC1_MASK__SI = 0x190C; +constexpr unsigned int mmDC_GPIO_DDC1_Y__SI = 0x190F; +constexpr unsigned int mmDC_GPIO_DDC2_A__SI = 0x1911; +constexpr unsigned int mmDC_GPIO_DDC2_EN__SI = 0x1912; +constexpr unsigned int mmDC_GPIO_DDC2_MASK__SI = 0x1910; +constexpr unsigned int mmDC_GPIO_DDC2_Y__SI = 0x1913; +constexpr unsigned int mmDC_GPIO_DDC3_A__SI = 0x1915; +constexpr unsigned int mmDC_GPIO_DDC3_EN__SI = 0x1916; +constexpr unsigned int mmDC_GPIO_DDC3_MASK__SI = 0x1914; +constexpr unsigned int mmDC_GPIO_DDC3_Y__SI = 0x1917; +constexpr unsigned int mmDC_GPIO_DDC4_A__SI = 0x1919; +constexpr unsigned int mmDC_GPIO_DDC4_EN__SI = 0x191A; +constexpr unsigned int mmDC_GPIO_DDC4_MASK__SI = 0x1918; +constexpr unsigned int mmDC_GPIO_DDC4_Y__SI = 0x191B; +constexpr unsigned int mmDC_GPIO_DDC5_A__SI = 0x191D; +constexpr unsigned int mmDC_GPIO_DDC5_EN__SI = 0x191E; +constexpr unsigned int mmDC_GPIO_DDC5_MASK__SI = 0x191C; +constexpr unsigned int mmDC_GPIO_DDC5_Y__SI = 0x191F; +constexpr unsigned int mmDC_GPIO_DDC6_A__SI = 0x1921; +constexpr unsigned int mmDC_GPIO_DDC6_EN__SI = 0x1922; +constexpr unsigned int mmDC_GPIO_DDC6_MASK__SI = 0x1920; +constexpr unsigned int mmDC_GPIO_DDC6_Y__SI = 0x1923; +constexpr unsigned int mmDC_GPIO_DEBUG__SI = 0x1946; +constexpr unsigned int mmDC_GPIO_DVODATA_A__SI = 0x1909; +constexpr unsigned int mmDC_GPIO_DVODATA_EN__SI = 0x190A; +constexpr unsigned int mmDC_GPIO_DVODATA_MASK__SI = 0x1908; +constexpr unsigned int mmDC_GPIO_DVODATA_Y__SI = 0x190B; +constexpr unsigned int mmDC_GPIO_GENERIC_A__SI = 0x1905; +constexpr unsigned int mmDC_GPIO_GENERIC_EN__SI = 0x1906; +constexpr unsigned int mmDC_GPIO_GENERIC_MASK__SI = 0x1904; +constexpr unsigned int mmDC_GPIO_GENERIC_Y__SI = 0x1907; +constexpr unsigned int mmDC_GPIO_HPD_A__SI = 0x192D; +constexpr unsigned int mmDC_GPIO_HPD_EN__SI = 0x192E; +constexpr unsigned int mmDC_GPIO_HPD_MASK__SI = 0x192C; +constexpr unsigned int mmDC_GPIO_HPD_Y__SI = 0x192F; +constexpr unsigned int mmDC_GPIO_PAD_STRENGTH_1__SI = 0x1944; +constexpr unsigned int mmDC_GPIO_PAD_STRENGTH_2__SI = 0x1945; +constexpr unsigned int mmDC_GPIO_PWRSEQ_A__SI = 0x1941; +constexpr unsigned int mmDC_GPIO_PWRSEQ_EN__SI = 0x1942; +constexpr unsigned int mmDC_GPIO_PWRSEQ_MASK__SI = 0x1940; +constexpr unsigned int mmDC_GPIO_PWRSEQ_Y__SI = 0x1943; +constexpr unsigned int mmDC_GPIO_SYNCA_A__SI = 0x1925; +constexpr unsigned int mmDC_GPIO_SYNCA_EN__SI = 0x1926; +constexpr unsigned int mmDC_GPIO_SYNCA_MASK__SI = 0x1924; +constexpr unsigned int mmDC_GPIO_SYNCA_Y__SI = 0x1927; +constexpr unsigned int mmDC_GPU_TIMER_READ_CNTL__SI = 0x1972; +constexpr unsigned int mmDC_GPU_TIMER_READ__SI = 0x1971; +constexpr unsigned int mmDC_GPU_TIMER_START_POSITION__SI = 0x1970; +constexpr unsigned int mmDC_HPD1_CONTROL__SI = 0x1809; +constexpr unsigned int mmDC_HPD1_INT_CONTROL__SI = 0x1808; +constexpr unsigned int mmDC_HPD1_INT_STATUS__SI = 0x1807; +constexpr unsigned int mmDC_HPD2_CONTROL__SI = 0x180C; +constexpr unsigned int mmDC_HPD2_INT_CONTROL__SI = 0x180B; +constexpr unsigned int mmDC_HPD2_INT_STATUS__SI = 0x180A; +constexpr unsigned int mmDC_HPD3_CONTROL__SI = 0x180F; +constexpr unsigned int mmDC_HPD3_INT_CONTROL__SI = 0x180E; +constexpr unsigned int mmDC_HPD3_INT_STATUS__SI = 0x180D; +constexpr unsigned int mmDC_HPD4_CONTROL__SI = 0x1812; +constexpr unsigned int mmDC_HPD4_INT_CONTROL__SI = 0x1811; +constexpr unsigned int mmDC_HPD4_INT_STATUS__SI = 0x1810; +constexpr unsigned int mmDC_HPD5_CONTROL__SI = 0x1815; +constexpr unsigned int mmDC_HPD5_INT_CONTROL__SI = 0x1814; +constexpr unsigned int mmDC_HPD5_INT_STATUS__SI = 0x1813; +constexpr unsigned int mmDC_HPD6_CONTROL__SI = 0x1818; +constexpr unsigned int mmDC_HPD6_INT_CONTROL__SI = 0x1817; +constexpr unsigned int mmDC_HPD6_INT_STATUS__SI = 0x1816; +constexpr unsigned int mmDC_I2C_ARBITRATION__SI = 0x181A; +constexpr unsigned int mmDC_I2C_CONTROL__SI = 0x1819; +constexpr unsigned int mmDC_I2C_DATA__SI = 0x1833; +constexpr unsigned int mmDC_I2C_DDC1_HW_STATUS__SI = 0x181D; +constexpr unsigned int mmDC_I2C_DDC1_SETUP__SI = 0x1824; +constexpr unsigned int mmDC_I2C_DDC1_SPEED__SI = 0x1823; +constexpr unsigned int mmDC_I2C_DDC2_HW_STATUS__SI = 0x181E; +constexpr unsigned int mmDC_I2C_DDC2_SETUP__SI = 0x1826; +constexpr unsigned int mmDC_I2C_DDC2_SPEED__SI = 0x1825; +constexpr unsigned int mmDC_I2C_DDC3_HW_STATUS__SI = 0x181F; +constexpr unsigned int mmDC_I2C_DDC3_SETUP__SI = 0x1828; +constexpr unsigned int mmDC_I2C_DDC3_SPEED__SI = 0x1827; +constexpr unsigned int mmDC_I2C_DDC4_HW_STATUS__SI = 0x1820; +constexpr unsigned int mmDC_I2C_DDC4_SETUP__SI = 0x182A; +constexpr unsigned int mmDC_I2C_DDC4_SPEED__SI = 0x1829; +constexpr unsigned int mmDC_I2C_DDC5_HW_STATUS__SI = 0x1821; +constexpr unsigned int mmDC_I2C_DDC5_SETUP__SI = 0x182C; +constexpr unsigned int mmDC_I2C_DDC5_SPEED__SI = 0x182B; +constexpr unsigned int mmDC_I2C_DDC6_HW_STATUS__SI = 0x1822; +constexpr unsigned int mmDC_I2C_DDC6_SETUP__SI = 0x182E; +constexpr unsigned int mmDC_I2C_DDC6_SPEED__SI = 0x182D; +constexpr unsigned int mmDC_I2C_INTERRUPT_CONTROL__SI = 0x181B; +constexpr unsigned int mmDC_I2C_SW_STATUS__SI = 0x181C; +constexpr unsigned int mmDC_I2C_TRANSACTION0__SI = 0x182F; +constexpr unsigned int mmDC_I2C_TRANSACTION1__SI = 0x1830; +constexpr unsigned int mmDC_I2C_TRANSACTION2__SI = 0x1831; +constexpr unsigned int mmDC_I2C_TRANSACTION3__SI = 0x1832; +constexpr unsigned int mmDC_LUT_30_COLOR__SI__VI = 0x1A7C; +constexpr unsigned int mmDC_LUT_AUTOFILL__SI__VI = 0x1A7F; +constexpr unsigned int mmDC_LUT_BLACK_OFFSET_BLUE__SI__VI = 0x1A81; +constexpr unsigned int mmDC_LUT_BLACK_OFFSET_GREEN__SI__VI = 0x1A82; +constexpr unsigned int mmDC_LUT_BLACK_OFFSET_RED__SI__VI = 0x1A83; +constexpr unsigned int mmDC_LUT_CONTROL__SI__VI = 0x1A80; +constexpr unsigned int mmDC_LUT_PWL_DATA__SI__VI = 0x1A7B; +constexpr unsigned int mmDC_LUT_RW_INDEX__SI__VI = 0x1A79; +constexpr unsigned int mmDC_LUT_RW_MODE__SI__VI = 0x1A78; +constexpr unsigned int mmDC_LUT_SEQ_COLOR__SI__VI = 0x1A7A; +constexpr unsigned int mmDC_LUT_WHITE_OFFSET_BLUE__SI__VI = 0x1A84; +constexpr unsigned int mmDC_LUT_WHITE_OFFSET_GREEN__SI__VI = 0x1A85; +constexpr unsigned int mmDC_LUT_WHITE_OFFSET_RED__SI__VI = 0x1A86; +constexpr unsigned int mmDC_LUT_WRITE_EN_MASK__SI__VI = 0x1A7E; +constexpr unsigned int mmDC_MVP_LB_CONTROL__SI = 0x1ADB; +constexpr unsigned int mmDC_PAD_EXTERN_SIG__SI = 0x1902; +constexpr unsigned int mmDC_PINSTRAPS__SI = 0x1954; +constexpr unsigned int mmDC_REF_CLK_CNTL__SI = 0x1903; +constexpr unsigned int mmDC_TEST_DEBUG_DATA__SI = 0x186D; +constexpr unsigned int mmDC_TEST_DEBUG_INDEX__SI = 0x186C; +constexpr unsigned int mmDEBUG_DATA = 0x203D; +constexpr unsigned int mmDEBUG_INDEX = 0x203C; +constexpr unsigned int mmDENTIST_DISPCLK_CNTL__SI = 0x015F; +constexpr unsigned int mmDESKTOP_HEIGHT__SI = 0x1AC1; +constexpr unsigned int mmDIDT_IND_DATA__CI__VI = 0x3281; +constexpr unsigned int mmDIDT_IND_INDEX__CI__VI = 0x3280; +constexpr unsigned int mmDIG0_AFMT_60958_0__SI = 0x1C41; +constexpr unsigned int mmDIG0_AFMT_60958_1__SI = 0x1C42; +constexpr unsigned int mmDIG0_AFMT_60958_2__SI = 0x1C48; +constexpr unsigned int mmDIG0_AFMT_AUDIO_CRC_CONTROL__SI = 0x1C43; +constexpr unsigned int mmDIG0_AFMT_AUDIO_CRC_RESULT__SI = 0x1C49; +constexpr unsigned int mmDIG0_AFMT_AUDIO_INFO0__SI = 0x1C3F; +constexpr unsigned int mmDIG0_AFMT_AUDIO_INFO1__SI = 0x1C40; +constexpr unsigned int mmDIG0_AFMT_AUDIO_PACKET_CONTROL2__SI = 0x1C17; +constexpr unsigned int mmDIG0_AFMT_AUDIO_PACKET_CONTROL__SI = 0x1C4B; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO0__SI = 0x1C21; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO1__SI = 0x1C22; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO2__SI = 0x1C23; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO3__SI = 0x1C24; +constexpr unsigned int mmDIG0_AFMT_INFOFRAME_CONTROL0__SI = 0x1C4D; +constexpr unsigned int mmDIG0_AFMT_ISRC1_0__SI = 0x1C18; +constexpr unsigned int mmDIG0_AFMT_ISRC1_1__SI = 0x1C19; +constexpr unsigned int mmDIG0_AFMT_ISRC1_2__SI = 0x1C1A; +constexpr unsigned int mmDIG0_AFMT_ISRC1_3__SI = 0x1C1B; +constexpr unsigned int mmDIG0_AFMT_ISRC1_4__SI = 0x1C1C; +constexpr unsigned int mmDIG0_AFMT_ISRC2_0__SI = 0x1C1D; +constexpr unsigned int mmDIG0_AFMT_ISRC2_1__SI = 0x1C1E; +constexpr unsigned int mmDIG0_AFMT_ISRC2_2__SI = 0x1C1F; +constexpr unsigned int mmDIG0_AFMT_ISRC2_3__SI = 0x1C20; +constexpr unsigned int mmDIG0_AFMT_MPEG_INFO0__SI = 0x1C25; +constexpr unsigned int mmDIG0_AFMT_MPEG_INFO1__SI = 0x1C26; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL0__SI = 0x1C44; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL1__SI = 0x1C45; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL2__SI = 0x1C46; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL3__SI = 0x1C47; +constexpr unsigned int mmDIG0_AFMT_STATUS__SI = 0x1C4A; +constexpr unsigned int mmDIG0_AFMT_VBI_PACKET_CONTROL__SI = 0x1C4C; +constexpr unsigned int mmDIG0_DIG_CLOCK_PATTERN__SI = 0x1C03; +constexpr unsigned int mmDIG0_DIG_OUTPUT_CRC_CNTL__SI = 0x1C01; +constexpr unsigned int mmDIG0_DIG_OUTPUT_CRC_RESULT__SI = 0x1C02; +constexpr unsigned int mmDIG0_DIG_RANDOM_PATTERN_SEED__SI = 0x1C05; +constexpr unsigned int mmDIG0_DIG_TEST_PATTERN__SI = 0x1C04; +constexpr unsigned int mmDIG0_HDMI_ACR_32_0__SI = 0x1C37; +constexpr unsigned int mmDIG0_HDMI_ACR_32_1__SI = 0x1C38; +constexpr unsigned int mmDIG0_HDMI_ACR_44_0__SI = 0x1C39; +constexpr unsigned int mmDIG0_HDMI_ACR_44_1__SI = 0x1C3A; +constexpr unsigned int mmDIG0_HDMI_ACR_48_0__SI = 0x1C3B; +constexpr unsigned int mmDIG0_HDMI_ACR_48_1__SI = 0x1C3C; +constexpr unsigned int mmDIG0_HDMI_ACR_PACKET_CONTROL__SI = 0x1C0F; +constexpr unsigned int mmDIG0_HDMI_ACR_STATUS_0__SI = 0x1C3D; +constexpr unsigned int mmDIG0_HDMI_ACR_STATUS_1__SI = 0x1C3E; +constexpr unsigned int mmDIG0_HDMI_AUDIO_PACKET_CONTROL__SI = 0x1C0E; +constexpr unsigned int mmDIG0_HDMI_CONTROL__SI = 0x1C0C; +constexpr unsigned int mmDIG0_HDMI_GC__SI = 0x1C16; +constexpr unsigned int mmDIG0_HDMI_GENERIC_PACKET_CONTROL__SI = 0x1C13; +constexpr unsigned int mmDIG0_HDMI_INFOFRAME_CONTROL0__SI = 0x1C11; +constexpr unsigned int mmDIG0_HDMI_INFOFRAME_CONTROL1__SI = 0x1C12; +constexpr unsigned int mmDIG0_HDMI_STATUS__SI = 0x1C0D; +constexpr unsigned int mmDIG0_HDMI_VBI_PACKET_CONTROL__SI = 0x1C10; +constexpr unsigned int mmDIG0_LVDS_DATA_CNTL__SI = 0x1C8C; +constexpr unsigned int mmDIG0_TMDS_CNTL__SI = 0x1C7C; +constexpr unsigned int mmDIG0_TMDS_CONTROL0_FEEDBACK__SI = 0x1C7E; +constexpr unsigned int mmDIG0_TMDS_CONTROL_CHAR__SI = 0x1C7D; +constexpr unsigned int mmDIG0_TMDS_CTL0_1_GEN_CNTL__SI = 0x1C86; +constexpr unsigned int mmDIG0_TMDS_CTL2_3_GEN_CNTL__SI = 0x1C87; +constexpr unsigned int mmDIG0_TMDS_CTL_BITS__SI = 0x1C83; +constexpr unsigned int mmDIG0_TMDS_DCBALANCER_CONTROL__SI = 0x1C84; +constexpr unsigned int mmDIG0_TMDS_DEBUG__SI = 0x1C82; +constexpr unsigned int mmDIG0_TMDS_STEREOSYNC_CTL_SEL__SI = 0x1C7F; +constexpr unsigned int mmDIG0_TMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x1C80; +constexpr unsigned int mmDIG0_TMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x1C81; +constexpr unsigned int mmDIG1_AFMT_60958_0__SI = 0x1F41; +constexpr unsigned int mmDIG1_AFMT_60958_1__SI = 0x1F42; +constexpr unsigned int mmDIG1_AFMT_60958_2__SI = 0x1F48; +constexpr unsigned int mmDIG1_AFMT_AUDIO_CRC_CONTROL__SI = 0x1F43; +constexpr unsigned int mmDIG1_AFMT_AUDIO_CRC_RESULT__SI = 0x1F49; +constexpr unsigned int mmDIG1_AFMT_AUDIO_INFO0__SI = 0x1F3F; +constexpr unsigned int mmDIG1_AFMT_AUDIO_INFO1__SI = 0x1F40; +constexpr unsigned int mmDIG1_AFMT_AUDIO_PACKET_CONTROL2__SI = 0x1F17; +constexpr unsigned int mmDIG1_AFMT_AUDIO_PACKET_CONTROL__SI = 0x1F4B; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO0__SI = 0x1F21; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO1__SI = 0x1F22; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO2__SI = 0x1F23; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO3__SI = 0x1F24; +constexpr unsigned int mmDIG1_AFMT_INFOFRAME_CONTROL0__SI = 0x1F4D; +constexpr unsigned int mmDIG1_AFMT_ISRC1_0__SI = 0x1F18; +constexpr unsigned int mmDIG1_AFMT_ISRC1_1__SI = 0x1F19; +constexpr unsigned int mmDIG1_AFMT_ISRC1_2__SI = 0x1F1A; +constexpr unsigned int mmDIG1_AFMT_ISRC1_3__SI = 0x1F1B; +constexpr unsigned int mmDIG1_AFMT_ISRC1_4__SI = 0x1F1C; +constexpr unsigned int mmDIG1_AFMT_ISRC2_0__SI = 0x1F1D; +constexpr unsigned int mmDIG1_AFMT_ISRC2_1__SI = 0x1F1E; +constexpr unsigned int mmDIG1_AFMT_ISRC2_2__SI = 0x1F1F; +constexpr unsigned int mmDIG1_AFMT_ISRC2_3__SI = 0x1F20; +constexpr unsigned int mmDIG1_AFMT_MPEG_INFO0__SI = 0x1F25; +constexpr unsigned int mmDIG1_AFMT_MPEG_INFO1__SI = 0x1F26; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL0__SI = 0x1F44; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL1__SI = 0x1F45; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL2__SI = 0x1F46; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL3__SI = 0x1F47; +constexpr unsigned int mmDIG1_AFMT_STATUS__SI = 0x1F4A; +constexpr unsigned int mmDIG1_AFMT_VBI_PACKET_CONTROL__SI = 0x1F4C; +constexpr unsigned int mmDIG1_DIG_CLOCK_PATTERN__SI = 0x1F03; +constexpr unsigned int mmDIG1_DIG_OUTPUT_CRC_CNTL__SI = 0x1F01; +constexpr unsigned int mmDIG1_DIG_OUTPUT_CRC_RESULT__SI = 0x1F02; +constexpr unsigned int mmDIG1_DIG_RANDOM_PATTERN_SEED__SI = 0x1F05; +constexpr unsigned int mmDIG1_DIG_TEST_PATTERN__SI = 0x1F04; +constexpr unsigned int mmDIG1_HDMI_ACR_32_0__SI = 0x1F37; +constexpr unsigned int mmDIG1_HDMI_ACR_32_1__SI = 0x1F38; +constexpr unsigned int mmDIG1_HDMI_ACR_44_0__SI = 0x1F39; +constexpr unsigned int mmDIG1_HDMI_ACR_44_1__SI = 0x1F3A; +constexpr unsigned int mmDIG1_HDMI_ACR_48_0__SI = 0x1F3B; +constexpr unsigned int mmDIG1_HDMI_ACR_48_1__SI = 0x1F3C; +constexpr unsigned int mmDIG1_HDMI_ACR_PACKET_CONTROL__SI = 0x1F0F; +constexpr unsigned int mmDIG1_HDMI_ACR_STATUS_0__SI = 0x1F3D; +constexpr unsigned int mmDIG1_HDMI_ACR_STATUS_1__SI = 0x1F3E; +constexpr unsigned int mmDIG1_HDMI_AUDIO_PACKET_CONTROL__SI = 0x1F0E; +constexpr unsigned int mmDIG1_HDMI_CONTROL__SI = 0x1F0C; +constexpr unsigned int mmDIG1_HDMI_GC__SI = 0x1F16; +constexpr unsigned int mmDIG1_HDMI_GENERIC_PACKET_CONTROL__SI = 0x1F13; +constexpr unsigned int mmDIG1_HDMI_INFOFRAME_CONTROL0__SI = 0x1F11; +constexpr unsigned int mmDIG1_HDMI_INFOFRAME_CONTROL1__SI = 0x1F12; +constexpr unsigned int mmDIG1_HDMI_STATUS__SI = 0x1F0D; +constexpr unsigned int mmDIG1_HDMI_VBI_PACKET_CONTROL__SI = 0x1F10; +constexpr unsigned int mmDIG1_LVDS_DATA_CNTL__SI = 0x1F8C; +constexpr unsigned int mmDIG1_TMDS_CNTL__SI = 0x1F7C; +constexpr unsigned int mmDIG1_TMDS_CONTROL0_FEEDBACK__SI = 0x1F7E; +constexpr unsigned int mmDIG1_TMDS_CONTROL_CHAR__SI = 0x1F7D; +constexpr unsigned int mmDIG1_TMDS_CTL0_1_GEN_CNTL__SI = 0x1F86; +constexpr unsigned int mmDIG1_TMDS_CTL2_3_GEN_CNTL__SI = 0x1F87; +constexpr unsigned int mmDIG1_TMDS_CTL_BITS__SI = 0x1F83; +constexpr unsigned int mmDIG1_TMDS_DCBALANCER_CONTROL__SI = 0x1F84; +constexpr unsigned int mmDIG1_TMDS_DEBUG__SI = 0x1F82; +constexpr unsigned int mmDIG1_TMDS_STEREOSYNC_CTL_SEL__SI = 0x1F7F; +constexpr unsigned int mmDIG1_TMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x1F80; +constexpr unsigned int mmDIG1_TMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x1F81; +constexpr unsigned int mmDIG2_AFMT_60958_0__SI = 0x4241; +constexpr unsigned int mmDIG2_AFMT_60958_1__SI = 0x4242; +constexpr unsigned int mmDIG2_AFMT_60958_2__SI = 0x4248; +constexpr unsigned int mmDIG2_AFMT_AUDIO_CRC_CONTROL__SI = 0x4243; +constexpr unsigned int mmDIG2_AFMT_AUDIO_CRC_RESULT__SI = 0x4249; +constexpr unsigned int mmDIG2_AFMT_AUDIO_INFO0__SI = 0x423F; +constexpr unsigned int mmDIG2_AFMT_AUDIO_INFO1__SI = 0x4240; +constexpr unsigned int mmDIG2_AFMT_AUDIO_PACKET_CONTROL2__SI = 0x4217; +constexpr unsigned int mmDIG2_AFMT_AUDIO_PACKET_CONTROL__SI = 0x424B; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO0__SI = 0x4221; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO1__SI = 0x4222; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO2__SI = 0x4223; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO3__SI = 0x4224; +constexpr unsigned int mmDIG2_AFMT_INFOFRAME_CONTROL0__SI = 0x424D; +constexpr unsigned int mmDIG2_AFMT_ISRC1_0__SI = 0x4218; +constexpr unsigned int mmDIG2_AFMT_ISRC1_1__SI = 0x4219; +constexpr unsigned int mmDIG2_AFMT_ISRC1_2__SI = 0x421A; +constexpr unsigned int mmDIG2_AFMT_ISRC1_3__SI = 0x421B; +constexpr unsigned int mmDIG2_AFMT_ISRC1_4__SI = 0x421C; +constexpr unsigned int mmDIG2_AFMT_ISRC2_0__SI = 0x421D; +constexpr unsigned int mmDIG2_AFMT_ISRC2_1__SI = 0x421E; +constexpr unsigned int mmDIG2_AFMT_ISRC2_2__SI = 0x421F; +constexpr unsigned int mmDIG2_AFMT_ISRC2_3__SI = 0x4220; +constexpr unsigned int mmDIG2_AFMT_MPEG_INFO0__SI = 0x4225; +constexpr unsigned int mmDIG2_AFMT_MPEG_INFO1__SI = 0x4226; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL0__SI = 0x4244; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL1__SI = 0x4245; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL2__SI = 0x4246; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL3__SI = 0x4247; +constexpr unsigned int mmDIG2_AFMT_STATUS__SI = 0x424A; +constexpr unsigned int mmDIG2_AFMT_VBI_PACKET_CONTROL__SI = 0x424C; +constexpr unsigned int mmDIG2_DIG_CLOCK_PATTERN__SI = 0x4203; +constexpr unsigned int mmDIG2_DIG_OUTPUT_CRC_CNTL__SI = 0x4201; +constexpr unsigned int mmDIG2_DIG_OUTPUT_CRC_RESULT__SI = 0x4202; +constexpr unsigned int mmDIG2_DIG_RANDOM_PATTERN_SEED__SI = 0x4205; +constexpr unsigned int mmDIG2_DIG_TEST_PATTERN__SI = 0x4204; +constexpr unsigned int mmDIG2_HDMI_ACR_32_0__SI = 0x4237; +constexpr unsigned int mmDIG2_HDMI_ACR_32_1__SI = 0x4238; +constexpr unsigned int mmDIG2_HDMI_ACR_44_0__SI = 0x4239; +constexpr unsigned int mmDIG2_HDMI_ACR_44_1__SI = 0x423A; +constexpr unsigned int mmDIG2_HDMI_ACR_48_0__SI = 0x423B; +constexpr unsigned int mmDIG2_HDMI_ACR_48_1__SI = 0x423C; +constexpr unsigned int mmDIG2_HDMI_ACR_PACKET_CONTROL__SI = 0x420F; +constexpr unsigned int mmDIG2_HDMI_ACR_STATUS_0__SI = 0x423D; +constexpr unsigned int mmDIG2_HDMI_ACR_STATUS_1__SI = 0x423E; +constexpr unsigned int mmDIG2_HDMI_AUDIO_PACKET_CONTROL__SI = 0x420E; +constexpr unsigned int mmDIG2_HDMI_CONTROL__SI = 0x420C; +constexpr unsigned int mmDIG2_HDMI_GC__SI = 0x4216; +constexpr unsigned int mmDIG2_HDMI_GENERIC_PACKET_CONTROL__SI = 0x4213; +constexpr unsigned int mmDIG2_HDMI_INFOFRAME_CONTROL0__SI = 0x4211; +constexpr unsigned int mmDIG2_HDMI_INFOFRAME_CONTROL1__SI = 0x4212; +constexpr unsigned int mmDIG2_HDMI_STATUS__SI = 0x420D; +constexpr unsigned int mmDIG2_HDMI_VBI_PACKET_CONTROL__SI = 0x4210; +constexpr unsigned int mmDIG2_LVDS_DATA_CNTL__SI = 0x428C; +constexpr unsigned int mmDIG2_TMDS_CNTL__SI = 0x427C; +constexpr unsigned int mmDIG2_TMDS_CONTROL0_FEEDBACK__SI = 0x427E; +constexpr unsigned int mmDIG2_TMDS_CONTROL_CHAR__SI = 0x427D; +constexpr unsigned int mmDIG2_TMDS_CTL0_1_GEN_CNTL__SI = 0x4286; +constexpr unsigned int mmDIG2_TMDS_CTL2_3_GEN_CNTL__SI = 0x4287; +constexpr unsigned int mmDIG2_TMDS_CTL_BITS__SI = 0x4283; +constexpr unsigned int mmDIG2_TMDS_DCBALANCER_CONTROL__SI = 0x4284; +constexpr unsigned int mmDIG2_TMDS_DEBUG__SI = 0x4282; +constexpr unsigned int mmDIG2_TMDS_STEREOSYNC_CTL_SEL__SI = 0x427F; +constexpr unsigned int mmDIG2_TMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x4280; +constexpr unsigned int mmDIG2_TMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x4281; +constexpr unsigned int mmDIG3_AFMT_60958_0__SI = 0x4541; +constexpr unsigned int mmDIG3_AFMT_60958_1__SI = 0x4542; +constexpr unsigned int mmDIG3_AFMT_60958_2__SI = 0x4548; +constexpr unsigned int mmDIG3_AFMT_AUDIO_CRC_CONTROL__SI = 0x4543; +constexpr unsigned int mmDIG3_AFMT_AUDIO_CRC_RESULT__SI = 0x4549; +constexpr unsigned int mmDIG3_AFMT_AUDIO_INFO0__SI = 0x453F; +constexpr unsigned int mmDIG3_AFMT_AUDIO_INFO1__SI = 0x4540; +constexpr unsigned int mmDIG3_AFMT_AUDIO_PACKET_CONTROL2__SI = 0x4517; +constexpr unsigned int mmDIG3_AFMT_AUDIO_PACKET_CONTROL__SI = 0x454B; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO0__SI = 0x4521; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO1__SI = 0x4522; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO2__SI = 0x4523; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO3__SI = 0x4524; +constexpr unsigned int mmDIG3_AFMT_INFOFRAME_CONTROL0__SI = 0x454D; +constexpr unsigned int mmDIG3_AFMT_ISRC1_0__SI = 0x4518; +constexpr unsigned int mmDIG3_AFMT_ISRC1_1__SI = 0x4519; +constexpr unsigned int mmDIG3_AFMT_ISRC1_2__SI = 0x451A; +constexpr unsigned int mmDIG3_AFMT_ISRC1_3__SI = 0x451B; +constexpr unsigned int mmDIG3_AFMT_ISRC1_4__SI = 0x451C; +constexpr unsigned int mmDIG3_AFMT_ISRC2_0__SI = 0x451D; +constexpr unsigned int mmDIG3_AFMT_ISRC2_1__SI = 0x451E; +constexpr unsigned int mmDIG3_AFMT_ISRC2_2__SI = 0x451F; +constexpr unsigned int mmDIG3_AFMT_ISRC2_3__SI = 0x4520; +constexpr unsigned int mmDIG3_AFMT_MPEG_INFO0__SI = 0x4525; +constexpr unsigned int mmDIG3_AFMT_MPEG_INFO1__SI = 0x4526; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL0__SI = 0x4544; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL1__SI = 0x4545; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL2__SI = 0x4546; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL3__SI = 0x4547; +constexpr unsigned int mmDIG3_AFMT_STATUS__SI = 0x454A; +constexpr unsigned int mmDIG3_AFMT_VBI_PACKET_CONTROL__SI = 0x454C; +constexpr unsigned int mmDIG3_DIG_CLOCK_PATTERN__SI = 0x4503; +constexpr unsigned int mmDIG3_DIG_OUTPUT_CRC_CNTL__SI = 0x4501; +constexpr unsigned int mmDIG3_DIG_OUTPUT_CRC_RESULT__SI = 0x4502; +constexpr unsigned int mmDIG3_DIG_RANDOM_PATTERN_SEED__SI = 0x4505; +constexpr unsigned int mmDIG3_DIG_TEST_PATTERN__SI = 0x4504; +constexpr unsigned int mmDIG3_HDMI_ACR_32_0__SI = 0x4537; +constexpr unsigned int mmDIG3_HDMI_ACR_32_1__SI = 0x4538; +constexpr unsigned int mmDIG3_HDMI_ACR_44_0__SI = 0x4539; +constexpr unsigned int mmDIG3_HDMI_ACR_44_1__SI = 0x453A; +constexpr unsigned int mmDIG3_HDMI_ACR_48_0__SI = 0x453B; +constexpr unsigned int mmDIG3_HDMI_ACR_48_1__SI = 0x453C; +constexpr unsigned int mmDIG3_HDMI_ACR_PACKET_CONTROL__SI = 0x450F; +constexpr unsigned int mmDIG3_HDMI_ACR_STATUS_0__SI = 0x453D; +constexpr unsigned int mmDIG3_HDMI_ACR_STATUS_1__SI = 0x453E; +constexpr unsigned int mmDIG3_HDMI_AUDIO_PACKET_CONTROL__SI = 0x450E; +constexpr unsigned int mmDIG3_HDMI_CONTROL__SI = 0x450C; +constexpr unsigned int mmDIG3_HDMI_GC__SI = 0x4516; +constexpr unsigned int mmDIG3_HDMI_GENERIC_PACKET_CONTROL__SI = 0x4513; +constexpr unsigned int mmDIG3_HDMI_INFOFRAME_CONTROL0__SI = 0x4511; +constexpr unsigned int mmDIG3_HDMI_INFOFRAME_CONTROL1__SI = 0x4512; +constexpr unsigned int mmDIG3_HDMI_STATUS__SI = 0x450D; +constexpr unsigned int mmDIG3_HDMI_VBI_PACKET_CONTROL__SI = 0x4510; +constexpr unsigned int mmDIG3_LVDS_DATA_CNTL__SI = 0x458C; +constexpr unsigned int mmDIG3_TMDS_CNTL__SI = 0x457C; +constexpr unsigned int mmDIG3_TMDS_CONTROL0_FEEDBACK__SI = 0x457E; +constexpr unsigned int mmDIG3_TMDS_CONTROL_CHAR__SI = 0x457D; +constexpr unsigned int mmDIG3_TMDS_CTL0_1_GEN_CNTL__SI = 0x4586; +constexpr unsigned int mmDIG3_TMDS_CTL2_3_GEN_CNTL__SI = 0x4587; +constexpr unsigned int mmDIG3_TMDS_CTL_BITS__SI = 0x4583; +constexpr unsigned int mmDIG3_TMDS_DCBALANCER_CONTROL__SI = 0x4584; +constexpr unsigned int mmDIG3_TMDS_DEBUG__SI = 0x4582; +constexpr unsigned int mmDIG3_TMDS_STEREOSYNC_CTL_SEL__SI = 0x457F; +constexpr unsigned int mmDIG3_TMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x4580; +constexpr unsigned int mmDIG3_TMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x4581; +constexpr unsigned int mmDIG4_AFMT_60958_0__SI = 0x4841; +constexpr unsigned int mmDIG4_AFMT_60958_1__SI = 0x4842; +constexpr unsigned int mmDIG4_AFMT_60958_2__SI = 0x4848; +constexpr unsigned int mmDIG4_AFMT_AUDIO_CRC_CONTROL__SI = 0x4843; +constexpr unsigned int mmDIG4_AFMT_AUDIO_CRC_RESULT__SI = 0x4849; +constexpr unsigned int mmDIG4_AFMT_AUDIO_INFO0__SI = 0x483F; +constexpr unsigned int mmDIG4_AFMT_AUDIO_INFO1__SI = 0x4840; +constexpr unsigned int mmDIG4_AFMT_AUDIO_PACKET_CONTROL2__SI = 0x4817; +constexpr unsigned int mmDIG4_AFMT_AUDIO_PACKET_CONTROL__SI = 0x484B; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO0__SI = 0x4821; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO1__SI = 0x4822; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO2__SI = 0x4823; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO3__SI = 0x4824; +constexpr unsigned int mmDIG4_AFMT_INFOFRAME_CONTROL0__SI = 0x484D; +constexpr unsigned int mmDIG4_AFMT_ISRC1_0__SI = 0x4818; +constexpr unsigned int mmDIG4_AFMT_ISRC1_1__SI = 0x4819; +constexpr unsigned int mmDIG4_AFMT_ISRC1_2__SI = 0x481A; +constexpr unsigned int mmDIG4_AFMT_ISRC1_3__SI = 0x481B; +constexpr unsigned int mmDIG4_AFMT_ISRC1_4__SI = 0x481C; +constexpr unsigned int mmDIG4_AFMT_ISRC2_0__SI = 0x481D; +constexpr unsigned int mmDIG4_AFMT_ISRC2_1__SI = 0x481E; +constexpr unsigned int mmDIG4_AFMT_ISRC2_2__SI = 0x481F; +constexpr unsigned int mmDIG4_AFMT_ISRC2_3__SI = 0x4820; +constexpr unsigned int mmDIG4_AFMT_MPEG_INFO0__SI = 0x4825; +constexpr unsigned int mmDIG4_AFMT_MPEG_INFO1__SI = 0x4826; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL0__SI = 0x4844; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL1__SI = 0x4845; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL2__SI = 0x4846; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL3__SI = 0x4847; +constexpr unsigned int mmDIG4_AFMT_STATUS__SI = 0x484A; +constexpr unsigned int mmDIG4_AFMT_VBI_PACKET_CONTROL__SI = 0x484C; +constexpr unsigned int mmDIG4_DIG_CLOCK_PATTERN__SI = 0x4803; +constexpr unsigned int mmDIG4_DIG_OUTPUT_CRC_CNTL__SI = 0x4801; +constexpr unsigned int mmDIG4_DIG_OUTPUT_CRC_RESULT__SI = 0x4802; +constexpr unsigned int mmDIG4_DIG_RANDOM_PATTERN_SEED__SI = 0x4805; +constexpr unsigned int mmDIG4_DIG_TEST_PATTERN__SI = 0x4804; +constexpr unsigned int mmDIG4_HDMI_ACR_32_0__SI = 0x4837; +constexpr unsigned int mmDIG4_HDMI_ACR_32_1__SI = 0x4838; +constexpr unsigned int mmDIG4_HDMI_ACR_44_0__SI = 0x4839; +constexpr unsigned int mmDIG4_HDMI_ACR_44_1__SI = 0x483A; +constexpr unsigned int mmDIG4_HDMI_ACR_48_0__SI = 0x483B; +constexpr unsigned int mmDIG4_HDMI_ACR_48_1__SI = 0x483C; +constexpr unsigned int mmDIG4_HDMI_ACR_PACKET_CONTROL__SI = 0x480F; +constexpr unsigned int mmDIG4_HDMI_ACR_STATUS_0__SI = 0x483D; +constexpr unsigned int mmDIG4_HDMI_ACR_STATUS_1__SI = 0x483E; +constexpr unsigned int mmDIG4_HDMI_AUDIO_PACKET_CONTROL__SI = 0x480E; +constexpr unsigned int mmDIG4_HDMI_CONTROL__SI = 0x480C; +constexpr unsigned int mmDIG4_HDMI_GC__SI = 0x4816; +constexpr unsigned int mmDIG4_HDMI_GENERIC_PACKET_CONTROL__SI = 0x4813; +constexpr unsigned int mmDIG4_HDMI_INFOFRAME_CONTROL0__SI = 0x4811; +constexpr unsigned int mmDIG4_HDMI_INFOFRAME_CONTROL1__SI = 0x4812; +constexpr unsigned int mmDIG4_HDMI_STATUS__SI = 0x480D; +constexpr unsigned int mmDIG4_HDMI_VBI_PACKET_CONTROL__SI = 0x4810; +constexpr unsigned int mmDIG4_LVDS_DATA_CNTL__SI = 0x488C; +constexpr unsigned int mmDIG4_TMDS_CNTL__SI = 0x487C; +constexpr unsigned int mmDIG4_TMDS_CONTROL0_FEEDBACK__SI = 0x487E; +constexpr unsigned int mmDIG4_TMDS_CONTROL_CHAR__SI = 0x487D; +constexpr unsigned int mmDIG4_TMDS_CTL0_1_GEN_CNTL__SI = 0x4886; +constexpr unsigned int mmDIG4_TMDS_CTL2_3_GEN_CNTL__SI = 0x4887; +constexpr unsigned int mmDIG4_TMDS_CTL_BITS__SI = 0x4883; +constexpr unsigned int mmDIG4_TMDS_DCBALANCER_CONTROL__SI = 0x4884; +constexpr unsigned int mmDIG4_TMDS_DEBUG__SI = 0x4882; +constexpr unsigned int mmDIG4_TMDS_STEREOSYNC_CTL_SEL__SI = 0x487F; +constexpr unsigned int mmDIG4_TMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x4880; +constexpr unsigned int mmDIG4_TMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x4881; +constexpr unsigned int mmDIG5_AFMT_60958_0__SI = 0x4B41; +constexpr unsigned int mmDIG5_AFMT_60958_1__SI = 0x4B42; +constexpr unsigned int mmDIG5_AFMT_60958_2__SI = 0x4B48; +constexpr unsigned int mmDIG5_AFMT_AUDIO_CRC_CONTROL__SI = 0x4B43; +constexpr unsigned int mmDIG5_AFMT_AUDIO_CRC_RESULT__SI = 0x4B49; +constexpr unsigned int mmDIG5_AFMT_AUDIO_INFO0__SI = 0x4B3F; +constexpr unsigned int mmDIG5_AFMT_AUDIO_INFO1__SI = 0x4B40; +constexpr unsigned int mmDIG5_AFMT_AUDIO_PACKET_CONTROL2__SI = 0x4B17; +constexpr unsigned int mmDIG5_AFMT_AUDIO_PACKET_CONTROL__SI = 0x4B4B; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO0__SI = 0x4B21; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO1__SI = 0x4B22; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO2__SI = 0x4B23; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO3__SI = 0x4B24; +constexpr unsigned int mmDIG5_AFMT_INFOFRAME_CONTROL0__SI = 0x4B4D; +constexpr unsigned int mmDIG5_AFMT_ISRC1_0__SI = 0x4B18; +constexpr unsigned int mmDIG5_AFMT_ISRC1_1__SI = 0x4B19; +constexpr unsigned int mmDIG5_AFMT_ISRC1_2__SI = 0x4B1A; +constexpr unsigned int mmDIG5_AFMT_ISRC1_3__SI = 0x4B1B; +constexpr unsigned int mmDIG5_AFMT_ISRC1_4__SI = 0x4B1C; +constexpr unsigned int mmDIG5_AFMT_ISRC2_0__SI = 0x4B1D; +constexpr unsigned int mmDIG5_AFMT_ISRC2_1__SI = 0x4B1E; +constexpr unsigned int mmDIG5_AFMT_ISRC2_2__SI = 0x4B1F; +constexpr unsigned int mmDIG5_AFMT_ISRC2_3__SI = 0x4B20; +constexpr unsigned int mmDIG5_AFMT_MPEG_INFO0__SI = 0x4B25; +constexpr unsigned int mmDIG5_AFMT_MPEG_INFO1__SI = 0x4B26; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL0__SI = 0x4B44; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL1__SI = 0x4B45; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL2__SI = 0x4B46; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL3__SI = 0x4B47; +constexpr unsigned int mmDIG5_AFMT_STATUS__SI = 0x4B4A; +constexpr unsigned int mmDIG5_AFMT_VBI_PACKET_CONTROL__SI = 0x4B4C; +constexpr unsigned int mmDIG5_DIG_CLOCK_PATTERN__SI = 0x4B03; +constexpr unsigned int mmDIG5_DIG_OUTPUT_CRC_CNTL__SI = 0x4B01; +constexpr unsigned int mmDIG5_DIG_OUTPUT_CRC_RESULT__SI = 0x4B02; +constexpr unsigned int mmDIG5_DIG_RANDOM_PATTERN_SEED__SI = 0x4B05; +constexpr unsigned int mmDIG5_DIG_TEST_PATTERN__SI = 0x4B04; +constexpr unsigned int mmDIG5_HDMI_ACR_32_0__SI = 0x4B37; +constexpr unsigned int mmDIG5_HDMI_ACR_32_1__SI = 0x4B38; +constexpr unsigned int mmDIG5_HDMI_ACR_44_0__SI = 0x4B39; +constexpr unsigned int mmDIG5_HDMI_ACR_44_1__SI = 0x4B3A; +constexpr unsigned int mmDIG5_HDMI_ACR_48_0__SI = 0x4B3B; +constexpr unsigned int mmDIG5_HDMI_ACR_48_1__SI = 0x4B3C; +constexpr unsigned int mmDIG5_HDMI_ACR_PACKET_CONTROL__SI = 0x4B0F; +constexpr unsigned int mmDIG5_HDMI_ACR_STATUS_0__SI = 0x4B3D; +constexpr unsigned int mmDIG5_HDMI_ACR_STATUS_1__SI = 0x4B3E; +constexpr unsigned int mmDIG5_HDMI_AUDIO_PACKET_CONTROL__SI = 0x4B0E; +constexpr unsigned int mmDIG5_HDMI_CONTROL__SI = 0x4B0C; +constexpr unsigned int mmDIG5_HDMI_GC__SI = 0x4B16; +constexpr unsigned int mmDIG5_HDMI_GENERIC_PACKET_CONTROL__SI = 0x4B13; +constexpr unsigned int mmDIG5_HDMI_INFOFRAME_CONTROL0__SI = 0x4B11; +constexpr unsigned int mmDIG5_HDMI_INFOFRAME_CONTROL1__SI = 0x4B12; +constexpr unsigned int mmDIG5_HDMI_STATUS__SI = 0x4B0D; +constexpr unsigned int mmDIG5_HDMI_VBI_PACKET_CONTROL__SI = 0x4B10; +constexpr unsigned int mmDIG5_LVDS_DATA_CNTL__SI = 0x4B8C; +constexpr unsigned int mmDIG5_TMDS_CNTL__SI = 0x4B7C; +constexpr unsigned int mmDIG5_TMDS_CONTROL0_FEEDBACK__SI = 0x4B7E; +constexpr unsigned int mmDIG5_TMDS_CONTROL_CHAR__SI = 0x4B7D; +constexpr unsigned int mmDIG5_TMDS_CTL0_1_GEN_CNTL__SI = 0x4B86; +constexpr unsigned int mmDIG5_TMDS_CTL2_3_GEN_CNTL__SI = 0x4B87; +constexpr unsigned int mmDIG5_TMDS_CTL_BITS__SI = 0x4B83; +constexpr unsigned int mmDIG5_TMDS_DCBALANCER_CONTROL__SI = 0x4B84; +constexpr unsigned int mmDIG5_TMDS_DEBUG__SI = 0x4B82; +constexpr unsigned int mmDIG5_TMDS_STEREOSYNC_CTL_SEL__SI = 0x4B7F; +constexpr unsigned int mmDIG5_TMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x4B80; +constexpr unsigned int mmDIG5_TMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x4B81; +constexpr unsigned int mmDIG_CLOCK_PATTERN__SI = 0x1C03; +constexpr unsigned int mmDIG_OUTPUT_CRC_CNTL__SI = 0x1C01; +constexpr unsigned int mmDIG_OUTPUT_CRC_RESULT__SI = 0x1C02; +constexpr unsigned int mmDIG_RANDOM_PATTERN_SEED__SI = 0x1C05; +constexpr unsigned int mmDIG_TEST_PATTERN__SI = 0x1C04; +constexpr unsigned int mmDISPCLK_CGTT_BLK_CTRL_REG__SI = 0x0128; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE2__SI = 0x183F; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE__SI = 0x183E; +constexpr unsigned int mmDISP_INTERRUPT_STATUS__SI = 0x183D; +constexpr unsigned int mmDISP_TIMER_CONTROL__SI = 0x1842; +constexpr unsigned int mmDLL_CNTL__SI__CI = 0x0AE9; +constexpr unsigned int mmDMCU_CTRL__SI__VI = 0x1600; +constexpr unsigned int mmDMCU_ERAM_RD_CTRL__SI__VI = 0x160B; +constexpr unsigned int mmDMCU_ERAM_RD_DATA__SI__VI = 0x160C; +constexpr unsigned int mmDMCU_ERAM_WR_CTRL__SI__VI = 0x1609; +constexpr unsigned int mmDMCU_ERAM_WR_DATA__SI__VI = 0x160A; +constexpr unsigned int mmDMCU_EVENT_TRIGGER__SI__VI = 0x1611; +constexpr unsigned int mmDMCU_FW_CHECKSUM_SMPL_BYTE_POS__SI__VI = 0x161A; +constexpr unsigned int mmDMCU_FW_CS_HI__SI__VI = 0x1606; +constexpr unsigned int mmDMCU_FW_CS_LO__SI__VI = 0x1607; +constexpr unsigned int mmDMCU_FW_END_ADDR__SI__VI = 0x1604; +constexpr unsigned int mmDMCU_FW_ISR_START_ADDR__SI__VI = 0x1605; +constexpr unsigned int mmDMCU_FW_START_ADDR__SI__VI = 0x1603; +constexpr unsigned int mmDMCU_INTERRUPT_STATUS__SI__VI = 0x1614; +constexpr unsigned int mmDMCU_INTERRUPT_TO_HOST_EN_MASK__SI__VI = 0x1615; +constexpr unsigned int mmDMCU_INTERRUPT_TO_UC_EN_MASK__SI__VI = 0x1616; +constexpr unsigned int mmDMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__SI__VI = 0x1617; +constexpr unsigned int mmDMCU_INT_CNT__SI__VI = 0x1619; +constexpr unsigned int mmDMCU_IRAM_RD_CTRL__SI__VI = 0x160F; +constexpr unsigned int mmDMCU_IRAM_RD_DATA__SI__VI = 0x1610; +constexpr unsigned int mmDMCU_IRAM_WR_CTRL__SI__VI = 0x160D; +constexpr unsigned int mmDMCU_IRAM_WR_DATA__SI__VI = 0x160E; +constexpr unsigned int mmDMCU_PC_START_ADDR__SI__VI = 0x1602; +constexpr unsigned int mmDMCU_RAM_ACCESS_CTRL__SI__VI = 0x1608; +constexpr unsigned int mmDMCU_STATUS__SI__VI = 0x1601; +constexpr unsigned int mmDMCU_TEST_DEBUG_DATA__SI__VI = 0x1627; +constexpr unsigned int mmDMCU_TEST_DEBUG_INDEX__SI__VI = 0x1626; +constexpr unsigned int mmDMCU_UC_INTERNAL_INT_STATUS__SI__VI = 0x1612; +constexpr unsigned int mmDMIF_ARBITRATION_CONTROL__SI__VI = 0x02F9; +constexpr unsigned int mmDMIF_CONTROL__SI__VI = 0x02F6; +constexpr unsigned int mmDMIF_HW_DEBUG__SI__VI = 0x02F8; +constexpr unsigned int mmDMIF_STATUS__SI__VI = 0x02F7; +constexpr unsigned int mmDMIF_TEST_DEBUG_DATA__SI = 0x0313; +constexpr unsigned int mmDMIF_TEST_DEBUG_INDEX__SI = 0x0312; +constexpr unsigned int mmDOUT_POWER_MANAGEMENT_CNTL__SI = 0x1841; +constexpr unsigned int mmDOUT_SCRATCH0__SI = 0x1844; +constexpr unsigned int mmDOUT_SCRATCH1__SI = 0x1845; +constexpr unsigned int mmDOUT_SCRATCH2__SI = 0x1846; +constexpr unsigned int mmDOUT_SCRATCH3__SI = 0x1847; +constexpr unsigned int mmDOUT_SCRATCH4__SI = 0x1848; +constexpr unsigned int mmDOUT_SCRATCH5__SI = 0x1849; +constexpr unsigned int mmDOUT_SCRATCH6__SI = 0x184A; +constexpr unsigned int mmDOUT_SCRATCH7__SI = 0x184B; +constexpr unsigned int mmDOUT_TEST_DEBUG_DATA__SI = 0x184E; +constexpr unsigned int mmDOUT_TEST_DEBUG_INDEX__SI = 0x184D; +constexpr unsigned int mmDP0_DP_CONFIG__SI = 0x1CC2; +constexpr unsigned int mmDP0_DP_DPHY_8B10B_CNTL__SI = 0x1CD3; +constexpr unsigned int mmDP0_DP_DPHY_CNTL__SI = 0x1CD0; +constexpr unsigned int mmDP0_DP_DPHY_CRC_CNTL__SI = 0x1CD7; +constexpr unsigned int mmDP0_DP_DPHY_CRC_EN__SI = 0x1CD6; +constexpr unsigned int mmDP0_DP_DPHY_CRC_RESULT__SI = 0x1CD8; +constexpr unsigned int mmDP0_DP_DPHY_FAST_TRAINING__SI = 0x1CCE; +constexpr unsigned int mmDP0_DP_DPHY_PRBS_CNTL__SI = 0x1CD4; +constexpr unsigned int mmDP0_DP_DPHY_SYM__SI = 0x1CD2; +constexpr unsigned int mmDP0_DP_DPHY_TRAINING_PATTERN_SEL__SI = 0x1CD1; +constexpr unsigned int mmDP0_DP_LINK_CNTL__SI = 0x1CC0; +constexpr unsigned int mmDP0_DP_PIXEL_FORMAT__SI = 0x1CC1; +constexpr unsigned int mmDP0_DP_SEC_AUD_M_READBACK__SI = 0x1CA8; +constexpr unsigned int mmDP0_DP_SEC_AUD_M__SI = 0x1CA7; +constexpr unsigned int mmDP0_DP_SEC_AUD_N_READBACK__SI = 0x1CA6; +constexpr unsigned int mmDP0_DP_SEC_AUD_N__SI = 0x1CA5; +constexpr unsigned int mmDP0_DP_SEC_CNTL__SI = 0x1CA0; +constexpr unsigned int mmDP0_DP_SEC_FRAMING1__SI = 0x1CA1; +constexpr unsigned int mmDP0_DP_SEC_FRAMING2__SI = 0x1CA2; +constexpr unsigned int mmDP0_DP_SEC_FRAMING3__SI = 0x1CA3; +constexpr unsigned int mmDP0_DP_SEC_FRAMING4__SI = 0x1CA4; +constexpr unsigned int mmDP0_DP_SEC_PACKET_CNTL__SI = 0x1CAA; +constexpr unsigned int mmDP0_DP_SEC_TIMESTAMP__SI = 0x1CA9; +constexpr unsigned int mmDP0_DP_STEER_FIFO__SI = 0x1CC4; +constexpr unsigned int mmDP0_DP_TEST_DEBUG_DATA__SI = 0x1CFD; +constexpr unsigned int mmDP0_DP_TEST_DEBUG_INDEX__SI = 0x1CFC; +constexpr unsigned int mmDP0_DP_VID_INTERRUPT_CNTL__SI = 0x1CCF; +constexpr unsigned int mmDP0_DP_VID_MSA_VBID__SI = 0x1CCD; +constexpr unsigned int mmDP0_DP_VID_M__SI = 0x1CCB; +constexpr unsigned int mmDP0_DP_VID_N__SI = 0x1CCA; +constexpr unsigned int mmDP0_DP_VID_STREAM_CNTL__SI = 0x1CC3; +constexpr unsigned int mmDP0_DP_VID_TIMING__SI = 0x1CC9; +constexpr unsigned int mmDP1_DP_CONFIG__SI = 0x1FC2; +constexpr unsigned int mmDP1_DP_DPHY_8B10B_CNTL__SI = 0x1FD3; +constexpr unsigned int mmDP1_DP_DPHY_CNTL__SI = 0x1FD0; +constexpr unsigned int mmDP1_DP_DPHY_CRC_CNTL__SI = 0x1FD7; +constexpr unsigned int mmDP1_DP_DPHY_CRC_EN__SI = 0x1FD6; +constexpr unsigned int mmDP1_DP_DPHY_CRC_RESULT__SI = 0x1FD8; +constexpr unsigned int mmDP1_DP_DPHY_FAST_TRAINING__SI = 0x1FCE; +constexpr unsigned int mmDP1_DP_DPHY_PRBS_CNTL__SI = 0x1FD4; +constexpr unsigned int mmDP1_DP_DPHY_SYM__SI = 0x1FD2; +constexpr unsigned int mmDP1_DP_DPHY_TRAINING_PATTERN_SEL__SI = 0x1FD1; +constexpr unsigned int mmDP1_DP_LINK_CNTL__SI = 0x1FC0; +constexpr unsigned int mmDP1_DP_PIXEL_FORMAT__SI = 0x1FC1; +constexpr unsigned int mmDP1_DP_SEC_AUD_M_READBACK__SI = 0x1FA8; +constexpr unsigned int mmDP1_DP_SEC_AUD_M__SI = 0x1FA7; +constexpr unsigned int mmDP1_DP_SEC_AUD_N_READBACK__SI = 0x1FA6; +constexpr unsigned int mmDP1_DP_SEC_AUD_N__SI = 0x1FA5; +constexpr unsigned int mmDP1_DP_SEC_CNTL__SI = 0x1FA0; +constexpr unsigned int mmDP1_DP_SEC_FRAMING1__SI = 0x1FA1; +constexpr unsigned int mmDP1_DP_SEC_FRAMING2__SI = 0x1FA2; +constexpr unsigned int mmDP1_DP_SEC_FRAMING3__SI = 0x1FA3; +constexpr unsigned int mmDP1_DP_SEC_FRAMING4__SI = 0x1FA4; +constexpr unsigned int mmDP1_DP_SEC_PACKET_CNTL__SI = 0x1FAA; +constexpr unsigned int mmDP1_DP_SEC_TIMESTAMP__SI = 0x1FA9; +constexpr unsigned int mmDP1_DP_STEER_FIFO__SI = 0x1FC4; +constexpr unsigned int mmDP1_DP_TEST_DEBUG_DATA__SI = 0x1FFD; +constexpr unsigned int mmDP1_DP_TEST_DEBUG_INDEX__SI = 0x1FFC; +constexpr unsigned int mmDP1_DP_VID_INTERRUPT_CNTL__SI = 0x1FCF; +constexpr unsigned int mmDP1_DP_VID_MSA_VBID__SI = 0x1FCD; +constexpr unsigned int mmDP1_DP_VID_M__SI = 0x1FCB; +constexpr unsigned int mmDP1_DP_VID_N__SI = 0x1FCA; +constexpr unsigned int mmDP1_DP_VID_STREAM_CNTL__SI = 0x1FC3; +constexpr unsigned int mmDP1_DP_VID_TIMING__SI = 0x1FC9; +constexpr unsigned int mmDP2_DP_CONFIG__SI = 0x42C2; +constexpr unsigned int mmDP2_DP_DPHY_8B10B_CNTL__SI = 0x42D3; +constexpr unsigned int mmDP2_DP_DPHY_CNTL__SI = 0x42D0; +constexpr unsigned int mmDP2_DP_DPHY_CRC_CNTL__SI = 0x42D7; +constexpr unsigned int mmDP2_DP_DPHY_CRC_EN__SI = 0x42D6; +constexpr unsigned int mmDP2_DP_DPHY_CRC_RESULT__SI = 0x42D8; +constexpr unsigned int mmDP2_DP_DPHY_FAST_TRAINING__SI = 0x42CE; +constexpr unsigned int mmDP2_DP_DPHY_PRBS_CNTL__SI = 0x42D4; +constexpr unsigned int mmDP2_DP_DPHY_SYM__SI = 0x42D2; +constexpr unsigned int mmDP2_DP_DPHY_TRAINING_PATTERN_SEL__SI = 0x42D1; +constexpr unsigned int mmDP2_DP_LINK_CNTL__SI = 0x42C0; +constexpr unsigned int mmDP2_DP_PIXEL_FORMAT__SI = 0x42C1; +constexpr unsigned int mmDP2_DP_SEC_AUD_M_READBACK__SI = 0x42A8; +constexpr unsigned int mmDP2_DP_SEC_AUD_M__SI = 0x42A7; +constexpr unsigned int mmDP2_DP_SEC_AUD_N_READBACK__SI = 0x42A6; +constexpr unsigned int mmDP2_DP_SEC_AUD_N__SI = 0x42A5; +constexpr unsigned int mmDP2_DP_SEC_CNTL__SI = 0x42A0; +constexpr unsigned int mmDP2_DP_SEC_FRAMING1__SI = 0x42A1; +constexpr unsigned int mmDP2_DP_SEC_FRAMING2__SI = 0x42A2; +constexpr unsigned int mmDP2_DP_SEC_FRAMING3__SI = 0x42A3; +constexpr unsigned int mmDP2_DP_SEC_FRAMING4__SI = 0x42A4; +constexpr unsigned int mmDP2_DP_SEC_PACKET_CNTL__SI = 0x42AA; +constexpr unsigned int mmDP2_DP_SEC_TIMESTAMP__SI = 0x42A9; +constexpr unsigned int mmDP2_DP_STEER_FIFO__SI = 0x42C4; +constexpr unsigned int mmDP2_DP_TEST_DEBUG_DATA__SI = 0x42FD; +constexpr unsigned int mmDP2_DP_TEST_DEBUG_INDEX__SI = 0x42FC; +constexpr unsigned int mmDP2_DP_VID_INTERRUPT_CNTL__SI = 0x42CF; +constexpr unsigned int mmDP2_DP_VID_MSA_VBID__SI = 0x42CD; +constexpr unsigned int mmDP2_DP_VID_M__SI = 0x42CB; +constexpr unsigned int mmDP2_DP_VID_N__SI = 0x42CA; +constexpr unsigned int mmDP2_DP_VID_STREAM_CNTL__SI = 0x42C3; +constexpr unsigned int mmDP2_DP_VID_TIMING__SI = 0x42C9; +constexpr unsigned int mmDP3_DP_CONFIG__SI = 0x45C2; +constexpr unsigned int mmDP3_DP_DPHY_8B10B_CNTL__SI = 0x45D3; +constexpr unsigned int mmDP3_DP_DPHY_CNTL__SI = 0x45D0; +constexpr unsigned int mmDP3_DP_DPHY_CRC_CNTL__SI = 0x45D7; +constexpr unsigned int mmDP3_DP_DPHY_CRC_EN__SI = 0x45D6; +constexpr unsigned int mmDP3_DP_DPHY_CRC_RESULT__SI = 0x45D8; +constexpr unsigned int mmDP3_DP_DPHY_FAST_TRAINING__SI = 0x45CE; +constexpr unsigned int mmDP3_DP_DPHY_PRBS_CNTL__SI = 0x45D4; +constexpr unsigned int mmDP3_DP_DPHY_SYM__SI = 0x45D2; +constexpr unsigned int mmDP3_DP_DPHY_TRAINING_PATTERN_SEL__SI = 0x45D1; +constexpr unsigned int mmDP3_DP_LINK_CNTL__SI = 0x45C0; +constexpr unsigned int mmDP3_DP_PIXEL_FORMAT__SI = 0x45C1; +constexpr unsigned int mmDP3_DP_SEC_AUD_M_READBACK__SI = 0x45A8; +constexpr unsigned int mmDP3_DP_SEC_AUD_M__SI = 0x45A7; +constexpr unsigned int mmDP3_DP_SEC_AUD_N_READBACK__SI = 0x45A6; +constexpr unsigned int mmDP3_DP_SEC_AUD_N__SI = 0x45A5; +constexpr unsigned int mmDP3_DP_SEC_CNTL__SI = 0x45A0; +constexpr unsigned int mmDP3_DP_SEC_FRAMING1__SI = 0x45A1; +constexpr unsigned int mmDP3_DP_SEC_FRAMING2__SI = 0x45A2; +constexpr unsigned int mmDP3_DP_SEC_FRAMING3__SI = 0x45A3; +constexpr unsigned int mmDP3_DP_SEC_FRAMING4__SI = 0x45A4; +constexpr unsigned int mmDP3_DP_SEC_PACKET_CNTL__SI = 0x45AA; +constexpr unsigned int mmDP3_DP_SEC_TIMESTAMP__SI = 0x45A9; +constexpr unsigned int mmDP3_DP_STEER_FIFO__SI = 0x45C4; +constexpr unsigned int mmDP3_DP_TEST_DEBUG_DATA__SI = 0x45FD; +constexpr unsigned int mmDP3_DP_TEST_DEBUG_INDEX__SI = 0x45FC; +constexpr unsigned int mmDP3_DP_VID_INTERRUPT_CNTL__SI = 0x45CF; +constexpr unsigned int mmDP3_DP_VID_MSA_VBID__SI = 0x45CD; +constexpr unsigned int mmDP3_DP_VID_M__SI = 0x45CB; +constexpr unsigned int mmDP3_DP_VID_N__SI = 0x45CA; +constexpr unsigned int mmDP3_DP_VID_STREAM_CNTL__SI = 0x45C3; +constexpr unsigned int mmDP3_DP_VID_TIMING__SI = 0x45C9; +constexpr unsigned int mmDP4_DP_CONFIG__SI = 0x48C2; +constexpr unsigned int mmDP4_DP_DPHY_8B10B_CNTL__SI = 0x48D3; +constexpr unsigned int mmDP4_DP_DPHY_CNTL__SI = 0x48D0; +constexpr unsigned int mmDP4_DP_DPHY_CRC_CNTL__SI = 0x48D7; +constexpr unsigned int mmDP4_DP_DPHY_CRC_EN__SI = 0x48D6; +constexpr unsigned int mmDP4_DP_DPHY_CRC_RESULT__SI = 0x48D8; +constexpr unsigned int mmDP4_DP_DPHY_FAST_TRAINING__SI = 0x48CE; +constexpr unsigned int mmDP4_DP_DPHY_PRBS_CNTL__SI = 0x48D4; +constexpr unsigned int mmDP4_DP_DPHY_SYM__SI = 0x48D2; +constexpr unsigned int mmDP4_DP_DPHY_TRAINING_PATTERN_SEL__SI = 0x48D1; +constexpr unsigned int mmDP4_DP_LINK_CNTL__SI = 0x48C0; +constexpr unsigned int mmDP4_DP_PIXEL_FORMAT__SI = 0x48C1; +constexpr unsigned int mmDP4_DP_SEC_AUD_M_READBACK__SI = 0x48A8; +constexpr unsigned int mmDP4_DP_SEC_AUD_M__SI = 0x48A7; +constexpr unsigned int mmDP4_DP_SEC_AUD_N_READBACK__SI = 0x48A6; +constexpr unsigned int mmDP4_DP_SEC_AUD_N__SI = 0x48A5; +constexpr unsigned int mmDP4_DP_SEC_CNTL__SI = 0x48A0; +constexpr unsigned int mmDP4_DP_SEC_FRAMING1__SI = 0x48A1; +constexpr unsigned int mmDP4_DP_SEC_FRAMING2__SI = 0x48A2; +constexpr unsigned int mmDP4_DP_SEC_FRAMING3__SI = 0x48A3; +constexpr unsigned int mmDP4_DP_SEC_FRAMING4__SI = 0x48A4; +constexpr unsigned int mmDP4_DP_SEC_PACKET_CNTL__SI = 0x48AA; +constexpr unsigned int mmDP4_DP_SEC_TIMESTAMP__SI = 0x48A9; +constexpr unsigned int mmDP4_DP_STEER_FIFO__SI = 0x48C4; +constexpr unsigned int mmDP4_DP_TEST_DEBUG_DATA__SI = 0x48FD; +constexpr unsigned int mmDP4_DP_TEST_DEBUG_INDEX__SI = 0x48FC; +constexpr unsigned int mmDP4_DP_VID_INTERRUPT_CNTL__SI = 0x48CF; +constexpr unsigned int mmDP4_DP_VID_MSA_VBID__SI = 0x48CD; +constexpr unsigned int mmDP4_DP_VID_M__SI = 0x48CB; +constexpr unsigned int mmDP4_DP_VID_N__SI = 0x48CA; +constexpr unsigned int mmDP4_DP_VID_STREAM_CNTL__SI = 0x48C3; +constexpr unsigned int mmDP4_DP_VID_TIMING__SI = 0x48C9; +constexpr unsigned int mmDP5_DP_CONFIG__SI = 0x4BC2; +constexpr unsigned int mmDP5_DP_DPHY_8B10B_CNTL__SI = 0x4BD3; +constexpr unsigned int mmDP5_DP_DPHY_CNTL__SI = 0x4BD0; +constexpr unsigned int mmDP5_DP_DPHY_CRC_CNTL__SI = 0x4BD7; +constexpr unsigned int mmDP5_DP_DPHY_CRC_EN__SI = 0x4BD6; +constexpr unsigned int mmDP5_DP_DPHY_CRC_RESULT__SI = 0x4BD8; +constexpr unsigned int mmDP5_DP_DPHY_FAST_TRAINING__SI = 0x4BCE; +constexpr unsigned int mmDP5_DP_DPHY_PRBS_CNTL__SI = 0x4BD4; +constexpr unsigned int mmDP5_DP_DPHY_SYM__SI = 0x4BD2; +constexpr unsigned int mmDP5_DP_DPHY_TRAINING_PATTERN_SEL__SI = 0x4BD1; +constexpr unsigned int mmDP5_DP_LINK_CNTL__SI = 0x4BC0; +constexpr unsigned int mmDP5_DP_PIXEL_FORMAT__SI = 0x4BC1; +constexpr unsigned int mmDP5_DP_SEC_AUD_M_READBACK__SI = 0x4BA8; +constexpr unsigned int mmDP5_DP_SEC_AUD_M__SI = 0x4BA7; +constexpr unsigned int mmDP5_DP_SEC_AUD_N_READBACK__SI = 0x4BA6; +constexpr unsigned int mmDP5_DP_SEC_AUD_N__SI = 0x4BA5; +constexpr unsigned int mmDP5_DP_SEC_CNTL__SI = 0x4BA0; +constexpr unsigned int mmDP5_DP_SEC_FRAMING1__SI = 0x4BA1; +constexpr unsigned int mmDP5_DP_SEC_FRAMING2__SI = 0x4BA2; +constexpr unsigned int mmDP5_DP_SEC_FRAMING3__SI = 0x4BA3; +constexpr unsigned int mmDP5_DP_SEC_FRAMING4__SI = 0x4BA4; +constexpr unsigned int mmDP5_DP_SEC_PACKET_CNTL__SI = 0x4BAA; +constexpr unsigned int mmDP5_DP_SEC_TIMESTAMP__SI = 0x4BA9; +constexpr unsigned int mmDP5_DP_STEER_FIFO__SI = 0x4BC4; +constexpr unsigned int mmDP5_DP_TEST_DEBUG_DATA__SI = 0x4BFD; +constexpr unsigned int mmDP5_DP_TEST_DEBUG_INDEX__SI = 0x4BFC; +constexpr unsigned int mmDP5_DP_VID_INTERRUPT_CNTL__SI = 0x4BCF; +constexpr unsigned int mmDP5_DP_VID_MSA_VBID__SI = 0x4BCD; +constexpr unsigned int mmDP5_DP_VID_M__SI = 0x4BCB; +constexpr unsigned int mmDP5_DP_VID_N__SI = 0x4BCA; +constexpr unsigned int mmDP5_DP_VID_STREAM_CNTL__SI = 0x4BC3; +constexpr unsigned int mmDP5_DP_VID_TIMING__SI = 0x4BC9; +constexpr unsigned int mmDP_AUX0_AUX_ARB_CONTROL__SI = 0x1882; +constexpr unsigned int mmDP_AUX0_AUX_CONTROL__SI = 0x1880; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_RX_CONTROL0__SI = 0x188A; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_RX_CONTROL1__SI = 0x188B; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_RX_STATUS__SI = 0x188D; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_TX_CONTROL__SI = 0x1889; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_TX_REF_CONTROL__SI = 0x1888; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_TX_STATUS__SI = 0x188C; +constexpr unsigned int mmDP_AUX0_AUX_INTERRUPT_CONTROL__SI = 0x1883; +constexpr unsigned int mmDP_AUX0_AUX_LS_DATA__SI = 0x1887; +constexpr unsigned int mmDP_AUX0_AUX_LS_STATUS__SI = 0x1885; +constexpr unsigned int mmDP_AUX0_AUX_SW_CONTROL__SI = 0x1881; +constexpr unsigned int mmDP_AUX0_AUX_SW_DATA__SI = 0x1886; +constexpr unsigned int mmDP_AUX0_AUX_SW_STATUS__SI = 0x1884; +constexpr unsigned int mmDP_AUX1_AUX_ARB_CONTROL__SI = 0x1896; +constexpr unsigned int mmDP_AUX1_AUX_CONTROL__SI = 0x1894; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_RX_CONTROL0__SI = 0x189E; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_RX_CONTROL1__SI = 0x189F; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_RX_STATUS__SI = 0x18A1; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_TX_CONTROL__SI = 0x189D; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_TX_REF_CONTROL__SI = 0x189C; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_TX_STATUS__SI = 0x18A0; +constexpr unsigned int mmDP_AUX1_AUX_INTERRUPT_CONTROL__SI = 0x1897; +constexpr unsigned int mmDP_AUX1_AUX_LS_DATA__SI = 0x189B; +constexpr unsigned int mmDP_AUX1_AUX_LS_STATUS__SI = 0x1899; +constexpr unsigned int mmDP_AUX1_AUX_SW_CONTROL__SI = 0x1895; +constexpr unsigned int mmDP_AUX1_AUX_SW_DATA__SI = 0x189A; +constexpr unsigned int mmDP_AUX1_AUX_SW_STATUS__SI = 0x1898; +constexpr unsigned int mmDP_AUX2_AUX_ARB_CONTROL__SI = 0x18AA; +constexpr unsigned int mmDP_AUX2_AUX_CONTROL__SI = 0x18A8; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_RX_CONTROL0__SI = 0x18B2; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_RX_CONTROL1__SI = 0x18B3; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_RX_STATUS__SI = 0x18B5; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_TX_CONTROL__SI = 0x18B1; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_TX_REF_CONTROL__SI = 0x18B0; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_TX_STATUS__SI = 0x18B4; +constexpr unsigned int mmDP_AUX2_AUX_INTERRUPT_CONTROL__SI = 0x18AB; +constexpr unsigned int mmDP_AUX2_AUX_LS_DATA__SI = 0x18AF; +constexpr unsigned int mmDP_AUX2_AUX_LS_STATUS__SI = 0x18AD; +constexpr unsigned int mmDP_AUX2_AUX_SW_CONTROL__SI = 0x18A9; +constexpr unsigned int mmDP_AUX2_AUX_SW_DATA__SI = 0x18AE; +constexpr unsigned int mmDP_AUX2_AUX_SW_STATUS__SI = 0x18AC; +constexpr unsigned int mmDP_AUX3_AUX_ARB_CONTROL__SI = 0x18C2; +constexpr unsigned int mmDP_AUX3_AUX_CONTROL__SI = 0x18C0; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_RX_CONTROL0__SI = 0x18CA; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_RX_CONTROL1__SI = 0x18CB; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_RX_STATUS__SI = 0x18CD; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_TX_CONTROL__SI = 0x18C9; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_TX_REF_CONTROL__SI = 0x18C8; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_TX_STATUS__SI = 0x18CC; +constexpr unsigned int mmDP_AUX3_AUX_INTERRUPT_CONTROL__SI = 0x18C3; +constexpr unsigned int mmDP_AUX3_AUX_LS_DATA__SI = 0x18C7; +constexpr unsigned int mmDP_AUX3_AUX_LS_STATUS__SI = 0x18C5; +constexpr unsigned int mmDP_AUX3_AUX_SW_CONTROL__SI = 0x18C1; +constexpr unsigned int mmDP_AUX3_AUX_SW_DATA__SI = 0x18C6; +constexpr unsigned int mmDP_AUX3_AUX_SW_STATUS__SI = 0x18C4; +constexpr unsigned int mmDP_AUX4_AUX_ARB_CONTROL__SI = 0x18D6; +constexpr unsigned int mmDP_AUX4_AUX_CONTROL__SI = 0x18D4; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_RX_CONTROL0__SI = 0x18DE; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_RX_CONTROL1__SI = 0x18DF; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_RX_STATUS__SI = 0x18E1; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_TX_CONTROL__SI = 0x18DD; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_TX_REF_CONTROL__SI = 0x18DC; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_TX_STATUS__SI = 0x18E0; +constexpr unsigned int mmDP_AUX4_AUX_INTERRUPT_CONTROL__SI = 0x18D7; +constexpr unsigned int mmDP_AUX4_AUX_LS_DATA__SI = 0x18DB; +constexpr unsigned int mmDP_AUX4_AUX_LS_STATUS__SI = 0x18D9; +constexpr unsigned int mmDP_AUX4_AUX_SW_CONTROL__SI = 0x18D5; +constexpr unsigned int mmDP_AUX4_AUX_SW_DATA__SI = 0x18DA; +constexpr unsigned int mmDP_AUX4_AUX_SW_STATUS__SI = 0x18D8; +constexpr unsigned int mmDP_AUX5_AUX_ARB_CONTROL__SI = 0x18EA; +constexpr unsigned int mmDP_AUX5_AUX_CONTROL__SI = 0x18E8; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_RX_CONTROL0__SI = 0x18F2; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_RX_CONTROL1__SI = 0x18F3; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_RX_STATUS__SI = 0x18F5; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_TX_CONTROL__SI = 0x18F1; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_TX_REF_CONTROL__SI = 0x18F0; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_TX_STATUS__SI = 0x18F4; +constexpr unsigned int mmDP_AUX5_AUX_INTERRUPT_CONTROL__SI = 0x18EB; +constexpr unsigned int mmDP_AUX5_AUX_LS_DATA__SI = 0x18EF; +constexpr unsigned int mmDP_AUX5_AUX_LS_STATUS__SI = 0x18ED; +constexpr unsigned int mmDP_AUX5_AUX_SW_CONTROL__SI = 0x18E9; +constexpr unsigned int mmDP_AUX5_AUX_SW_DATA__SI = 0x18EE; +constexpr unsigned int mmDP_AUX5_AUX_SW_STATUS__SI = 0x18EC; +constexpr unsigned int mmDP_CONFIG__SI = 0x1CC2; +constexpr unsigned int mmDP_DPHY_8B10B_CNTL__SI = 0x1CD3; +constexpr unsigned int mmDP_DPHY_CNTL__SI = 0x1CD0; +constexpr unsigned int mmDP_DPHY_CRC_CNTL__SI = 0x1CD7; +constexpr unsigned int mmDP_DPHY_CRC_EN__SI = 0x1CD6; +constexpr unsigned int mmDP_DPHY_CRC_RESULT__SI = 0x1CD8; +constexpr unsigned int mmDP_DPHY_FAST_TRAINING__SI = 0x1CCE; +constexpr unsigned int mmDP_DPHY_PRBS_CNTL__SI = 0x1CD4; +constexpr unsigned int mmDP_DPHY_SYM__SI = 0x1CD2; +constexpr unsigned int mmDP_DPHY_TRAINING_PATTERN_SEL__SI = 0x1CD1; +constexpr unsigned int mmDP_DTO0_MODULO__SI = 0x0171; +constexpr unsigned int mmDP_DTO0_PHASE__SI = 0x0170; +constexpr unsigned int mmDP_DTO1_MODULO__SI = 0x0173; +constexpr unsigned int mmDP_DTO1_PHASE__SI = 0x0172; +constexpr unsigned int mmDP_DTO2_MODULO__SI = 0x0175; +constexpr unsigned int mmDP_DTO2_PHASE__SI = 0x0174; +constexpr unsigned int mmDP_DTO3_MODULO__SI = 0x0177; +constexpr unsigned int mmDP_DTO3_PHASE__SI = 0x0176; +constexpr unsigned int mmDP_DTO4_MODULO__SI = 0x0179; +constexpr unsigned int mmDP_DTO4_PHASE__SI = 0x0178; +constexpr unsigned int mmDP_DTO5_MODULO__SI = 0x017B; +constexpr unsigned int mmDP_DTO5_PHASE__SI = 0x017A; +constexpr unsigned int mmDP_LINK_CNTL__SI = 0x1CC0; +constexpr unsigned int mmDP_PIXEL_FORMAT__SI = 0x1CC1; +constexpr unsigned int mmDP_SEC_AUD_M_READBACK__SI = 0x1CA8; +constexpr unsigned int mmDP_SEC_AUD_M__SI = 0x1CA7; +constexpr unsigned int mmDP_SEC_AUD_N_READBACK__SI = 0x1CA6; +constexpr unsigned int mmDP_SEC_AUD_N__SI = 0x1CA5; +constexpr unsigned int mmDP_SEC_CNTL__SI = 0x1CA0; +constexpr unsigned int mmDP_SEC_FRAMING1__SI = 0x1CA1; +constexpr unsigned int mmDP_SEC_FRAMING2__SI = 0x1CA2; +constexpr unsigned int mmDP_SEC_FRAMING3__SI = 0x1CA3; +constexpr unsigned int mmDP_SEC_FRAMING4__SI = 0x1CA4; +constexpr unsigned int mmDP_SEC_PACKET_CNTL__SI = 0x1CAA; +constexpr unsigned int mmDP_SEC_TIMESTAMP__SI = 0x1CA9; +constexpr unsigned int mmDP_STEER_FIFO__SI = 0x1CC4; +constexpr unsigned int mmDP_TEST_DEBUG_DATA__SI = 0x1CFD; +constexpr unsigned int mmDP_TEST_DEBUG_INDEX__SI = 0x1CFC; +constexpr unsigned int mmDP_VID_INTERRUPT_CNTL__SI = 0x1CCF; +constexpr unsigned int mmDP_VID_MSA_VBID__SI = 0x1CCD; +constexpr unsigned int mmDP_VID_M__SI = 0x1CCB; +constexpr unsigned int mmDP_VID_N__SI = 0x1CCA; +constexpr unsigned int mmDP_VID_STREAM_CNTL__SI = 0x1CC3; +constexpr unsigned int mmDP_VID_TIMING__SI = 0x1CC9; +constexpr unsigned int mmDVOACLKC_CNTL__SI = 0x014E; +constexpr unsigned int mmDVOACLKC_MVP_CNTL__SI = 0x014D; +constexpr unsigned int mmDVOACLKD_CNTL__SI = 0x014C; +constexpr unsigned int mmDVO_CONTROL__SI = 0x185B; +constexpr unsigned int mmDVO_CRC2_SIG_MASK__SI = 0x185D; +constexpr unsigned int mmDVO_CRC2_SIG_RESULT__SI = 0x185E; +constexpr unsigned int mmDVO_CRC_EN__SI = 0x185C; +constexpr unsigned int mmDVO_ENABLE__SI = 0x1858; +constexpr unsigned int mmDVO_OUTPUT__SI = 0x185A; +constexpr unsigned int mmDVO_SOURCE_SELECT__SI = 0x1859; +constexpr unsigned int mmDVO_STRENGTH_CONTROL__SI = 0x195D; +constexpr unsigned int mmEXT_OVERSCAN_LEFT_RIGHT__SI__VI = 0x1B5E; +constexpr unsigned int mmEXT_OVERSCAN_TOP_BOTTOM__SI__VI = 0x1B5F; +constexpr unsigned int mmFBC_CLIENT_REGION_MASK__SI = 0x16EB; +constexpr unsigned int mmFBC_CNTL__SI = 0x16D0; +constexpr unsigned int mmFBC_COMP_CNTL__SI = 0x16D4; +constexpr unsigned int mmFBC_COMP_MODE__SI = 0x16D5; +constexpr unsigned int mmFBC_CSM_REGION_OFFSET_01__SI = 0x16E9; +constexpr unsigned int mmFBC_CSM_REGION_OFFSET_23__SI = 0x16EA; +constexpr unsigned int mmFBC_DEBUG0__SI = 0x16D6; +constexpr unsigned int mmFBC_DEBUG1__SI = 0x16D7; +constexpr unsigned int mmFBC_DEBUG2__SI = 0x16D8; +constexpr unsigned int mmFBC_DEBUG_COMP__SI = 0x16EC; +constexpr unsigned int mmFBC_DEBUG_CSR_RDATA__SI = 0x16EE; +constexpr unsigned int mmFBC_DEBUG_CSR_WDATA__SI = 0x16EF; +constexpr unsigned int mmFBC_DEBUG_CSR__SI = 0x16ED; +constexpr unsigned int mmFBC_IDLE_FORCE_CLEAR_MASK__SI = 0x16D2; +constexpr unsigned int mmFBC_IDLE_MASK__SI = 0x16D1; +constexpr unsigned int mmFBC_IND_LUT0__SI = 0x16D9; +constexpr unsigned int mmFBC_IND_LUT10__SI = 0x16E3; +constexpr unsigned int mmFBC_IND_LUT11__SI = 0x16E4; +constexpr unsigned int mmFBC_IND_LUT12__SI = 0x16E5; +constexpr unsigned int mmFBC_IND_LUT13__SI = 0x16E6; +constexpr unsigned int mmFBC_IND_LUT14__SI = 0x16E7; +constexpr unsigned int mmFBC_IND_LUT15__SI = 0x16E8; +constexpr unsigned int mmFBC_IND_LUT1__SI = 0x16DA; +constexpr unsigned int mmFBC_IND_LUT2__SI = 0x16DB; +constexpr unsigned int mmFBC_IND_LUT3__SI = 0x16DC; +constexpr unsigned int mmFBC_IND_LUT4__SI = 0x16DD; +constexpr unsigned int mmFBC_IND_LUT5__SI = 0x16DE; +constexpr unsigned int mmFBC_IND_LUT6__SI = 0x16DF; +constexpr unsigned int mmFBC_IND_LUT7__SI = 0x16E0; +constexpr unsigned int mmFBC_IND_LUT8__SI = 0x16E1; +constexpr unsigned int mmFBC_IND_LUT9__SI = 0x16E2; +constexpr unsigned int mmFBC_MISC__SI = 0x16F0; +constexpr unsigned int mmFBC_START_STOP_DELAY__SI = 0x16D3; +constexpr unsigned int mmFBC_TEST_DEBUG_DATA__SI = 0x16F5; +constexpr unsigned int mmFBC_TEST_DEBUG_INDEX__SI = 0x16F4; +constexpr unsigned int mmFMT0_FMT_BIT_DEPTH_CONTROL__SI__VI = 0x1BF2; +constexpr unsigned int mmFMT0_FMT_CLAMP_CNTL__SI__VI = 0x1BF9; +constexpr unsigned int mmFMT0_FMT_CONTROL__SI__VI = 0x1BEE; +constexpr unsigned int mmFMT0_FMT_CRC_CNTL__SI__VI = 0x1BFA; +constexpr unsigned int mmFMT0_FMT_CRC_SIG_BLUE_CONTROL_MASK__SI__VI = 0x1BFC; +constexpr unsigned int mmFMT0_FMT_CRC_SIG_BLUE_CONTROL__SI__VI = 0x1BFE; +constexpr unsigned int mmFMT0_FMT_CRC_SIG_RED_GREEN_MASK__SI__VI = 0x1BFB; +constexpr unsigned int mmFMT0_FMT_CRC_SIG_RED_GREEN__SI__VI = 0x1BFD; +constexpr unsigned int mmFMT0_FMT_DEBUG_CNTL__SI__VI = 0x1BFF; +constexpr unsigned int mmFMT0_FMT_DITHER_RAND_B_SEED__SI__VI = 0x1BF5; +constexpr unsigned int mmFMT0_FMT_DITHER_RAND_G_SEED__SI__VI = 0x1BF4; +constexpr unsigned int mmFMT0_FMT_DITHER_RAND_R_SEED__SI__VI = 0x1BF3; +constexpr unsigned int mmFMT0_FMT_DYNAMIC_EXP_CNTL__SI__VI = 0x1BED; +constexpr unsigned int mmFMT0_FMT_FORCE_DATA_0_1__SI__VI = 0x1BF0; +constexpr unsigned int mmFMT0_FMT_FORCE_DATA_2_3__SI__VI = 0x1BF1; +constexpr unsigned int mmFMT0_FMT_FORCE_OUTPUT_CNTL__SI__VI = 0x1BEF; +constexpr unsigned int mmFMT0_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI__VI = 0x1BF6; +constexpr unsigned int mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI__VI = 0x1BF7; +constexpr unsigned int mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI__VI = 0x1BF8; +constexpr unsigned int mmFMT1_FMT_BIT_DEPTH_CONTROL__SI = 0x1EF2; +constexpr unsigned int mmFMT1_FMT_CLAMP_CNTL__SI = 0x1EF9; +constexpr unsigned int mmFMT1_FMT_CONTROL__SI = 0x1EEE; +constexpr unsigned int mmFMT1_FMT_CRC_CNTL__SI = 0x1EFA; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_BLUE_CONTROL_MASK__SI = 0x1EFC; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_BLUE_CONTROL__SI = 0x1EFE; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_RED_GREEN_MASK__SI = 0x1EFB; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_RED_GREEN__SI = 0x1EFD; +constexpr unsigned int mmFMT1_FMT_DEBUG_CNTL__SI = 0x1EFF; +constexpr unsigned int mmFMT1_FMT_DITHER_RAND_B_SEED__SI = 0x1EF5; +constexpr unsigned int mmFMT1_FMT_DITHER_RAND_G_SEED__SI = 0x1EF4; +constexpr unsigned int mmFMT1_FMT_DITHER_RAND_R_SEED__SI = 0x1EF3; +constexpr unsigned int mmFMT1_FMT_DYNAMIC_EXP_CNTL__SI = 0x1EED; +constexpr unsigned int mmFMT1_FMT_FORCE_DATA_0_1__SI = 0x1EF0; +constexpr unsigned int mmFMT1_FMT_FORCE_DATA_2_3__SI = 0x1EF1; +constexpr unsigned int mmFMT1_FMT_FORCE_OUTPUT_CNTL__SI = 0x1EEF; +constexpr unsigned int mmFMT1_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI = 0x1EF6; +constexpr unsigned int mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI = 0x1EF7; +constexpr unsigned int mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI = 0x1EF8; +constexpr unsigned int mmFMT2_FMT_BIT_DEPTH_CONTROL__SI = 0x41F2; +constexpr unsigned int mmFMT2_FMT_CLAMP_CNTL__SI = 0x41F9; +constexpr unsigned int mmFMT2_FMT_CONTROL__SI = 0x41EE; +constexpr unsigned int mmFMT2_FMT_CRC_CNTL__SI = 0x41FA; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_BLUE_CONTROL_MASK__SI = 0x41FC; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_BLUE_CONTROL__SI = 0x41FE; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_RED_GREEN_MASK__SI = 0x41FB; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_RED_GREEN__SI = 0x41FD; +constexpr unsigned int mmFMT2_FMT_DEBUG_CNTL__SI = 0x41FF; +constexpr unsigned int mmFMT2_FMT_DITHER_RAND_B_SEED__SI = 0x41F5; +constexpr unsigned int mmFMT2_FMT_DITHER_RAND_G_SEED__SI = 0x41F4; +constexpr unsigned int mmFMT2_FMT_DITHER_RAND_R_SEED__SI = 0x41F3; +constexpr unsigned int mmFMT2_FMT_DYNAMIC_EXP_CNTL__SI = 0x41ED; +constexpr unsigned int mmFMT2_FMT_FORCE_DATA_0_1__SI = 0x41F0; +constexpr unsigned int mmFMT2_FMT_FORCE_DATA_2_3__SI = 0x41F1; +constexpr unsigned int mmFMT2_FMT_FORCE_OUTPUT_CNTL__SI = 0x41EF; +constexpr unsigned int mmFMT2_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI = 0x41F6; +constexpr unsigned int mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI = 0x41F7; +constexpr unsigned int mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI = 0x41F8; +constexpr unsigned int mmFMT3_FMT_BIT_DEPTH_CONTROL__SI = 0x44F2; +constexpr unsigned int mmFMT3_FMT_CLAMP_CNTL__SI = 0x44F9; +constexpr unsigned int mmFMT3_FMT_CONTROL__SI = 0x44EE; +constexpr unsigned int mmFMT3_FMT_CRC_CNTL__SI = 0x44FA; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_BLUE_CONTROL_MASK__SI = 0x44FC; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_BLUE_CONTROL__SI = 0x44FE; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_RED_GREEN_MASK__SI = 0x44FB; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_RED_GREEN__SI = 0x44FD; +constexpr unsigned int mmFMT3_FMT_DEBUG_CNTL__SI = 0x44FF; +constexpr unsigned int mmFMT3_FMT_DITHER_RAND_B_SEED__SI = 0x44F5; +constexpr unsigned int mmFMT3_FMT_DITHER_RAND_G_SEED__SI = 0x44F4; +constexpr unsigned int mmFMT3_FMT_DITHER_RAND_R_SEED__SI = 0x44F3; +constexpr unsigned int mmFMT3_FMT_DYNAMIC_EXP_CNTL__SI = 0x44ED; +constexpr unsigned int mmFMT3_FMT_FORCE_DATA_0_1__SI = 0x44F0; +constexpr unsigned int mmFMT3_FMT_FORCE_DATA_2_3__SI = 0x44F1; +constexpr unsigned int mmFMT3_FMT_FORCE_OUTPUT_CNTL__SI = 0x44EF; +constexpr unsigned int mmFMT3_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI = 0x44F6; +constexpr unsigned int mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI = 0x44F7; +constexpr unsigned int mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI = 0x44F8; +constexpr unsigned int mmFMT4_FMT_BIT_DEPTH_CONTROL__SI = 0x47F2; +constexpr unsigned int mmFMT4_FMT_CLAMP_CNTL__SI = 0x47F9; +constexpr unsigned int mmFMT4_FMT_CONTROL__SI = 0x47EE; +constexpr unsigned int mmFMT4_FMT_CRC_CNTL__SI = 0x47FA; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_BLUE_CONTROL_MASK__SI = 0x47FC; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_BLUE_CONTROL__SI = 0x47FE; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_RED_GREEN_MASK__SI = 0x47FB; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_RED_GREEN__SI = 0x47FD; +constexpr unsigned int mmFMT4_FMT_DEBUG_CNTL__SI = 0x47FF; +constexpr unsigned int mmFMT4_FMT_DITHER_RAND_B_SEED__SI = 0x47F5; +constexpr unsigned int mmFMT4_FMT_DITHER_RAND_G_SEED__SI = 0x47F4; +constexpr unsigned int mmFMT4_FMT_DITHER_RAND_R_SEED__SI = 0x47F3; +constexpr unsigned int mmFMT4_FMT_DYNAMIC_EXP_CNTL__SI = 0x47ED; +constexpr unsigned int mmFMT4_FMT_FORCE_DATA_0_1__SI = 0x47F0; +constexpr unsigned int mmFMT4_FMT_FORCE_DATA_2_3__SI = 0x47F1; +constexpr unsigned int mmFMT4_FMT_FORCE_OUTPUT_CNTL__SI = 0x47EF; +constexpr unsigned int mmFMT4_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI = 0x47F6; +constexpr unsigned int mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI = 0x47F7; +constexpr unsigned int mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI = 0x47F8; +constexpr unsigned int mmFMT5_FMT_BIT_DEPTH_CONTROL__SI = 0x4AF2; +constexpr unsigned int mmFMT5_FMT_CLAMP_CNTL__SI = 0x4AF9; +constexpr unsigned int mmFMT5_FMT_CONTROL__SI = 0x4AEE; +constexpr unsigned int mmFMT5_FMT_CRC_CNTL__SI = 0x4AFA; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_BLUE_CONTROL_MASK__SI = 0x4AFC; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_BLUE_CONTROL__SI = 0x4AFE; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_RED_GREEN_MASK__SI = 0x4AFB; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_RED_GREEN__SI = 0x4AFD; +constexpr unsigned int mmFMT5_FMT_DEBUG_CNTL__SI = 0x4AFF; +constexpr unsigned int mmFMT5_FMT_DITHER_RAND_B_SEED__SI = 0x4AF5; +constexpr unsigned int mmFMT5_FMT_DITHER_RAND_G_SEED__SI = 0x4AF4; +constexpr unsigned int mmFMT5_FMT_DITHER_RAND_R_SEED__SI = 0x4AF3; +constexpr unsigned int mmFMT5_FMT_DYNAMIC_EXP_CNTL__SI = 0x4AED; +constexpr unsigned int mmFMT5_FMT_FORCE_DATA_0_1__SI = 0x4AF0; +constexpr unsigned int mmFMT5_FMT_FORCE_DATA_2_3__SI = 0x4AF1; +constexpr unsigned int mmFMT5_FMT_FORCE_OUTPUT_CNTL__SI = 0x4AEF; +constexpr unsigned int mmFMT5_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI = 0x4AF6; +constexpr unsigned int mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI = 0x4AF7; +constexpr unsigned int mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI = 0x4AF8; +constexpr unsigned int mmFMT_BIT_DEPTH_CONTROL__SI__VI = 0x1BF2; +constexpr unsigned int mmFMT_CLAMP_CNTL__SI__VI = 0x1BF9; +constexpr unsigned int mmFMT_CONTROL__SI__VI = 0x1BEE; +constexpr unsigned int mmFMT_CRC_CNTL__SI__VI = 0x1BFA; +constexpr unsigned int mmFMT_CRC_SIG_BLUE_CONTROL_MASK__SI__VI = 0x1BFC; +constexpr unsigned int mmFMT_CRC_SIG_BLUE_CONTROL__SI__VI = 0x1BFE; +constexpr unsigned int mmFMT_CRC_SIG_RED_GREEN_MASK__SI__VI = 0x1BFB; +constexpr unsigned int mmFMT_CRC_SIG_RED_GREEN__SI__VI = 0x1BFD; +constexpr unsigned int mmFMT_DEBUG_CNTL__SI__VI = 0x1BFF; +constexpr unsigned int mmFMT_DITHER_RAND_B_SEED__SI__VI = 0x1BF5; +constexpr unsigned int mmFMT_DITHER_RAND_G_SEED__SI__VI = 0x1BF4; +constexpr unsigned int mmFMT_DITHER_RAND_R_SEED__SI__VI = 0x1BF3; +constexpr unsigned int mmFMT_DYNAMIC_EXP_CNTL__SI__VI = 0x1BED; +constexpr unsigned int mmFMT_FORCE_DATA_0_1__SI__VI = 0x1BF0; +constexpr unsigned int mmFMT_FORCE_DATA_2_3__SI__VI = 0x1BF1; +constexpr unsigned int mmFMT_FORCE_OUTPUT_CNTL__SI__VI = 0x1BEF; +constexpr unsigned int mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL__SI__VI = 0x1BF6; +constexpr unsigned int mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SI__VI = 0x1BF7; +constexpr unsigned int mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SI__VI = 0x1BF8; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_0__CI__VI = 0x1403; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_1__CI__VI = 0x1405; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_2__CI__VI = 0x1407; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_3__CI__VI = 0x1409; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_4__CI__VI = 0x140B; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_5__CI__VI = 0x140D; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_6__CI__VI = 0x140F; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_END_7__CI__VI = 0x1411; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_0__CI__VI = 0x1402; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_1__CI__VI = 0x1404; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_2__CI__VI = 0x1406; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_3__CI__VI = 0x1408; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_4__CI__VI = 0x140A; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_5__CI__VI = 0x140C; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_6__CI__VI = 0x140E; +constexpr unsigned int mmGARLIC_FLUSH_ADDR_START_7__CI__VI = 0x1410; +constexpr unsigned int mmGARLIC_FLUSH_CNTL__CI__VI = 0x1401; +constexpr unsigned int mmGARLIC_FLUSH_REQ__CI__VI = 0x1412; +constexpr unsigned int mmGB_ADDR_CONFIG = 0x263E; +constexpr unsigned int mmGB_BACKEND_MAP = 0x263F; +constexpr unsigned int mmGB_EDC_MODE = 0x307E; +constexpr unsigned int mmGB_GPU_ID = 0x2640; +constexpr unsigned int mmGB_MACROTILE_MODE0__CI__VI = 0x2664; +constexpr unsigned int mmGB_MACROTILE_MODE10__CI__VI = 0x266E; +constexpr unsigned int mmGB_MACROTILE_MODE11__CI__VI = 0x266F; +constexpr unsigned int mmGB_MACROTILE_MODE12__CI__VI = 0x2670; +constexpr unsigned int mmGB_MACROTILE_MODE13__CI__VI = 0x2671; +constexpr unsigned int mmGB_MACROTILE_MODE14__CI__VI = 0x2672; +constexpr unsigned int mmGB_MACROTILE_MODE15__CI__VI = 0x2673; +constexpr unsigned int mmGB_MACROTILE_MODE1__CI__VI = 0x2665; +constexpr unsigned int mmGB_MACROTILE_MODE2__CI__VI = 0x2666; +constexpr unsigned int mmGB_MACROTILE_MODE3__CI__VI = 0x2667; +constexpr unsigned int mmGB_MACROTILE_MODE4__CI__VI = 0x2668; +constexpr unsigned int mmGB_MACROTILE_MODE5__CI__VI = 0x2669; +constexpr unsigned int mmGB_MACROTILE_MODE6__CI__VI = 0x266A; +constexpr unsigned int mmGB_MACROTILE_MODE7__CI__VI = 0x266B; +constexpr unsigned int mmGB_MACROTILE_MODE8__CI__VI = 0x266C; +constexpr unsigned int mmGB_MACROTILE_MODE9__CI__VI = 0x266D; +constexpr unsigned int mmGB_TILE_MODE0 = 0x2644; +constexpr unsigned int mmGB_TILE_MODE1 = 0x2645; +constexpr unsigned int mmGB_TILE_MODE10 = 0x264E; +constexpr unsigned int mmGB_TILE_MODE11 = 0x264F; +constexpr unsigned int mmGB_TILE_MODE12 = 0x2650; +constexpr unsigned int mmGB_TILE_MODE13 = 0x2651; +constexpr unsigned int mmGB_TILE_MODE14 = 0x2652; +constexpr unsigned int mmGB_TILE_MODE15 = 0x2653; +constexpr unsigned int mmGB_TILE_MODE16 = 0x2654; +constexpr unsigned int mmGB_TILE_MODE17 = 0x2655; +constexpr unsigned int mmGB_TILE_MODE18 = 0x2656; +constexpr unsigned int mmGB_TILE_MODE19 = 0x2657; +constexpr unsigned int mmGB_TILE_MODE2 = 0x2646; +constexpr unsigned int mmGB_TILE_MODE20 = 0x2658; +constexpr unsigned int mmGB_TILE_MODE21 = 0x2659; +constexpr unsigned int mmGB_TILE_MODE22 = 0x265A; +constexpr unsigned int mmGB_TILE_MODE23 = 0x265B; +constexpr unsigned int mmGB_TILE_MODE24 = 0x265C; +constexpr unsigned int mmGB_TILE_MODE25 = 0x265D; +constexpr unsigned int mmGB_TILE_MODE26 = 0x265E; +constexpr unsigned int mmGB_TILE_MODE27 = 0x265F; +constexpr unsigned int mmGB_TILE_MODE28 = 0x2660; +constexpr unsigned int mmGB_TILE_MODE29 = 0x2661; +constexpr unsigned int mmGB_TILE_MODE3 = 0x2647; +constexpr unsigned int mmGB_TILE_MODE30 = 0x2662; +constexpr unsigned int mmGB_TILE_MODE31 = 0x2663; +constexpr unsigned int mmGB_TILE_MODE4 = 0x2648; +constexpr unsigned int mmGB_TILE_MODE5 = 0x2649; +constexpr unsigned int mmGB_TILE_MODE6 = 0x264A; +constexpr unsigned int mmGB_TILE_MODE7 = 0x264B; +constexpr unsigned int mmGB_TILE_MODE8 = 0x264C; +constexpr unsigned int mmGB_TILE_MODE9 = 0x264D; +constexpr unsigned int mmGCK_SMC_IND_DATA__CI__VI = 0x0081; +constexpr unsigned int mmGCK_SMC_IND_INDEX__CI__VI = 0x0080; +constexpr unsigned int mmGC_USER_PRIM_CONFIG__CI__VI = 0x2241; +constexpr unsigned int mmGC_USER_RB_BACKEND_DISABLE = 0x26DF; +constexpr unsigned int mmGC_USER_RB_REDUNDANCY__CI__VI = 0x26DE; +constexpr unsigned int mmGC_USER_SHADER_ARRAY_CONFIG = 0x2270; +constexpr unsigned int mmGC_USER_SYS_RB_BACKEND_DISABLE = 0x03A1; +constexpr unsigned int mmGDS_ATOM_BASE__CI__VI = 0xC40C; +constexpr unsigned int mmGDS_ATOM_BASE__SI = 0x25CE; +constexpr unsigned int mmGDS_ATOM_CNTL__CI__VI = 0xC40A; +constexpr unsigned int mmGDS_ATOM_CNTL__SI = 0x25CC; +constexpr unsigned int mmGDS_ATOM_COMPLETE__CI__VI = 0xC40B; +constexpr unsigned int mmGDS_ATOM_COMPLETE__SI = 0x25CD; +constexpr unsigned int mmGDS_ATOM_DST__CI__VI = 0xC410; +constexpr unsigned int mmGDS_ATOM_DST__SI = 0x25D2; +constexpr unsigned int mmGDS_ATOM_OFFSET0__CI__VI = 0xC40E; +constexpr unsigned int mmGDS_ATOM_OFFSET0__SI = 0x25D0; +constexpr unsigned int mmGDS_ATOM_OFFSET1__CI__VI = 0xC40F; +constexpr unsigned int mmGDS_ATOM_OFFSET1__SI = 0x25D1; +constexpr unsigned int mmGDS_ATOM_OP__CI__VI = 0xC411; +constexpr unsigned int mmGDS_ATOM_OP__SI = 0x25D3; +constexpr unsigned int mmGDS_ATOM_READ0_U__CI__VI = 0xC417; +constexpr unsigned int mmGDS_ATOM_READ0_U__SI = 0x25D9; +constexpr unsigned int mmGDS_ATOM_READ0__CI__VI = 0xC416; +constexpr unsigned int mmGDS_ATOM_READ0__SI = 0x25D8; +constexpr unsigned int mmGDS_ATOM_READ1_U__CI__VI = 0xC419; +constexpr unsigned int mmGDS_ATOM_READ1_U__SI = 0x25DB; +constexpr unsigned int mmGDS_ATOM_READ1__CI__VI = 0xC418; +constexpr unsigned int mmGDS_ATOM_READ1__SI = 0x25DA; +constexpr unsigned int mmGDS_ATOM_SIZE__CI__VI = 0xC40D; +constexpr unsigned int mmGDS_ATOM_SIZE__SI = 0x25CF; +constexpr unsigned int mmGDS_ATOM_SRC0_U__CI__VI = 0xC413; +constexpr unsigned int mmGDS_ATOM_SRC0_U__SI = 0x25D5; +constexpr unsigned int mmGDS_ATOM_SRC0__CI__VI = 0xC412; +constexpr unsigned int mmGDS_ATOM_SRC0__SI = 0x25D4; +constexpr unsigned int mmGDS_ATOM_SRC1_U__CI__VI = 0xC415; +constexpr unsigned int mmGDS_ATOM_SRC1_U__SI = 0x25D7; +constexpr unsigned int mmGDS_ATOM_SRC1__CI__VI = 0xC414; +constexpr unsigned int mmGDS_ATOM_SRC1__SI = 0x25D6; +constexpr unsigned int mmGDS_CNTL_STATUS = 0x25C1; +constexpr unsigned int mmGDS_COMPUTE_MAX_WAVE_ID__CI__VI = 0x3348; +constexpr unsigned int mmGDS_CONFIG = 0x25C0; +constexpr unsigned int mmGDS_DEBUG_CNTL__CI__VI = 0x25C8; +constexpr unsigned int mmGDS_DEBUG_CNTL__SI = 0x25DE; +constexpr unsigned int mmGDS_DEBUG_DATA__CI__VI = 0x25C9; +constexpr unsigned int mmGDS_DEBUG_DATA__SI = 0x25DF; +constexpr unsigned int mmGDS_ENHANCE2__CI__VI = 0x25C2; +constexpr unsigned int mmGDS_ENHANCE__CI__VI = 0x334B; +constexpr unsigned int mmGDS_ENHANCE__SI = 0x25DC; +constexpr unsigned int mmGDS_GRBM_SECDED_CNT__CI = 0x25C6; +constexpr unsigned int mmGDS_GRBM_SECDED_CNT__SI = 0x25E3; +constexpr unsigned int mmGDS_GWS_RESET0__CI__VI = 0x3344; +constexpr unsigned int mmGDS_GWS_RESET1__CI__VI = 0x3345; +constexpr unsigned int mmGDS_GWS_RESOURCE_CNTL__CI__VI = 0xC41A; +constexpr unsigned int mmGDS_GWS_RESOURCE_CNTL__SI = 0x25E0; +constexpr unsigned int mmGDS_GWS_RESOURCE_CNT__CI__VI = 0xC41C; +constexpr unsigned int mmGDS_GWS_RESOURCE_RESET__CI__VI = 0x3346; +constexpr unsigned int mmGDS_GWS_RESOURCE__CI__VI = 0xC41B; +constexpr unsigned int mmGDS_GWS_RESOURCE__SI = 0x25E1; +constexpr unsigned int mmGDS_GWS_VMID0__CI__VI = 0x3320; +constexpr unsigned int mmGDS_GWS_VMID10__CI__VI = 0x332A; +constexpr unsigned int mmGDS_GWS_VMID11__CI__VI = 0x332B; +constexpr unsigned int mmGDS_GWS_VMID12__CI__VI = 0x332C; +constexpr unsigned int mmGDS_GWS_VMID13__CI__VI = 0x332D; +constexpr unsigned int mmGDS_GWS_VMID14__CI__VI = 0x332E; +constexpr unsigned int mmGDS_GWS_VMID15__CI__VI = 0x332F; +constexpr unsigned int mmGDS_GWS_VMID1__CI__VI = 0x3321; +constexpr unsigned int mmGDS_GWS_VMID2__CI__VI = 0x3322; +constexpr unsigned int mmGDS_GWS_VMID3__CI__VI = 0x3323; +constexpr unsigned int mmGDS_GWS_VMID4__CI__VI = 0x3324; +constexpr unsigned int mmGDS_GWS_VMID5__CI__VI = 0x3325; +constexpr unsigned int mmGDS_GWS_VMID6__CI__VI = 0x3326; +constexpr unsigned int mmGDS_GWS_VMID7__CI__VI = 0x3327; +constexpr unsigned int mmGDS_GWS_VMID8__CI__VI = 0x3328; +constexpr unsigned int mmGDS_GWS_VMID9__CI__VI = 0x3329; +constexpr unsigned int mmGDS_OA_ADDRESS__CI__VI = 0xC41F; +constexpr unsigned int mmGDS_OA_CGPG_RESTORE__CI__VI = 0x334C; +constexpr unsigned int mmGDS_OA_CNTL__CI__VI = 0xC41D; +constexpr unsigned int mmGDS_OA_COUNTER__CI__VI = 0xC41E; +constexpr unsigned int mmGDS_OA_DED__CI = 0x25C7; +constexpr unsigned int mmGDS_OA_DED__SI = 0x25E4; +constexpr unsigned int mmGDS_OA_INCDEC__CI__VI = 0xC420; +constexpr unsigned int mmGDS_OA_RESET_MASK__CI__VI = 0x3349; +constexpr unsigned int mmGDS_OA_RESET__CI__VI = 0x334A; +constexpr unsigned int mmGDS_OA_RING_SIZE__CI__VI = 0xC421; +constexpr unsigned int mmGDS_OA_VMID0__CI__VI = 0x3330; +constexpr unsigned int mmGDS_OA_VMID10__CI__VI = 0x333A; +constexpr unsigned int mmGDS_OA_VMID11__CI__VI = 0x333B; +constexpr unsigned int mmGDS_OA_VMID12__CI__VI = 0x333C; +constexpr unsigned int mmGDS_OA_VMID13__CI__VI = 0x333D; +constexpr unsigned int mmGDS_OA_VMID14__CI__VI = 0x333E; +constexpr unsigned int mmGDS_OA_VMID15__CI__VI = 0x333F; +constexpr unsigned int mmGDS_OA_VMID1__CI__VI = 0x3331; +constexpr unsigned int mmGDS_OA_VMID2__CI__VI = 0x3332; +constexpr unsigned int mmGDS_OA_VMID3__CI__VI = 0x3333; +constexpr unsigned int mmGDS_OA_VMID4__CI__VI = 0x3334; +constexpr unsigned int mmGDS_OA_VMID5__CI__VI = 0x3335; +constexpr unsigned int mmGDS_OA_VMID6__CI__VI = 0x3336; +constexpr unsigned int mmGDS_OA_VMID7__CI__VI = 0x3337; +constexpr unsigned int mmGDS_OA_VMID8__CI__VI = 0x3338; +constexpr unsigned int mmGDS_OA_VMID9__CI__VI = 0x3339; +constexpr unsigned int mmGDS_PERFCOUNTER0_HI__CI__VI = 0xD281; +constexpr unsigned int mmGDS_PERFCOUNTER0_HI__SI = 0x25E7; +constexpr unsigned int mmGDS_PERFCOUNTER0_LO__CI__VI = 0xD280; +constexpr unsigned int mmGDS_PERFCOUNTER0_LO__SI = 0x25E6; +constexpr unsigned int mmGDS_PERFCOUNTER0_SELECT1__CI__VI = 0xDA84; +constexpr unsigned int mmGDS_PERFCOUNTER0_SELECT__CI__VI = 0xDA80; +constexpr unsigned int mmGDS_PERFCOUNTER0_SELECT__SI = 0x25E5; +constexpr unsigned int mmGDS_PERFCOUNTER1_HI__CI__VI = 0xD283; +constexpr unsigned int mmGDS_PERFCOUNTER1_HI__SI = 0x25EA; +constexpr unsigned int mmGDS_PERFCOUNTER1_LO__CI__VI = 0xD282; +constexpr unsigned int mmGDS_PERFCOUNTER1_LO__SI = 0x25E9; +constexpr unsigned int mmGDS_PERFCOUNTER1_SELECT__CI__VI = 0xDA81; +constexpr unsigned int mmGDS_PERFCOUNTER1_SELECT__SI = 0x25E8; +constexpr unsigned int mmGDS_PERFCOUNTER2_HI__CI__VI = 0xD285; +constexpr unsigned int mmGDS_PERFCOUNTER2_HI__SI = 0x25ED; +constexpr unsigned int mmGDS_PERFCOUNTER2_LO__CI__VI = 0xD284; +constexpr unsigned int mmGDS_PERFCOUNTER2_LO__SI = 0x25EC; +constexpr unsigned int mmGDS_PERFCOUNTER2_SELECT__CI__VI = 0xDA82; +constexpr unsigned int mmGDS_PERFCOUNTER2_SELECT__SI = 0x25EB; +constexpr unsigned int mmGDS_PERFCOUNTER3_HI__CI__VI = 0xD287; +constexpr unsigned int mmGDS_PERFCOUNTER3_HI__SI = 0x25F0; +constexpr unsigned int mmGDS_PERFCOUNTER3_LO__CI__VI = 0xD286; +constexpr unsigned int mmGDS_PERFCOUNTER3_LO__SI = 0x25EF; +constexpr unsigned int mmGDS_PERFCOUNTER3_SELECT__CI__VI = 0xDA83; +constexpr unsigned int mmGDS_PERFCOUNTER3_SELECT__SI = 0x25EE; +constexpr unsigned int mmGDS_PROTECTION_FAULT__CI__VI = 0x25C3; +constexpr unsigned int mmGDS_RD_ADDR__CI__VI = 0xC400; +constexpr unsigned int mmGDS_RD_ADDR__SI = 0x25C2; +constexpr unsigned int mmGDS_RD_BURST_ADDR__CI__VI = 0xC402; +constexpr unsigned int mmGDS_RD_BURST_ADDR__SI = 0x25C4; +constexpr unsigned int mmGDS_RD_BURST_COUNT__CI__VI = 0xC403; +constexpr unsigned int mmGDS_RD_BURST_COUNT__SI = 0x25C5; +constexpr unsigned int mmGDS_RD_BURST_DATA__CI__VI = 0xC404; +constexpr unsigned int mmGDS_RD_BURST_DATA__SI = 0x25C6; +constexpr unsigned int mmGDS_RD_DATA__CI__VI = 0xC401; +constexpr unsigned int mmGDS_RD_DATA__SI = 0x25C3; +constexpr unsigned int mmGDS_SECDED_CNT__CI = 0x25C5; +constexpr unsigned int mmGDS_SECDED_CNT__SI = 0x25E2; +constexpr unsigned int mmGDS_VMID0_BASE__CI__VI = 0x3300; +constexpr unsigned int mmGDS_VMID0_SIZE__CI__VI = 0x3301; +constexpr unsigned int mmGDS_VMID10_BASE__CI__VI = 0x3314; +constexpr unsigned int mmGDS_VMID10_SIZE__CI__VI = 0x3315; +constexpr unsigned int mmGDS_VMID11_BASE__CI__VI = 0x3316; +constexpr unsigned int mmGDS_VMID11_SIZE__CI__VI = 0x3317; +constexpr unsigned int mmGDS_VMID12_BASE__CI__VI = 0x3318; +constexpr unsigned int mmGDS_VMID12_SIZE__CI__VI = 0x3319; +constexpr unsigned int mmGDS_VMID13_BASE__CI__VI = 0x331A; +constexpr unsigned int mmGDS_VMID13_SIZE__CI__VI = 0x331B; +constexpr unsigned int mmGDS_VMID14_BASE__CI__VI = 0x331C; +constexpr unsigned int mmGDS_VMID14_SIZE__CI__VI = 0x331D; +constexpr unsigned int mmGDS_VMID15_BASE__CI__VI = 0x331E; +constexpr unsigned int mmGDS_VMID15_SIZE__CI__VI = 0x331F; +constexpr unsigned int mmGDS_VMID1_BASE__CI__VI = 0x3302; +constexpr unsigned int mmGDS_VMID1_SIZE__CI__VI = 0x3303; +constexpr unsigned int mmGDS_VMID2_BASE__CI__VI = 0x3304; +constexpr unsigned int mmGDS_VMID2_SIZE__CI__VI = 0x3305; +constexpr unsigned int mmGDS_VMID3_BASE__CI__VI = 0x3306; +constexpr unsigned int mmGDS_VMID3_SIZE__CI__VI = 0x3307; +constexpr unsigned int mmGDS_VMID4_BASE__CI__VI = 0x3308; +constexpr unsigned int mmGDS_VMID4_SIZE__CI__VI = 0x3309; +constexpr unsigned int mmGDS_VMID5_BASE__CI__VI = 0x330A; +constexpr unsigned int mmGDS_VMID5_SIZE__CI__VI = 0x330B; +constexpr unsigned int mmGDS_VMID6_BASE__CI__VI = 0x330C; +constexpr unsigned int mmGDS_VMID6_SIZE__CI__VI = 0x330D; +constexpr unsigned int mmGDS_VMID7_BASE__CI__VI = 0x330E; +constexpr unsigned int mmGDS_VMID7_SIZE__CI__VI = 0x330F; +constexpr unsigned int mmGDS_VMID8_BASE__CI__VI = 0x3310; +constexpr unsigned int mmGDS_VMID8_SIZE__CI__VI = 0x3311; +constexpr unsigned int mmGDS_VMID9_BASE__CI__VI = 0x3312; +constexpr unsigned int mmGDS_VMID9_SIZE__CI__VI = 0x3313; +constexpr unsigned int mmGDS_VM_PROTECTION_FAULT__CI__VI = 0x25C4; +constexpr unsigned int mmGDS_WRITE_COMPLETE__CI__VI = 0xC409; +constexpr unsigned int mmGDS_WRITE_COMPLETE__SI = 0x25CB; +constexpr unsigned int mmGDS_WR_ADDR__CI__VI = 0xC405; +constexpr unsigned int mmGDS_WR_ADDR__SI = 0x25C7; +constexpr unsigned int mmGDS_WR_BURST_ADDR__CI__VI = 0xC407; +constexpr unsigned int mmGDS_WR_BURST_ADDR__SI = 0x25C9; +constexpr unsigned int mmGDS_WR_BURST_DATA__CI__VI = 0xC408; +constexpr unsigned int mmGDS_WR_BURST_DATA__SI = 0x25CA; +constexpr unsigned int mmGDS_WR_DATA__CI__VI = 0xC406; +constexpr unsigned int mmGDS_WR_DATA__SI = 0x25C8; +constexpr unsigned int mmGENENB__SI__VI = 0x00F0; +constexpr unsigned int mmGENERAL_PWRMGT__SI = 0x01E0; +constexpr unsigned int mmGENERIC_I2C_CONTROL__SI = 0x1834; +constexpr unsigned int mmGENERIC_I2C_DATA__SI = 0x183A; +constexpr unsigned int mmGENERIC_I2C_INTERRUPT_CONTROL__SI = 0x1835; +constexpr unsigned int mmGENERIC_I2C_PIN_DEBUG__SI = 0x183C; +constexpr unsigned int mmGENERIC_I2C_PIN_SELECTION__SI = 0x183B; +constexpr unsigned int mmGENERIC_I2C_SETUP__SI = 0x1838; +constexpr unsigned int mmGENERIC_I2C_SPEED__SI = 0x1837; +constexpr unsigned int mmGENERIC_I2C_STATUS__SI = 0x1836; +constexpr unsigned int mmGENERIC_I2C_TRANSACTION__SI = 0x1839; +constexpr unsigned int mmGENFC_RD__SI__VI = 0x00F2; +constexpr unsigned int mmGENFC_WT__SI__VI = 0x00EE; +constexpr unsigned int mmGENMO_RD__SI__VI = 0x00F3; +constexpr unsigned int mmGENMO_WT__SI__VI = 0x00F0; +constexpr unsigned int mmGENS0__SI__VI = 0x00F0; +constexpr unsigned int mmGENS1__SI__VI = 0x00EE; +constexpr unsigned int mmGFX_COPY_STATE = 0xA1F4; +constexpr unsigned int mmGFX_PIPE_CONTROL__CI__VI = 0x226D; +constexpr unsigned int mmGFX_PIPE_PRIORITY__CI__VI = 0xF87F; +constexpr unsigned int mmGMCON_DEBUG__CI__VI = 0x0D5F; +constexpr unsigned int mmGMCON_MASK__CI__VI = 0x0D52; +constexpr unsigned int mmGMCON_MISC2__CI__VI = 0x0D44; +constexpr unsigned int mmGMCON_MISC3__CI__VI = 0x0D51; +constexpr unsigned int mmGMCON_MISC__CI__VI = 0x0D43; +constexpr unsigned int mmGMCON_PERF_MON_CNTL0__CI__VI = 0x0D4A; +constexpr unsigned int mmGMCON_PERF_MON_CNTL1__CI__VI = 0x0D4B; +constexpr unsigned int mmGMCON_PERF_MON_RSLT0__CI__VI = 0x0D4C; +constexpr unsigned int mmGMCON_PERF_MON_RSLT1__CI__VI = 0x0D4D; +constexpr unsigned int mmGMCON_PGFSM_CONFIG__CI__VI = 0x0D4E; +constexpr unsigned int mmGMCON_PGFSM_READ__CI__VI = 0x0D50; +constexpr unsigned int mmGMCON_PGFSM_WRITE__CI__VI = 0x0D4F; +constexpr unsigned int mmGMCON_RENG_EXECUTE__CI__VI = 0x0D42; +constexpr unsigned int mmGMCON_RENG_RAM_DATA__CI__VI = 0x0D41; +constexpr unsigned int mmGMCON_RENG_RAM_INDEX__CI__VI = 0x0D40; +constexpr unsigned int mmGMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__CI__VI = 0x0D48; +constexpr unsigned int mmGMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__CI__VI = 0x0D49; +constexpr unsigned int mmGMCON_STCTRL_REGISTER_SAVE_RANGE0__CI__VI = 0x0D45; +constexpr unsigned int mmGMCON_STCTRL_REGISTER_SAVE_RANGE1__CI__VI = 0x0D46; +constexpr unsigned int mmGMCON_STCTRL_REGISTER_SAVE_RANGE2__CI__VI = 0x0D47; +constexpr unsigned int mmGPIOPAD_A__CI__VI = 0x0183; +constexpr unsigned int mmGPIOPAD_A__SI = 0x05E7; +constexpr unsigned int mmGPIOPAD_EN__CI__VI = 0x0184; +constexpr unsigned int mmGPIOPAD_EN__SI = 0x05E8; +constexpr unsigned int mmGPIOPAD_EXTERN_TRIG_CNTL__CI__VI = 0x018D; +constexpr unsigned int mmGPIOPAD_EXTERN_TRIG_CNTL__SI = 0x05F1; +constexpr unsigned int mmGPIOPAD_INT_EN__CI__VI = 0x018A; +constexpr unsigned int mmGPIOPAD_INT_EN__SI = 0x05EE; +constexpr unsigned int mmGPIOPAD_INT_POLARITY__CI__VI = 0x018C; +constexpr unsigned int mmGPIOPAD_INT_POLARITY__SI = 0x05F0; +constexpr unsigned int mmGPIOPAD_INT_STAT_AK__CI__VI = 0x0189; +constexpr unsigned int mmGPIOPAD_INT_STAT_AK__SI = 0x05ED; +constexpr unsigned int mmGPIOPAD_INT_STAT_EN__CI__VI = 0x0187; +constexpr unsigned int mmGPIOPAD_INT_STAT_EN__SI = 0x05EB; +constexpr unsigned int mmGPIOPAD_INT_STAT__CI__VI = 0x0188; +constexpr unsigned int mmGPIOPAD_INT_STAT__SI = 0x05EC; +constexpr unsigned int mmGPIOPAD_INT_TYPE__CI__VI = 0x018B; +constexpr unsigned int mmGPIOPAD_INT_TYPE__SI = 0x05EF; +constexpr unsigned int mmGPIOPAD_MASK__CI__VI = 0x0182; +constexpr unsigned int mmGPIOPAD_MASK__SI = 0x05E6; +constexpr unsigned int mmGPIOPAD_PD_EN__CI__VI = 0x0193; +constexpr unsigned int mmGPIOPAD_PD_EN__SI = 0x05F4; +constexpr unsigned int mmGPIOPAD_PINSTRAPS__CI__VI = 0x0186; +constexpr unsigned int mmGPIOPAD_PINSTRAPS__SI = 0x05EA; +constexpr unsigned int mmGPIOPAD_PU_EN__CI__VI = 0x0192; +constexpr unsigned int mmGPIOPAD_PU_EN__SI = 0x05F3; +constexpr unsigned int mmGPIOPAD_RCVR_SEL__CI__VI = 0x0191; +constexpr unsigned int mmGPIOPAD_RCVR_SEL__SI = 0x05F2; +constexpr unsigned int mmGPIOPAD_STRENGTH__CI__VI = 0x0181; +constexpr unsigned int mmGPIOPAD_STRENGTH__SI = 0x05E5; +constexpr unsigned int mmGPIOPAD_SW_INT_STAT__CI__VI = 0x0180; +constexpr unsigned int mmGPIOPAD_SW_INT_STAT__SI = 0x05E4; +constexpr unsigned int mmGPIOPAD_Y__CI__VI = 0x0185; +constexpr unsigned int mmGPIOPAD_Y__SI = 0x05E9; +constexpr unsigned int mmGPU_GARLIC_FLUSH_DONE__CI__VI = 0x1414; +constexpr unsigned int mmGPU_GARLIC_FLUSH_REQ__CI__VI = 0x1413; +constexpr unsigned int mmGPU_HDP_FLUSH_DONE__CI__VI = 0x1538; +constexpr unsigned int mmGPU_HDP_FLUSH_REQ__CI__VI = 0x1537; +constexpr unsigned int mmGRBM_CNTL = 0x2000; +constexpr unsigned int mmGRBM_DEBUG = 0x2014; +constexpr unsigned int mmGRBM_DEBUG_CNTL = 0x2009; +constexpr unsigned int mmGRBM_DEBUG_DATA = 0x200A; +constexpr unsigned int mmGRBM_DEBUG_SNAPSHOT = 0x2015; +constexpr unsigned int mmGRBM_GFX_CLKEN_CNTL = 0x200C; +constexpr unsigned int mmGRBM_GFX_INDEX__CI__VI = 0xC200; +constexpr unsigned int mmGRBM_GFX_INDEX__SI = 0x200B; +constexpr unsigned int mmGRBM_INT_CNTL = 0x2018; +constexpr unsigned int mmGRBM_NOWHERE = 0x203F; +constexpr unsigned int mmGRBM_PERFCOUNTER0_HI__CI__VI = 0xD041; +constexpr unsigned int mmGRBM_PERFCOUNTER0_HI__SI = 0x201F; +constexpr unsigned int mmGRBM_PERFCOUNTER0_LO__CI__VI = 0xD040; +constexpr unsigned int mmGRBM_PERFCOUNTER0_LO__SI = 0x201E; +constexpr unsigned int mmGRBM_PERFCOUNTER0_SELECT__CI__VI = 0xD840; +constexpr unsigned int mmGRBM_PERFCOUNTER0_SELECT__SI = 0x201C; +constexpr unsigned int mmGRBM_PERFCOUNTER1_HI__CI__VI = 0xD044; +constexpr unsigned int mmGRBM_PERFCOUNTER1_HI__SI = 0x2021; +constexpr unsigned int mmGRBM_PERFCOUNTER1_LO__CI__VI = 0xD043; +constexpr unsigned int mmGRBM_PERFCOUNTER1_LO__SI = 0x2020; +constexpr unsigned int mmGRBM_PERFCOUNTER1_SELECT__CI__VI = 0xD841; +constexpr unsigned int mmGRBM_PERFCOUNTER1_SELECT__SI = 0x201D; +constexpr unsigned int mmGRBM_PWR_CNTL = 0x2003; +constexpr unsigned int mmGRBM_READ_ERROR = 0x2016; +constexpr unsigned int mmGRBM_READ_ERROR2__CI__VI = 0x2017; +constexpr unsigned int mmGRBM_SCRATCH_REG0 = 0x2040; +constexpr unsigned int mmGRBM_SCRATCH_REG1 = 0x2041; +constexpr unsigned int mmGRBM_SCRATCH_REG2 = 0x2042; +constexpr unsigned int mmGRBM_SCRATCH_REG3 = 0x2043; +constexpr unsigned int mmGRBM_SCRATCH_REG4 = 0x2044; +constexpr unsigned int mmGRBM_SCRATCH_REG5 = 0x2045; +constexpr unsigned int mmGRBM_SCRATCH_REG6 = 0x2046; +constexpr unsigned int mmGRBM_SCRATCH_REG7 = 0x2047; +constexpr unsigned int mmGRBM_SE0_PERFCOUNTER_HI__CI__VI = 0xD046; +constexpr unsigned int mmGRBM_SE0_PERFCOUNTER_HI__SI = 0x202B; +constexpr unsigned int mmGRBM_SE0_PERFCOUNTER_LO__CI__VI = 0xD045; +constexpr unsigned int mmGRBM_SE0_PERFCOUNTER_LO__SI = 0x202A; +constexpr unsigned int mmGRBM_SE0_PERFCOUNTER_SELECT__CI__VI = 0xD842; +constexpr unsigned int mmGRBM_SE0_PERFCOUNTER_SELECT__SI = 0x2026; +constexpr unsigned int mmGRBM_SE1_PERFCOUNTER_HI__CI__VI = 0xD048; +constexpr unsigned int mmGRBM_SE1_PERFCOUNTER_HI__SI = 0x202D; +constexpr unsigned int mmGRBM_SE1_PERFCOUNTER_LO__CI__VI = 0xD047; +constexpr unsigned int mmGRBM_SE1_PERFCOUNTER_LO__SI = 0x202C; +constexpr unsigned int mmGRBM_SE1_PERFCOUNTER_SELECT__CI__VI = 0xD843; +constexpr unsigned int mmGRBM_SE1_PERFCOUNTER_SELECT__SI = 0x2027; +constexpr unsigned int mmGRBM_SE2_PERFCOUNTER_HI__CI__VI = 0xD04A; +constexpr unsigned int mmGRBM_SE2_PERFCOUNTER_LO__CI__VI = 0xD049; +constexpr unsigned int mmGRBM_SE2_PERFCOUNTER_SELECT__CI__VI = 0xD844; +constexpr unsigned int mmGRBM_SE3_PERFCOUNTER_HI__CI__VI = 0xD04C; +constexpr unsigned int mmGRBM_SE3_PERFCOUNTER_LO__CI__VI = 0xD04B; +constexpr unsigned int mmGRBM_SE3_PERFCOUNTER_SELECT__CI__VI = 0xD845; +constexpr unsigned int mmGRBM_SKEW_CNTL = 0x2001; +constexpr unsigned int mmGRBM_SOFT_RESET = 0x2008; +constexpr unsigned int mmGRBM_STATUS = 0x2004; +constexpr unsigned int mmGRBM_STATUS2 = 0x2002; +constexpr unsigned int mmGRBM_STATUS_SE0 = 0x2005; +constexpr unsigned int mmGRBM_STATUS_SE1 = 0x2006; +constexpr unsigned int mmGRBM_STATUS_SE2__CI__VI = 0x200E; +constexpr unsigned int mmGRBM_STATUS_SE3__CI__VI = 0x200F; +constexpr unsigned int mmGRBM_WAIT_IDLE_CLOCKS = 0x200D; +constexpr unsigned int mmGRPH8_DATA__SI__VI = 0x00F3; +constexpr unsigned int mmGRPH8_IDX__SI__VI = 0x00F3; +constexpr unsigned int mmGRPH_COMPRESS_PITCH__SI__VI = 0x1A1A; +constexpr unsigned int mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A1B; +constexpr unsigned int mmGRPH_COMPRESS_SURFACE_ADDRESS__SI__VI = 0x1A19; +constexpr unsigned int mmGRPH_CONTROL = 0x1A01; +constexpr unsigned int mmGRPH_DFQ_CONTROL__SI__VI = 0x1A14; +constexpr unsigned int mmGRPH_DFQ_STATUS__SI__VI = 0x1A15; +constexpr unsigned int mmGRPH_ENABLE__SI__VI = 0x1A00; +constexpr unsigned int mmGRPH_FLIP_CONTROL__SI__VI = 0x1A12; +constexpr unsigned int mmGRPH_INTERRUPT_CONTROL__SI__VI = 0x1A17; +constexpr unsigned int mmGRPH_INTERRUPT_STATUS__SI__VI = 0x1A16; +constexpr unsigned int mmGRPH_LUT_10BIT_BYPASS__SI__VI = 0x1A02; +constexpr unsigned int mmGRPH_PITCH__SI__VI = 0x1A06; +constexpr unsigned int mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A07; +constexpr unsigned int mmGRPH_PRIMARY_SURFACE_ADDRESS__SI__VI = 0x1A04; +constexpr unsigned int mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SI__VI = 0x1A08; +constexpr unsigned int mmGRPH_SECONDARY_SURFACE_ADDRESS__SI__VI = 0x1A05; +constexpr unsigned int mmGRPH_SURFACE_ADDRESS_HIGH_INUSE__SI__VI = 0x1A18; +constexpr unsigned int mmGRPH_SURFACE_ADDRESS_INUSE__SI__VI = 0x1A13; +constexpr unsigned int mmGRPH_SURFACE_OFFSET_X__SI__VI = 0x1A09; +constexpr unsigned int mmGRPH_SURFACE_OFFSET_Y__SI__VI = 0x1A0A; +constexpr unsigned int mmGRPH_SWAP_CNTL__SI__VI = 0x1A03; +constexpr unsigned int mmGRPH_UPDATE__SI__VI = 0x1A11; +constexpr unsigned int mmGRPH_X_END__SI__VI = 0x1A0D; +constexpr unsigned int mmGRPH_X_START__SI__VI = 0x1A0B; +constexpr unsigned int mmGRPH_Y_END__SI__VI = 0x1A0E; +constexpr unsigned int mmGRPH_Y_START__SI__VI = 0x1A0C; +constexpr unsigned int mmHDMI_ACR_32_0__SI = 0x1C37; +constexpr unsigned int mmHDMI_ACR_32_1__SI = 0x1C38; +constexpr unsigned int mmHDMI_ACR_44_0__SI = 0x1C39; +constexpr unsigned int mmHDMI_ACR_44_1__SI = 0x1C3A; +constexpr unsigned int mmHDMI_ACR_48_0__SI = 0x1C3B; +constexpr unsigned int mmHDMI_ACR_48_1__SI = 0x1C3C; +constexpr unsigned int mmHDMI_ACR_PACKET_CONTROL__SI = 0x1C0F; +constexpr unsigned int mmHDMI_ACR_STATUS_0__SI = 0x1C3D; +constexpr unsigned int mmHDMI_ACR_STATUS_1__SI = 0x1C3E; +constexpr unsigned int mmHDMI_AUDIO_PACKET_CONTROL__SI = 0x1C0E; +constexpr unsigned int mmHDMI_CONTROL__SI = 0x1C0C; +constexpr unsigned int mmHDMI_GC__SI = 0x1C16; +constexpr unsigned int mmHDMI_GENERIC_PACKET_CONTROL__SI = 0x1C13; +constexpr unsigned int mmHDMI_INFOFRAME_CONTROL0__SI = 0x1C11; +constexpr unsigned int mmHDMI_INFOFRAME_CONTROL1__SI = 0x1C12; +constexpr unsigned int mmHDMI_STATUS__SI = 0x1C0D; +constexpr unsigned int mmHDMI_VBI_PACKET_CONTROL__SI = 0x1C10; +constexpr unsigned int mmHDP_DEBUG0 = 0x0BCC; +constexpr unsigned int mmHDP_DEBUG1 = 0x0BCD; +constexpr unsigned int mmHDP_HOST_PATH_CNTL = 0x0B00; +constexpr unsigned int mmHDP_LAST_SURFACE_HIT = 0x0BCE; +constexpr unsigned int mmHDP_MEM_COHERENCY_FLUSH_CNTL = 0x1520; +constexpr unsigned int mmHDP_NONSURFACE_BASE = 0x0B01; +constexpr unsigned int mmHDP_NONSURFACE_INFO = 0x0B02; +constexpr unsigned int mmHDP_NONSURFACE_SIZE = 0x0B03; +constexpr unsigned int mmHDP_NONSURF_FLAGS = 0x0BC9; +constexpr unsigned int mmHDP_NONSURF_FLAGS_CLR = 0x0BCA; +constexpr unsigned int mmHDP_OUTSTANDING_REQ = 0x0BD1; +constexpr unsigned int mmHDP_REG_COHERENCY_FLUSH_CNTL = 0x1528; +constexpr unsigned int mmHDP_SC_MULTI_CHIP_CNTL = 0x0BD0; +constexpr unsigned int mmHDP_SW_SEMAPHORE = 0x0BCB; +constexpr unsigned int mmHDP_TILING_CONFIG = 0x0BCF; +constexpr unsigned int mmHDP_XDP_BUSY_STS = 0x0C3E; +constexpr unsigned int mmHDP_XDP_CGTT_BLK_CTRL = 0x0C33; +constexpr unsigned int mmHDP_XDP_CHKN = 0x0C40; +constexpr unsigned int mmHDP_XDP_D2H_BAR_UPDATE = 0x0C02; +constexpr unsigned int mmHDP_XDP_D2H_FLUSH = 0x0C01; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_10 = 0x0C0A; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_11 = 0x0C0B; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_12 = 0x0C0C; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_13 = 0x0C0D; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_14 = 0x0C0E; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_15 = 0x0C0F; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_16 = 0x0C10; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_17 = 0x0C11; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_18 = 0x0C12; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_19 = 0x0C13; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_20 = 0x0C14; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_21 = 0x0C15; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_22 = 0x0C16; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_23 = 0x0C17; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_24 = 0x0C18; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_25 = 0x0C19; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_26 = 0x0C1A; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_27 = 0x0C1B; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_28 = 0x0C1C; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_29 = 0x0C1D; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_3 = 0x0C03; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_30 = 0x0C1E; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_31 = 0x0C1F; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_32 = 0x0C20; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_33 = 0x0C21; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_34 = 0x0C22; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_4 = 0x0C04; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_5 = 0x0C05; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_6 = 0x0C06; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_7 = 0x0C07; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_8 = 0x0C08; +constexpr unsigned int mmHDP_XDP_D2H_RSVD_9 = 0x0C09; +constexpr unsigned int mmHDP_XDP_DBG_ADDR = 0x0C41; +constexpr unsigned int mmHDP_XDP_DBG_DATA = 0x0C42; +constexpr unsigned int mmHDP_XDP_DBG_MASK = 0x0C43; +constexpr unsigned int mmHDP_XDP_DIRECT2HDP_FIRST = 0x0C00; +constexpr unsigned int mmHDP_XDP_DIRECT2HDP_LAST = 0x0C23; +constexpr unsigned int mmHDP_XDP_FLUSH_ARMED_STS = 0x0C3C; +constexpr unsigned int mmHDP_XDP_FLUSH_CNTR0_STS = 0x0C3D; +constexpr unsigned int mmHDP_XDP_HDP_IPH_CFG = 0x0C31; +constexpr unsigned int mmHDP_XDP_HDP_MBX_MC_CFG = 0x0C2D; +constexpr unsigned int mmHDP_XDP_HDP_MC_CFG = 0x0C2E; +constexpr unsigned int mmHDP_XDP_HST_CFG = 0x0C2F; +constexpr unsigned int mmHDP_XDP_P2P_BAR0 = 0x0C34; +constexpr unsigned int mmHDP_XDP_P2P_BAR1 = 0x0C35; +constexpr unsigned int mmHDP_XDP_P2P_BAR2 = 0x0C36; +constexpr unsigned int mmHDP_XDP_P2P_BAR3 = 0x0C37; +constexpr unsigned int mmHDP_XDP_P2P_BAR4 = 0x0C38; +constexpr unsigned int mmHDP_XDP_P2P_BAR5 = 0x0C39; +constexpr unsigned int mmHDP_XDP_P2P_BAR6 = 0x0C3A; +constexpr unsigned int mmHDP_XDP_P2P_BAR7 = 0x0C3B; +constexpr unsigned int mmHDP_XDP_P2P_BAR_CFG = 0x0C24; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR0 = 0x0C26; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR1 = 0x0C27; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR2 = 0x0C28; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR3 = 0x0C29; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR4 = 0x0C2A; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR5 = 0x0C2B; +constexpr unsigned int mmHDP_XDP_P2P_MBX_ADDR6 = 0x0C2C; +constexpr unsigned int mmHDP_XDP_P2P_MBX_OFFSET = 0x0C25; +constexpr unsigned int mmHDP_XDP_SID_CFG = 0x0C30; +constexpr unsigned int mmHDP_XDP_SRBM_CFG = 0x0C32; +constexpr unsigned int mmHDP_XDP_STICKY = 0x0C3F; +constexpr unsigned int mmHOST_BUSNUM = 0x153D; +constexpr unsigned int mmHW_DEBUG = 0x1515; +constexpr unsigned int mmIA_CNTL_STATUS = 0x2237; +constexpr unsigned int mmIA_DEBUG_CNTL = 0x223A; +constexpr unsigned int mmIA_DEBUG_DATA = 0x223B; +constexpr unsigned int mmIA_ENHANCE = 0xA29C; +constexpr unsigned int mmIA_MULTI_VGT_PARAM = 0xA2AA; +constexpr unsigned int mmIA_PERFCOUNTER0_HI__CI__VI = 0xD089; +constexpr unsigned int mmIA_PERFCOUNTER0_HI__SI = 0x2225; +constexpr unsigned int mmIA_PERFCOUNTER0_LO__CI__VI = 0xD088; +constexpr unsigned int mmIA_PERFCOUNTER0_LO__SI = 0x2224; +constexpr unsigned int mmIA_PERFCOUNTER0_SELECT1__CI__VI = 0xD888; +constexpr unsigned int mmIA_PERFCOUNTER0_SELECT__CI__VI = 0xD884; +constexpr unsigned int mmIA_PERFCOUNTER0_SELECT__SI = 0x2220; +constexpr unsigned int mmIA_PERFCOUNTER1_HI__CI__VI = 0xD08B; +constexpr unsigned int mmIA_PERFCOUNTER1_HI__SI = 0x2227; +constexpr unsigned int mmIA_PERFCOUNTER1_LO__CI__VI = 0xD08A; +constexpr unsigned int mmIA_PERFCOUNTER1_LO__SI = 0x2226; +constexpr unsigned int mmIA_PERFCOUNTER1_SELECT__CI__VI = 0xD885; +constexpr unsigned int mmIA_PERFCOUNTER1_SELECT__SI = 0x2221; +constexpr unsigned int mmIA_PERFCOUNTER2_HI__CI__VI = 0xD08D; +constexpr unsigned int mmIA_PERFCOUNTER2_HI__SI = 0x2229; +constexpr unsigned int mmIA_PERFCOUNTER2_LO__CI__VI = 0xD08C; +constexpr unsigned int mmIA_PERFCOUNTER2_LO__SI = 0x2228; +constexpr unsigned int mmIA_PERFCOUNTER2_SELECT__CI__VI = 0xD886; +constexpr unsigned int mmIA_PERFCOUNTER2_SELECT__SI = 0x2222; +constexpr unsigned int mmIA_PERFCOUNTER3_HI__CI__VI = 0xD08F; +constexpr unsigned int mmIA_PERFCOUNTER3_HI__SI = 0x222B; +constexpr unsigned int mmIA_PERFCOUNTER3_LO__CI__VI = 0xD08E; +constexpr unsigned int mmIA_PERFCOUNTER3_LO__SI = 0x222A; +constexpr unsigned int mmIA_PERFCOUNTER3_SELECT__CI__VI = 0xD887; +constexpr unsigned int mmIA_PERFCOUNTER3_SELECT__SI = 0x2223; +constexpr unsigned int mmIA_VMID_OVERRIDE__SI__CI = 0x2260; +constexpr unsigned int mmIH_ADVFAULT_CNTL__SI__CI = 0x0F8C; +constexpr unsigned int mmIH_PERFCOUNTER0_RESULT__CI = 0x0F8A; +constexpr unsigned int mmIH_PERFCOUNTER1_RESULT__CI = 0x0F8B; +constexpr unsigned int mmIH_PERFMON_CNTL__CI = 0x0F89; +constexpr unsigned int mmIH_VMID_0_LUT__CI = 0x0F50; +constexpr unsigned int mmIH_VMID_10_LUT__CI = 0x0F5A; +constexpr unsigned int mmIH_VMID_11_LUT__CI = 0x0F5B; +constexpr unsigned int mmIH_VMID_12_LUT__CI = 0x0F5C; +constexpr unsigned int mmIH_VMID_13_LUT__CI = 0x0F5D; +constexpr unsigned int mmIH_VMID_14_LUT__CI = 0x0F5E; +constexpr unsigned int mmIH_VMID_15_LUT__CI = 0x0F5F; +constexpr unsigned int mmIH_VMID_1_LUT__CI = 0x0F51; +constexpr unsigned int mmIH_VMID_2_LUT__CI = 0x0F52; +constexpr unsigned int mmIH_VMID_3_LUT__CI = 0x0F53; +constexpr unsigned int mmIH_VMID_4_LUT__CI = 0x0F54; +constexpr unsigned int mmIH_VMID_5_LUT__CI = 0x0F55; +constexpr unsigned int mmIH_VMID_6_LUT__CI = 0x0F56; +constexpr unsigned int mmIH_VMID_7_LUT__CI = 0x0F57; +constexpr unsigned int mmIH_VMID_8_LUT__CI = 0x0F58; +constexpr unsigned int mmIH_VMID_9_LUT__CI = 0x0F59; +constexpr unsigned int mmIMPCTL_RESET__CI__VI = 0x14F5; +constexpr unsigned int mmINTERRUPT_CNTL = 0x151A; +constexpr unsigned int mmINTERRUPT_CNTL2 = 0x151B; +constexpr unsigned int mmINT_MASK__SI = 0x1AD0; +constexpr unsigned int mmLB0_DC_MVP_LB_CONTROL__SI = 0x1ADB; +constexpr unsigned int mmLB0_LB_DEBUG__SI = 0x1AFC; +constexpr unsigned int mmLB0_LB_SYNC_RESET_SEL__SI = 0x1ACA; +constexpr unsigned int mmLB0_LB_TEST_DEBUG_DATA__SI__VI = 0x1AFF; +constexpr unsigned int mmLB0_LB_TEST_DEBUG_INDEX__SI__VI = 0x1AFE; +constexpr unsigned int mmLB0_MVP_AFR_FLIP_FIFO_CNTL__SI = 0x1AD9; +constexpr unsigned int mmLB0_MVP_AFR_FLIP_MODE__SI = 0x1AD8; +constexpr unsigned int mmLB0_MVP_FLIP_LINE_NUM_INSERT__SI = 0x1ADA; +constexpr unsigned int mmLB1_DC_MVP_LB_CONTROL__SI = 0x1DDB; +constexpr unsigned int mmLB1_LB_DEBUG__SI = 0x1DFC; +constexpr unsigned int mmLB1_LB_SYNC_RESET_SEL__SI = 0x1DCA; +constexpr unsigned int mmLB1_LB_TEST_DEBUG_DATA__SI = 0x1DFF; +constexpr unsigned int mmLB1_LB_TEST_DEBUG_INDEX__SI = 0x1DFE; +constexpr unsigned int mmLB1_MVP_AFR_FLIP_FIFO_CNTL__SI = 0x1DD9; +constexpr unsigned int mmLB1_MVP_AFR_FLIP_MODE__SI = 0x1DD8; +constexpr unsigned int mmLB1_MVP_FLIP_LINE_NUM_INSERT__SI = 0x1DDA; +constexpr unsigned int mmLB2_DC_MVP_LB_CONTROL__SI = 0x40DB; +constexpr unsigned int mmLB2_LB_DEBUG__SI = 0x40FC; +constexpr unsigned int mmLB2_LB_SYNC_RESET_SEL__SI = 0x40CA; +constexpr unsigned int mmLB2_LB_TEST_DEBUG_DATA__SI = 0x40FF; +constexpr unsigned int mmLB2_LB_TEST_DEBUG_INDEX__SI = 0x40FE; +constexpr unsigned int mmLB2_MVP_AFR_FLIP_FIFO_CNTL__SI = 0x40D9; +constexpr unsigned int mmLB2_MVP_AFR_FLIP_MODE__SI = 0x40D8; +constexpr unsigned int mmLB2_MVP_FLIP_LINE_NUM_INSERT__SI = 0x40DA; +constexpr unsigned int mmLB3_DC_MVP_LB_CONTROL__SI = 0x43DB; +constexpr unsigned int mmLB3_LB_DEBUG__SI = 0x43FC; +constexpr unsigned int mmLB3_LB_SYNC_RESET_SEL__SI = 0x43CA; +constexpr unsigned int mmLB3_LB_TEST_DEBUG_DATA__SI = 0x43FF; +constexpr unsigned int mmLB3_LB_TEST_DEBUG_INDEX__SI = 0x43FE; +constexpr unsigned int mmLB3_MVP_AFR_FLIP_FIFO_CNTL__SI = 0x43D9; +constexpr unsigned int mmLB3_MVP_AFR_FLIP_MODE__SI = 0x43D8; +constexpr unsigned int mmLB3_MVP_FLIP_LINE_NUM_INSERT__SI = 0x43DA; +constexpr unsigned int mmLB4_DC_MVP_LB_CONTROL__SI = 0x46DB; +constexpr unsigned int mmLB4_LB_DEBUG__SI = 0x46FC; +constexpr unsigned int mmLB4_LB_SYNC_RESET_SEL__SI = 0x46CA; +constexpr unsigned int mmLB4_LB_TEST_DEBUG_DATA__SI = 0x46FF; +constexpr unsigned int mmLB4_LB_TEST_DEBUG_INDEX__SI = 0x46FE; +constexpr unsigned int mmLB4_MVP_AFR_FLIP_FIFO_CNTL__SI = 0x46D9; +constexpr unsigned int mmLB4_MVP_AFR_FLIP_MODE__SI = 0x46D8; +constexpr unsigned int mmLB4_MVP_FLIP_LINE_NUM_INSERT__SI = 0x46DA; +constexpr unsigned int mmLB5_DC_MVP_LB_CONTROL__SI = 0x49DB; +constexpr unsigned int mmLB5_LB_DEBUG__SI = 0x49FC; +constexpr unsigned int mmLB5_LB_SYNC_RESET_SEL__SI = 0x49CA; +constexpr unsigned int mmLB5_LB_TEST_DEBUG_DATA__SI = 0x49FF; +constexpr unsigned int mmLB5_LB_TEST_DEBUG_INDEX__SI = 0x49FE; +constexpr unsigned int mmLB5_MVP_AFR_FLIP_FIFO_CNTL__SI = 0x49D9; +constexpr unsigned int mmLB5_MVP_AFR_FLIP_MODE__SI = 0x49D8; +constexpr unsigned int mmLB5_MVP_FLIP_LINE_NUM_INSERT__SI = 0x49DA; +constexpr unsigned int mmLB_DEBUG__SI = 0x1AFC; +constexpr unsigned int mmLB_SYNC_RESET_SEL__SI = 0x1ACA; +constexpr unsigned int mmLB_TEST_DEBUG_DATA__SI__VI = 0x1AFF; +constexpr unsigned int mmLB_TEST_DEBUG_INDEX__SI__VI = 0x1AFE; +constexpr unsigned int mmLNCNT_CONTROL__CI = 0x1487; +constexpr unsigned int mmLVDS_DATA_CNTL__SI = 0x1C8C; +constexpr unsigned int mmLVTMA_PWRSEQ_CNTL__SI = 0x1962; +constexpr unsigned int mmLVTMA_PWRSEQ_DELAY1__SI = 0x1965; +constexpr unsigned int mmLVTMA_PWRSEQ_DELAY2__SI = 0x1966; +constexpr unsigned int mmLVTMA_PWRSEQ_REF_DIV__SI = 0x1964; +constexpr unsigned int mmLVTMA_PWRSEQ_STATE__SI = 0x1963; +constexpr unsigned int mmMASTER_COMM_CMD_REG__SI__VI = 0x161F; +constexpr unsigned int mmMASTER_COMM_CNTL_REG__SI__VI = 0x1620; +constexpr unsigned int mmMASTER_COMM_DATA_REG1__SI__VI = 0x161C; +constexpr unsigned int mmMASTER_COMM_DATA_REG2__SI__VI = 0x161D; +constexpr unsigned int mmMASTER_COMM_DATA_REG3__SI__VI = 0x161E; +constexpr unsigned int mmMASTER_CREDIT_CNTL = 0x1516; +constexpr unsigned int mmMASTER_UPDATE_LOCK__SI__VI = 0x1BBD; +constexpr unsigned int mmMASTER_UPDATE_MODE__SI__VI = 0x1BBE; +constexpr unsigned int mmMCIF_CONTROL__SI = 0x0314; +constexpr unsigned int mmMCIF_TEST_DEBUG_DATA__SI = 0x0317; +constexpr unsigned int mmMCIF_TEST_DEBUG_INDEX__SI = 0x0316; +constexpr unsigned int mmMCIF_WRITE_COMBINE_CONTROL__SI = 0x0315; +constexpr unsigned int mmMCLK_PWRMGT_CNTL__SI__CI = 0x0AE8; +constexpr unsigned int mmMC_ARB_ADDR_HASH = 0x09DC; +constexpr unsigned int mmMC_ARB_ADDR_SWIZ0__CI__VI = 0x09CB; +constexpr unsigned int mmMC_ARB_ADDR_SWIZ1__CI__VI = 0x09CC; +constexpr unsigned int mmMC_ARB_AGE_CNTL__CI__VI = 0x09BF; +constexpr unsigned int mmMC_ARB_AGE_RD = 0x09E9; +constexpr unsigned int mmMC_ARB_AGE_WR = 0x09EA; +constexpr unsigned int mmMC_ARB_BANKMAP = 0x09D7; +constexpr unsigned int mmMC_ARB_BURST_TIME = 0x0A02; +constexpr unsigned int mmMC_ARB_BUSY_STATUS__CI__VI = 0x09FD; +constexpr unsigned int mmMC_ARB_CAC_CNTL = 0x09D4; +constexpr unsigned int mmMC_ARB_CG = 0x09FA; +constexpr unsigned int mmMC_ARB_DRAM_TIMING = 0x09DD; +constexpr unsigned int mmMC_ARB_DRAM_TIMING2 = 0x09DE; +constexpr unsigned int mmMC_ARB_DRAM_TIMING2_1 = 0x09FF; +constexpr unsigned int mmMC_ARB_DRAM_TIMING_1 = 0x09FC; +constexpr unsigned int mmMC_ARB_FED_CNTL = 0x09C1; +constexpr unsigned int mmMC_ARB_GDEC_RD_CNTL = 0x09EE; +constexpr unsigned int mmMC_ARB_GDEC_WR_CNTL = 0x09EF; +constexpr unsigned int mmMC_ARB_GECC2 = 0x09C9; +constexpr unsigned int mmMC_ARB_GECC2_CLI = 0x09CA; +constexpr unsigned int mmMC_ARB_GECC2_DEBUG = 0x09C4; +constexpr unsigned int mmMC_ARB_GECC2_DEBUG2 = 0x09C5; +constexpr unsigned int mmMC_ARB_GECC2_MISC = 0x09C3; +constexpr unsigned int mmMC_ARB_GECC2_STATUS = 0x09C2; +constexpr unsigned int mmMC_ARB_HARSH_BWCNT0_RD__CI__VI = 0x0DCE; +constexpr unsigned int mmMC_ARB_HARSH_BWCNT0_WR__CI__VI = 0x0DCF; +constexpr unsigned int mmMC_ARB_HARSH_BWCNT1_RD__CI__VI = 0x0DD0; +constexpr unsigned int mmMC_ARB_HARSH_BWCNT1_WR__CI__VI = 0x0DD1; +constexpr unsigned int mmMC_ARB_HARSH_BWPERIOD0_RD__CI__VI = 0x0DCA; +constexpr unsigned int mmMC_ARB_HARSH_BWPERIOD0_WR__CI__VI = 0x0DCB; +constexpr unsigned int mmMC_ARB_HARSH_BWPERIOD1_RD__CI__VI = 0x0DCC; +constexpr unsigned int mmMC_ARB_HARSH_BWPERIOD1_WR__CI__VI = 0x0DCD; +constexpr unsigned int mmMC_ARB_HARSH_CTL_RD__CI__VI = 0x0DD6; +constexpr unsigned int mmMC_ARB_HARSH_CTL_WR__CI__VI = 0x0DD7; +constexpr unsigned int mmMC_ARB_HARSH_EN_RD__CI__VI = 0x0DC0; +constexpr unsigned int mmMC_ARB_HARSH_EN_WR__CI__VI = 0x0DC1; +constexpr unsigned int mmMC_ARB_HARSH_SAT0_RD__CI__VI = 0x0DD2; +constexpr unsigned int mmMC_ARB_HARSH_SAT0_WR__CI__VI = 0x0DD3; +constexpr unsigned int mmMC_ARB_HARSH_SAT1_RD__CI__VI = 0x0DD4; +constexpr unsigned int mmMC_ARB_HARSH_SAT1_WR__CI__VI = 0x0DD5; +constexpr unsigned int mmMC_ARB_HARSH_TX_HI0_RD__CI__VI = 0x0DC2; +constexpr unsigned int mmMC_ARB_HARSH_TX_HI0_WR__CI__VI = 0x0DC3; +constexpr unsigned int mmMC_ARB_HARSH_TX_HI1_RD__CI__VI = 0x0DC4; +constexpr unsigned int mmMC_ARB_HARSH_TX_HI1_WR__CI__VI = 0x0DC5; +constexpr unsigned int mmMC_ARB_HARSH_TX_LO0_RD__CI__VI = 0x0DC6; +constexpr unsigned int mmMC_ARB_HARSH_TX_LO0_WR__CI__VI = 0x0DC7; +constexpr unsigned int mmMC_ARB_HARSH_TX_LO1_RD__CI__VI = 0x0DC8; +constexpr unsigned int mmMC_ARB_HARSH_TX_LO1_WR__CI__VI = 0x0DC9; +constexpr unsigned int mmMC_ARB_LAZY0_RD = 0x09E5; +constexpr unsigned int mmMC_ARB_LAZY0_WR = 0x09E6; +constexpr unsigned int mmMC_ARB_LAZY1_RD = 0x09E7; +constexpr unsigned int mmMC_ARB_LAZY1_WR = 0x09E8; +constexpr unsigned int mmMC_ARB_LM_RD = 0x09F0; +constexpr unsigned int mmMC_ARB_LM_WR = 0x09F1; +constexpr unsigned int mmMC_ARB_MAX_LAT_CID__CI__VI = 0x09F6; +constexpr unsigned int mmMC_ARB_MAX_LAT_RSLT0__CI__VI = 0x09F7; +constexpr unsigned int mmMC_ARB_MAX_LAT_RSLT1__CI__VI = 0x09F8; +constexpr unsigned int mmMC_ARB_MINCLKS = 0x09DA; +constexpr unsigned int mmMC_ARB_MISC = 0x09D6; +constexpr unsigned int mmMC_ARB_MISC2 = 0x09D5; +constexpr unsigned int mmMC_ARB_MISC3__CI__VI = 0x09CD; +constexpr unsigned int mmMC_ARB_PERFCOUNTER0_CFG__CI__VI = 0x07BC; +constexpr unsigned int mmMC_ARB_PERFCOUNTER1_CFG__CI__VI = 0x07BD; +constexpr unsigned int mmMC_ARB_PERFCOUNTER2_CFG__CI__VI = 0x07BE; +constexpr unsigned int mmMC_ARB_PERFCOUNTER3_CFG__CI__VI = 0x07BF; +constexpr unsigned int mmMC_ARB_PERFCOUNTER_HI__CI__VI = 0x07AE; +constexpr unsigned int mmMC_ARB_PERFCOUNTER_LO__CI__VI = 0x07A6; +constexpr unsigned int mmMC_ARB_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07D4; +constexpr unsigned int mmMC_ARB_PERF_MON_CNTL0_ECC__CI = 0x07DB; +constexpr unsigned int mmMC_ARB_PERF_MON_CNTL0__SI = 0x09F6; +constexpr unsigned int mmMC_ARB_PM_CNTL = 0x09ED; +constexpr unsigned int mmMC_ARB_POP = 0x09D9; +constexpr unsigned int mmMC_ARB_RAMCFG = 0x09D8; +constexpr unsigned int mmMC_ARB_REMREQ = 0x09F2; +constexpr unsigned int mmMC_ARB_REPLAY = 0x09F3; +constexpr unsigned int mmMC_ARB_RET_CREDITS2__CI__VI = 0x09C0; +constexpr unsigned int mmMC_ARB_RET_CREDITS_RD = 0x09F4; +constexpr unsigned int mmMC_ARB_RET_CREDITS_WR = 0x09F5; +constexpr unsigned int mmMC_ARB_RFSH_CNTL = 0x09EB; +constexpr unsigned int mmMC_ARB_RFSH_RATE = 0x09EC; +constexpr unsigned int mmMC_ARB_RTT_CNTL0 = 0x09D0; +constexpr unsigned int mmMC_ARB_RTT_CNTL1 = 0x09D1; +constexpr unsigned int mmMC_ARB_RTT_CNTL2 = 0x09D2; +constexpr unsigned int mmMC_ARB_RTT_DATA = 0x09CF; +constexpr unsigned int mmMC_ARB_RTT_DEBUG = 0x09D3; +constexpr unsigned int mmMC_ARB_SQM_CNTL = 0x09DB; +constexpr unsigned int mmMC_ARB_SSM__CI = 0x09F9; +constexpr unsigned int mmMC_ARB_TM_CNTL_RD = 0x09E3; +constexpr unsigned int mmMC_ARB_TM_CNTL_WR = 0x09E4; +constexpr unsigned int mmMC_ARB_WCDR__SI__CI = 0x09FB; +constexpr unsigned int mmMC_ARB_WCDR_2__SI__CI = 0x09CE; +constexpr unsigned int mmMC_ARB_WTM_CNTL_RD = 0x09DF; +constexpr unsigned int mmMC_ARB_WTM_CNTL_WR = 0x09E0; +constexpr unsigned int mmMC_ARB_WTM_GRPWT_RD = 0x09E1; +constexpr unsigned int mmMC_ARB_WTM_GRPWT_WR = 0x09E2; +constexpr unsigned int mmMC_BIST_AUTO_CNTL__SI__CI = 0x0A06; +constexpr unsigned int mmMC_BIST_CMD_CNTL__SI__CI = 0x0A8E; +constexpr unsigned int mmMC_BIST_CMP_CNTL__SI__CI = 0x0A8D; +constexpr unsigned int mmMC_BIST_CMP_CNTL_2__SI__CI = 0x0AB6; +constexpr unsigned int mmMC_BIST_DATA_MASK__SI__CI = 0x0A12; +constexpr unsigned int mmMC_BIST_DIR_CNTL__SI__CI = 0x0A07; +constexpr unsigned int mmMC_BIST_EADDR__SI__CI = 0x0A09; +constexpr unsigned int mmMC_BIST_RDATA_EDC__SI__CI = 0x0A1D; +constexpr unsigned int mmMC_BIST_RDATA_MASK__SI__CI = 0x0A1C; +constexpr unsigned int mmMC_BIST_SADDR__SI__CI = 0x0A08; +constexpr unsigned int mmMC_CG_CONFIG = 0x096F; +constexpr unsigned int mmMC_CG_CONFIG_MCD = 0x0829; +constexpr unsigned int mmMC_CITF_CNTL = 0x0970; +constexpr unsigned int mmMC_CITF_CREDITS_ARB_RD = 0x0972; +constexpr unsigned int mmMC_CITF_CREDITS_ARB_WR = 0x0973; +constexpr unsigned int mmMC_CITF_CREDITS_VM = 0x0971; +constexpr unsigned int mmMC_CITF_CREDITS_XBAR = 0x0989; +constexpr unsigned int mmMC_CITF_DAGB_CNTL = 0x0974; +constexpr unsigned int mmMC_CITF_DAGB_DLY = 0x0977; +constexpr unsigned int mmMC_CITF_INT_CREDITS = 0x0975; +constexpr unsigned int mmMC_CITF_INT_CREDITS_WR__CI__VI = 0x097D; +constexpr unsigned int mmMC_CITF_MISC_RD_CG = 0x0992; +constexpr unsigned int mmMC_CITF_MISC_VM_CG = 0x0994; +constexpr unsigned int mmMC_CITF_MISC_WR_CG = 0x0993; +constexpr unsigned int mmMC_CITF_PERFCOUNTER0_CFG__CI__VI = 0x07B0; +constexpr unsigned int mmMC_CITF_PERFCOUNTER1_CFG__CI__VI = 0x07B1; +constexpr unsigned int mmMC_CITF_PERFCOUNTER2_CFG__CI__VI = 0x07B2; +constexpr unsigned int mmMC_CITF_PERFCOUNTER3_CFG__CI__VI = 0x07B3; +constexpr unsigned int mmMC_CITF_PERFCOUNTER_HI__CI__VI = 0x07A8; +constexpr unsigned int mmMC_CITF_PERFCOUNTER_LO__CI__VI = 0x07A0; +constexpr unsigned int mmMC_CITF_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07CE; +constexpr unsigned int mmMC_CITF_PERF_MON_CNTL2 = 0x098E; +constexpr unsigned int mmMC_CITF_PERF_MON_RSLT2 = 0x0991; +constexpr unsigned int mmMC_CITF_REMREQ = 0x097A; +constexpr unsigned int mmMC_CITF_RET_MODE = 0x0976; +constexpr unsigned int mmMC_CITF_WTM_RD_CNTL = 0x097F; +constexpr unsigned int mmMC_CITF_WTM_WR_CNTL = 0x0980; +constexpr unsigned int mmMC_CITF_XTRA_ENABLE = 0x096D; +constexpr unsigned int mmMC_CONFIG = 0x0800; +constexpr unsigned int mmMC_CONFIG_MCD = 0x0828; +constexpr unsigned int mmMC_DC_INTERFACE_NACK_STATUS__SI = 0x031C; +constexpr unsigned int mmMC_DLB_CONFIG0__CI = 0x0D93; +constexpr unsigned int mmMC_DLB_CONFIG1__CI = 0x0D94; +constexpr unsigned int mmMC_DLB_MISCCTRL0__CI = 0x0D90; +constexpr unsigned int mmMC_DLB_MISCCTRL1__CI = 0x0D91; +constexpr unsigned int mmMC_DLB_MISCCTRL2__CI = 0x0D92; +constexpr unsigned int mmMC_DLB_SETUPFIFO__CI = 0x0D97; +constexpr unsigned int mmMC_DLB_SETUPSWEEP__CI = 0x0D96; +constexpr unsigned int mmMC_DLB_SETUP__CI = 0x0D95; +constexpr unsigned int mmMC_DLB_STATUS_MISC0__CI = 0x0D9A; +constexpr unsigned int mmMC_DLB_STATUS_MISC1__CI = 0x0D9B; +constexpr unsigned int mmMC_DLB_STATUS_MISC2__CI = 0x0D9C; +constexpr unsigned int mmMC_DLB_STATUS_MISC3__CI = 0x0D9D; +constexpr unsigned int mmMC_DLB_STATUS_MISC4__CI = 0x0D9E; +constexpr unsigned int mmMC_DLB_STATUS_MISC5__CI = 0x0D9F; +constexpr unsigned int mmMC_DLB_STATUS_MISC6__CI = 0x0DA0; +constexpr unsigned int mmMC_DLB_STATUS_MISC7__CI = 0x0DA1; +constexpr unsigned int mmMC_DLB_STATUS__CI = 0x0D99; +constexpr unsigned int mmMC_DLB_WRITE_MASK__CI = 0x0D98; +constexpr unsigned int mmMC_HUB_MISC_DBG__SI__CI = 0x0831; +constexpr unsigned int mmMC_HUB_MISC_FRAMING = 0x0834; +constexpr unsigned int mmMC_HUB_MISC_HUB_CG = 0x082E; +constexpr unsigned int mmMC_HUB_MISC_IDLE_STATUS = 0x0847; +constexpr unsigned int mmMC_HUB_MISC_OVERRIDE = 0x0833; +constexpr unsigned int mmMC_HUB_MISC_POWER = 0x082D; +constexpr unsigned int mmMC_HUB_MISC_SIP_CG = 0x0830; +constexpr unsigned int mmMC_HUB_MISC_STATUS = 0x0832; +constexpr unsigned int mmMC_HUB_MISC_VM_CG = 0x082F; +constexpr unsigned int mmMC_HUB_PERFCOUNTER0_CFG__CI__VI = 0x07B4; +constexpr unsigned int mmMC_HUB_PERFCOUNTER1_CFG__CI__VI = 0x07B5; +constexpr unsigned int mmMC_HUB_PERFCOUNTER2_CFG__CI__VI = 0x07B6; +constexpr unsigned int mmMC_HUB_PERFCOUNTER3_CFG__CI__VI = 0x07B7; +constexpr unsigned int mmMC_HUB_PERFCOUNTER_HI__CI__VI = 0x07A9; +constexpr unsigned int mmMC_HUB_PERFCOUNTER_LO__CI__VI = 0x07A1; +constexpr unsigned int mmMC_HUB_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07CF; +constexpr unsigned int mmMC_HUB_RDREQ_ACPG_LIMIT__CI__VI = 0x0849; +constexpr unsigned int mmMC_HUB_RDREQ_ACPG__CI = 0x0887; +constexpr unsigned int mmMC_HUB_RDREQ_ACPO__CI = 0x0888; +constexpr unsigned int mmMC_HUB_RDREQ_CNTL = 0x083B; +constexpr unsigned int mmMC_HUB_RDREQ_CPC__CI = 0x085A; +constexpr unsigned int mmMC_HUB_RDREQ_CPF__CI = 0x085B; +constexpr unsigned int mmMC_HUB_RDREQ_CPG__CI = 0x0859; +constexpr unsigned int mmMC_HUB_RDREQ_CP__SI = 0x0859; +constexpr unsigned int mmMC_HUB_RDREQ_CREDITS = 0x0844; +constexpr unsigned int mmMC_HUB_RDREQ_CREDITS2 = 0x0845; +constexpr unsigned int mmMC_HUB_RDREQ_DMIF_LIMIT = 0x0848; +constexpr unsigned int mmMC_HUB_RDREQ_DMIF__CI = 0x0865; +constexpr unsigned int mmMC_HUB_RDREQ_DMIF__SI = 0x0863; +constexpr unsigned int mmMC_HUB_RDREQ_GBL0 = 0x0856; +constexpr unsigned int mmMC_HUB_RDREQ_GBL1 = 0x0857; +constexpr unsigned int mmMC_HUB_RDREQ_HDP__CI = 0x085E; +constexpr unsigned int mmMC_HUB_RDREQ_HDP__SI = 0x085B; +constexpr unsigned int mmMC_HUB_RDREQ_IA0__CI = 0x084F; +constexpr unsigned int mmMC_HUB_RDREQ_IA1__CI = 0x0850; +constexpr unsigned int mmMC_HUB_RDREQ_IA__CI = 0x0864; +constexpr unsigned int mmMC_HUB_RDREQ_MCDW = 0x0851; +constexpr unsigned int mmMC_HUB_RDREQ_MCDX = 0x0852; +constexpr unsigned int mmMC_HUB_RDREQ_MCDY = 0x0853; +constexpr unsigned int mmMC_HUB_RDREQ_MCDZ = 0x0854; +constexpr unsigned int mmMC_HUB_RDREQ_MCIF__CI = 0x0866; +constexpr unsigned int mmMC_HUB_RDREQ_MCIF__SI = 0x0864; +constexpr unsigned int mmMC_HUB_RDREQ_RLC__CI = 0x085F; +constexpr unsigned int mmMC_HUB_RDREQ_RLC__SI = 0x085D; +constexpr unsigned int mmMC_HUB_RDREQ_SAM__CI = 0x0889; +constexpr unsigned int mmMC_HUB_RDREQ_SDMA0__CI = 0x085C; +constexpr unsigned int mmMC_HUB_RDREQ_SDMA1__CI = 0x085D; +constexpr unsigned int mmMC_HUB_RDREQ_SEM__CI = 0x0860; +constexpr unsigned int mmMC_HUB_RDREQ_SEM__SI = 0x085E; +constexpr unsigned int mmMC_HUB_RDREQ_SIP = 0x0855; +constexpr unsigned int mmMC_HUB_RDREQ_SMU = 0x0858; +constexpr unsigned int mmMC_HUB_RDREQ_STATUS = 0x0839; +constexpr unsigned int mmMC_HUB_RDREQ_UMC__CI = 0x0862; +constexpr unsigned int mmMC_HUB_RDREQ_UMC__SI = 0x0860; +constexpr unsigned int mmMC_HUB_RDREQ_UVD__CI = 0x0863; +constexpr unsigned int mmMC_HUB_RDREQ_UVD__SI = 0x0861; +constexpr unsigned int mmMC_HUB_RDREQ_VCEU__CI = 0x0868; +constexpr unsigned int mmMC_HUB_RDREQ_VCEU__SI = 0x0866; +constexpr unsigned int mmMC_HUB_RDREQ_VCE__CI = 0x0861; +constexpr unsigned int mmMC_HUB_RDREQ_VCE__SI = 0x085F; +constexpr unsigned int mmMC_HUB_RDREQ_VMC__CI = 0x0867; +constexpr unsigned int mmMC_HUB_RDREQ_VMC__SI = 0x0865; +constexpr unsigned int mmMC_HUB_RDREQ_WTM_CNTL = 0x083D; +constexpr unsigned int mmMC_HUB_RDREQ_XDMAM__CI = 0x0886; +constexpr unsigned int mmMC_HUB_RDREQ_XDMAM__SI = 0x0882; +constexpr unsigned int mmMC_HUB_SHARED_DAGB_DLY = 0x0846; +constexpr unsigned int mmMC_HUB_WDP_ACPG__CI = 0x088A; +constexpr unsigned int mmMC_HUB_WDP_ACPO__CI = 0x088B; +constexpr unsigned int mmMC_HUB_WDP_BP = 0x0837; +constexpr unsigned int mmMC_HUB_WDP_CNTL = 0x0835; +constexpr unsigned int mmMC_HUB_WDP_CPC__CI = 0x086F; +constexpr unsigned int mmMC_HUB_WDP_CPF__CI = 0x0870; +constexpr unsigned int mmMC_HUB_WDP_CPG__CI = 0x086E; +constexpr unsigned int mmMC_HUB_WDP_CP__SI = 0x086C; +constexpr unsigned int mmMC_HUB_WDP_CREDITS = 0x083F; +constexpr unsigned int mmMC_HUB_WDP_ERR = 0x0836; +constexpr unsigned int mmMC_HUB_WDP_GBL0 = 0x0841; +constexpr unsigned int mmMC_HUB_WDP_GBL1 = 0x0842; +constexpr unsigned int mmMC_HUB_WDP_HDP__CI = 0x087C; +constexpr unsigned int mmMC_HUB_WDP_HDP__SI = 0x0879; +constexpr unsigned int mmMC_HUB_WDP_IH__CI = 0x0875; +constexpr unsigned int mmMC_HUB_WDP_IH__SI = 0x0872; +constexpr unsigned int mmMC_HUB_WDP_MCDW__CI = 0x0869; +constexpr unsigned int mmMC_HUB_WDP_MCDW__SI = 0x0867; +constexpr unsigned int mmMC_HUB_WDP_MCDX__CI = 0x086A; +constexpr unsigned int mmMC_HUB_WDP_MCDX__SI = 0x0868; +constexpr unsigned int mmMC_HUB_WDP_MCDY__CI = 0x086B; +constexpr unsigned int mmMC_HUB_WDP_MCDY__SI = 0x0869; +constexpr unsigned int mmMC_HUB_WDP_MCDZ__CI = 0x086C; +constexpr unsigned int mmMC_HUB_WDP_MCDZ__SI = 0x086A; +constexpr unsigned int mmMC_HUB_WDP_MCIF__CI = 0x0872; +constexpr unsigned int mmMC_HUB_WDP_MCIF__SI = 0x086F; +constexpr unsigned int mmMC_HUB_WDP_MGPU__SI__CI = 0x0843; +constexpr unsigned int mmMC_HUB_WDP_MGPU2__SI__CI = 0x0840; +constexpr unsigned int mmMC_HUB_WDP_RLC__CI = 0x0876; +constexpr unsigned int mmMC_HUB_WDP_RLC__SI = 0x0873; +constexpr unsigned int mmMC_HUB_WDP_SAM__CI = 0x088C; +constexpr unsigned int mmMC_HUB_WDP_SDMA0__CI = 0x087D; +constexpr unsigned int mmMC_HUB_WDP_SDMA1__CI = 0x087E; +constexpr unsigned int mmMC_HUB_WDP_SEM__CI = 0x0877; +constexpr unsigned int mmMC_HUB_WDP_SEM__SI = 0x0874; +constexpr unsigned int mmMC_HUB_WDP_SH0__CI = 0x0871; +constexpr unsigned int mmMC_HUB_WDP_SH0__SI = 0x086E; +constexpr unsigned int mmMC_HUB_WDP_SH1__CI = 0x0879; +constexpr unsigned int mmMC_HUB_WDP_SH1__SI = 0x0876; +constexpr unsigned int mmMC_HUB_WDP_SH2__CI__VI = 0x084D; +constexpr unsigned int mmMC_HUB_WDP_SH3__CI__VI = 0x084E; +constexpr unsigned int mmMC_HUB_WDP_SIP__CI = 0x086D; +constexpr unsigned int mmMC_HUB_WDP_SIP__SI = 0x086B; +constexpr unsigned int mmMC_HUB_WDP_SMU__CI = 0x0878; +constexpr unsigned int mmMC_HUB_WDP_SMU__SI = 0x0875; +constexpr unsigned int mmMC_HUB_WDP_STATUS = 0x0838; +constexpr unsigned int mmMC_HUB_WDP_UMC__CI = 0x087A; +constexpr unsigned int mmMC_HUB_WDP_UMC__SI = 0x0877; +constexpr unsigned int mmMC_HUB_WDP_UVD__CI = 0x087B; +constexpr unsigned int mmMC_HUB_WDP_UVD__SI = 0x0878; +constexpr unsigned int mmMC_HUB_WDP_VCEU__CI = 0x0883; +constexpr unsigned int mmMC_HUB_WDP_VCEU__SI = 0x087F; +constexpr unsigned int mmMC_HUB_WDP_VCE__CI = 0x0873; +constexpr unsigned int mmMC_HUB_WDP_VCE__SI = 0x0870; +constexpr unsigned int mmMC_HUB_WDP_WTM_CNTL = 0x083E; +constexpr unsigned int mmMC_HUB_WDP_XDMAM__CI = 0x0884; +constexpr unsigned int mmMC_HUB_WDP_XDMAM__SI = 0x0880; +constexpr unsigned int mmMC_HUB_WDP_XDMA__CI = 0x0885; +constexpr unsigned int mmMC_HUB_WDP_XDMA__SI = 0x0881; +constexpr unsigned int mmMC_HUB_WDP_XDP__CI = 0x0874; +constexpr unsigned int mmMC_HUB_WDP_XDP__SI = 0x0871; +constexpr unsigned int mmMC_HUB_WRRET_CNTL = 0x083C; +constexpr unsigned int mmMC_HUB_WRRET_MCDW__CI = 0x087F; +constexpr unsigned int mmMC_HUB_WRRET_MCDW__SI = 0x087B; +constexpr unsigned int mmMC_HUB_WRRET_MCDX__CI = 0x0880; +constexpr unsigned int mmMC_HUB_WRRET_MCDX__SI = 0x087C; +constexpr unsigned int mmMC_HUB_WRRET_MCDY__CI = 0x0881; +constexpr unsigned int mmMC_HUB_WRRET_MCDY__SI = 0x087D; +constexpr unsigned int mmMC_HUB_WRRET_MCDZ__CI = 0x0882; +constexpr unsigned int mmMC_HUB_WRRET_MCDZ__SI = 0x087E; +constexpr unsigned int mmMC_HUB_WRRET_STATUS = 0x083A; +constexpr unsigned int mmMC_IMP_CNTL__SI__CI = 0x0A36; +constexpr unsigned int mmMC_IMP_DEBUG__SI__CI = 0x0A37; +constexpr unsigned int mmMC_IMP_DQ_STATUS__SI__CI = 0x0ABC; +constexpr unsigned int mmMC_IMP_STATUS__SI__CI = 0x0A38; +constexpr unsigned int mmMC_IO_APHY_STR_CNTL_D0__SI__CI = 0x0A97; +constexpr unsigned int mmMC_IO_APHY_STR_CNTL_D1__SI__CI = 0x0A98; +constexpr unsigned int mmMC_IO_CDRCNTL1_D0__SI__CI = 0x0ADD; +constexpr unsigned int mmMC_IO_CDRCNTL1_D1__SI__CI = 0x0ADE; +constexpr unsigned int mmMC_IO_CDRCNTL2_D0__SI__CI = 0x0AE4; +constexpr unsigned int mmMC_IO_CDRCNTL2_D1__SI__CI = 0x0AE5; +constexpr unsigned int mmMC_IO_CDRCNTL_D0__SI__CI = 0x0A55; +constexpr unsigned int mmMC_IO_CDRCNTL_D1__SI__CI = 0x0A56; +constexpr unsigned int mmMC_IO_DPHY_STR_CNTL_D0__SI__CI = 0x0A4E; +constexpr unsigned int mmMC_IO_DPHY_STR_CNTL_D1__SI__CI = 0x0A54; +constexpr unsigned int mmMC_IO_PAD_CNTL__SI__CI = 0x0A73; +constexpr unsigned int mmMC_IO_PAD_CNTL_D0__SI__CI = 0x0A74; +constexpr unsigned int mmMC_IO_PAD_CNTL_D1__SI__CI = 0x0A75; +constexpr unsigned int mmMC_IO_RXCNTL1_DPHY0_D0__SI__CI = 0x0ADF; +constexpr unsigned int mmMC_IO_RXCNTL1_DPHY0_D1__SI__CI = 0x0AE1; +constexpr unsigned int mmMC_IO_RXCNTL1_DPHY1_D0__SI__CI = 0x0AE0; +constexpr unsigned int mmMC_IO_RXCNTL1_DPHY1_D1__SI__CI = 0x0AE2; +constexpr unsigned int mmMC_IO_RXCNTL_DPHY0_D0__SI__CI = 0x0A4C; +constexpr unsigned int mmMC_IO_RXCNTL_DPHY0_D1__SI__CI = 0x0A52; +constexpr unsigned int mmMC_IO_RXCNTL_DPHY1_D0__SI__CI = 0x0A4D; +constexpr unsigned int mmMC_IO_RXCNTL_DPHY1_D1__SI__CI = 0x0A53; +constexpr unsigned int mmMC_IO_TXCNTL_APHY_D0__SI__CI = 0x0A4B; +constexpr unsigned int mmMC_IO_TXCNTL_APHY_D1__SI__CI = 0x0A51; +constexpr unsigned int mmMC_IO_TXCNTL_DPHY0_D0__SI__CI = 0x0A49; +constexpr unsigned int mmMC_IO_TXCNTL_DPHY0_D1__SI__CI = 0x0A4F; +constexpr unsigned int mmMC_IO_TXCNTL_DPHY1_D0__SI__CI = 0x0A4A; +constexpr unsigned int mmMC_IO_TXCNTL_DPHY1_D1__SI__CI = 0x0A50; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER0_CFG__CI__VI = 0x07C0; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER1_CFG__CI__VI = 0x07C1; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER2_CFG__CI__VI = 0x07C2; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER3_CFG__CI__VI = 0x07C3; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER_HI__CI__VI = 0x07AA; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER_LO__CI__VI = 0x07A3; +constexpr unsigned int mmMC_MCBVM_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07D1; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER0_CFG__CI__VI = 0x07C4; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER1_CFG__CI__VI = 0x07C5; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER2_CFG__CI__VI = 0x07C6; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER3_CFG__CI__VI = 0x07C7; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER_HI__CI__VI = 0x07AB; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER_LO__CI__VI = 0x07A4; +constexpr unsigned int mmMC_MCDVM_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07D2; +constexpr unsigned int mmMC_MEM_POWER_LS = 0x082A; +constexpr unsigned int mmMC_NPL_STATUS__SI__CI = 0x0A76; +constexpr unsigned int mmMC_PHY_TIMING_2__SI__CI = 0x0ACE; +constexpr unsigned int mmMC_PHY_TIMING_D0__SI__CI = 0x0ACC; +constexpr unsigned int mmMC_PHY_TIMING_D1__SI__CI = 0x0ACD; +constexpr unsigned int mmMC_PMG_AUTO_CFG__SI__CI = 0x0A35; +constexpr unsigned int mmMC_PMG_AUTO_CMD__SI__CI = 0x0A34; +constexpr unsigned int mmMC_RD_CB = 0x0981; +constexpr unsigned int mmMC_RD_DB = 0x0982; +constexpr unsigned int mmMC_RD_GRP_EXT = 0x0978; +constexpr unsigned int mmMC_RD_GRP_GFX = 0x0803; +constexpr unsigned int mmMC_RD_GRP_LCL = 0x098A; +constexpr unsigned int mmMC_RD_GRP_OTH = 0x0807; +constexpr unsigned int mmMC_RD_GRP_SYS = 0x0805; +constexpr unsigned int mmMC_RD_HUB = 0x0985; +constexpr unsigned int mmMC_RD_TC0 = 0x0983; +constexpr unsigned int mmMC_RD_TC1 = 0x0984; +constexpr unsigned int mmMC_RPB_ARB_CNTL = 0x0951; +constexpr unsigned int mmMC_RPB_BIF_CNTL = 0x0952; +constexpr unsigned int mmMC_RPB_CID_QUEUE_EX = 0x095A; +constexpr unsigned int mmMC_RPB_CID_QUEUE_EX_DATA = 0x095B; +constexpr unsigned int mmMC_RPB_CID_QUEUE_RD = 0x0957; +constexpr unsigned int mmMC_RPB_CID_QUEUE_WR = 0x0956; +constexpr unsigned int mmMC_RPB_CONF = 0x094D; +constexpr unsigned int mmMC_RPB_DBG1 = 0x094F; +constexpr unsigned int mmMC_RPB_EFF_CNTL = 0x0950; +constexpr unsigned int mmMC_RPB_IF_CONF = 0x094E; +constexpr unsigned int mmMC_RPB_PERFCOUNTER0_CFG__CI__VI = 0x07B8; +constexpr unsigned int mmMC_RPB_PERFCOUNTER1_CFG__CI__VI = 0x07B9; +constexpr unsigned int mmMC_RPB_PERFCOUNTER2_CFG__CI__VI = 0x07BA; +constexpr unsigned int mmMC_RPB_PERFCOUNTER3_CFG__CI__VI = 0x07BB; +constexpr unsigned int mmMC_RPB_PERFCOUNTER_HI__CI__VI = 0x07AC; +constexpr unsigned int mmMC_RPB_PERFCOUNTER_LO__CI__VI = 0x07A2; +constexpr unsigned int mmMC_RPB_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07D0; +constexpr unsigned int mmMC_RPB_PERF_COUNTER_CNTL = 0x0958; +constexpr unsigned int mmMC_RPB_PERF_COUNTER_STATUS = 0x0959; +constexpr unsigned int mmMC_RPB_RD_SWITCH_CNTL = 0x0955; +constexpr unsigned int mmMC_RPB_WR_COMBINE_CNTL = 0x0954; +constexpr unsigned int mmMC_RPB_WR_SWITCH_CNTL = 0x0953; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B0_D0__SI__CI = 0x0AA3; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B0_D1__SI__CI = 0x0AA7; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B1_D0__SI__CI = 0x0AA4; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B1_D1__SI__CI = 0x0AA8; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B2_D0__SI__CI = 0x0AA5; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B2_D1__SI__CI = 0x0AA9; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B3_D0__SI__CI = 0x0AA6; +constexpr unsigned int mmMC_SEQ_BIT_REMAP_B3_D1__SI__CI = 0x0AAA; +constexpr unsigned int mmMC_SEQ_BYTE_REMAP_D0__SI__CI = 0x0A93; +constexpr unsigned int mmMC_SEQ_BYTE_REMAP_D1__SI__CI = 0x0A94; +constexpr unsigned int mmMC_SEQ_CNTL_3__CI = 0x0D80; +constexpr unsigned int mmMC_SEQ_DLL_STBY_LP__CI = 0x0D8F; +constexpr unsigned int mmMC_SEQ_DLL_STBY__CI = 0x0D8E; +constexpr unsigned int mmMC_SEQ_DRAM_ERROR_INSERTION__SI__CI = 0x0ACB; +constexpr unsigned int mmMC_SEQ_G5PDX_CMD0_LP__CI = 0x0D84; +constexpr unsigned int mmMC_SEQ_G5PDX_CMD0__CI = 0x0D83; +constexpr unsigned int mmMC_SEQ_G5PDX_CMD1_LP__CI = 0x0D86; +constexpr unsigned int mmMC_SEQ_G5PDX_CMD1__CI = 0x0D85; +constexpr unsigned int mmMC_SEQ_G5PDX_CTRL_LP__CI = 0x0D82; +constexpr unsigned int mmMC_SEQ_G5PDX_CTRL__CI = 0x0D81; +constexpr unsigned int mmMC_SEQ_IO_RDBI__SI__CI = 0x0AB4; +constexpr unsigned int mmMC_SEQ_IO_REDC__SI__CI = 0x0AB5; +constexpr unsigned int mmMC_SEQ_IO_RESERVE_D0__SI__CI = 0x0AB7; +constexpr unsigned int mmMC_SEQ_IO_RESERVE_D1__SI__CI = 0x0AB8; +constexpr unsigned int mmMC_SEQ_IO_RWORD0__SI__CI = 0x0AAC; +constexpr unsigned int mmMC_SEQ_IO_RWORD1__SI__CI = 0x0AAD; +constexpr unsigned int mmMC_SEQ_IO_RWORD2__SI__CI = 0x0AAE; +constexpr unsigned int mmMC_SEQ_IO_RWORD3__SI__CI = 0x0AAF; +constexpr unsigned int mmMC_SEQ_IO_RWORD4__SI__CI = 0x0AB0; +constexpr unsigned int mmMC_SEQ_IO_RWORD5__SI__CI = 0x0AB1; +constexpr unsigned int mmMC_SEQ_IO_RWORD6__SI__CI = 0x0AB2; +constexpr unsigned int mmMC_SEQ_IO_RWORD7__SI__CI = 0x0AB3; +constexpr unsigned int mmMC_SEQ_MPLL_OVERRIDE__SI__CI = 0x0A22; +constexpr unsigned int mmMC_SEQ_PERF_CNTL__SI__CI = 0x0A77; +constexpr unsigned int mmMC_SEQ_PERF_CNTL_1__SI__CI = 0x0AFD; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_A_I0__SI__CI = 0x0A79; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_A_I1__SI__CI = 0x0A7A; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_B_I0__SI__CI = 0x0A7B; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_B_I1__SI__CI = 0x0A7C; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_C_I0__SI__CI = 0x0AD9; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_C_I1__SI__CI = 0x0ADA; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_D_I0__SI__CI = 0x0ADB; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CNT_D_I1__SI__CI = 0x0ADC; +constexpr unsigned int mmMC_SEQ_PERF_SEQ_CTL__SI__CI = 0x0A78; +constexpr unsigned int mmMC_SEQ_PHYREG_BCAST__CI = 0x0D89; +constexpr unsigned int mmMC_SEQ_PMG_CMD_EMRS_LP__SI__CI = 0x0AA1; +constexpr unsigned int mmMC_SEQ_PMG_CMD_MRS1_LP__SI__CI = 0x0AD2; +constexpr unsigned int mmMC_SEQ_PMG_CMD_MRS2_LP__SI__CI = 0x0AD8; +constexpr unsigned int mmMC_SEQ_PMG_CMD_MRS_LP__SI__CI = 0x0AA2; +constexpr unsigned int mmMC_SEQ_PMG_DVS_CMD_LP__CI = 0x0D8D; +constexpr unsigned int mmMC_SEQ_PMG_DVS_CMD__CI = 0x0D8C; +constexpr unsigned int mmMC_SEQ_PMG_DVS_CTL_LP__CI = 0x0D8B; +constexpr unsigned int mmMC_SEQ_PMG_DVS_CTL__CI = 0x0D8A; +constexpr unsigned int mmMC_SEQ_PMG_PG_HWCNTL__SI__CI = 0x0AB9; +constexpr unsigned int mmMC_SEQ_PMG_PG_SWCNTL_0__SI__CI = 0x0ABA; +constexpr unsigned int mmMC_SEQ_PMG_PG_SWCNTL_1__SI__CI = 0x0ABB; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE0_D0__SI__CI = 0x0A67; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE0_D1__SI__CI = 0x0A6D; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE1_D0__SI__CI = 0x0A68; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE1_D1__SI__CI = 0x0A6E; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE2_D0__SI__CI = 0x0A69; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE2_D1__SI__CI = 0x0A6F; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE3_D0__SI__CI = 0x0A6A; +constexpr unsigned int mmMC_SEQ_RXFRAMING_BYTE3_D1__SI__CI = 0x0A70; +constexpr unsigned int mmMC_SEQ_RXFRAMING_DBI_D0__SI__CI = 0x0A6B; +constexpr unsigned int mmMC_SEQ_RXFRAMING_DBI_D1__SI__CI = 0x0A71; +constexpr unsigned int mmMC_SEQ_RXFRAMING_EDC_D0__SI__CI = 0x0A6C; +constexpr unsigned int mmMC_SEQ_RXFRAMING_EDC_D1__SI__CI = 0x0A72; +constexpr unsigned int mmMC_SEQ_SREG_READ__CI = 0x0D87; +constexpr unsigned int mmMC_SEQ_SREG_STATUS__CI = 0x0D88; +constexpr unsigned int mmMC_SEQ_TCG_CNTL__SI__CI = 0x0ABD; +constexpr unsigned int mmMC_SEQ_TRAIN_EDC_THRESHOLD__SI__CI = 0x0A3B; +constexpr unsigned int mmMC_SEQ_TRAIN_EDC_THRESHOLD2__SI__CI = 0x0AFE; +constexpr unsigned int mmMC_SEQ_TRAIN_EDC_THRESHOLD3__SI__CI = 0x0AFF; +constexpr unsigned int mmMC_SEQ_TRAIN_TIMING__SI__CI = 0x0A40; +constexpr unsigned int mmMC_SEQ_TSM_BCNT__SI__CI = 0x0AC2; +constexpr unsigned int mmMC_SEQ_TSM_CTRL__SI__CI = 0x0ABE; +constexpr unsigned int mmMC_SEQ_TSM_DBI__SI__CI = 0x0AC6; +constexpr unsigned int mmMC_SEQ_TSM_DEBUG_DATA__SI__CI = 0x0AD0; +constexpr unsigned int mmMC_SEQ_TSM_DEBUG_INDEX__SI__CI = 0x0ACF; +constexpr unsigned int mmMC_SEQ_TSM_EDC__SI__CI = 0x0AC5; +constexpr unsigned int mmMC_SEQ_TSM_FLAG__SI__CI = 0x0AC3; +constexpr unsigned int mmMC_SEQ_TSM_GCNT__SI__CI = 0x0ABF; +constexpr unsigned int mmMC_SEQ_TSM_MISC__SI__CI = 0x0AE6; +constexpr unsigned int mmMC_SEQ_TSM_NCNT__SI__CI = 0x0AC1; +constexpr unsigned int mmMC_SEQ_TSM_OCNT__SI__CI = 0x0AC0; +constexpr unsigned int mmMC_SEQ_TSM_UPDATE__SI__CI = 0x0AC4; +constexpr unsigned int mmMC_SEQ_TSM_WCDR__SI__CI = 0x0AE3; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE0_D0__SI__CI = 0x0A58; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE0_D1__SI__CI = 0x0A60; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE1_D0__SI__CI = 0x0A59; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE1_D1__SI__CI = 0x0A61; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE2_D0__SI__CI = 0x0A5A; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE2_D1__SI__CI = 0x0A62; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE3_D0__SI__CI = 0x0A5B; +constexpr unsigned int mmMC_SEQ_TXFRAMING_BYTE3_D1__SI__CI = 0x0A63; +constexpr unsigned int mmMC_SEQ_TXFRAMING_DBI_D0__SI__CI = 0x0A5C; +constexpr unsigned int mmMC_SEQ_TXFRAMING_DBI_D1__SI__CI = 0x0A64; +constexpr unsigned int mmMC_SEQ_TXFRAMING_EDC_D0__SI__CI = 0x0A5D; +constexpr unsigned int mmMC_SEQ_TXFRAMING_EDC_D1__SI__CI = 0x0A65; +constexpr unsigned int mmMC_SEQ_TXFRAMING_FCK_D0__SI__CI = 0x0A5E; +constexpr unsigned int mmMC_SEQ_TXFRAMING_FCK_D1__SI__CI = 0x0A66; +constexpr unsigned int mmMC_SEQ_VENDOR_ID_I0__SI__CI = 0x0A7E; +constexpr unsigned int mmMC_SEQ_VENDOR_ID_I1__SI__CI = 0x0A7F; +constexpr unsigned int mmMC_SEQ_WCDR_CTRL__SI__CI = 0x0A39; +constexpr unsigned int mmMC_SEQ_WR_CTL_2__SI__CI = 0x0AD5; +constexpr unsigned int mmMC_SEQ_WR_CTL_2_LP__SI__CI = 0x0AD6; +constexpr unsigned int mmMC_SHARED_BLACKOUT_CNTL = 0x082B; +constexpr unsigned int mmMC_SHARED_CHMAP = 0x0801; +constexpr unsigned int mmMC_SHARED_CHREMAP = 0x0802; +constexpr unsigned int mmMC_TRAIN_EDCCDR_R_D0__SI__CI = 0x0A41; +constexpr unsigned int mmMC_TRAIN_EDCCDR_R_D1__SI__CI = 0x0A42; +constexpr unsigned int mmMC_TRAIN_EDC_STATUS_D0__SI__CI = 0x0A45; +constexpr unsigned int mmMC_TRAIN_EDC_STATUS_D1__SI__CI = 0x0A48; +constexpr unsigned int mmMC_TRAIN_PRBSERR_0_D0__SI__CI = 0x0A43; +constexpr unsigned int mmMC_TRAIN_PRBSERR_0_D1__SI__CI = 0x0A46; +constexpr unsigned int mmMC_TRAIN_PRBSERR_1_D0__SI__CI = 0x0A44; +constexpr unsigned int mmMC_TRAIN_PRBSERR_1_D1__SI__CI = 0x0A47; +constexpr unsigned int mmMC_TRAIN_PRBSERR_2_D0__SI__CI = 0x0AFB; +constexpr unsigned int mmMC_TRAIN_PRBSERR_2_D1__SI__CI = 0x0AFC; +constexpr unsigned int mmMC_VM_AGP_BASE = 0x080C; +constexpr unsigned int mmMC_VM_AGP_BOT = 0x080B; +constexpr unsigned int mmMC_VM_AGP_TOP = 0x080A; +constexpr unsigned int mmMC_VM_DC_WRITE_CNTL = 0x0810; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR = 0x0815; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR = 0x0811; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR = 0x0816; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR = 0x0812; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR = 0x0817; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR = 0x0813; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR = 0x0818; +constexpr unsigned int mmMC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR = 0x0814; +constexpr unsigned int mmMC_VM_FB_LOCATION = 0x0809; +constexpr unsigned int mmMC_VM_FB_OFFSET = 0x081A; +constexpr unsigned int mmMC_VM_L2_PERFCOUNTER0_CFG__CI__VI = 0x07CC; +constexpr unsigned int mmMC_VM_L2_PERFCOUNTER1_CFG__CI__VI = 0x07CD; +constexpr unsigned int mmMC_VM_L2_PERFCOUNTER_HI__CI__VI = 0x07AD; +constexpr unsigned int mmMC_VM_L2_PERFCOUNTER_LO__CI__VI = 0x07A5; +constexpr unsigned int mmMC_VM_L2_PERFCOUNTER_RSLT_CNTL__CI__VI = 0x07D3; +constexpr unsigned int mmMC_VM_MB_L1_TLB0_DEBUG = 0x0891; +constexpr unsigned int mmMC_VM_MB_L1_TLB0_STATUS = 0x0895; +constexpr unsigned int mmMC_VM_MB_L1_TLB1_STATUS = 0x0896; +constexpr unsigned int mmMC_VM_MB_L1_TLB2_DEBUG = 0x0893; +constexpr unsigned int mmMC_VM_MB_L1_TLB2_STATUS = 0x0897; +constexpr unsigned int mmMC_VM_MB_L1_TLB3_DEBUG = 0x08A5; +constexpr unsigned int mmMC_VM_MB_L1_TLB3_STATUS = 0x08A6; +constexpr unsigned int mmMC_VM_MB_L2ARBITER_L2_CREDITS = 0x08A1; +constexpr unsigned int mmMC_VM_MD_L1_TLB0_DEBUG = 0x0998; +constexpr unsigned int mmMC_VM_MD_L1_TLB0_STATUS = 0x099B; +constexpr unsigned int mmMC_VM_MD_L1_TLB1_DEBUG = 0x0999; +constexpr unsigned int mmMC_VM_MD_L1_TLB1_STATUS = 0x099C; +constexpr unsigned int mmMC_VM_MD_L1_TLB2_DEBUG = 0x099A; +constexpr unsigned int mmMC_VM_MD_L1_TLB2_STATUS = 0x099D; +constexpr unsigned int mmMC_VM_MD_L1_TLB3_DEBUG = 0x09A7; +constexpr unsigned int mmMC_VM_MD_L1_TLB3_STATUS = 0x09A8; +constexpr unsigned int mmMC_VM_MD_L2ARBITER_L2_CREDITS = 0x09A4; +constexpr unsigned int mmMC_VM_MX_L1_TLB_CNTL = 0x0819; +constexpr unsigned int mmMC_VM_STEERING__CI__VI = 0x081B; +constexpr unsigned int mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR = 0x080F; +constexpr unsigned int mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR = 0x080E; +constexpr unsigned int mmMC_VM_SYSTEM_APERTURE_LOW_ADDR = 0x080D; +constexpr unsigned int mmMC_WR_CB = 0x0986; +constexpr unsigned int mmMC_WR_DB = 0x0987; +constexpr unsigned int mmMC_WR_GRP_EXT = 0x0979; +constexpr unsigned int mmMC_WR_GRP_GFX = 0x0804; +constexpr unsigned int mmMC_WR_GRP_LCL = 0x098B; +constexpr unsigned int mmMC_WR_GRP_OTH = 0x0808; +constexpr unsigned int mmMC_WR_GRP_SYS = 0x0806; +constexpr unsigned int mmMC_WR_HUB = 0x0988; +constexpr unsigned int mmMC_WR_TC0 = 0x097B; +constexpr unsigned int mmMC_WR_TC1 = 0x097C; +constexpr unsigned int mmMC_XBAR_ADDR_DEC = 0x0C80; +constexpr unsigned int mmMC_XBAR_ARB = 0x0C8D; +constexpr unsigned int mmMC_XBAR_ARB_MAX_BURST = 0x0C8E; +constexpr unsigned int mmMC_XBAR_CHTRIREMAP = 0x0C8B; +constexpr unsigned int mmMC_XBAR_PERF_MON_CNTL0__SI__CI = 0x0C8F; +constexpr unsigned int mmMC_XBAR_PERF_MON_CNTL1__SI__CI = 0x0C90; +constexpr unsigned int mmMC_XBAR_PERF_MON_CNTL2__SI__CI = 0x0C91; +constexpr unsigned int mmMC_XBAR_PERF_MON_MAX_THSH__SI__CI = 0x0C96; +constexpr unsigned int mmMC_XBAR_PERF_MON_RSLT0__SI__CI = 0x0C92; +constexpr unsigned int mmMC_XBAR_PERF_MON_RSLT1__SI__CI = 0x0C93; +constexpr unsigned int mmMC_XBAR_PERF_MON_RSLT2__SI__CI = 0x0C94; +constexpr unsigned int mmMC_XBAR_PERF_MON_RSLT3__SI__CI = 0x0C95; +constexpr unsigned int mmMC_XBAR_RDREQ_CREDIT = 0x0C83; +constexpr unsigned int mmMC_XBAR_RDREQ_PRI_CREDIT = 0x0C84; +constexpr unsigned int mmMC_XBAR_RDRET_CREDIT1 = 0x0C87; +constexpr unsigned int mmMC_XBAR_RDRET_CREDIT2 = 0x0C88; +constexpr unsigned int mmMC_XBAR_RDRET_PRI_CREDIT1 = 0x0C89; +constexpr unsigned int mmMC_XBAR_RDRET_PRI_CREDIT2 = 0x0C8A; +constexpr unsigned int mmMC_XBAR_REMOTE = 0x0C81; +constexpr unsigned int mmMC_XBAR_SPARE0 = 0x0C97; +constexpr unsigned int mmMC_XBAR_SPARE1 = 0x0C98; +constexpr unsigned int mmMC_XBAR_TWOCHAN = 0x0C8C; +constexpr unsigned int mmMC_XBAR_WRREQ_CREDIT = 0x0C82; +constexpr unsigned int mmMC_XBAR_WRRET_CREDIT1 = 0x0C85; +constexpr unsigned int mmMC_XBAR_WRRET_CREDIT2 = 0x0C86; +constexpr unsigned int mmMC_XPB_CLG_CFG0 = 0x08E9; +constexpr unsigned int mmMC_XPB_CLG_CFG1 = 0x08EA; +constexpr unsigned int mmMC_XPB_CLG_CFG10 = 0x08F3; +constexpr unsigned int mmMC_XPB_CLG_CFG11 = 0x08F4; +constexpr unsigned int mmMC_XPB_CLG_CFG12 = 0x08F5; +constexpr unsigned int mmMC_XPB_CLG_CFG13 = 0x08F6; +constexpr unsigned int mmMC_XPB_CLG_CFG14 = 0x08F7; +constexpr unsigned int mmMC_XPB_CLG_CFG15 = 0x08F8; +constexpr unsigned int mmMC_XPB_CLG_CFG16 = 0x08F9; +constexpr unsigned int mmMC_XPB_CLG_CFG17 = 0x08FA; +constexpr unsigned int mmMC_XPB_CLG_CFG18 = 0x08FB; +constexpr unsigned int mmMC_XPB_CLG_CFG19 = 0x08FC; +constexpr unsigned int mmMC_XPB_CLG_CFG2 = 0x08EB; +constexpr unsigned int mmMC_XPB_CLG_CFG20 = 0x0928; +constexpr unsigned int mmMC_XPB_CLG_CFG21 = 0x0929; +constexpr unsigned int mmMC_XPB_CLG_CFG22 = 0x092A; +constexpr unsigned int mmMC_XPB_CLG_CFG23 = 0x092B; +constexpr unsigned int mmMC_XPB_CLG_CFG24 = 0x092C; +constexpr unsigned int mmMC_XPB_CLG_CFG25 = 0x092D; +constexpr unsigned int mmMC_XPB_CLG_CFG26 = 0x092E; +constexpr unsigned int mmMC_XPB_CLG_CFG27 = 0x092F; +constexpr unsigned int mmMC_XPB_CLG_CFG28 = 0x0930; +constexpr unsigned int mmMC_XPB_CLG_CFG29 = 0x0931; +constexpr unsigned int mmMC_XPB_CLG_CFG3 = 0x08EC; +constexpr unsigned int mmMC_XPB_CLG_CFG30 = 0x0932; +constexpr unsigned int mmMC_XPB_CLG_CFG31 = 0x0933; +constexpr unsigned int mmMC_XPB_CLG_CFG32 = 0x0936; +constexpr unsigned int mmMC_XPB_CLG_CFG33 = 0x0937; +constexpr unsigned int mmMC_XPB_CLG_CFG34 = 0x0938; +constexpr unsigned int mmMC_XPB_CLG_CFG35 = 0x0939; +constexpr unsigned int mmMC_XPB_CLG_CFG36 = 0x093A; +constexpr unsigned int mmMC_XPB_CLG_CFG4 = 0x08ED; +constexpr unsigned int mmMC_XPB_CLG_CFG5 = 0x08EE; +constexpr unsigned int mmMC_XPB_CLG_CFG6 = 0x08EF; +constexpr unsigned int mmMC_XPB_CLG_CFG7 = 0x08F0; +constexpr unsigned int mmMC_XPB_CLG_CFG8 = 0x08F1; +constexpr unsigned int mmMC_XPB_CLG_CFG9 = 0x08F2; +constexpr unsigned int mmMC_XPB_CLG_EXTRA = 0x08FD; +constexpr unsigned int mmMC_XPB_CLG_EXTRA_RD = 0x0935; +constexpr unsigned int mmMC_XPB_CLK_GAT = 0x091E; +constexpr unsigned int mmMC_XPB_INTF_CFG = 0x091F; +constexpr unsigned int mmMC_XPB_INTF_CFG2 = 0x0934; +constexpr unsigned int mmMC_XPB_INTF_STS = 0x0920; +constexpr unsigned int mmMC_XPB_LB_ADDR = 0x08FE; +constexpr unsigned int mmMC_XPB_MAP_INVERT_FLUSH_NUM_LSB = 0x0923; +constexpr unsigned int mmMC_XPB_MISC_CFG = 0x0927; +constexpr unsigned int mmMC_XPB_P2P_BAR0 = 0x0904; +constexpr unsigned int mmMC_XPB_P2P_BAR1 = 0x0905; +constexpr unsigned int mmMC_XPB_P2P_BAR2 = 0x0906; +constexpr unsigned int mmMC_XPB_P2P_BAR3 = 0x0907; +constexpr unsigned int mmMC_XPB_P2P_BAR4 = 0x0908; +constexpr unsigned int mmMC_XPB_P2P_BAR5 = 0x0909; +constexpr unsigned int mmMC_XPB_P2P_BAR6 = 0x090A; +constexpr unsigned int mmMC_XPB_P2P_BAR7 = 0x090B; +constexpr unsigned int mmMC_XPB_P2P_BAR_CFG = 0x0903; +constexpr unsigned int mmMC_XPB_P2P_BAR_DEBUG = 0x090D; +constexpr unsigned int mmMC_XPB_P2P_BAR_DELTA_ABOVE = 0x090E; +constexpr unsigned int mmMC_XPB_P2P_BAR_DELTA_BELOW = 0x090F; +constexpr unsigned int mmMC_XPB_P2P_BAR_SETUP = 0x090C; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR0 = 0x0910; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR1 = 0x0911; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR2 = 0x0912; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR3 = 0x0913; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR4 = 0x0914; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR5 = 0x0915; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR6 = 0x0916; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR7 = 0x0917; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR8 = 0x0918; +constexpr unsigned int mmMC_XPB_PEER_SYS_BAR9 = 0x0919; +constexpr unsigned int mmMC_XPB_PERF_KNOBS = 0x0924; +constexpr unsigned int mmMC_XPB_PIPE_STS = 0x0921; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP0 = 0x08DB; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP1 = 0x08DC; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP2 = 0x08DD; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP3 = 0x08DE; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP4 = 0x08DF; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP5 = 0x08E0; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP6 = 0x08E1; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP7 = 0x08E2; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP8 = 0x08E3; +constexpr unsigned int mmMC_XPB_RTR_DEST_MAP9 = 0x08E4; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR0 = 0x08CD; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR1 = 0x08CE; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR2 = 0x08CF; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR3 = 0x08D0; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR4 = 0x08D1; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR5 = 0x08D2; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR6 = 0x08D3; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR7 = 0x08D4; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR8 = 0x08D5; +constexpr unsigned int mmMC_XPB_RTR_SRC_APRTR9 = 0x08D6; +constexpr unsigned int mmMC_XPB_STICKY = 0x0925; +constexpr unsigned int mmMC_XPB_STICKY_W1C = 0x0926; +constexpr unsigned int mmMC_XPB_SUB_CTRL = 0x0922; +constexpr unsigned int mmMC_XPB_UNC_THRESH_HST = 0x08FF; +constexpr unsigned int mmMC_XPB_UNC_THRESH_SID = 0x0900; +constexpr unsigned int mmMC_XPB_WCB_CFG = 0x0902; +constexpr unsigned int mmMC_XPB_WCB_STS = 0x0901; +constexpr unsigned int mmMC_XPB_XDMA_PEER_SYS_BAR0 = 0x091A; +constexpr unsigned int mmMC_XPB_XDMA_PEER_SYS_BAR1 = 0x091B; +constexpr unsigned int mmMC_XPB_XDMA_PEER_SYS_BAR2 = 0x091C; +constexpr unsigned int mmMC_XPB_XDMA_PEER_SYS_BAR3 = 0x091D; +constexpr unsigned int mmMC_XPB_XDMA_RTR_DEST_MAP0 = 0x08E5; +constexpr unsigned int mmMC_XPB_XDMA_RTR_DEST_MAP1 = 0x08E6; +constexpr unsigned int mmMC_XPB_XDMA_RTR_DEST_MAP2 = 0x08E7; +constexpr unsigned int mmMC_XPB_XDMA_RTR_DEST_MAP3 = 0x08E8; +constexpr unsigned int mmMC_XPB_XDMA_RTR_SRC_APRTR0 = 0x08D7; +constexpr unsigned int mmMC_XPB_XDMA_RTR_SRC_APRTR1 = 0x08D8; +constexpr unsigned int mmMC_XPB_XDMA_RTR_SRC_APRTR2 = 0x08D9; +constexpr unsigned int mmMC_XPB_XDMA_RTR_SRC_APRTR3 = 0x08DA; +constexpr unsigned int mmMEM_TYPE_CNTL__CI__VI = 0x14E4; +constexpr unsigned int mmMICROSECOND_TIME_BASE_DIV__SI = 0x0148; +constexpr unsigned int mmMM_CFGREGS_CNTL = 0x1513; +constexpr unsigned int mmMM_DATA = 0x0001; +constexpr unsigned int mmMM_INDEX = 0x0000; +constexpr unsigned int mmMM_INDEX_HI__CI__VI = 0x0006; +constexpr unsigned int mmMPLL_AD_FUNC_CNTL__SI__CI = 0x0AF0; +constexpr unsigned int mmMPLL_AD_STATUS__SI__CI = 0x0AF6; +constexpr unsigned int mmMPLL_BYPASSCLK_SEL__SI = 0x0197; +constexpr unsigned int mmMPLL_CNTL_MODE__SI__CI = 0x0AEC; +constexpr unsigned int mmMPLL_CONTROL__SI__CI = 0x0AF5; +constexpr unsigned int mmMPLL_DQ_0_0_STATUS__SI__CI = 0x0AF7; +constexpr unsigned int mmMPLL_DQ_0_1_STATUS__SI__CI = 0x0AF8; +constexpr unsigned int mmMPLL_DQ_1_0_STATUS__SI__CI = 0x0AF9; +constexpr unsigned int mmMPLL_DQ_1_1_STATUS__SI__CI = 0x0AFA; +constexpr unsigned int mmMPLL_DQ_FUNC_CNTL__SI__CI = 0x0AF1; +constexpr unsigned int mmMPLL_FUNC_CNTL__SI__CI = 0x0AED; +constexpr unsigned int mmMPLL_FUNC_CNTL_1__SI__CI = 0x0AEE; +constexpr unsigned int mmMPLL_FUNC_CNTL_2__SI__CI = 0x0AEF; +constexpr unsigned int mmMPLL_SEQ_UCODE_1__SI__CI = 0x0AEA; +constexpr unsigned int mmMPLL_SEQ_UCODE_2__SI__CI = 0x0AEB; +constexpr unsigned int mmMPLL_SS1__SI__CI = 0x0AF3; +constexpr unsigned int mmMPLL_SS2__SI__CI = 0x0AF4; +constexpr unsigned int mmMPLL_TIME__SI__CI = 0x0AF2; +constexpr unsigned int mmMVP_AFR_FLIP_FIFO_CNTL__SI = 0x1AD9; +constexpr unsigned int mmMVP_AFR_FLIP_MODE__SI = 0x1AD8; +constexpr unsigned int mmMVP_BLACK_KEYER__SI = 0x1686; +constexpr unsigned int mmMVP_CONTROL1__SI = 0x1680; +constexpr unsigned int mmMVP_CONTROL2__SI = 0x1681; +constexpr unsigned int mmMVP_CONTROL3__SI = 0x168A; +constexpr unsigned int mmMVP_CRC_CNTL__SI = 0x1687; +constexpr unsigned int mmMVP_CRC_RESULT_BLUE_GREEN__SI = 0x1688; +constexpr unsigned int mmMVP_CRC_RESULT_RED__SI = 0x1689; +constexpr unsigned int mmMVP_FIFO_CONTROL__SI = 0x1682; +constexpr unsigned int mmMVP_FIFO_STATUS__SI = 0x1683; +constexpr unsigned int mmMVP_FLIP_LINE_NUM_INSERT__SI = 0x1ADA; +constexpr unsigned int mmMVP_INBAND_CNTL_CAP__SI = 0x1685; +constexpr unsigned int mmMVP_RECEIVE_CNT_CNTL1__SI = 0x168B; +constexpr unsigned int mmMVP_RECEIVE_CNT_CNTL2__SI = 0x168C; +constexpr unsigned int mmMVP_SLAVE_STATUS__SI = 0x1684; +constexpr unsigned int mmMVP_TEST_DEBUG_DATA__SI = 0x168E; +constexpr unsigned int mmMVP_TEST_DEBUG_INDEX__SI = 0x168D; +constexpr unsigned int mmNEW_REFCLKB_TIMER_1__CI = 0x1484; +constexpr unsigned int mmNEW_REFCLKB_TIMER__CI = 0x1485; +constexpr unsigned int mmOVLSCL_EDGE_PIXEL_CNTL__SI__VI = 0x1A2C; +constexpr unsigned int mmOVL_CONTROL1__SI__VI = 0x1A1D; +constexpr unsigned int mmOVL_CONTROL2__SI__VI = 0x1A1E; +constexpr unsigned int mmOVL_DFQ_CONTROL__SI__VI = 0x1A29; +constexpr unsigned int mmOVL_DFQ_STATUS__SI__VI = 0x1A2A; +constexpr unsigned int mmOVL_ENABLE__SI__VI = 0x1A1C; +constexpr unsigned int mmOVL_END__SI__VI = 0x1A26; +constexpr unsigned int mmOVL_PITCH__SI__VI = 0x1A21; +constexpr unsigned int mmOVL_START__SI__VI = 0x1A25; +constexpr unsigned int mmOVL_SURFACE_ADDRESS = 0x1A20; +constexpr unsigned int mmOVL_SURFACE_ADDRESS_HIGH = 0x1A22; +constexpr unsigned int mmOVL_SURFACE_ADDRESS_HIGH_INUSE__SI__VI = 0x1A2B; +constexpr unsigned int mmOVL_SURFACE_ADDRESS_INUSE__SI__VI = 0x1A28; +constexpr unsigned int mmOVL_SURFACE_OFFSET_X__SI__VI = 0x1A23; +constexpr unsigned int mmOVL_SURFACE_OFFSET_Y__SI__VI = 0x1A24; +constexpr unsigned int mmOVL_SWAP_CNTL__SI__VI = 0x1A1F; +constexpr unsigned int mmOVL_UPDATE__SI__VI = 0x1A27; +constexpr unsigned int mmPAGE_MIRROR_CNTL__SI = 0x0581; +constexpr unsigned int mmPA_CL_CLIP_CNTL = 0xA204; +constexpr unsigned int mmPA_CL_CNTL_STATUS = 0x2284; +constexpr unsigned int mmPA_CL_ENHANCE = 0x2285; +constexpr unsigned int mmPA_CL_GB_HORZ_CLIP_ADJ = 0xA2FC; +constexpr unsigned int mmPA_CL_GB_HORZ_DISC_ADJ = 0xA2FD; +constexpr unsigned int mmPA_CL_GB_VERT_CLIP_ADJ = 0xA2FA; +constexpr unsigned int mmPA_CL_GB_VERT_DISC_ADJ = 0xA2FB; +constexpr unsigned int mmPA_CL_NANINF_CNTL = 0xA208; +constexpr unsigned int mmPA_CL_POINT_CULL_RAD = 0xA1F8; +constexpr unsigned int mmPA_CL_POINT_SIZE = 0xA1F7; +constexpr unsigned int mmPA_CL_POINT_X_RAD = 0xA1F5; +constexpr unsigned int mmPA_CL_POINT_Y_RAD = 0xA1F6; +constexpr unsigned int mmPA_CL_RESET_DEBUG__CI__VI = 0x2286; +constexpr unsigned int mmPA_CL_UCP_0_W = 0xA172; +constexpr unsigned int mmPA_CL_UCP_0_X = 0xA16F; +constexpr unsigned int mmPA_CL_UCP_0_Y = 0xA170; +constexpr unsigned int mmPA_CL_UCP_0_Z = 0xA171; +constexpr unsigned int mmPA_CL_UCP_1_W = 0xA176; +constexpr unsigned int mmPA_CL_UCP_1_X = 0xA173; +constexpr unsigned int mmPA_CL_UCP_1_Y = 0xA174; +constexpr unsigned int mmPA_CL_UCP_1_Z = 0xA175; +constexpr unsigned int mmPA_CL_UCP_2_W = 0xA17A; +constexpr unsigned int mmPA_CL_UCP_2_X = 0xA177; +constexpr unsigned int mmPA_CL_UCP_2_Y = 0xA178; +constexpr unsigned int mmPA_CL_UCP_2_Z = 0xA179; +constexpr unsigned int mmPA_CL_UCP_3_W = 0xA17E; +constexpr unsigned int mmPA_CL_UCP_3_X = 0xA17B; +constexpr unsigned int mmPA_CL_UCP_3_Y = 0xA17C; +constexpr unsigned int mmPA_CL_UCP_3_Z = 0xA17D; +constexpr unsigned int mmPA_CL_UCP_4_W = 0xA182; +constexpr unsigned int mmPA_CL_UCP_4_X = 0xA17F; +constexpr unsigned int mmPA_CL_UCP_4_Y = 0xA180; +constexpr unsigned int mmPA_CL_UCP_4_Z = 0xA181; +constexpr unsigned int mmPA_CL_UCP_5_W = 0xA186; +constexpr unsigned int mmPA_CL_UCP_5_X = 0xA183; +constexpr unsigned int mmPA_CL_UCP_5_Y = 0xA184; +constexpr unsigned int mmPA_CL_UCP_5_Z = 0xA185; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET = 0xA110; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_1 = 0xA116; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_10 = 0xA14C; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_11 = 0xA152; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_12 = 0xA158; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_13 = 0xA15E; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_14 = 0xA164; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_15 = 0xA16A; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_2 = 0xA11C; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_3 = 0xA122; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_4 = 0xA128; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_5 = 0xA12E; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_6 = 0xA134; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_7 = 0xA13A; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_8 = 0xA140; +constexpr unsigned int mmPA_CL_VPORT_XOFFSET_9 = 0xA146; +constexpr unsigned int mmPA_CL_VPORT_XSCALE = 0xA10F; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_1 = 0xA115; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_10 = 0xA14B; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_11 = 0xA151; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_12 = 0xA157; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_13 = 0xA15D; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_14 = 0xA163; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_15 = 0xA169; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_2 = 0xA11B; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_3 = 0xA121; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_4 = 0xA127; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_5 = 0xA12D; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_6 = 0xA133; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_7 = 0xA139; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_8 = 0xA13F; +constexpr unsigned int mmPA_CL_VPORT_XSCALE_9 = 0xA145; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET = 0xA112; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_1 = 0xA118; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_10 = 0xA14E; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_11 = 0xA154; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_12 = 0xA15A; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_13 = 0xA160; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_14 = 0xA166; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_15 = 0xA16C; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_2 = 0xA11E; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_3 = 0xA124; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_4 = 0xA12A; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_5 = 0xA130; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_6 = 0xA136; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_7 = 0xA13C; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_8 = 0xA142; +constexpr unsigned int mmPA_CL_VPORT_YOFFSET_9 = 0xA148; +constexpr unsigned int mmPA_CL_VPORT_YSCALE = 0xA111; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_1 = 0xA117; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_10 = 0xA14D; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_11 = 0xA153; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_12 = 0xA159; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_13 = 0xA15F; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_14 = 0xA165; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_15 = 0xA16B; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_2 = 0xA11D; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_3 = 0xA123; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_4 = 0xA129; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_5 = 0xA12F; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_6 = 0xA135; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_7 = 0xA13B; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_8 = 0xA141; +constexpr unsigned int mmPA_CL_VPORT_YSCALE_9 = 0xA147; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET = 0xA114; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_1 = 0xA11A; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_10 = 0xA150; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_11 = 0xA156; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_12 = 0xA15C; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_13 = 0xA162; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_14 = 0xA168; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_15 = 0xA16E; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_2 = 0xA120; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_3 = 0xA126; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_4 = 0xA12C; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_5 = 0xA132; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_6 = 0xA138; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_7 = 0xA13E; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_8 = 0xA144; +constexpr unsigned int mmPA_CL_VPORT_ZOFFSET_9 = 0xA14A; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE = 0xA113; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_1 = 0xA119; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_10 = 0xA14F; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_11 = 0xA155; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_12 = 0xA15B; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_13 = 0xA161; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_14 = 0xA167; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_15 = 0xA16D; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_2 = 0xA11F; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_3 = 0xA125; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_4 = 0xA12B; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_5 = 0xA131; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_6 = 0xA137; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_7 = 0xA13D; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_8 = 0xA143; +constexpr unsigned int mmPA_CL_VPORT_ZSCALE_9 = 0xA149; +constexpr unsigned int mmPA_CL_VS_OUT_CNTL = 0xA207; +constexpr unsigned int mmPA_CL_VTE_CNTL = 0xA206; +constexpr unsigned int mmPA_SC_AA_CONFIG = 0xA2F8; +constexpr unsigned int mmPA_SC_AA_MASK_X0Y0_X1Y0 = 0xA30E; +constexpr unsigned int mmPA_SC_AA_MASK_X0Y1_X1Y1 = 0xA30F; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 = 0xA2FE; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1 = 0xA2FF; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2 = 0xA300; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3 = 0xA301; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0 = 0xA306; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1 = 0xA307; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2 = 0xA308; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3 = 0xA309; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0 = 0xA302; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1 = 0xA303; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2 = 0xA304; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3 = 0xA305; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0 = 0xA30A; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1 = 0xA30B; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2 = 0xA30C; +constexpr unsigned int mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3 = 0xA30D; +constexpr unsigned int mmPA_SC_CENTROID_PRIORITY_0 = 0xA2F5; +constexpr unsigned int mmPA_SC_CENTROID_PRIORITY_1 = 0xA2F6; +constexpr unsigned int mmPA_SC_CLIPRECT_0_BR = 0xA085; +constexpr unsigned int mmPA_SC_CLIPRECT_0_TL = 0xA084; +constexpr unsigned int mmPA_SC_CLIPRECT_1_BR = 0xA087; +constexpr unsigned int mmPA_SC_CLIPRECT_1_TL = 0xA086; +constexpr unsigned int mmPA_SC_CLIPRECT_2_BR = 0xA089; +constexpr unsigned int mmPA_SC_CLIPRECT_2_TL = 0xA088; +constexpr unsigned int mmPA_SC_CLIPRECT_3_BR = 0xA08B; +constexpr unsigned int mmPA_SC_CLIPRECT_3_TL = 0xA08A; +constexpr unsigned int mmPA_SC_CLIPRECT_RULE = 0xA083; +constexpr unsigned int mmPA_SC_DEBUG_CNTL = 0x22F6; +constexpr unsigned int mmPA_SC_DEBUG_DATA = 0x22F7; +constexpr unsigned int mmPA_SC_EDGERULE = 0xA08C; +constexpr unsigned int mmPA_SC_ENHANCE = 0x22FC; +constexpr unsigned int mmPA_SC_FIFO_DEPTH_CNTL = 0x2295; +constexpr unsigned int mmPA_SC_FIFO_SIZE = 0x22F3; +constexpr unsigned int mmPA_SC_FORCE_EOV_MAX_CNTS = 0x22C9; +constexpr unsigned int mmPA_SC_GENERIC_SCISSOR_BR = 0xA091; +constexpr unsigned int mmPA_SC_GENERIC_SCISSOR_TL = 0xA090; +constexpr unsigned int mmPA_SC_HP3D_TRAP_SCREEN_COUNT__CI__VI = 0xC2AC; +constexpr unsigned int mmPA_SC_HP3D_TRAP_SCREEN_HV_EN__CI__VI = 0xC2A8; +constexpr unsigned int mmPA_SC_HP3D_TRAP_SCREEN_HV_LOCK__CI__VI = 0x22C1; +constexpr unsigned int mmPA_SC_HP3D_TRAP_SCREEN_H__CI__VI = 0xC2A9; +constexpr unsigned int mmPA_SC_HP3D_TRAP_SCREEN_OCCURRENCE__CI__VI = 0xC2AB; +constexpr unsigned int mmPA_SC_HP3D_TRAP_SCREEN_V__CI__VI = 0xC2AA; +constexpr unsigned int mmPA_SC_IF_FIFO_SIZE = 0x22F5; +constexpr unsigned int mmPA_SC_LINE_CNTL = 0xA2F7; +constexpr unsigned int mmPA_SC_LINE_STIPPLE = 0xA283; +constexpr unsigned int mmPA_SC_LINE_STIPPLE_STATE__CI__VI = 0xC281; +constexpr unsigned int mmPA_SC_LINE_STIPPLE_STATE__SI = 0x22C4; +constexpr unsigned int mmPA_SC_MODE_CNTL_0 = 0xA292; +constexpr unsigned int mmPA_SC_MODE_CNTL_1 = 0xA293; +constexpr unsigned int mmPA_SC_P3D_TRAP_SCREEN_COUNT__CI__VI = 0xC2A4; +constexpr unsigned int mmPA_SC_P3D_TRAP_SCREEN_HV_EN__CI__VI = 0xC2A0; +constexpr unsigned int mmPA_SC_P3D_TRAP_SCREEN_HV_LOCK__CI__VI = 0x22C0; +constexpr unsigned int mmPA_SC_P3D_TRAP_SCREEN_H__CI__VI = 0xC2A1; +constexpr unsigned int mmPA_SC_P3D_TRAP_SCREEN_OCCURRENCE__CI__VI = 0xC2A3; +constexpr unsigned int mmPA_SC_P3D_TRAP_SCREEN_V__CI__VI = 0xC2A2; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_HI__CI__VI = 0xD141; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_HI__SI = 0x22A9; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_LO__CI__VI = 0xD140; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_LO__SI = 0x22A8; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_SELECT1__CI__VI = 0xD941; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_SELECT__CI__VI = 0xD940; +constexpr unsigned int mmPA_SC_PERFCOUNTER0_SELECT__SI = 0x22A0; +constexpr unsigned int mmPA_SC_PERFCOUNTER1_HI__CI__VI = 0xD143; +constexpr unsigned int mmPA_SC_PERFCOUNTER1_HI__SI = 0x22AB; +constexpr unsigned int mmPA_SC_PERFCOUNTER1_LO__CI__VI = 0xD142; +constexpr unsigned int mmPA_SC_PERFCOUNTER1_LO__SI = 0x22AA; +constexpr unsigned int mmPA_SC_PERFCOUNTER1_SELECT__CI__VI = 0xD942; +constexpr unsigned int mmPA_SC_PERFCOUNTER1_SELECT__SI = 0x22A1; +constexpr unsigned int mmPA_SC_PERFCOUNTER2_HI__CI__VI = 0xD145; +constexpr unsigned int mmPA_SC_PERFCOUNTER2_HI__SI = 0x22AD; +constexpr unsigned int mmPA_SC_PERFCOUNTER2_LO__CI__VI = 0xD144; +constexpr unsigned int mmPA_SC_PERFCOUNTER2_LO__SI = 0x22AC; +constexpr unsigned int mmPA_SC_PERFCOUNTER2_SELECT__CI__VI = 0xD943; +constexpr unsigned int mmPA_SC_PERFCOUNTER2_SELECT__SI = 0x22A2; +constexpr unsigned int mmPA_SC_PERFCOUNTER3_HI__CI__VI = 0xD147; +constexpr unsigned int mmPA_SC_PERFCOUNTER3_HI__SI = 0x22AF; +constexpr unsigned int mmPA_SC_PERFCOUNTER3_LO__CI__VI = 0xD146; +constexpr unsigned int mmPA_SC_PERFCOUNTER3_LO__SI = 0x22AE; +constexpr unsigned int mmPA_SC_PERFCOUNTER3_SELECT__CI__VI = 0xD944; +constexpr unsigned int mmPA_SC_PERFCOUNTER3_SELECT__SI = 0x22A3; +constexpr unsigned int mmPA_SC_PERFCOUNTER4_HI__CI__VI = 0xD149; +constexpr unsigned int mmPA_SC_PERFCOUNTER4_HI__SI = 0x22B1; +constexpr unsigned int mmPA_SC_PERFCOUNTER4_LO__CI__VI = 0xD148; +constexpr unsigned int mmPA_SC_PERFCOUNTER4_LO__SI = 0x22B0; +constexpr unsigned int mmPA_SC_PERFCOUNTER4_SELECT__CI__VI = 0xD945; +constexpr unsigned int mmPA_SC_PERFCOUNTER4_SELECT__SI = 0x22A4; +constexpr unsigned int mmPA_SC_PERFCOUNTER5_HI__CI__VI = 0xD14B; +constexpr unsigned int mmPA_SC_PERFCOUNTER5_HI__SI = 0x22B3; +constexpr unsigned int mmPA_SC_PERFCOUNTER5_LO__CI__VI = 0xD14A; +constexpr unsigned int mmPA_SC_PERFCOUNTER5_LO__SI = 0x22B2; +constexpr unsigned int mmPA_SC_PERFCOUNTER5_SELECT__CI__VI = 0xD946; +constexpr unsigned int mmPA_SC_PERFCOUNTER5_SELECT__SI = 0x22A5; +constexpr unsigned int mmPA_SC_PERFCOUNTER6_HI__CI__VI = 0xD14D; +constexpr unsigned int mmPA_SC_PERFCOUNTER6_HI__SI = 0x22B5; +constexpr unsigned int mmPA_SC_PERFCOUNTER6_LO__CI__VI = 0xD14C; +constexpr unsigned int mmPA_SC_PERFCOUNTER6_LO__SI = 0x22B4; +constexpr unsigned int mmPA_SC_PERFCOUNTER6_SELECT__CI__VI = 0xD947; +constexpr unsigned int mmPA_SC_PERFCOUNTER6_SELECT__SI = 0x22A6; +constexpr unsigned int mmPA_SC_PERFCOUNTER7_HI__CI__VI = 0xD14F; +constexpr unsigned int mmPA_SC_PERFCOUNTER7_HI__SI = 0x22B7; +constexpr unsigned int mmPA_SC_PERFCOUNTER7_LO__CI__VI = 0xD14E; +constexpr unsigned int mmPA_SC_PERFCOUNTER7_LO__SI = 0x22B6; +constexpr unsigned int mmPA_SC_PERFCOUNTER7_SELECT__CI__VI = 0xD948; +constexpr unsigned int mmPA_SC_PERFCOUNTER7_SELECT__SI = 0x22A7; +constexpr unsigned int mmPA_SC_RASTER_CONFIG = 0xA0D4; +constexpr unsigned int mmPA_SC_RASTER_CONFIG_1__CI__VI = 0xA0D5; +constexpr unsigned int mmPA_SC_SCREEN_SCISSOR_BR = 0xA00D; +constexpr unsigned int mmPA_SC_SCREEN_SCISSOR_TL = 0xA00C; +constexpr unsigned int mmPA_SC_TRAP_SCREEN_COUNT__CI__VI = 0xC2B4; +constexpr unsigned int mmPA_SC_TRAP_SCREEN_HV_EN__CI__VI = 0xC2B0; +constexpr unsigned int mmPA_SC_TRAP_SCREEN_HV_LOCK__CI__VI = 0x22C2; +constexpr unsigned int mmPA_SC_TRAP_SCREEN_H__CI__VI = 0xC2B1; +constexpr unsigned int mmPA_SC_TRAP_SCREEN_OCCURRENCE__CI__VI = 0xC2B3; +constexpr unsigned int mmPA_SC_TRAP_SCREEN_V__CI__VI = 0xC2B2; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_0_BR = 0xA095; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_0_TL = 0xA094; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_10_BR = 0xA0A9; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_10_TL = 0xA0A8; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_11_BR = 0xA0AB; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_11_TL = 0xA0AA; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_12_BR = 0xA0AD; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_12_TL = 0xA0AC; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_13_BR = 0xA0AF; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_13_TL = 0xA0AE; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_14_BR = 0xA0B1; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_14_TL = 0xA0B0; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_15_BR = 0xA0B3; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_15_TL = 0xA0B2; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_1_BR = 0xA097; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_1_TL = 0xA096; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_2_BR = 0xA099; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_2_TL = 0xA098; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_3_BR = 0xA09B; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_3_TL = 0xA09A; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_4_BR = 0xA09D; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_4_TL = 0xA09C; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_5_BR = 0xA09F; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_5_TL = 0xA09E; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_6_BR = 0xA0A1; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_6_TL = 0xA0A0; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_7_BR = 0xA0A3; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_7_TL = 0xA0A2; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_8_BR = 0xA0A5; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_8_TL = 0xA0A4; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_9_BR = 0xA0A7; +constexpr unsigned int mmPA_SC_VPORT_SCISSOR_9_TL = 0xA0A6; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_0 = 0xA0B5; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_1 = 0xA0B7; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_10 = 0xA0C9; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_11 = 0xA0CB; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_12 = 0xA0CD; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_13 = 0xA0CF; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_14 = 0xA0D1; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_15 = 0xA0D3; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_2 = 0xA0B9; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_3 = 0xA0BB; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_4 = 0xA0BD; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_5 = 0xA0BF; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_6 = 0xA0C1; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_7 = 0xA0C3; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_8 = 0xA0C5; +constexpr unsigned int mmPA_SC_VPORT_ZMAX_9 = 0xA0C7; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_0 = 0xA0B4; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_1 = 0xA0B6; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_10 = 0xA0C8; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_11 = 0xA0CA; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_12 = 0xA0CC; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_13 = 0xA0CE; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_14 = 0xA0D0; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_15 = 0xA0D2; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_2 = 0xA0B8; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_3 = 0xA0BA; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_4 = 0xA0BC; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_5 = 0xA0BE; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_6 = 0xA0C0; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_7 = 0xA0C2; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_8 = 0xA0C4; +constexpr unsigned int mmPA_SC_VPORT_ZMIN_9 = 0xA0C6; +constexpr unsigned int mmPA_SC_WINDOW_OFFSET = 0xA080; +constexpr unsigned int mmPA_SC_WINDOW_SCISSOR_BR = 0xA082; +constexpr unsigned int mmPA_SC_WINDOW_SCISSOR_TL = 0xA081; +constexpr unsigned int mmPA_SU_CNTL_STATUS = 0x2294; +constexpr unsigned int mmPA_SU_DEBUG_CNTL = 0x2280; +constexpr unsigned int mmPA_SU_DEBUG_DATA = 0x2281; +constexpr unsigned int mmPA_SU_HARDWARE_SCREEN_OFFSET = 0xA08D; +constexpr unsigned int mmPA_SU_LINE_CNTL = 0xA282; +constexpr unsigned int mmPA_SU_LINE_STIPPLE_CNTL = 0xA209; +constexpr unsigned int mmPA_SU_LINE_STIPPLE_SCALE = 0xA20A; +constexpr unsigned int mmPA_SU_LINE_STIPPLE_VALUE__CI__VI = 0xC280; +constexpr unsigned int mmPA_SU_LINE_STIPPLE_VALUE__SI = 0x2298; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_HI__CI__VI = 0xD101; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_HI__SI = 0x228D; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_LO__CI__VI = 0xD100; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_LO__SI = 0x228C; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_SELECT1__CI__VI = 0xD901; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_SELECT__CI__VI = 0xD900; +constexpr unsigned int mmPA_SU_PERFCOUNTER0_SELECT__SI = 0x2288; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_HI__CI__VI = 0xD103; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_HI__SI = 0x228F; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_LO__CI__VI = 0xD102; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_LO__SI = 0x228E; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_SELECT1__CI__VI = 0xD903; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_SELECT__CI__VI = 0xD902; +constexpr unsigned int mmPA_SU_PERFCOUNTER1_SELECT__SI = 0x2289; +constexpr unsigned int mmPA_SU_PERFCOUNTER2_HI__CI__VI = 0xD105; +constexpr unsigned int mmPA_SU_PERFCOUNTER2_HI__SI = 0x2291; +constexpr unsigned int mmPA_SU_PERFCOUNTER2_LO__CI__VI = 0xD104; +constexpr unsigned int mmPA_SU_PERFCOUNTER2_LO__SI = 0x2290; +constexpr unsigned int mmPA_SU_PERFCOUNTER2_SELECT__CI__VI = 0xD904; +constexpr unsigned int mmPA_SU_PERFCOUNTER2_SELECT__SI = 0x228A; +constexpr unsigned int mmPA_SU_PERFCOUNTER3_HI__CI__VI = 0xD107; +constexpr unsigned int mmPA_SU_PERFCOUNTER3_HI__SI = 0x2293; +constexpr unsigned int mmPA_SU_PERFCOUNTER3_LO__CI__VI = 0xD106; +constexpr unsigned int mmPA_SU_PERFCOUNTER3_LO__SI = 0x2292; +constexpr unsigned int mmPA_SU_PERFCOUNTER3_SELECT__CI__VI = 0xD905; +constexpr unsigned int mmPA_SU_PERFCOUNTER3_SELECT__SI = 0x228B; +constexpr unsigned int mmPA_SU_POINT_MINMAX = 0xA281; +constexpr unsigned int mmPA_SU_POINT_SIZE = 0xA280; +constexpr unsigned int mmPA_SU_POLY_OFFSET_BACK_OFFSET = 0xA2E3; +constexpr unsigned int mmPA_SU_POLY_OFFSET_BACK_SCALE = 0xA2E2; +constexpr unsigned int mmPA_SU_POLY_OFFSET_CLAMP = 0xA2DF; +constexpr unsigned int mmPA_SU_POLY_OFFSET_DB_FMT_CNTL = 0xA2DE; +constexpr unsigned int mmPA_SU_POLY_OFFSET_FRONT_OFFSET = 0xA2E1; +constexpr unsigned int mmPA_SU_POLY_OFFSET_FRONT_SCALE = 0xA2E0; +constexpr unsigned int mmPA_SU_PRIM_FILTER_CNTL = 0xA20B; +constexpr unsigned int mmPA_SU_SC_MODE_CNTL = 0xA205; +constexpr unsigned int mmPA_SU_VTX_CNTL = 0xA2F9; +constexpr unsigned int mmPCIE_DATA_2__CI__VI = 0x000D; +constexpr unsigned int mmPCIE_DATA__CI__VI = 0x000F; +constexpr unsigned int mmPCIE_DATA__SI = 0x000D; +constexpr unsigned int mmPCIE_INDEX_2__CI__VI = 0x000C; +constexpr unsigned int mmPCIE_INDEX__CI__VI = 0x000E; +constexpr unsigned int mmPCIE_INDEX__SI = 0x000C; +constexpr unsigned int mmPEER0_FB_OFFSET_HI__CI__VI = 0x14F3; +constexpr unsigned int mmPEER0_FB_OFFSET_LO__CI__VI = 0x14F2; +constexpr unsigned int mmPEER1_FB_OFFSET_HI__CI__VI = 0x14F1; +constexpr unsigned int mmPEER1_FB_OFFSET_LO__CI__VI = 0x14F0; +constexpr unsigned int mmPEER2_FB_OFFSET_HI__CI__VI = 0x14EF; +constexpr unsigned int mmPEER2_FB_OFFSET_LO__CI__VI = 0x14EE; +constexpr unsigned int mmPEER3_FB_OFFSET_HI__CI__VI = 0x14ED; +constexpr unsigned int mmPEER3_FB_OFFSET_LO__CI__VI = 0x14EC; +constexpr unsigned int mmPEER_REG_RANGE0 = 0x153E; +constexpr unsigned int mmPEER_REG_RANGE1 = 0x153F; +constexpr unsigned int mmPHY_AUX_CNTL__SI = 0x1953; +constexpr unsigned int mmPIPE0_ARBITRATION_CONTROL3__SI = 0x02FC; +constexpr unsigned int mmPIPE1_ARBITRATION_CONTROL3__SI = 0x0300; +constexpr unsigned int mmPIPE2_ARBITRATION_CONTROL3__SI = 0x0304; +constexpr unsigned int mmPIPE3_ARBITRATION_CONTROL3__SI = 0x0308; +constexpr unsigned int mmPIPE4_ARBITRATION_CONTROL3__SI = 0x030C; +constexpr unsigned int mmPIPE5_ARBITRATION_CONTROL3__SI = 0x0310; +constexpr unsigned int mmPIXCLK1_RESYNC_CNTL__SI = 0x0126; +constexpr unsigned int mmPIXCLK2_RESYNC_CNTL__SI = 0x0127; +constexpr unsigned int mmPLL_TEST_CNTL__SI = 0x0199; +constexpr unsigned int mmRAS_BCI_SIGNATURE0 = 0x339E; +constexpr unsigned int mmRAS_BCI_SIGNATURE1 = 0x339F; +constexpr unsigned int mmRAS_CB_SIGNATURE0 = 0x339D; +constexpr unsigned int mmRAS_DB_SIGNATURE0 = 0x338B; +constexpr unsigned int mmRAS_IA_SIGNATURE0 = 0x3397; +constexpr unsigned int mmRAS_IA_SIGNATURE1 = 0x3398; +constexpr unsigned int mmRAS_PA_SIGNATURE0 = 0x338C; +constexpr unsigned int mmRAS_SC_SIGNATURE0 = 0x338F; +constexpr unsigned int mmRAS_SC_SIGNATURE1 = 0x3390; +constexpr unsigned int mmRAS_SC_SIGNATURE2 = 0x3391; +constexpr unsigned int mmRAS_SC_SIGNATURE3 = 0x3392; +constexpr unsigned int mmRAS_SC_SIGNATURE4 = 0x3393; +constexpr unsigned int mmRAS_SC_SIGNATURE5 = 0x3394; +constexpr unsigned int mmRAS_SC_SIGNATURE6 = 0x3395; +constexpr unsigned int mmRAS_SC_SIGNATURE7 = 0x3396; +constexpr unsigned int mmRAS_SIGNATURE_CONTROL = 0x3380; +constexpr unsigned int mmRAS_SIGNATURE_MASK = 0x3381; +constexpr unsigned int mmRAS_SPI_SIGNATURE0 = 0x3399; +constexpr unsigned int mmRAS_SPI_SIGNATURE1 = 0x339A; +constexpr unsigned int mmRAS_SQ_SIGNATURE0 = 0x338E; +constexpr unsigned int mmRAS_SX_SIGNATURE0 = 0x3382; +constexpr unsigned int mmRAS_SX_SIGNATURE1 = 0x3383; +constexpr unsigned int mmRAS_SX_SIGNATURE2 = 0x3384; +constexpr unsigned int mmRAS_SX_SIGNATURE3 = 0x3385; +constexpr unsigned int mmRAS_TA_SIGNATURE0 = 0x339B; +constexpr unsigned int mmRAS_TD_SIGNATURE0 = 0x339C; +constexpr unsigned int mmRAS_VGT_SIGNATURE0 = 0x338D; +constexpr unsigned int mmRCU_MISC_CTRL__SI = 0x0043; +constexpr unsigned int mmRCU_UC_EVENTS__SI = 0x0045; +constexpr unsigned int mmRLC_AUTO_PG_CTRL__CI = 0x3115; +constexpr unsigned int mmRLC_AUTO_PG_CTRL__SI = 0x310D; +constexpr unsigned int mmRLC_CAPTURE_GPU_CLOCK_COUNT__CI = 0x30E6; +constexpr unsigned int mmRLC_CAPTURE_GPU_CLOCK_COUNT__SI = 0x30D0; +constexpr unsigned int mmRLC_CGCG_CGLS_CTRL__CI = 0x3109; +constexpr unsigned int mmRLC_CGCG_CGLS_CTRL__SI = 0x3101; +constexpr unsigned int mmRLC_CGCG_RAMP_CTRL__CI = 0x310A; +constexpr unsigned int mmRLC_CGCG_RAMP_CTRL__SI = 0x3102; +constexpr unsigned int mmRLC_CGTT_MGCG_OVERRIDE__CI = 0x3108; +constexpr unsigned int mmRLC_CGTT_MGCG_OVERRIDE__SI = 0x3100; +constexpr unsigned int mmRLC_CU_STATUS__CI = 0x310E; +constexpr unsigned int mmRLC_CU_STATUS__SI = 0x3106; +constexpr unsigned int mmRLC_DEBUG_SELECT__CI = 0x30C1; +constexpr unsigned int mmRLC_DEBUG_SELECT__SI = 0x30C9; +constexpr unsigned int mmRLC_DEBUG__CI = 0x30C2; +constexpr unsigned int mmRLC_DEBUG__SI = 0x30CA; +constexpr unsigned int mmRLC_DRIVER_CPDMA_STATUS__CI = 0x30DE; +constexpr unsigned int mmRLC_DRIVER_CPDMA_STATUS__SI = 0x30C7; +constexpr unsigned int mmRLC_DYN_PG_REQUEST__CI = 0x310C; +constexpr unsigned int mmRLC_DYN_PG_REQUEST__SI = 0x3104; +constexpr unsigned int mmRLC_DYN_PG_STATUS__CI = 0x310B; +constexpr unsigned int mmRLC_DYN_PG_STATUS__SI = 0x3103; +constexpr unsigned int mmRLC_GPM_CU_PD_TIMEOUT__CI = 0x312B; +constexpr unsigned int mmRLC_GPM_DEBUG_SELECT__CI = 0x30E0; +constexpr unsigned int mmRLC_GPM_DEBUG__CI = 0x30E1; +constexpr unsigned int mmRLC_GPM_GENERAL_0__CI = 0x3123; +constexpr unsigned int mmRLC_GPM_GENERAL_1__CI = 0x3124; +constexpr unsigned int mmRLC_GPM_GENERAL_2__CI = 0x3125; +constexpr unsigned int mmRLC_GPM_GENERAL_3__CI = 0x3126; +constexpr unsigned int mmRLC_GPM_GENERAL_4__CI = 0x3127; +constexpr unsigned int mmRLC_GPM_GENERAL_5__CI = 0x3128; +constexpr unsigned int mmRLC_GPM_GENERAL_6__CI = 0x3129; +constexpr unsigned int mmRLC_GPM_GENERAL_7__CI = 0x312A; +constexpr unsigned int mmRLC_GPM_LOG_ADDR__CI = 0x3136; +constexpr unsigned int mmRLC_GPM_LOG_CONT__CI = 0x3138; +constexpr unsigned int mmRLC_GPM_LOG_SIZE__CI = 0x3137; +constexpr unsigned int mmRLC_GPM_PERF_COUNT_0__CI = 0x312F; +constexpr unsigned int mmRLC_GPM_PERF_COUNT_1__CI = 0x3130; +constexpr unsigned int mmRLC_GPM_SCRATCH_ADDR__CI = 0x312C; +constexpr unsigned int mmRLC_GPM_SCRATCH_DATA__CI = 0x312D; +constexpr unsigned int mmRLC_GPM_STAT__CI = 0x3100; +constexpr unsigned int mmRLC_GPM_THREAD_ENABLE__CI = 0x3105; +constexpr unsigned int mmRLC_GPM_THREAD_PRIORITY__CI = 0x3104; +constexpr unsigned int mmRLC_GPM_UCODE_ADDR__CI = 0x30E2; +constexpr unsigned int mmRLC_GPM_UCODE_DATA__CI = 0x30E3; +constexpr unsigned int mmRLC_GPM_VMID_THREAD0__CI = 0x3106; +constexpr unsigned int mmRLC_GPM_VMID_THREAD1__CI = 0x3107; +constexpr unsigned int mmRLC_GPR_REG1__CI = 0x3139; +constexpr unsigned int mmRLC_GPR_REG2__CI = 0x313A; +constexpr unsigned int mmRLC_GPU_CLOCK_32_RES_SEL__CI = 0x3101; +constexpr unsigned int mmRLC_GPU_CLOCK_32_RES_SEL__SI = 0x30D4; +constexpr unsigned int mmRLC_GPU_CLOCK_32__CI = 0x3102; +constexpr unsigned int mmRLC_GPU_CLOCK_32__SI = 0x30D5; +constexpr unsigned int mmRLC_GPU_CLOCK_COUNT_LSB__CI = 0x30E4; +constexpr unsigned int mmRLC_GPU_CLOCK_COUNT_LSB__SI = 0x30CE; +constexpr unsigned int mmRLC_GPU_CLOCK_COUNT_MSB__CI = 0x30E5; +constexpr unsigned int mmRLC_GPU_CLOCK_COUNT_MSB__SI = 0x30CF; +constexpr unsigned int mmRLC_JUMP_TABLE_RESTORE__CI = 0x30DE; +constexpr unsigned int mmRLC_LB_ALWAYS_ACTIVE_CU_MASK__CI = 0x3110; +constexpr unsigned int mmRLC_LB_ALWAYS_ACTIVE_CU_MASK__SI = 0x3108; +constexpr unsigned int mmRLC_LB_CNTL__CI = 0x30D9; +constexpr unsigned int mmRLC_LB_CNTL__SI = 0x30C3; +constexpr unsigned int mmRLC_LB_CNTR_INIT__CI = 0x30DB; +constexpr unsigned int mmRLC_LB_CNTR_INIT__SI = 0x30C6; +constexpr unsigned int mmRLC_LB_CNTR_MAX__CI = 0x30D2; +constexpr unsigned int mmRLC_LB_CNTR_MAX__SI = 0x30C5; +constexpr unsigned int mmRLC_LB_INIT_CU_MASK__CI = 0x310F; +constexpr unsigned int mmRLC_LB_INIT_CU_MASK__SI = 0x3107; +constexpr unsigned int mmRLC_LB_PARAMS__CI = 0x3111; +constexpr unsigned int mmRLC_LB_PARAMS__SI = 0x3109; +constexpr unsigned int mmRLC_LOAD_BALANCE_CNTR__CI = 0x30DC; +constexpr unsigned int mmRLC_LOAD_BALANCE_CNTR__SI = 0x30F6; +constexpr unsigned int mmRLC_MAX_PG_CU__CI = 0x3114; +constexpr unsigned int mmRLC_MAX_PG_CU__SI = 0x310C; +constexpr unsigned int mmRLC_MC_CNTL__CI = 0x30C3; +constexpr unsigned int mmRLC_MC_CNTL__SI = 0x30D1; +constexpr unsigned int mmRLC_MEM_SLP_CNTL__CI = 0x30C6; +constexpr unsigned int mmRLC_MEM_SLP_CNTL__SI = 0x30D8; +constexpr unsigned int mmRLC_PERFCOUNTER0_HI__CI__VI = 0xD481; +constexpr unsigned int mmRLC_PERFCOUNTER0_HI__SI = 0x30DC; +constexpr unsigned int mmRLC_PERFCOUNTER0_LO__CI__VI = 0xD480; +constexpr unsigned int mmRLC_PERFCOUNTER0_LO__SI = 0x30DB; +constexpr unsigned int mmRLC_PERFCOUNTER0_SELECT__CI__VI = 0xDCC1; +constexpr unsigned int mmRLC_PERFCOUNTER0_SELECT__SI = 0x30DA; +constexpr unsigned int mmRLC_PERFCOUNTER1_HI__CI__VI = 0xD483; +constexpr unsigned int mmRLC_PERFCOUNTER1_HI__SI = 0x30DF; +constexpr unsigned int mmRLC_PERFCOUNTER1_LO__CI__VI = 0xD482; +constexpr unsigned int mmRLC_PERFCOUNTER1_LO__SI = 0x30DE; +constexpr unsigned int mmRLC_PERFCOUNTER1_SELECT__CI__VI = 0xDCC2; +constexpr unsigned int mmRLC_PERFCOUNTER1_SELECT__SI = 0x30DD; +constexpr unsigned int mmRLC_PERFMON_CNTL__CI__VI = 0xDCC0; +constexpr unsigned int mmRLC_PERFMON_CNTL__SI = 0x30D9; +constexpr unsigned int mmRLC_PG_ALWAYS_ON_CU_MASK__CI = 0x3113; +constexpr unsigned int mmRLC_PG_ALWAYS_ON_CU_MASK__SI = 0x310B; +constexpr unsigned int mmRLC_PG_CNTL__CI = 0x3103; +constexpr unsigned int mmRLC_PG_CNTL__SI = 0x30D7; +constexpr unsigned int mmRLC_PG_DELAY_2__CI = 0x30DF; +constexpr unsigned int mmRLC_PG_DELAY__CI = 0x310D; +constexpr unsigned int mmRLC_SAFE_MODE__CI = 0x313A; +constexpr unsigned int mmRLC_SAVE_AND_RESTORE_BASE__CI = 0x30DD; +constexpr unsigned int mmRLC_SAVE_AND_RESTORE_BASE__SI = 0x30C4; +constexpr unsigned int mmRLC_SERDES_CU_MASTER_BUSY__CI = 0x3121; +constexpr unsigned int mmRLC_SERDES_NONCU_MASTER_BUSY__CI = 0x3122; +constexpr unsigned int mmRLC_SERDES_RD_DATA_0__CI = 0x311A; +constexpr unsigned int mmRLC_SERDES_RD_DATA_0__SI = 0x3112; +constexpr unsigned int mmRLC_SERDES_RD_DATA_1__CI = 0x311B; +constexpr unsigned int mmRLC_SERDES_RD_DATA_1__SI = 0x3113; +constexpr unsigned int mmRLC_SERDES_RD_DATA_2__CI = 0x311C; +constexpr unsigned int mmRLC_SERDES_RD_DATA_2__SI = 0x3114; +constexpr unsigned int mmRLC_SERDES_RD_MASTER_INDEX__CI = 0x3119; +constexpr unsigned int mmRLC_SERDES_RD_MASTER_INDEX__SI = 0x3111; +constexpr unsigned int mmRLC_SERDES_WR_CTRL__CI = 0x311F; +constexpr unsigned int mmRLC_SERDES_WR_CTRL__SI = 0x3117; +constexpr unsigned int mmRLC_SERDES_WR_CU_MASTER_MASK__CI = 0x311D; +constexpr unsigned int mmRLC_SERDES_WR_DATA__CI = 0x3120; +constexpr unsigned int mmRLC_SERDES_WR_DATA__SI = 0x3118; +constexpr unsigned int mmRLC_SERDES_WR_NONCU_MASTER_MASK__CI = 0x311E; +constexpr unsigned int mmRLC_SMU_GRBM_REG_SAVE_CTRL__CI = 0x3116; +constexpr unsigned int mmRLC_SMU_GRBM_REG_SAVE_CTRL__SI = 0x310E; +constexpr unsigned int mmRLC_SMU_PG_CTRL__CI = 0x3117; +constexpr unsigned int mmRLC_SMU_PG_CTRL__SI = 0x310F; +constexpr unsigned int mmRLC_SMU_PG_WAKE_UP_CTRL__CI = 0x3118; +constexpr unsigned int mmRLC_SMU_PG_WAKE_UP_CTRL__SI = 0x3110; +constexpr unsigned int mmRLC_SOFT_RESET_GPU__CI = 0x30C5; +constexpr unsigned int mmRLC_SOFT_RESET_GPU__SI = 0x30D6; +constexpr unsigned int mmRLC_SPM_CB_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC8A; +constexpr unsigned int mmRLC_SPM_CPC_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC88; +constexpr unsigned int mmRLC_SPM_CPF_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC89; +constexpr unsigned int mmRLC_SPM_CPG_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC87; +constexpr unsigned int mmRLC_SPM_DB_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC8B; +constexpr unsigned int mmRLC_SPM_DEBUG_SELECT__CI = 0x3134; +constexpr unsigned int mmRLC_SPM_DEBUG__CI = 0x3135; +constexpr unsigned int mmRLC_SPM_GDS_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC8D; +constexpr unsigned int mmRLC_SPM_GLOBAL_MUXSEL_ADDR__CI__VI = 0xDC9B; +constexpr unsigned int mmRLC_SPM_GLOBAL_MUXSEL_DATA__CI__VI = 0xDC9C; +constexpr unsigned int mmRLC_SPM_IA_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC8E; +constexpr unsigned int mmRLC_SPM_INT_CNTL__CI = 0x3132; +constexpr unsigned int mmRLC_SPM_INT_STATUS__CI = 0x3133; +constexpr unsigned int mmRLC_SPM_PA_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC8C; +constexpr unsigned int mmRLC_SPM_PERFMON_CNTL__CI__VI = 0xDC80; +constexpr unsigned int mmRLC_SPM_PERFMON_RING_BASE_HI__CI__VI = 0xDC82; +constexpr unsigned int mmRLC_SPM_PERFMON_RING_BASE_LO__CI__VI = 0xDC81; +constexpr unsigned int mmRLC_SPM_PERFMON_RING_SIZE__CI__VI = 0xDC83; +constexpr unsigned int mmRLC_SPM_PERFMON_SEGMENT_SIZE__CI__VI = 0xDC84; +constexpr unsigned int mmRLC_SPM_RING_RDPTR__CI__VI = 0xDC9D; +constexpr unsigned int mmRLC_SPM_SC_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC90; +constexpr unsigned int mmRLC_SPM_SEGMENT_THRESHOLD__CI__VI = 0xDC9E; +constexpr unsigned int mmRLC_SPM_SE_MUXSEL_ADDR__CI__VI = 0xDC85; +constexpr unsigned int mmRLC_SPM_SE_MUXSEL_DATA__CI__VI = 0xDC86; +constexpr unsigned int mmRLC_SPM_SPI_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC97; +constexpr unsigned int mmRLC_SPM_SQG_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC98; +constexpr unsigned int mmRLC_SPM_SX_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC9A; +constexpr unsigned int mmRLC_SPM_TA_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC94; +constexpr unsigned int mmRLC_SPM_TCA_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC92; +constexpr unsigned int mmRLC_SPM_TCC_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC91; +constexpr unsigned int mmRLC_SPM_TCP_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC93; +constexpr unsigned int mmRLC_SPM_TCS_PERFMON_SAMPLE_DELAY__CI = 0xDC99; +constexpr unsigned int mmRLC_SPM_TD_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC95; +constexpr unsigned int mmRLC_SPM_VGT_PERFMON_SAMPLE_DELAY__CI__VI = 0xDC96; +constexpr unsigned int mmRLC_SPM_VMID__CI = 0x3131; +constexpr unsigned int mmRLC_STATIC_PG_STATUS__CI = 0x312E; +constexpr unsigned int mmRLC_STAT__CI = 0x30C4; +constexpr unsigned int mmRLC_STAT__SI = 0x30D3; +constexpr unsigned int mmRLC_THREAD1_DELAY__CI = 0x3112; +constexpr unsigned int mmRLC_THREAD1_DELAY__SI = 0x310A; +constexpr unsigned int mmRLC_UCODE_CNTL__CI = 0x30E7; +constexpr unsigned int mmRLC_UCODE_CNTL__SI = 0x30D2; +constexpr unsigned int mmROM_CNTL__SI = 0x0580; +constexpr unsigned int mmROM_DATA__SI = 0x002B; +constexpr unsigned int mmROM_INDEX__SI = 0x002A; +constexpr unsigned int mmROM_SMC_IND_DATA__CI__VI = 0x0081; +constexpr unsigned int mmROM_SMC_IND_INDEX__CI__VI = 0x0080; +constexpr unsigned int mmROM_START__SI = 0x0585; +constexpr unsigned int mmROM_STATUS__SI = 0x0582; +constexpr unsigned int mmROM_SW_CNTL__SI = 0x0586; +constexpr unsigned int mmROM_SW_COMMAND__SI = 0x0588; +constexpr unsigned int mmROM_SW_DATA_10__SI = 0x0592; +constexpr unsigned int mmROM_SW_DATA_11__SI = 0x0593; +constexpr unsigned int mmROM_SW_DATA_12__SI = 0x0594; +constexpr unsigned int mmROM_SW_DATA_13__SI = 0x0595; +constexpr unsigned int mmROM_SW_DATA_14__SI = 0x0596; +constexpr unsigned int mmROM_SW_DATA_15__SI = 0x0597; +constexpr unsigned int mmROM_SW_DATA_16__SI = 0x0598; +constexpr unsigned int mmROM_SW_DATA_17__SI = 0x0599; +constexpr unsigned int mmROM_SW_DATA_18__SI = 0x059A; +constexpr unsigned int mmROM_SW_DATA_19__SI = 0x059B; +constexpr unsigned int mmROM_SW_DATA_1__SI = 0x0589; +constexpr unsigned int mmROM_SW_DATA_20__SI = 0x059C; +constexpr unsigned int mmROM_SW_DATA_21__SI = 0x059D; +constexpr unsigned int mmROM_SW_DATA_22__SI = 0x059E; +constexpr unsigned int mmROM_SW_DATA_23__SI = 0x059F; +constexpr unsigned int mmROM_SW_DATA_24__SI = 0x05A0; +constexpr unsigned int mmROM_SW_DATA_25__SI = 0x05A1; +constexpr unsigned int mmROM_SW_DATA_26__SI = 0x05A2; +constexpr unsigned int mmROM_SW_DATA_27__SI = 0x05A3; +constexpr unsigned int mmROM_SW_DATA_28__SI = 0x05A4; +constexpr unsigned int mmROM_SW_DATA_29__SI = 0x05A5; +constexpr unsigned int mmROM_SW_DATA_2__SI = 0x058A; +constexpr unsigned int mmROM_SW_DATA_30__SI = 0x05A6; +constexpr unsigned int mmROM_SW_DATA_31__SI = 0x05A7; +constexpr unsigned int mmROM_SW_DATA_32__SI = 0x05A8; +constexpr unsigned int mmROM_SW_DATA_33__SI = 0x05A9; +constexpr unsigned int mmROM_SW_DATA_34__SI = 0x05AA; +constexpr unsigned int mmROM_SW_DATA_35__SI = 0x05AB; +constexpr unsigned int mmROM_SW_DATA_36__SI = 0x05AC; +constexpr unsigned int mmROM_SW_DATA_37__SI = 0x05AD; +constexpr unsigned int mmROM_SW_DATA_38__SI = 0x05AE; +constexpr unsigned int mmROM_SW_DATA_39__SI = 0x05AF; +constexpr unsigned int mmROM_SW_DATA_3__SI = 0x058B; +constexpr unsigned int mmROM_SW_DATA_40__SI = 0x05B0; +constexpr unsigned int mmROM_SW_DATA_41__SI = 0x05B1; +constexpr unsigned int mmROM_SW_DATA_42__SI = 0x05B2; +constexpr unsigned int mmROM_SW_DATA_43__SI = 0x05B3; +constexpr unsigned int mmROM_SW_DATA_44__SI = 0x05B4; +constexpr unsigned int mmROM_SW_DATA_45__SI = 0x05B5; +constexpr unsigned int mmROM_SW_DATA_46__SI = 0x05B6; +constexpr unsigned int mmROM_SW_DATA_47__SI = 0x05B7; +constexpr unsigned int mmROM_SW_DATA_48__SI = 0x05B8; +constexpr unsigned int mmROM_SW_DATA_49__SI = 0x05B9; +constexpr unsigned int mmROM_SW_DATA_4__SI = 0x058C; +constexpr unsigned int mmROM_SW_DATA_50__SI = 0x05BA; +constexpr unsigned int mmROM_SW_DATA_51__SI = 0x05BB; +constexpr unsigned int mmROM_SW_DATA_52__SI = 0x05BC; +constexpr unsigned int mmROM_SW_DATA_53__SI = 0x05BD; +constexpr unsigned int mmROM_SW_DATA_54__SI = 0x05BE; +constexpr unsigned int mmROM_SW_DATA_55__SI = 0x05BF; +constexpr unsigned int mmROM_SW_DATA_56__SI = 0x05C0; +constexpr unsigned int mmROM_SW_DATA_57__SI = 0x05C1; +constexpr unsigned int mmROM_SW_DATA_58__SI = 0x05C2; +constexpr unsigned int mmROM_SW_DATA_59__SI = 0x05C3; +constexpr unsigned int mmROM_SW_DATA_5__SI = 0x058D; +constexpr unsigned int mmROM_SW_DATA_60__SI = 0x05C4; +constexpr unsigned int mmROM_SW_DATA_61__SI = 0x05C5; +constexpr unsigned int mmROM_SW_DATA_62__SI = 0x05C6; +constexpr unsigned int mmROM_SW_DATA_63__SI = 0x05C7; +constexpr unsigned int mmROM_SW_DATA_64__SI = 0x05C8; +constexpr unsigned int mmROM_SW_DATA_6__SI = 0x058E; +constexpr unsigned int mmROM_SW_DATA_7__SI = 0x058F; +constexpr unsigned int mmROM_SW_DATA_8__SI = 0x0590; +constexpr unsigned int mmROM_SW_DATA_9__SI = 0x0591; +constexpr unsigned int mmROM_SW_STATUS__SI = 0x0587; +constexpr unsigned int mmSCL0_EXT_OVERSCAN_LEFT_RIGHT__SI__VI = 0x1B5E; +constexpr unsigned int mmSCL0_EXT_OVERSCAN_TOP_BOTTOM__SI__VI = 0x1B5F; +constexpr unsigned int mmSCL0_SCL_ALU_CONTROL__SI__VI = 0x1B54; +constexpr unsigned int mmSCL0_SCL_AUTOMATIC_MODE_CONTROL__SI__VI = 0x1B47; +constexpr unsigned int mmSCL0_SCL_BYPASS_CONTROL__SI__VI = 0x1B45; +constexpr unsigned int mmSCL0_SCL_COEF_RAM_CONFLICT_STATUS__SI__VI = 0x1B55; +constexpr unsigned int mmSCL0_SCL_COEF_RAM_SELECT__SI__VI = 0x1B40; +constexpr unsigned int mmSCL0_SCL_COEF_RAM_TAP_DATA__SI__VI = 0x1B41; +constexpr unsigned int mmSCL0_SCL_CONTROL__SI__VI = 0x1B44; +constexpr unsigned int mmSCL0_SCL_DEBUG__SI__VI = 0x1B6A; +constexpr unsigned int mmSCL0_SCL_F_SHARP_CONTROL__SI__VI = 0x1B53; +constexpr unsigned int mmSCL0_SCL_HORZ_FILTER_CONTROL__SI = 0x1B4A; +constexpr unsigned int mmSCL0_SCL_HORZ_FILTER_SCALE_RATIO__SI = 0x1B4B; +constexpr unsigned int mmSCL0_SCL_MANUAL_REPLICATE_CONTROL__SI__VI = 0x1B46; +constexpr unsigned int mmSCL0_SCL_MODE_CHANGE_DET1__SI__VI = 0x1B60; +constexpr unsigned int mmSCL0_SCL_MODE_CHANGE_DET2__SI__VI = 0x1B61; +constexpr unsigned int mmSCL0_SCL_MODE_CHANGE_DET3__SI__VI = 0x1B62; +constexpr unsigned int mmSCL0_SCL_MODE_CHANGE_MASK__SI__VI = 0x1B63; +constexpr unsigned int mmSCL0_SCL_TAP_CONTROL__SI__VI = 0x1B43; +constexpr unsigned int mmSCL0_SCL_TEST_DEBUG_DATA__SI__VI = 0x1B6C; +constexpr unsigned int mmSCL0_SCL_TEST_DEBUG_INDEX__SI__VI = 0x1B6B; +constexpr unsigned int mmSCL0_SCL_UPDATE__SI__VI = 0x1B51; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_CONTROL__SI = 0x1B4E; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_INIT_BOT__SI = 0x1B57; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_INIT__SI = 0x1B50; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_SCALE_RATIO__SI = 0x1B4F; +constexpr unsigned int mmSCL0_VIEWPORT_SIZE__SI__VI = 0x1B5D; +constexpr unsigned int mmSCL0_VIEWPORT_START__SI__VI = 0x1B5C; +constexpr unsigned int mmSCL1_EXT_OVERSCAN_LEFT_RIGHT__SI = 0x1E5E; +constexpr unsigned int mmSCL1_EXT_OVERSCAN_TOP_BOTTOM__SI = 0x1E5F; +constexpr unsigned int mmSCL1_SCL_ALU_CONTROL__SI = 0x1E54; +constexpr unsigned int mmSCL1_SCL_AUTOMATIC_MODE_CONTROL__SI = 0x1E47; +constexpr unsigned int mmSCL1_SCL_BYPASS_CONTROL__SI = 0x1E45; +constexpr unsigned int mmSCL1_SCL_COEF_RAM_CONFLICT_STATUS__SI = 0x1E55; +constexpr unsigned int mmSCL1_SCL_COEF_RAM_SELECT__SI = 0x1E40; +constexpr unsigned int mmSCL1_SCL_COEF_RAM_TAP_DATA__SI = 0x1E41; +constexpr unsigned int mmSCL1_SCL_CONTROL__SI = 0x1E44; +constexpr unsigned int mmSCL1_SCL_DEBUG__SI = 0x1E6A; +constexpr unsigned int mmSCL1_SCL_F_SHARP_CONTROL__SI = 0x1E53; +constexpr unsigned int mmSCL1_SCL_HORZ_FILTER_CONTROL__SI = 0x1E4A; +constexpr unsigned int mmSCL1_SCL_HORZ_FILTER_SCALE_RATIO__SI = 0x1E4B; +constexpr unsigned int mmSCL1_SCL_MANUAL_REPLICATE_CONTROL__SI = 0x1E46; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_DET1__SI = 0x1E60; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_DET2__SI = 0x1E61; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_DET3__SI = 0x1E62; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_MASK__SI = 0x1E63; +constexpr unsigned int mmSCL1_SCL_TAP_CONTROL__SI = 0x1E43; +constexpr unsigned int mmSCL1_SCL_TEST_DEBUG_DATA__SI = 0x1E6C; +constexpr unsigned int mmSCL1_SCL_TEST_DEBUG_INDEX__SI = 0x1E6B; +constexpr unsigned int mmSCL1_SCL_UPDATE__SI = 0x1E51; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_CONTROL__SI = 0x1E4E; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_INIT_BOT__SI = 0x1E57; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_INIT__SI = 0x1E50; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_SCALE_RATIO__SI = 0x1E4F; +constexpr unsigned int mmSCL1_VIEWPORT_SIZE__SI = 0x1E5D; +constexpr unsigned int mmSCL1_VIEWPORT_START__SI = 0x1E5C; +constexpr unsigned int mmSCL2_EXT_OVERSCAN_LEFT_RIGHT__SI = 0x415E; +constexpr unsigned int mmSCL2_EXT_OVERSCAN_TOP_BOTTOM__SI = 0x415F; +constexpr unsigned int mmSCL2_SCL_ALU_CONTROL__SI = 0x4154; +constexpr unsigned int mmSCL2_SCL_AUTOMATIC_MODE_CONTROL__SI = 0x4147; +constexpr unsigned int mmSCL2_SCL_BYPASS_CONTROL__SI = 0x4145; +constexpr unsigned int mmSCL2_SCL_COEF_RAM_CONFLICT_STATUS__SI = 0x4155; +constexpr unsigned int mmSCL2_SCL_COEF_RAM_SELECT__SI = 0x4140; +constexpr unsigned int mmSCL2_SCL_COEF_RAM_TAP_DATA__SI = 0x4141; +constexpr unsigned int mmSCL2_SCL_CONTROL__SI = 0x4144; +constexpr unsigned int mmSCL2_SCL_DEBUG__SI = 0x416A; +constexpr unsigned int mmSCL2_SCL_F_SHARP_CONTROL__SI = 0x4153; +constexpr unsigned int mmSCL2_SCL_HORZ_FILTER_CONTROL__SI = 0x414A; +constexpr unsigned int mmSCL2_SCL_HORZ_FILTER_SCALE_RATIO__SI = 0x414B; +constexpr unsigned int mmSCL2_SCL_MANUAL_REPLICATE_CONTROL__SI = 0x4146; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_DET1__SI = 0x4160; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_DET2__SI = 0x4161; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_DET3__SI = 0x4162; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_MASK__SI = 0x4163; +constexpr unsigned int mmSCL2_SCL_TAP_CONTROL__SI = 0x4143; +constexpr unsigned int mmSCL2_SCL_TEST_DEBUG_DATA__SI = 0x416C; +constexpr unsigned int mmSCL2_SCL_TEST_DEBUG_INDEX__SI = 0x416B; +constexpr unsigned int mmSCL2_SCL_UPDATE__SI = 0x4151; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_CONTROL__SI = 0x414E; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_INIT_BOT__SI = 0x4157; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_INIT__SI = 0x4150; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_SCALE_RATIO__SI = 0x414F; +constexpr unsigned int mmSCL2_VIEWPORT_SIZE__SI = 0x415D; +constexpr unsigned int mmSCL2_VIEWPORT_START__SI = 0x415C; +constexpr unsigned int mmSCL3_EXT_OVERSCAN_LEFT_RIGHT__SI = 0x445E; +constexpr unsigned int mmSCL3_EXT_OVERSCAN_TOP_BOTTOM__SI = 0x445F; +constexpr unsigned int mmSCL3_SCL_ALU_CONTROL__SI = 0x4454; +constexpr unsigned int mmSCL3_SCL_AUTOMATIC_MODE_CONTROL__SI = 0x4447; +constexpr unsigned int mmSCL3_SCL_BYPASS_CONTROL__SI = 0x4445; +constexpr unsigned int mmSCL3_SCL_COEF_RAM_CONFLICT_STATUS__SI = 0x4455; +constexpr unsigned int mmSCL3_SCL_COEF_RAM_SELECT__SI = 0x4440; +constexpr unsigned int mmSCL3_SCL_COEF_RAM_TAP_DATA__SI = 0x4441; +constexpr unsigned int mmSCL3_SCL_CONTROL__SI = 0x4444; +constexpr unsigned int mmSCL3_SCL_DEBUG__SI = 0x446A; +constexpr unsigned int mmSCL3_SCL_F_SHARP_CONTROL__SI = 0x4453; +constexpr unsigned int mmSCL3_SCL_HORZ_FILTER_CONTROL__SI = 0x444A; +constexpr unsigned int mmSCL3_SCL_HORZ_FILTER_SCALE_RATIO__SI = 0x444B; +constexpr unsigned int mmSCL3_SCL_MANUAL_REPLICATE_CONTROL__SI = 0x4446; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_DET1__SI = 0x4460; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_DET2__SI = 0x4461; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_DET3__SI = 0x4462; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_MASK__SI = 0x4463; +constexpr unsigned int mmSCL3_SCL_TAP_CONTROL__SI = 0x4443; +constexpr unsigned int mmSCL3_SCL_TEST_DEBUG_DATA__SI = 0x446C; +constexpr unsigned int mmSCL3_SCL_TEST_DEBUG_INDEX__SI = 0x446B; +constexpr unsigned int mmSCL3_SCL_UPDATE__SI = 0x4451; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_CONTROL__SI = 0x444E; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_INIT_BOT__SI = 0x4457; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_INIT__SI = 0x4450; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_SCALE_RATIO__SI = 0x444F; +constexpr unsigned int mmSCL3_VIEWPORT_SIZE__SI = 0x445D; +constexpr unsigned int mmSCL3_VIEWPORT_START__SI = 0x445C; +constexpr unsigned int mmSCL4_EXT_OVERSCAN_LEFT_RIGHT__SI = 0x475E; +constexpr unsigned int mmSCL4_EXT_OVERSCAN_TOP_BOTTOM__SI = 0x475F; +constexpr unsigned int mmSCL4_SCL_ALU_CONTROL__SI = 0x4754; +constexpr unsigned int mmSCL4_SCL_AUTOMATIC_MODE_CONTROL__SI = 0x4747; +constexpr unsigned int mmSCL4_SCL_BYPASS_CONTROL__SI = 0x4745; +constexpr unsigned int mmSCL4_SCL_COEF_RAM_CONFLICT_STATUS__SI = 0x4755; +constexpr unsigned int mmSCL4_SCL_COEF_RAM_SELECT__SI = 0x4740; +constexpr unsigned int mmSCL4_SCL_COEF_RAM_TAP_DATA__SI = 0x4741; +constexpr unsigned int mmSCL4_SCL_CONTROL__SI = 0x4744; +constexpr unsigned int mmSCL4_SCL_DEBUG__SI = 0x476A; +constexpr unsigned int mmSCL4_SCL_F_SHARP_CONTROL__SI = 0x4753; +constexpr unsigned int mmSCL4_SCL_HORZ_FILTER_CONTROL__SI = 0x474A; +constexpr unsigned int mmSCL4_SCL_HORZ_FILTER_SCALE_RATIO__SI = 0x474B; +constexpr unsigned int mmSCL4_SCL_MANUAL_REPLICATE_CONTROL__SI = 0x4746; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_DET1__SI = 0x4760; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_DET2__SI = 0x4761; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_DET3__SI = 0x4762; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_MASK__SI = 0x4763; +constexpr unsigned int mmSCL4_SCL_TAP_CONTROL__SI = 0x4743; +constexpr unsigned int mmSCL4_SCL_TEST_DEBUG_DATA__SI = 0x476C; +constexpr unsigned int mmSCL4_SCL_TEST_DEBUG_INDEX__SI = 0x476B; +constexpr unsigned int mmSCL4_SCL_UPDATE__SI = 0x4751; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_CONTROL__SI = 0x474E; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_INIT_BOT__SI = 0x4757; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_INIT__SI = 0x4750; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_SCALE_RATIO__SI = 0x474F; +constexpr unsigned int mmSCL4_VIEWPORT_SIZE__SI = 0x475D; +constexpr unsigned int mmSCL4_VIEWPORT_START__SI = 0x475C; +constexpr unsigned int mmSCL5_EXT_OVERSCAN_LEFT_RIGHT__SI = 0x4A5E; +constexpr unsigned int mmSCL5_EXT_OVERSCAN_TOP_BOTTOM__SI = 0x4A5F; +constexpr unsigned int mmSCL5_SCL_ALU_CONTROL__SI = 0x4A54; +constexpr unsigned int mmSCL5_SCL_AUTOMATIC_MODE_CONTROL__SI = 0x4A47; +constexpr unsigned int mmSCL5_SCL_BYPASS_CONTROL__SI = 0x4A45; +constexpr unsigned int mmSCL5_SCL_COEF_RAM_CONFLICT_STATUS__SI = 0x4A55; +constexpr unsigned int mmSCL5_SCL_COEF_RAM_SELECT__SI = 0x4A40; +constexpr unsigned int mmSCL5_SCL_COEF_RAM_TAP_DATA__SI = 0x4A41; +constexpr unsigned int mmSCL5_SCL_CONTROL__SI = 0x4A44; +constexpr unsigned int mmSCL5_SCL_DEBUG__SI = 0x4A6A; +constexpr unsigned int mmSCL5_SCL_F_SHARP_CONTROL__SI = 0x4A53; +constexpr unsigned int mmSCL5_SCL_HORZ_FILTER_CONTROL__SI = 0x4A4A; +constexpr unsigned int mmSCL5_SCL_HORZ_FILTER_SCALE_RATIO__SI = 0x4A4B; +constexpr unsigned int mmSCL5_SCL_MANUAL_REPLICATE_CONTROL__SI = 0x4A46; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_DET1__SI = 0x4A60; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_DET2__SI = 0x4A61; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_DET3__SI = 0x4A62; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_MASK__SI = 0x4A63; +constexpr unsigned int mmSCL5_SCL_TAP_CONTROL__SI = 0x4A43; +constexpr unsigned int mmSCL5_SCL_TEST_DEBUG_DATA__SI = 0x4A6C; +constexpr unsigned int mmSCL5_SCL_TEST_DEBUG_INDEX__SI = 0x4A6B; +constexpr unsigned int mmSCL5_SCL_UPDATE__SI = 0x4A51; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_CONTROL__SI = 0x4A4E; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_INIT_BOT__SI = 0x4A57; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_INIT__SI = 0x4A50; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_SCALE_RATIO__SI = 0x4A4F; +constexpr unsigned int mmSCL5_VIEWPORT_SIZE__SI = 0x4A5D; +constexpr unsigned int mmSCL5_VIEWPORT_START__SI = 0x4A5C; +constexpr unsigned int mmSCLK_CGTT_BLK_CTRL_REG__SI = 0x0129; +constexpr unsigned int mmSCLK_PWRMGT_CNTL__SI = 0x01E2; +constexpr unsigned int mmSCL_ALU_CONTROL__SI__VI = 0x1B54; +constexpr unsigned int mmSCL_AUTOMATIC_MODE_CONTROL__SI__VI = 0x1B47; +constexpr unsigned int mmSCL_BYPASS_CONTROL__SI__VI = 0x1B45; +constexpr unsigned int mmSCL_COEF_RAM_CONFLICT_STATUS__SI__VI = 0x1B55; +constexpr unsigned int mmSCL_COEF_RAM_SELECT__SI__VI = 0x1B40; +constexpr unsigned int mmSCL_COEF_RAM_TAP_DATA__SI__VI = 0x1B41; +constexpr unsigned int mmSCL_CONTROL__SI__VI = 0x1B44; +constexpr unsigned int mmSCL_DEBUG__SI__VI = 0x1B6A; +constexpr unsigned int mmSCL_F_SHARP_CONTROL__SI__VI = 0x1B53; +constexpr unsigned int mmSCL_HORZ_FILTER_CONTROL__SI = 0x1B4A; +constexpr unsigned int mmSCL_HORZ_FILTER_SCALE_RATIO__SI = 0x1B4B; +constexpr unsigned int mmSCL_MANUAL_REPLICATE_CONTROL__SI__VI = 0x1B46; +constexpr unsigned int mmSCL_MODE_CHANGE_DET1__SI__VI = 0x1B60; +constexpr unsigned int mmSCL_MODE_CHANGE_DET2__SI__VI = 0x1B61; +constexpr unsigned int mmSCL_MODE_CHANGE_DET3__SI__VI = 0x1B62; +constexpr unsigned int mmSCL_MODE_CHANGE_MASK__SI__VI = 0x1B63; +constexpr unsigned int mmSCL_TAP_CONTROL__SI__VI = 0x1B43; +constexpr unsigned int mmSCL_TEST_DEBUG_DATA__SI__VI = 0x1B6C; +constexpr unsigned int mmSCL_TEST_DEBUG_INDEX__SI__VI = 0x1B6B; +constexpr unsigned int mmSCL_UPDATE__SI__VI = 0x1B51; +constexpr unsigned int mmSCL_VERT_FILTER_CONTROL__SI = 0x1B4E; +constexpr unsigned int mmSCL_VERT_FILTER_INIT_BOT__SI = 0x1B57; +constexpr unsigned int mmSCL_VERT_FILTER_INIT__SI = 0x1B50; +constexpr unsigned int mmSCL_VERT_FILTER_SCALE_RATIO__SI = 0x1B4F; +constexpr unsigned int mmSCRATCH_ADDR__CI__VI = 0xC051; +constexpr unsigned int mmSCRATCH_ADDR__SI = 0x2151; +constexpr unsigned int mmSCRATCH_REG0__CI__VI = 0xC040; +constexpr unsigned int mmSCRATCH_REG0__SI = 0x2140; +constexpr unsigned int mmSCRATCH_REG1__CI__VI = 0xC041; +constexpr unsigned int mmSCRATCH_REG1__SI = 0x2141; +constexpr unsigned int mmSCRATCH_REG2__CI__VI = 0xC042; +constexpr unsigned int mmSCRATCH_REG2__SI = 0x2142; +constexpr unsigned int mmSCRATCH_REG3__CI__VI = 0xC043; +constexpr unsigned int mmSCRATCH_REG3__SI = 0x2143; +constexpr unsigned int mmSCRATCH_REG4__CI__VI = 0xC044; +constexpr unsigned int mmSCRATCH_REG4__SI = 0x2144; +constexpr unsigned int mmSCRATCH_REG5__CI__VI = 0xC045; +constexpr unsigned int mmSCRATCH_REG5__SI = 0x2145; +constexpr unsigned int mmSCRATCH_REG6__CI__VI = 0xC046; +constexpr unsigned int mmSCRATCH_REG6__SI = 0x2146; +constexpr unsigned int mmSCRATCH_REG7__CI__VI = 0xC047; +constexpr unsigned int mmSCRATCH_REG7__SI = 0x2147; +constexpr unsigned int mmSCRATCH_UMSK__CI__VI = 0xC050; +constexpr unsigned int mmSCRATCH_UMSK__SI = 0x2150; +constexpr unsigned int mmSDMA0_CHICKEN_BITS__CI__VI = 0x3405; +constexpr unsigned int mmSDMA0_CLK_CTRL__CI__VI = 0x3403; +constexpr unsigned int mmSDMA0_CNTL__CI__VI = 0x3404; +constexpr unsigned int mmSDMA0_F32_CNTL__CI__VI = 0x3412; +constexpr unsigned int mmSDMA0_FREEZE__CI__VI = 0x3413; +constexpr unsigned int mmSDMA0_GFX_APE1_CNTL__CI__VI = 0x34A8; +constexpr unsigned int mmSDMA0_GFX_CONTEXT_CNTL__CI__VI = 0x3493; +constexpr unsigned int mmSDMA0_GFX_CONTEXT_STATUS__CI__VI = 0x3491; +constexpr unsigned int mmSDMA0_GFX_IB_BASE_HI__CI__VI = 0x348E; +constexpr unsigned int mmSDMA0_GFX_IB_BASE_LO__CI__VI = 0x348D; +constexpr unsigned int mmSDMA0_GFX_IB_CNTL__CI__VI = 0x348A; +constexpr unsigned int mmSDMA0_GFX_IB_OFFSET__CI__VI = 0x348C; +constexpr unsigned int mmSDMA0_GFX_IB_RPTR__CI__VI = 0x348B; +constexpr unsigned int mmSDMA0_GFX_IB_SIZE__CI__VI = 0x348F; +constexpr unsigned int mmSDMA0_GFX_RB_BASE_HI__CI__VI = 0x3482; +constexpr unsigned int mmSDMA0_GFX_RB_BASE__CI__VI = 0x3481; +constexpr unsigned int mmSDMA0_GFX_RB_CNTL__CI__VI = 0x3480; +constexpr unsigned int mmSDMA0_GFX_RB_RPTR_ADDR_HI__CI__VI = 0x3488; +constexpr unsigned int mmSDMA0_GFX_RB_RPTR_ADDR_LO__CI__VI = 0x3489; +constexpr unsigned int mmSDMA0_GFX_RB_RPTR__CI__VI = 0x3483; +constexpr unsigned int mmSDMA0_GFX_RB_WPTR_POLL_ADDR_HI__CI__VI = 0x3486; +constexpr unsigned int mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO__CI__VI = 0x3487; +constexpr unsigned int mmSDMA0_GFX_RB_WPTR_POLL_CNTL__CI__VI = 0x3485; +constexpr unsigned int mmSDMA0_GFX_RB_WPTR__CI__VI = 0x3484; +constexpr unsigned int mmSDMA0_GFX_SKIP_CNTL__CI__VI = 0x3490; +constexpr unsigned int mmSDMA0_GFX_VIRTUAL_ADDR__CI__VI = 0x34A7; +constexpr unsigned int mmSDMA0_HASH__CI__VI = 0x3407; +constexpr unsigned int mmSDMA0_IB_OFFSET_FETCH__CI__VI = 0x340B; +constexpr unsigned int mmSDMA0_PERFCOUNTER0_RESULT__CI = 0x3410; +constexpr unsigned int mmSDMA0_PERFCOUNTER1_RESULT__CI = 0x3411; +constexpr unsigned int mmSDMA0_PERFMON_CNTL__CI = 0x340F; +constexpr unsigned int mmSDMA0_PHASE0_QUANTUM__CI__VI = 0x3414; +constexpr unsigned int mmSDMA0_PHASE1_QUANTUM__CI__VI = 0x3415; +constexpr unsigned int mmSDMA0_POWER_CNTL__CI__VI = 0x3402; +constexpr unsigned int mmSDMA0_PROGRAM__CI__VI = 0x340C; +constexpr unsigned int mmSDMA0_RB_RPTR_FETCH__CI__VI = 0x340A; +constexpr unsigned int mmSDMA0_RLC0_APE1_CNTL__CI__VI = 0x3528; +constexpr unsigned int mmSDMA0_RLC0_CONTEXT_STATUS__CI__VI = 0x3511; +constexpr unsigned int mmSDMA0_RLC0_DOORBELL_LOG__CI__VI = 0x3529; +constexpr unsigned int mmSDMA0_RLC0_DOORBELL__CI__VI = 0x3512; +constexpr unsigned int mmSDMA0_RLC0_IB_BASE_HI__CI__VI = 0x350E; +constexpr unsigned int mmSDMA0_RLC0_IB_BASE_LO__CI__VI = 0x350D; +constexpr unsigned int mmSDMA0_RLC0_IB_CNTL__CI__VI = 0x350A; +constexpr unsigned int mmSDMA0_RLC0_IB_OFFSET__CI__VI = 0x350C; +constexpr unsigned int mmSDMA0_RLC0_IB_RPTR__CI__VI = 0x350B; +constexpr unsigned int mmSDMA0_RLC0_IB_SIZE__CI__VI = 0x350F; +constexpr unsigned int mmSDMA0_RLC0_RB_BASE_HI__CI__VI = 0x3502; +constexpr unsigned int mmSDMA0_RLC0_RB_BASE__CI__VI = 0x3501; +constexpr unsigned int mmSDMA0_RLC0_RB_CNTL__CI__VI = 0x3500; +constexpr unsigned int mmSDMA0_RLC0_RB_RPTR_ADDR_HI__CI__VI = 0x3508; +constexpr unsigned int mmSDMA0_RLC0_RB_RPTR_ADDR_LO__CI__VI = 0x3509; +constexpr unsigned int mmSDMA0_RLC0_RB_RPTR__CI__VI = 0x3503; +constexpr unsigned int mmSDMA0_RLC0_RB_WPTR_POLL_ADDR_HI__CI__VI = 0x3506; +constexpr unsigned int mmSDMA0_RLC0_RB_WPTR_POLL_ADDR_LO__CI__VI = 0x3507; +constexpr unsigned int mmSDMA0_RLC0_RB_WPTR_POLL_CNTL__CI__VI = 0x3505; +constexpr unsigned int mmSDMA0_RLC0_RB_WPTR__CI__VI = 0x3504; +constexpr unsigned int mmSDMA0_RLC0_SKIP_CNTL__CI__VI = 0x3510; +constexpr unsigned int mmSDMA0_RLC0_VIRTUAL_ADDR__CI__VI = 0x3527; +constexpr unsigned int mmSDMA0_RLC1_APE1_CNTL__CI__VI = 0x35A8; +constexpr unsigned int mmSDMA0_RLC1_CONTEXT_STATUS__CI__VI = 0x3591; +constexpr unsigned int mmSDMA0_RLC1_DOORBELL_LOG__CI__VI = 0x35A9; +constexpr unsigned int mmSDMA0_RLC1_DOORBELL__CI__VI = 0x3592; +constexpr unsigned int mmSDMA0_RLC1_IB_BASE_HI__CI__VI = 0x358E; +constexpr unsigned int mmSDMA0_RLC1_IB_BASE_LO__CI__VI = 0x358D; +constexpr unsigned int mmSDMA0_RLC1_IB_CNTL__CI__VI = 0x358A; +constexpr unsigned int mmSDMA0_RLC1_IB_OFFSET__CI__VI = 0x358C; +constexpr unsigned int mmSDMA0_RLC1_IB_RPTR__CI__VI = 0x358B; +constexpr unsigned int mmSDMA0_RLC1_IB_SIZE__CI__VI = 0x358F; +constexpr unsigned int mmSDMA0_RLC1_RB_BASE_HI__CI__VI = 0x3582; +constexpr unsigned int mmSDMA0_RLC1_RB_BASE__CI__VI = 0x3581; +constexpr unsigned int mmSDMA0_RLC1_RB_CNTL__CI__VI = 0x3580; +constexpr unsigned int mmSDMA0_RLC1_RB_RPTR_ADDR_HI__CI__VI = 0x3588; +constexpr unsigned int mmSDMA0_RLC1_RB_RPTR_ADDR_LO__CI__VI = 0x3589; +constexpr unsigned int mmSDMA0_RLC1_RB_RPTR__CI__VI = 0x3583; +constexpr unsigned int mmSDMA0_RLC1_RB_WPTR_POLL_ADDR_HI__CI__VI = 0x3586; +constexpr unsigned int mmSDMA0_RLC1_RB_WPTR_POLL_ADDR_LO__CI__VI = 0x3587; +constexpr unsigned int mmSDMA0_RLC1_RB_WPTR_POLL_CNTL__CI__VI = 0x3585; +constexpr unsigned int mmSDMA0_RLC1_RB_WPTR__CI__VI = 0x3584; +constexpr unsigned int mmSDMA0_RLC1_SKIP_CNTL__CI__VI = 0x3590; +constexpr unsigned int mmSDMA0_RLC1_VIRTUAL_ADDR__CI__VI = 0x35A7; +constexpr unsigned int mmSDMA0_SEM_INCOMPLETE_TIMER_CNTL__CI = 0x3408; +constexpr unsigned int mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL__CI__VI = 0x3409; +constexpr unsigned int mmSDMA0_STATUS1_REG__CI__VI = 0x340E; +constexpr unsigned int mmSDMA0_STATUS_REG__CI__VI = 0x340D; +constexpr unsigned int mmSDMA0_TILING_CONFIG__CI__VI = 0x3406; +constexpr unsigned int mmSDMA0_UCODE_ADDR__CI__VI = 0x3400; +constexpr unsigned int mmSDMA0_UCODE_DATA__CI__VI = 0x3401; +constexpr unsigned int mmSDMA1_CHICKEN_BITS__CI__VI = 0x3605; +constexpr unsigned int mmSDMA1_CLK_CTRL__CI__VI = 0x3603; +constexpr unsigned int mmSDMA1_CNTL__CI__VI = 0x3604; +constexpr unsigned int mmSDMA1_CONFIG__CI__VI = 0x0F92; +constexpr unsigned int mmSDMA1_F32_CNTL__CI__VI = 0x3612; +constexpr unsigned int mmSDMA1_FREEZE__CI__VI = 0x3613; +constexpr unsigned int mmSDMA1_GFX_APE1_CNTL__CI__VI = 0x36A8; +constexpr unsigned int mmSDMA1_GFX_CONTEXT_CNTL__CI__VI = 0x3693; +constexpr unsigned int mmSDMA1_GFX_CONTEXT_STATUS__CI__VI = 0x3691; +constexpr unsigned int mmSDMA1_GFX_IB_BASE_HI__CI__VI = 0x368E; +constexpr unsigned int mmSDMA1_GFX_IB_BASE_LO__CI__VI = 0x368D; +constexpr unsigned int mmSDMA1_GFX_IB_CNTL__CI__VI = 0x368A; +constexpr unsigned int mmSDMA1_GFX_IB_OFFSET__CI__VI = 0x368C; +constexpr unsigned int mmSDMA1_GFX_IB_RPTR__CI__VI = 0x368B; +constexpr unsigned int mmSDMA1_GFX_IB_SIZE__CI__VI = 0x368F; +constexpr unsigned int mmSDMA1_GFX_RB_BASE_HI__CI__VI = 0x3682; +constexpr unsigned int mmSDMA1_GFX_RB_BASE__CI__VI = 0x3681; +constexpr unsigned int mmSDMA1_GFX_RB_CNTL__CI__VI = 0x3680; +constexpr unsigned int mmSDMA1_GFX_RB_RPTR_ADDR_HI__CI__VI = 0x3688; +constexpr unsigned int mmSDMA1_GFX_RB_RPTR_ADDR_LO__CI__VI = 0x3689; +constexpr unsigned int mmSDMA1_GFX_RB_RPTR__CI__VI = 0x3683; +constexpr unsigned int mmSDMA1_GFX_RB_WPTR_POLL_ADDR_HI__CI__VI = 0x3686; +constexpr unsigned int mmSDMA1_GFX_RB_WPTR_POLL_ADDR_LO__CI__VI = 0x3687; +constexpr unsigned int mmSDMA1_GFX_RB_WPTR_POLL_CNTL__CI__VI = 0x3685; +constexpr unsigned int mmSDMA1_GFX_RB_WPTR__CI__VI = 0x3684; +constexpr unsigned int mmSDMA1_GFX_SKIP_CNTL__CI__VI = 0x3690; +constexpr unsigned int mmSDMA1_GFX_VIRTUAL_ADDR__CI__VI = 0x36A7; +constexpr unsigned int mmSDMA1_HASH__CI__VI = 0x3607; +constexpr unsigned int mmSDMA1_IB_OFFSET_FETCH__CI__VI = 0x360B; +constexpr unsigned int mmSDMA1_PERFCOUNTER0_RESULT__CI = 0x3610; +constexpr unsigned int mmSDMA1_PERFCOUNTER1_RESULT__CI = 0x3611; +constexpr unsigned int mmSDMA1_PERFMON_CNTL__CI = 0x360F; +constexpr unsigned int mmSDMA1_PHASE0_QUANTUM__CI__VI = 0x3614; +constexpr unsigned int mmSDMA1_PHASE1_QUANTUM__CI__VI = 0x3615; +constexpr unsigned int mmSDMA1_POWER_CNTL__CI__VI = 0x3602; +constexpr unsigned int mmSDMA1_PROGRAM__CI__VI = 0x360C; +constexpr unsigned int mmSDMA1_RB_RPTR_FETCH__CI__VI = 0x360A; +constexpr unsigned int mmSDMA1_RLC0_APE1_CNTL__CI__VI = 0x3728; +constexpr unsigned int mmSDMA1_RLC0_CONTEXT_STATUS__CI__VI = 0x3711; +constexpr unsigned int mmSDMA1_RLC0_DOORBELL_LOG__CI__VI = 0x3729; +constexpr unsigned int mmSDMA1_RLC0_DOORBELL__CI__VI = 0x3712; +constexpr unsigned int mmSDMA1_RLC0_IB_BASE_HI__CI__VI = 0x370E; +constexpr unsigned int mmSDMA1_RLC0_IB_BASE_LO__CI__VI = 0x370D; +constexpr unsigned int mmSDMA1_RLC0_IB_CNTL__CI__VI = 0x370A; +constexpr unsigned int mmSDMA1_RLC0_IB_OFFSET__CI__VI = 0x370C; +constexpr unsigned int mmSDMA1_RLC0_IB_RPTR__CI__VI = 0x370B; +constexpr unsigned int mmSDMA1_RLC0_IB_SIZE__CI__VI = 0x370F; +constexpr unsigned int mmSDMA1_RLC0_RB_BASE_HI__CI__VI = 0x3702; +constexpr unsigned int mmSDMA1_RLC0_RB_BASE__CI__VI = 0x3701; +constexpr unsigned int mmSDMA1_RLC0_RB_CNTL__CI__VI = 0x3700; +constexpr unsigned int mmSDMA1_RLC0_RB_RPTR_ADDR_HI__CI__VI = 0x3708; +constexpr unsigned int mmSDMA1_RLC0_RB_RPTR_ADDR_LO__CI__VI = 0x3709; +constexpr unsigned int mmSDMA1_RLC0_RB_RPTR__CI__VI = 0x3703; +constexpr unsigned int mmSDMA1_RLC0_RB_WPTR_POLL_ADDR_HI__CI__VI = 0x3706; +constexpr unsigned int mmSDMA1_RLC0_RB_WPTR_POLL_ADDR_LO__CI__VI = 0x3707; +constexpr unsigned int mmSDMA1_RLC0_RB_WPTR_POLL_CNTL__CI__VI = 0x3705; +constexpr unsigned int mmSDMA1_RLC0_RB_WPTR__CI__VI = 0x3704; +constexpr unsigned int mmSDMA1_RLC0_SKIP_CNTL__CI__VI = 0x3710; +constexpr unsigned int mmSDMA1_RLC0_VIRTUAL_ADDR__CI__VI = 0x3727; +constexpr unsigned int mmSDMA1_RLC1_APE1_CNTL__CI__VI = 0x37A8; +constexpr unsigned int mmSDMA1_RLC1_CONTEXT_STATUS__CI__VI = 0x3791; +constexpr unsigned int mmSDMA1_RLC1_DOORBELL_LOG__CI__VI = 0x37A9; +constexpr unsigned int mmSDMA1_RLC1_DOORBELL__CI__VI = 0x3792; +constexpr unsigned int mmSDMA1_RLC1_IB_BASE_HI__CI__VI = 0x378E; +constexpr unsigned int mmSDMA1_RLC1_IB_BASE_LO__CI__VI = 0x378D; +constexpr unsigned int mmSDMA1_RLC1_IB_CNTL__CI__VI = 0x378A; +constexpr unsigned int mmSDMA1_RLC1_IB_OFFSET__CI__VI = 0x378C; +constexpr unsigned int mmSDMA1_RLC1_IB_RPTR__CI__VI = 0x378B; +constexpr unsigned int mmSDMA1_RLC1_IB_SIZE__CI__VI = 0x378F; +constexpr unsigned int mmSDMA1_RLC1_RB_BASE_HI__CI__VI = 0x3782; +constexpr unsigned int mmSDMA1_RLC1_RB_BASE__CI__VI = 0x3781; +constexpr unsigned int mmSDMA1_RLC1_RB_CNTL__CI__VI = 0x3780; +constexpr unsigned int mmSDMA1_RLC1_RB_RPTR_ADDR_HI__CI__VI = 0x3788; +constexpr unsigned int mmSDMA1_RLC1_RB_RPTR_ADDR_LO__CI__VI = 0x3789; +constexpr unsigned int mmSDMA1_RLC1_RB_RPTR__CI__VI = 0x3783; +constexpr unsigned int mmSDMA1_RLC1_RB_WPTR_POLL_ADDR_HI__CI__VI = 0x3786; +constexpr unsigned int mmSDMA1_RLC1_RB_WPTR_POLL_ADDR_LO__CI__VI = 0x3787; +constexpr unsigned int mmSDMA1_RLC1_RB_WPTR_POLL_CNTL__CI__VI = 0x3785; +constexpr unsigned int mmSDMA1_RLC1_RB_WPTR__CI__VI = 0x3784; +constexpr unsigned int mmSDMA1_RLC1_SKIP_CNTL__CI__VI = 0x3790; +constexpr unsigned int mmSDMA1_RLC1_VIRTUAL_ADDR__CI__VI = 0x37A7; +constexpr unsigned int mmSDMA1_SEM_INCOMPLETE_TIMER_CNTL__CI = 0x3608; +constexpr unsigned int mmSDMA1_SEM_WAIT_FAIL_TIMER_CNTL__CI__VI = 0x3609; +constexpr unsigned int mmSDMA1_STATUS1_REG__CI__VI = 0x360E; +constexpr unsigned int mmSDMA1_STATUS_REG__CI__VI = 0x360D; +constexpr unsigned int mmSDMA1_TILING_CONFIG__CI__VI = 0x3606; +constexpr unsigned int mmSDMA1_UCODE_ADDR__CI__VI = 0x3600; +constexpr unsigned int mmSDMA1_UCODE_DATA__CI__VI = 0x3601; +constexpr unsigned int mmSDMA_CONFIG__CI__VI = 0x0F91; +constexpr unsigned int mmSDMA_PGFSM_CONFIG__CI__VI = 0x3417; +constexpr unsigned int mmSDMA_PGFSM_READ__CI__VI = 0x3419; +constexpr unsigned int mmSDMA_PGFSM_WRITE__CI__VI = 0x3418; +constexpr unsigned int mmSDMA_POWER_GATING__CI__VI = 0x3416; +constexpr unsigned int mmSEM_CHICKEN_BITS__CI__VI = 0x0F9E; +constexpr unsigned int mmSEM_EDC_CONFIG__CI__VI = 0x0F9A; +constexpr unsigned int mmSEM_MAILBOX_CLIENTCONFIG__CI__VI = 0x0F9B; +constexpr unsigned int mmSEM_MAILBOX_CLIENTCONFIG__SI = 0x0F9A; +constexpr unsigned int mmSEM_MAILBOX_CONTROL__CI__VI = 0x0F9D; +constexpr unsigned int mmSEM_MAILBOX_CONTROL__SI = 0x0F9C; +constexpr unsigned int mmSEM_MAILBOX__CI__VI = 0x0F9C; +constexpr unsigned int mmSEM_MAILBOX__SI = 0x0F9B; +constexpr unsigned int mmSEM_MCIF_CONFIG = 0x0F90; +constexpr unsigned int mmSEM_STATUS__CI__VI = 0x0F99; +constexpr unsigned int mmSEQ8_DATA__SI__VI = 0x00F1; +constexpr unsigned int mmSEQ8_IDX__SI__VI = 0x00F1; +constexpr unsigned int mmSH_HIDDEN_PRIVATE_BASE_VMID__CI__VI = 0x2580; +constexpr unsigned int mmSH_MEM_APE1_BASE__CI__VI = 0x230B; +constexpr unsigned int mmSH_MEM_APE1_LIMIT__CI__VI = 0x230C; +constexpr unsigned int mmSH_MEM_BASES__CI__VI = 0x230A; +constexpr unsigned int mmSH_MEM_CONFIG__CI__VI = 0x230D; +constexpr unsigned int mmSH_STATIC_MEM_CONFIG__CI__VI = 0x2581; +constexpr unsigned int mmSLAVE_COMM_CMD_REG__SI__VI = 0x1624; +constexpr unsigned int mmSLAVE_COMM_CNTL_REG__SI__VI = 0x1625; +constexpr unsigned int mmSLAVE_COMM_DATA_REG1__SI__VI = 0x1621; +constexpr unsigned int mmSLAVE_COMM_DATA_REG2__SI__VI = 0x1622; +constexpr unsigned int mmSLAVE_COMM_DATA_REG3__SI__VI = 0x1623; +constexpr unsigned int mmSLAVE_HANG_ERROR = 0x153B; +constexpr unsigned int mmSLAVE_HANG_PROTECTION_CNTL = 0x1536; +constexpr unsigned int mmSLAVE_REQ_CREDIT_CNTL = 0x1517; +constexpr unsigned int mmSMBCLK_PAD_CNTL__CI = 0x1523; +constexpr unsigned int mmSMBDAT_PAD_CNTL__CI = 0x1522; +constexpr unsigned int mmSMBUS_SLV_CNTL__CI = 0x14FD; +constexpr unsigned int mmSMC_IND_ACCESS_CNTL__CI__VI = 0x0090; +constexpr unsigned int mmSMC_IND_ACCESS_CNTL__SI = 0x008A; +constexpr unsigned int mmSMC_IND_DATA = 0x0081; +constexpr unsigned int mmSMC_IND_DATA_0__CI__VI = 0x0081; +constexpr unsigned int mmSMC_IND_DATA_1__CI__VI = 0x0083; +constexpr unsigned int mmSMC_IND_DATA_2__CI__VI = 0x0085; +constexpr unsigned int mmSMC_IND_DATA_3__CI__VI = 0x0087; +constexpr unsigned int mmSMC_IND_DATA_4__CI__VI = 0x0089; +constexpr unsigned int mmSMC_IND_DATA_5__CI__VI = 0x008B; +constexpr unsigned int mmSMC_IND_DATA_6__CI__VI = 0x008D; +constexpr unsigned int mmSMC_IND_DATA_7__CI__VI = 0x008F; +constexpr unsigned int mmSMC_IND_INDEX = 0x0080; +constexpr unsigned int mmSMC_IND_INDEX_0__CI__VI = 0x0080; +constexpr unsigned int mmSMC_IND_INDEX_1__CI__VI = 0x0082; +constexpr unsigned int mmSMC_IND_INDEX_2__CI__VI = 0x0084; +constexpr unsigned int mmSMC_IND_INDEX_3__CI__VI = 0x0086; +constexpr unsigned int mmSMC_IND_INDEX_4__CI__VI = 0x0088; +constexpr unsigned int mmSMC_IND_INDEX_5__CI__VI = 0x008A; +constexpr unsigned int mmSMC_IND_INDEX_6__CI__VI = 0x008C; +constexpr unsigned int mmSMC_IND_INDEX_7__CI__VI = 0x008E; +constexpr unsigned int mmSMC_MESSAGE_0__CI__VI = 0x0094; +constexpr unsigned int mmSMC_MESSAGE_0__SI = 0x008B; +constexpr unsigned int mmSMC_MESSAGE_10__CI__VI = 0x00B9; +constexpr unsigned int mmSMC_MESSAGE_11__CI__VI = 0x00BB; +constexpr unsigned int mmSMC_MESSAGE_1__CI__VI = 0x0096; +constexpr unsigned int mmSMC_MESSAGE_1__SI = 0x008D; +constexpr unsigned int mmSMC_MESSAGE_2__CI__VI = 0x0098; +constexpr unsigned int mmSMC_MESSAGE_3__CI__VI = 0x009A; +constexpr unsigned int mmSMC_MESSAGE_4__CI__VI = 0x009C; +constexpr unsigned int mmSMC_MESSAGE_5__CI__VI = 0x009E; +constexpr unsigned int mmSMC_MESSAGE_6__CI__VI = 0x00A0; +constexpr unsigned int mmSMC_MESSAGE_7__CI__VI = 0x00A2; +constexpr unsigned int mmSMC_MESSAGE_8__CI__VI = 0x00B5; +constexpr unsigned int mmSMC_MESSAGE_9__CI__VI = 0x00B7; +constexpr unsigned int mmSMC_MSG_ARG_0__CI__VI = 0x00A4; +constexpr unsigned int mmSMC_MSG_ARG_10__CI__VI = 0x00BF; +constexpr unsigned int mmSMC_MSG_ARG_11__CI = 0x0091; +constexpr unsigned int mmSMC_MSG_ARG_1__CI__VI = 0x00A5; +constexpr unsigned int mmSMC_MSG_ARG_2__CI__VI = 0x00A6; +constexpr unsigned int mmSMC_MSG_ARG_3__CI__VI = 0x00A7; +constexpr unsigned int mmSMC_MSG_ARG_4__CI__VI = 0x00A8; +constexpr unsigned int mmSMC_MSG_ARG_5__CI__VI = 0x00A9; +constexpr unsigned int mmSMC_MSG_ARG_6__CI__VI = 0x00AA; +constexpr unsigned int mmSMC_MSG_ARG_7__CI__VI = 0x00AB; +constexpr unsigned int mmSMC_MSG_ARG_8__CI__VI = 0x00BD; +constexpr unsigned int mmSMC_MSG_ARG_9__CI__VI = 0x00BE; +constexpr unsigned int mmSMC_RESP_0__CI__VI = 0x0095; +constexpr unsigned int mmSMC_RESP_0__SI = 0x008C; +constexpr unsigned int mmSMC_RESP_10__CI__VI = 0x00BA; +constexpr unsigned int mmSMC_RESP_11__CI__VI = 0x00BC; +constexpr unsigned int mmSMC_RESP_1__CI__VI = 0x0097; +constexpr unsigned int mmSMC_RESP_1__SI = 0x008E; +constexpr unsigned int mmSMC_RESP_2__CI__VI = 0x0099; +constexpr unsigned int mmSMC_RESP_3__CI__VI = 0x009B; +constexpr unsigned int mmSMC_RESP_4__CI__VI = 0x009D; +constexpr unsigned int mmSMC_RESP_5__CI__VI = 0x009F; +constexpr unsigned int mmSMC_RESP_6__CI__VI = 0x00A1; +constexpr unsigned int mmSMC_RESP_7__CI__VI = 0x00A3; +constexpr unsigned int mmSMC_RESP_8__CI__VI = 0x00B6; +constexpr unsigned int mmSMC_RESP_9__CI__VI = 0x00B8; +constexpr unsigned int mmSMC_SCRATCH9__SI = 0x022A; +constexpr unsigned int mmSMU_SMC_IND_DATA__CI__VI = 0x0081; +constexpr unsigned int mmSMU_SMC_IND_INDEX__CI__VI = 0x0080; +constexpr unsigned int mmSPI_ARB_CYCLES_0__CI__VI = 0x31C1; +constexpr unsigned int mmSPI_ARB_CYCLES_0__SI = 0x243D; +constexpr unsigned int mmSPI_ARB_CYCLES_1__CI__VI = 0x31C2; +constexpr unsigned int mmSPI_ARB_CYCLES_1__SI = 0x243E; +constexpr unsigned int mmSPI_ARB_PRIORITY__CI__VI = 0x31C0; +constexpr unsigned int mmSPI_ARB_PRIORITY__SI = 0x243C; +constexpr unsigned int mmSPI_BARYC_CNTL = 0xA1B8; +constexpr unsigned int mmSPI_CDBG_SYS_CS0__CI__VI = 0x31C5; +constexpr unsigned int mmSPI_CDBG_SYS_CS1__CI__VI = 0x31C6; +constexpr unsigned int mmSPI_CDBG_SYS_GFX__CI__VI = 0x31C3; +constexpr unsigned int mmSPI_CDBG_SYS_HP3D__CI__VI = 0x31C4; +constexpr unsigned int mmSPI_COMPUTE_QUEUE_RESET__CI__VI = 0x31DB; +constexpr unsigned int mmSPI_CONFIG_CNTL = 0x2440; +constexpr unsigned int mmSPI_CONFIG_CNTL_1 = 0x244F; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_0__CI__VI = 0x24DC; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_1__CI__VI = 0x24DD; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_2__CI__VI = 0x24DE; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_3__CI__VI = 0x24DF; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_4__CI__VI = 0x24E0; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_5__CI__VI = 0x24E1; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_6__CI__VI = 0x24E2; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_COUNT_7__CI__VI = 0x24E3; +constexpr unsigned int mmSPI_CSQ_WF_ACTIVE_STATUS__CI__VI = 0x24DB; +constexpr unsigned int mmSPI_DEBUG_BUSY = 0x2450; +constexpr unsigned int mmSPI_DEBUG_CNTL = 0x2441; +constexpr unsigned int mmSPI_DEBUG_READ = 0x2442; +constexpr unsigned int mmSPI_GDBG_TBA_HI__CI__VI = 0x31D5; +constexpr unsigned int mmSPI_GDBG_TBA_LO__CI__VI = 0x31D4; +constexpr unsigned int mmSPI_GDBG_TMA_HI__CI__VI = 0x31D7; +constexpr unsigned int mmSPI_GDBG_TMA_LO__CI__VI = 0x31D6; +constexpr unsigned int mmSPI_GDBG_TRAP_CONFIG__CI__VI = 0x31D2; +constexpr unsigned int mmSPI_GDBG_TRAP_DATA0__CI__VI = 0x31D8; +constexpr unsigned int mmSPI_GDBG_TRAP_DATA1__CI__VI = 0x31D9; +constexpr unsigned int mmSPI_GDBG_TRAP_MASK__CI__VI = 0x31D3; +constexpr unsigned int mmSPI_GDBG_WAVE_CNTL__CI__VI = 0x31D1; +constexpr unsigned int mmSPI_GDS_CREDITS = 0x24D8; +constexpr unsigned int mmSPI_INTERP_CONTROL_0 = 0xA1B5; +constexpr unsigned int mmSPI_LB_CTR_CTRL = 0x24D4; +constexpr unsigned int mmSPI_LB_CU_MASK = 0x24D5; +constexpr unsigned int mmSPI_LB_DATA_REG = 0x24D6; +constexpr unsigned int mmSPI_P0_TRAP_SCREEN_GPR_MIN__CI__VI = 0x24F0; +constexpr unsigned int mmSPI_P0_TRAP_SCREEN_PSBA_HI__CI__VI = 0x24ED; +constexpr unsigned int mmSPI_P0_TRAP_SCREEN_PSBA_LO__CI__VI = 0x24EC; +constexpr unsigned int mmSPI_P0_TRAP_SCREEN_PSMA_HI__CI__VI = 0x24EF; +constexpr unsigned int mmSPI_P0_TRAP_SCREEN_PSMA_LO__CI__VI = 0x24EE; +constexpr unsigned int mmSPI_P1_TRAP_SCREEN_GPR_MIN__CI__VI = 0x24F5; +constexpr unsigned int mmSPI_P1_TRAP_SCREEN_PSBA_HI__CI__VI = 0x24F2; +constexpr unsigned int mmSPI_P1_TRAP_SCREEN_PSBA_LO__CI__VI = 0x24F1; +constexpr unsigned int mmSPI_P1_TRAP_SCREEN_PSMA_HI__CI__VI = 0x24F4; +constexpr unsigned int mmSPI_P1_TRAP_SCREEN_PSMA_LO__CI__VI = 0x24F3; +constexpr unsigned int mmSPI_PERFCOUNTER0_HI__CI__VI = 0xD180; +constexpr unsigned int mmSPI_PERFCOUNTER0_HI__SI = 0x2447; +constexpr unsigned int mmSPI_PERFCOUNTER0_LO__CI__VI = 0xD181; +constexpr unsigned int mmSPI_PERFCOUNTER0_LO__SI = 0x2448; +constexpr unsigned int mmSPI_PERFCOUNTER0_SELECT1__CI__VI = 0xD984; +constexpr unsigned int mmSPI_PERFCOUNTER0_SELECT__CI__VI = 0xD980; +constexpr unsigned int mmSPI_PERFCOUNTER0_SELECT__SI = 0x2443; +constexpr unsigned int mmSPI_PERFCOUNTER1_HI__CI__VI = 0xD182; +constexpr unsigned int mmSPI_PERFCOUNTER1_HI__SI = 0x2449; +constexpr unsigned int mmSPI_PERFCOUNTER1_LO__CI__VI = 0xD183; +constexpr unsigned int mmSPI_PERFCOUNTER1_LO__SI = 0x244A; +constexpr unsigned int mmSPI_PERFCOUNTER1_SELECT1__CI__VI = 0xD985; +constexpr unsigned int mmSPI_PERFCOUNTER1_SELECT__CI__VI = 0xD981; +constexpr unsigned int mmSPI_PERFCOUNTER1_SELECT__SI = 0x2444; +constexpr unsigned int mmSPI_PERFCOUNTER2_HI__CI__VI = 0xD184; +constexpr unsigned int mmSPI_PERFCOUNTER2_HI__SI = 0x244B; +constexpr unsigned int mmSPI_PERFCOUNTER2_LO__CI__VI = 0xD185; +constexpr unsigned int mmSPI_PERFCOUNTER2_LO__SI = 0x244C; +constexpr unsigned int mmSPI_PERFCOUNTER2_SELECT1__CI__VI = 0xD986; +constexpr unsigned int mmSPI_PERFCOUNTER2_SELECT__CI__VI = 0xD982; +constexpr unsigned int mmSPI_PERFCOUNTER2_SELECT__SI = 0x2445; +constexpr unsigned int mmSPI_PERFCOUNTER3_HI__CI__VI = 0xD186; +constexpr unsigned int mmSPI_PERFCOUNTER3_HI__SI = 0x244D; +constexpr unsigned int mmSPI_PERFCOUNTER3_LO__CI__VI = 0xD187; +constexpr unsigned int mmSPI_PERFCOUNTER3_LO__SI = 0x244E; +constexpr unsigned int mmSPI_PERFCOUNTER3_SELECT1__CI__VI = 0xD987; +constexpr unsigned int mmSPI_PERFCOUNTER3_SELECT__CI__VI = 0xD983; +constexpr unsigned int mmSPI_PERFCOUNTER3_SELECT__SI = 0x2446; +constexpr unsigned int mmSPI_PERFCOUNTER4_HI__CI__VI = 0xD188; +constexpr unsigned int mmSPI_PERFCOUNTER4_LO__CI__VI = 0xD189; +constexpr unsigned int mmSPI_PERFCOUNTER4_SELECT__CI__VI = 0xD988; +constexpr unsigned int mmSPI_PERFCOUNTER5_HI__CI__VI = 0xD18A; +constexpr unsigned int mmSPI_PERFCOUNTER5_LO__CI__VI = 0xD18B; +constexpr unsigned int mmSPI_PERFCOUNTER5_SELECT__CI__VI = 0xD989; +constexpr unsigned int mmSPI_PERFCOUNTER_BINS__CI__VI = 0xD98A; +constexpr unsigned int mmSPI_PERFCOUNTER_BINS__SI = 0x243F; +constexpr unsigned int mmSPI_PG_ENABLE_STATIC_CU_MASK = 0x24D7; +constexpr unsigned int mmSPI_PS_INPUT_ADDR = 0xA1B4; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_0 = 0xA191; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_1 = 0xA192; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_10 = 0xA19B; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_11 = 0xA19C; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_12 = 0xA19D; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_13 = 0xA19E; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_14 = 0xA19F; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_15 = 0xA1A0; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_16 = 0xA1A1; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_17 = 0xA1A2; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_18 = 0xA1A3; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_19 = 0xA1A4; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_2 = 0xA193; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_20 = 0xA1A5; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_21 = 0xA1A6; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_22 = 0xA1A7; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_23 = 0xA1A8; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_24 = 0xA1A9; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_25 = 0xA1AA; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_26 = 0xA1AB; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_27 = 0xA1AC; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_28 = 0xA1AD; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_29 = 0xA1AE; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_3 = 0xA194; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_30 = 0xA1AF; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_31 = 0xA1B0; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_4 = 0xA195; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_5 = 0xA196; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_6 = 0xA197; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_7 = 0xA198; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_8 = 0xA199; +constexpr unsigned int mmSPI_PS_INPUT_CNTL_9 = 0xA19A; +constexpr unsigned int mmSPI_PS_INPUT_ENA = 0xA1B3; +constexpr unsigned int mmSPI_PS_IN_CONTROL = 0xA1B6; +constexpr unsigned int mmSPI_PS_MAX_WAVE_ID__CI__VI = 0x243A; +constexpr unsigned int mmSPI_PS_MAX_WAVE_ID__SI = 0x243B; +constexpr unsigned int mmSPI_RESET_DEBUG__CI__VI = 0x31DA; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_0__CI__VI = 0x31DC; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_10__CI__VI = 0x31F0; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_11__CI__VI = 0x31F1; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_1__CI__VI = 0x31DD; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_2__CI__VI = 0x31DE; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_3__CI__VI = 0x31DF; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_4__CI__VI = 0x31E0; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_5__CI__VI = 0x31E1; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_6__CI__VI = 0x31E2; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_7__CI__VI = 0x31E3; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_8__CI__VI = 0x31E4; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_9__CI__VI = 0x31E5; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_0__CI__VI = 0x31E6; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_10__CI__VI = 0x31F2; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_11__CI__VI = 0x31F3; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_1__CI__VI = 0x31E7; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_2__CI__VI = 0x31E8; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_3__CI__VI = 0x31E9; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_4__CI__VI = 0x31EA; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_5__CI__VI = 0x31EB; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_6__CI__VI = 0x31EC; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_7__CI__VI = 0x31ED; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_8__CI__VI = 0x31EE; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_9__CI__VI = 0x31EF; +constexpr unsigned int mmSPI_SHADER_COL_FORMAT = 0xA1C5; +constexpr unsigned int mmSPI_SHADER_LATE_ALLOC_VS__CI__VI = 0x2C47; +constexpr unsigned int mmSPI_SHADER_PGM_HI_ES = 0x2CC9; +constexpr unsigned int mmSPI_SHADER_PGM_HI_GS = 0x2C89; +constexpr unsigned int mmSPI_SHADER_PGM_HI_HS = 0x2D09; +constexpr unsigned int mmSPI_SHADER_PGM_HI_LS = 0x2D49; +constexpr unsigned int mmSPI_SHADER_PGM_HI_PS = 0x2C09; +constexpr unsigned int mmSPI_SHADER_PGM_HI_VS = 0x2C49; +constexpr unsigned int mmSPI_SHADER_PGM_LO_ES = 0x2CC8; +constexpr unsigned int mmSPI_SHADER_PGM_LO_GS = 0x2C88; +constexpr unsigned int mmSPI_SHADER_PGM_LO_HS = 0x2D08; +constexpr unsigned int mmSPI_SHADER_PGM_LO_LS = 0x2D48; +constexpr unsigned int mmSPI_SHADER_PGM_LO_PS = 0x2C08; +constexpr unsigned int mmSPI_SHADER_PGM_LO_VS = 0x2C48; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC1_ES = 0x2CCA; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC1_GS = 0x2C8A; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC1_HS = 0x2D0A; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC1_LS = 0x2D4A; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC1_PS = 0x2C0A; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC1_VS = 0x2C4A; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_ES = 0x2CCB; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_ES_GS__CI__VI = 0x2CBC; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_ES_VS__CI__VI = 0x2C7C; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_GS = 0x2C8B; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_HS = 0x2D0B; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_LS = 0x2D4B; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_LS_ES__CI__VI = 0x2CFD; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_LS_HS__CI__VI = 0x2D3D; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_LS_VS__CI__VI = 0x2C7D; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_PS = 0x2C0B; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC2_VS = 0x2C4B; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC3_ES__CI__VI = 0x2CC7; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC3_GS__CI__VI = 0x2C87; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC3_HS__CI__VI = 0x2D07; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC3_LS__CI__VI = 0x2D47; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC3_PS__CI__VI = 0x2C07; +constexpr unsigned int mmSPI_SHADER_PGM_RSRC3_VS__CI__VI = 0x2C46; +constexpr unsigned int mmSPI_SHADER_POS_FORMAT = 0xA1C3; +constexpr unsigned int mmSPI_SHADER_TBA_HI_ES = 0x2CC1; +constexpr unsigned int mmSPI_SHADER_TBA_HI_GS = 0x2C81; +constexpr unsigned int mmSPI_SHADER_TBA_HI_HS = 0x2D01; +constexpr unsigned int mmSPI_SHADER_TBA_HI_LS = 0x2D41; +constexpr unsigned int mmSPI_SHADER_TBA_HI_PS = 0x2C01; +constexpr unsigned int mmSPI_SHADER_TBA_HI_VS = 0x2C41; +constexpr unsigned int mmSPI_SHADER_TBA_LO_ES = 0x2CC0; +constexpr unsigned int mmSPI_SHADER_TBA_LO_GS = 0x2C80; +constexpr unsigned int mmSPI_SHADER_TBA_LO_HS = 0x2D00; +constexpr unsigned int mmSPI_SHADER_TBA_LO_LS = 0x2D40; +constexpr unsigned int mmSPI_SHADER_TBA_LO_PS = 0x2C00; +constexpr unsigned int mmSPI_SHADER_TBA_LO_VS = 0x2C40; +constexpr unsigned int mmSPI_SHADER_TMA_HI_ES = 0x2CC3; +constexpr unsigned int mmSPI_SHADER_TMA_HI_GS = 0x2C83; +constexpr unsigned int mmSPI_SHADER_TMA_HI_HS = 0x2D03; +constexpr unsigned int mmSPI_SHADER_TMA_HI_LS = 0x2D43; +constexpr unsigned int mmSPI_SHADER_TMA_HI_PS = 0x2C03; +constexpr unsigned int mmSPI_SHADER_TMA_HI_VS = 0x2C43; +constexpr unsigned int mmSPI_SHADER_TMA_LO_ES = 0x2CC2; +constexpr unsigned int mmSPI_SHADER_TMA_LO_GS = 0x2C82; +constexpr unsigned int mmSPI_SHADER_TMA_LO_HS = 0x2D02; +constexpr unsigned int mmSPI_SHADER_TMA_LO_LS = 0x2D42; +constexpr unsigned int mmSPI_SHADER_TMA_LO_PS = 0x2C02; +constexpr unsigned int mmSPI_SHADER_TMA_LO_VS = 0x2C42; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_0 = 0x2CCC; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_1 = 0x2CCD; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_10 = 0x2CD6; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_11 = 0x2CD7; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_12 = 0x2CD8; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_13 = 0x2CD9; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_14 = 0x2CDA; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_15 = 0x2CDB; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_2 = 0x2CCE; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_3 = 0x2CCF; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_4 = 0x2CD0; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_5 = 0x2CD1; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_6 = 0x2CD2; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_7 = 0x2CD3; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_8 = 0x2CD4; +constexpr unsigned int mmSPI_SHADER_USER_DATA_ES_9 = 0x2CD5; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_0 = 0x2C8C; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_1 = 0x2C8D; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_10 = 0x2C96; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_11 = 0x2C97; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_12 = 0x2C98; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_13 = 0x2C99; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_14 = 0x2C9A; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_15 = 0x2C9B; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_2 = 0x2C8E; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_3 = 0x2C8F; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_4 = 0x2C90; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_5 = 0x2C91; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_6 = 0x2C92; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_7 = 0x2C93; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_8 = 0x2C94; +constexpr unsigned int mmSPI_SHADER_USER_DATA_GS_9 = 0x2C95; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_0 = 0x2D0C; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_1 = 0x2D0D; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_10 = 0x2D16; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_11 = 0x2D17; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_12 = 0x2D18; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_13 = 0x2D19; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_14 = 0x2D1A; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_15 = 0x2D1B; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_2 = 0x2D0E; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_3 = 0x2D0F; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_4 = 0x2D10; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_5 = 0x2D11; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_6 = 0x2D12; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_7 = 0x2D13; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_8 = 0x2D14; +constexpr unsigned int mmSPI_SHADER_USER_DATA_HS_9 = 0x2D15; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_0 = 0x2D4C; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_1 = 0x2D4D; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_10 = 0x2D56; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_11 = 0x2D57; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_12 = 0x2D58; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_13 = 0x2D59; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_14 = 0x2D5A; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_15 = 0x2D5B; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_2 = 0x2D4E; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_3 = 0x2D4F; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_4 = 0x2D50; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_5 = 0x2D51; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_6 = 0x2D52; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_7 = 0x2D53; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_8 = 0x2D54; +constexpr unsigned int mmSPI_SHADER_USER_DATA_LS_9 = 0x2D55; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_0 = 0x2C0C; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_1 = 0x2C0D; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_10 = 0x2C16; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_11 = 0x2C17; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_12 = 0x2C18; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_13 = 0x2C19; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_14 = 0x2C1A; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_15 = 0x2C1B; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_2 = 0x2C0E; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_3 = 0x2C0F; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_4 = 0x2C10; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_5 = 0x2C11; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_6 = 0x2C12; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_7 = 0x2C13; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_8 = 0x2C14; +constexpr unsigned int mmSPI_SHADER_USER_DATA_PS_9 = 0x2C15; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_0 = 0x2C4C; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_1 = 0x2C4D; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_10 = 0x2C56; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_11 = 0x2C57; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_12 = 0x2C58; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_13 = 0x2C59; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_14 = 0x2C5A; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_15 = 0x2C5B; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_2 = 0x2C4E; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_3 = 0x2C4F; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_4 = 0x2C50; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_5 = 0x2C51; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_6 = 0x2C52; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_7 = 0x2C53; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_8 = 0x2C54; +constexpr unsigned int mmSPI_SHADER_USER_DATA_VS_9 = 0x2C55; +constexpr unsigned int mmSPI_SHADER_Z_FORMAT = 0xA1C4; +constexpr unsigned int mmSPI_SLAVE_DEBUG_BUSY = 0x24D3; +constexpr unsigned int mmSPI_STATIC_THREAD_MGMT_3__SI = 0x243A; +constexpr unsigned int mmSPI_SX_EXPORT_BUFFER_SIZES = 0x24D9; +constexpr unsigned int mmSPI_SX_SCOREBOARD_BUFFER_SIZES = 0x24DA; +constexpr unsigned int mmSPI_TMPRING_SIZE = 0xA1BA; +constexpr unsigned int mmSPI_VS_OUT_CONFIG = 0xA1B1; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS0__CI__VI = 0x31C9; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS1__CI__VI = 0x31CA; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS2__CI__VI = 0x31CB; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS3__CI__VI = 0x31CC; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS4__CI__VI = 0x31CD; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS5__CI__VI = 0x31CE; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS6__CI__VI = 0x31CF; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_CS7__CI__VI = 0x31D0; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_GFX__CI__VI = 0x31C7; +constexpr unsigned int mmSPI_WCL_PIPE_PERCENT_HP3D__CI__VI = 0x31C8; +constexpr unsigned int mmSPI_WF_LIFETIME_CNTL__CI__VI = 0x24AA; +constexpr unsigned int mmSPI_WF_LIFETIME_DEBUG__CI__VI = 0x24CA; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_0__CI__VI = 0x24AB; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_1__CI__VI = 0x24AC; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_2__CI__VI = 0x24AD; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_3__CI__VI = 0x24AE; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_4__CI__VI = 0x24AF; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_5__CI__VI = 0x24B0; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_6__CI__VI = 0x24B1; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_7__CI__VI = 0x24B2; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_8__CI__VI = 0x24B3; +constexpr unsigned int mmSPI_WF_LIFETIME_LIMIT_9__CI__VI = 0x24B4; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_0__CI__VI = 0x24B5; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_10__CI__VI = 0x24BF; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_11__CI__VI = 0x24C0; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_12__CI__VI = 0x24C1; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_13__CI__VI = 0x24C2; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_14__CI__VI = 0x24C3; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_15__CI__VI = 0x24C4; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_16__CI__VI = 0x24C5; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_17__CI__VI = 0x24C6; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_18__CI__VI = 0x24C7; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_19__CI__VI = 0x24C8; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_1__CI__VI = 0x24B6; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_20__CI__VI = 0x24C9; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_2__CI__VI = 0x24B7; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_3__CI__VI = 0x24B8; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_4__CI__VI = 0x24B9; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_5__CI__VI = 0x24BA; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_6__CI__VI = 0x24BB; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_7__CI__VI = 0x24BC; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_8__CI__VI = 0x24BD; +constexpr unsigned int mmSPI_WF_LIFETIME_STATUS_9__CI__VI = 0x24BE; +constexpr unsigned int mmSPLL_CNTL_MODE__SI = 0x0186; +constexpr unsigned int mmSQC_CACHES__CI__VI = 0xC348; +constexpr unsigned int mmSQC_CACHES__SI = 0x2302; +constexpr unsigned int mmSQC_CONFIG = 0x2301; +constexpr unsigned int mmSQC_POLICY__CI = 0x230E; +constexpr unsigned int mmSQC_SECDED_CNT__SI__CI = 0x23A0; +constexpr unsigned int mmSQC_VOLATILE__CI = 0x230F; +constexpr unsigned int mmSQ_ALU_CLK_CTRL__CI__VI = 0xF08E; +constexpr unsigned int mmSQ_ALU_CLK_CTRL__SI = 0x2360; +constexpr unsigned int mmSQ_BUF_RSRC_WORD0 = 0x23C0; +constexpr unsigned int mmSQ_BUF_RSRC_WORD1 = 0x23C1; +constexpr unsigned int mmSQ_BUF_RSRC_WORD2 = 0x23C2; +constexpr unsigned int mmSQ_BUF_RSRC_WORD3 = 0x23C3; +constexpr unsigned int mmSQ_CMD_TIMESTAMP__CI__VI = 0x2375; +constexpr unsigned int mmSQ_CMD__CI__VI = 0x237B; +constexpr unsigned int mmSQ_CONFIG = 0x2300; +constexpr unsigned int mmSQ_DEBUG_STS_GLOBAL = 0x2309; +constexpr unsigned int mmSQ_DEBUG_STS_GLOBAL2__CI__VI = 0x2310; +constexpr unsigned int mmSQ_DEBUG_STS_GLOBAL3__CI__VI = 0x2311; +constexpr unsigned int mmSQ_DED_CNT__SI__CI = 0x23A2; +constexpr unsigned int mmSQ_DED_INFO__SI__CI = 0x23A3; +constexpr unsigned int mmSQ_DS_0 = 0x237F; +constexpr unsigned int mmSQ_DS_1 = 0x237F; +constexpr unsigned int mmSQ_EXP_0 = 0x237F; +constexpr unsigned int mmSQ_EXP_1 = 0x237F; +constexpr unsigned int mmSQ_FIFO_SIZES = 0x2305; +constexpr unsigned int mmSQ_FLAT_0__CI__VI = 0x237F; +constexpr unsigned int mmSQ_FLAT_1__CI__VI = 0x237F; +constexpr unsigned int mmSQ_FLAT_SCRATCH_WORD0__CI__VI = 0x23D0; +constexpr unsigned int mmSQ_FLAT_SCRATCH_WORD1__CI__VI = 0x23D1; +constexpr unsigned int mmSQ_HV_VMID_CTRL__CI__VI = 0xF840; +constexpr unsigned int mmSQ_IMG_RSRC_WORD0 = 0x23C4; +constexpr unsigned int mmSQ_IMG_RSRC_WORD1 = 0x23C5; +constexpr unsigned int mmSQ_IMG_RSRC_WORD2 = 0x23C6; +constexpr unsigned int mmSQ_IMG_RSRC_WORD3 = 0x23C7; +constexpr unsigned int mmSQ_IMG_RSRC_WORD4 = 0x23C8; +constexpr unsigned int mmSQ_IMG_RSRC_WORD5 = 0x23C9; +constexpr unsigned int mmSQ_IMG_RSRC_WORD6 = 0x23CA; +constexpr unsigned int mmSQ_IMG_RSRC_WORD7 = 0x23CB; +constexpr unsigned int mmSQ_IMG_SAMP_WORD0 = 0x23CC; +constexpr unsigned int mmSQ_IMG_SAMP_WORD1 = 0x23CD; +constexpr unsigned int mmSQ_IMG_SAMP_WORD2 = 0x23CE; +constexpr unsigned int mmSQ_IMG_SAMP_WORD3 = 0x23CF; +constexpr unsigned int mmSQ_IND_DATA = 0x2379; +constexpr unsigned int mmSQ_IND_INDEX = 0x2378; +constexpr unsigned int mmSQ_INST = 0x237F; +constexpr unsigned int mmSQ_INTERRUPT_AUTO_MASK__CI__VI = 0x2314; +constexpr unsigned int mmSQ_INTERRUPT_MSG_CTRL__CI__VI = 0x2315; +constexpr unsigned int mmSQ_LB_CTR_CTRL = 0x2398; +constexpr unsigned int mmSQ_LB_DATA_ALU_CYCLES = 0x2399; +constexpr unsigned int mmSQ_LB_DATA_ALU_STALLS = 0x239B; +constexpr unsigned int mmSQ_LB_DATA_TEX_CYCLES = 0x239A; +constexpr unsigned int mmSQ_LB_DATA_TEX_STALLS = 0x239C; +constexpr unsigned int mmSQ_LDS_CLK_CTRL__CI__VI = 0xF090; +constexpr unsigned int mmSQ_MIMG_0 = 0x237F; +constexpr unsigned int mmSQ_MIMG_1 = 0x237F; +constexpr unsigned int mmSQ_MTBUF_0 = 0x237F; +constexpr unsigned int mmSQ_MTBUF_1 = 0x237F; +constexpr unsigned int mmSQ_MUBUF_0 = 0x237F; +constexpr unsigned int mmSQ_MUBUF_1 = 0x237F; +constexpr unsigned int mmSQ_PERFCOUNTER0_HI__CI__VI = 0xD1C1; +constexpr unsigned int mmSQ_PERFCOUNTER0_HI__SI = 0x2321; +constexpr unsigned int mmSQ_PERFCOUNTER0_LO__CI__VI = 0xD1C0; +constexpr unsigned int mmSQ_PERFCOUNTER0_LO__SI = 0x2320; +constexpr unsigned int mmSQ_PERFCOUNTER0_SELECT__CI__VI = 0xD9C0; +constexpr unsigned int mmSQ_PERFCOUNTER0_SELECT__SI = 0x2340; +constexpr unsigned int mmSQ_PERFCOUNTER10_HI__CI__VI = 0xD1D5; +constexpr unsigned int mmSQ_PERFCOUNTER10_HI__SI = 0x2335; +constexpr unsigned int mmSQ_PERFCOUNTER10_LO__CI__VI = 0xD1D4; +constexpr unsigned int mmSQ_PERFCOUNTER10_LO__SI = 0x2334; +constexpr unsigned int mmSQ_PERFCOUNTER10_SELECT__CI__VI = 0xD9CA; +constexpr unsigned int mmSQ_PERFCOUNTER10_SELECT__SI = 0x234A; +constexpr unsigned int mmSQ_PERFCOUNTER11_HI__CI__VI = 0xD1D7; +constexpr unsigned int mmSQ_PERFCOUNTER11_HI__SI = 0x2337; +constexpr unsigned int mmSQ_PERFCOUNTER11_LO__CI__VI = 0xD1D6; +constexpr unsigned int mmSQ_PERFCOUNTER11_LO__SI = 0x2336; +constexpr unsigned int mmSQ_PERFCOUNTER11_SELECT__CI__VI = 0xD9CB; +constexpr unsigned int mmSQ_PERFCOUNTER11_SELECT__SI = 0x234B; +constexpr unsigned int mmSQ_PERFCOUNTER12_HI__CI__VI = 0xD1D9; +constexpr unsigned int mmSQ_PERFCOUNTER12_HI__SI = 0x2339; +constexpr unsigned int mmSQ_PERFCOUNTER12_LO__CI__VI = 0xD1D8; +constexpr unsigned int mmSQ_PERFCOUNTER12_LO__SI = 0x2338; +constexpr unsigned int mmSQ_PERFCOUNTER12_SELECT__CI__VI = 0xD9CC; +constexpr unsigned int mmSQ_PERFCOUNTER12_SELECT__SI = 0x234C; +constexpr unsigned int mmSQ_PERFCOUNTER13_HI__CI__VI = 0xD1DB; +constexpr unsigned int mmSQ_PERFCOUNTER13_HI__SI = 0x233B; +constexpr unsigned int mmSQ_PERFCOUNTER13_LO__CI__VI = 0xD1DA; +constexpr unsigned int mmSQ_PERFCOUNTER13_LO__SI = 0x233A; +constexpr unsigned int mmSQ_PERFCOUNTER13_SELECT__CI__VI = 0xD9CD; +constexpr unsigned int mmSQ_PERFCOUNTER13_SELECT__SI = 0x234D; +constexpr unsigned int mmSQ_PERFCOUNTER14_HI__CI__VI = 0xD1DD; +constexpr unsigned int mmSQ_PERFCOUNTER14_HI__SI = 0x233D; +constexpr unsigned int mmSQ_PERFCOUNTER14_LO__CI__VI = 0xD1DC; +constexpr unsigned int mmSQ_PERFCOUNTER14_LO__SI = 0x233C; +constexpr unsigned int mmSQ_PERFCOUNTER14_SELECT__CI__VI = 0xD9CE; +constexpr unsigned int mmSQ_PERFCOUNTER14_SELECT__SI = 0x234E; +constexpr unsigned int mmSQ_PERFCOUNTER15_HI__CI__VI = 0xD1DF; +constexpr unsigned int mmSQ_PERFCOUNTER15_HI__SI = 0x233F; +constexpr unsigned int mmSQ_PERFCOUNTER15_LO__CI__VI = 0xD1DE; +constexpr unsigned int mmSQ_PERFCOUNTER15_LO__SI = 0x233E; +constexpr unsigned int mmSQ_PERFCOUNTER15_SELECT__CI__VI = 0xD9CF; +constexpr unsigned int mmSQ_PERFCOUNTER15_SELECT__SI = 0x234F; +constexpr unsigned int mmSQ_PERFCOUNTER1_HI__CI__VI = 0xD1C3; +constexpr unsigned int mmSQ_PERFCOUNTER1_HI__SI = 0x2323; +constexpr unsigned int mmSQ_PERFCOUNTER1_LO__CI__VI = 0xD1C2; +constexpr unsigned int mmSQ_PERFCOUNTER1_LO__SI = 0x2322; +constexpr unsigned int mmSQ_PERFCOUNTER1_SELECT__CI__VI = 0xD9C1; +constexpr unsigned int mmSQ_PERFCOUNTER1_SELECT__SI = 0x2341; +constexpr unsigned int mmSQ_PERFCOUNTER2_HI__CI__VI = 0xD1C5; +constexpr unsigned int mmSQ_PERFCOUNTER2_HI__SI = 0x2325; +constexpr unsigned int mmSQ_PERFCOUNTER2_LO__CI__VI = 0xD1C4; +constexpr unsigned int mmSQ_PERFCOUNTER2_LO__SI = 0x2324; +constexpr unsigned int mmSQ_PERFCOUNTER2_SELECT__CI__VI = 0xD9C2; +constexpr unsigned int mmSQ_PERFCOUNTER2_SELECT__SI = 0x2342; +constexpr unsigned int mmSQ_PERFCOUNTER3_HI__CI__VI = 0xD1C7; +constexpr unsigned int mmSQ_PERFCOUNTER3_HI__SI = 0x2327; +constexpr unsigned int mmSQ_PERFCOUNTER3_LO__CI__VI = 0xD1C6; +constexpr unsigned int mmSQ_PERFCOUNTER3_LO__SI = 0x2326; +constexpr unsigned int mmSQ_PERFCOUNTER3_SELECT__CI__VI = 0xD9C3; +constexpr unsigned int mmSQ_PERFCOUNTER3_SELECT__SI = 0x2343; +constexpr unsigned int mmSQ_PERFCOUNTER4_HI__CI__VI = 0xD1C9; +constexpr unsigned int mmSQ_PERFCOUNTER4_HI__SI = 0x2329; +constexpr unsigned int mmSQ_PERFCOUNTER4_LO__CI__VI = 0xD1C8; +constexpr unsigned int mmSQ_PERFCOUNTER4_LO__SI = 0x2328; +constexpr unsigned int mmSQ_PERFCOUNTER4_SELECT__CI__VI = 0xD9C4; +constexpr unsigned int mmSQ_PERFCOUNTER4_SELECT__SI = 0x2344; +constexpr unsigned int mmSQ_PERFCOUNTER5_HI__CI__VI = 0xD1CB; +constexpr unsigned int mmSQ_PERFCOUNTER5_HI__SI = 0x232B; +constexpr unsigned int mmSQ_PERFCOUNTER5_LO__CI__VI = 0xD1CA; +constexpr unsigned int mmSQ_PERFCOUNTER5_LO__SI = 0x232A; +constexpr unsigned int mmSQ_PERFCOUNTER5_SELECT__CI__VI = 0xD9C5; +constexpr unsigned int mmSQ_PERFCOUNTER5_SELECT__SI = 0x2345; +constexpr unsigned int mmSQ_PERFCOUNTER6_HI__CI__VI = 0xD1CD; +constexpr unsigned int mmSQ_PERFCOUNTER6_HI__SI = 0x232D; +constexpr unsigned int mmSQ_PERFCOUNTER6_LO__CI__VI = 0xD1CC; +constexpr unsigned int mmSQ_PERFCOUNTER6_LO__SI = 0x232C; +constexpr unsigned int mmSQ_PERFCOUNTER6_SELECT__CI__VI = 0xD9C6; +constexpr unsigned int mmSQ_PERFCOUNTER6_SELECT__SI = 0x2346; +constexpr unsigned int mmSQ_PERFCOUNTER7_HI__CI__VI = 0xD1CF; +constexpr unsigned int mmSQ_PERFCOUNTER7_HI__SI = 0x232F; +constexpr unsigned int mmSQ_PERFCOUNTER7_LO__CI__VI = 0xD1CE; +constexpr unsigned int mmSQ_PERFCOUNTER7_LO__SI = 0x232E; +constexpr unsigned int mmSQ_PERFCOUNTER7_SELECT__CI__VI = 0xD9C7; +constexpr unsigned int mmSQ_PERFCOUNTER7_SELECT__SI = 0x2347; +constexpr unsigned int mmSQ_PERFCOUNTER8_HI__CI__VI = 0xD1D1; +constexpr unsigned int mmSQ_PERFCOUNTER8_HI__SI = 0x2331; +constexpr unsigned int mmSQ_PERFCOUNTER8_LO__CI__VI = 0xD1D0; +constexpr unsigned int mmSQ_PERFCOUNTER8_LO__SI = 0x2330; +constexpr unsigned int mmSQ_PERFCOUNTER8_SELECT__CI__VI = 0xD9C8; +constexpr unsigned int mmSQ_PERFCOUNTER8_SELECT__SI = 0x2348; +constexpr unsigned int mmSQ_PERFCOUNTER9_HI__CI__VI = 0xD1D3; +constexpr unsigned int mmSQ_PERFCOUNTER9_HI__SI = 0x2333; +constexpr unsigned int mmSQ_PERFCOUNTER9_LO__CI__VI = 0xD1D2; +constexpr unsigned int mmSQ_PERFCOUNTER9_LO__SI = 0x2332; +constexpr unsigned int mmSQ_PERFCOUNTER9_SELECT__CI__VI = 0xD9C9; +constexpr unsigned int mmSQ_PERFCOUNTER9_SELECT__SI = 0x2349; +constexpr unsigned int mmSQ_PERFCOUNTER_CTRL2__CI__VI = 0xD9E2; +constexpr unsigned int mmSQ_PERFCOUNTER_CTRL__CI__VI = 0xD9E0; +constexpr unsigned int mmSQ_PERFCOUNTER_CTRL__SI = 0x2306; +constexpr unsigned int mmSQ_PERFCOUNTER_MASK__CI__VI = 0xD9E1; +constexpr unsigned int mmSQ_POWER_THROTTLE2__CI__VI = 0xF092; +constexpr unsigned int mmSQ_POWER_THROTTLE2__SI = 0x2397; +constexpr unsigned int mmSQ_POWER_THROTTLE__CI__VI = 0xF091; +constexpr unsigned int mmSQ_POWER_THROTTLE__SI = 0x2396; +constexpr unsigned int mmSQ_RANDOM_WAVE_PRI = 0x2303; +constexpr unsigned int mmSQ_REG_CREDITS = 0x2304; +constexpr unsigned int mmSQ_REG_TIMESTAMP__CI__VI = 0x2374; +constexpr unsigned int mmSQ_SEC_CNT__SI__CI = 0x23A1; +constexpr unsigned int mmSQ_SMRD__SI__CI = 0x237F; +constexpr unsigned int mmSQ_SOP1 = 0x237F; +constexpr unsigned int mmSQ_SOP2 = 0x237F; +constexpr unsigned int mmSQ_SOPC = 0x237F; +constexpr unsigned int mmSQ_SOPK = 0x237F; +constexpr unsigned int mmSQ_SOPP = 0x237F; +constexpr unsigned int mmSQ_TEX_CLK_CTRL__CI__VI = 0xF08F; +constexpr unsigned int mmSQ_TEX_CLK_CTRL__SI = 0x2361; +constexpr unsigned int mmSQ_THREAD_TRACE_BASE2__CI = 0x2385; +constexpr unsigned int mmSQ_THREAD_TRACE_CNTR = 0x2390; +constexpr unsigned int mmSQ_THREAD_TRACE_TOKEN_MASK2__CI = 0x2386; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_0__CI__VI = 0xC340; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_0__SI = 0x2388; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_1__CI__VI = 0xC341; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_1__SI = 0x2389; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_2__CI__VI = 0xC342; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_2__SI = 0x238A; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_3__CI__VI = 0xC343; +constexpr unsigned int mmSQ_THREAD_TRACE_USERDATA_3__SI = 0x238B; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_CMN = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_EVENT = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_INST = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_INST_PC_1_OF_2 = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_INST_PC_2_OF_2 = 0x23B1; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2 = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2 = 0x23B1; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_ISSUE = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_MISC = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_PERF_1_OF_2 = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_PERF_2_OF_2 = 0x23B1; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_REG_1_OF_2 = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_REG_2_OF_2 = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_REG_CS_1_OF_2__CI__VI = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_REG_CS_2_OF_2__CI__VI = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2 = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2 = 0x23B1; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_TIME__SI = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_WAVE = 0x23B0; +constexpr unsigned int mmSQ_THREAD_TRACE_WORD_WAVE_START = 0x23B0; +constexpr unsigned int mmSQ_TIME_HI = 0x237C; +constexpr unsigned int mmSQ_TIME_LO = 0x237D; +constexpr unsigned int mmSQ_VINTRP = 0x237F; +constexpr unsigned int mmSQ_VOP1 = 0x237F; +constexpr unsigned int mmSQ_VOP2 = 0x237F; +constexpr unsigned int mmSQ_VOP3_0 = 0x237F; +constexpr unsigned int mmSQ_VOP3_0_SDST_ENC = 0x237F; +constexpr unsigned int mmSQ_VOP3_1 = 0x237F; +constexpr unsigned int mmSQ_VOPC = 0x237F; +constexpr unsigned int mmSRBM_CHIP_REVISION = 0x039B; +constexpr unsigned int mmSRBM_CNTL = 0x0390; +constexpr unsigned int mmSRBM_DEBUG = 0x03A4; +constexpr unsigned int mmSRBM_DEBUG_CNTL = 0x0399; +constexpr unsigned int mmSRBM_DEBUG_DATA = 0x039A; +constexpr unsigned int mmSRBM_DEBUG_SNAPSHOT = 0x03A5; +constexpr unsigned int mmSRBM_GFX_CNTL = 0x0391; +constexpr unsigned int mmSRBM_INT_ACK = 0x03AA; +constexpr unsigned int mmSRBM_INT_CNTL = 0x03A8; +constexpr unsigned int mmSRBM_INT_STATUS = 0x03A9; +constexpr unsigned int mmSRBM_MC_CLKEN_CNTL__CI__VI = 0x03B3; +constexpr unsigned int mmSRBM_READ_ERROR = 0x03A6; +constexpr unsigned int mmSRBM_SAM_CLKEN_CNTL__CI__VI = 0x03B8; +constexpr unsigned int mmSRBM_SDMA_CLKEN_CNTL__CI__VI = 0x03B7; +constexpr unsigned int mmSRBM_SOFT_RESET = 0x0398; +constexpr unsigned int mmSRBM_STATUS = 0x0394; +constexpr unsigned int mmSRBM_STATUS2 = 0x0393; +constexpr unsigned int mmSRBM_SYS_CLKEN_CNTL = 0x03B4; +constexpr unsigned int mmSRBM_UVD_CLKEN_CNTL = 0x03B6; +constexpr unsigned int mmSRBM_VCE_CLKEN_CNTL = 0x03B5; +constexpr unsigned int mmSX_DEBUG_1 = 0x2418; +constexpr unsigned int mmSX_DEBUG_BUSY = 0x2414; +constexpr unsigned int mmSX_DEBUG_BUSY_2 = 0x2415; +constexpr unsigned int mmSX_DEBUG_BUSY_3 = 0x2416; +constexpr unsigned int mmSX_DEBUG_BUSY_4 = 0x2417; +constexpr unsigned int mmSX_PERFCOUNTER0_HI__CI__VI = 0xD241; +constexpr unsigned int mmSX_PERFCOUNTER0_HI__SI = 0x2421; +constexpr unsigned int mmSX_PERFCOUNTER0_LO__CI__VI = 0xD240; +constexpr unsigned int mmSX_PERFCOUNTER0_LO__SI = 0x2420; +constexpr unsigned int mmSX_PERFCOUNTER0_SELECT1__CI__VI = 0xDA44; +constexpr unsigned int mmSX_PERFCOUNTER0_SELECT__CI__VI = 0xDA40; +constexpr unsigned int mmSX_PERFCOUNTER0_SELECT__SI = 0x241C; +constexpr unsigned int mmSX_PERFCOUNTER1_HI__CI__VI = 0xD243; +constexpr unsigned int mmSX_PERFCOUNTER1_HI__SI = 0x2423; +constexpr unsigned int mmSX_PERFCOUNTER1_LO__CI__VI = 0xD242; +constexpr unsigned int mmSX_PERFCOUNTER1_LO__SI = 0x2422; +constexpr unsigned int mmSX_PERFCOUNTER1_SELECT1__CI__VI = 0xDA45; +constexpr unsigned int mmSX_PERFCOUNTER1_SELECT__CI__VI = 0xDA41; +constexpr unsigned int mmSX_PERFCOUNTER1_SELECT__SI = 0x241D; +constexpr unsigned int mmSX_PERFCOUNTER2_HI__CI__VI = 0xD245; +constexpr unsigned int mmSX_PERFCOUNTER2_HI__SI = 0x2425; +constexpr unsigned int mmSX_PERFCOUNTER2_LO__CI__VI = 0xD244; +constexpr unsigned int mmSX_PERFCOUNTER2_LO__SI = 0x2424; +constexpr unsigned int mmSX_PERFCOUNTER2_SELECT__CI__VI = 0xDA42; +constexpr unsigned int mmSX_PERFCOUNTER2_SELECT__SI = 0x241E; +constexpr unsigned int mmSX_PERFCOUNTER3_HI__CI__VI = 0xD247; +constexpr unsigned int mmSX_PERFCOUNTER3_HI__SI = 0x2427; +constexpr unsigned int mmSX_PERFCOUNTER3_LO__CI__VI = 0xD246; +constexpr unsigned int mmSX_PERFCOUNTER3_LO__SI = 0x2426; +constexpr unsigned int mmSX_PERFCOUNTER3_SELECT__CI__VI = 0xDA43; +constexpr unsigned int mmSX_PERFCOUNTER3_SELECT__SI = 0x241F; +constexpr unsigned int mmTARGET_AND_CURRENT_PROFILE_INDEX_1__SI = 0x021D; +constexpr unsigned int mmTARGET_AND_CURRENT_PROFILE_INDEX__SI = 0x01E6; +constexpr unsigned int mmTA_BC_BASE_ADDR = 0xA020; +constexpr unsigned int mmTA_BC_BASE_ADDR_HI__CI__VI = 0xA021; +constexpr unsigned int mmTA_CGTT_CTRL__CI__VI = 0xF09D; +constexpr unsigned int mmTA_CGTT_CTRL__SI = 0x2544; +constexpr unsigned int mmTA_CNTL = 0x2541; +constexpr unsigned int mmTA_CNTL_AUX = 0x2542; +constexpr unsigned int mmTA_CS_BC_BASE_ADDR_HI__CI__VI = 0xC381; +constexpr unsigned int mmTA_CS_BC_BASE_ADDR__CI__VI = 0xC380; +constexpr unsigned int mmTA_CS_BC_BASE_ADDR__SI = 0x2543; +constexpr unsigned int mmTA_DEBUG_DATA = 0x254D; +constexpr unsigned int mmTA_DEBUG_INDEX = 0x254C; +constexpr unsigned int mmTA_PERFCOUNTER0_HI__CI__VI = 0xD2C1; +constexpr unsigned int mmTA_PERFCOUNTER0_HI__SI = 0x2556; +constexpr unsigned int mmTA_PERFCOUNTER0_LO__CI__VI = 0xD2C0; +constexpr unsigned int mmTA_PERFCOUNTER0_LO__SI = 0x2555; +constexpr unsigned int mmTA_PERFCOUNTER0_SELECT1__CI__VI = 0xDAC1; +constexpr unsigned int mmTA_PERFCOUNTER0_SELECT__CI__VI = 0xDAC0; +constexpr unsigned int mmTA_PERFCOUNTER0_SELECT__SI = 0x2554; +constexpr unsigned int mmTA_PERFCOUNTER1_HI__CI__VI = 0xD2C3; +constexpr unsigned int mmTA_PERFCOUNTER1_HI__SI = 0x2562; +constexpr unsigned int mmTA_PERFCOUNTER1_LO__CI__VI = 0xD2C2; +constexpr unsigned int mmTA_PERFCOUNTER1_LO__SI = 0x2561; +constexpr unsigned int mmTA_PERFCOUNTER1_SELECT__CI__VI = 0xDAC2; +constexpr unsigned int mmTA_PERFCOUNTER1_SELECT__SI = 0x2560; +constexpr unsigned int mmTA_RESERVED_010C__CI__VI = 0x2543; +constexpr unsigned int mmTA_SCRATCH = 0x2564; +constexpr unsigned int mmTA_STATUS = 0x2548; +constexpr unsigned int mmTCA_CGTT_SCLK_CTRL__CI__VI = 0xF0AD; +constexpr unsigned int mmTCA_CGTT_SCLK_CTRL__SI = 0x2BC1; +constexpr unsigned int mmTCA_CTRL = 0x2BC0; +constexpr unsigned int mmTCA_PERFCOUNTER0_HI__CI__VI = 0xD391; +constexpr unsigned int mmTCA_PERFCOUNTER0_HI__SI = 0x2BD2; +constexpr unsigned int mmTCA_PERFCOUNTER0_LO__CI__VI = 0xD390; +constexpr unsigned int mmTCA_PERFCOUNTER0_LO__SI = 0x2BD1; +constexpr unsigned int mmTCA_PERFCOUNTER0_SELECT1__CI__VI = 0xDB91; +constexpr unsigned int mmTCA_PERFCOUNTER0_SELECT__CI__VI = 0xDB90; +constexpr unsigned int mmTCA_PERFCOUNTER0_SELECT__SI = 0x2BD0; +constexpr unsigned int mmTCA_PERFCOUNTER1_HI__CI__VI = 0xD393; +constexpr unsigned int mmTCA_PERFCOUNTER1_HI__SI = 0x2BD5; +constexpr unsigned int mmTCA_PERFCOUNTER1_LO__CI__VI = 0xD392; +constexpr unsigned int mmTCA_PERFCOUNTER1_LO__SI = 0x2BD4; +constexpr unsigned int mmTCA_PERFCOUNTER1_SELECT1__CI__VI = 0xDB93; +constexpr unsigned int mmTCA_PERFCOUNTER1_SELECT__CI__VI = 0xDB92; +constexpr unsigned int mmTCA_PERFCOUNTER1_SELECT__SI = 0x2BD3; +constexpr unsigned int mmTCA_PERFCOUNTER2_HI__CI__VI = 0xD395; +constexpr unsigned int mmTCA_PERFCOUNTER2_HI__SI = 0x2BD8; +constexpr unsigned int mmTCA_PERFCOUNTER2_LO__CI__VI = 0xD394; +constexpr unsigned int mmTCA_PERFCOUNTER2_LO__SI = 0x2BD7; +constexpr unsigned int mmTCA_PERFCOUNTER2_SELECT__CI__VI = 0xDB94; +constexpr unsigned int mmTCA_PERFCOUNTER2_SELECT__SI = 0x2BD6; +constexpr unsigned int mmTCA_PERFCOUNTER3_HI__CI__VI = 0xD397; +constexpr unsigned int mmTCA_PERFCOUNTER3_HI__SI = 0x2BDB; +constexpr unsigned int mmTCA_PERFCOUNTER3_LO__CI__VI = 0xD396; +constexpr unsigned int mmTCA_PERFCOUNTER3_LO__SI = 0x2BDA; +constexpr unsigned int mmTCA_PERFCOUNTER3_SELECT__CI__VI = 0xDB95; +constexpr unsigned int mmTCA_PERFCOUNTER3_SELECT__SI = 0x2BD9; +constexpr unsigned int mmTCC_CGTT_SCLK_CTRL__CI__VI = 0xF0AC; +constexpr unsigned int mmTCC_CGTT_SCLK_CTRL__SI = 0x2B81; +constexpr unsigned int mmTCC_CTRL = 0x2B80; +constexpr unsigned int mmTCC_EDC_COUNTER__SI__CI = 0x2B82; +constexpr unsigned int mmTCC_PERFCOUNTER0_HI__CI__VI = 0xD381; +constexpr unsigned int mmTCC_PERFCOUNTER0_HI__SI = 0x2B92; +constexpr unsigned int mmTCC_PERFCOUNTER0_LO__CI__VI = 0xD380; +constexpr unsigned int mmTCC_PERFCOUNTER0_LO__SI = 0x2B91; +constexpr unsigned int mmTCC_PERFCOUNTER0_SELECT1__CI__VI = 0xDB81; +constexpr unsigned int mmTCC_PERFCOUNTER0_SELECT__CI__VI = 0xDB80; +constexpr unsigned int mmTCC_PERFCOUNTER0_SELECT__SI = 0x2B90; +constexpr unsigned int mmTCC_PERFCOUNTER1_HI__CI__VI = 0xD383; +constexpr unsigned int mmTCC_PERFCOUNTER1_HI__SI = 0x2B95; +constexpr unsigned int mmTCC_PERFCOUNTER1_LO__CI__VI = 0xD382; +constexpr unsigned int mmTCC_PERFCOUNTER1_LO__SI = 0x2B94; +constexpr unsigned int mmTCC_PERFCOUNTER1_SELECT1__CI__VI = 0xDB83; +constexpr unsigned int mmTCC_PERFCOUNTER1_SELECT__CI__VI = 0xDB82; +constexpr unsigned int mmTCC_PERFCOUNTER1_SELECT__SI = 0x2B93; +constexpr unsigned int mmTCC_PERFCOUNTER2_HI__CI__VI = 0xD385; +constexpr unsigned int mmTCC_PERFCOUNTER2_HI__SI = 0x2B98; +constexpr unsigned int mmTCC_PERFCOUNTER2_LO__CI__VI = 0xD384; +constexpr unsigned int mmTCC_PERFCOUNTER2_LO__SI = 0x2B97; +constexpr unsigned int mmTCC_PERFCOUNTER2_SELECT__CI__VI = 0xDB84; +constexpr unsigned int mmTCC_PERFCOUNTER2_SELECT__SI = 0x2B96; +constexpr unsigned int mmTCC_PERFCOUNTER3_HI__CI__VI = 0xD387; +constexpr unsigned int mmTCC_PERFCOUNTER3_HI__SI = 0x2B9B; +constexpr unsigned int mmTCC_PERFCOUNTER3_LO__CI__VI = 0xD386; +constexpr unsigned int mmTCC_PERFCOUNTER3_LO__SI = 0x2B9A; +constexpr unsigned int mmTCC_PERFCOUNTER3_SELECT__CI__VI = 0xDB85; +constexpr unsigned int mmTCC_PERFCOUNTER3_SELECT__SI = 0x2B99; +constexpr unsigned int mmTCC_REDUNDANCY__CI__VI = 0x2B83; +constexpr unsigned int mmTCI_CNTL_1 = 0x2B62; +constexpr unsigned int mmTCI_CNTL_2 = 0x2B63; +constexpr unsigned int mmTCI_STATUS = 0x2B61; +constexpr unsigned int mmTCP_ADDR_CONFIG = 0x2B05; +constexpr unsigned int mmTCP_BUFFER_ADDR_HASH_CNTL = 0x2B16; +constexpr unsigned int mmTCP_CHAN_STEER_HI = 0x2B04; +constexpr unsigned int mmTCP_CHAN_STEER_LO = 0x2B03; +constexpr unsigned int mmTCP_CNTL = 0x2B02; +constexpr unsigned int mmTCP_CREDIT = 0x2B06; +constexpr unsigned int mmTCP_EDC_COUNTER__SI__CI = 0x2B17; +constexpr unsigned int mmTCP_INVALIDATE = 0x2B00; +constexpr unsigned int mmTCP_PERFCOUNTER0_HI__CI__VI = 0xD341; +constexpr unsigned int mmTCP_PERFCOUNTER0_HI__SI = 0x2B0A; +constexpr unsigned int mmTCP_PERFCOUNTER0_LO__CI__VI = 0xD340; +constexpr unsigned int mmTCP_PERFCOUNTER0_LO__SI = 0x2B0B; +constexpr unsigned int mmTCP_PERFCOUNTER0_SELECT1__CI__VI = 0xDB41; +constexpr unsigned int mmTCP_PERFCOUNTER0_SELECT__CI__VI = 0xDB40; +constexpr unsigned int mmTCP_PERFCOUNTER0_SELECT__SI = 0x2B09; +constexpr unsigned int mmTCP_PERFCOUNTER1_HI__CI__VI = 0xD343; +constexpr unsigned int mmTCP_PERFCOUNTER1_HI__SI = 0x2B0D; +constexpr unsigned int mmTCP_PERFCOUNTER1_LO__CI__VI = 0xD342; +constexpr unsigned int mmTCP_PERFCOUNTER1_LO__SI = 0x2B0E; +constexpr unsigned int mmTCP_PERFCOUNTER1_SELECT1__CI__VI = 0xDB43; +constexpr unsigned int mmTCP_PERFCOUNTER1_SELECT__CI__VI = 0xDB42; +constexpr unsigned int mmTCP_PERFCOUNTER1_SELECT__SI = 0x2B0C; +constexpr unsigned int mmTCP_PERFCOUNTER2_HI__CI__VI = 0xD345; +constexpr unsigned int mmTCP_PERFCOUNTER2_HI__SI = 0x2B10; +constexpr unsigned int mmTCP_PERFCOUNTER2_LO__CI__VI = 0xD344; +constexpr unsigned int mmTCP_PERFCOUNTER2_LO__SI = 0x2B11; +constexpr unsigned int mmTCP_PERFCOUNTER2_SELECT__CI__VI = 0xDB44; +constexpr unsigned int mmTCP_PERFCOUNTER2_SELECT__SI = 0x2B0F; +constexpr unsigned int mmTCP_PERFCOUNTER3_HI__CI__VI = 0xD347; +constexpr unsigned int mmTCP_PERFCOUNTER3_HI__SI = 0x2B13; +constexpr unsigned int mmTCP_PERFCOUNTER3_LO__CI__VI = 0xD346; +constexpr unsigned int mmTCP_PERFCOUNTER3_LO__SI = 0x2B14; +constexpr unsigned int mmTCP_PERFCOUNTER3_SELECT__CI__VI = 0xDB45; +constexpr unsigned int mmTCP_PERFCOUNTER3_SELECT__SI = 0x2B12; +constexpr unsigned int mmTCP_STATUS = 0x2B01; +constexpr unsigned int mmTCP_WATCH0_ADDR_H__CI__VI = 0x32A0; +constexpr unsigned int mmTCP_WATCH0_ADDR_L__CI__VI = 0x32A1; +constexpr unsigned int mmTCP_WATCH0_CNTL__CI__VI = 0x32A2; +constexpr unsigned int mmTCP_WATCH1_ADDR_H__CI__VI = 0x32A3; +constexpr unsigned int mmTCP_WATCH1_ADDR_L__CI__VI = 0x32A4; +constexpr unsigned int mmTCP_WATCH1_CNTL__CI__VI = 0x32A5; +constexpr unsigned int mmTCP_WATCH2_ADDR_H__CI__VI = 0x32A6; +constexpr unsigned int mmTCP_WATCH2_ADDR_L__CI__VI = 0x32A7; +constexpr unsigned int mmTCP_WATCH2_CNTL__CI__VI = 0x32A8; +constexpr unsigned int mmTCP_WATCH3_ADDR_H__CI__VI = 0x32A9; +constexpr unsigned int mmTCP_WATCH3_ADDR_L__CI__VI = 0x32AA; +constexpr unsigned int mmTCP_WATCH3_CNTL__CI__VI = 0x32AB; +constexpr unsigned int mmTCS_CGTT_SCLK_CTRL__CI = 0xF0AE; +constexpr unsigned int mmTCS_CTRL__CI = 0x2BE0; +constexpr unsigned int mmTCS_PERFCOUNTER0_HI__CI = 0xD3A1; +constexpr unsigned int mmTCS_PERFCOUNTER0_LO__CI = 0xD3A0; +constexpr unsigned int mmTCS_PERFCOUNTER0_SELECT1__CI = 0xDBA1; +constexpr unsigned int mmTCS_PERFCOUNTER0_SELECT__CI = 0xDBA0; +constexpr unsigned int mmTCS_PERFCOUNTER1_HI__CI = 0xD3A3; +constexpr unsigned int mmTCS_PERFCOUNTER1_LO__CI = 0xD3A2; +constexpr unsigned int mmTCS_PERFCOUNTER1_SELECT__CI = 0xDBA2; +constexpr unsigned int mmTCS_PERFCOUNTER2_HI__CI = 0xD3A5; +constexpr unsigned int mmTCS_PERFCOUNTER2_LO__CI = 0xD3A4; +constexpr unsigned int mmTCS_PERFCOUNTER2_SELECT__CI = 0xDBA3; +constexpr unsigned int mmTCS_PERFCOUNTER3_HI__CI = 0xD3A7; +constexpr unsigned int mmTCS_PERFCOUNTER3_LO__CI = 0xD3A6; +constexpr unsigned int mmTCS_PERFCOUNTER3_SELECT__CI = 0xDBA4; +constexpr unsigned int mmTC_CFG_L1_LOAD_POLICY0__CI__VI = 0x2B1A; +constexpr unsigned int mmTC_CFG_L1_LOAD_POLICY1__CI__VI = 0x2B1B; +constexpr unsigned int mmTC_CFG_L1_STORE_POLICY__CI__VI = 0x2B1C; +constexpr unsigned int mmTC_CFG_L1_VOLATILE__CI__VI = 0x2B22; +constexpr unsigned int mmTC_CFG_L2_ATOMIC_POLICY__CI__VI = 0x2B21; +constexpr unsigned int mmTC_CFG_L2_LOAD_POLICY0__CI__VI = 0x2B1D; +constexpr unsigned int mmTC_CFG_L2_LOAD_POLICY1__CI__VI = 0x2B1E; +constexpr unsigned int mmTC_CFG_L2_STORE_POLICY0__CI__VI = 0x2B1F; +constexpr unsigned int mmTC_CFG_L2_STORE_POLICY1__CI__VI = 0x2B20; +constexpr unsigned int mmTC_CFG_L2_VOLATILE__CI__VI = 0x2B23; +constexpr unsigned int mmTD_CGTT_CTRL__CI__VI = 0xF09C; +constexpr unsigned int mmTD_CGTT_CTRL__SI = 0x2527; +constexpr unsigned int mmTD_CNTL = 0x2525; +constexpr unsigned int mmTD_DEBUG_DATA = 0x2529; +constexpr unsigned int mmTD_DEBUG_INDEX = 0x2528; +constexpr unsigned int mmTD_PERFCOUNTER0_HI__CI__VI = 0xD301; +constexpr unsigned int mmTD_PERFCOUNTER0_HI__SI = 0x252E; +constexpr unsigned int mmTD_PERFCOUNTER0_LO__CI__VI = 0xD300; +constexpr unsigned int mmTD_PERFCOUNTER0_LO__SI = 0x252D; +constexpr unsigned int mmTD_PERFCOUNTER0_SELECT1__CI__VI = 0xDB01; +constexpr unsigned int mmTD_PERFCOUNTER0_SELECT__CI__VI = 0xDB00; +constexpr unsigned int mmTD_PERFCOUNTER0_SELECT__SI = 0x252C; +constexpr unsigned int mmTD_PERFCOUNTER1_HI__CI__VI = 0xD303; +constexpr unsigned int mmTD_PERFCOUNTER1_LO__CI__VI = 0xD302; +constexpr unsigned int mmTD_PERFCOUNTER1_SELECT__CI__VI = 0xDB02; +constexpr unsigned int mmTD_SCRATCH__CI__VI = 0x2533; +constexpr unsigned int mmTD_SCRATCH__SI = 0x2530; +constexpr unsigned int mmTD_STATUS = 0x2526; +constexpr unsigned int mmTHM_CLK_CNTL__SI = 0x019A; +constexpr unsigned int mmTMDS_CNTL__SI = 0x1C7C; +constexpr unsigned int mmTMDS_CONTROL0_FEEDBACK__SI = 0x1C7E; +constexpr unsigned int mmTMDS_CONTROL_CHAR__SI = 0x1C7D; +constexpr unsigned int mmTMDS_CTL0_1_GEN_CNTL__SI = 0x1C86; +constexpr unsigned int mmTMDS_CTL2_3_GEN_CNTL__SI = 0x1C87; +constexpr unsigned int mmTMDS_CTL_BITS__SI = 0x1C83; +constexpr unsigned int mmTMDS_DCBALANCER_CONTROL__SI = 0x1C84; +constexpr unsigned int mmTMDS_DEBUG__SI = 0x1C82; +constexpr unsigned int mmTMDS_STEREOSYNC_CTL_SEL__SI = 0x1C7F; +constexpr unsigned int mmTMDS_SYNC_CHAR_PATTERN_0_1__SI = 0x1C80; +constexpr unsigned int mmTMDS_SYNC_CHAR_PATTERN_2_3__SI = 0x1C81; +constexpr unsigned int mmUNIPHY_DATA_SYNCHRONIZATION__SI = 0x1984; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKA__SI = 0x1947; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKB__SI = 0x1948; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKC__SI = 0x194D; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKD__SI = 0x194E; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKE__SI = 0x1950; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKF__SI = 0x1951; +constexpr unsigned int mmUNIPHY_IMPCAL_PERIOD__SI = 0x1949; +constexpr unsigned int mmUNIPHY_REG_TEST_OUTPUT__SI = 0x1986; +constexpr unsigned int mmUSER_SQC_BANK_DISABLE = 0x2308; +constexpr unsigned int mmUVD_CGC_CTRL__SI__VI = 0x3D2C; +constexpr unsigned int mmUVD_CGC_GATE__SI__VI = 0x3D2A; +constexpr unsigned int mmUVD_CGC_STATUS__SI__VI = 0x3D2B; +constexpr unsigned int mmUVD_CONFIG__CI__VI = 0x0F93; +constexpr unsigned int mmUVD_CONFIG__SI = 0x0F98; +constexpr unsigned int mmUVD_CONTEXT_ID__SI__VI = 0x3DBD; +constexpr unsigned int mmUVD_CTX_DATA__SI__VI = 0x3D29; +constexpr unsigned int mmUVD_CTX_INDEX__SI__VI = 0x3D28; +constexpr unsigned int mmUVD_ENGINE_CNTL__SI__VI = 0x3BC6; +constexpr unsigned int mmUVD_GPCOM_VCPU_CMD__SI__VI = 0x3BC3; +constexpr unsigned int mmUVD_GPCOM_VCPU_DATA0__SI__VI = 0x3BC4; +constexpr unsigned int mmUVD_GPCOM_VCPU_DATA1__SI__VI = 0x3BC5; +constexpr unsigned int mmUVD_LMI_ADDR_EXT__SI__VI = 0x3D65; +constexpr unsigned int mmUVD_LMI_CTRL2__SI__VI = 0x3D3D; +constexpr unsigned int mmUVD_LMI_CTRL__SI__VI = 0x3D66; +constexpr unsigned int mmUVD_LMI_EXT40_ADDR__SI__VI = 0x3D26; +constexpr unsigned int mmUVD_LMI_STATUS__SI__VI = 0x3D67; +constexpr unsigned int mmUVD_LMI_SWAP_CNTL__SI__VI = 0x3D6D; +constexpr unsigned int mmUVD_MASTINT_EN__SI__VI = 0x3D40; +constexpr unsigned int mmUVD_MPC_CNTL__SI__VI = 0x3D77; +constexpr unsigned int mmUVD_MPC_SET_ALU__SI__VI = 0x3D7E; +constexpr unsigned int mmUVD_MPC_SET_MUXA0__SI__VI = 0x3D79; +constexpr unsigned int mmUVD_MPC_SET_MUXA1__SI__VI = 0x3D7A; +constexpr unsigned int mmUVD_MPC_SET_MUXB0__SI__VI = 0x3D7B; +constexpr unsigned int mmUVD_MPC_SET_MUXB1__SI__VI = 0x3D7C; +constexpr unsigned int mmUVD_MPC_SET_MUX__SI__VI = 0x3D7D; +constexpr unsigned int mmUVD_MP_SWAP_CNTL__SI__VI = 0x3D6F; +constexpr unsigned int mmUVD_RBC_IB_BASE__SI = 0x3DA1; +constexpr unsigned int mmUVD_RBC_IB_SIZE__SI__VI = 0x3DA2; +constexpr unsigned int mmUVD_RBC_RB_BASE__SI = 0x3DA3; +constexpr unsigned int mmUVD_RBC_RB_CNTL__SI__VI = 0x3DA9; +constexpr unsigned int mmUVD_RBC_RB_RPTR_ADDR__SI__VI = 0x3DAA; +constexpr unsigned int mmUVD_RBC_RB_RPTR__SI__VI = 0x3DA4; +constexpr unsigned int mmUVD_RBC_RB_WPTR__SI__VI = 0x3DA5; +constexpr unsigned int mmUVD_SEMA_ADDR_HIGH__SI__VI = 0x3BC1; +constexpr unsigned int mmUVD_SEMA_ADDR_LOW__SI__VI = 0x3BC0; +constexpr unsigned int mmUVD_SEMA_CMD__SI__VI = 0x3BC2; +constexpr unsigned int mmUVD_SEMA_CNTL__SI__VI = 0x3D00; +constexpr unsigned int mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SI__VI = 0x3DB3; +constexpr unsigned int mmUVD_SEMA_TIMEOUT_STATUS__SI__VI = 0x3DB0; +constexpr unsigned int mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__SI__VI = 0x3DB2; +constexpr unsigned int mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__SI__VI = 0x3DB1; +constexpr unsigned int mmUVD_SOFT_RESET__SI__VI = 0x3DA0; +constexpr unsigned int mmUVD_STATUS__SI__VI = 0x3DAF; +constexpr unsigned int mmUVD_VCPU_CACHE_OFFSET0__SI__VI = 0x3D82; +constexpr unsigned int mmUVD_VCPU_CACHE_OFFSET1__SI__VI = 0x3D84; +constexpr unsigned int mmUVD_VCPU_CACHE_OFFSET2__SI__VI = 0x3D86; +constexpr unsigned int mmUVD_VCPU_CACHE_SIZE0__SI__VI = 0x3D83; +constexpr unsigned int mmUVD_VCPU_CACHE_SIZE1__SI__VI = 0x3D85; +constexpr unsigned int mmUVD_VCPU_CACHE_SIZE2__SI__VI = 0x3D87; +constexpr unsigned int mmUVD_VCPU_CNTL__SI__VI = 0x3D98; +constexpr unsigned int mmVBLANK_STATUS__SI = 0x1AEF; +constexpr unsigned int mmVCE_CONFIG__CI__VI = 0x0F94; +constexpr unsigned int mmVGA25_PPLL_FB_DIV__SI = 0x00DE; +constexpr unsigned int mmVGA25_PPLL_POST_DIV__SI = 0x00E2; +constexpr unsigned int mmVGA25_PPLL_REF_DIV__SI = 0x00D9; +constexpr unsigned int mmVGA28_PPLL_FB_DIV__SI = 0x00DF; +constexpr unsigned int mmVGA28_PPLL_POST_DIV__SI = 0x00E4; +constexpr unsigned int mmVGA28_PPLL_REF_DIV__SI = 0x00DB; +constexpr unsigned int mmVGA41_PPLL_FB_DIV__SI = 0x00E0; +constexpr unsigned int mmVGA41_PPLL_POST_DIV__SI = 0x00E6; +constexpr unsigned int mmVGA41_PPLL_REF_DIV__SI = 0x00DD; +constexpr unsigned int mmVGA_CACHE_CONTROL__SI__VI = 0x00CB; +constexpr unsigned int mmVGA_DEBUG_READBACK_DATA__SI__VI = 0x00D7; +constexpr unsigned int mmVGA_DEBUG_READBACK_INDEX__SI__VI = 0x00D6; +constexpr unsigned int mmVGA_DISPBUF1_SURFACE_ADDR__SI__VI = 0x00C6; +constexpr unsigned int mmVGA_DISPBUF2_SURFACE_ADDR__SI__VI = 0x00C8; +constexpr unsigned int mmVGA_HDP_CONTROL__SI__VI = 0x00CA; +constexpr unsigned int mmVGA_HW_DEBUG__SI__VI = 0x00CF; +constexpr unsigned int mmVGA_INTERRUPT_CONTROL__SI__VI = 0x00D1; +constexpr unsigned int mmVGA_INTERRUPT_STATUS__SI__VI = 0x00D3; +constexpr unsigned int mmVGA_MAIN_CONTROL__SI__VI = 0x00D4; +constexpr unsigned int mmVGA_MEMORY_BASE_ADDRESS_HIGH__SI__VI = 0x00C9; +constexpr unsigned int mmVGA_MEMORY_BASE_ADDRESS__SI__VI = 0x00C4; +constexpr unsigned int mmVGA_MEM_READ_PAGE_ADDR__SI__VI = 0x0013; +constexpr unsigned int mmVGA_MEM_WRITE_PAGE_ADDR__SI__VI = 0x0012; +constexpr unsigned int mmVGA_MODE_CONTROL__SI__VI = 0x00C2; +constexpr unsigned int mmVGA_RENDER_CONTROL__SI__VI = 0x00C0; +constexpr unsigned int mmVGA_SEQUENCER_RESET_CONTROL__SI__VI = 0x00C1; +constexpr unsigned int mmVGA_SOURCE_SELECT__SI__VI = 0x00FC; +constexpr unsigned int mmVGA_STATUS_CLEAR__SI__VI = 0x00D2; +constexpr unsigned int mmVGA_STATUS__SI__VI = 0x00D0; +constexpr unsigned int mmVGA_SURFACE_PITCH_SELECT__SI__VI = 0x00C3; +constexpr unsigned int mmVGA_TEST_CONTROL__SI__VI = 0x00D5; +constexpr unsigned int mmVGA_TEST_DEBUG_DATA__SI__VI = 0x00C7; +constexpr unsigned int mmVGA_TEST_DEBUG_INDEX__SI__VI = 0x00C5; +constexpr unsigned int mmVGT_CACHE_INVALIDATION = 0x2231; +constexpr unsigned int mmVGT_CNTL_STATUS = 0x223C; +constexpr unsigned int mmVGT_DEBUG_CNTL = 0x2238; +constexpr unsigned int mmVGT_DEBUG_DATA = 0x2239; +constexpr unsigned int mmVGT_DMA_BASE = 0xA1FA; +constexpr unsigned int mmVGT_DMA_BASE_HI = 0xA1F9; +constexpr unsigned int mmVGT_DMA_CONTROL__CI__VI = 0x2272; +constexpr unsigned int mmVGT_DMA_DATA_FIFO_DEPTH = 0x222D; +constexpr unsigned int mmVGT_DMA_INDEX_TYPE = 0xA29F; +constexpr unsigned int mmVGT_DMA_LS_HS_CONFIG__CI__VI = 0x2273; +constexpr unsigned int mmVGT_DMA_MAX_SIZE = 0xA29E; +constexpr unsigned int mmVGT_DMA_NUM_INSTANCES = 0xA2A2; +constexpr unsigned int mmVGT_DMA_PRIMITIVE_TYPE__CI__VI = 0x2271; +constexpr unsigned int mmVGT_DMA_REQ_FIFO_DEPTH = 0x222E; +constexpr unsigned int mmVGT_DMA_SIZE = 0xA29D; +constexpr unsigned int mmVGT_DRAW_INITIATOR = 0xA1FC; +constexpr unsigned int mmVGT_DRAW_INIT_FIFO_DEPTH = 0x222F; +constexpr unsigned int mmVGT_ENHANCE = 0xA294; +constexpr unsigned int mmVGT_ESGS_RING_ITEMSIZE = 0xA2AB; +constexpr unsigned int mmVGT_ESGS_RING_SIZE__CI__VI = 0xC240; +constexpr unsigned int mmVGT_ESGS_RING_SIZE__SI = 0x2232; +constexpr unsigned int mmVGT_ES_PER_GS = 0xA296; +constexpr unsigned int mmVGT_EVENT_ADDRESS_REG = 0xA1FE; +constexpr unsigned int mmVGT_EVENT_INITIATOR = 0xA2A4; +constexpr unsigned int mmVGT_FIFO_DEPTHS = 0x2234; +constexpr unsigned int mmVGT_GROUP_DECR = 0xA28B; +constexpr unsigned int mmVGT_GROUP_FIRST_DECR = 0xA28A; +constexpr unsigned int mmVGT_GROUP_PRIM_TYPE = 0xA289; +constexpr unsigned int mmVGT_GROUP_VECT_0_CNTL = 0xA28C; +constexpr unsigned int mmVGT_GROUP_VECT_0_FMT_CNTL = 0xA28E; +constexpr unsigned int mmVGT_GROUP_VECT_1_CNTL = 0xA28D; +constexpr unsigned int mmVGT_GROUP_VECT_1_FMT_CNTL = 0xA28F; +constexpr unsigned int mmVGT_GSVS_RING_ITEMSIZE = 0xA2AC; +constexpr unsigned int mmVGT_GSVS_RING_OFFSET_1 = 0xA298; +constexpr unsigned int mmVGT_GSVS_RING_OFFSET_2 = 0xA299; +constexpr unsigned int mmVGT_GSVS_RING_OFFSET_3 = 0xA29A; +constexpr unsigned int mmVGT_GSVS_RING_SIZE__CI__VI = 0xC241; +constexpr unsigned int mmVGT_GSVS_RING_SIZE__SI = 0x2233; +constexpr unsigned int mmVGT_GS_INSTANCE_CNT = 0xA2E4; +constexpr unsigned int mmVGT_GS_MAX_VERT_OUT = 0xA2CE; +constexpr unsigned int mmVGT_GS_MODE = 0xA290; +constexpr unsigned int mmVGT_GS_ONCHIP_CNTL__CI__VI = 0xA291; +constexpr unsigned int mmVGT_GS_OUT_PRIM_TYPE = 0xA29B; +constexpr unsigned int mmVGT_GS_PER_ES = 0xA295; +constexpr unsigned int mmVGT_GS_PER_VS = 0xA297; +constexpr unsigned int mmVGT_GS_VERTEX_REUSE = 0x2235; +constexpr unsigned int mmVGT_GS_VERT_ITEMSIZE = 0xA2D7; +constexpr unsigned int mmVGT_GS_VERT_ITEMSIZE_1 = 0xA2D8; +constexpr unsigned int mmVGT_GS_VERT_ITEMSIZE_2 = 0xA2D9; +constexpr unsigned int mmVGT_GS_VERT_ITEMSIZE_3 = 0xA2DA; +constexpr unsigned int mmVGT_HOS_CNTL = 0xA285; +constexpr unsigned int mmVGT_HOS_MAX_TESS_LEVEL = 0xA286; +constexpr unsigned int mmVGT_HOS_MIN_TESS_LEVEL = 0xA287; +constexpr unsigned int mmVGT_HOS_REUSE_DEPTH = 0xA288; +constexpr unsigned int mmVGT_HS_OFFCHIP_PARAM__CI__VI = 0xC24F; +constexpr unsigned int mmVGT_HS_OFFCHIP_PARAM__SI = 0x226C; +constexpr unsigned int mmVGT_IMMED_DATA = 0xA1FD; +constexpr unsigned int mmVGT_INDEX_TYPE__CI__VI = 0xC243; +constexpr unsigned int mmVGT_INDEX_TYPE__SI = 0x2257; +constexpr unsigned int mmVGT_INDX_OFFSET = 0xA102; +constexpr unsigned int mmVGT_INSTANCE_STEP_RATE_0 = 0xA2A8; +constexpr unsigned int mmVGT_INSTANCE_STEP_RATE_1 = 0xA2A9; +constexpr unsigned int mmVGT_LAST_COPY_STATE = 0x2230; +constexpr unsigned int mmVGT_LS_HS_CONFIG = 0xA2D6; +constexpr unsigned int mmVGT_MAX_VTX_INDX = 0xA100; +constexpr unsigned int mmVGT_MC_LAT_CNTL = 0x2236; +constexpr unsigned int mmVGT_MIN_VTX_INDX = 0xA101; +constexpr unsigned int mmVGT_MULTI_PRIM_IB_RESET_EN = 0xA2A5; +constexpr unsigned int mmVGT_MULTI_PRIM_IB_RESET_INDX = 0xA103; +constexpr unsigned int mmVGT_NUM_INDICES__CI__VI = 0xC24C; +constexpr unsigned int mmVGT_NUM_INDICES__SI = 0x225C; +constexpr unsigned int mmVGT_NUM_INSTANCES__CI__VI = 0xC24D; +constexpr unsigned int mmVGT_NUM_INSTANCES__SI = 0x225D; +constexpr unsigned int mmVGT_OUTPUT_PATH_CNTL = 0xA284; +constexpr unsigned int mmVGT_OUT_DEALLOC_CNTL = 0xA317; +constexpr unsigned int mmVGT_PERFCOUNTER0_HI__CI__VI = 0xD091; +constexpr unsigned int mmVGT_PERFCOUNTER0_HI__SI = 0x224D; +constexpr unsigned int mmVGT_PERFCOUNTER0_LO__CI__VI = 0xD090; +constexpr unsigned int mmVGT_PERFCOUNTER0_LO__SI = 0x224C; +constexpr unsigned int mmVGT_PERFCOUNTER0_SELECT1__CI__VI = 0xD890; +constexpr unsigned int mmVGT_PERFCOUNTER0_SELECT__CI__VI = 0xD88C; +constexpr unsigned int mmVGT_PERFCOUNTER0_SELECT__SI = 0x2248; +constexpr unsigned int mmVGT_PERFCOUNTER1_HI__CI__VI = 0xD093; +constexpr unsigned int mmVGT_PERFCOUNTER1_HI__SI = 0x224F; +constexpr unsigned int mmVGT_PERFCOUNTER1_LO__CI__VI = 0xD092; +constexpr unsigned int mmVGT_PERFCOUNTER1_LO__SI = 0x224E; +constexpr unsigned int mmVGT_PERFCOUNTER1_SELECT1__CI__VI = 0xD891; +constexpr unsigned int mmVGT_PERFCOUNTER1_SELECT__CI__VI = 0xD88D; +constexpr unsigned int mmVGT_PERFCOUNTER1_SELECT__SI = 0x2249; +constexpr unsigned int mmVGT_PERFCOUNTER2_HI__CI__VI = 0xD095; +constexpr unsigned int mmVGT_PERFCOUNTER2_HI__SI = 0x2251; +constexpr unsigned int mmVGT_PERFCOUNTER2_LO__CI__VI = 0xD094; +constexpr unsigned int mmVGT_PERFCOUNTER2_LO__SI = 0x2250; +constexpr unsigned int mmVGT_PERFCOUNTER2_SELECT__CI__VI = 0xD88E; +constexpr unsigned int mmVGT_PERFCOUNTER2_SELECT__SI = 0x224A; +constexpr unsigned int mmVGT_PERFCOUNTER3_HI__CI__VI = 0xD097; +constexpr unsigned int mmVGT_PERFCOUNTER3_HI__SI = 0x2253; +constexpr unsigned int mmVGT_PERFCOUNTER3_LO__CI__VI = 0xD096; +constexpr unsigned int mmVGT_PERFCOUNTER3_LO__SI = 0x2252; +constexpr unsigned int mmVGT_PERFCOUNTER3_SELECT__CI__VI = 0xD88F; +constexpr unsigned int mmVGT_PERFCOUNTER3_SELECT__SI = 0x224B; +constexpr unsigned int mmVGT_PERFCOUNTER_SEID_MASK__CI__VI = 0xD894; +constexpr unsigned int mmVGT_PERFCOUNTER_SEID_MASK__SI = 0x2247; +constexpr unsigned int mmVGT_PRIMITIVEID_EN = 0xA2A1; +constexpr unsigned int mmVGT_PRIMITIVEID_RESET = 0xA2A3; +constexpr unsigned int mmVGT_PRIMITIVE_TYPE__CI__VI = 0xC242; +constexpr unsigned int mmVGT_PRIMITIVE_TYPE__SI = 0x2256; +constexpr unsigned int mmVGT_RESET_DEBUG__CI__VI = 0x2232; +constexpr unsigned int mmVGT_REUSE_OFF = 0xA2AD; +constexpr unsigned int mmVGT_SHADER_STAGES_EN = 0xA2D5; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_CONFIG = 0xA2E6; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_0__CI__VI = 0xC244; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_0__SI = 0x2258; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_1__CI__VI = 0xC245; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_1__SI = 0x2259; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_2__CI__VI = 0xC246; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_2__SI = 0x225A; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_3__CI__VI = 0xC247; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_FILLED_SIZE_3__SI = 0x225B; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_OFFSET_0 = 0xA2B7; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_OFFSET_1 = 0xA2BB; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_OFFSET_2 = 0xA2BF; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_OFFSET_3 = 0xA2C3; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_SIZE_0 = 0xA2B4; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_SIZE_1 = 0xA2B8; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_SIZE_2 = 0xA2BC; +constexpr unsigned int mmVGT_STRMOUT_BUFFER_SIZE_3 = 0xA2C0; +constexpr unsigned int mmVGT_STRMOUT_CONFIG = 0xA2E5; +constexpr unsigned int mmVGT_STRMOUT_DELAY__CI__VI = 0x2233; +constexpr unsigned int mmVGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE = 0xA2CB; +constexpr unsigned int mmVGT_STRMOUT_DRAW_OPAQUE_OFFSET = 0xA2CA; +constexpr unsigned int mmVGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE = 0xA2CC; +constexpr unsigned int mmVGT_STRMOUT_VTX_STRIDE_0 = 0xA2B5; +constexpr unsigned int mmVGT_STRMOUT_VTX_STRIDE_1 = 0xA2B9; +constexpr unsigned int mmVGT_STRMOUT_VTX_STRIDE_2 = 0xA2BD; +constexpr unsigned int mmVGT_STRMOUT_VTX_STRIDE_3 = 0xA2C1; +constexpr unsigned int mmVGT_SYS_CONFIG = 0x2263; +constexpr unsigned int mmVGT_TF_MEMORY_BASE__CI__VI = 0xC250; +constexpr unsigned int mmVGT_TF_MEMORY_BASE__SI = 0x226E; +constexpr unsigned int mmVGT_TF_PARAM = 0xA2DB; +constexpr unsigned int mmVGT_TF_RING_SIZE__CI__VI = 0xC24E; +constexpr unsigned int mmVGT_TF_RING_SIZE__SI = 0x2262; +constexpr unsigned int mmVGT_VERTEX_REUSE_BLOCK_CNTL = 0xA316; +constexpr unsigned int mmVGT_VS_MAX_WAVE_ID__CI__VI = 0x2268; +constexpr unsigned int mmVGT_VTX_CNT_EN = 0xA2AE; +constexpr unsigned int mmVGT_VTX_VECT_EJECT_REG = 0x222C; +constexpr unsigned int mmVIEWPORT_SIZE__SI__VI = 0x1B5D; +constexpr unsigned int mmVIEWPORT_START__SI__VI = 0x1B5C; +constexpr unsigned int mmVLINE_STATUS__SI = 0x1AEE; +constexpr unsigned int mmVM_CONTEXT0_CNTL = 0x0504; +constexpr unsigned int mmVM_CONTEXT0_CNTL2 = 0x050C; +constexpr unsigned int mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR = 0x054F; +constexpr unsigned int mmVM_CONTEXT0_PAGE_TABLE_END_ADDR = 0x055F; +constexpr unsigned int mmVM_CONTEXT0_PAGE_TABLE_START_ADDR = 0x0557; +constexpr unsigned int mmVM_CONTEXT0_PROTECTION_FAULT_ADDR = 0x053E; +constexpr unsigned int mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR = 0x0546; +constexpr unsigned int mmVM_CONTEXT0_PROTECTION_FAULT_MCCLIENT__CI__VI = 0x0538; +constexpr unsigned int mmVM_CONTEXT0_PROTECTION_FAULT_STATUS = 0x0536; +constexpr unsigned int mmVM_CONTEXT10_PAGE_TABLE_BASE_ADDR = 0x0510; +constexpr unsigned int mmVM_CONTEXT11_PAGE_TABLE_BASE_ADDR = 0x0511; +constexpr unsigned int mmVM_CONTEXT12_PAGE_TABLE_BASE_ADDR = 0x0512; +constexpr unsigned int mmVM_CONTEXT13_PAGE_TABLE_BASE_ADDR = 0x0513; +constexpr unsigned int mmVM_CONTEXT14_PAGE_TABLE_BASE_ADDR = 0x0514; +constexpr unsigned int mmVM_CONTEXT15_PAGE_TABLE_BASE_ADDR = 0x0515; +constexpr unsigned int mmVM_CONTEXT1_CNTL = 0x0505; +constexpr unsigned int mmVM_CONTEXT1_CNTL2 = 0x050D; +constexpr unsigned int mmVM_CONTEXT1_PAGE_TABLE_BASE_ADDR = 0x0550; +constexpr unsigned int mmVM_CONTEXT1_PAGE_TABLE_END_ADDR = 0x0560; +constexpr unsigned int mmVM_CONTEXT1_PAGE_TABLE_START_ADDR = 0x0558; +constexpr unsigned int mmVM_CONTEXT1_PROTECTION_FAULT_ADDR = 0x053F; +constexpr unsigned int mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR = 0x0547; +constexpr unsigned int mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT__CI__VI = 0x0539; +constexpr unsigned int mmVM_CONTEXT1_PROTECTION_FAULT_STATUS = 0x0537; +constexpr unsigned int mmVM_CONTEXT2_PAGE_TABLE_BASE_ADDR = 0x0551; +constexpr unsigned int mmVM_CONTEXT3_PAGE_TABLE_BASE_ADDR = 0x0552; +constexpr unsigned int mmVM_CONTEXT4_PAGE_TABLE_BASE_ADDR = 0x0553; +constexpr unsigned int mmVM_CONTEXT5_PAGE_TABLE_BASE_ADDR = 0x0554; +constexpr unsigned int mmVM_CONTEXT6_PAGE_TABLE_BASE_ADDR = 0x0555; +constexpr unsigned int mmVM_CONTEXT7_PAGE_TABLE_BASE_ADDR = 0x0556; +constexpr unsigned int mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR = 0x050E; +constexpr unsigned int mmVM_CONTEXT9_PAGE_TABLE_BASE_ADDR = 0x050F; +constexpr unsigned int mmVM_CONTEXTS_DISABLE = 0x0535; +constexpr unsigned int mmVM_DEBUG = 0x056F; +constexpr unsigned int mmVM_DUMMY_PAGE_FAULT_ADDR = 0x0507; +constexpr unsigned int mmVM_DUMMY_PAGE_FAULT_CNTL = 0x0506; +constexpr unsigned int mmVM_FAULT_CLIENT_ID = 0x054E; +constexpr unsigned int mmVM_INVALIDATE_REQUEST = 0x051E; +constexpr unsigned int mmVM_INVALIDATE_RESPONSE = 0x051F; +constexpr unsigned int mmVM_L2_BANK_SELECT_MASKA = 0x0572; +constexpr unsigned int mmVM_L2_BANK_SELECT_MASKB = 0x0573; +constexpr unsigned int mmVM_L2_CG = 0x0570; +constexpr unsigned int mmVM_L2_CNTL = 0x0500; +constexpr unsigned int mmVM_L2_CNTL2 = 0x0501; +constexpr unsigned int mmVM_L2_CNTL3 = 0x0502; +constexpr unsigned int mmVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR = 0x0576; +constexpr unsigned int mmVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR = 0x0575; +constexpr unsigned int mmVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET = 0x0577; +constexpr unsigned int mmVM_L2_STATUS = 0x0503; +constexpr unsigned int mmVM_PRT_APERTURE0_HIGH_ADDR = 0x0530; +constexpr unsigned int mmVM_PRT_APERTURE0_LOW_ADDR = 0x052C; +constexpr unsigned int mmVM_PRT_APERTURE1_HIGH_ADDR = 0x0531; +constexpr unsigned int mmVM_PRT_APERTURE1_LOW_ADDR = 0x052D; +constexpr unsigned int mmVM_PRT_APERTURE2_HIGH_ADDR = 0x0532; +constexpr unsigned int mmVM_PRT_APERTURE2_LOW_ADDR = 0x052E; +constexpr unsigned int mmVM_PRT_APERTURE3_HIGH_ADDR = 0x0533; +constexpr unsigned int mmVM_PRT_APERTURE3_LOW_ADDR = 0x052F; +constexpr unsigned int mmVM_PRT_CNTL = 0x0534; +constexpr unsigned int mmWD_CNTL_STATUS__CI__VI = 0x223F; +constexpr unsigned int mmWD_DEBUG_CNTL__CI__VI = 0x223D; +constexpr unsigned int mmWD_DEBUG_DATA__CI__VI = 0x223E; +constexpr unsigned int mmWD_ENHANCE__CI__VI = 0xA2A0; +constexpr unsigned int mmWD_PERFCOUNTER0_HI__CI__VI = 0xD081; +constexpr unsigned int mmWD_PERFCOUNTER0_LO__CI__VI = 0xD080; +constexpr unsigned int mmWD_PERFCOUNTER0_SELECT__CI__VI = 0xD880; +constexpr unsigned int mmWD_PERFCOUNTER1_HI__CI__VI = 0xD083; +constexpr unsigned int mmWD_PERFCOUNTER1_LO__CI__VI = 0xD082; +constexpr unsigned int mmWD_PERFCOUNTER1_SELECT__CI__VI = 0xD881; +constexpr unsigned int mmWD_PERFCOUNTER2_HI__CI__VI = 0xD085; +constexpr unsigned int mmWD_PERFCOUNTER2_LO__CI__VI = 0xD084; +constexpr unsigned int mmWD_PERFCOUNTER2_SELECT__CI__VI = 0xD882; +constexpr unsigned int mmWD_PERFCOUNTER3_HI__CI__VI = 0xD087; +constexpr unsigned int mmWD_PERFCOUNTER3_LO__CI__VI = 0xD086; +constexpr unsigned int mmWD_PERFCOUNTER3_SELECT__CI__VI = 0xD883; +constexpr unsigned int mmXDMA_SLV_FLIP_PENDING__CI__VI = 0x046C; +constexpr unsigned int mmXDMA_SLV_FLIP_PENDING__SI = 0x0407; +constexpr unsigned int pciADAPTER_ID = 0x000B; +constexpr unsigned int pciADAPTER_ID_W = 0x0013; +constexpr unsigned int pciBASE_ADDR_1 = 0x0004; +constexpr unsigned int pciBASE_ADDR_2 = 0x0005; +constexpr unsigned int pciBASE_ADDR_3 = 0x0006; +constexpr unsigned int pciBASE_ADDR_4 = 0x0007; +constexpr unsigned int pciBASE_ADDR_5 = 0x0008; +constexpr unsigned int pciBASE_ADDR_6 = 0x0009; +constexpr unsigned int pciBASE_CLASS = 0x0002; +constexpr unsigned int pciBIST = 0x0003; +constexpr unsigned int pciCACHE_LINE = 0x0003; +constexpr unsigned int pciCAP_PTR = 0x000D; +constexpr unsigned int pciCOMMAND = 0x0001; +constexpr unsigned int pciDEVICE_CAP = 0x0017; +constexpr unsigned int pciDEVICE_CAP2 = 0x001F; +constexpr unsigned int pciDEVICE_CNTL = 0x0018; +constexpr unsigned int pciDEVICE_CNTL2 = 0x0020; +constexpr unsigned int pciDEVICE_ID = 0x0000; +constexpr unsigned int pciDEVICE_STATUS = 0x0018; +constexpr unsigned int pciDEVICE_STATUS2 = 0x0020; +constexpr unsigned int pciHEADER = 0x0003; +constexpr unsigned int pciINTERRUPT_LINE = 0x000F; +constexpr unsigned int pciINTERRUPT_PIN = 0x000F; +constexpr unsigned int pciLATENCY = 0x0003; +constexpr unsigned int pciLINK_CAP = 0x0019; +constexpr unsigned int pciLINK_CAP2 = 0x0021; +constexpr unsigned int pciLINK_CNTL = 0x001A; +constexpr unsigned int pciLINK_CNTL2 = 0x0022; +constexpr unsigned int pciLINK_STATUS = 0x001A; +constexpr unsigned int pciLINK_STATUS2 = 0x0022; +constexpr unsigned int pciMAX_LATENCY = 0x000F; +constexpr unsigned int pciMIN_GRANT = 0x000F; +constexpr unsigned int pciMSI_CAP_LIST = 0x0028; +constexpr unsigned int pciMSI_MSG_ADDR_HI = 0x002A; +constexpr unsigned int pciMSI_MSG_ADDR_LO = 0x0029; +constexpr unsigned int pciMSI_MSG_CNTL = 0x0028; +constexpr unsigned int pciMSI_MSG_DATA = 0x002A; +constexpr unsigned int pciMSI_MSG_DATA_64 = 0x002B; +constexpr unsigned int pciPCIE_ACS_CAP__CI__VI = 0x00A9; +constexpr unsigned int pciPCIE_ACS_CNTL__CI__VI = 0x00A9; +constexpr unsigned int pciPCIE_ACS_ENH_CAP_LIST__CI__VI = 0x00A8; +constexpr unsigned int pciPCIE_ADV_ERR_CAP_CNTL = 0x005A; +constexpr unsigned int pciPCIE_ADV_ERR_RPT_ENH_CAP_LIST = 0x0054; +constexpr unsigned int pciPCIE_ATS_CAP__CI__VI = 0x00AD; +constexpr unsigned int pciPCIE_ATS_CNTL__CI__VI = 0x00AD; +constexpr unsigned int pciPCIE_ATS_ENH_CAP_LIST__CI__VI = 0x00AC; +constexpr unsigned int pciPCIE_BAR1_CAP__CI__VI = 0x0081; +constexpr unsigned int pciPCIE_BAR1_CNTL__CI__VI = 0x0082; +constexpr unsigned int pciPCIE_BAR2_CAP__CI__VI = 0x0083; +constexpr unsigned int pciPCIE_BAR2_CNTL__CI__VI = 0x0084; +constexpr unsigned int pciPCIE_BAR3_CAP__CI__VI = 0x0085; +constexpr unsigned int pciPCIE_BAR3_CNTL__CI__VI = 0x0086; +constexpr unsigned int pciPCIE_BAR4_CAP__CI__VI = 0x0087; +constexpr unsigned int pciPCIE_BAR4_CNTL__CI__VI = 0x0088; +constexpr unsigned int pciPCIE_BAR5_CAP__CI__VI = 0x0089; +constexpr unsigned int pciPCIE_BAR5_CNTL__CI__VI = 0x008A; +constexpr unsigned int pciPCIE_BAR6_CAP__CI__VI = 0x008B; +constexpr unsigned int pciPCIE_BAR6_CNTL__CI__VI = 0x008C; +constexpr unsigned int pciPCIE_BAR_ENH_CAP_LIST__CI__VI = 0x0080; +constexpr unsigned int pciPCIE_CAP = 0x0016; +constexpr unsigned int pciPCIE_CAP_LIST = 0x0016; +constexpr unsigned int pciPCIE_CORR_ERR_MASK = 0x0059; +constexpr unsigned int pciPCIE_CORR_ERR_STATUS = 0x0058; +constexpr unsigned int pciPCIE_DEV_SERIAL_NUM_DW1 = 0x0051; +constexpr unsigned int pciPCIE_DEV_SERIAL_NUM_DW2 = 0x0052; +constexpr unsigned int pciPCIE_DEV_SERIAL_NUM_ENH_CAP_LIST = 0x0050; +constexpr unsigned int pciPCIE_DPA_CAP__CI__VI = 0x0095; +constexpr unsigned int pciPCIE_DPA_CNTL__CI__VI = 0x0097; +constexpr unsigned int pciPCIE_DPA_ENH_CAP_LIST__CI__VI = 0x0094; +constexpr unsigned int pciPCIE_DPA_LATENCY_INDICATOR__CI__VI = 0x0096; +constexpr unsigned int pciPCIE_DPA_STATUS__CI__VI = 0x0097; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_0__CI__VI = 0x0098; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_1__CI__VI = 0x0098; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_2__CI__VI = 0x0098; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_3__CI__VI = 0x0098; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_4__CI__VI = 0x0099; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_5__CI__VI = 0x0099; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_6__CI__VI = 0x0099; +constexpr unsigned int pciPCIE_DPA_SUBSTATE_PWR_ALLOC_7__CI__VI = 0x0099; +constexpr unsigned int pciPCIE_HDR_LOG0 = 0x005B; +constexpr unsigned int pciPCIE_HDR_LOG1 = 0x005C; +constexpr unsigned int pciPCIE_HDR_LOG2 = 0x005D; +constexpr unsigned int pciPCIE_HDR_LOG3 = 0x005E; +constexpr unsigned int pciPCIE_LANE_0_EQUALIZATION_CNTL__CI__VI = 0x009F; +constexpr unsigned int pciPCIE_LANE_10_EQUALIZATION_CNTL__CI__VI = 0x00A4; +constexpr unsigned int pciPCIE_LANE_11_EQUALIZATION_CNTL__CI__VI = 0x00A4; +constexpr unsigned int pciPCIE_LANE_12_EQUALIZATION_CNTL__CI__VI = 0x00A5; +constexpr unsigned int pciPCIE_LANE_13_EQUALIZATION_CNTL__CI__VI = 0x00A5; +constexpr unsigned int pciPCIE_LANE_14_EQUALIZATION_CNTL__CI__VI = 0x00A6; +constexpr unsigned int pciPCIE_LANE_15_EQUALIZATION_CNTL__CI__VI = 0x00A6; +constexpr unsigned int pciPCIE_LANE_1_EQUALIZATION_CNTL__CI__VI = 0x009F; +constexpr unsigned int pciPCIE_LANE_2_EQUALIZATION_CNTL__CI__VI = 0x00A0; +constexpr unsigned int pciPCIE_LANE_3_EQUALIZATION_CNTL__CI__VI = 0x00A0; +constexpr unsigned int pciPCIE_LANE_4_EQUALIZATION_CNTL__CI__VI = 0x00A1; +constexpr unsigned int pciPCIE_LANE_5_EQUALIZATION_CNTL__CI__VI = 0x00A1; +constexpr unsigned int pciPCIE_LANE_6_EQUALIZATION_CNTL__CI__VI = 0x00A2; +constexpr unsigned int pciPCIE_LANE_7_EQUALIZATION_CNTL__CI__VI = 0x00A2; +constexpr unsigned int pciPCIE_LANE_8_EQUALIZATION_CNTL__CI__VI = 0x00A3; +constexpr unsigned int pciPCIE_LANE_9_EQUALIZATION_CNTL__CI__VI = 0x00A3; +constexpr unsigned int pciPCIE_LANE_ERROR_STATUS__CI__VI = 0x009E; +constexpr unsigned int pciPCIE_LINK_CNTL3__CI__VI = 0x009D; +constexpr unsigned int pciPCIE_OUTSTAND_PAGE_REQ_ALLOC__CI__VI = 0x00B3; +constexpr unsigned int pciPCIE_OUTSTAND_PAGE_REQ_CAPACITY__CI__VI = 0x00B2; +constexpr unsigned int pciPCIE_PAGE_REQ_CNTL__CI__VI = 0x00B1; +constexpr unsigned int pciPCIE_PAGE_REQ_ENH_CAP_LIST__CI__VI = 0x00B0; +constexpr unsigned int pciPCIE_PAGE_REQ_STATUS__CI__VI = 0x00B1; +constexpr unsigned int pciPCIE_PASID_CAP__CI__VI = 0x00B5; +constexpr unsigned int pciPCIE_PASID_CNTL__CI__VI = 0x00B5; +constexpr unsigned int pciPCIE_PASID_ENH_CAP_LIST__CI__VI = 0x00B4; +constexpr unsigned int pciPCIE_PORT_VC_CAP_REG1 = 0x0045; +constexpr unsigned int pciPCIE_PORT_VC_CAP_REG2 = 0x0046; +constexpr unsigned int pciPCIE_PORT_VC_CNTL = 0x0047; +constexpr unsigned int pciPCIE_PORT_VC_STATUS = 0x0047; +constexpr unsigned int pciPCIE_PWR_BUDGET_CAP__CI__VI = 0x0093; +constexpr unsigned int pciPCIE_PWR_BUDGET_DATA_SELECT__CI__VI = 0x0091; +constexpr unsigned int pciPCIE_PWR_BUDGET_DATA__CI__VI = 0x0092; +constexpr unsigned int pciPCIE_PWR_BUDGET_ENH_CAP_LIST__CI__VI = 0x0090; +constexpr unsigned int pciPCIE_SECONDARY_ENH_CAP_LIST__CI__VI = 0x009C; +constexpr unsigned int pciPCIE_TLP_PREFIX_LOG0__CI__VI = 0x0062; +constexpr unsigned int pciPCIE_TLP_PREFIX_LOG1__CI__VI = 0x0063; +constexpr unsigned int pciPCIE_TLP_PREFIX_LOG2__CI__VI = 0x0064; +constexpr unsigned int pciPCIE_TLP_PREFIX_LOG3__CI__VI = 0x0065; +constexpr unsigned int pciPCIE_UNCORR_ERR_MASK = 0x0056; +constexpr unsigned int pciPCIE_UNCORR_ERR_SEVERITY = 0x0057; +constexpr unsigned int pciPCIE_UNCORR_ERR_STATUS = 0x0055; +constexpr unsigned int pciPCIE_VC0_RESOURCE_CAP = 0x0048; +constexpr unsigned int pciPCIE_VC0_RESOURCE_CNTL = 0x0049; +constexpr unsigned int pciPCIE_VC0_RESOURCE_STATUS = 0x004A; +constexpr unsigned int pciPCIE_VC1_RESOURCE_CAP = 0x004B; +constexpr unsigned int pciPCIE_VC1_RESOURCE_CNTL = 0x004C; +constexpr unsigned int pciPCIE_VC1_RESOURCE_STATUS = 0x004D; +constexpr unsigned int pciPCIE_VC_ENH_CAP_LIST = 0x0044; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC1 = 0x0042; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC2 = 0x0043; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC_ENH_CAP_LIST = 0x0040; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC_HDR = 0x0041; +constexpr unsigned int pciPMI_CAP = 0x0014; +constexpr unsigned int pciPMI_CAP_LIST = 0x0014; +constexpr unsigned int pciPMI_STATUS_CNTL = 0x0015; +constexpr unsigned int pciPROG_INTERFACE = 0x0002; +constexpr unsigned int pciREVISION_ID = 0x0002; +constexpr unsigned int pciROM_BASE_ADDR = 0x000C; +constexpr unsigned int pciSTATUS = 0x0001; +constexpr unsigned int pciSUB_CLASS = 0x0002; +constexpr unsigned int pciVENDOR_CAP_LIST__CI__VI = 0x0012; +constexpr unsigned int pciVENDOR_ID = 0x0000; + +//Merged Defines + +constexpr unsigned int cfgMSI_MASK__VI = 0x002B; +constexpr unsigned int cfgMSI_MASK_64__VI = 0x002C; +constexpr unsigned int cfgMSI_PENDING__VI = 0x002C; +constexpr unsigned int cfgMSI_PENDING_64__VI = 0x002D; +constexpr unsigned int cfgPCIE_ARI_CAP__VI = 0x00CB; +constexpr unsigned int cfgPCIE_ARI_CNTL__VI = 0x00CB; +constexpr unsigned int cfgPCIE_ARI_ENH_CAP_LIST__VI = 0x00CA; +constexpr unsigned int cfgPCIE_LTR_CAP__VI = 0x00C9; +constexpr unsigned int cfgPCIE_LTR_ENH_CAP_LIST__VI = 0x00C8; +constexpr unsigned int cfgPCIE_MC_ADDR0__VI = 0x00BE; +constexpr unsigned int cfgPCIE_MC_ADDR1__VI = 0x00BF; +constexpr unsigned int cfgPCIE_MC_BLOCK_ALL0__VI = 0x00C2; +constexpr unsigned int cfgPCIE_MC_BLOCK_ALL1__VI = 0x00C3; +constexpr unsigned int cfgPCIE_MC_BLOCK_UNTRANSLATED_0__VI = 0x00C4; +constexpr unsigned int cfgPCIE_MC_BLOCK_UNTRANSLATED_1__VI = 0x00C5; +constexpr unsigned int cfgPCIE_MC_CAP__VI = 0x00BD; +constexpr unsigned int cfgPCIE_MC_CNTL__VI = 0x00BD; +constexpr unsigned int cfgPCIE_MC_ENH_CAP_LIST__VI = 0x00BC; +constexpr unsigned int cfgPCIE_MC_RCV0__VI = 0x00C0; +constexpr unsigned int cfgPCIE_MC_RCV1__VI = 0x00C1; +constexpr unsigned int cfgPCIE_SRIOV_CAP__VI = 0x00CD; +constexpr unsigned int cfgPCIE_SRIOV_CONTROL__VI = 0x00CE; +constexpr unsigned int cfgPCIE_SRIOV_ENH_CAP_LIST__VI = 0x00CC; +constexpr unsigned int cfgPCIE_SRIOV_FIRST_VF_OFFSET__VI = 0x00D1; +constexpr unsigned int cfgPCIE_SRIOV_FUNC_DEP_LINK__VI = 0x00D0; +constexpr unsigned int cfgPCIE_SRIOV_INITIAL_VFS__VI = 0x00CF; +constexpr unsigned int cfgPCIE_SRIOV_NUM_VFS__VI = 0x00D0; +constexpr unsigned int cfgPCIE_SRIOV_STATUS__VI = 0x00CE; +constexpr unsigned int cfgPCIE_SRIOV_SUPPORTED_PAGE_SIZE__VI = 0x00D3; +constexpr unsigned int cfgPCIE_SRIOV_SYSTEM_PAGE_SIZE__VI = 0x00D4; +constexpr unsigned int cfgPCIE_SRIOV_TOTAL_VFS__VI = 0x00CF; +constexpr unsigned int cfgPCIE_SRIOV_VF_BASE_ADDR_0__VI = 0x00D5; +constexpr unsigned int cfgPCIE_SRIOV_VF_BASE_ADDR_1__VI = 0x00D6; +constexpr unsigned int cfgPCIE_SRIOV_VF_BASE_ADDR_2__VI = 0x00D7; +constexpr unsigned int cfgPCIE_SRIOV_VF_BASE_ADDR_3__VI = 0x00D8; +constexpr unsigned int cfgPCIE_SRIOV_VF_BASE_ADDR_4__VI = 0x00D9; +constexpr unsigned int cfgPCIE_SRIOV_VF_BASE_ADDR_5__VI = 0x00DA; +constexpr unsigned int cfgPCIE_SRIOV_VF_DEVICE_ID__VI = 0x00D2; +constexpr unsigned int cfgPCIE_SRIOV_VF_MIGRATION_STATE_ARRAY_OFFSET__VI = 0x00DB; +constexpr unsigned int cfgPCIE_SRIOV_VF_STRIDE__VI = 0x00D1; +constexpr unsigned int cfgPCIE_TPH_REQR_CAP__VI = 0x00B9; +constexpr unsigned int cfgPCIE_TPH_REQR_CNTL__VI = 0x00BA; +constexpr unsigned int cfgPCIE_TPH_REQR_ENH_CAP_LIST__VI = 0x00B8; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC_ENH_CAP_LIST_GPUIOV__VI = 0x0100; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC_HDR_GPUIOV__VI = 0x0101; +constexpr unsigned int cfgPCIE_VENDOR_SPECIFIC_HDR_GPUIOV_RESET_CONTROL__VI = 0x0105; +constexpr unsigned int mmAFMT_60958_0__VI = 0x4A38; +constexpr unsigned int mmAFMT_60958_1__VI = 0x4A39; +constexpr unsigned int mmAFMT_60958_2__VI = 0x4A3F; +constexpr unsigned int mmAFMT_AUDIO_CRC_CONTROL__VI = 0x4A3A; +constexpr unsigned int mmAFMT_AUDIO_CRC_RESULT__VI = 0x4A40; +constexpr unsigned int mmAFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4A46; +constexpr unsigned int mmAFMT_AUDIO_INFO0__VI = 0x4A36; +constexpr unsigned int mmAFMT_AUDIO_INFO1__VI = 0x4A37; +constexpr unsigned int mmAFMT_AUDIO_PACKET_CONTROL__VI = 0x4A42; +constexpr unsigned int mmAFMT_AUDIO_PACKET_CONTROL2__VI = 0x4A14; +constexpr unsigned int mmAFMT_AUDIO_SRC_CONTROL__VI = 0x4A45; +constexpr unsigned int mmAFMT_AVI_INFO0__VI = 0x4A1E; +constexpr unsigned int mmAFMT_AVI_INFO1__VI = 0x4A1F; +constexpr unsigned int mmAFMT_AVI_INFO2__VI = 0x4A20; +constexpr unsigned int mmAFMT_AVI_INFO3__VI = 0x4A21; +constexpr unsigned int mmAFMT_GENERIC_0__VI = 0x4A25; +constexpr unsigned int mmAFMT_GENERIC_1__VI = 0x4A26; +constexpr unsigned int mmAFMT_GENERIC_2__VI = 0x4A27; +constexpr unsigned int mmAFMT_GENERIC_3__VI = 0x4A28; +constexpr unsigned int mmAFMT_GENERIC_4__VI = 0x4A29; +constexpr unsigned int mmAFMT_GENERIC_5__VI = 0x4A2A; +constexpr unsigned int mmAFMT_GENERIC_6__VI = 0x4A2B; +constexpr unsigned int mmAFMT_GENERIC_7__VI = 0x4A2C; +constexpr unsigned int mmAFMT_GENERIC_HDR__VI = 0x4A24; +constexpr unsigned int mmAFMT_INFOFRAME_CONTROL0__VI = 0x4A44; +constexpr unsigned int mmAFMT_ISRC1_0__VI = 0x4A15; +constexpr unsigned int mmAFMT_ISRC1_1__VI = 0x4A16; +constexpr unsigned int mmAFMT_ISRC1_2__VI = 0x4A17; +constexpr unsigned int mmAFMT_ISRC1_3__VI = 0x4A18; +constexpr unsigned int mmAFMT_ISRC1_4__VI = 0x4A19; +constexpr unsigned int mmAFMT_ISRC2_0__VI = 0x4A1A; +constexpr unsigned int mmAFMT_ISRC2_1__VI = 0x4A1B; +constexpr unsigned int mmAFMT_ISRC2_2__VI = 0x4A1C; +constexpr unsigned int mmAFMT_ISRC2_3__VI = 0x4A1D; +constexpr unsigned int mmAFMT_MPEG_INFO0__VI = 0x4A22; +constexpr unsigned int mmAFMT_MPEG_INFO1__VI = 0x4A23; +constexpr unsigned int mmAFMT_RAMP_CONTROL0__VI = 0x4A3B; +constexpr unsigned int mmAFMT_RAMP_CONTROL1__VI = 0x4A3C; +constexpr unsigned int mmAFMT_RAMP_CONTROL2__VI = 0x4A3D; +constexpr unsigned int mmAFMT_RAMP_CONTROL3__VI = 0x4A3E; +constexpr unsigned int mmAFMT_STATUS__VI = 0x4A41; +constexpr unsigned int mmAFMT_VBI_PACKET_CONTROL__VI = 0x4A43; +constexpr unsigned int mmALPHA_CONTROL__VI = 0x1ABC; +constexpr unsigned int mmATC_ATS_FAULT_STATUS_INFO2__VI = 0x0CD2; +constexpr unsigned int mmATC_ATS_SMU_STATUS__VI = 0x0D08; +constexpr unsigned int mmATC_ATS_VMID_STATUS__VI = 0x0D07; +constexpr unsigned int mmATC_L1RD_DEBUG2_TLB__VI = 0x0CE2; +constexpr unsigned int mmATC_L1WR_DEBUG2_TLB__VI = 0x0CE3; +constexpr unsigned int mmATC_L2_CACHE_DATA0__VI = 0x0CD9; +constexpr unsigned int mmATC_L2_CACHE_DATA1__VI = 0x0CDA; +constexpr unsigned int mmATC_L2_CACHE_DATA2__VI = 0x0CDB; +constexpr unsigned int mmATC_L2_CNTL3__VI = 0x0D08; +constexpr unsigned int mmATC_L2_STATUS__VI = 0x0D09; +constexpr unsigned int mmATC_L2_STATUS2__VI = 0x0D0A; +constexpr unsigned int mmAUXN_IMPCAL__VI = 0x483C; +constexpr unsigned int mmAUXP_IMPCAL__VI = 0x483B; +constexpr unsigned int mmAUX_ARB_CONTROL__VI = 0x5C02; +constexpr unsigned int mmAUX_CONTROL__VI = 0x5C00; +constexpr unsigned int mmAUX_DPHY_RX_CONTROL0__VI = 0x5C0A; +constexpr unsigned int mmAUX_DPHY_RX_CONTROL1__VI = 0x5C0B; +constexpr unsigned int mmAUX_DPHY_RX_STATUS__VI = 0x5C0D; +constexpr unsigned int mmAUX_DPHY_TX_CONTROL__VI = 0x5C09; +constexpr unsigned int mmAUX_DPHY_TX_REF_CONTROL__VI = 0x5C08; +constexpr unsigned int mmAUX_DPHY_TX_STATUS__VI = 0x5C0C; +constexpr unsigned int mmAUX_GTC_SYNC_CONTROL__VI = 0x5C0E; +constexpr unsigned int mmAUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C10; +constexpr unsigned int mmAUX_GTC_SYNC_DATA__VI = 0x5C12; +constexpr unsigned int mmAUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C0F; +constexpr unsigned int mmAUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C13; +constexpr unsigned int mmAUX_GTC_SYNC_STATUS__VI = 0x5C11; +constexpr unsigned int mmAUX_INTERRUPT_CONTROL__VI = 0x5C03; +constexpr unsigned int mmAUX_LS_DATA__VI = 0x5C07; +constexpr unsigned int mmAUX_LS_STATUS__VI = 0x5C05; +constexpr unsigned int mmAUX_SW_CONTROL__VI = 0x5C01; +constexpr unsigned int mmAUX_SW_DATA__VI = 0x5C06; +constexpr unsigned int mmAUX_SW_STATUS__VI = 0x5C04; +constexpr unsigned int mmAUX_TEST_DEBUG_DATA__VI = 0x5C15; +constexpr unsigned int mmAUX_TEST_DEBUG_INDEX__VI = 0x5C14; +constexpr unsigned int mmAVSYNC_COUNTER_CONTROL__VI = 0x012B; +constexpr unsigned int mmAVSYNC_COUNTER_READ__VI = 0x012F; +constexpr unsigned int mmAVSYNC_COUNTER_WRITE__VI = 0x012A; +constexpr unsigned int mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__VI = 0x17F3; +constexpr unsigned int mmAZALIA_AUDIO_DTO__VI = 0x17E5; +constexpr unsigned int mmAZALIA_AUDIO_DTO_CONTROL__VI = 0x17E6; +constexpr unsigned int mmAZALIA_BDL_DMA_CONTROL__VI = 0x17EA; +constexpr unsigned int mmAZALIA_CONTROLLER_CLOCK_GATING__VI = 0x17E4; +constexpr unsigned int mmAZALIA_CONTROLLER_DEBUG__VI = 0x17F9; +constexpr unsigned int mmAZALIA_CORB_DMA_CONTROL__VI = 0x17EC; +constexpr unsigned int mmAZALIA_CRC0_CONTROL0__VI = 0x1805; +constexpr unsigned int mmAZALIA_CRC0_CONTROL1__VI = 0x1806; +constexpr unsigned int mmAZALIA_CRC0_CONTROL2__VI = 0x1807; +constexpr unsigned int mmAZALIA_CRC0_CONTROL3__VI = 0x1808; +constexpr unsigned int mmAZALIA_CRC0_RESULT__VI = 0x1809; +constexpr unsigned int mmAZALIA_CRC1_CONTROL0__VI = 0x180A; +constexpr unsigned int mmAZALIA_CRC1_CONTROL1__VI = 0x180B; +constexpr unsigned int mmAZALIA_CRC1_CONTROL2__VI = 0x180C; +constexpr unsigned int mmAZALIA_CRC1_CONTROL3__VI = 0x180D; +constexpr unsigned int mmAZALIA_CRC1_RESULT__VI = 0x180E; +constexpr unsigned int mmAZALIA_CYCLIC_BUFFER_SYNC__VI = 0x17F4; +constexpr unsigned int mmAZALIA_DATA_DMA_CONTROL__VI = 0x17E9; +constexpr unsigned int mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__VI = 0x182A; +constexpr unsigned int mmAZALIA_F0_CODEC_DEBUG__VI = 0x1836; +constexpr unsigned int mmAZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17A9; +constexpr unsigned int mmAZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17A8; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__VI = 0x1833; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__VI = 0x1830; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__VI = 0x1831; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__VI = 0x1832; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__VI = 0x182C; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__VI = 0x182F; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__VI = 0x182E; +constexpr unsigned int mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__VI = 0x182D; +constexpr unsigned int mmAZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59D5; +constexpr unsigned int mmAZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59D4; +constexpr unsigned int mmAZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__VI = 0x182B; +constexpr unsigned int mmAZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__VI = 0x1829; +constexpr unsigned int mmAZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__VI = 0x1828; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET0__VI = 0x1837; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET1__VI = 0x1838; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET2__VI = 0x1839; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET3__VI = 0x183A; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET4__VI = 0x183B; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET5__VI = 0x183C; +constexpr unsigned int mmAZALIA_F0_GTC_GROUP_OFFSET6__VI = 0x183D; +constexpr unsigned int mmAZALIA_GLOBAL_CAPABILITIES__VI = 0x17F5; +constexpr unsigned int mmAZALIA_INPUT_CRC0_CONTROL0__VI = 0x17FB; +constexpr unsigned int mmAZALIA_INPUT_CRC0_CONTROL1__VI = 0x17FC; +constexpr unsigned int mmAZALIA_INPUT_CRC0_CONTROL2__VI = 0x17FD; +constexpr unsigned int mmAZALIA_INPUT_CRC0_CONTROL3__VI = 0x17FE; +constexpr unsigned int mmAZALIA_INPUT_CRC0_RESULT__VI = 0x17FF; +constexpr unsigned int mmAZALIA_INPUT_CRC1_CONTROL0__VI = 0x1800; +constexpr unsigned int mmAZALIA_INPUT_CRC1_CONTROL1__VI = 0x1801; +constexpr unsigned int mmAZALIA_INPUT_CRC1_CONTROL2__VI = 0x1802; +constexpr unsigned int mmAZALIA_INPUT_CRC1_CONTROL3__VI = 0x1803; +constexpr unsigned int mmAZALIA_INPUT_CRC1_RESULT__VI = 0x1804; +constexpr unsigned int mmAZALIA_INPUT_PAYLOAD_CAPABILITY__VI = 0x17F8; +constexpr unsigned int mmAZALIA_MEM_PWR_CTRL__VI = 0x1810; +constexpr unsigned int mmAZALIA_MEM_PWR_STATUS__VI = 0x1811; +constexpr unsigned int mmAZALIA_OUTPUT_PAYLOAD_CAPABILITY__VI = 0x17F6; +constexpr unsigned int mmAZALIA_OUTPUT_STREAM_ARBITER_CONTROL__VI = 0x17F7; +constexpr unsigned int mmAZALIA_RIRB_AND_DP_CONTROL__VI = 0x17EB; +constexpr unsigned int mmAZALIA_SCLK_CONTROL__VI = 0x17E7; +constexpr unsigned int mmAZALIA_STREAM_DATA__VI = 0x1781; +constexpr unsigned int mmAZALIA_STREAM_INDEX__VI = 0x1780; +constexpr unsigned int mmAZALIA_UNDERFLOW_FILLER_SAMPLE__VI = 0x17E8; +constexpr unsigned int mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17A9; +constexpr unsigned int mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17A8; +constexpr unsigned int mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17AD; +constexpr unsigned int mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17AC; +constexpr unsigned int mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17B1; +constexpr unsigned int mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17B0; +constexpr unsigned int mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17B5; +constexpr unsigned int mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17B4; +constexpr unsigned int mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17B9; +constexpr unsigned int mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17B8; +constexpr unsigned int mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17BD; +constexpr unsigned int mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17BC; +constexpr unsigned int mmAZF0ENDPOINT6_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17C1; +constexpr unsigned int mmAZF0ENDPOINT6_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17C0; +constexpr unsigned int mmAZF0ENDPOINT7_AZALIA_F0_CODEC_ENDPOINT_DATA__VI = 0x17C5; +constexpr unsigned int mmAZF0ENDPOINT7_AZALIA_F0_CODEC_ENDPOINT_INDEX__VI = 0x17C4; +constexpr unsigned int mmAZF0INPUTENDPOINT0_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59D5; +constexpr unsigned int mmAZF0INPUTENDPOINT0_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59D4; +constexpr unsigned int mmAZF0INPUTENDPOINT1_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59D9; +constexpr unsigned int mmAZF0INPUTENDPOINT1_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59D8; +constexpr unsigned int mmAZF0INPUTENDPOINT2_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59DD; +constexpr unsigned int mmAZF0INPUTENDPOINT2_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59DC; +constexpr unsigned int mmAZF0INPUTENDPOINT3_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59E1; +constexpr unsigned int mmAZF0INPUTENDPOINT3_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59E0; +constexpr unsigned int mmAZF0INPUTENDPOINT4_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59E5; +constexpr unsigned int mmAZF0INPUTENDPOINT4_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59E4; +constexpr unsigned int mmAZF0INPUTENDPOINT5_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59E9; +constexpr unsigned int mmAZF0INPUTENDPOINT5_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59E8; +constexpr unsigned int mmAZF0INPUTENDPOINT6_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59ED; +constexpr unsigned int mmAZF0INPUTENDPOINT6_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59EC; +constexpr unsigned int mmAZF0INPUTENDPOINT7_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__VI = 0x59F1; +constexpr unsigned int mmAZF0INPUTENDPOINT7_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__VI = 0x59F0; +constexpr unsigned int mmAZF0STREAM0_AZALIA_STREAM_DATA__VI = 0x1781; +constexpr unsigned int mmAZF0STREAM0_AZALIA_STREAM_INDEX__VI = 0x1780; +constexpr unsigned int mmAZF0STREAM10_AZALIA_STREAM_DATA__VI = 0x59C5; +constexpr unsigned int mmAZF0STREAM10_AZALIA_STREAM_INDEX__VI = 0x59C4; +constexpr unsigned int mmAZF0STREAM11_AZALIA_STREAM_DATA__VI = 0x59C7; +constexpr unsigned int mmAZF0STREAM11_AZALIA_STREAM_INDEX__VI = 0x59C6; +constexpr unsigned int mmAZF0STREAM12_AZALIA_STREAM_DATA__VI = 0x59C9; +constexpr unsigned int mmAZF0STREAM12_AZALIA_STREAM_INDEX__VI = 0x59C8; +constexpr unsigned int mmAZF0STREAM13_AZALIA_STREAM_DATA__VI = 0x59CB; +constexpr unsigned int mmAZF0STREAM13_AZALIA_STREAM_INDEX__VI = 0x59CA; +constexpr unsigned int mmAZF0STREAM14_AZALIA_STREAM_DATA__VI = 0x59CD; +constexpr unsigned int mmAZF0STREAM14_AZALIA_STREAM_INDEX__VI = 0x59CC; +constexpr unsigned int mmAZF0STREAM15_AZALIA_STREAM_DATA__VI = 0x59CF; +constexpr unsigned int mmAZF0STREAM15_AZALIA_STREAM_INDEX__VI = 0x59CE; +constexpr unsigned int mmAZF0STREAM1_AZALIA_STREAM_DATA__VI = 0x1783; +constexpr unsigned int mmAZF0STREAM1_AZALIA_STREAM_INDEX__VI = 0x1782; +constexpr unsigned int mmAZF0STREAM2_AZALIA_STREAM_DATA__VI = 0x1785; +constexpr unsigned int mmAZF0STREAM2_AZALIA_STREAM_INDEX__VI = 0x1784; +constexpr unsigned int mmAZF0STREAM3_AZALIA_STREAM_DATA__VI = 0x1787; +constexpr unsigned int mmAZF0STREAM3_AZALIA_STREAM_INDEX__VI = 0x1786; +constexpr unsigned int mmAZF0STREAM4_AZALIA_STREAM_DATA__VI = 0x1789; +constexpr unsigned int mmAZF0STREAM4_AZALIA_STREAM_INDEX__VI = 0x1788; +constexpr unsigned int mmAZF0STREAM5_AZALIA_STREAM_DATA__VI = 0x178B; +constexpr unsigned int mmAZF0STREAM5_AZALIA_STREAM_INDEX__VI = 0x178A; +constexpr unsigned int mmAZF0STREAM6_AZALIA_STREAM_DATA__VI = 0x178D; +constexpr unsigned int mmAZF0STREAM6_AZALIA_STREAM_INDEX__VI = 0x178C; +constexpr unsigned int mmAZF0STREAM7_AZALIA_STREAM_DATA__VI = 0x178F; +constexpr unsigned int mmAZF0STREAM7_AZALIA_STREAM_INDEX__VI = 0x178E; +constexpr unsigned int mmAZF0STREAM8_AZALIA_STREAM_DATA__VI = 0x59C1; +constexpr unsigned int mmAZF0STREAM8_AZALIA_STREAM_INDEX__VI = 0x59C0; +constexpr unsigned int mmAZF0STREAM9_AZALIA_STREAM_DATA__VI = 0x59C3; +constexpr unsigned int mmAZF0STREAM9_AZALIA_STREAM_INDEX__VI = 0x59C2; +constexpr unsigned int mmAZ_TEST_DEBUG_DATA__VI = 0x1820; +constexpr unsigned int mmAZ_TEST_DEBUG_INDEX__VI = 0x181F; +constexpr unsigned int mmBF_ANA_ISO_CNTL__VI = 0x14C7; +constexpr unsigned int mmBIF_ATOMIC_ERR_LOG__VI = 0x1512; +constexpr unsigned int mmBIF_BME_STATUS__VI = 0x1511; +constexpr unsigned int mmBIF_CLK_CTRL__VI = 0x14C5; +constexpr unsigned int mmBIF_DOORBELL_APER_EN__VI = 0x1501; +constexpr unsigned int mmBIF_DOORBELL_GBLAPER1_LOWER__VI = 0x14FC; +constexpr unsigned int mmBIF_DOORBELL_GBLAPER1_UPPER__VI = 0x14FD; +constexpr unsigned int mmBIF_DOORBELL_GBLAPER2_LOWER__VI = 0x14FE; +constexpr unsigned int mmBIF_DOORBELL_GBLAPER2_UPPER__VI = 0x14FF; +constexpr unsigned int mmBIF_GPUIOV_FB_TOTAL_FB_INFO__VI = 0x14D8; +constexpr unsigned int mmBIF_GPUIOV_RESET_NOTIFICATION__VI = 0x14D5; +constexpr unsigned int mmBIF_GPUIOV_VM_INIT_STATUS__VI = 0x14D6; +constexpr unsigned int mmBIF_IOV_FUNC_IDENTIFIER__VI = 0x1503; +constexpr unsigned int mmBIF_MM_INDACCESS_CNTL__VI = 0x1500; +constexpr unsigned int mmBIF_MST_TRANS_PENDING__VI = 0x14EA; +constexpr unsigned int mmBIF_RB_BASE__VI = 0x1531; +constexpr unsigned int mmBIF_RB_CNTL__VI = 0x1530; +constexpr unsigned int mmBIF_RB_RPTR__VI = 0x1532; +constexpr unsigned int mmBIF_RB_WPTR__VI = 0x1533; +constexpr unsigned int mmBIF_RB_WPTR_ADDR_HI__VI = 0x1534; +constexpr unsigned int mmBIF_RB_WPTR_ADDR_LO__VI = 0x1535; +constexpr unsigned int mmBIF_RFE_MST_BX_CMDSTATUS__VI = 0x1449; +constexpr unsigned int mmBIF_RFE_MST_SMBUS_CMDSTATUS__VI = 0x1448; +constexpr unsigned int mmBIF_RFE_WARMRST_CNTL__VI = 0x1459; +constexpr unsigned int mmBIF_RLC_INTR_CNTL__VI = 0x1510; +constexpr unsigned int mmBIF_SLV_TRANS_PENDING__VI = 0x14E9; +constexpr unsigned int mmBIF_SMU_DATA__VI = 0x143E; +constexpr unsigned int mmBIF_SMU_INDEX__VI = 0x143D; +constexpr unsigned int mmBIF_VDDGFX_FB_CMP__VI = 0x143C; +constexpr unsigned int mmBIF_VDDGFX_GFX0_LOWER__VI = 0x1428; +constexpr unsigned int mmBIF_VDDGFX_GFX0_UPPER__VI = 0x1429; +constexpr unsigned int mmBIF_VDDGFX_GFX1_LOWER__VI = 0x142A; +constexpr unsigned int mmBIF_VDDGFX_GFX1_UPPER__VI = 0x142B; +constexpr unsigned int mmBIF_VDDGFX_GFX2_LOWER__VI = 0x142C; +constexpr unsigned int mmBIF_VDDGFX_GFX2_UPPER__VI = 0x142D; +constexpr unsigned int mmBIF_VDDGFX_GFX3_LOWER__VI = 0x142E; +constexpr unsigned int mmBIF_VDDGFX_GFX3_UPPER__VI = 0x142F; +constexpr unsigned int mmBIF_VDDGFX_GFX4_LOWER__VI = 0x1430; +constexpr unsigned int mmBIF_VDDGFX_GFX4_UPPER__VI = 0x1431; +constexpr unsigned int mmBIF_VDDGFX_GFX5_LOWER__VI = 0x1432; +constexpr unsigned int mmBIF_VDDGFX_GFX5_UPPER__VI = 0x1433; +constexpr unsigned int mmBIF_VDDGFX_RSV1_LOWER__VI = 0x1434; +constexpr unsigned int mmBIF_VDDGFX_RSV1_UPPER__VI = 0x1435; +constexpr unsigned int mmBIF_VDDGFX_RSV2_LOWER__VI = 0x1436; +constexpr unsigned int mmBIF_VDDGFX_RSV2_UPPER__VI = 0x1437; +constexpr unsigned int mmBIF_VDDGFX_RSV3_LOWER__VI = 0x1438; +constexpr unsigned int mmBIF_VDDGFX_RSV3_UPPER__VI = 0x1439; +constexpr unsigned int mmBIF_VDDGFX_RSV4_LOWER__VI = 0x143A; +constexpr unsigned int mmBIF_VDDGFX_RSV4_UPPER__VI = 0x143B; +constexpr unsigned int mmBIF_VIRT_RESET_REQ__VI = 0x14D2; +constexpr unsigned int mmBLND0_BLND_CONTROL__VI = 0x1B6D; +constexpr unsigned int mmBLND0_BLND_CONTROL2__VI = 0x1B6F; +constexpr unsigned int mmBLND0_BLND_DEBUG__VI = 0x1B74; +constexpr unsigned int mmBLND0_BLND_REG_UPDATE_STATUS__VI = 0x1B77; +constexpr unsigned int mmBLND0_BLND_TEST_DEBUG_DATA__VI = 0x1B76; +constexpr unsigned int mmBLND0_BLND_TEST_DEBUG_INDEX__VI = 0x1B75; +constexpr unsigned int mmBLND0_BLND_UNDERFLOW_INTERRUPT__VI = 0x1B71; +constexpr unsigned int mmBLND0_BLND_UPDATE__VI = 0x1B70; +constexpr unsigned int mmBLND0_BLND_V_UPDATE_LOCK__VI = 0x1B73; +constexpr unsigned int mmBLND0_SM_CONTROL2__VI = 0x1B6E; +constexpr unsigned int mmBLND1_BLND_CONTROL__VI = 0x1D6D; +constexpr unsigned int mmBLND1_BLND_CONTROL2__VI = 0x1D6F; +constexpr unsigned int mmBLND1_BLND_DEBUG__VI = 0x1D74; +constexpr unsigned int mmBLND1_BLND_REG_UPDATE_STATUS__VI = 0x1D77; +constexpr unsigned int mmBLND1_BLND_TEST_DEBUG_DATA__VI = 0x1D76; +constexpr unsigned int mmBLND1_BLND_TEST_DEBUG_INDEX__VI = 0x1D75; +constexpr unsigned int mmBLND1_BLND_UNDERFLOW_INTERRUPT__VI = 0x1D71; +constexpr unsigned int mmBLND1_BLND_UPDATE__VI = 0x1D70; +constexpr unsigned int mmBLND1_BLND_V_UPDATE_LOCK__VI = 0x1D73; +constexpr unsigned int mmBLND1_SM_CONTROL2__VI = 0x1D6E; +constexpr unsigned int mmBLND2_BLND_CONTROL__VI = 0x1F6D; +constexpr unsigned int mmBLND2_BLND_CONTROL2__VI = 0x1F6F; +constexpr unsigned int mmBLND2_BLND_DEBUG__VI = 0x1F74; +constexpr unsigned int mmBLND2_BLND_REG_UPDATE_STATUS__VI = 0x1F77; +constexpr unsigned int mmBLND2_BLND_TEST_DEBUG_DATA__VI = 0x1F76; +constexpr unsigned int mmBLND2_BLND_TEST_DEBUG_INDEX__VI = 0x1F75; +constexpr unsigned int mmBLND2_BLND_UNDERFLOW_INTERRUPT__VI = 0x1F71; +constexpr unsigned int mmBLND2_BLND_UPDATE__VI = 0x1F70; +constexpr unsigned int mmBLND2_BLND_V_UPDATE_LOCK__VI = 0x1F73; +constexpr unsigned int mmBLND2_SM_CONTROL2__VI = 0x1F6E; +constexpr unsigned int mmBLND3_BLND_CONTROL__VI = 0x416D; +constexpr unsigned int mmBLND3_BLND_CONTROL2__VI = 0x416F; +constexpr unsigned int mmBLND3_BLND_DEBUG__VI = 0x4174; +constexpr unsigned int mmBLND3_BLND_REG_UPDATE_STATUS__VI = 0x4177; +constexpr unsigned int mmBLND3_BLND_TEST_DEBUG_DATA__VI = 0x4176; +constexpr unsigned int mmBLND3_BLND_TEST_DEBUG_INDEX__VI = 0x4175; +constexpr unsigned int mmBLND3_BLND_UNDERFLOW_INTERRUPT__VI = 0x4171; +constexpr unsigned int mmBLND3_BLND_UPDATE__VI = 0x4170; +constexpr unsigned int mmBLND3_BLND_V_UPDATE_LOCK__VI = 0x4173; +constexpr unsigned int mmBLND3_SM_CONTROL2__VI = 0x416E; +constexpr unsigned int mmBLND4_BLND_CONTROL__VI = 0x436D; +constexpr unsigned int mmBLND4_BLND_CONTROL2__VI = 0x436F; +constexpr unsigned int mmBLND4_BLND_DEBUG__VI = 0x4374; +constexpr unsigned int mmBLND4_BLND_REG_UPDATE_STATUS__VI = 0x4377; +constexpr unsigned int mmBLND4_BLND_TEST_DEBUG_DATA__VI = 0x4376; +constexpr unsigned int mmBLND4_BLND_TEST_DEBUG_INDEX__VI = 0x4375; +constexpr unsigned int mmBLND4_BLND_UNDERFLOW_INTERRUPT__VI = 0x4371; +constexpr unsigned int mmBLND4_BLND_UPDATE__VI = 0x4370; +constexpr unsigned int mmBLND4_BLND_V_UPDATE_LOCK__VI = 0x4373; +constexpr unsigned int mmBLND4_SM_CONTROL2__VI = 0x436E; +constexpr unsigned int mmBLND5_BLND_CONTROL__VI = 0x456D; +constexpr unsigned int mmBLND5_BLND_CONTROL2__VI = 0x456F; +constexpr unsigned int mmBLND5_BLND_DEBUG__VI = 0x4574; +constexpr unsigned int mmBLND5_BLND_REG_UPDATE_STATUS__VI = 0x4577; +constexpr unsigned int mmBLND5_BLND_TEST_DEBUG_DATA__VI = 0x4576; +constexpr unsigned int mmBLND5_BLND_TEST_DEBUG_INDEX__VI = 0x4575; +constexpr unsigned int mmBLND5_BLND_UNDERFLOW_INTERRUPT__VI = 0x4571; +constexpr unsigned int mmBLND5_BLND_UPDATE__VI = 0x4570; +constexpr unsigned int mmBLND5_BLND_V_UPDATE_LOCK__VI = 0x4573; +constexpr unsigned int mmBLND5_SM_CONTROL2__VI = 0x456E; +constexpr unsigned int mmBLND6_BLND_CONTROL__VI = 0x476D; +constexpr unsigned int mmBLND6_BLND_CONTROL2__VI = 0x476F; +constexpr unsigned int mmBLND6_BLND_DEBUG__VI = 0x4774; +constexpr unsigned int mmBLND6_BLND_REG_UPDATE_STATUS__VI = 0x4777; +constexpr unsigned int mmBLND6_BLND_TEST_DEBUG_DATA__VI = 0x4776; +constexpr unsigned int mmBLND6_BLND_TEST_DEBUG_INDEX__VI = 0x4775; +constexpr unsigned int mmBLND6_BLND_UNDERFLOW_INTERRUPT__VI = 0x4771; +constexpr unsigned int mmBLND6_BLND_UPDATE__VI = 0x4770; +constexpr unsigned int mmBLND6_BLND_V_UPDATE_LOCK__VI = 0x4773; +constexpr unsigned int mmBLND6_SM_CONTROL2__VI = 0x476E; +constexpr unsigned int mmBLND_CONTROL__VI = 0x1B6D; +constexpr unsigned int mmBLND_CONTROL2__VI = 0x1B6F; +constexpr unsigned int mmBLND_DEBUG__VI = 0x1B74; +constexpr unsigned int mmBLND_REG_UPDATE_STATUS__VI = 0x1B77; +constexpr unsigned int mmBLND_TEST_DEBUG_DATA__VI = 0x1B76; +constexpr unsigned int mmBLND_TEST_DEBUG_INDEX__VI = 0x1B75; +constexpr unsigned int mmBLND_UNDERFLOW_INTERRUPT__VI = 0x1B71; +constexpr unsigned int mmBLND_UPDATE__VI = 0x1B70; +constexpr unsigned int mmBLND_V_UPDATE_LOCK__VI = 0x1B73; +constexpr unsigned int mmBL_PWM_CNTL__VI = 0x4820; +constexpr unsigned int mmBL_PWM_CNTL2__VI = 0x4821; +constexpr unsigned int mmBL_PWM_GRP1_REG_LOCK__VI = 0x4823; +constexpr unsigned int mmBL_PWM_PERIOD_CNTL__VI = 0x4822; +constexpr unsigned int mmBPHYC_DAC_AUTO_CALIB_CONTROL__VI = 0x48BA; +constexpr unsigned int mmBPHYC_DAC_MACRO_CNTL__VI = 0x48B9; +constexpr unsigned int mmBPHYC_PLL0_DISPPLL_BG_CNTL__VI = 0x171E; +constexpr unsigned int mmBPHYC_PLL0_PLL_ANALOG__VI = 0x1708; +constexpr unsigned int mmBPHYC_PLL0_PLL_ANALOG_CNTL__VI = 0x1711; +constexpr unsigned int mmBPHYC_PLL0_PLL_CNTL__VI = 0x1707; +constexpr unsigned int mmBPHYC_PLL0_PLL_DEBUG_CNTL__VI = 0x170B; +constexpr unsigned int mmBPHYC_PLL0_PLL_DS_CNTL__VI = 0x1705; +constexpr unsigned int mmBPHYC_PLL0_PLL_FB_DIV__VI = 0x1701; +constexpr unsigned int mmBPHYC_PLL0_PLL_IDCLK_CNTL__VI = 0x1706; +constexpr unsigned int mmBPHYC_PLL0_PLL_POST_DIV__VI = 0x1702; +constexpr unsigned int mmBPHYC_PLL0_PLL_REF_DIV__VI = 0x1700; +constexpr unsigned int mmBPHYC_PLL0_PLL_SS_AMOUNT_DSFRAC__VI = 0x1703; +constexpr unsigned int mmBPHYC_PLL0_PLL_SS_CNTL__VI = 0x1704; +constexpr unsigned int mmBPHYC_PLL0_PLL_UNLOCK_DETECT_CNTL__VI = 0x170A; +constexpr unsigned int mmBPHYC_PLL0_PLL_UPDATE_CNTL__VI = 0x170D; +constexpr unsigned int mmBPHYC_PLL0_PLL_UPDATE_LOCK__VI = 0x170C; +constexpr unsigned int mmBPHYC_PLL0_PLL_VREG_CNTL__VI = 0x1709; +constexpr unsigned int mmBPHYC_PLL0_PLL_XOR_LOCK__VI = 0x1710; +constexpr unsigned int mmBPHYC_PLL0_PPLL_DEBUG_MUX_CNTL__VI = 0x1721; +constexpr unsigned int mmBPHYC_PLL0_PPLL_DIV_UPDATE_DEBUG__VI = 0x171F; +constexpr unsigned int mmBPHYC_PLL0_PPLL_SPARE0__VI = 0x1722; +constexpr unsigned int mmBPHYC_PLL0_PPLL_SPARE1__VI = 0x1723; +constexpr unsigned int mmBPHYC_PLL0_PPLL_STATUS_DEBUG__VI = 0x1720; +constexpr unsigned int mmBPHYC_PLL0_VGA25_PPLL_ANALOG__VI = 0x171B; +constexpr unsigned int mmBPHYC_PLL0_VGA25_PPLL_FB_DIV__VI = 0x1715; +constexpr unsigned int mmBPHYC_PLL0_VGA25_PPLL_POST_DIV__VI = 0x1718; +constexpr unsigned int mmBPHYC_PLL0_VGA25_PPLL_REF_DIV__VI = 0x1712; +constexpr unsigned int mmBPHYC_PLL0_VGA28_PPLL_ANALOG__VI = 0x171C; +constexpr unsigned int mmBPHYC_PLL0_VGA28_PPLL_FB_DIV__VI = 0x1716; +constexpr unsigned int mmBPHYC_PLL0_VGA28_PPLL_POST_DIV__VI = 0x1719; +constexpr unsigned int mmBPHYC_PLL0_VGA28_PPLL_REF_DIV__VI = 0x1713; +constexpr unsigned int mmBPHYC_PLL0_VGA41_PPLL_ANALOG__VI = 0x171D; +constexpr unsigned int mmBPHYC_PLL0_VGA41_PPLL_FB_DIV__VI = 0x1717; +constexpr unsigned int mmBPHYC_PLL0_VGA41_PPLL_POST_DIV__VI = 0x171A; +constexpr unsigned int mmBPHYC_PLL0_VGA41_PPLL_REF_DIV__VI = 0x1714; +constexpr unsigned int mmBPHYC_PLL1_DISPPLL_BG_CNTL__VI = 0x1748; +constexpr unsigned int mmBPHYC_PLL1_PLL_ANALOG__VI = 0x1732; +constexpr unsigned int mmBPHYC_PLL1_PLL_ANALOG_CNTL__VI = 0x173B; +constexpr unsigned int mmBPHYC_PLL1_PLL_CNTL__VI = 0x1731; +constexpr unsigned int mmBPHYC_PLL1_PLL_DEBUG_CNTL__VI = 0x1735; +constexpr unsigned int mmBPHYC_PLL1_PLL_DS_CNTL__VI = 0x172F; +constexpr unsigned int mmBPHYC_PLL1_PLL_FB_DIV__VI = 0x172B; +constexpr unsigned int mmBPHYC_PLL1_PLL_IDCLK_CNTL__VI = 0x1730; +constexpr unsigned int mmBPHYC_PLL1_PLL_POST_DIV__VI = 0x172C; +constexpr unsigned int mmBPHYC_PLL1_PLL_REF_DIV__VI = 0x172A; +constexpr unsigned int mmBPHYC_PLL1_PLL_SS_AMOUNT_DSFRAC__VI = 0x172D; +constexpr unsigned int mmBPHYC_PLL1_PLL_SS_CNTL__VI = 0x172E; +constexpr unsigned int mmBPHYC_PLL1_PLL_UNLOCK_DETECT_CNTL__VI = 0x1734; +constexpr unsigned int mmBPHYC_PLL1_PLL_UPDATE_CNTL__VI = 0x1737; +constexpr unsigned int mmBPHYC_PLL1_PLL_UPDATE_LOCK__VI = 0x1736; +constexpr unsigned int mmBPHYC_PLL1_PLL_VREG_CNTL__VI = 0x1733; +constexpr unsigned int mmBPHYC_PLL1_PLL_XOR_LOCK__VI = 0x173A; +constexpr unsigned int mmBPHYC_PLL1_PPLL_DEBUG_MUX_CNTL__VI = 0x174B; +constexpr unsigned int mmBPHYC_PLL1_PPLL_DIV_UPDATE_DEBUG__VI = 0x1749; +constexpr unsigned int mmBPHYC_PLL1_PPLL_SPARE0__VI = 0x174C; +constexpr unsigned int mmBPHYC_PLL1_PPLL_SPARE1__VI = 0x174D; +constexpr unsigned int mmBPHYC_PLL1_PPLL_STATUS_DEBUG__VI = 0x174A; +constexpr unsigned int mmBPHYC_PLL1_VGA25_PPLL_ANALOG__VI = 0x1745; +constexpr unsigned int mmBPHYC_PLL1_VGA25_PPLL_FB_DIV__VI = 0x173F; +constexpr unsigned int mmBPHYC_PLL1_VGA25_PPLL_POST_DIV__VI = 0x1742; +constexpr unsigned int mmBPHYC_PLL1_VGA25_PPLL_REF_DIV__VI = 0x173C; +constexpr unsigned int mmBPHYC_PLL1_VGA28_PPLL_ANALOG__VI = 0x1746; +constexpr unsigned int mmBPHYC_PLL1_VGA28_PPLL_FB_DIV__VI = 0x1740; +constexpr unsigned int mmBPHYC_PLL1_VGA28_PPLL_POST_DIV__VI = 0x1743; +constexpr unsigned int mmBPHYC_PLL1_VGA28_PPLL_REF_DIV__VI = 0x173D; +constexpr unsigned int mmBPHYC_PLL1_VGA41_PPLL_ANALOG__VI = 0x1747; +constexpr unsigned int mmBPHYC_PLL1_VGA41_PPLL_FB_DIV__VI = 0x1741; +constexpr unsigned int mmBPHYC_PLL1_VGA41_PPLL_POST_DIV__VI = 0x1744; +constexpr unsigned int mmBPHYC_PLL1_VGA41_PPLL_REF_DIV__VI = 0x173E; +constexpr unsigned int mmBPHYC_PLL2_DISPPLL_BG_CNTL__VI = 0x1772; +constexpr unsigned int mmBPHYC_PLL2_PLL_ANALOG__VI = 0x175C; +constexpr unsigned int mmBPHYC_PLL2_PLL_ANALOG_CNTL__VI = 0x1765; +constexpr unsigned int mmBPHYC_PLL2_PLL_CNTL__VI = 0x175B; +constexpr unsigned int mmBPHYC_PLL2_PLL_DEBUG_CNTL__VI = 0x175F; +constexpr unsigned int mmBPHYC_PLL2_PLL_DS_CNTL__VI = 0x1759; +constexpr unsigned int mmBPHYC_PLL2_PLL_FB_DIV__VI = 0x1755; +constexpr unsigned int mmBPHYC_PLL2_PLL_IDCLK_CNTL__VI = 0x175A; +constexpr unsigned int mmBPHYC_PLL2_PLL_POST_DIV__VI = 0x1756; +constexpr unsigned int mmBPHYC_PLL2_PLL_REF_DIV__VI = 0x1754; +constexpr unsigned int mmBPHYC_PLL2_PLL_SS_AMOUNT_DSFRAC__VI = 0x1757; +constexpr unsigned int mmBPHYC_PLL2_PLL_SS_CNTL__VI = 0x1758; +constexpr unsigned int mmBPHYC_PLL2_PLL_UNLOCK_DETECT_CNTL__VI = 0x175E; +constexpr unsigned int mmBPHYC_PLL2_PLL_UPDATE_CNTL__VI = 0x1761; +constexpr unsigned int mmBPHYC_PLL2_PLL_UPDATE_LOCK__VI = 0x1760; +constexpr unsigned int mmBPHYC_PLL2_PLL_VREG_CNTL__VI = 0x175D; +constexpr unsigned int mmBPHYC_PLL2_PLL_XOR_LOCK__VI = 0x1764; +constexpr unsigned int mmBPHYC_PLL2_PPLL_DEBUG_MUX_CNTL__VI = 0x1775; +constexpr unsigned int mmBPHYC_PLL2_PPLL_DIV_UPDATE_DEBUG__VI = 0x1773; +constexpr unsigned int mmBPHYC_PLL2_PPLL_SPARE0__VI = 0x1776; +constexpr unsigned int mmBPHYC_PLL2_PPLL_SPARE1__VI = 0x1777; +constexpr unsigned int mmBPHYC_PLL2_PPLL_STATUS_DEBUG__VI = 0x1774; +constexpr unsigned int mmBPHYC_PLL2_VGA25_PPLL_ANALOG__VI = 0x176F; +constexpr unsigned int mmBPHYC_PLL2_VGA25_PPLL_FB_DIV__VI = 0x1769; +constexpr unsigned int mmBPHYC_PLL2_VGA25_PPLL_POST_DIV__VI = 0x176C; +constexpr unsigned int mmBPHYC_PLL2_VGA25_PPLL_REF_DIV__VI = 0x1766; +constexpr unsigned int mmBPHYC_PLL2_VGA28_PPLL_ANALOG__VI = 0x1770; +constexpr unsigned int mmBPHYC_PLL2_VGA28_PPLL_FB_DIV__VI = 0x176A; +constexpr unsigned int mmBPHYC_PLL2_VGA28_PPLL_POST_DIV__VI = 0x176D; +constexpr unsigned int mmBPHYC_PLL2_VGA28_PPLL_REF_DIV__VI = 0x1767; +constexpr unsigned int mmBPHYC_PLL2_VGA41_PPLL_ANALOG__VI = 0x1771; +constexpr unsigned int mmBPHYC_PLL2_VGA41_PPLL_FB_DIV__VI = 0x176B; +constexpr unsigned int mmBPHYC_PLL2_VGA41_PPLL_POST_DIV__VI = 0x176E; +constexpr unsigned int mmBPHYC_PLL2_VGA41_PPLL_REF_DIV__VI = 0x1768; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_ANG_BIST_CNTL__VI = 0x48CC; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x48CA; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_DEBUG__VI = 0x48D6; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_PLL_CONTROL1__VI = 0x48C6; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_PLL_CONTROL2__VI = 0x48C7; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_PLL_FBDIV__VI = 0x48C5; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_PLL_SS_CNTL__VI = 0x48C9; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x48C8; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_POWER_CONTROL__VI = 0x48C4; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_REG_TEST_OUTPUT__VI = 0x48CB; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_REG_TEST_OUTPUT2__VI = 0x48CD; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_TPG_CONTROL__VI = 0x48D4; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_TPG_SEED__VI = 0x48D5; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL1__VI = 0x48C0; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL2__VI = 0x48C1; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL3__VI = 0x48C2; +constexpr unsigned int mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL4__VI = 0x48C3; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_ANG_BIST_CNTL__VI = 0x48EC; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x48EA; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_DEBUG__VI = 0x48F6; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_PLL_CONTROL1__VI = 0x48E6; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_PLL_CONTROL2__VI = 0x48E7; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_PLL_FBDIV__VI = 0x48E5; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_PLL_SS_CNTL__VI = 0x48E9; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x48E8; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_POWER_CONTROL__VI = 0x48E4; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_REG_TEST_OUTPUT__VI = 0x48EB; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_REG_TEST_OUTPUT2__VI = 0x48ED; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_TPG_CONTROL__VI = 0x48F4; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_TPG_SEED__VI = 0x48F5; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_TX_CONTROL1__VI = 0x48E0; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_TX_CONTROL2__VI = 0x48E1; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_TX_CONTROL3__VI = 0x48E2; +constexpr unsigned int mmBPHYC_UNIPHY1_UNIPHY_TX_CONTROL4__VI = 0x48E3; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_ANG_BIST_CNTL__VI = 0x490C; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x490A; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_DEBUG__VI = 0x4916; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_PLL_CONTROL1__VI = 0x4906; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_PLL_CONTROL2__VI = 0x4907; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_PLL_FBDIV__VI = 0x4905; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_PLL_SS_CNTL__VI = 0x4909; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x4908; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_POWER_CONTROL__VI = 0x4904; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_REG_TEST_OUTPUT__VI = 0x490B; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_REG_TEST_OUTPUT2__VI = 0x490D; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_TPG_CONTROL__VI = 0x4914; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_TPG_SEED__VI = 0x4915; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_TX_CONTROL1__VI = 0x4900; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_TX_CONTROL2__VI = 0x4901; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_TX_CONTROL3__VI = 0x4902; +constexpr unsigned int mmBPHYC_UNIPHY2_UNIPHY_TX_CONTROL4__VI = 0x4903; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_ANG_BIST_CNTL__VI = 0x492C; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x492A; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_DEBUG__VI = 0x4936; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_PLL_CONTROL1__VI = 0x4926; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_PLL_CONTROL2__VI = 0x4927; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_PLL_FBDIV__VI = 0x4925; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_PLL_SS_CNTL__VI = 0x4929; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x4928; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_POWER_CONTROL__VI = 0x4924; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_REG_TEST_OUTPUT__VI = 0x492B; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_REG_TEST_OUTPUT2__VI = 0x492D; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_TPG_CONTROL__VI = 0x4934; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_TPG_SEED__VI = 0x4935; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_TX_CONTROL1__VI = 0x4920; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_TX_CONTROL2__VI = 0x4921; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_TX_CONTROL3__VI = 0x4922; +constexpr unsigned int mmBPHYC_UNIPHY3_UNIPHY_TX_CONTROL4__VI = 0x4923; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_ANG_BIST_CNTL__VI = 0x494C; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x494A; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_DEBUG__VI = 0x4956; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_PLL_CONTROL1__VI = 0x4946; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_PLL_CONTROL2__VI = 0x4947; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_PLL_FBDIV__VI = 0x4945; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_PLL_SS_CNTL__VI = 0x4949; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x4948; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_POWER_CONTROL__VI = 0x4944; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_REG_TEST_OUTPUT__VI = 0x494B; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_REG_TEST_OUTPUT2__VI = 0x494D; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_TPG_CONTROL__VI = 0x4954; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_TPG_SEED__VI = 0x4955; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_TX_CONTROL1__VI = 0x4940; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_TX_CONTROL2__VI = 0x4941; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_TX_CONTROL3__VI = 0x4942; +constexpr unsigned int mmBPHYC_UNIPHY4_UNIPHY_TX_CONTROL4__VI = 0x4943; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_ANG_BIST_CNTL__VI = 0x496C; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x496A; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_DEBUG__VI = 0x4976; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_PLL_CONTROL1__VI = 0x4966; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_PLL_CONTROL2__VI = 0x4967; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_PLL_FBDIV__VI = 0x4965; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_PLL_SS_CNTL__VI = 0x4969; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x4968; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_POWER_CONTROL__VI = 0x4964; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_REG_TEST_OUTPUT__VI = 0x496B; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_REG_TEST_OUTPUT2__VI = 0x496D; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_TPG_CONTROL__VI = 0x4974; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_TPG_SEED__VI = 0x4975; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_TX_CONTROL1__VI = 0x4960; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_TX_CONTROL2__VI = 0x4961; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_TX_CONTROL3__VI = 0x4962; +constexpr unsigned int mmBPHYC_UNIPHY5_UNIPHY_TX_CONTROL4__VI = 0x4963; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_ANG_BIST_CNTL__VI = 0x498C; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_DATA_SYNCHRONIZATION__VI = 0x498A; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_DEBUG__VI = 0x4996; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_PLL_CONTROL1__VI = 0x4986; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_PLL_CONTROL2__VI = 0x4987; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_PLL_FBDIV__VI = 0x4985; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_PLL_SS_CNTL__VI = 0x4989; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_PLL_SS_STEP_SIZE__VI = 0x4988; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_POWER_CONTROL__VI = 0x4984; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_REG_TEST_OUTPUT__VI = 0x498B; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_REG_TEST_OUTPUT2__VI = 0x498D; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_TPG_CONTROL__VI = 0x4994; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_TPG_SEED__VI = 0x4995; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_TX_CONTROL1__VI = 0x4980; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_TX_CONTROL2__VI = 0x4981; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_TX_CONTROL3__VI = 0x4982; +constexpr unsigned int mmBPHYC_UNIPHY6_UNIPHY_TX_CONTROL4__VI = 0x4983; +constexpr unsigned int mmBX_RESET_CNTL__VI = 0x1518; +constexpr unsigned int mmCB_COLOR0_DCC_BASE__VI = 0xA325; +constexpr unsigned int mmCB_COLOR0_DCC_CONTROL__VI = 0xA31E; +constexpr unsigned int mmCB_COLOR1_DCC_BASE__VI = 0xA334; +constexpr unsigned int mmCB_COLOR1_DCC_CONTROL__VI = 0xA32D; +constexpr unsigned int mmCB_COLOR2_DCC_BASE__VI = 0xA343; +constexpr unsigned int mmCB_COLOR2_DCC_CONTROL__VI = 0xA33C; +constexpr unsigned int mmCB_COLOR3_DCC_BASE__VI = 0xA352; +constexpr unsigned int mmCB_COLOR3_DCC_CONTROL__VI = 0xA34B; +constexpr unsigned int mmCB_COLOR4_DCC_BASE__VI = 0xA361; +constexpr unsigned int mmCB_COLOR4_DCC_CONTROL__VI = 0xA35A; +constexpr unsigned int mmCB_COLOR5_DCC_BASE__VI = 0xA370; +constexpr unsigned int mmCB_COLOR5_DCC_CONTROL__VI = 0xA369; +constexpr unsigned int mmCB_COLOR6_DCC_BASE__VI = 0xA37F; +constexpr unsigned int mmCB_COLOR6_DCC_CONTROL__VI = 0xA378; +constexpr unsigned int mmCB_COLOR7_DCC_BASE__VI = 0xA38E; +constexpr unsigned int mmCB_COLOR7_DCC_CONTROL__VI = 0xA387; +constexpr unsigned int mmCB_DCC_CONFIG__VI = 0x2687; +constexpr unsigned int mmCB_DCC_CONTROL__VI = 0xA109; +constexpr unsigned int mmCB_DEBUG_BUS_19__VI = 0x26AB; +constexpr unsigned int mmCB_DEBUG_BUS_20__VI = 0x26AC; +constexpr unsigned int mmCB_DEBUG_BUS_21__VI = 0x26AD; +constexpr unsigned int mmCB_DEBUG_BUS_22__VI = 0x26AE; +constexpr unsigned int mmCC_DC_PIPE_DIS__VI = 0x0312; +constexpr unsigned int mmCC_GC_SHADER_RATE_CONFIG__VI = 0x2312; +constexpr unsigned int mmCC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY__VI = 0x1835; +constexpr unsigned int mmCC_RCU_DC_AUDIO_PORT_CONNECTIVITY__VI = 0x1834; +constexpr unsigned int mmCG_FPS_CNT__VI = 0x01B6; +constexpr unsigned int mmCLKREQB_PERF_COUNTER__VI = 0x1522; +constexpr unsigned int mmCNV_CSC_C11_C12__VI = 0x5E20; +constexpr unsigned int mmCNV_CSC_C13_C14__VI = 0x5E21; +constexpr unsigned int mmCNV_CSC_C21_C22__VI = 0x5E22; +constexpr unsigned int mmCNV_CSC_C23_C24__VI = 0x5E23; +constexpr unsigned int mmCNV_CSC_C31_C32__VI = 0x5E24; +constexpr unsigned int mmCNV_CSC_C33_C34__VI = 0x5E25; +constexpr unsigned int mmCNV_CSC_CLAMP_B__VI = 0x5E2B; +constexpr unsigned int mmCNV_CSC_CLAMP_G__VI = 0x5E2A; +constexpr unsigned int mmCNV_CSC_CLAMP_R__VI = 0x5E29; +constexpr unsigned int mmCNV_CSC_CONTROL__VI = 0x5E1F; +constexpr unsigned int mmCNV_CSC_ROUND_OFFSET_B__VI = 0x5E28; +constexpr unsigned int mmCNV_CSC_ROUND_OFFSET_G__VI = 0x5E27; +constexpr unsigned int mmCNV_CSC_ROUND_OFFSET_R__VI = 0x5E26; +constexpr unsigned int mmCNV_INPUT_SELECT__VI = 0x5E33; +constexpr unsigned int mmCNV_MODE__VI = 0x5E1A; +constexpr unsigned int mmCNV_SOURCE_SIZE__VI = 0x5E1E; +constexpr unsigned int mmCNV_TEST_CNTL__VI = 0x5E2C; +constexpr unsigned int mmCNV_TEST_CRC_BLUE__VI = 0x5E2F; +constexpr unsigned int mmCNV_TEST_CRC_GREEN__VI = 0x5E2E; +constexpr unsigned int mmCNV_TEST_CRC_RED__VI = 0x5E2D; +constexpr unsigned int mmCNV_TEST_DEBUG_DATA__VI = 0x5E35; +constexpr unsigned int mmCNV_TEST_DEBUG_INDEX__VI = 0x5E34; +constexpr unsigned int mmCNV_UPDATE__VI = 0x5E1D; +constexpr unsigned int mmCNV_WINDOW_SIZE__VI = 0x5E1C; +constexpr unsigned int mmCNV_WINDOW_START__VI = 0x5E1B; +constexpr unsigned int mmCOL_MAN_DEBUG_CONTROL__VI = 0x46E6; +constexpr unsigned int mmCOL_MAN_FP_CONVERTED_FIELD__VI = 0x46C7; +constexpr unsigned int mmCOL_MAN_INPUT_CSC_CONTROL__VI = 0x46A5; +constexpr unsigned int mmCOL_MAN_OUTPUT_CSC_CONTROL__VI = 0x46B6; +constexpr unsigned int mmCOL_MAN_TEST_DEBUG_DATA__VI = 0x46E5; +constexpr unsigned int mmCOL_MAN_TEST_DEBUG_INDEX__VI = 0x46E4; +constexpr unsigned int mmCOL_MAN_UPDATE__VI = 0x46A4; +constexpr unsigned int mmCOMM_MATRIXA_TRANS_C11_C12__VI = 0x1A43; +constexpr unsigned int mmCOMM_MATRIXA_TRANS_C13_C14__VI = 0x1A44; +constexpr unsigned int mmCOMM_MATRIXA_TRANS_C21_C22__VI = 0x1A45; +constexpr unsigned int mmCOMM_MATRIXA_TRANS_C23_C24__VI = 0x1A46; +constexpr unsigned int mmCOMM_MATRIXA_TRANS_C31_C32__VI = 0x1A47; +constexpr unsigned int mmCOMM_MATRIXA_TRANS_C33_C34__VI = 0x1A48; +constexpr unsigned int mmCOMM_MATRIXB_TRANS_C11_C12__VI = 0x1A49; +constexpr unsigned int mmCOMM_MATRIXB_TRANS_C13_C14__VI = 0x1A4A; +constexpr unsigned int mmCOMM_MATRIXB_TRANS_C21_C22__VI = 0x1A4B; +constexpr unsigned int mmCOMM_MATRIXB_TRANS_C23_C24__VI = 0x1A4C; +constexpr unsigned int mmCOMM_MATRIXB_TRANS_C31_C32__VI = 0x1A4D; +constexpr unsigned int mmCOMM_MATRIXB_TRANS_C33_C34__VI = 0x1A4E; +constexpr unsigned int mmCOMPUTE_DISPATCH_ID__VI = 0x2E20; +constexpr unsigned int mmCOMPUTE_NOWHERE__VI = 0x2E7F; +constexpr unsigned int mmCOMPUTE_RELAUNCH__VI = 0x2E22; +constexpr unsigned int mmCOMPUTE_THREADGROUP_ID__VI = 0x2E21; +constexpr unsigned int mmCOMPUTE_WAVE_RESTORE_ADDR_HI__VI = 0x2E24; +constexpr unsigned int mmCOMPUTE_WAVE_RESTORE_ADDR_LO__VI = 0x2E23; +constexpr unsigned int mmCOMPUTE_WAVE_RESTORE_CONTROL__VI = 0x2E25; +constexpr unsigned int mmCONFIG_RESERVED__VI = 0x1502; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED0__VI = 0x5FD0; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED1__VI = 0x5FD1; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED10__VI = 0x5FDA; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED11__VI = 0x5FDB; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED2__VI = 0x5FD2; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED3__VI = 0x5FD3; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED4__VI = 0x5FD4; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED5__VI = 0x5FD5; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED6__VI = 0x5FD6; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED7__VI = 0x5FD7; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED8__VI = 0x5FD8; +constexpr unsigned int mmCPLL_MACRO_CNTL_RESERVED9__VI = 0x5FD9; +constexpr unsigned int mmCPM_CONTROL__VI = 0x14B8; +constexpr unsigned int mmCP_CE_COMPLETION_STATUS__VI = 0xC0ED; +constexpr unsigned int mmCP_CE_METADATA_BASE_ADDR__VI = 0xC0F2; +constexpr unsigned int mmCP_CE_METADATA_BASE_ADDR_HI__VI = 0xC0F3; +constexpr unsigned int mmCP_CE_RB_OFFSET__VI = 0xC09B; +constexpr unsigned int mmCP_CE_UCODE_ADDR__SI__CI = 0x305A; +constexpr unsigned int mmCP_CE_UCODE_ADDR__VI = 0xF818; +constexpr unsigned int mmCP_CE_UCODE_DATA__SI__CI = 0x305B; +constexpr unsigned int mmCP_CE_UCODE_DATA__VI = 0xF819; +constexpr unsigned int mmCP_CONFIG__VI = 0x0F96; +constexpr unsigned int mmCP_CPC_IC_BASE_CNTL__VI = 0x30BB; +constexpr unsigned int mmCP_CPC_IC_BASE_HI__VI = 0x30BA; +constexpr unsigned int mmCP_CPC_IC_BASE_LO__VI = 0x30B9; +constexpr unsigned int mmCP_CPC_IC_OP_CNTL__VI = 0x30BC; +constexpr unsigned int mmCP_CPC_MGCG_SYNC_CNTL__VI = 0x3036; +constexpr unsigned int mmCP_DFY_CMD__VI = 0x3034; +constexpr unsigned int mmCP_DISPATCH_INDR_ADDR__VI = 0xC0F6; +constexpr unsigned int mmCP_DISPATCH_INDR_ADDR_HI__VI = 0xC0F7; +constexpr unsigned int mmCP_DRAW_INDX_INDR_ADDR__VI = 0xC0F4; +constexpr unsigned int mmCP_DRAW_INDX_INDR_ADDR_HI__VI = 0xC0F5; +constexpr unsigned int mmCP_DRAW_OBJECT__VI = 0xD810; +constexpr unsigned int mmCP_DRAW_OBJECT_COUNTER__VI = 0xD811; +constexpr unsigned int mmCP_DRAW_WINDOW_CNTL__VI = 0xD815; +constexpr unsigned int mmCP_DRAW_WINDOW_HI__VI = 0xD813; +constexpr unsigned int mmCP_DRAW_WINDOW_LO__VI = 0xD814; +constexpr unsigned int mmCP_DRAW_WINDOW_MASK_HI__VI = 0xD812; +constexpr unsigned int mmCP_EOP_DONE_CNTX_ID__VI = 0xC0D7; +constexpr unsigned int mmCP_GDS_BKUP_ADDR__VI = 0xC0FB; +constexpr unsigned int mmCP_GDS_BKUP_ADDR_HI__VI = 0xC0FC; +constexpr unsigned int mmCP_HPD_STATUS0__VI = 0x3241; +constexpr unsigned int mmCP_HQD_CNTL_STACK_OFFSET__VI = 0x3273; +constexpr unsigned int mmCP_HQD_CNTL_STACK_SIZE__VI = 0x3274; +constexpr unsigned int mmCP_HQD_CTX_SAVE_BASE_ADDR_HI__VI = 0x3271; +constexpr unsigned int mmCP_HQD_CTX_SAVE_BASE_ADDR_LO__VI = 0x3270; +constexpr unsigned int mmCP_HQD_CTX_SAVE_CONTROL__VI = 0x3272; +constexpr unsigned int mmCP_HQD_CTX_SAVE_SIZE__VI = 0x3276; +constexpr unsigned int mmCP_HQD_EOP_BASE_ADDR__VI = 0x326A; +constexpr unsigned int mmCP_HQD_EOP_BASE_ADDR_HI__VI = 0x326B; +constexpr unsigned int mmCP_HQD_EOP_CONTROL__VI = 0x326C; +constexpr unsigned int mmCP_HQD_EOP_DONES__VI = 0x327A; +constexpr unsigned int mmCP_HQD_EOP_EVENTS__VI = 0x326F; +constexpr unsigned int mmCP_HQD_EOP_RPTR__VI = 0x326D; +constexpr unsigned int mmCP_HQD_EOP_WPTR__VI = 0x326E; +constexpr unsigned int mmCP_HQD_EOP_WPTR_MEM__VI = 0x3279; +constexpr unsigned int mmCP_HQD_ERROR__VI = 0x3278; +constexpr unsigned int mmCP_HQD_GDS_RESOURCE_STATE__VI = 0x3277; +constexpr unsigned int mmCP_HQD_HQ_CONTROL0__VI = 0x3266; +constexpr unsigned int mmCP_HQD_HQ_CONTROL1__VI = 0x3269; +constexpr unsigned int mmCP_HQD_HQ_STATUS0__VI = 0x3265; +constexpr unsigned int mmCP_HQD_HQ_STATUS1__VI = 0x3268; +constexpr unsigned int mmCP_HQD_OFFLOAD__VI = 0x325E; +constexpr unsigned int mmCP_HQD_WG_STATE_OFFSET__VI = 0x3275; +constexpr unsigned int mmCP_INDEX_BASE_ADDR__VI = 0xC0F8; +constexpr unsigned int mmCP_INDEX_BASE_ADDR_HI__VI = 0xC0F9; +constexpr unsigned int mmCP_INDEX_TYPE__VI = 0xC0FA; +constexpr unsigned int mmCP_MEC1_F32_INT_DIS__VI = 0x30BD; +constexpr unsigned int mmCP_MEC2_F32_INT_DIS__VI = 0x30BE; +constexpr unsigned int mmCP_MEC_DOORBELL_RANGE_LOWER__VI = 0x305C; +constexpr unsigned int mmCP_MEC_DOORBELL_RANGE_UPPER__VI = 0x305D; +constexpr unsigned int mmCP_MEC_ME1_UCODE_ADDR__VI = 0xF81A; +constexpr unsigned int mmCP_MEC_ME1_UCODE_DATA__VI = 0xF81B; +constexpr unsigned int mmCP_MEC_ME2_UCODE_ADDR__VI = 0xF81C; +constexpr unsigned int mmCP_MEC_ME2_UCODE_DATA__VI = 0xF81D; +constexpr unsigned int mmCP_ME_RAM_DATA__SI__CI = 0x3058; +constexpr unsigned int mmCP_ME_RAM_DATA__VI = 0xF817; +constexpr unsigned int mmCP_ME_RAM_RADDR__SI__CI = 0x3056; +constexpr unsigned int mmCP_ME_RAM_RADDR__VI = 0xF816; +constexpr unsigned int mmCP_ME_RAM_WADDR__SI__CI = 0x3057; +constexpr unsigned int mmCP_ME_RAM_WADDR__VI = 0xF816; +constexpr unsigned int mmCP_PFP_COMPLETION_STATUS__VI = 0xC0EC; +constexpr unsigned int mmCP_PFP_METADATA_BASE_ADDR__VI = 0xC0F0; +constexpr unsigned int mmCP_PFP_METADATA_BASE_ADDR_HI__VI = 0xC0F1; +constexpr unsigned int mmCP_PFP_UCODE_ADDR__SI__CI = 0x3054; +constexpr unsigned int mmCP_PFP_UCODE_ADDR__VI = 0xF814; +constexpr unsigned int mmCP_PFP_UCODE_DATA__SI__CI = 0x3055; +constexpr unsigned int mmCP_PFP_UCODE_DATA__VI = 0xF815; +constexpr unsigned int mmCP_PIPE_STATS_CONTROL__VI = 0xC03D; +constexpr unsigned int mmCP_PQ_STATUS__VI = 0x30B8; +constexpr unsigned int mmCP_PRED_NOT_VISIBLE__VI = 0xC0EE; +constexpr unsigned int mmCP_RB_DOORBELL_CONTROL__VI = 0x3059; +constexpr unsigned int mmCP_RB_DOORBELL_RANGE_LOWER__VI = 0x305A; +constexpr unsigned int mmCP_RB_DOORBELL_RANGE_UPPER__VI = 0x305B; +constexpr unsigned int mmCP_SAMPLE_STATUS__VI = 0xC0FD; +constexpr unsigned int mmCP_STREAM_OUT_CONTROL__VI = 0xC03E; +constexpr unsigned int mmCP_VIRT_STATUS__VI = 0x3038; +constexpr unsigned int mmCP_VMID_STATUS__VI = 0x30BF; +constexpr unsigned int mmCRTC0_CRTC_3D_STRUCTURE_CONTROL__VI = 0x1B78; +constexpr unsigned int mmCRTC0_CRTC_AVSYNC_COUNTER__VI = 0x1B9B; +constexpr unsigned int mmCRTC0_CRTC_BLACK_COLOR__VI = 0x1BCC; +constexpr unsigned int mmCRTC0_CRTC_BLACK_COLOR_EXT__VI = 0x1BCD; +constexpr unsigned int mmCRTC0_CRTC_BLANK_DATA_COLOR__VI = 0x1BCA; +constexpr unsigned int mmCRTC0_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x1BCB; +constexpr unsigned int mmCRTC0_CRTC_CRC0_DATA_B__VI = 0x1BDA; +constexpr unsigned int mmCRTC0_CRTC_CRC0_DATA_RG__VI = 0x1BD9; +constexpr unsigned int mmCRTC0_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x1BD5; +constexpr unsigned int mmCRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x1BD6; +constexpr unsigned int mmCRTC0_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x1BD7; +constexpr unsigned int mmCRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x1BD8; +constexpr unsigned int mmCRTC0_CRTC_CRC1_DATA_B__VI = 0x1BE0; +constexpr unsigned int mmCRTC0_CRTC_CRC1_DATA_RG__VI = 0x1BDF; +constexpr unsigned int mmCRTC0_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x1BDB; +constexpr unsigned int mmCRTC0_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x1BDC; +constexpr unsigned int mmCRTC0_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x1BDD; +constexpr unsigned int mmCRTC0_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x1BDE; +constexpr unsigned int mmCRTC0_CRTC_CRC_CNTL__VI = 0x1BD4; +constexpr unsigned int mmCRTC0_CRTC_DCFE_CLOCK_CONTROL__VI = 0x1B7C; +constexpr unsigned int mmCRTC0_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x1BE1; +constexpr unsigned int mmCRTC0_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x1BE5; +constexpr unsigned int mmCRTC0_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x1BE4; +constexpr unsigned int mmCRTC0_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x1BE6; +constexpr unsigned int mmCRTC0_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x1BE3; +constexpr unsigned int mmCRTC0_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x1BE2; +constexpr unsigned int mmCRTC0_CRTC_FIELD_INDICATION_CONTROL__VI = 0x1BA0; +constexpr unsigned int mmCRTC0_CRTC_GSL_CONTROL__VI = 0x1B7B; +constexpr unsigned int mmCRTC0_CRTC_GSL_VSYNC_GAP__VI = 0x1B79; +constexpr unsigned int mmCRTC0_CRTC_GSL_WINDOW__VI = 0x1B7A; +constexpr unsigned int mmCRTC0_CRTC_H_BLANK_EARLY_NUM__VI = 0x1B7D; +constexpr unsigned int mmCRTC0_CRTC_OVERSCAN_COLOR__VI = 0x1BC8; +constexpr unsigned int mmCRTC0_CRTC_OVERSCAN_COLOR_EXT__VI = 0x1BC9; +constexpr unsigned int mmCRTC0_CRTC_PIXEL_DATA_READBACK0__VI = 0x1BA1; +constexpr unsigned int mmCRTC0_CRTC_PIXEL_DATA_READBACK1__VI = 0x1BA2; +constexpr unsigned int mmCRTC0_CRTC_STATIC_SCREEN_CONTROL__VI = 0x1BE7; +constexpr unsigned int mmCRTC0_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x1B9A; +constexpr unsigned int mmCRTC0_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x1BCF; +constexpr unsigned int mmCRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x1BCE; +constexpr unsigned int mmCRTC0_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x1BD1; +constexpr unsigned int mmCRTC0_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x1BD0; +constexpr unsigned int mmCRTC0_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x1BD3; +constexpr unsigned int mmCRTC0_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x1BD2; +constexpr unsigned int mmCRTC0_DCFE_DBG_SEL__VI = 0x1B7E; +constexpr unsigned int mmCRTC0_DCFE_MEM_PWR_CTRL__VI = 0x1B7F; +constexpr unsigned int mmCRTC0_DCFE_MEM_PWR_CTRL2__VI = 0x1BB8; +constexpr unsigned int mmCRTC0_DCFE_MEM_PWR_STATUS__VI = 0x1BB9; +constexpr unsigned int mmCRTC0_PIXEL_RATE_CNTL__VI = 0x0140; +constexpr unsigned int mmCRTC1_CRTC_3D_STRUCTURE_CONTROL__VI = 0x1D78; +constexpr unsigned int mmCRTC1_CRTC_ALLOW_STOP_OFF_V_CNT__VI = 0x1DC3; +constexpr unsigned int mmCRTC1_CRTC_AVSYNC_COUNTER__VI = 0x1D9B; +constexpr unsigned int mmCRTC1_CRTC_BLACK_COLOR__VI = 0x1DCC; +constexpr unsigned int mmCRTC1_CRTC_BLACK_COLOR_EXT__VI = 0x1DCD; +constexpr unsigned int mmCRTC1_CRTC_BLANK_CONTROL__SI__CI = 0x1E9D; +constexpr unsigned int mmCRTC1_CRTC_BLANK_CONTROL__VI = 0x1D9D; +constexpr unsigned int mmCRTC1_CRTC_BLANK_DATA_COLOR__VI = 0x1DCA; +constexpr unsigned int mmCRTC1_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x1DCB; +constexpr unsigned int mmCRTC1_CRTC_CONTROL__VI = 0x1D9C; +constexpr unsigned int mmCRTC1_CRTC_COUNT_CONTROL__VI = 0x1DA9; +constexpr unsigned int mmCRTC1_CRTC_COUNT_RESET__VI = 0x1DAA; +constexpr unsigned int mmCRTC1_CRTC_CRC0_DATA_B__VI = 0x1DDA; +constexpr unsigned int mmCRTC1_CRTC_CRC0_DATA_RG__VI = 0x1DD9; +constexpr unsigned int mmCRTC1_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x1DD5; +constexpr unsigned int mmCRTC1_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x1DD6; +constexpr unsigned int mmCRTC1_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x1DD7; +constexpr unsigned int mmCRTC1_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x1DD8; +constexpr unsigned int mmCRTC1_CRTC_CRC1_DATA_B__VI = 0x1DE0; +constexpr unsigned int mmCRTC1_CRTC_CRC1_DATA_RG__VI = 0x1DDF; +constexpr unsigned int mmCRTC1_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x1DDB; +constexpr unsigned int mmCRTC1_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x1DDC; +constexpr unsigned int mmCRTC1_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x1DDD; +constexpr unsigned int mmCRTC1_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x1DDE; +constexpr unsigned int mmCRTC1_CRTC_CRC_CNTL__VI = 0x1DD4; +constexpr unsigned int mmCRTC1_CRTC_DCFE_CLOCK_CONTROL__VI = 0x1D7C; +constexpr unsigned int mmCRTC1_CRTC_DOUBLE_BUFFER_CONTROL__VI = 0x1DB6; +constexpr unsigned int mmCRTC1_CRTC_DTMTEST_CNTL__VI = 0x1D92; +constexpr unsigned int mmCRTC1_CRTC_DTMTEST_STATUS_POSITION__VI = 0x1D93; +constexpr unsigned int mmCRTC1_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x1DE1; +constexpr unsigned int mmCRTC1_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x1DE5; +constexpr unsigned int mmCRTC1_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x1DE4; +constexpr unsigned int mmCRTC1_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x1DE6; +constexpr unsigned int mmCRTC1_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x1DE3; +constexpr unsigned int mmCRTC1_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x1DE2; +constexpr unsigned int mmCRTC1_CRTC_FIELD_INDICATION_CONTROL__VI = 0x1DA0; +constexpr unsigned int mmCRTC1_CRTC_FLOW_CONTROL__VI = 0x1D99; +constexpr unsigned int mmCRTC1_CRTC_FORCE_COUNT_NOW_CNTL__VI = 0x1D98; +constexpr unsigned int mmCRTC1_CRTC_GSL_CONTROL__VI = 0x1D7B; +constexpr unsigned int mmCRTC1_CRTC_GSL_VSYNC_GAP__VI = 0x1D79; +constexpr unsigned int mmCRTC1_CRTC_GSL_WINDOW__VI = 0x1D7A; +constexpr unsigned int mmCRTC1_CRTC_H_BLANK_EARLY_NUM__VI = 0x1D7D; +constexpr unsigned int mmCRTC1_CRTC_H_BLANK_START_END__VI = 0x1D81; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_A__VI = 0x1D82; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_A_CNTL__VI = 0x1D83; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_B__VI = 0x1D84; +constexpr unsigned int mmCRTC1_CRTC_H_SYNC_B_CNTL__VI = 0x1D85; +constexpr unsigned int mmCRTC1_CRTC_H_TOTAL__VI = 0x1D80; +constexpr unsigned int mmCRTC1_CRTC_INTERLACE_CONTROL__VI = 0x1D9E; +constexpr unsigned int mmCRTC1_CRTC_INTERLACE_STATUS__VI = 0x1D9F; +constexpr unsigned int mmCRTC1_CRTC_INTERRUPT_CONTROL__VI = 0x1DB4; +constexpr unsigned int mmCRTC1_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__VI = 0x1DAB; +constexpr unsigned int mmCRTC1_CRTC_MASTER_EN__VI = 0x1DC2; +constexpr unsigned int mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT__VI = 0x1DBF; +constexpr unsigned int mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__VI = 0x1DC0; +constexpr unsigned int mmCRTC1_CRTC_MVP_STATUS__VI = 0x1DC1; +constexpr unsigned int mmCRTC1_CRTC_NOM_VERT_POSITION__VI = 0x1DA5; +constexpr unsigned int mmCRTC1_CRTC_OVERSCAN_COLOR__VI = 0x1DC8; +constexpr unsigned int mmCRTC1_CRTC_OVERSCAN_COLOR_EXT__VI = 0x1DC9; +constexpr unsigned int mmCRTC1_CRTC_PIXEL_DATA_READBACK0__VI = 0x1DA1; +constexpr unsigned int mmCRTC1_CRTC_PIXEL_DATA_READBACK1__VI = 0x1DA2; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_CONTROL__VI = 0x1DB0; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_FRAME__VI = 0x1DB2; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_POSITION__VI = 0x1DB1; +constexpr unsigned int mmCRTC1_CRTC_SNAPSHOT_STATUS__VI = 0x1DAF; +constexpr unsigned int mmCRTC1_CRTC_START_LINE_CONTROL__VI = 0x1DB3; +constexpr unsigned int mmCRTC1_CRTC_STATIC_SCREEN_CONTROL__VI = 0x1DE7; +constexpr unsigned int mmCRTC1_CRTC_STATUS__SI__CI = 0x1EA3; +constexpr unsigned int mmCRTC1_CRTC_STATUS__VI = 0x1DA3; +constexpr unsigned int mmCRTC1_CRTC_STATUS_FRAME_COUNT__VI = 0x1DA6; +constexpr unsigned int mmCRTC1_CRTC_STATUS_HV_COUNT__VI = 0x1DA8; +constexpr unsigned int mmCRTC1_CRTC_STATUS_POSITION__SI__CI = 0x1EA4; +constexpr unsigned int mmCRTC1_CRTC_STATUS_POSITION__VI = 0x1DA4; +constexpr unsigned int mmCRTC1_CRTC_STATUS_VF_COUNT__VI = 0x1DA7; +constexpr unsigned int mmCRTC1_CRTC_STEREO_CONTROL__VI = 0x1DAE; +constexpr unsigned int mmCRTC1_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x1D9A; +constexpr unsigned int mmCRTC1_CRTC_STEREO_STATUS__VI = 0x1DAD; +constexpr unsigned int mmCRTC1_CRTC_TEST_DEBUG_DATA__VI = 0x1DC7; +constexpr unsigned int mmCRTC1_CRTC_TEST_DEBUG_INDEX__VI = 0x1DC6; +constexpr unsigned int mmCRTC1_CRTC_TEST_PATTERN_COLOR__VI = 0x1DBC; +constexpr unsigned int mmCRTC1_CRTC_TEST_PATTERN_CONTROL__VI = 0x1DBA; +constexpr unsigned int mmCRTC1_CRTC_TEST_PATTERN_PARAMETERS__VI = 0x1DBB; +constexpr unsigned int mmCRTC1_CRTC_TRIGA_CNTL__VI = 0x1D94; +constexpr unsigned int mmCRTC1_CRTC_TRIGA_MANUAL_TRIG__VI = 0x1D95; +constexpr unsigned int mmCRTC1_CRTC_TRIGB_CNTL__VI = 0x1D96; +constexpr unsigned int mmCRTC1_CRTC_TRIGB_MANUAL_TRIG__VI = 0x1D97; +constexpr unsigned int mmCRTC1_CRTC_UPDATE_LOCK__VI = 0x1DB5; +constexpr unsigned int mmCRTC1_CRTC_VBI_END__VI = 0x1D86; +constexpr unsigned int mmCRTC1_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x1DCF; +constexpr unsigned int mmCRTC1_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x1DCE; +constexpr unsigned int mmCRTC1_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x1DD1; +constexpr unsigned int mmCRTC1_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x1DD0; +constexpr unsigned int mmCRTC1_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x1DD3; +constexpr unsigned int mmCRTC1_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x1DD2; +constexpr unsigned int mmCRTC1_CRTC_VERT_SYNC_CONTROL__VI = 0x1DAC; +constexpr unsigned int mmCRTC1_CRTC_VGA_PARAMETER_CAPTURE_MODE__VI = 0x1DB7; +constexpr unsigned int mmCRTC1_CRTC_VSYNC_NOM_INT_STATUS__VI = 0x1D8C; +constexpr unsigned int mmCRTC1_CRTC_V_BLANK_START_END__VI = 0x1D8D; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_A__VI = 0x1D8E; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_A_CNTL__VI = 0x1D8F; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_B__VI = 0x1D90; +constexpr unsigned int mmCRTC1_CRTC_V_SYNC_B_CNTL__VI = 0x1D91; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL__VI = 0x1D87; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_CONTROL__VI = 0x1D8A; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_INT_STATUS__VI = 0x1D8B; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_MAX__VI = 0x1D89; +constexpr unsigned int mmCRTC1_CRTC_V_TOTAL_MIN__VI = 0x1D88; +constexpr unsigned int mmCRTC1_CRTC_V_UPDATE_INT_STATUS__VI = 0x1DC4; +constexpr unsigned int mmCRTC1_DCFE_DBG_SEL__VI = 0x1D7E; +constexpr unsigned int mmCRTC1_DCFE_MEM_PWR_CTRL__VI = 0x1D7F; +constexpr unsigned int mmCRTC1_DCFE_MEM_PWR_CTRL2__VI = 0x1DB8; +constexpr unsigned int mmCRTC1_DCFE_MEM_PWR_STATUS__VI = 0x1DB9; +constexpr unsigned int mmCRTC1_MASTER_UPDATE_LOCK__VI = 0x1DBD; +constexpr unsigned int mmCRTC1_MASTER_UPDATE_MODE__SI__CI = 0x1EBE; +constexpr unsigned int mmCRTC1_MASTER_UPDATE_MODE__VI = 0x1DBE; +constexpr unsigned int mmCRTC1_PIXEL_RATE_CNTL__VI = 0x0144; +constexpr unsigned int mmCRTC2_CRTC_3D_STRUCTURE_CONTROL__VI = 0x1F78; +constexpr unsigned int mmCRTC2_CRTC_ALLOW_STOP_OFF_V_CNT__VI = 0x1FC3; +constexpr unsigned int mmCRTC2_CRTC_AVSYNC_COUNTER__VI = 0x1F9B; +constexpr unsigned int mmCRTC2_CRTC_BLACK_COLOR__VI = 0x1FCC; +constexpr unsigned int mmCRTC2_CRTC_BLACK_COLOR_EXT__VI = 0x1FCD; +constexpr unsigned int mmCRTC2_CRTC_BLANK_CONTROL__SI__CI = 0x419D; +constexpr unsigned int mmCRTC2_CRTC_BLANK_CONTROL__VI = 0x1F9D; +constexpr unsigned int mmCRTC2_CRTC_BLANK_DATA_COLOR__VI = 0x1FCA; +constexpr unsigned int mmCRTC2_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x1FCB; +constexpr unsigned int mmCRTC2_CRTC_CONTROL__VI = 0x1F9C; +constexpr unsigned int mmCRTC2_CRTC_COUNT_CONTROL__VI = 0x1FA9; +constexpr unsigned int mmCRTC2_CRTC_COUNT_RESET__VI = 0x1FAA; +constexpr unsigned int mmCRTC2_CRTC_CRC0_DATA_B__VI = 0x1FDA; +constexpr unsigned int mmCRTC2_CRTC_CRC0_DATA_RG__VI = 0x1FD9; +constexpr unsigned int mmCRTC2_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x1FD5; +constexpr unsigned int mmCRTC2_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x1FD6; +constexpr unsigned int mmCRTC2_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x1FD7; +constexpr unsigned int mmCRTC2_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x1FD8; +constexpr unsigned int mmCRTC2_CRTC_CRC1_DATA_B__VI = 0x1FE0; +constexpr unsigned int mmCRTC2_CRTC_CRC1_DATA_RG__VI = 0x1FDF; +constexpr unsigned int mmCRTC2_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x1FDB; +constexpr unsigned int mmCRTC2_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x1FDC; +constexpr unsigned int mmCRTC2_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x1FDD; +constexpr unsigned int mmCRTC2_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x1FDE; +constexpr unsigned int mmCRTC2_CRTC_CRC_CNTL__VI = 0x1FD4; +constexpr unsigned int mmCRTC2_CRTC_DCFE_CLOCK_CONTROL__VI = 0x1F7C; +constexpr unsigned int mmCRTC2_CRTC_DOUBLE_BUFFER_CONTROL__VI = 0x1FB6; +constexpr unsigned int mmCRTC2_CRTC_DTMTEST_CNTL__VI = 0x1F92; +constexpr unsigned int mmCRTC2_CRTC_DTMTEST_STATUS_POSITION__VI = 0x1F93; +constexpr unsigned int mmCRTC2_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x1FE1; +constexpr unsigned int mmCRTC2_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x1FE5; +constexpr unsigned int mmCRTC2_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x1FE4; +constexpr unsigned int mmCRTC2_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x1FE6; +constexpr unsigned int mmCRTC2_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x1FE3; +constexpr unsigned int mmCRTC2_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x1FE2; +constexpr unsigned int mmCRTC2_CRTC_FIELD_INDICATION_CONTROL__VI = 0x1FA0; +constexpr unsigned int mmCRTC2_CRTC_FLOW_CONTROL__VI = 0x1F99; +constexpr unsigned int mmCRTC2_CRTC_FORCE_COUNT_NOW_CNTL__VI = 0x1F98; +constexpr unsigned int mmCRTC2_CRTC_GSL_CONTROL__VI = 0x1F7B; +constexpr unsigned int mmCRTC2_CRTC_GSL_VSYNC_GAP__VI = 0x1F79; +constexpr unsigned int mmCRTC2_CRTC_GSL_WINDOW__VI = 0x1F7A; +constexpr unsigned int mmCRTC2_CRTC_H_BLANK_EARLY_NUM__VI = 0x1F7D; +constexpr unsigned int mmCRTC2_CRTC_H_BLANK_START_END__VI = 0x1F81; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_A__VI = 0x1F82; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_A_CNTL__VI = 0x1F83; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_B__VI = 0x1F84; +constexpr unsigned int mmCRTC2_CRTC_H_SYNC_B_CNTL__VI = 0x1F85; +constexpr unsigned int mmCRTC2_CRTC_H_TOTAL__VI = 0x1F80; +constexpr unsigned int mmCRTC2_CRTC_INTERLACE_CONTROL__VI = 0x1F9E; +constexpr unsigned int mmCRTC2_CRTC_INTERLACE_STATUS__VI = 0x1F9F; +constexpr unsigned int mmCRTC2_CRTC_INTERRUPT_CONTROL__VI = 0x1FB4; +constexpr unsigned int mmCRTC2_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__VI = 0x1FAB; +constexpr unsigned int mmCRTC2_CRTC_MASTER_EN__VI = 0x1FC2; +constexpr unsigned int mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT__VI = 0x1FBF; +constexpr unsigned int mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__VI = 0x1FC0; +constexpr unsigned int mmCRTC2_CRTC_MVP_STATUS__VI = 0x1FC1; +constexpr unsigned int mmCRTC2_CRTC_NOM_VERT_POSITION__VI = 0x1FA5; +constexpr unsigned int mmCRTC2_CRTC_OVERSCAN_COLOR__VI = 0x1FC8; +constexpr unsigned int mmCRTC2_CRTC_OVERSCAN_COLOR_EXT__VI = 0x1FC9; +constexpr unsigned int mmCRTC2_CRTC_PIXEL_DATA_READBACK0__VI = 0x1FA1; +constexpr unsigned int mmCRTC2_CRTC_PIXEL_DATA_READBACK1__VI = 0x1FA2; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_CONTROL__VI = 0x1FB0; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_FRAME__VI = 0x1FB2; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_POSITION__VI = 0x1FB1; +constexpr unsigned int mmCRTC2_CRTC_SNAPSHOT_STATUS__VI = 0x1FAF; +constexpr unsigned int mmCRTC2_CRTC_START_LINE_CONTROL__VI = 0x1FB3; +constexpr unsigned int mmCRTC2_CRTC_STATIC_SCREEN_CONTROL__VI = 0x1FE7; +constexpr unsigned int mmCRTC2_CRTC_STATUS__SI__CI = 0x41A3; +constexpr unsigned int mmCRTC2_CRTC_STATUS__VI = 0x1FA3; +constexpr unsigned int mmCRTC2_CRTC_STATUS_FRAME_COUNT__VI = 0x1FA6; +constexpr unsigned int mmCRTC2_CRTC_STATUS_HV_COUNT__VI = 0x1FA8; +constexpr unsigned int mmCRTC2_CRTC_STATUS_POSITION__SI__CI = 0x41A4; +constexpr unsigned int mmCRTC2_CRTC_STATUS_POSITION__VI = 0x1FA4; +constexpr unsigned int mmCRTC2_CRTC_STATUS_VF_COUNT__VI = 0x1FA7; +constexpr unsigned int mmCRTC2_CRTC_STEREO_CONTROL__VI = 0x1FAE; +constexpr unsigned int mmCRTC2_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x1F9A; +constexpr unsigned int mmCRTC2_CRTC_STEREO_STATUS__VI = 0x1FAD; +constexpr unsigned int mmCRTC2_CRTC_TEST_DEBUG_DATA__VI = 0x1FC7; +constexpr unsigned int mmCRTC2_CRTC_TEST_DEBUG_INDEX__VI = 0x1FC6; +constexpr unsigned int mmCRTC2_CRTC_TEST_PATTERN_COLOR__VI = 0x1FBC; +constexpr unsigned int mmCRTC2_CRTC_TEST_PATTERN_CONTROL__VI = 0x1FBA; +constexpr unsigned int mmCRTC2_CRTC_TEST_PATTERN_PARAMETERS__VI = 0x1FBB; +constexpr unsigned int mmCRTC2_CRTC_TRIGA_CNTL__VI = 0x1F94; +constexpr unsigned int mmCRTC2_CRTC_TRIGA_MANUAL_TRIG__VI = 0x1F95; +constexpr unsigned int mmCRTC2_CRTC_TRIGB_CNTL__VI = 0x1F96; +constexpr unsigned int mmCRTC2_CRTC_TRIGB_MANUAL_TRIG__VI = 0x1F97; +constexpr unsigned int mmCRTC2_CRTC_UPDATE_LOCK__VI = 0x1FB5; +constexpr unsigned int mmCRTC2_CRTC_VBI_END__VI = 0x1F86; +constexpr unsigned int mmCRTC2_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x1FCF; +constexpr unsigned int mmCRTC2_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x1FCE; +constexpr unsigned int mmCRTC2_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x1FD1; +constexpr unsigned int mmCRTC2_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x1FD0; +constexpr unsigned int mmCRTC2_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x1FD3; +constexpr unsigned int mmCRTC2_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x1FD2; +constexpr unsigned int mmCRTC2_CRTC_VERT_SYNC_CONTROL__VI = 0x1FAC; +constexpr unsigned int mmCRTC2_CRTC_VGA_PARAMETER_CAPTURE_MODE__VI = 0x1FB7; +constexpr unsigned int mmCRTC2_CRTC_VSYNC_NOM_INT_STATUS__VI = 0x1F8C; +constexpr unsigned int mmCRTC2_CRTC_V_BLANK_START_END__VI = 0x1F8D; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_A__VI = 0x1F8E; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_A_CNTL__VI = 0x1F8F; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_B__VI = 0x1F90; +constexpr unsigned int mmCRTC2_CRTC_V_SYNC_B_CNTL__VI = 0x1F91; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL__VI = 0x1F87; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_CONTROL__VI = 0x1F8A; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_INT_STATUS__VI = 0x1F8B; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_MAX__VI = 0x1F89; +constexpr unsigned int mmCRTC2_CRTC_V_TOTAL_MIN__VI = 0x1F88; +constexpr unsigned int mmCRTC2_CRTC_V_UPDATE_INT_STATUS__VI = 0x1FC4; +constexpr unsigned int mmCRTC2_DCFE_DBG_SEL__VI = 0x1F7E; +constexpr unsigned int mmCRTC2_DCFE_MEM_PWR_CTRL__VI = 0x1F7F; +constexpr unsigned int mmCRTC2_DCFE_MEM_PWR_CTRL2__VI = 0x1FB8; +constexpr unsigned int mmCRTC2_DCFE_MEM_PWR_STATUS__VI = 0x1FB9; +constexpr unsigned int mmCRTC2_MASTER_UPDATE_LOCK__VI = 0x1FBD; +constexpr unsigned int mmCRTC2_MASTER_UPDATE_MODE__SI__CI = 0x41BE; +constexpr unsigned int mmCRTC2_MASTER_UPDATE_MODE__VI = 0x1FBE; +constexpr unsigned int mmCRTC2_PIXEL_RATE_CNTL__VI = 0x0148; +constexpr unsigned int mmCRTC3_CRTC_3D_STRUCTURE_CONTROL__VI = 0x4178; +constexpr unsigned int mmCRTC3_CRTC_ALLOW_STOP_OFF_V_CNT__VI = 0x41C3; +constexpr unsigned int mmCRTC3_CRTC_AVSYNC_COUNTER__VI = 0x419B; +constexpr unsigned int mmCRTC3_CRTC_BLACK_COLOR__VI = 0x41CC; +constexpr unsigned int mmCRTC3_CRTC_BLACK_COLOR_EXT__VI = 0x41CD; +constexpr unsigned int mmCRTC3_CRTC_BLANK_CONTROL__SI__CI = 0x449D; +constexpr unsigned int mmCRTC3_CRTC_BLANK_CONTROL__VI = 0x419D; +constexpr unsigned int mmCRTC3_CRTC_BLANK_DATA_COLOR__VI = 0x41CA; +constexpr unsigned int mmCRTC3_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x41CB; +constexpr unsigned int mmCRTC3_CRTC_CONTROL__VI = 0x419C; +constexpr unsigned int mmCRTC3_CRTC_COUNT_CONTROL__VI = 0x41A9; +constexpr unsigned int mmCRTC3_CRTC_COUNT_RESET__VI = 0x41AA; +constexpr unsigned int mmCRTC3_CRTC_CRC0_DATA_B__VI = 0x41DA; +constexpr unsigned int mmCRTC3_CRTC_CRC0_DATA_RG__VI = 0x41D9; +constexpr unsigned int mmCRTC3_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x41D5; +constexpr unsigned int mmCRTC3_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x41D6; +constexpr unsigned int mmCRTC3_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x41D7; +constexpr unsigned int mmCRTC3_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x41D8; +constexpr unsigned int mmCRTC3_CRTC_CRC1_DATA_B__VI = 0x41E0; +constexpr unsigned int mmCRTC3_CRTC_CRC1_DATA_RG__VI = 0x41DF; +constexpr unsigned int mmCRTC3_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x41DB; +constexpr unsigned int mmCRTC3_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x41DC; +constexpr unsigned int mmCRTC3_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x41DD; +constexpr unsigned int mmCRTC3_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x41DE; +constexpr unsigned int mmCRTC3_CRTC_CRC_CNTL__VI = 0x41D4; +constexpr unsigned int mmCRTC3_CRTC_DCFE_CLOCK_CONTROL__VI = 0x417C; +constexpr unsigned int mmCRTC3_CRTC_DOUBLE_BUFFER_CONTROL__VI = 0x41B6; +constexpr unsigned int mmCRTC3_CRTC_DTMTEST_CNTL__VI = 0x4192; +constexpr unsigned int mmCRTC3_CRTC_DTMTEST_STATUS_POSITION__VI = 0x4193; +constexpr unsigned int mmCRTC3_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x41E1; +constexpr unsigned int mmCRTC3_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x41E5; +constexpr unsigned int mmCRTC3_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x41E4; +constexpr unsigned int mmCRTC3_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x41E6; +constexpr unsigned int mmCRTC3_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x41E3; +constexpr unsigned int mmCRTC3_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x41E2; +constexpr unsigned int mmCRTC3_CRTC_FIELD_INDICATION_CONTROL__VI = 0x41A0; +constexpr unsigned int mmCRTC3_CRTC_FLOW_CONTROL__VI = 0x4199; +constexpr unsigned int mmCRTC3_CRTC_FORCE_COUNT_NOW_CNTL__VI = 0x4198; +constexpr unsigned int mmCRTC3_CRTC_GSL_CONTROL__VI = 0x417B; +constexpr unsigned int mmCRTC3_CRTC_GSL_VSYNC_GAP__VI = 0x4179; +constexpr unsigned int mmCRTC3_CRTC_GSL_WINDOW__VI = 0x417A; +constexpr unsigned int mmCRTC3_CRTC_H_BLANK_EARLY_NUM__VI = 0x417D; +constexpr unsigned int mmCRTC3_CRTC_H_BLANK_START_END__VI = 0x4181; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_A__VI = 0x4182; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_A_CNTL__VI = 0x4183; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_B__VI = 0x4184; +constexpr unsigned int mmCRTC3_CRTC_H_SYNC_B_CNTL__VI = 0x4185; +constexpr unsigned int mmCRTC3_CRTC_H_TOTAL__VI = 0x4180; +constexpr unsigned int mmCRTC3_CRTC_INTERLACE_CONTROL__VI = 0x419E; +constexpr unsigned int mmCRTC3_CRTC_INTERLACE_STATUS__VI = 0x419F; +constexpr unsigned int mmCRTC3_CRTC_INTERRUPT_CONTROL__VI = 0x41B4; +constexpr unsigned int mmCRTC3_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__VI = 0x41AB; +constexpr unsigned int mmCRTC3_CRTC_MASTER_EN__VI = 0x41C2; +constexpr unsigned int mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT__VI = 0x41BF; +constexpr unsigned int mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__VI = 0x41C0; +constexpr unsigned int mmCRTC3_CRTC_MVP_STATUS__VI = 0x41C1; +constexpr unsigned int mmCRTC3_CRTC_NOM_VERT_POSITION__VI = 0x41A5; +constexpr unsigned int mmCRTC3_CRTC_OVERSCAN_COLOR__VI = 0x41C8; +constexpr unsigned int mmCRTC3_CRTC_OVERSCAN_COLOR_EXT__VI = 0x41C9; +constexpr unsigned int mmCRTC3_CRTC_PIXEL_DATA_READBACK0__VI = 0x41A1; +constexpr unsigned int mmCRTC3_CRTC_PIXEL_DATA_READBACK1__VI = 0x41A2; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_CONTROL__VI = 0x41B0; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_FRAME__VI = 0x41B2; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_POSITION__VI = 0x41B1; +constexpr unsigned int mmCRTC3_CRTC_SNAPSHOT_STATUS__VI = 0x41AF; +constexpr unsigned int mmCRTC3_CRTC_START_LINE_CONTROL__VI = 0x41B3; +constexpr unsigned int mmCRTC3_CRTC_STATIC_SCREEN_CONTROL__VI = 0x41E7; +constexpr unsigned int mmCRTC3_CRTC_STATUS__SI__CI = 0x44A3; +constexpr unsigned int mmCRTC3_CRTC_STATUS__VI = 0x41A3; +constexpr unsigned int mmCRTC3_CRTC_STATUS_FRAME_COUNT__VI = 0x41A6; +constexpr unsigned int mmCRTC3_CRTC_STATUS_HV_COUNT__VI = 0x41A8; +constexpr unsigned int mmCRTC3_CRTC_STATUS_POSITION__SI__CI = 0x44A4; +constexpr unsigned int mmCRTC3_CRTC_STATUS_POSITION__VI = 0x41A4; +constexpr unsigned int mmCRTC3_CRTC_STATUS_VF_COUNT__VI = 0x41A7; +constexpr unsigned int mmCRTC3_CRTC_STEREO_CONTROL__VI = 0x41AE; +constexpr unsigned int mmCRTC3_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x419A; +constexpr unsigned int mmCRTC3_CRTC_STEREO_STATUS__VI = 0x41AD; +constexpr unsigned int mmCRTC3_CRTC_TEST_DEBUG_DATA__VI = 0x41C7; +constexpr unsigned int mmCRTC3_CRTC_TEST_DEBUG_INDEX__VI = 0x41C6; +constexpr unsigned int mmCRTC3_CRTC_TEST_PATTERN_COLOR__VI = 0x41BC; +constexpr unsigned int mmCRTC3_CRTC_TEST_PATTERN_CONTROL__VI = 0x41BA; +constexpr unsigned int mmCRTC3_CRTC_TEST_PATTERN_PARAMETERS__VI = 0x41BB; +constexpr unsigned int mmCRTC3_CRTC_TRIGA_CNTL__VI = 0x4194; +constexpr unsigned int mmCRTC3_CRTC_TRIGA_MANUAL_TRIG__VI = 0x4195; +constexpr unsigned int mmCRTC3_CRTC_TRIGB_CNTL__VI = 0x4196; +constexpr unsigned int mmCRTC3_CRTC_TRIGB_MANUAL_TRIG__VI = 0x4197; +constexpr unsigned int mmCRTC3_CRTC_UPDATE_LOCK__VI = 0x41B5; +constexpr unsigned int mmCRTC3_CRTC_VBI_END__VI = 0x4186; +constexpr unsigned int mmCRTC3_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x41CF; +constexpr unsigned int mmCRTC3_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x41CE; +constexpr unsigned int mmCRTC3_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x41D1; +constexpr unsigned int mmCRTC3_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x41D0; +constexpr unsigned int mmCRTC3_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x41D3; +constexpr unsigned int mmCRTC3_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x41D2; +constexpr unsigned int mmCRTC3_CRTC_VERT_SYNC_CONTROL__VI = 0x41AC; +constexpr unsigned int mmCRTC3_CRTC_VGA_PARAMETER_CAPTURE_MODE__VI = 0x41B7; +constexpr unsigned int mmCRTC3_CRTC_VSYNC_NOM_INT_STATUS__VI = 0x418C; +constexpr unsigned int mmCRTC3_CRTC_V_BLANK_START_END__VI = 0x418D; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_A__VI = 0x418E; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_A_CNTL__VI = 0x418F; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_B__VI = 0x4190; +constexpr unsigned int mmCRTC3_CRTC_V_SYNC_B_CNTL__VI = 0x4191; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL__VI = 0x4187; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_CONTROL__VI = 0x418A; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_INT_STATUS__VI = 0x418B; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_MAX__VI = 0x4189; +constexpr unsigned int mmCRTC3_CRTC_V_TOTAL_MIN__VI = 0x4188; +constexpr unsigned int mmCRTC3_CRTC_V_UPDATE_INT_STATUS__VI = 0x41C4; +constexpr unsigned int mmCRTC3_DCFE_DBG_SEL__VI = 0x417E; +constexpr unsigned int mmCRTC3_DCFE_MEM_PWR_CTRL__VI = 0x417F; +constexpr unsigned int mmCRTC3_DCFE_MEM_PWR_CTRL2__VI = 0x41B8; +constexpr unsigned int mmCRTC3_DCFE_MEM_PWR_STATUS__VI = 0x41B9; +constexpr unsigned int mmCRTC3_MASTER_UPDATE_LOCK__VI = 0x41BD; +constexpr unsigned int mmCRTC3_MASTER_UPDATE_MODE__SI__CI = 0x44BE; +constexpr unsigned int mmCRTC3_MASTER_UPDATE_MODE__VI = 0x41BE; +constexpr unsigned int mmCRTC3_PIXEL_RATE_CNTL__VI = 0x014C; +constexpr unsigned int mmCRTC4_CRTC_3D_STRUCTURE_CONTROL__VI = 0x4378; +constexpr unsigned int mmCRTC4_CRTC_ALLOW_STOP_OFF_V_CNT__VI = 0x43C3; +constexpr unsigned int mmCRTC4_CRTC_AVSYNC_COUNTER__VI = 0x439B; +constexpr unsigned int mmCRTC4_CRTC_BLACK_COLOR__VI = 0x43CC; +constexpr unsigned int mmCRTC4_CRTC_BLACK_COLOR_EXT__VI = 0x43CD; +constexpr unsigned int mmCRTC4_CRTC_BLANK_CONTROL__SI__CI = 0x479D; +constexpr unsigned int mmCRTC4_CRTC_BLANK_CONTROL__VI = 0x439D; +constexpr unsigned int mmCRTC4_CRTC_BLANK_DATA_COLOR__VI = 0x43CA; +constexpr unsigned int mmCRTC4_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x43CB; +constexpr unsigned int mmCRTC4_CRTC_CONTROL__VI = 0x439C; +constexpr unsigned int mmCRTC4_CRTC_COUNT_CONTROL__VI = 0x43A9; +constexpr unsigned int mmCRTC4_CRTC_COUNT_RESET__VI = 0x43AA; +constexpr unsigned int mmCRTC4_CRTC_CRC0_DATA_B__VI = 0x43DA; +constexpr unsigned int mmCRTC4_CRTC_CRC0_DATA_RG__VI = 0x43D9; +constexpr unsigned int mmCRTC4_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x43D5; +constexpr unsigned int mmCRTC4_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x43D6; +constexpr unsigned int mmCRTC4_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x43D7; +constexpr unsigned int mmCRTC4_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x43D8; +constexpr unsigned int mmCRTC4_CRTC_CRC1_DATA_B__VI = 0x43E0; +constexpr unsigned int mmCRTC4_CRTC_CRC1_DATA_RG__VI = 0x43DF; +constexpr unsigned int mmCRTC4_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x43DB; +constexpr unsigned int mmCRTC4_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x43DC; +constexpr unsigned int mmCRTC4_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x43DD; +constexpr unsigned int mmCRTC4_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x43DE; +constexpr unsigned int mmCRTC4_CRTC_CRC_CNTL__VI = 0x43D4; +constexpr unsigned int mmCRTC4_CRTC_DCFE_CLOCK_CONTROL__VI = 0x437C; +constexpr unsigned int mmCRTC4_CRTC_DOUBLE_BUFFER_CONTROL__VI = 0x43B6; +constexpr unsigned int mmCRTC4_CRTC_DTMTEST_CNTL__VI = 0x4392; +constexpr unsigned int mmCRTC4_CRTC_DTMTEST_STATUS_POSITION__VI = 0x4393; +constexpr unsigned int mmCRTC4_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x43E1; +constexpr unsigned int mmCRTC4_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x43E5; +constexpr unsigned int mmCRTC4_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x43E4; +constexpr unsigned int mmCRTC4_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x43E6; +constexpr unsigned int mmCRTC4_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x43E3; +constexpr unsigned int mmCRTC4_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x43E2; +constexpr unsigned int mmCRTC4_CRTC_FIELD_INDICATION_CONTROL__VI = 0x43A0; +constexpr unsigned int mmCRTC4_CRTC_FLOW_CONTROL__VI = 0x4399; +constexpr unsigned int mmCRTC4_CRTC_FORCE_COUNT_NOW_CNTL__VI = 0x4398; +constexpr unsigned int mmCRTC4_CRTC_GSL_CONTROL__VI = 0x437B; +constexpr unsigned int mmCRTC4_CRTC_GSL_VSYNC_GAP__VI = 0x4379; +constexpr unsigned int mmCRTC4_CRTC_GSL_WINDOW__VI = 0x437A; +constexpr unsigned int mmCRTC4_CRTC_H_BLANK_EARLY_NUM__VI = 0x437D; +constexpr unsigned int mmCRTC4_CRTC_H_BLANK_START_END__VI = 0x4381; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_A__VI = 0x4382; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_A_CNTL__VI = 0x4383; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_B__VI = 0x4384; +constexpr unsigned int mmCRTC4_CRTC_H_SYNC_B_CNTL__VI = 0x4385; +constexpr unsigned int mmCRTC4_CRTC_H_TOTAL__VI = 0x4380; +constexpr unsigned int mmCRTC4_CRTC_INTERLACE_CONTROL__VI = 0x439E; +constexpr unsigned int mmCRTC4_CRTC_INTERLACE_STATUS__VI = 0x439F; +constexpr unsigned int mmCRTC4_CRTC_INTERRUPT_CONTROL__VI = 0x43B4; +constexpr unsigned int mmCRTC4_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__VI = 0x43AB; +constexpr unsigned int mmCRTC4_CRTC_MASTER_EN__VI = 0x43C2; +constexpr unsigned int mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT__VI = 0x43BF; +constexpr unsigned int mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__VI = 0x43C0; +constexpr unsigned int mmCRTC4_CRTC_MVP_STATUS__VI = 0x43C1; +constexpr unsigned int mmCRTC4_CRTC_NOM_VERT_POSITION__VI = 0x43A5; +constexpr unsigned int mmCRTC4_CRTC_OVERSCAN_COLOR__VI = 0x43C8; +constexpr unsigned int mmCRTC4_CRTC_OVERSCAN_COLOR_EXT__VI = 0x43C9; +constexpr unsigned int mmCRTC4_CRTC_PIXEL_DATA_READBACK0__VI = 0x43A1; +constexpr unsigned int mmCRTC4_CRTC_PIXEL_DATA_READBACK1__VI = 0x43A2; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_CONTROL__VI = 0x43B0; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_FRAME__VI = 0x43B2; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_POSITION__VI = 0x43B1; +constexpr unsigned int mmCRTC4_CRTC_SNAPSHOT_STATUS__VI = 0x43AF; +constexpr unsigned int mmCRTC4_CRTC_START_LINE_CONTROL__VI = 0x43B3; +constexpr unsigned int mmCRTC4_CRTC_STATIC_SCREEN_CONTROL__VI = 0x43E7; +constexpr unsigned int mmCRTC4_CRTC_STATUS__SI__CI = 0x47A3; +constexpr unsigned int mmCRTC4_CRTC_STATUS__VI = 0x43A3; +constexpr unsigned int mmCRTC4_CRTC_STATUS_FRAME_COUNT__VI = 0x43A6; +constexpr unsigned int mmCRTC4_CRTC_STATUS_HV_COUNT__VI = 0x43A8; +constexpr unsigned int mmCRTC4_CRTC_STATUS_POSITION__SI__CI = 0x47A4; +constexpr unsigned int mmCRTC4_CRTC_STATUS_POSITION__VI = 0x43A4; +constexpr unsigned int mmCRTC4_CRTC_STATUS_VF_COUNT__VI = 0x43A7; +constexpr unsigned int mmCRTC4_CRTC_STEREO_CONTROL__VI = 0x43AE; +constexpr unsigned int mmCRTC4_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x439A; +constexpr unsigned int mmCRTC4_CRTC_STEREO_STATUS__VI = 0x43AD; +constexpr unsigned int mmCRTC4_CRTC_TEST_DEBUG_DATA__VI = 0x43C7; +constexpr unsigned int mmCRTC4_CRTC_TEST_DEBUG_INDEX__VI = 0x43C6; +constexpr unsigned int mmCRTC4_CRTC_TEST_PATTERN_COLOR__VI = 0x43BC; +constexpr unsigned int mmCRTC4_CRTC_TEST_PATTERN_CONTROL__VI = 0x43BA; +constexpr unsigned int mmCRTC4_CRTC_TEST_PATTERN_PARAMETERS__VI = 0x43BB; +constexpr unsigned int mmCRTC4_CRTC_TRIGA_CNTL__VI = 0x4394; +constexpr unsigned int mmCRTC4_CRTC_TRIGA_MANUAL_TRIG__VI = 0x4395; +constexpr unsigned int mmCRTC4_CRTC_TRIGB_CNTL__VI = 0x4396; +constexpr unsigned int mmCRTC4_CRTC_TRIGB_MANUAL_TRIG__VI = 0x4397; +constexpr unsigned int mmCRTC4_CRTC_UPDATE_LOCK__VI = 0x43B5; +constexpr unsigned int mmCRTC4_CRTC_VBI_END__VI = 0x4386; +constexpr unsigned int mmCRTC4_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x43CF; +constexpr unsigned int mmCRTC4_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x43CE; +constexpr unsigned int mmCRTC4_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x43D1; +constexpr unsigned int mmCRTC4_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x43D0; +constexpr unsigned int mmCRTC4_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x43D3; +constexpr unsigned int mmCRTC4_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x43D2; +constexpr unsigned int mmCRTC4_CRTC_VERT_SYNC_CONTROL__VI = 0x43AC; +constexpr unsigned int mmCRTC4_CRTC_VGA_PARAMETER_CAPTURE_MODE__VI = 0x43B7; +constexpr unsigned int mmCRTC4_CRTC_VSYNC_NOM_INT_STATUS__VI = 0x438C; +constexpr unsigned int mmCRTC4_CRTC_V_BLANK_START_END__VI = 0x438D; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_A__VI = 0x438E; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_A_CNTL__VI = 0x438F; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_B__VI = 0x4390; +constexpr unsigned int mmCRTC4_CRTC_V_SYNC_B_CNTL__VI = 0x4391; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL__VI = 0x4387; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_CONTROL__VI = 0x438A; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_INT_STATUS__VI = 0x438B; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_MAX__VI = 0x4389; +constexpr unsigned int mmCRTC4_CRTC_V_TOTAL_MIN__VI = 0x4388; +constexpr unsigned int mmCRTC4_CRTC_V_UPDATE_INT_STATUS__VI = 0x43C4; +constexpr unsigned int mmCRTC4_DCFE_DBG_SEL__VI = 0x437E; +constexpr unsigned int mmCRTC4_DCFE_MEM_PWR_CTRL__VI = 0x437F; +constexpr unsigned int mmCRTC4_DCFE_MEM_PWR_CTRL2__VI = 0x43B8; +constexpr unsigned int mmCRTC4_DCFE_MEM_PWR_STATUS__VI = 0x43B9; +constexpr unsigned int mmCRTC4_MASTER_UPDATE_LOCK__VI = 0x43BD; +constexpr unsigned int mmCRTC4_MASTER_UPDATE_MODE__SI__CI = 0x47BE; +constexpr unsigned int mmCRTC4_MASTER_UPDATE_MODE__VI = 0x43BE; +constexpr unsigned int mmCRTC4_PIXEL_RATE_CNTL__VI = 0x0150; +constexpr unsigned int mmCRTC5_CRTC_3D_STRUCTURE_CONTROL__VI = 0x4578; +constexpr unsigned int mmCRTC5_CRTC_ALLOW_STOP_OFF_V_CNT__VI = 0x45C3; +constexpr unsigned int mmCRTC5_CRTC_AVSYNC_COUNTER__VI = 0x459B; +constexpr unsigned int mmCRTC5_CRTC_BLACK_COLOR__VI = 0x45CC; +constexpr unsigned int mmCRTC5_CRTC_BLACK_COLOR_EXT__VI = 0x45CD; +constexpr unsigned int mmCRTC5_CRTC_BLANK_CONTROL__SI__CI = 0x4A9D; +constexpr unsigned int mmCRTC5_CRTC_BLANK_CONTROL__VI = 0x459D; +constexpr unsigned int mmCRTC5_CRTC_BLANK_DATA_COLOR__VI = 0x45CA; +constexpr unsigned int mmCRTC5_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x45CB; +constexpr unsigned int mmCRTC5_CRTC_CONTROL__VI = 0x459C; +constexpr unsigned int mmCRTC5_CRTC_COUNT_CONTROL__VI = 0x45A9; +constexpr unsigned int mmCRTC5_CRTC_COUNT_RESET__VI = 0x45AA; +constexpr unsigned int mmCRTC5_CRTC_CRC0_DATA_B__VI = 0x45DA; +constexpr unsigned int mmCRTC5_CRTC_CRC0_DATA_RG__VI = 0x45D9; +constexpr unsigned int mmCRTC5_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x45D5; +constexpr unsigned int mmCRTC5_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x45D6; +constexpr unsigned int mmCRTC5_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x45D7; +constexpr unsigned int mmCRTC5_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x45D8; +constexpr unsigned int mmCRTC5_CRTC_CRC1_DATA_B__VI = 0x45E0; +constexpr unsigned int mmCRTC5_CRTC_CRC1_DATA_RG__VI = 0x45DF; +constexpr unsigned int mmCRTC5_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x45DB; +constexpr unsigned int mmCRTC5_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x45DC; +constexpr unsigned int mmCRTC5_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x45DD; +constexpr unsigned int mmCRTC5_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x45DE; +constexpr unsigned int mmCRTC5_CRTC_CRC_CNTL__VI = 0x45D4; +constexpr unsigned int mmCRTC5_CRTC_DCFE_CLOCK_CONTROL__VI = 0x457C; +constexpr unsigned int mmCRTC5_CRTC_DOUBLE_BUFFER_CONTROL__VI = 0x45B6; +constexpr unsigned int mmCRTC5_CRTC_DTMTEST_CNTL__VI = 0x4592; +constexpr unsigned int mmCRTC5_CRTC_DTMTEST_STATUS_POSITION__VI = 0x4593; +constexpr unsigned int mmCRTC5_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x45E1; +constexpr unsigned int mmCRTC5_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x45E5; +constexpr unsigned int mmCRTC5_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x45E4; +constexpr unsigned int mmCRTC5_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x45E6; +constexpr unsigned int mmCRTC5_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x45E3; +constexpr unsigned int mmCRTC5_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x45E2; +constexpr unsigned int mmCRTC5_CRTC_FIELD_INDICATION_CONTROL__VI = 0x45A0; +constexpr unsigned int mmCRTC5_CRTC_FLOW_CONTROL__VI = 0x4599; +constexpr unsigned int mmCRTC5_CRTC_FORCE_COUNT_NOW_CNTL__VI = 0x4598; +constexpr unsigned int mmCRTC5_CRTC_GSL_CONTROL__VI = 0x457B; +constexpr unsigned int mmCRTC5_CRTC_GSL_VSYNC_GAP__VI = 0x4579; +constexpr unsigned int mmCRTC5_CRTC_GSL_WINDOW__VI = 0x457A; +constexpr unsigned int mmCRTC5_CRTC_H_BLANK_EARLY_NUM__VI = 0x457D; +constexpr unsigned int mmCRTC5_CRTC_H_BLANK_START_END__VI = 0x4581; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_A__VI = 0x4582; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_A_CNTL__VI = 0x4583; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_B__VI = 0x4584; +constexpr unsigned int mmCRTC5_CRTC_H_SYNC_B_CNTL__VI = 0x4585; +constexpr unsigned int mmCRTC5_CRTC_H_TOTAL__VI = 0x4580; +constexpr unsigned int mmCRTC5_CRTC_INTERLACE_CONTROL__VI = 0x459E; +constexpr unsigned int mmCRTC5_CRTC_INTERLACE_STATUS__VI = 0x459F; +constexpr unsigned int mmCRTC5_CRTC_INTERRUPT_CONTROL__VI = 0x45B4; +constexpr unsigned int mmCRTC5_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__VI = 0x45AB; +constexpr unsigned int mmCRTC5_CRTC_MASTER_EN__VI = 0x45C2; +constexpr unsigned int mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT__VI = 0x45BF; +constexpr unsigned int mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__VI = 0x45C0; +constexpr unsigned int mmCRTC5_CRTC_MVP_STATUS__VI = 0x45C1; +constexpr unsigned int mmCRTC5_CRTC_NOM_VERT_POSITION__VI = 0x45A5; +constexpr unsigned int mmCRTC5_CRTC_OVERSCAN_COLOR__VI = 0x45C8; +constexpr unsigned int mmCRTC5_CRTC_OVERSCAN_COLOR_EXT__VI = 0x45C9; +constexpr unsigned int mmCRTC5_CRTC_PIXEL_DATA_READBACK0__VI = 0x45A1; +constexpr unsigned int mmCRTC5_CRTC_PIXEL_DATA_READBACK1__VI = 0x45A2; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_CONTROL__VI = 0x45B0; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_FRAME__VI = 0x45B2; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_POSITION__VI = 0x45B1; +constexpr unsigned int mmCRTC5_CRTC_SNAPSHOT_STATUS__VI = 0x45AF; +constexpr unsigned int mmCRTC5_CRTC_START_LINE_CONTROL__VI = 0x45B3; +constexpr unsigned int mmCRTC5_CRTC_STATIC_SCREEN_CONTROL__VI = 0x45E7; +constexpr unsigned int mmCRTC5_CRTC_STATUS__SI__CI = 0x4AA3; +constexpr unsigned int mmCRTC5_CRTC_STATUS__VI = 0x45A3; +constexpr unsigned int mmCRTC5_CRTC_STATUS_FRAME_COUNT__VI = 0x45A6; +constexpr unsigned int mmCRTC5_CRTC_STATUS_HV_COUNT__VI = 0x45A8; +constexpr unsigned int mmCRTC5_CRTC_STATUS_POSITION__SI__CI = 0x4AA4; +constexpr unsigned int mmCRTC5_CRTC_STATUS_POSITION__VI = 0x45A4; +constexpr unsigned int mmCRTC5_CRTC_STATUS_VF_COUNT__VI = 0x45A7; +constexpr unsigned int mmCRTC5_CRTC_STEREO_CONTROL__VI = 0x45AE; +constexpr unsigned int mmCRTC5_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x459A; +constexpr unsigned int mmCRTC5_CRTC_STEREO_STATUS__VI = 0x45AD; +constexpr unsigned int mmCRTC5_CRTC_TEST_DEBUG_DATA__VI = 0x45C7; +constexpr unsigned int mmCRTC5_CRTC_TEST_DEBUG_INDEX__VI = 0x45C6; +constexpr unsigned int mmCRTC5_CRTC_TEST_PATTERN_COLOR__VI = 0x45BC; +constexpr unsigned int mmCRTC5_CRTC_TEST_PATTERN_CONTROL__VI = 0x45BA; +constexpr unsigned int mmCRTC5_CRTC_TEST_PATTERN_PARAMETERS__VI = 0x45BB; +constexpr unsigned int mmCRTC5_CRTC_TRIGA_CNTL__VI = 0x4594; +constexpr unsigned int mmCRTC5_CRTC_TRIGA_MANUAL_TRIG__VI = 0x4595; +constexpr unsigned int mmCRTC5_CRTC_TRIGB_CNTL__VI = 0x4596; +constexpr unsigned int mmCRTC5_CRTC_TRIGB_MANUAL_TRIG__VI = 0x4597; +constexpr unsigned int mmCRTC5_CRTC_UPDATE_LOCK__VI = 0x45B5; +constexpr unsigned int mmCRTC5_CRTC_VBI_END__VI = 0x4586; +constexpr unsigned int mmCRTC5_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x45CF; +constexpr unsigned int mmCRTC5_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x45CE; +constexpr unsigned int mmCRTC5_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x45D1; +constexpr unsigned int mmCRTC5_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x45D0; +constexpr unsigned int mmCRTC5_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x45D3; +constexpr unsigned int mmCRTC5_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x45D2; +constexpr unsigned int mmCRTC5_CRTC_VERT_SYNC_CONTROL__VI = 0x45AC; +constexpr unsigned int mmCRTC5_CRTC_VGA_PARAMETER_CAPTURE_MODE__VI = 0x45B7; +constexpr unsigned int mmCRTC5_CRTC_VSYNC_NOM_INT_STATUS__VI = 0x458C; +constexpr unsigned int mmCRTC5_CRTC_V_BLANK_START_END__VI = 0x458D; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_A__VI = 0x458E; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_A_CNTL__VI = 0x458F; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_B__VI = 0x4590; +constexpr unsigned int mmCRTC5_CRTC_V_SYNC_B_CNTL__VI = 0x4591; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL__VI = 0x4587; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_CONTROL__VI = 0x458A; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_INT_STATUS__VI = 0x458B; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_MAX__VI = 0x4589; +constexpr unsigned int mmCRTC5_CRTC_V_TOTAL_MIN__VI = 0x4588; +constexpr unsigned int mmCRTC5_CRTC_V_UPDATE_INT_STATUS__VI = 0x45C4; +constexpr unsigned int mmCRTC5_DCFE_DBG_SEL__VI = 0x457E; +constexpr unsigned int mmCRTC5_DCFE_MEM_PWR_CTRL__VI = 0x457F; +constexpr unsigned int mmCRTC5_DCFE_MEM_PWR_CTRL2__VI = 0x45B8; +constexpr unsigned int mmCRTC5_DCFE_MEM_PWR_STATUS__VI = 0x45B9; +constexpr unsigned int mmCRTC5_MASTER_UPDATE_LOCK__VI = 0x45BD; +constexpr unsigned int mmCRTC5_MASTER_UPDATE_MODE__SI__CI = 0x4ABE; +constexpr unsigned int mmCRTC5_MASTER_UPDATE_MODE__VI = 0x45BE; +constexpr unsigned int mmCRTC5_PIXEL_RATE_CNTL__VI = 0x0154; +constexpr unsigned int mmCRTC6_CRTC_3D_STRUCTURE_CONTROL__VI = 0x4778; +constexpr unsigned int mmCRTC6_CRTC_ALLOW_STOP_OFF_V_CNT__VI = 0x47C3; +constexpr unsigned int mmCRTC6_CRTC_AVSYNC_COUNTER__VI = 0x479B; +constexpr unsigned int mmCRTC6_CRTC_BLACK_COLOR__VI = 0x47CC; +constexpr unsigned int mmCRTC6_CRTC_BLACK_COLOR_EXT__VI = 0x47CD; +constexpr unsigned int mmCRTC6_CRTC_BLANK_CONTROL__VI = 0x479D; +constexpr unsigned int mmCRTC6_CRTC_BLANK_DATA_COLOR__VI = 0x47CA; +constexpr unsigned int mmCRTC6_CRTC_BLANK_DATA_COLOR_EXT__VI = 0x47CB; +constexpr unsigned int mmCRTC6_CRTC_CONTROL__VI = 0x479C; +constexpr unsigned int mmCRTC6_CRTC_COUNT_CONTROL__VI = 0x47A9; +constexpr unsigned int mmCRTC6_CRTC_COUNT_RESET__VI = 0x47AA; +constexpr unsigned int mmCRTC6_CRTC_CRC0_DATA_B__VI = 0x47DA; +constexpr unsigned int mmCRTC6_CRTC_CRC0_DATA_RG__VI = 0x47D9; +constexpr unsigned int mmCRTC6_CRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x47D5; +constexpr unsigned int mmCRTC6_CRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x47D6; +constexpr unsigned int mmCRTC6_CRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x47D7; +constexpr unsigned int mmCRTC6_CRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x47D8; +constexpr unsigned int mmCRTC6_CRTC_CRC1_DATA_B__VI = 0x47E0; +constexpr unsigned int mmCRTC6_CRTC_CRC1_DATA_RG__VI = 0x47DF; +constexpr unsigned int mmCRTC6_CRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x47DB; +constexpr unsigned int mmCRTC6_CRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x47DC; +constexpr unsigned int mmCRTC6_CRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x47DD; +constexpr unsigned int mmCRTC6_CRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x47DE; +constexpr unsigned int mmCRTC6_CRTC_CRC_CNTL__VI = 0x47D4; +constexpr unsigned int mmCRTC6_CRTC_DCFE_CLOCK_CONTROL__VI = 0x477C; +constexpr unsigned int mmCRTC6_CRTC_DOUBLE_BUFFER_CONTROL__VI = 0x47B6; +constexpr unsigned int mmCRTC6_CRTC_DTMTEST_CNTL__VI = 0x4792; +constexpr unsigned int mmCRTC6_CRTC_DTMTEST_STATUS_POSITION__VI = 0x4793; +constexpr unsigned int mmCRTC6_CRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x47E1; +constexpr unsigned int mmCRTC6_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x47E5; +constexpr unsigned int mmCRTC6_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x47E4; +constexpr unsigned int mmCRTC6_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x47E6; +constexpr unsigned int mmCRTC6_CRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x47E3; +constexpr unsigned int mmCRTC6_CRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x47E2; +constexpr unsigned int mmCRTC6_CRTC_FIELD_INDICATION_CONTROL__VI = 0x47A0; +constexpr unsigned int mmCRTC6_CRTC_FLOW_CONTROL__VI = 0x4799; +constexpr unsigned int mmCRTC6_CRTC_FORCE_COUNT_NOW_CNTL__VI = 0x4798; +constexpr unsigned int mmCRTC6_CRTC_GSL_CONTROL__VI = 0x477B; +constexpr unsigned int mmCRTC6_CRTC_GSL_VSYNC_GAP__VI = 0x4779; +constexpr unsigned int mmCRTC6_CRTC_GSL_WINDOW__VI = 0x477A; +constexpr unsigned int mmCRTC6_CRTC_H_BLANK_EARLY_NUM__VI = 0x477D; +constexpr unsigned int mmCRTC6_CRTC_H_BLANK_START_END__VI = 0x4781; +constexpr unsigned int mmCRTC6_CRTC_H_SYNC_A__VI = 0x4782; +constexpr unsigned int mmCRTC6_CRTC_H_SYNC_A_CNTL__VI = 0x4783; +constexpr unsigned int mmCRTC6_CRTC_H_SYNC_B__VI = 0x4784; +constexpr unsigned int mmCRTC6_CRTC_H_SYNC_B_CNTL__VI = 0x4785; +constexpr unsigned int mmCRTC6_CRTC_H_TOTAL__VI = 0x4780; +constexpr unsigned int mmCRTC6_CRTC_INTERLACE_CONTROL__VI = 0x479E; +constexpr unsigned int mmCRTC6_CRTC_INTERLACE_STATUS__VI = 0x479F; +constexpr unsigned int mmCRTC6_CRTC_INTERRUPT_CONTROL__VI = 0x47B4; +constexpr unsigned int mmCRTC6_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__VI = 0x47AB; +constexpr unsigned int mmCRTC6_CRTC_MASTER_EN__VI = 0x47C2; +constexpr unsigned int mmCRTC6_CRTC_MVP_INBAND_CNTL_INSERT__VI = 0x47BF; +constexpr unsigned int mmCRTC6_CRTC_MVP_INBAND_CNTL_INSERT_TIMER__VI = 0x47C0; +constexpr unsigned int mmCRTC6_CRTC_MVP_STATUS__VI = 0x47C1; +constexpr unsigned int mmCRTC6_CRTC_NOM_VERT_POSITION__VI = 0x47A5; +constexpr unsigned int mmCRTC6_CRTC_OVERSCAN_COLOR__VI = 0x47C8; +constexpr unsigned int mmCRTC6_CRTC_OVERSCAN_COLOR_EXT__VI = 0x47C9; +constexpr unsigned int mmCRTC6_CRTC_PIXEL_DATA_READBACK0__VI = 0x47A1; +constexpr unsigned int mmCRTC6_CRTC_PIXEL_DATA_READBACK1__VI = 0x47A2; +constexpr unsigned int mmCRTC6_CRTC_SNAPSHOT_CONTROL__VI = 0x47B0; +constexpr unsigned int mmCRTC6_CRTC_SNAPSHOT_FRAME__VI = 0x47B2; +constexpr unsigned int mmCRTC6_CRTC_SNAPSHOT_POSITION__VI = 0x47B1; +constexpr unsigned int mmCRTC6_CRTC_SNAPSHOT_STATUS__VI = 0x47AF; +constexpr unsigned int mmCRTC6_CRTC_START_LINE_CONTROL__VI = 0x47B3; +constexpr unsigned int mmCRTC6_CRTC_STATIC_SCREEN_CONTROL__VI = 0x47E7; +constexpr unsigned int mmCRTC6_CRTC_STATUS__VI = 0x47A3; +constexpr unsigned int mmCRTC6_CRTC_STATUS_FRAME_COUNT__VI = 0x47A6; +constexpr unsigned int mmCRTC6_CRTC_STATUS_HV_COUNT__VI = 0x47A8; +constexpr unsigned int mmCRTC6_CRTC_STATUS_POSITION__VI = 0x47A4; +constexpr unsigned int mmCRTC6_CRTC_STATUS_VF_COUNT__VI = 0x47A7; +constexpr unsigned int mmCRTC6_CRTC_STEREO_CONTROL__VI = 0x47AE; +constexpr unsigned int mmCRTC6_CRTC_STEREO_FORCE_NEXT_EYE__VI = 0x479A; +constexpr unsigned int mmCRTC6_CRTC_STEREO_STATUS__VI = 0x47AD; +constexpr unsigned int mmCRTC6_CRTC_TEST_DEBUG_DATA__VI = 0x47C7; +constexpr unsigned int mmCRTC6_CRTC_TEST_DEBUG_INDEX__VI = 0x47C6; +constexpr unsigned int mmCRTC6_CRTC_TEST_PATTERN_COLOR__VI = 0x47BC; +constexpr unsigned int mmCRTC6_CRTC_TEST_PATTERN_CONTROL__VI = 0x47BA; +constexpr unsigned int mmCRTC6_CRTC_TEST_PATTERN_PARAMETERS__VI = 0x47BB; +constexpr unsigned int mmCRTC6_CRTC_TRIGA_CNTL__VI = 0x4794; +constexpr unsigned int mmCRTC6_CRTC_TRIGA_MANUAL_TRIG__VI = 0x4795; +constexpr unsigned int mmCRTC6_CRTC_TRIGB_CNTL__VI = 0x4796; +constexpr unsigned int mmCRTC6_CRTC_TRIGB_MANUAL_TRIG__VI = 0x4797; +constexpr unsigned int mmCRTC6_CRTC_UPDATE_LOCK__VI = 0x47B5; +constexpr unsigned int mmCRTC6_CRTC_VBI_END__VI = 0x4786; +constexpr unsigned int mmCRTC6_CRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x47CF; +constexpr unsigned int mmCRTC6_CRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x47CE; +constexpr unsigned int mmCRTC6_CRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x47D1; +constexpr unsigned int mmCRTC6_CRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x47D0; +constexpr unsigned int mmCRTC6_CRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x47D3; +constexpr unsigned int mmCRTC6_CRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x47D2; +constexpr unsigned int mmCRTC6_CRTC_VERT_SYNC_CONTROL__VI = 0x47AC; +constexpr unsigned int mmCRTC6_CRTC_VGA_PARAMETER_CAPTURE_MODE__VI = 0x47B7; +constexpr unsigned int mmCRTC6_CRTC_VSYNC_NOM_INT_STATUS__VI = 0x478C; +constexpr unsigned int mmCRTC6_CRTC_V_BLANK_START_END__VI = 0x478D; +constexpr unsigned int mmCRTC6_CRTC_V_SYNC_A__VI = 0x478E; +constexpr unsigned int mmCRTC6_CRTC_V_SYNC_A_CNTL__VI = 0x478F; +constexpr unsigned int mmCRTC6_CRTC_V_SYNC_B__VI = 0x4790; +constexpr unsigned int mmCRTC6_CRTC_V_SYNC_B_CNTL__VI = 0x4791; +constexpr unsigned int mmCRTC6_CRTC_V_TOTAL__VI = 0x4787; +constexpr unsigned int mmCRTC6_CRTC_V_TOTAL_CONTROL__VI = 0x478A; +constexpr unsigned int mmCRTC6_CRTC_V_TOTAL_INT_STATUS__VI = 0x478B; +constexpr unsigned int mmCRTC6_CRTC_V_TOTAL_MAX__VI = 0x4789; +constexpr unsigned int mmCRTC6_CRTC_V_TOTAL_MIN__VI = 0x4788; +constexpr unsigned int mmCRTC6_CRTC_V_UPDATE_INT_STATUS__VI = 0x47C4; +constexpr unsigned int mmCRTC6_DCFE_DBG_SEL__VI = 0x477E; +constexpr unsigned int mmCRTC6_DCFE_MEM_PWR_CTRL__VI = 0x477F; +constexpr unsigned int mmCRTC6_DCFE_MEM_PWR_CTRL2__VI = 0x47B8; +constexpr unsigned int mmCRTC6_DCFE_MEM_PWR_STATUS__VI = 0x47B9; +constexpr unsigned int mmCRTC6_MASTER_UPDATE_LOCK__VI = 0x47BD; +constexpr unsigned int mmCRTC6_MASTER_UPDATE_MODE__VI = 0x47BE; +constexpr unsigned int mmCRTC_3D_STRUCTURE_CONTROL__VI = 0x1B78; +constexpr unsigned int mmCRTC_AVSYNC_COUNTER__VI = 0x1B9B; +constexpr unsigned int mmCRTC_BLACK_COLOR__VI = 0x1BCC; +constexpr unsigned int mmCRTC_BLACK_COLOR_EXT__VI = 0x1BCD; +constexpr unsigned int mmCRTC_BLANK_DATA_COLOR__VI = 0x1BCA; +constexpr unsigned int mmCRTC_BLANK_DATA_COLOR_EXT__VI = 0x1BCB; +constexpr unsigned int mmCRTC_CRC0_DATA_B__VI = 0x1BDA; +constexpr unsigned int mmCRTC_CRC0_DATA_RG__VI = 0x1BD9; +constexpr unsigned int mmCRTC_CRC0_WINDOWA_X_CONTROL__VI = 0x1BD5; +constexpr unsigned int mmCRTC_CRC0_WINDOWA_Y_CONTROL__VI = 0x1BD6; +constexpr unsigned int mmCRTC_CRC0_WINDOWB_X_CONTROL__VI = 0x1BD7; +constexpr unsigned int mmCRTC_CRC0_WINDOWB_Y_CONTROL__VI = 0x1BD8; +constexpr unsigned int mmCRTC_CRC1_DATA_B__VI = 0x1BE0; +constexpr unsigned int mmCRTC_CRC1_DATA_RG__VI = 0x1BDF; +constexpr unsigned int mmCRTC_CRC1_WINDOWA_X_CONTROL__VI = 0x1BDB; +constexpr unsigned int mmCRTC_CRC1_WINDOWA_Y_CONTROL__VI = 0x1BDC; +constexpr unsigned int mmCRTC_CRC1_WINDOWB_X_CONTROL__VI = 0x1BDD; +constexpr unsigned int mmCRTC_CRC1_WINDOWB_Y_CONTROL__VI = 0x1BDE; +constexpr unsigned int mmCRTC_CRC_CNTL__VI = 0x1BD4; +constexpr unsigned int mmCRTC_DCFE_CLOCK_CONTROL__VI = 0x1B7C; +constexpr unsigned int mmCRTC_EXT_TIMING_SYNC_CONTROL__VI = 0x1BE1; +constexpr unsigned int mmCRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__VI = 0x1BE5; +constexpr unsigned int mmCRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__VI = 0x1BE4; +constexpr unsigned int mmCRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__VI = 0x1BE6; +constexpr unsigned int mmCRTC_EXT_TIMING_SYNC_WINDOW_END__VI = 0x1BE3; +constexpr unsigned int mmCRTC_EXT_TIMING_SYNC_WINDOW_START__VI = 0x1BE2; +constexpr unsigned int mmCRTC_FIELD_INDICATION_CONTROL__VI = 0x1BA0; +constexpr unsigned int mmCRTC_GSL_CONTROL__VI = 0x1B7B; +constexpr unsigned int mmCRTC_GSL_VSYNC_GAP__VI = 0x1B79; +constexpr unsigned int mmCRTC_GSL_WINDOW__VI = 0x1B7A; +constexpr unsigned int mmCRTC_H_BLANK_EARLY_NUM__VI = 0x1B7D; +constexpr unsigned int mmCRTC_OVERSCAN_COLOR__VI = 0x1BC8; +constexpr unsigned int mmCRTC_OVERSCAN_COLOR_EXT__VI = 0x1BC9; +constexpr unsigned int mmCRTC_PIXEL_DATA_READBACK0__VI = 0x1BA1; +constexpr unsigned int mmCRTC_PIXEL_DATA_READBACK1__VI = 0x1BA2; +constexpr unsigned int mmCRTC_STATIC_SCREEN_CONTROL__VI = 0x1BE7; +constexpr unsigned int mmCRTC_STEREO_FORCE_NEXT_EYE__VI = 0x1B9A; +constexpr unsigned int mmCRTC_VERTICAL_INTERRUPT0_CONTROL__VI = 0x1BCF; +constexpr unsigned int mmCRTC_VERTICAL_INTERRUPT0_POSITION__VI = 0x1BCE; +constexpr unsigned int mmCRTC_VERTICAL_INTERRUPT1_CONTROL__VI = 0x1BD1; +constexpr unsigned int mmCRTC_VERTICAL_INTERRUPT1_POSITION__VI = 0x1BD0; +constexpr unsigned int mmCRTC_VERTICAL_INTERRUPT2_CONTROL__VI = 0x1BD3; +constexpr unsigned int mmCRTC_VERTICAL_INTERRUPT2_POSITION__VI = 0x1BD2; +constexpr unsigned int mmCUR2_COLOR1__VI = 0x1A75; +constexpr unsigned int mmCUR2_COLOR2__VI = 0x1A76; +constexpr unsigned int mmCUR2_CONTROL__VI = 0x1A6F; +constexpr unsigned int mmCUR2_HOT_SPOT__VI = 0x1A74; +constexpr unsigned int mmCUR2_POSITION__VI = 0x1A73; +constexpr unsigned int mmCUR2_SIZE__VI = 0x1A71; +constexpr unsigned int mmCUR2_STEREO_CONTROL__VI = 0x1A9B; +constexpr unsigned int mmCUR2_SURFACE_ADDRESS__VI = 0x1A70; +constexpr unsigned int mmCUR2_SURFACE_ADDRESS_HIGH__VI = 0x1A72; +constexpr unsigned int mmCUR2_UPDATE__VI = 0x1A77; +constexpr unsigned int mmCUR_REQUEST_FILTER_CNTL__VI = 0x1A99; +constexpr unsigned int mmCUR_STEREO_CONTROL__VI = 0x1A9A; +constexpr unsigned int mmDAC_AUTODETECT_CONTROL__VI = 0x16B4; +constexpr unsigned int mmDAC_AUTODETECT_CONTROL2__VI = 0x16B5; +constexpr unsigned int mmDAC_AUTODETECT_CONTROL3__VI = 0x16B6; +constexpr unsigned int mmDAC_AUTODETECT_INT_CONTROL__VI = 0x16B8; +constexpr unsigned int mmDAC_AUTODETECT_STATUS__VI = 0x16B7; +constexpr unsigned int mmDAC_CLK_ENABLE__VI = 0x0128; +constexpr unsigned int mmDAC_COMPARATOR_ENABLE__VI = 0x16BD; +constexpr unsigned int mmDAC_COMPARATOR_OUTPUT__VI = 0x16BE; +constexpr unsigned int mmDAC_CONTROL__VI = 0x16BC; +constexpr unsigned int mmDAC_CRC_CONTROL__VI = 0x16AD; +constexpr unsigned int mmDAC_CRC_EN__VI = 0x16AC; +constexpr unsigned int mmDAC_CRC_SIG_CONTROL__VI = 0x16B1; +constexpr unsigned int mmDAC_CRC_SIG_CONTROL_MASK__VI = 0x16AF; +constexpr unsigned int mmDAC_CRC_SIG_RGB__VI = 0x16B0; +constexpr unsigned int mmDAC_CRC_SIG_RGB_MASK__VI = 0x16AE; +constexpr unsigned int mmDAC_DFT_CONFIG__VI = 0x16C0; +constexpr unsigned int mmDAC_ENABLE__VI = 0x16AA; +constexpr unsigned int mmDAC_FIFO_STATUS__VI = 0x16C1; +constexpr unsigned int mmDAC_FORCE_DATA__VI = 0x16BA; +constexpr unsigned int mmDAC_FORCE_OUTPUT_CNTL__VI = 0x16B9; +constexpr unsigned int mmDAC_MACRO_CNTL_RESERVED0__VI = 0x48B8; +constexpr unsigned int mmDAC_MACRO_CNTL_RESERVED1__VI = 0x48B9; +constexpr unsigned int mmDAC_MACRO_CNTL_RESERVED2__VI = 0x48BA; +constexpr unsigned int mmDAC_MACRO_CNTL_RESERVED3__VI = 0x48BB; +constexpr unsigned int mmDAC_POWERDOWN__VI = 0x16BB; +constexpr unsigned int mmDAC_PWR_CNTL__VI = 0x16BF; +constexpr unsigned int mmDAC_SOURCE_SELECT__VI = 0x16AB; +constexpr unsigned int mmDAC_STEREOSYNC_SELECT__VI = 0x16B3; +constexpr unsigned int mmDAC_SYNC_TRISTATE_CONTROL__VI = 0x16B2; +constexpr unsigned int mmDAC_TEST_DEBUG_DATA__VI = 0x16C3; +constexpr unsigned int mmDAC_TEST_DEBUG_INDEX__VI = 0x16C2; +constexpr unsigned int mmDBG_OUT_CNTL__VI = 0x4834; +constexpr unsigned int mmDBG_SMB_BYPASS_SRBM_ACCESS__VI = 0x14EB; +constexpr unsigned int mmDCCG_AUDIO_DTO0_MODULE__VI = 0x016D; +constexpr unsigned int mmDCCG_AUDIO_DTO0_PHASE__VI = 0x016C; +constexpr unsigned int mmDCCG_AUDIO_DTO1_MODULE__VI = 0x016F; +constexpr unsigned int mmDCCG_AUDIO_DTO1_PHASE__VI = 0x016E; +constexpr unsigned int mmDCCG_AUDIO_DTO_SOURCE__VI = 0x016B; +constexpr unsigned int mmDCCG_CAC_STATUS__VI = 0x0137; +constexpr unsigned int mmDCCG_CBUS_WRCMD_DELAY__VI = 0x0110; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED0__VI = 0x5FD0; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED1__VI = 0x5FD1; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED10__VI = 0x5FDA; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED11__VI = 0x5FDB; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED2__VI = 0x5FD2; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED3__VI = 0x5FD3; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED4__VI = 0x5FD4; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED5__VI = 0x5FD5; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED6__VI = 0x5FD6; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED7__VI = 0x5FD7; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED8__VI = 0x5FD8; +constexpr unsigned int mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED9__VI = 0x5FD9; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED0__VI = 0x5FDC; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED1__VI = 0x5FDD; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED10__VI = 0x5FE6; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED11__VI = 0x5FE7; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED2__VI = 0x5FDE; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED3__VI = 0x5FDF; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED4__VI = 0x5FE0; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED5__VI = 0x5FE1; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED6__VI = 0x5FE2; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED7__VI = 0x5FE3; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED8__VI = 0x5FE4; +constexpr unsigned int mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED9__VI = 0x5FE5; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED0__VI = 0x5FE8; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED1__VI = 0x5FE9; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED10__VI = 0x5FF2; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED11__VI = 0x5FF3; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED2__VI = 0x5FEA; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED3__VI = 0x5FEB; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED4__VI = 0x5FEC; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED5__VI = 0x5FED; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED6__VI = 0x5FEE; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED7__VI = 0x5FEF; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED8__VI = 0x5FF0; +constexpr unsigned int mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED9__VI = 0x5FF1; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED0__VI = 0x5FF4; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED1__VI = 0x5FF5; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED10__VI = 0x5FFE; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED11__VI = 0x5FFF; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED2__VI = 0x5FF6; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED3__VI = 0x5FF7; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED4__VI = 0x5FF8; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED5__VI = 0x5FF9; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED6__VI = 0x5FFA; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED7__VI = 0x5FFB; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED8__VI = 0x5FFC; +constexpr unsigned int mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED9__VI = 0x5FFD; +constexpr unsigned int mmDCCG_DISP_CNTL_REG__VI = 0x013F; +constexpr unsigned int mmDCCG_DS_CNTL__VI = 0x0115; +constexpr unsigned int mmDCCG_DS_DEBUG_CNTL__VI = 0x0112; +constexpr unsigned int mmDCCG_DS_DTO_INCR__VI = 0x0113; +constexpr unsigned int mmDCCG_DS_DTO_MODULO__VI = 0x0114; +constexpr unsigned int mmDCCG_DS_HW_CAL_INTERVAL__VI = 0x0116; +constexpr unsigned int mmDCCG_GATE_DISABLE_CNTL__VI = 0x0134; +constexpr unsigned int mmDCCG_GTC_CNTL__VI = 0x0120; +constexpr unsigned int mmDCCG_GTC_CURRENT__VI = 0x0123; +constexpr unsigned int mmDCCG_GTC_DTO_INCR__VI = 0x0121; +constexpr unsigned int mmDCCG_GTC_DTO_MODULO__VI = 0x0122; +constexpr unsigned int mmDCCG_PERFMON_CNTL__VI = 0x0133; +constexpr unsigned int mmDCCG_PERFMON_CNTL2__VI = 0x010E; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED0__VI = 0x1700; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED1__VI = 0x1701; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED10__VI = 0x170A; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED11__VI = 0x170B; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED12__VI = 0x170C; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED13__VI = 0x170D; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED14__VI = 0x170E; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED15__VI = 0x170F; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED16__VI = 0x1710; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED17__VI = 0x1711; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED18__VI = 0x1712; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED19__VI = 0x1713; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED2__VI = 0x1702; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED20__VI = 0x1714; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED21__VI = 0x1715; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED22__VI = 0x1716; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED23__VI = 0x1717; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED24__VI = 0x1718; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED25__VI = 0x1719; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED26__VI = 0x171A; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED27__VI = 0x171B; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED28__VI = 0x171C; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED29__VI = 0x171D; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED3__VI = 0x1703; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED30__VI = 0x171E; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED31__VI = 0x171F; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED32__VI = 0x1720; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED33__VI = 0x1721; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED34__VI = 0x1722; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED35__VI = 0x1723; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED36__VI = 0x1724; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED37__VI = 0x1725; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED38__VI = 0x1726; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED39__VI = 0x1727; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED4__VI = 0x1704; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED40__VI = 0x1728; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED41__VI = 0x1729; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED5__VI = 0x1705; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED6__VI = 0x1706; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED7__VI = 0x1707; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED8__VI = 0x1708; +constexpr unsigned int mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED9__VI = 0x1709; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED0__VI = 0x172A; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED1__VI = 0x172B; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED10__VI = 0x1734; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED11__VI = 0x1735; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED12__VI = 0x1736; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED13__VI = 0x1737; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED14__VI = 0x1738; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED15__VI = 0x1739; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED16__VI = 0x173A; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED17__VI = 0x173B; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED18__VI = 0x173C; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED19__VI = 0x173D; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED2__VI = 0x172C; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED20__VI = 0x173E; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED21__VI = 0x173F; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED22__VI = 0x1740; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED23__VI = 0x1741; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED24__VI = 0x1742; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED25__VI = 0x1743; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED26__VI = 0x1744; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED27__VI = 0x1745; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED28__VI = 0x1746; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED29__VI = 0x1747; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED3__VI = 0x172D; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED30__VI = 0x1748; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED31__VI = 0x1749; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED32__VI = 0x174A; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED33__VI = 0x174B; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED34__VI = 0x174C; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED35__VI = 0x174D; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED36__VI = 0x174E; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED37__VI = 0x174F; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED38__VI = 0x1750; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED39__VI = 0x1751; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED4__VI = 0x172E; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED40__VI = 0x1752; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED41__VI = 0x1753; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED5__VI = 0x172F; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED6__VI = 0x1730; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED7__VI = 0x1731; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED8__VI = 0x1732; +constexpr unsigned int mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED9__VI = 0x1733; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED0__VI = 0x1754; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED1__VI = 0x1755; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED10__VI = 0x175E; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED11__VI = 0x175F; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED12__VI = 0x1760; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED13__VI = 0x1761; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED14__VI = 0x1762; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED15__VI = 0x1763; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED16__VI = 0x1764; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED17__VI = 0x1765; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED18__VI = 0x1766; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED19__VI = 0x1767; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED2__VI = 0x1756; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED20__VI = 0x1768; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED21__VI = 0x1769; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED22__VI = 0x176A; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED23__VI = 0x176B; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED24__VI = 0x176C; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED25__VI = 0x176D; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED26__VI = 0x176E; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED27__VI = 0x176F; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED28__VI = 0x1770; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED29__VI = 0x1771; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED3__VI = 0x1757; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED30__VI = 0x1772; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED31__VI = 0x1773; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED32__VI = 0x1774; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED33__VI = 0x1775; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED34__VI = 0x1776; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED35__VI = 0x1777; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED36__VI = 0x1778; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED37__VI = 0x1779; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED38__VI = 0x177A; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED39__VI = 0x177B; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED4__VI = 0x1758; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED40__VI = 0x177C; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED41__VI = 0x177D; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED5__VI = 0x1759; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED6__VI = 0x175A; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED7__VI = 0x175B; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED8__VI = 0x175C; +constexpr unsigned int mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED9__VI = 0x175D; +constexpr unsigned int mmDCCG_SOFT_RESET__VI = 0x015F; +constexpr unsigned int mmDCCG_TEST_CLK_SEL__VI = 0x017E; +constexpr unsigned int mmDCCG_TEST_DEBUG_DATA__VI = 0x017D; +constexpr unsigned int mmDCCG_TEST_DEBUG_INDEX__VI = 0x017C; +constexpr unsigned int mmDCDEBUG_BUS_CLK1_SEL__VI = 0x16C4; +constexpr unsigned int mmDCDEBUG_BUS_CLK2_SEL__VI = 0x16C5; +constexpr unsigned int mmDCDEBUG_BUS_CLK3_SEL__VI = 0x16C6; +constexpr unsigned int mmDCDEBUG_BUS_CLK4_SEL__VI = 0x16C7; +constexpr unsigned int mmDCDEBUG_BUS_CLK5_SEL__VI = 0x16C8; +constexpr unsigned int mmDCDEBUG_OUT_CNTL__VI = 0x16CA; +constexpr unsigned int mmDCDEBUG_OUT_DATA__VI = 0x16CB; +constexpr unsigned int mmDCDEBUG_OUT_PIN_OVERRIDE__VI = 0x16C9; +constexpr unsigned int mmDCE_VCE_CONTROL__VI = 0x1856; +constexpr unsigned int mmDCFE0_DCFE_CLOCK_CONTROL__VI = 0x1B00; +constexpr unsigned int mmDCFE0_DCFE_DBG_CONFIG__VI = 0x1B02; +constexpr unsigned int mmDCFE0_DCFE_SOFT_RESET__VI = 0x1B01; +constexpr unsigned int mmDCFE1_DCFE_CLOCK_CONTROL__VI = 0x1D00; +constexpr unsigned int mmDCFE1_DCFE_DBG_CONFIG__VI = 0x1D02; +constexpr unsigned int mmDCFE1_DCFE_SOFT_RESET__VI = 0x1D01; +constexpr unsigned int mmDCFE2_DCFE_CLOCK_CONTROL__VI = 0x1F00; +constexpr unsigned int mmDCFE2_DCFE_DBG_CONFIG__VI = 0x1F02; +constexpr unsigned int mmDCFE2_DCFE_SOFT_RESET__VI = 0x1F01; +constexpr unsigned int mmDCFE3_DCFE_CLOCK_CONTROL__VI = 0x4100; +constexpr unsigned int mmDCFE3_DCFE_DBG_CONFIG__VI = 0x4102; +constexpr unsigned int mmDCFE3_DCFE_SOFT_RESET__VI = 0x4101; +constexpr unsigned int mmDCFE4_DCFE_CLOCK_CONTROL__VI = 0x4300; +constexpr unsigned int mmDCFE4_DCFE_DBG_CONFIG__VI = 0x4302; +constexpr unsigned int mmDCFE4_DCFE_SOFT_RESET__VI = 0x4301; +constexpr unsigned int mmDCFE5_DCFE_CLOCK_CONTROL__VI = 0x4500; +constexpr unsigned int mmDCFE5_DCFE_DBG_CONFIG__VI = 0x4502; +constexpr unsigned int mmDCFE5_DCFE_SOFT_RESET__VI = 0x4501; +constexpr unsigned int mmDCFEV0_CRTC_PIXEL_RATE_CNTL__VI = 0x0104; +constexpr unsigned int mmDCFEV0_PG_CONFIG__VI = 0x02DB; +constexpr unsigned int mmDCFEV0_PG_ENABLE__VI = 0x02DC; +constexpr unsigned int mmDCFEV0_PG_STATUS__VI = 0x02DD; +constexpr unsigned int mmDCFEV_CLOCK_CONTROL__VI = 0x46F4; +constexpr unsigned int mmDCFEV_DBG_CONFIG__VI = 0x46F7; +constexpr unsigned int mmDCFEV_DMIFV_CLOCK_CONTROL__VI = 0x46F6; +constexpr unsigned int mmDCFEV_DMIFV_MEM_PWR_CTRL__VI = 0x46F8; +constexpr unsigned int mmDCFEV_DMIFV_MEM_PWR_STATUS__VI = 0x46F9; +constexpr unsigned int mmDCFEV_SOFT_RESET__VI = 0x46F5; +constexpr unsigned int mmDCFE_CLOCK_CONTROL__VI = 0x1B00; +constexpr unsigned int mmDCFE_DBG_CONFIG__VI = 0x1B02; +constexpr unsigned int mmDCFE_DBG_SEL__VI = 0x1B7E; +constexpr unsigned int mmDCFE_MEM_PWR_CTRL__VI = 0x1B7F; +constexpr unsigned int mmDCFE_MEM_PWR_CTRL2__VI = 0x1BB8; +constexpr unsigned int mmDCFE_MEM_PWR_STATUS__VI = 0x1BB9; +constexpr unsigned int mmDCFE_SOFT_RESET__VI = 0x1B01; +constexpr unsigned int mmDCIO_CLOCK_CNTL__VI = 0x482D; +constexpr unsigned int mmDCIO_DEBUG__VI = 0x482F; +constexpr unsigned int mmDCIO_DEBUG_CONFIG__VI = 0x4835; +constexpr unsigned int mmDCIO_DPHY_SEL__VI = 0x4837; +constexpr unsigned int mmDCIO_GSL0_CNTL__VI = 0x4826; +constexpr unsigned int mmDCIO_GSL1_CNTL__VI = 0x4827; +constexpr unsigned int mmDCIO_GSL2_CNTL__VI = 0x4828; +constexpr unsigned int mmDCIO_GSL_GENLK_PAD_CNTL__VI = 0x4824; +constexpr unsigned int mmDCIO_GSL_SWAPLOCK_PAD_CNTL__VI = 0x4825; +constexpr unsigned int mmDCIO_IMPCAL_CNTL__VI = 0x483D; +constexpr unsigned int mmDCIO_IMPCAL_CNTL_CD__VI = 0x4841; +constexpr unsigned int mmDCIO_IMPCAL_CNTL_EF__VI = 0x4845; +constexpr unsigned int mmDCIO_SOFT_RESET__VI = 0x4836; +constexpr unsigned int mmDCIO_TEST_DEBUG_DATA__VI = 0x4832; +constexpr unsigned int mmDCIO_TEST_DEBUG_INDEX__VI = 0x4831; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x48C0; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x48C1; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x48CA; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x48CB; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x48CC; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x48CD; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x48CE; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x48CF; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x48D0; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x48D1; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x48D2; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x48D3; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x48C2; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x48D4; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x48D5; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x48D6; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x48D7; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x48D8; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x48D9; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x48DA; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x48DB; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x48DC; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x48DD; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x48C3; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x48DE; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x48DF; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x48C4; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x48C5; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x48C6; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x48C7; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x48C8; +constexpr unsigned int mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x48C9; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x48E0; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x48E1; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x48EA; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x48EB; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x48EC; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x48ED; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x48EE; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x48EF; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x48F0; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x48F1; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x48F2; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x48F3; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x48E2; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x48F4; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x48F5; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x48F6; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x48F7; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x48F8; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x48F9; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x48FA; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x48FB; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x48FC; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x48FD; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x48E3; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x48FE; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x48FF; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x48E4; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x48E5; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x48E6; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x48E7; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x48E8; +constexpr unsigned int mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x48E9; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x4900; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x4901; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x490A; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x490B; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x490C; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x490D; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x490E; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x490F; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x4910; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x4911; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x4912; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x4913; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x4902; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x4914; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x4915; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x4916; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x4917; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x4918; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x4919; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x491A; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x491B; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x491C; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x491D; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x4903; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x491E; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x491F; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x4904; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x4905; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x4906; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x4907; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x4908; +constexpr unsigned int mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x4909; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x4920; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x4921; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x492A; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x492B; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x492C; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x492D; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x492E; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x492F; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x4930; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x4931; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x4932; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x4933; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x4922; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x4934; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x4935; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x4936; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x4937; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x4938; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x4939; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x493A; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x493B; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x493C; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x493D; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x4923; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x493E; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x493F; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x4924; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x4925; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x4926; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x4927; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x4928; +constexpr unsigned int mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x4929; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x4940; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x4941; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x494A; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x494B; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x494C; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x494D; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x494E; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x494F; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x4950; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x4951; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x4952; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x4953; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x4942; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x4954; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x4955; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x4956; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x4957; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x4958; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x4959; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x495A; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x495B; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x495C; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x495D; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x4943; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x495E; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x495F; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x4944; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x4945; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x4946; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x4947; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x4948; +constexpr unsigned int mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x4949; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x4960; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x4961; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x496A; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x496B; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x496C; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x496D; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x496E; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x496F; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x4970; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x4971; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x4972; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x4973; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x4962; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x4974; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x4975; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x4976; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x4977; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x4978; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x4979; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x497A; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x497B; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x497C; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x497D; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x4963; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x497E; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x497F; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x4964; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x4965; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x4966; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x4967; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x4968; +constexpr unsigned int mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x4969; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED0__VI = 0x4980; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED1__VI = 0x4981; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED10__VI = 0x498A; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED11__VI = 0x498B; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED12__VI = 0x498C; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED13__VI = 0x498D; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED14__VI = 0x498E; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED15__VI = 0x498F; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED16__VI = 0x4990; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED17__VI = 0x4991; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED18__VI = 0x4992; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED19__VI = 0x4993; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED2__VI = 0x4982; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED20__VI = 0x4994; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED21__VI = 0x4995; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED22__VI = 0x4996; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED23__VI = 0x4997; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED24__VI = 0x4998; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED25__VI = 0x4999; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED26__VI = 0x499A; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED27__VI = 0x499B; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED28__VI = 0x499C; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED29__VI = 0x499D; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED3__VI = 0x4983; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED30__VI = 0x499E; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED31__VI = 0x499F; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED4__VI = 0x4984; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED5__VI = 0x4985; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED6__VI = 0x4986; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED7__VI = 0x4987; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED8__VI = 0x4988; +constexpr unsigned int mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED9__VI = 0x4989; +constexpr unsigned int mmDCIO_WRCMD_DELAY__VI = 0x4816; +constexpr unsigned int mmDCI_CLK_CNTL__VI = 0x0319; +constexpr unsigned int mmDCI_CLK_RAMP_CNTL__VI = 0x031A; +constexpr unsigned int mmDCI_DEBUG_CONFIG__VI = 0x0320; +constexpr unsigned int mmDCI_MEM_PWR_CNTL__VI = 0x031B; +constexpr unsigned int mmDCI_MEM_PWR_CNTL2__VI = 0x031C; +constexpr unsigned int mmDCI_MEM_PWR_CNTL3__VI = 0x031D; +constexpr unsigned int mmDCI_MEM_PWR_STATUS__VI = 0x0317; +constexpr unsigned int mmDCI_MEM_PWR_STATUS2__VI = 0x0318; +constexpr unsigned int mmDCI_PG_DEBUG_CONFIG__VI = 0x1812; +constexpr unsigned int mmDCI_SOFT_RESET__VI = 0x0328; +constexpr unsigned int mmDCI_TEST_DEBUG_DATA__VI = 0x031F; +constexpr unsigned int mmDCI_TEST_DEBUG_INDEX__VI = 0x031E; +constexpr unsigned int mmDCO_CLK_CNTL__VI = 0x1864; +constexpr unsigned int mmDCO_CLK_RAMP_CNTL__VI = 0x1865; +constexpr unsigned int mmDCO_DCFE_EXT_VSYNC_CNTL__VI = 0x4830; +constexpr unsigned int mmDCO_MEM_PWR_CTRL__VI = 0x1862; +constexpr unsigned int mmDCO_MEM_PWR_CTRL2__VI = 0x1863; +constexpr unsigned int mmDCO_MEM_PWR_STATUS__VI = 0x1861; +constexpr unsigned int mmDCO_POWER_MANAGEMENT_CNTL__VI = 0x1868; +constexpr unsigned int mmDCO_SCRATCH0__VI = 0x184E; +constexpr unsigned int mmDCO_SCRATCH1__VI = 0x184F; +constexpr unsigned int mmDCO_SCRATCH2__VI = 0x1850; +constexpr unsigned int mmDCO_SCRATCH3__VI = 0x1851; +constexpr unsigned int mmDCO_SCRATCH4__VI = 0x1852; +constexpr unsigned int mmDCO_SCRATCH5__VI = 0x1853; +constexpr unsigned int mmDCO_SCRATCH6__VI = 0x1854; +constexpr unsigned int mmDCO_SCRATCH7__VI = 0x1855; +constexpr unsigned int mmDCO_SOFT_RESET__VI = 0x1871; +constexpr unsigned int mmDCO_STEREOSYNC_SEL__VI = 0x186E; +constexpr unsigned int mmDCO_TEST_DEBUG_DATA__VI = 0x1870; +constexpr unsigned int mmDCO_TEST_DEBUG_INDEX__VI = 0x186F; +constexpr unsigned int mmDCP0_ALPHA_CONTROL__VI = 0x1ABC; +constexpr unsigned int mmDCP0_COMM_MATRIXA_TRANS_C11_C12__VI = 0x1A43; +constexpr unsigned int mmDCP0_COMM_MATRIXA_TRANS_C13_C14__VI = 0x1A44; +constexpr unsigned int mmDCP0_COMM_MATRIXA_TRANS_C21_C22__VI = 0x1A45; +constexpr unsigned int mmDCP0_COMM_MATRIXA_TRANS_C23_C24__VI = 0x1A46; +constexpr unsigned int mmDCP0_COMM_MATRIXA_TRANS_C31_C32__VI = 0x1A47; +constexpr unsigned int mmDCP0_COMM_MATRIXA_TRANS_C33_C34__VI = 0x1A48; +constexpr unsigned int mmDCP0_COMM_MATRIXB_TRANS_C11_C12__VI = 0x1A49; +constexpr unsigned int mmDCP0_COMM_MATRIXB_TRANS_C13_C14__VI = 0x1A4A; +constexpr unsigned int mmDCP0_COMM_MATRIXB_TRANS_C21_C22__VI = 0x1A4B; +constexpr unsigned int mmDCP0_COMM_MATRIXB_TRANS_C23_C24__VI = 0x1A4C; +constexpr unsigned int mmDCP0_COMM_MATRIXB_TRANS_C31_C32__VI = 0x1A4D; +constexpr unsigned int mmDCP0_COMM_MATRIXB_TRANS_C33_C34__VI = 0x1A4E; +constexpr unsigned int mmDCP0_CUR2_COLOR1__VI = 0x1A75; +constexpr unsigned int mmDCP0_CUR2_COLOR2__VI = 0x1A76; +constexpr unsigned int mmDCP0_CUR2_CONTROL__VI = 0x1A6F; +constexpr unsigned int mmDCP0_CUR2_HOT_SPOT__VI = 0x1A74; +constexpr unsigned int mmDCP0_CUR2_POSITION__VI = 0x1A73; +constexpr unsigned int mmDCP0_CUR2_SIZE__VI = 0x1A71; +constexpr unsigned int mmDCP0_CUR2_STEREO_CONTROL__VI = 0x1A9B; +constexpr unsigned int mmDCP0_CUR2_SURFACE_ADDRESS__VI = 0x1A70; +constexpr unsigned int mmDCP0_CUR2_SURFACE_ADDRESS_HIGH__VI = 0x1A72; +constexpr unsigned int mmDCP0_CUR2_UPDATE__VI = 0x1A77; +constexpr unsigned int mmDCP0_CUR_REQUEST_FILTER_CNTL__VI = 0x1A99; +constexpr unsigned int mmDCP0_CUR_STEREO_CONTROL__VI = 0x1A9A; +constexpr unsigned int mmDCP0_DCP_DEBUG2__VI = 0x1A98; +constexpr unsigned int mmDCP0_DCP_FP_CONVERTED_FIELD__VI = 0x1A65; +constexpr unsigned int mmDCP0_DCP_GSL_CONTROL__VI = 0x1A90; +constexpr unsigned int mmDCP0_DCP_RANDOM_SEEDS__VI = 0x1A61; +constexpr unsigned int mmDCP0_DCP_SPATIAL_DITHER_CNTL__VI = 0x1A60; +constexpr unsigned int mmDCP0_DC_LUT_VGA_ACCESS_ENABLE__VI = 0x1A7D; +constexpr unsigned int mmDCP0_DEGAMMA_CONTROL__VI = 0x1A58; +constexpr unsigned int mmDCP0_DENORM_CONTROL__VI = 0x1A50; +constexpr unsigned int mmDCP0_GAMUT_REMAP_C11_C12__VI = 0x1A5A; +constexpr unsigned int mmDCP0_GAMUT_REMAP_C13_C14__VI = 0x1A5B; +constexpr unsigned int mmDCP0_GAMUT_REMAP_C21_C22__VI = 0x1A5C; +constexpr unsigned int mmDCP0_GAMUT_REMAP_C23_C24__VI = 0x1A5D; +constexpr unsigned int mmDCP0_GAMUT_REMAP_C31_C32__VI = 0x1A5E; +constexpr unsigned int mmDCP0_GAMUT_REMAP_C33_C34__VI = 0x1A5F; +constexpr unsigned int mmDCP0_GAMUT_REMAP_CONTROL__VI = 0x1A59; +constexpr unsigned int mmDCP0_GRPH_FLIP_RATE_CNTL__VI = 0x1A8E; +constexpr unsigned int mmDCP0_GRPH_STEREOSYNC_FLIP__VI = 0x1A97; +constexpr unsigned int mmDCP0_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x1A9F; +constexpr unsigned int mmDCP0_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x1ABF; +constexpr unsigned int mmDCP0_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x1ABD; +constexpr unsigned int mmDCP0_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x1ABE; +constexpr unsigned int mmDCP0_HW_ROTATION__VI = 0x1A9E; +constexpr unsigned int mmDCP0_INPUT_CSC_C11_C12__VI = 0x1A36; +constexpr unsigned int mmDCP0_INPUT_CSC_C13_C14__VI = 0x1A37; +constexpr unsigned int mmDCP0_INPUT_CSC_C21_C22__VI = 0x1A38; +constexpr unsigned int mmDCP0_INPUT_CSC_C23_C24__VI = 0x1A39; +constexpr unsigned int mmDCP0_INPUT_CSC_C31_C32__VI = 0x1A3A; +constexpr unsigned int mmDCP0_INPUT_CSC_C33_C34__VI = 0x1A3B; +constexpr unsigned int mmDCP0_INPUT_CSC_CONTROL__VI = 0x1A35; +constexpr unsigned int mmDCP0_INPUT_GAMMA_CONTROL__VI = 0x1A10; +constexpr unsigned int mmDCP0_KEY_CONTROL__VI = 0x1A53; +constexpr unsigned int mmDCP0_KEY_RANGE_ALPHA__VI = 0x1A54; +constexpr unsigned int mmDCP0_KEY_RANGE_BLUE__VI = 0x1A57; +constexpr unsigned int mmDCP0_KEY_RANGE_GREEN__VI = 0x1A56; +constexpr unsigned int mmDCP0_KEY_RANGE_RED__VI = 0x1A55; +constexpr unsigned int mmDCP0_OUTPUT_CSC_C11_C12__VI = 0x1A3D; +constexpr unsigned int mmDCP0_OUTPUT_CSC_C13_C14__VI = 0x1A3E; +constexpr unsigned int mmDCP0_OUTPUT_CSC_C21_C22__VI = 0x1A3F; +constexpr unsigned int mmDCP0_OUTPUT_CSC_C23_C24__VI = 0x1A40; +constexpr unsigned int mmDCP0_OUTPUT_CSC_C31_C32__VI = 0x1A41; +constexpr unsigned int mmDCP0_OUTPUT_CSC_C33_C34__VI = 0x1A42; +constexpr unsigned int mmDCP0_OUTPUT_CSC_CONTROL__VI = 0x1A3C; +constexpr unsigned int mmDCP0_OUT_CLAMP_CONTROL_B_CB__VI = 0x1A9D; +constexpr unsigned int mmDCP0_OUT_CLAMP_CONTROL_G_Y__VI = 0x1A9C; +constexpr unsigned int mmDCP0_OUT_CLAMP_CONTROL_R_CR__VI = 0x1A52; +constexpr unsigned int mmDCP0_OUT_ROUND_CONTROL__VI = 0x1A51; +constexpr unsigned int mmDCP0_OVL_SECONDARY_SURFACE_ADDRESS__VI = 0x1A92; +constexpr unsigned int mmDCP0_OVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x1A94; +constexpr unsigned int mmDCP0_OVL_STEREOSYNC_FLIP__VI = 0x1A93; +constexpr unsigned int mmDCP0_PRESCALE_GRPH_CONTROL__VI = 0x1A2D; +constexpr unsigned int mmDCP0_PRESCALE_OVL_CONTROL__VI = 0x1A31; +constexpr unsigned int mmDCP0_PRESCALE_VALUES_GRPH_B__VI = 0x1A30; +constexpr unsigned int mmDCP0_PRESCALE_VALUES_GRPH_G__VI = 0x1A2F; +constexpr unsigned int mmDCP0_PRESCALE_VALUES_GRPH_R__VI = 0x1A2E; +constexpr unsigned int mmDCP0_PRESCALE_VALUES_OVL_CB__VI = 0x1A32; +constexpr unsigned int mmDCP0_PRESCALE_VALUES_OVL_CR__VI = 0x1A34; +constexpr unsigned int mmDCP0_PRESCALE_VALUES_OVL_Y__VI = 0x1A33; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_END_CNTL1__VI = 0x1AA6; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_END_CNTL2__VI = 0x1AA7; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_0_1__VI = 0x1AA8; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_10_11__VI = 0x1AAD; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_12_13__VI = 0x1AAE; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_14_15__VI = 0x1AAF; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_2_3__VI = 0x1AA9; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_4_5__VI = 0x1AAA; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_6_7__VI = 0x1AAB; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_REGION_8_9__VI = 0x1AAC; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_SLOPE_CNTL__VI = 0x1AA5; +constexpr unsigned int mmDCP0_REGAMMA_CNTLA_START_CNTL__VI = 0x1AA4; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_END_CNTL1__VI = 0x1AB2; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_END_CNTL2__VI = 0x1AB3; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_0_1__VI = 0x1AB4; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_10_11__VI = 0x1AB9; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_12_13__VI = 0x1ABA; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_14_15__VI = 0x1ABB; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_2_3__VI = 0x1AB5; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_4_5__VI = 0x1AB6; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_6_7__VI = 0x1AB7; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_REGION_8_9__VI = 0x1AB8; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_SLOPE_CNTL__VI = 0x1AB1; +constexpr unsigned int mmDCP0_REGAMMA_CNTLB_START_CNTL__VI = 0x1AB0; +constexpr unsigned int mmDCP0_REGAMMA_CONTROL__VI = 0x1AA0; +constexpr unsigned int mmDCP0_REGAMMA_LUT_DATA__VI = 0x1AA2; +constexpr unsigned int mmDCP0_REGAMMA_LUT_INDEX__VI = 0x1AA1; +constexpr unsigned int mmDCP0_REGAMMA_LUT_WRITE_EN_MASK__VI = 0x1AA3; +constexpr unsigned int mmDCP1_ALPHA_CONTROL__VI = 0x1CBC; +constexpr unsigned int mmDCP1_COMM_MATRIXA_TRANS_C11_C12__VI = 0x1C43; +constexpr unsigned int mmDCP1_COMM_MATRIXA_TRANS_C13_C14__VI = 0x1C44; +constexpr unsigned int mmDCP1_COMM_MATRIXA_TRANS_C21_C22__VI = 0x1C45; +constexpr unsigned int mmDCP1_COMM_MATRIXA_TRANS_C23_C24__VI = 0x1C46; +constexpr unsigned int mmDCP1_COMM_MATRIXA_TRANS_C31_C32__VI = 0x1C47; +constexpr unsigned int mmDCP1_COMM_MATRIXA_TRANS_C33_C34__VI = 0x1C48; +constexpr unsigned int mmDCP1_COMM_MATRIXB_TRANS_C11_C12__VI = 0x1C49; +constexpr unsigned int mmDCP1_COMM_MATRIXB_TRANS_C13_C14__VI = 0x1C4A; +constexpr unsigned int mmDCP1_COMM_MATRIXB_TRANS_C21_C22__VI = 0x1C4B; +constexpr unsigned int mmDCP1_COMM_MATRIXB_TRANS_C23_C24__VI = 0x1C4C; +constexpr unsigned int mmDCP1_COMM_MATRIXB_TRANS_C31_C32__VI = 0x1C4D; +constexpr unsigned int mmDCP1_COMM_MATRIXB_TRANS_C33_C34__VI = 0x1C4E; +constexpr unsigned int mmDCP1_CUR2_COLOR1__VI = 0x1C75; +constexpr unsigned int mmDCP1_CUR2_COLOR2__VI = 0x1C76; +constexpr unsigned int mmDCP1_CUR2_CONTROL__VI = 0x1C6F; +constexpr unsigned int mmDCP1_CUR2_HOT_SPOT__VI = 0x1C74; +constexpr unsigned int mmDCP1_CUR2_POSITION__VI = 0x1C73; +constexpr unsigned int mmDCP1_CUR2_SIZE__VI = 0x1C71; +constexpr unsigned int mmDCP1_CUR2_STEREO_CONTROL__VI = 0x1C9B; +constexpr unsigned int mmDCP1_CUR2_SURFACE_ADDRESS__VI = 0x1C70; +constexpr unsigned int mmDCP1_CUR2_SURFACE_ADDRESS_HIGH__VI = 0x1C72; +constexpr unsigned int mmDCP1_CUR2_UPDATE__VI = 0x1C77; +constexpr unsigned int mmDCP1_CUR_COLOR1__VI = 0x1C6C; +constexpr unsigned int mmDCP1_CUR_COLOR2__VI = 0x1C6D; +constexpr unsigned int mmDCP1_CUR_CONTROL__VI = 0x1C66; +constexpr unsigned int mmDCP1_CUR_HOT_SPOT__VI = 0x1C6B; +constexpr unsigned int mmDCP1_CUR_POSITION__VI = 0x1C6A; +constexpr unsigned int mmDCP1_CUR_REQUEST_FILTER_CNTL__VI = 0x1C99; +constexpr unsigned int mmDCP1_CUR_SIZE__VI = 0x1C68; +constexpr unsigned int mmDCP1_CUR_STEREO_CONTROL__VI = 0x1C9A; +constexpr unsigned int mmDCP1_CUR_SURFACE_ADDRESS__VI = 0x1C67; +constexpr unsigned int mmDCP1_CUR_SURFACE_ADDRESS_HIGH__VI = 0x1C69; +constexpr unsigned int mmDCP1_CUR_UPDATE__VI = 0x1C6E; +constexpr unsigned int mmDCP1_DCP_CRC_CONTROL__VI = 0x1C87; +constexpr unsigned int mmDCP1_DCP_CRC_CURRENT__VI = 0x1C89; +constexpr unsigned int mmDCP1_DCP_CRC_LAST__VI = 0x1C8B; +constexpr unsigned int mmDCP1_DCP_CRC_MASK__VI = 0x1C88; +constexpr unsigned int mmDCP1_DCP_DEBUG__VI = 0x1C8D; +constexpr unsigned int mmDCP1_DCP_DEBUG2__VI = 0x1C98; +constexpr unsigned int mmDCP1_DCP_FP_CONVERTED_FIELD__VI = 0x1C65; +constexpr unsigned int mmDCP1_DCP_GSL_CONTROL__VI = 0x1C90; +constexpr unsigned int mmDCP1_DCP_LB_DATA_GAP_BETWEEN_CHUNK__VI = 0x1C91; +constexpr unsigned int mmDCP1_DCP_RANDOM_SEEDS__VI = 0x1C61; +constexpr unsigned int mmDCP1_DCP_SPATIAL_DITHER_CNTL__VI = 0x1C60; +constexpr unsigned int mmDCP1_DCP_TEST_DEBUG_DATA__VI = 0x1C96; +constexpr unsigned int mmDCP1_DCP_TEST_DEBUG_INDEX__VI = 0x1C95; +constexpr unsigned int mmDCP1_DC_LUT_30_COLOR__VI = 0x1C7C; +constexpr unsigned int mmDCP1_DC_LUT_AUTOFILL__VI = 0x1C7F; +constexpr unsigned int mmDCP1_DC_LUT_BLACK_OFFSET_BLUE__VI = 0x1C81; +constexpr unsigned int mmDCP1_DC_LUT_BLACK_OFFSET_GREEN__VI = 0x1C82; +constexpr unsigned int mmDCP1_DC_LUT_BLACK_OFFSET_RED__VI = 0x1C83; +constexpr unsigned int mmDCP1_DC_LUT_CONTROL__VI = 0x1C80; +constexpr unsigned int mmDCP1_DC_LUT_PWL_DATA__VI = 0x1C7B; +constexpr unsigned int mmDCP1_DC_LUT_RW_INDEX__VI = 0x1C79; +constexpr unsigned int mmDCP1_DC_LUT_RW_MODE__VI = 0x1C78; +constexpr unsigned int mmDCP1_DC_LUT_SEQ_COLOR__VI = 0x1C7A; +constexpr unsigned int mmDCP1_DC_LUT_VGA_ACCESS_ENABLE__VI = 0x1C7D; +constexpr unsigned int mmDCP1_DC_LUT_WHITE_OFFSET_BLUE__VI = 0x1C84; +constexpr unsigned int mmDCP1_DC_LUT_WHITE_OFFSET_GREEN__VI = 0x1C85; +constexpr unsigned int mmDCP1_DC_LUT_WHITE_OFFSET_RED__VI = 0x1C86; +constexpr unsigned int mmDCP1_DC_LUT_WRITE_EN_MASK__VI = 0x1C7E; +constexpr unsigned int mmDCP1_DEGAMMA_CONTROL__VI = 0x1C58; +constexpr unsigned int mmDCP1_DENORM_CONTROL__VI = 0x1C50; +constexpr unsigned int mmDCP1_GAMUT_REMAP_C11_C12__VI = 0x1C5A; +constexpr unsigned int mmDCP1_GAMUT_REMAP_C13_C14__VI = 0x1C5B; +constexpr unsigned int mmDCP1_GAMUT_REMAP_C21_C22__VI = 0x1C5C; +constexpr unsigned int mmDCP1_GAMUT_REMAP_C23_C24__VI = 0x1C5D; +constexpr unsigned int mmDCP1_GAMUT_REMAP_C31_C32__VI = 0x1C5E; +constexpr unsigned int mmDCP1_GAMUT_REMAP_C33_C34__VI = 0x1C5F; +constexpr unsigned int mmDCP1_GAMUT_REMAP_CONTROL__VI = 0x1C59; +constexpr unsigned int mmDCP1_GRPH_COMPRESS_PITCH__VI = 0x1C1A; +constexpr unsigned int mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS__VI = 0x1C19; +constexpr unsigned int mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__VI = 0x1C1B; +constexpr unsigned int mmDCP1_GRPH_CONTROL__SI__CI = 0x1D01; +constexpr unsigned int mmDCP1_GRPH_CONTROL__VI = 0x1C01; +constexpr unsigned int mmDCP1_GRPH_DFQ_CONTROL__VI = 0x1C14; +constexpr unsigned int mmDCP1_GRPH_DFQ_STATUS__VI = 0x1C15; +constexpr unsigned int mmDCP1_GRPH_ENABLE__VI = 0x1C00; +constexpr unsigned int mmDCP1_GRPH_FLIP_CONTROL__SI__CI = 0x1D12; +constexpr unsigned int mmDCP1_GRPH_FLIP_CONTROL__VI = 0x1C12; +constexpr unsigned int mmDCP1_GRPH_FLIP_RATE_CNTL__VI = 0x1C8E; +constexpr unsigned int mmDCP1_GRPH_INTERRUPT_CONTROL__VI = 0x1C17; +constexpr unsigned int mmDCP1_GRPH_INTERRUPT_STATUS__VI = 0x1C16; +constexpr unsigned int mmDCP1_GRPH_LUT_10BIT_BYPASS__VI = 0x1C02; +constexpr unsigned int mmDCP1_GRPH_PITCH__SI__CI = 0x1D06; +constexpr unsigned int mmDCP1_GRPH_PITCH__VI = 0x1C06; +constexpr unsigned int mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS__SI__CI = 0x1D04; +constexpr unsigned int mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS__VI = 0x1C04; +constexpr unsigned int mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__VI = 0x1C07; +constexpr unsigned int mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS__VI = 0x1C05; +constexpr unsigned int mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x1C08; +constexpr unsigned int mmDCP1_GRPH_STEREOSYNC_FLIP__VI = 0x1C97; +constexpr unsigned int mmDCP1_GRPH_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x1C18; +constexpr unsigned int mmDCP1_GRPH_SURFACE_ADDRESS_INUSE__VI = 0x1C13; +constexpr unsigned int mmDCP1_GRPH_SURFACE_OFFSET_X__VI = 0x1C09; +constexpr unsigned int mmDCP1_GRPH_SURFACE_OFFSET_Y__VI = 0x1C0A; +constexpr unsigned int mmDCP1_GRPH_SWAP_CNTL__VI = 0x1C03; +constexpr unsigned int mmDCP1_GRPH_UPDATE__SI__CI = 0x1D11; +constexpr unsigned int mmDCP1_GRPH_UPDATE__VI = 0x1C11; +constexpr unsigned int mmDCP1_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x1C9F; +constexpr unsigned int mmDCP1_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x1CBF; +constexpr unsigned int mmDCP1_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x1CBD; +constexpr unsigned int mmDCP1_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x1CBE; +constexpr unsigned int mmDCP1_GRPH_X_END__VI = 0x1C0D; +constexpr unsigned int mmDCP1_GRPH_X_START__VI = 0x1C0B; +constexpr unsigned int mmDCP1_GRPH_Y_END__VI = 0x1C0E; +constexpr unsigned int mmDCP1_GRPH_Y_START__VI = 0x1C0C; +constexpr unsigned int mmDCP1_HW_ROTATION__VI = 0x1C9E; +constexpr unsigned int mmDCP1_INPUT_CSC_C11_C12__VI = 0x1C36; +constexpr unsigned int mmDCP1_INPUT_CSC_C13_C14__VI = 0x1C37; +constexpr unsigned int mmDCP1_INPUT_CSC_C21_C22__VI = 0x1C38; +constexpr unsigned int mmDCP1_INPUT_CSC_C23_C24__VI = 0x1C39; +constexpr unsigned int mmDCP1_INPUT_CSC_C31_C32__VI = 0x1C3A; +constexpr unsigned int mmDCP1_INPUT_CSC_C33_C34__VI = 0x1C3B; +constexpr unsigned int mmDCP1_INPUT_CSC_CONTROL__VI = 0x1C35; +constexpr unsigned int mmDCP1_INPUT_GAMMA_CONTROL__VI = 0x1C10; +constexpr unsigned int mmDCP1_KEY_CONTROL__VI = 0x1C53; +constexpr unsigned int mmDCP1_KEY_RANGE_ALPHA__VI = 0x1C54; +constexpr unsigned int mmDCP1_KEY_RANGE_BLUE__VI = 0x1C57; +constexpr unsigned int mmDCP1_KEY_RANGE_GREEN__VI = 0x1C56; +constexpr unsigned int mmDCP1_KEY_RANGE_RED__VI = 0x1C55; +constexpr unsigned int mmDCP1_OUTPUT_CSC_C11_C12__VI = 0x1C3D; +constexpr unsigned int mmDCP1_OUTPUT_CSC_C13_C14__VI = 0x1C3E; +constexpr unsigned int mmDCP1_OUTPUT_CSC_C21_C22__VI = 0x1C3F; +constexpr unsigned int mmDCP1_OUTPUT_CSC_C23_C24__VI = 0x1C40; +constexpr unsigned int mmDCP1_OUTPUT_CSC_C31_C32__VI = 0x1C41; +constexpr unsigned int mmDCP1_OUTPUT_CSC_C33_C34__VI = 0x1C42; +constexpr unsigned int mmDCP1_OUTPUT_CSC_CONTROL__VI = 0x1C3C; +constexpr unsigned int mmDCP1_OUT_CLAMP_CONTROL_B_CB__VI = 0x1C9D; +constexpr unsigned int mmDCP1_OUT_CLAMP_CONTROL_G_Y__VI = 0x1C9C; +constexpr unsigned int mmDCP1_OUT_CLAMP_CONTROL_R_CR__VI = 0x1C52; +constexpr unsigned int mmDCP1_OUT_ROUND_CONTROL__VI = 0x1C51; +constexpr unsigned int mmDCP1_OVLSCL_EDGE_PIXEL_CNTL__VI = 0x1C2C; +constexpr unsigned int mmDCP1_OVL_CONTROL1__VI = 0x1C1D; +constexpr unsigned int mmDCP1_OVL_CONTROL2__VI = 0x1C1E; +constexpr unsigned int mmDCP1_OVL_DFQ_CONTROL__VI = 0x1C29; +constexpr unsigned int mmDCP1_OVL_DFQ_STATUS__VI = 0x1C2A; +constexpr unsigned int mmDCP1_OVL_ENABLE__VI = 0x1C1C; +constexpr unsigned int mmDCP1_OVL_END__VI = 0x1C26; +constexpr unsigned int mmDCP1_OVL_PITCH__VI = 0x1C21; +constexpr unsigned int mmDCP1_OVL_SECONDARY_SURFACE_ADDRESS__VI = 0x1C92; +constexpr unsigned int mmDCP1_OVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x1C94; +constexpr unsigned int mmDCP1_OVL_START__VI = 0x1C25; +constexpr unsigned int mmDCP1_OVL_STEREOSYNC_FLIP__VI = 0x1C93; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS__SI__CI = 0x1D20; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS__VI = 0x1C20; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS_HIGH__VI = 0x1C22; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x1C2B; +constexpr unsigned int mmDCP1_OVL_SURFACE_ADDRESS_INUSE__VI = 0x1C28; +constexpr unsigned int mmDCP1_OVL_SURFACE_OFFSET_X__VI = 0x1C23; +constexpr unsigned int mmDCP1_OVL_SURFACE_OFFSET_Y__VI = 0x1C24; +constexpr unsigned int mmDCP1_OVL_SWAP_CNTL__VI = 0x1C1F; +constexpr unsigned int mmDCP1_OVL_UPDATE__VI = 0x1C27; +constexpr unsigned int mmDCP1_PRESCALE_GRPH_CONTROL__VI = 0x1C2D; +constexpr unsigned int mmDCP1_PRESCALE_OVL_CONTROL__VI = 0x1C31; +constexpr unsigned int mmDCP1_PRESCALE_VALUES_GRPH_B__VI = 0x1C30; +constexpr unsigned int mmDCP1_PRESCALE_VALUES_GRPH_G__VI = 0x1C2F; +constexpr unsigned int mmDCP1_PRESCALE_VALUES_GRPH_R__VI = 0x1C2E; +constexpr unsigned int mmDCP1_PRESCALE_VALUES_OVL_CB__VI = 0x1C32; +constexpr unsigned int mmDCP1_PRESCALE_VALUES_OVL_CR__VI = 0x1C34; +constexpr unsigned int mmDCP1_PRESCALE_VALUES_OVL_Y__VI = 0x1C33; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_END_CNTL1__VI = 0x1CA6; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_END_CNTL2__VI = 0x1CA7; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_0_1__VI = 0x1CA8; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_10_11__VI = 0x1CAD; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_12_13__VI = 0x1CAE; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_14_15__VI = 0x1CAF; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_2_3__VI = 0x1CA9; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_4_5__VI = 0x1CAA; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_6_7__VI = 0x1CAB; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_REGION_8_9__VI = 0x1CAC; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_SLOPE_CNTL__VI = 0x1CA5; +constexpr unsigned int mmDCP1_REGAMMA_CNTLA_START_CNTL__VI = 0x1CA4; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_END_CNTL1__VI = 0x1CB2; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_END_CNTL2__VI = 0x1CB3; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_0_1__VI = 0x1CB4; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_10_11__VI = 0x1CB9; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_12_13__VI = 0x1CBA; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_14_15__VI = 0x1CBB; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_2_3__VI = 0x1CB5; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_4_5__VI = 0x1CB6; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_6_7__VI = 0x1CB7; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_REGION_8_9__VI = 0x1CB8; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_SLOPE_CNTL__VI = 0x1CB1; +constexpr unsigned int mmDCP1_REGAMMA_CNTLB_START_CNTL__VI = 0x1CB0; +constexpr unsigned int mmDCP1_REGAMMA_CONTROL__VI = 0x1CA0; +constexpr unsigned int mmDCP1_REGAMMA_LUT_DATA__VI = 0x1CA2; +constexpr unsigned int mmDCP1_REGAMMA_LUT_INDEX__VI = 0x1CA1; +constexpr unsigned int mmDCP1_REGAMMA_LUT_WRITE_EN_MASK__VI = 0x1CA3; +constexpr unsigned int mmDCP2_ALPHA_CONTROL__VI = 0x1EBC; +constexpr unsigned int mmDCP2_COMM_MATRIXA_TRANS_C11_C12__VI = 0x1E43; +constexpr unsigned int mmDCP2_COMM_MATRIXA_TRANS_C13_C14__VI = 0x1E44; +constexpr unsigned int mmDCP2_COMM_MATRIXA_TRANS_C21_C22__VI = 0x1E45; +constexpr unsigned int mmDCP2_COMM_MATRIXA_TRANS_C23_C24__VI = 0x1E46; +constexpr unsigned int mmDCP2_COMM_MATRIXA_TRANS_C31_C32__VI = 0x1E47; +constexpr unsigned int mmDCP2_COMM_MATRIXA_TRANS_C33_C34__VI = 0x1E48; +constexpr unsigned int mmDCP2_COMM_MATRIXB_TRANS_C11_C12__VI = 0x1E49; +constexpr unsigned int mmDCP2_COMM_MATRIXB_TRANS_C13_C14__VI = 0x1E4A; +constexpr unsigned int mmDCP2_COMM_MATRIXB_TRANS_C21_C22__VI = 0x1E4B; +constexpr unsigned int mmDCP2_COMM_MATRIXB_TRANS_C23_C24__VI = 0x1E4C; +constexpr unsigned int mmDCP2_COMM_MATRIXB_TRANS_C31_C32__VI = 0x1E4D; +constexpr unsigned int mmDCP2_COMM_MATRIXB_TRANS_C33_C34__VI = 0x1E4E; +constexpr unsigned int mmDCP2_CUR2_COLOR1__VI = 0x1E75; +constexpr unsigned int mmDCP2_CUR2_COLOR2__VI = 0x1E76; +constexpr unsigned int mmDCP2_CUR2_CONTROL__VI = 0x1E6F; +constexpr unsigned int mmDCP2_CUR2_HOT_SPOT__VI = 0x1E74; +constexpr unsigned int mmDCP2_CUR2_POSITION__VI = 0x1E73; +constexpr unsigned int mmDCP2_CUR2_SIZE__VI = 0x1E71; +constexpr unsigned int mmDCP2_CUR2_STEREO_CONTROL__VI = 0x1E9B; +constexpr unsigned int mmDCP2_CUR2_SURFACE_ADDRESS__VI = 0x1E70; +constexpr unsigned int mmDCP2_CUR2_SURFACE_ADDRESS_HIGH__VI = 0x1E72; +constexpr unsigned int mmDCP2_CUR2_UPDATE__VI = 0x1E77; +constexpr unsigned int mmDCP2_CUR_COLOR1__VI = 0x1E6C; +constexpr unsigned int mmDCP2_CUR_COLOR2__VI = 0x1E6D; +constexpr unsigned int mmDCP2_CUR_CONTROL__VI = 0x1E66; +constexpr unsigned int mmDCP2_CUR_HOT_SPOT__VI = 0x1E6B; +constexpr unsigned int mmDCP2_CUR_POSITION__VI = 0x1E6A; +constexpr unsigned int mmDCP2_CUR_REQUEST_FILTER_CNTL__VI = 0x1E99; +constexpr unsigned int mmDCP2_CUR_SIZE__VI = 0x1E68; +constexpr unsigned int mmDCP2_CUR_STEREO_CONTROL__VI = 0x1E9A; +constexpr unsigned int mmDCP2_CUR_SURFACE_ADDRESS__VI = 0x1E67; +constexpr unsigned int mmDCP2_CUR_SURFACE_ADDRESS_HIGH__VI = 0x1E69; +constexpr unsigned int mmDCP2_CUR_UPDATE__VI = 0x1E6E; +constexpr unsigned int mmDCP2_DCP_CRC_CONTROL__VI = 0x1E87; +constexpr unsigned int mmDCP2_DCP_CRC_CURRENT__VI = 0x1E89; +constexpr unsigned int mmDCP2_DCP_CRC_LAST__VI = 0x1E8B; +constexpr unsigned int mmDCP2_DCP_CRC_MASK__VI = 0x1E88; +constexpr unsigned int mmDCP2_DCP_DEBUG__VI = 0x1E8D; +constexpr unsigned int mmDCP2_DCP_DEBUG2__VI = 0x1E98; +constexpr unsigned int mmDCP2_DCP_FP_CONVERTED_FIELD__VI = 0x1E65; +constexpr unsigned int mmDCP2_DCP_GSL_CONTROL__VI = 0x1E90; +constexpr unsigned int mmDCP2_DCP_LB_DATA_GAP_BETWEEN_CHUNK__VI = 0x1E91; +constexpr unsigned int mmDCP2_DCP_RANDOM_SEEDS__VI = 0x1E61; +constexpr unsigned int mmDCP2_DCP_SPATIAL_DITHER_CNTL__VI = 0x1E60; +constexpr unsigned int mmDCP2_DCP_TEST_DEBUG_DATA__VI = 0x1E96; +constexpr unsigned int mmDCP2_DCP_TEST_DEBUG_INDEX__VI = 0x1E95; +constexpr unsigned int mmDCP2_DC_LUT_30_COLOR__VI = 0x1E7C; +constexpr unsigned int mmDCP2_DC_LUT_AUTOFILL__VI = 0x1E7F; +constexpr unsigned int mmDCP2_DC_LUT_BLACK_OFFSET_BLUE__VI = 0x1E81; +constexpr unsigned int mmDCP2_DC_LUT_BLACK_OFFSET_GREEN__VI = 0x1E82; +constexpr unsigned int mmDCP2_DC_LUT_BLACK_OFFSET_RED__VI = 0x1E83; +constexpr unsigned int mmDCP2_DC_LUT_CONTROL__VI = 0x1E80; +constexpr unsigned int mmDCP2_DC_LUT_PWL_DATA__VI = 0x1E7B; +constexpr unsigned int mmDCP2_DC_LUT_RW_INDEX__VI = 0x1E79; +constexpr unsigned int mmDCP2_DC_LUT_RW_MODE__VI = 0x1E78; +constexpr unsigned int mmDCP2_DC_LUT_SEQ_COLOR__VI = 0x1E7A; +constexpr unsigned int mmDCP2_DC_LUT_VGA_ACCESS_ENABLE__VI = 0x1E7D; +constexpr unsigned int mmDCP2_DC_LUT_WHITE_OFFSET_BLUE__VI = 0x1E84; +constexpr unsigned int mmDCP2_DC_LUT_WHITE_OFFSET_GREEN__VI = 0x1E85; +constexpr unsigned int mmDCP2_DC_LUT_WHITE_OFFSET_RED__VI = 0x1E86; +constexpr unsigned int mmDCP2_DC_LUT_WRITE_EN_MASK__VI = 0x1E7E; +constexpr unsigned int mmDCP2_DEGAMMA_CONTROL__VI = 0x1E58; +constexpr unsigned int mmDCP2_DENORM_CONTROL__VI = 0x1E50; +constexpr unsigned int mmDCP2_GAMUT_REMAP_C11_C12__VI = 0x1E5A; +constexpr unsigned int mmDCP2_GAMUT_REMAP_C13_C14__VI = 0x1E5B; +constexpr unsigned int mmDCP2_GAMUT_REMAP_C21_C22__VI = 0x1E5C; +constexpr unsigned int mmDCP2_GAMUT_REMAP_C23_C24__VI = 0x1E5D; +constexpr unsigned int mmDCP2_GAMUT_REMAP_C31_C32__VI = 0x1E5E; +constexpr unsigned int mmDCP2_GAMUT_REMAP_C33_C34__VI = 0x1E5F; +constexpr unsigned int mmDCP2_GAMUT_REMAP_CONTROL__VI = 0x1E59; +constexpr unsigned int mmDCP2_GRPH_COMPRESS_PITCH__VI = 0x1E1A; +constexpr unsigned int mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS__VI = 0x1E19; +constexpr unsigned int mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__VI = 0x1E1B; +constexpr unsigned int mmDCP2_GRPH_CONTROL__SI__CI = 0x4001; +constexpr unsigned int mmDCP2_GRPH_CONTROL__VI = 0x1E01; +constexpr unsigned int mmDCP2_GRPH_DFQ_CONTROL__VI = 0x1E14; +constexpr unsigned int mmDCP2_GRPH_DFQ_STATUS__VI = 0x1E15; +constexpr unsigned int mmDCP2_GRPH_ENABLE__VI = 0x1E00; +constexpr unsigned int mmDCP2_GRPH_FLIP_CONTROL__SI__CI = 0x4012; +constexpr unsigned int mmDCP2_GRPH_FLIP_CONTROL__VI = 0x1E12; +constexpr unsigned int mmDCP2_GRPH_FLIP_RATE_CNTL__VI = 0x1E8E; +constexpr unsigned int mmDCP2_GRPH_INTERRUPT_CONTROL__VI = 0x1E17; +constexpr unsigned int mmDCP2_GRPH_INTERRUPT_STATUS__VI = 0x1E16; +constexpr unsigned int mmDCP2_GRPH_LUT_10BIT_BYPASS__VI = 0x1E02; +constexpr unsigned int mmDCP2_GRPH_PITCH__SI__CI = 0x4006; +constexpr unsigned int mmDCP2_GRPH_PITCH__VI = 0x1E06; +constexpr unsigned int mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS__SI__CI = 0x4004; +constexpr unsigned int mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS__VI = 0x1E04; +constexpr unsigned int mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__VI = 0x1E07; +constexpr unsigned int mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS__VI = 0x1E05; +constexpr unsigned int mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x1E08; +constexpr unsigned int mmDCP2_GRPH_STEREOSYNC_FLIP__VI = 0x1E97; +constexpr unsigned int mmDCP2_GRPH_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x1E18; +constexpr unsigned int mmDCP2_GRPH_SURFACE_ADDRESS_INUSE__VI = 0x1E13; +constexpr unsigned int mmDCP2_GRPH_SURFACE_OFFSET_X__VI = 0x1E09; +constexpr unsigned int mmDCP2_GRPH_SURFACE_OFFSET_Y__VI = 0x1E0A; +constexpr unsigned int mmDCP2_GRPH_SWAP_CNTL__VI = 0x1E03; +constexpr unsigned int mmDCP2_GRPH_UPDATE__SI__CI = 0x4011; +constexpr unsigned int mmDCP2_GRPH_UPDATE__VI = 0x1E11; +constexpr unsigned int mmDCP2_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x1E9F; +constexpr unsigned int mmDCP2_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x1EBF; +constexpr unsigned int mmDCP2_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x1EBD; +constexpr unsigned int mmDCP2_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x1EBE; +constexpr unsigned int mmDCP2_GRPH_X_END__VI = 0x1E0D; +constexpr unsigned int mmDCP2_GRPH_X_START__VI = 0x1E0B; +constexpr unsigned int mmDCP2_GRPH_Y_END__VI = 0x1E0E; +constexpr unsigned int mmDCP2_GRPH_Y_START__VI = 0x1E0C; +constexpr unsigned int mmDCP2_HW_ROTATION__VI = 0x1E9E; +constexpr unsigned int mmDCP2_INPUT_CSC_C11_C12__VI = 0x1E36; +constexpr unsigned int mmDCP2_INPUT_CSC_C13_C14__VI = 0x1E37; +constexpr unsigned int mmDCP2_INPUT_CSC_C21_C22__VI = 0x1E38; +constexpr unsigned int mmDCP2_INPUT_CSC_C23_C24__VI = 0x1E39; +constexpr unsigned int mmDCP2_INPUT_CSC_C31_C32__VI = 0x1E3A; +constexpr unsigned int mmDCP2_INPUT_CSC_C33_C34__VI = 0x1E3B; +constexpr unsigned int mmDCP2_INPUT_CSC_CONTROL__VI = 0x1E35; +constexpr unsigned int mmDCP2_INPUT_GAMMA_CONTROL__VI = 0x1E10; +constexpr unsigned int mmDCP2_KEY_CONTROL__VI = 0x1E53; +constexpr unsigned int mmDCP2_KEY_RANGE_ALPHA__VI = 0x1E54; +constexpr unsigned int mmDCP2_KEY_RANGE_BLUE__VI = 0x1E57; +constexpr unsigned int mmDCP2_KEY_RANGE_GREEN__VI = 0x1E56; +constexpr unsigned int mmDCP2_KEY_RANGE_RED__VI = 0x1E55; +constexpr unsigned int mmDCP2_OUTPUT_CSC_C11_C12__VI = 0x1E3D; +constexpr unsigned int mmDCP2_OUTPUT_CSC_C13_C14__VI = 0x1E3E; +constexpr unsigned int mmDCP2_OUTPUT_CSC_C21_C22__VI = 0x1E3F; +constexpr unsigned int mmDCP2_OUTPUT_CSC_C23_C24__VI = 0x1E40; +constexpr unsigned int mmDCP2_OUTPUT_CSC_C31_C32__VI = 0x1E41; +constexpr unsigned int mmDCP2_OUTPUT_CSC_C33_C34__VI = 0x1E42; +constexpr unsigned int mmDCP2_OUTPUT_CSC_CONTROL__VI = 0x1E3C; +constexpr unsigned int mmDCP2_OUT_CLAMP_CONTROL_B_CB__VI = 0x1E9D; +constexpr unsigned int mmDCP2_OUT_CLAMP_CONTROL_G_Y__VI = 0x1E9C; +constexpr unsigned int mmDCP2_OUT_CLAMP_CONTROL_R_CR__VI = 0x1E52; +constexpr unsigned int mmDCP2_OUT_ROUND_CONTROL__VI = 0x1E51; +constexpr unsigned int mmDCP2_OVLSCL_EDGE_PIXEL_CNTL__VI = 0x1E2C; +constexpr unsigned int mmDCP2_OVL_CONTROL1__VI = 0x1E1D; +constexpr unsigned int mmDCP2_OVL_CONTROL2__VI = 0x1E1E; +constexpr unsigned int mmDCP2_OVL_DFQ_CONTROL__VI = 0x1E29; +constexpr unsigned int mmDCP2_OVL_DFQ_STATUS__VI = 0x1E2A; +constexpr unsigned int mmDCP2_OVL_ENABLE__VI = 0x1E1C; +constexpr unsigned int mmDCP2_OVL_END__VI = 0x1E26; +constexpr unsigned int mmDCP2_OVL_PITCH__VI = 0x1E21; +constexpr unsigned int mmDCP2_OVL_SECONDARY_SURFACE_ADDRESS__VI = 0x1E92; +constexpr unsigned int mmDCP2_OVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x1E94; +constexpr unsigned int mmDCP2_OVL_START__VI = 0x1E25; +constexpr unsigned int mmDCP2_OVL_STEREOSYNC_FLIP__VI = 0x1E93; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS__SI__CI = 0x4020; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS__VI = 0x1E20; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS_HIGH__VI = 0x1E22; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x1E2B; +constexpr unsigned int mmDCP2_OVL_SURFACE_ADDRESS_INUSE__VI = 0x1E28; +constexpr unsigned int mmDCP2_OVL_SURFACE_OFFSET_X__VI = 0x1E23; +constexpr unsigned int mmDCP2_OVL_SURFACE_OFFSET_Y__VI = 0x1E24; +constexpr unsigned int mmDCP2_OVL_SWAP_CNTL__VI = 0x1E1F; +constexpr unsigned int mmDCP2_OVL_UPDATE__VI = 0x1E27; +constexpr unsigned int mmDCP2_PRESCALE_GRPH_CONTROL__VI = 0x1E2D; +constexpr unsigned int mmDCP2_PRESCALE_OVL_CONTROL__VI = 0x1E31; +constexpr unsigned int mmDCP2_PRESCALE_VALUES_GRPH_B__VI = 0x1E30; +constexpr unsigned int mmDCP2_PRESCALE_VALUES_GRPH_G__VI = 0x1E2F; +constexpr unsigned int mmDCP2_PRESCALE_VALUES_GRPH_R__VI = 0x1E2E; +constexpr unsigned int mmDCP2_PRESCALE_VALUES_OVL_CB__VI = 0x1E32; +constexpr unsigned int mmDCP2_PRESCALE_VALUES_OVL_CR__VI = 0x1E34; +constexpr unsigned int mmDCP2_PRESCALE_VALUES_OVL_Y__VI = 0x1E33; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_END_CNTL1__VI = 0x1EA6; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_END_CNTL2__VI = 0x1EA7; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_0_1__VI = 0x1EA8; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_10_11__VI = 0x1EAD; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_12_13__VI = 0x1EAE; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_14_15__VI = 0x1EAF; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_2_3__VI = 0x1EA9; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_4_5__VI = 0x1EAA; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_6_7__VI = 0x1EAB; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_REGION_8_9__VI = 0x1EAC; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_SLOPE_CNTL__VI = 0x1EA5; +constexpr unsigned int mmDCP2_REGAMMA_CNTLA_START_CNTL__VI = 0x1EA4; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_END_CNTL1__VI = 0x1EB2; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_END_CNTL2__VI = 0x1EB3; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_0_1__VI = 0x1EB4; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_10_11__VI = 0x1EB9; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_12_13__VI = 0x1EBA; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_14_15__VI = 0x1EBB; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_2_3__VI = 0x1EB5; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_4_5__VI = 0x1EB6; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_6_7__VI = 0x1EB7; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_REGION_8_9__VI = 0x1EB8; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_SLOPE_CNTL__VI = 0x1EB1; +constexpr unsigned int mmDCP2_REGAMMA_CNTLB_START_CNTL__VI = 0x1EB0; +constexpr unsigned int mmDCP2_REGAMMA_CONTROL__VI = 0x1EA0; +constexpr unsigned int mmDCP2_REGAMMA_LUT_DATA__VI = 0x1EA2; +constexpr unsigned int mmDCP2_REGAMMA_LUT_INDEX__VI = 0x1EA1; +constexpr unsigned int mmDCP2_REGAMMA_LUT_WRITE_EN_MASK__VI = 0x1EA3; +constexpr unsigned int mmDCP3_ALPHA_CONTROL__VI = 0x40BC; +constexpr unsigned int mmDCP3_COMM_MATRIXA_TRANS_C11_C12__VI = 0x4043; +constexpr unsigned int mmDCP3_COMM_MATRIXA_TRANS_C13_C14__VI = 0x4044; +constexpr unsigned int mmDCP3_COMM_MATRIXA_TRANS_C21_C22__VI = 0x4045; +constexpr unsigned int mmDCP3_COMM_MATRIXA_TRANS_C23_C24__VI = 0x4046; +constexpr unsigned int mmDCP3_COMM_MATRIXA_TRANS_C31_C32__VI = 0x4047; +constexpr unsigned int mmDCP3_COMM_MATRIXA_TRANS_C33_C34__VI = 0x4048; +constexpr unsigned int mmDCP3_COMM_MATRIXB_TRANS_C11_C12__VI = 0x4049; +constexpr unsigned int mmDCP3_COMM_MATRIXB_TRANS_C13_C14__VI = 0x404A; +constexpr unsigned int mmDCP3_COMM_MATRIXB_TRANS_C21_C22__VI = 0x404B; +constexpr unsigned int mmDCP3_COMM_MATRIXB_TRANS_C23_C24__VI = 0x404C; +constexpr unsigned int mmDCP3_COMM_MATRIXB_TRANS_C31_C32__VI = 0x404D; +constexpr unsigned int mmDCP3_COMM_MATRIXB_TRANS_C33_C34__VI = 0x404E; +constexpr unsigned int mmDCP3_CUR2_COLOR1__VI = 0x4075; +constexpr unsigned int mmDCP3_CUR2_COLOR2__VI = 0x4076; +constexpr unsigned int mmDCP3_CUR2_CONTROL__VI = 0x406F; +constexpr unsigned int mmDCP3_CUR2_HOT_SPOT__VI = 0x4074; +constexpr unsigned int mmDCP3_CUR2_POSITION__VI = 0x4073; +constexpr unsigned int mmDCP3_CUR2_SIZE__VI = 0x4071; +constexpr unsigned int mmDCP3_CUR2_STEREO_CONTROL__VI = 0x409B; +constexpr unsigned int mmDCP3_CUR2_SURFACE_ADDRESS__VI = 0x4070; +constexpr unsigned int mmDCP3_CUR2_SURFACE_ADDRESS_HIGH__VI = 0x4072; +constexpr unsigned int mmDCP3_CUR2_UPDATE__VI = 0x4077; +constexpr unsigned int mmDCP3_CUR_COLOR1__VI = 0x406C; +constexpr unsigned int mmDCP3_CUR_COLOR2__VI = 0x406D; +constexpr unsigned int mmDCP3_CUR_CONTROL__VI = 0x4066; +constexpr unsigned int mmDCP3_CUR_HOT_SPOT__VI = 0x406B; +constexpr unsigned int mmDCP3_CUR_POSITION__VI = 0x406A; +constexpr unsigned int mmDCP3_CUR_REQUEST_FILTER_CNTL__VI = 0x4099; +constexpr unsigned int mmDCP3_CUR_SIZE__VI = 0x4068; +constexpr unsigned int mmDCP3_CUR_STEREO_CONTROL__VI = 0x409A; +constexpr unsigned int mmDCP3_CUR_SURFACE_ADDRESS__VI = 0x4067; +constexpr unsigned int mmDCP3_CUR_SURFACE_ADDRESS_HIGH__VI = 0x4069; +constexpr unsigned int mmDCP3_CUR_UPDATE__VI = 0x406E; +constexpr unsigned int mmDCP3_DCP_CRC_CONTROL__VI = 0x4087; +constexpr unsigned int mmDCP3_DCP_CRC_CURRENT__VI = 0x4089; +constexpr unsigned int mmDCP3_DCP_CRC_LAST__VI = 0x408B; +constexpr unsigned int mmDCP3_DCP_CRC_MASK__VI = 0x4088; +constexpr unsigned int mmDCP3_DCP_DEBUG__VI = 0x408D; +constexpr unsigned int mmDCP3_DCP_DEBUG2__VI = 0x4098; +constexpr unsigned int mmDCP3_DCP_FP_CONVERTED_FIELD__VI = 0x4065; +constexpr unsigned int mmDCP3_DCP_GSL_CONTROL__VI = 0x4090; +constexpr unsigned int mmDCP3_DCP_LB_DATA_GAP_BETWEEN_CHUNK__VI = 0x4091; +constexpr unsigned int mmDCP3_DCP_RANDOM_SEEDS__VI = 0x4061; +constexpr unsigned int mmDCP3_DCP_SPATIAL_DITHER_CNTL__VI = 0x4060; +constexpr unsigned int mmDCP3_DCP_TEST_DEBUG_DATA__VI = 0x4096; +constexpr unsigned int mmDCP3_DCP_TEST_DEBUG_INDEX__VI = 0x4095; +constexpr unsigned int mmDCP3_DC_LUT_30_COLOR__VI = 0x407C; +constexpr unsigned int mmDCP3_DC_LUT_AUTOFILL__VI = 0x407F; +constexpr unsigned int mmDCP3_DC_LUT_BLACK_OFFSET_BLUE__VI = 0x4081; +constexpr unsigned int mmDCP3_DC_LUT_BLACK_OFFSET_GREEN__VI = 0x4082; +constexpr unsigned int mmDCP3_DC_LUT_BLACK_OFFSET_RED__VI = 0x4083; +constexpr unsigned int mmDCP3_DC_LUT_CONTROL__VI = 0x4080; +constexpr unsigned int mmDCP3_DC_LUT_PWL_DATA__VI = 0x407B; +constexpr unsigned int mmDCP3_DC_LUT_RW_INDEX__VI = 0x4079; +constexpr unsigned int mmDCP3_DC_LUT_RW_MODE__VI = 0x4078; +constexpr unsigned int mmDCP3_DC_LUT_SEQ_COLOR__VI = 0x407A; +constexpr unsigned int mmDCP3_DC_LUT_VGA_ACCESS_ENABLE__VI = 0x407D; +constexpr unsigned int mmDCP3_DC_LUT_WHITE_OFFSET_BLUE__VI = 0x4084; +constexpr unsigned int mmDCP3_DC_LUT_WHITE_OFFSET_GREEN__VI = 0x4085; +constexpr unsigned int mmDCP3_DC_LUT_WHITE_OFFSET_RED__VI = 0x4086; +constexpr unsigned int mmDCP3_DC_LUT_WRITE_EN_MASK__VI = 0x407E; +constexpr unsigned int mmDCP3_DEGAMMA_CONTROL__VI = 0x4058; +constexpr unsigned int mmDCP3_DENORM_CONTROL__VI = 0x4050; +constexpr unsigned int mmDCP3_GAMUT_REMAP_C11_C12__VI = 0x405A; +constexpr unsigned int mmDCP3_GAMUT_REMAP_C13_C14__VI = 0x405B; +constexpr unsigned int mmDCP3_GAMUT_REMAP_C21_C22__VI = 0x405C; +constexpr unsigned int mmDCP3_GAMUT_REMAP_C23_C24__VI = 0x405D; +constexpr unsigned int mmDCP3_GAMUT_REMAP_C31_C32__VI = 0x405E; +constexpr unsigned int mmDCP3_GAMUT_REMAP_C33_C34__VI = 0x405F; +constexpr unsigned int mmDCP3_GAMUT_REMAP_CONTROL__VI = 0x4059; +constexpr unsigned int mmDCP3_GRPH_COMPRESS_PITCH__VI = 0x401A; +constexpr unsigned int mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS__VI = 0x4019; +constexpr unsigned int mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__VI = 0x401B; +constexpr unsigned int mmDCP3_GRPH_CONTROL__SI__CI = 0x4301; +constexpr unsigned int mmDCP3_GRPH_CONTROL__VI = 0x4001; +constexpr unsigned int mmDCP3_GRPH_DFQ_CONTROL__VI = 0x4014; +constexpr unsigned int mmDCP3_GRPH_DFQ_STATUS__VI = 0x4015; +constexpr unsigned int mmDCP3_GRPH_ENABLE__VI = 0x4000; +constexpr unsigned int mmDCP3_GRPH_FLIP_CONTROL__SI__CI = 0x4312; +constexpr unsigned int mmDCP3_GRPH_FLIP_CONTROL__VI = 0x4012; +constexpr unsigned int mmDCP3_GRPH_FLIP_RATE_CNTL__VI = 0x408E; +constexpr unsigned int mmDCP3_GRPH_INTERRUPT_CONTROL__VI = 0x4017; +constexpr unsigned int mmDCP3_GRPH_INTERRUPT_STATUS__VI = 0x4016; +constexpr unsigned int mmDCP3_GRPH_LUT_10BIT_BYPASS__VI = 0x4002; +constexpr unsigned int mmDCP3_GRPH_PITCH__SI__CI = 0x4306; +constexpr unsigned int mmDCP3_GRPH_PITCH__VI = 0x4006; +constexpr unsigned int mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS__SI__CI = 0x4304; +constexpr unsigned int mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS__VI = 0x4004; +constexpr unsigned int mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__VI = 0x4007; +constexpr unsigned int mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS__VI = 0x4005; +constexpr unsigned int mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x4008; +constexpr unsigned int mmDCP3_GRPH_STEREOSYNC_FLIP__VI = 0x4097; +constexpr unsigned int mmDCP3_GRPH_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x4018; +constexpr unsigned int mmDCP3_GRPH_SURFACE_ADDRESS_INUSE__VI = 0x4013; +constexpr unsigned int mmDCP3_GRPH_SURFACE_OFFSET_X__VI = 0x4009; +constexpr unsigned int mmDCP3_GRPH_SURFACE_OFFSET_Y__VI = 0x400A; +constexpr unsigned int mmDCP3_GRPH_SWAP_CNTL__VI = 0x4003; +constexpr unsigned int mmDCP3_GRPH_UPDATE__SI__CI = 0x4311; +constexpr unsigned int mmDCP3_GRPH_UPDATE__VI = 0x4011; +constexpr unsigned int mmDCP3_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x409F; +constexpr unsigned int mmDCP3_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x40BF; +constexpr unsigned int mmDCP3_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x40BD; +constexpr unsigned int mmDCP3_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x40BE; +constexpr unsigned int mmDCP3_GRPH_X_END__VI = 0x400D; +constexpr unsigned int mmDCP3_GRPH_X_START__VI = 0x400B; +constexpr unsigned int mmDCP3_GRPH_Y_END__VI = 0x400E; +constexpr unsigned int mmDCP3_GRPH_Y_START__VI = 0x400C; +constexpr unsigned int mmDCP3_HW_ROTATION__VI = 0x409E; +constexpr unsigned int mmDCP3_INPUT_CSC_C11_C12__VI = 0x4036; +constexpr unsigned int mmDCP3_INPUT_CSC_C13_C14__VI = 0x4037; +constexpr unsigned int mmDCP3_INPUT_CSC_C21_C22__VI = 0x4038; +constexpr unsigned int mmDCP3_INPUT_CSC_C23_C24__VI = 0x4039; +constexpr unsigned int mmDCP3_INPUT_CSC_C31_C32__VI = 0x403A; +constexpr unsigned int mmDCP3_INPUT_CSC_C33_C34__VI = 0x403B; +constexpr unsigned int mmDCP3_INPUT_CSC_CONTROL__VI = 0x4035; +constexpr unsigned int mmDCP3_INPUT_GAMMA_CONTROL__VI = 0x4010; +constexpr unsigned int mmDCP3_KEY_CONTROL__VI = 0x4053; +constexpr unsigned int mmDCP3_KEY_RANGE_ALPHA__VI = 0x4054; +constexpr unsigned int mmDCP3_KEY_RANGE_BLUE__VI = 0x4057; +constexpr unsigned int mmDCP3_KEY_RANGE_GREEN__VI = 0x4056; +constexpr unsigned int mmDCP3_KEY_RANGE_RED__VI = 0x4055; +constexpr unsigned int mmDCP3_OUTPUT_CSC_C11_C12__VI = 0x403D; +constexpr unsigned int mmDCP3_OUTPUT_CSC_C13_C14__VI = 0x403E; +constexpr unsigned int mmDCP3_OUTPUT_CSC_C21_C22__VI = 0x403F; +constexpr unsigned int mmDCP3_OUTPUT_CSC_C23_C24__VI = 0x4040; +constexpr unsigned int mmDCP3_OUTPUT_CSC_C31_C32__VI = 0x4041; +constexpr unsigned int mmDCP3_OUTPUT_CSC_C33_C34__VI = 0x4042; +constexpr unsigned int mmDCP3_OUTPUT_CSC_CONTROL__VI = 0x403C; +constexpr unsigned int mmDCP3_OUT_CLAMP_CONTROL_B_CB__VI = 0x409D; +constexpr unsigned int mmDCP3_OUT_CLAMP_CONTROL_G_Y__VI = 0x409C; +constexpr unsigned int mmDCP3_OUT_CLAMP_CONTROL_R_CR__VI = 0x4052; +constexpr unsigned int mmDCP3_OUT_ROUND_CONTROL__VI = 0x4051; +constexpr unsigned int mmDCP3_OVLSCL_EDGE_PIXEL_CNTL__VI = 0x402C; +constexpr unsigned int mmDCP3_OVL_CONTROL1__VI = 0x401D; +constexpr unsigned int mmDCP3_OVL_CONTROL2__VI = 0x401E; +constexpr unsigned int mmDCP3_OVL_DFQ_CONTROL__VI = 0x4029; +constexpr unsigned int mmDCP3_OVL_DFQ_STATUS__VI = 0x402A; +constexpr unsigned int mmDCP3_OVL_ENABLE__VI = 0x401C; +constexpr unsigned int mmDCP3_OVL_END__VI = 0x4026; +constexpr unsigned int mmDCP3_OVL_PITCH__VI = 0x4021; +constexpr unsigned int mmDCP3_OVL_SECONDARY_SURFACE_ADDRESS__VI = 0x4092; +constexpr unsigned int mmDCP3_OVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x4094; +constexpr unsigned int mmDCP3_OVL_START__VI = 0x4025; +constexpr unsigned int mmDCP3_OVL_STEREOSYNC_FLIP__VI = 0x4093; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS__SI__CI = 0x4320; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS__VI = 0x4020; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS_HIGH__VI = 0x4022; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x402B; +constexpr unsigned int mmDCP3_OVL_SURFACE_ADDRESS_INUSE__VI = 0x4028; +constexpr unsigned int mmDCP3_OVL_SURFACE_OFFSET_X__VI = 0x4023; +constexpr unsigned int mmDCP3_OVL_SURFACE_OFFSET_Y__VI = 0x4024; +constexpr unsigned int mmDCP3_OVL_SWAP_CNTL__VI = 0x401F; +constexpr unsigned int mmDCP3_OVL_UPDATE__VI = 0x4027; +constexpr unsigned int mmDCP3_PRESCALE_GRPH_CONTROL__VI = 0x402D; +constexpr unsigned int mmDCP3_PRESCALE_OVL_CONTROL__VI = 0x4031; +constexpr unsigned int mmDCP3_PRESCALE_VALUES_GRPH_B__VI = 0x4030; +constexpr unsigned int mmDCP3_PRESCALE_VALUES_GRPH_G__VI = 0x402F; +constexpr unsigned int mmDCP3_PRESCALE_VALUES_GRPH_R__VI = 0x402E; +constexpr unsigned int mmDCP3_PRESCALE_VALUES_OVL_CB__VI = 0x4032; +constexpr unsigned int mmDCP3_PRESCALE_VALUES_OVL_CR__VI = 0x4034; +constexpr unsigned int mmDCP3_PRESCALE_VALUES_OVL_Y__VI = 0x4033; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_END_CNTL1__VI = 0x40A6; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_END_CNTL2__VI = 0x40A7; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_0_1__VI = 0x40A8; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_10_11__VI = 0x40AD; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_12_13__VI = 0x40AE; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_14_15__VI = 0x40AF; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_2_3__VI = 0x40A9; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_4_5__VI = 0x40AA; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_6_7__VI = 0x40AB; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_REGION_8_9__VI = 0x40AC; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_SLOPE_CNTL__VI = 0x40A5; +constexpr unsigned int mmDCP3_REGAMMA_CNTLA_START_CNTL__VI = 0x40A4; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_END_CNTL1__VI = 0x40B2; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_END_CNTL2__VI = 0x40B3; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_0_1__VI = 0x40B4; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_10_11__VI = 0x40B9; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_12_13__VI = 0x40BA; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_14_15__VI = 0x40BB; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_2_3__VI = 0x40B5; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_4_5__VI = 0x40B6; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_6_7__VI = 0x40B7; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_REGION_8_9__VI = 0x40B8; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_SLOPE_CNTL__VI = 0x40B1; +constexpr unsigned int mmDCP3_REGAMMA_CNTLB_START_CNTL__VI = 0x40B0; +constexpr unsigned int mmDCP3_REGAMMA_CONTROL__VI = 0x40A0; +constexpr unsigned int mmDCP3_REGAMMA_LUT_DATA__VI = 0x40A2; +constexpr unsigned int mmDCP3_REGAMMA_LUT_INDEX__VI = 0x40A1; +constexpr unsigned int mmDCP3_REGAMMA_LUT_WRITE_EN_MASK__VI = 0x40A3; +constexpr unsigned int mmDCP4_ALPHA_CONTROL__VI = 0x42BC; +constexpr unsigned int mmDCP4_COMM_MATRIXA_TRANS_C11_C12__VI = 0x4243; +constexpr unsigned int mmDCP4_COMM_MATRIXA_TRANS_C13_C14__VI = 0x4244; +constexpr unsigned int mmDCP4_COMM_MATRIXA_TRANS_C21_C22__VI = 0x4245; +constexpr unsigned int mmDCP4_COMM_MATRIXA_TRANS_C23_C24__VI = 0x4246; +constexpr unsigned int mmDCP4_COMM_MATRIXA_TRANS_C31_C32__VI = 0x4247; +constexpr unsigned int mmDCP4_COMM_MATRIXA_TRANS_C33_C34__VI = 0x4248; +constexpr unsigned int mmDCP4_COMM_MATRIXB_TRANS_C11_C12__VI = 0x4249; +constexpr unsigned int mmDCP4_COMM_MATRIXB_TRANS_C13_C14__VI = 0x424A; +constexpr unsigned int mmDCP4_COMM_MATRIXB_TRANS_C21_C22__VI = 0x424B; +constexpr unsigned int mmDCP4_COMM_MATRIXB_TRANS_C23_C24__VI = 0x424C; +constexpr unsigned int mmDCP4_COMM_MATRIXB_TRANS_C31_C32__VI = 0x424D; +constexpr unsigned int mmDCP4_COMM_MATRIXB_TRANS_C33_C34__VI = 0x424E; +constexpr unsigned int mmDCP4_CUR2_COLOR1__VI = 0x4275; +constexpr unsigned int mmDCP4_CUR2_COLOR2__VI = 0x4276; +constexpr unsigned int mmDCP4_CUR2_CONTROL__VI = 0x426F; +constexpr unsigned int mmDCP4_CUR2_HOT_SPOT__VI = 0x4274; +constexpr unsigned int mmDCP4_CUR2_POSITION__VI = 0x4273; +constexpr unsigned int mmDCP4_CUR2_SIZE__VI = 0x4271; +constexpr unsigned int mmDCP4_CUR2_STEREO_CONTROL__VI = 0x429B; +constexpr unsigned int mmDCP4_CUR2_SURFACE_ADDRESS__VI = 0x4270; +constexpr unsigned int mmDCP4_CUR2_SURFACE_ADDRESS_HIGH__VI = 0x4272; +constexpr unsigned int mmDCP4_CUR2_UPDATE__VI = 0x4277; +constexpr unsigned int mmDCP4_CUR_COLOR1__VI = 0x426C; +constexpr unsigned int mmDCP4_CUR_COLOR2__VI = 0x426D; +constexpr unsigned int mmDCP4_CUR_CONTROL__VI = 0x4266; +constexpr unsigned int mmDCP4_CUR_HOT_SPOT__VI = 0x426B; +constexpr unsigned int mmDCP4_CUR_POSITION__VI = 0x426A; +constexpr unsigned int mmDCP4_CUR_REQUEST_FILTER_CNTL__VI = 0x4299; +constexpr unsigned int mmDCP4_CUR_SIZE__VI = 0x4268; +constexpr unsigned int mmDCP4_CUR_STEREO_CONTROL__VI = 0x429A; +constexpr unsigned int mmDCP4_CUR_SURFACE_ADDRESS__VI = 0x4267; +constexpr unsigned int mmDCP4_CUR_SURFACE_ADDRESS_HIGH__VI = 0x4269; +constexpr unsigned int mmDCP4_CUR_UPDATE__VI = 0x426E; +constexpr unsigned int mmDCP4_DCP_CRC_CONTROL__VI = 0x4287; +constexpr unsigned int mmDCP4_DCP_CRC_CURRENT__VI = 0x4289; +constexpr unsigned int mmDCP4_DCP_CRC_LAST__VI = 0x428B; +constexpr unsigned int mmDCP4_DCP_CRC_MASK__VI = 0x4288; +constexpr unsigned int mmDCP4_DCP_DEBUG__VI = 0x428D; +constexpr unsigned int mmDCP4_DCP_DEBUG2__VI = 0x4298; +constexpr unsigned int mmDCP4_DCP_FP_CONVERTED_FIELD__VI = 0x4265; +constexpr unsigned int mmDCP4_DCP_GSL_CONTROL__VI = 0x4290; +constexpr unsigned int mmDCP4_DCP_LB_DATA_GAP_BETWEEN_CHUNK__VI = 0x4291; +constexpr unsigned int mmDCP4_DCP_RANDOM_SEEDS__VI = 0x4261; +constexpr unsigned int mmDCP4_DCP_SPATIAL_DITHER_CNTL__VI = 0x4260; +constexpr unsigned int mmDCP4_DCP_TEST_DEBUG_DATA__VI = 0x4296; +constexpr unsigned int mmDCP4_DCP_TEST_DEBUG_INDEX__VI = 0x4295; +constexpr unsigned int mmDCP4_DC_LUT_30_COLOR__VI = 0x427C; +constexpr unsigned int mmDCP4_DC_LUT_AUTOFILL__VI = 0x427F; +constexpr unsigned int mmDCP4_DC_LUT_BLACK_OFFSET_BLUE__VI = 0x4281; +constexpr unsigned int mmDCP4_DC_LUT_BLACK_OFFSET_GREEN__VI = 0x4282; +constexpr unsigned int mmDCP4_DC_LUT_BLACK_OFFSET_RED__VI = 0x4283; +constexpr unsigned int mmDCP4_DC_LUT_CONTROL__VI = 0x4280; +constexpr unsigned int mmDCP4_DC_LUT_PWL_DATA__VI = 0x427B; +constexpr unsigned int mmDCP4_DC_LUT_RW_INDEX__VI = 0x4279; +constexpr unsigned int mmDCP4_DC_LUT_RW_MODE__VI = 0x4278; +constexpr unsigned int mmDCP4_DC_LUT_SEQ_COLOR__VI = 0x427A; +constexpr unsigned int mmDCP4_DC_LUT_VGA_ACCESS_ENABLE__VI = 0x427D; +constexpr unsigned int mmDCP4_DC_LUT_WHITE_OFFSET_BLUE__VI = 0x4284; +constexpr unsigned int mmDCP4_DC_LUT_WHITE_OFFSET_GREEN__VI = 0x4285; +constexpr unsigned int mmDCP4_DC_LUT_WHITE_OFFSET_RED__VI = 0x4286; +constexpr unsigned int mmDCP4_DC_LUT_WRITE_EN_MASK__VI = 0x427E; +constexpr unsigned int mmDCP4_DEGAMMA_CONTROL__VI = 0x4258; +constexpr unsigned int mmDCP4_DENORM_CONTROL__VI = 0x4250; +constexpr unsigned int mmDCP4_GAMUT_REMAP_C11_C12__VI = 0x425A; +constexpr unsigned int mmDCP4_GAMUT_REMAP_C13_C14__VI = 0x425B; +constexpr unsigned int mmDCP4_GAMUT_REMAP_C21_C22__VI = 0x425C; +constexpr unsigned int mmDCP4_GAMUT_REMAP_C23_C24__VI = 0x425D; +constexpr unsigned int mmDCP4_GAMUT_REMAP_C31_C32__VI = 0x425E; +constexpr unsigned int mmDCP4_GAMUT_REMAP_C33_C34__VI = 0x425F; +constexpr unsigned int mmDCP4_GAMUT_REMAP_CONTROL__VI = 0x4259; +constexpr unsigned int mmDCP4_GRPH_COMPRESS_PITCH__VI = 0x421A; +constexpr unsigned int mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS__VI = 0x4219; +constexpr unsigned int mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__VI = 0x421B; +constexpr unsigned int mmDCP4_GRPH_CONTROL__SI__CI = 0x4601; +constexpr unsigned int mmDCP4_GRPH_CONTROL__VI = 0x4201; +constexpr unsigned int mmDCP4_GRPH_DFQ_CONTROL__VI = 0x4214; +constexpr unsigned int mmDCP4_GRPH_DFQ_STATUS__VI = 0x4215; +constexpr unsigned int mmDCP4_GRPH_ENABLE__VI = 0x4200; +constexpr unsigned int mmDCP4_GRPH_FLIP_CONTROL__SI__CI = 0x4612; +constexpr unsigned int mmDCP4_GRPH_FLIP_CONTROL__VI = 0x4212; +constexpr unsigned int mmDCP4_GRPH_FLIP_RATE_CNTL__VI = 0x428E; +constexpr unsigned int mmDCP4_GRPH_INTERRUPT_CONTROL__VI = 0x4217; +constexpr unsigned int mmDCP4_GRPH_INTERRUPT_STATUS__VI = 0x4216; +constexpr unsigned int mmDCP4_GRPH_LUT_10BIT_BYPASS__VI = 0x4202; +constexpr unsigned int mmDCP4_GRPH_PITCH__SI__CI = 0x4606; +constexpr unsigned int mmDCP4_GRPH_PITCH__VI = 0x4206; +constexpr unsigned int mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS__SI__CI = 0x4604; +constexpr unsigned int mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS__VI = 0x4204; +constexpr unsigned int mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__VI = 0x4207; +constexpr unsigned int mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS__VI = 0x4205; +constexpr unsigned int mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x4208; +constexpr unsigned int mmDCP4_GRPH_STEREOSYNC_FLIP__VI = 0x4297; +constexpr unsigned int mmDCP4_GRPH_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x4218; +constexpr unsigned int mmDCP4_GRPH_SURFACE_ADDRESS_INUSE__VI = 0x4213; +constexpr unsigned int mmDCP4_GRPH_SURFACE_OFFSET_X__VI = 0x4209; +constexpr unsigned int mmDCP4_GRPH_SURFACE_OFFSET_Y__VI = 0x420A; +constexpr unsigned int mmDCP4_GRPH_SWAP_CNTL__VI = 0x4203; +constexpr unsigned int mmDCP4_GRPH_UPDATE__SI__CI = 0x4611; +constexpr unsigned int mmDCP4_GRPH_UPDATE__VI = 0x4211; +constexpr unsigned int mmDCP4_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x429F; +constexpr unsigned int mmDCP4_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x42BF; +constexpr unsigned int mmDCP4_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x42BD; +constexpr unsigned int mmDCP4_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x42BE; +constexpr unsigned int mmDCP4_GRPH_X_END__VI = 0x420D; +constexpr unsigned int mmDCP4_GRPH_X_START__VI = 0x420B; +constexpr unsigned int mmDCP4_GRPH_Y_END__VI = 0x420E; +constexpr unsigned int mmDCP4_GRPH_Y_START__VI = 0x420C; +constexpr unsigned int mmDCP4_HW_ROTATION__VI = 0x429E; +constexpr unsigned int mmDCP4_INPUT_CSC_C11_C12__VI = 0x4236; +constexpr unsigned int mmDCP4_INPUT_CSC_C13_C14__VI = 0x4237; +constexpr unsigned int mmDCP4_INPUT_CSC_C21_C22__VI = 0x4238; +constexpr unsigned int mmDCP4_INPUT_CSC_C23_C24__VI = 0x4239; +constexpr unsigned int mmDCP4_INPUT_CSC_C31_C32__VI = 0x423A; +constexpr unsigned int mmDCP4_INPUT_CSC_C33_C34__VI = 0x423B; +constexpr unsigned int mmDCP4_INPUT_CSC_CONTROL__VI = 0x4235; +constexpr unsigned int mmDCP4_INPUT_GAMMA_CONTROL__VI = 0x4210; +constexpr unsigned int mmDCP4_KEY_CONTROL__VI = 0x4253; +constexpr unsigned int mmDCP4_KEY_RANGE_ALPHA__VI = 0x4254; +constexpr unsigned int mmDCP4_KEY_RANGE_BLUE__VI = 0x4257; +constexpr unsigned int mmDCP4_KEY_RANGE_GREEN__VI = 0x4256; +constexpr unsigned int mmDCP4_KEY_RANGE_RED__VI = 0x4255; +constexpr unsigned int mmDCP4_OUTPUT_CSC_C11_C12__VI = 0x423D; +constexpr unsigned int mmDCP4_OUTPUT_CSC_C13_C14__VI = 0x423E; +constexpr unsigned int mmDCP4_OUTPUT_CSC_C21_C22__VI = 0x423F; +constexpr unsigned int mmDCP4_OUTPUT_CSC_C23_C24__VI = 0x4240; +constexpr unsigned int mmDCP4_OUTPUT_CSC_C31_C32__VI = 0x4241; +constexpr unsigned int mmDCP4_OUTPUT_CSC_C33_C34__VI = 0x4242; +constexpr unsigned int mmDCP4_OUTPUT_CSC_CONTROL__VI = 0x423C; +constexpr unsigned int mmDCP4_OUT_CLAMP_CONTROL_B_CB__VI = 0x429D; +constexpr unsigned int mmDCP4_OUT_CLAMP_CONTROL_G_Y__VI = 0x429C; +constexpr unsigned int mmDCP4_OUT_CLAMP_CONTROL_R_CR__VI = 0x4252; +constexpr unsigned int mmDCP4_OUT_ROUND_CONTROL__VI = 0x4251; +constexpr unsigned int mmDCP4_OVLSCL_EDGE_PIXEL_CNTL__VI = 0x422C; +constexpr unsigned int mmDCP4_OVL_CONTROL1__VI = 0x421D; +constexpr unsigned int mmDCP4_OVL_CONTROL2__VI = 0x421E; +constexpr unsigned int mmDCP4_OVL_DFQ_CONTROL__VI = 0x4229; +constexpr unsigned int mmDCP4_OVL_DFQ_STATUS__VI = 0x422A; +constexpr unsigned int mmDCP4_OVL_ENABLE__VI = 0x421C; +constexpr unsigned int mmDCP4_OVL_END__VI = 0x4226; +constexpr unsigned int mmDCP4_OVL_PITCH__VI = 0x4221; +constexpr unsigned int mmDCP4_OVL_SECONDARY_SURFACE_ADDRESS__VI = 0x4292; +constexpr unsigned int mmDCP4_OVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x4294; +constexpr unsigned int mmDCP4_OVL_START__VI = 0x4225; +constexpr unsigned int mmDCP4_OVL_STEREOSYNC_FLIP__VI = 0x4293; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS__SI__CI = 0x4620; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS__VI = 0x4220; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS_HIGH__VI = 0x4222; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x422B; +constexpr unsigned int mmDCP4_OVL_SURFACE_ADDRESS_INUSE__VI = 0x4228; +constexpr unsigned int mmDCP4_OVL_SURFACE_OFFSET_X__VI = 0x4223; +constexpr unsigned int mmDCP4_OVL_SURFACE_OFFSET_Y__VI = 0x4224; +constexpr unsigned int mmDCP4_OVL_SWAP_CNTL__VI = 0x421F; +constexpr unsigned int mmDCP4_OVL_UPDATE__VI = 0x4227; +constexpr unsigned int mmDCP4_PRESCALE_GRPH_CONTROL__VI = 0x422D; +constexpr unsigned int mmDCP4_PRESCALE_OVL_CONTROL__VI = 0x4231; +constexpr unsigned int mmDCP4_PRESCALE_VALUES_GRPH_B__VI = 0x4230; +constexpr unsigned int mmDCP4_PRESCALE_VALUES_GRPH_G__VI = 0x422F; +constexpr unsigned int mmDCP4_PRESCALE_VALUES_GRPH_R__VI = 0x422E; +constexpr unsigned int mmDCP4_PRESCALE_VALUES_OVL_CB__VI = 0x4232; +constexpr unsigned int mmDCP4_PRESCALE_VALUES_OVL_CR__VI = 0x4234; +constexpr unsigned int mmDCP4_PRESCALE_VALUES_OVL_Y__VI = 0x4233; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_END_CNTL1__VI = 0x42A6; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_END_CNTL2__VI = 0x42A7; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_0_1__VI = 0x42A8; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_10_11__VI = 0x42AD; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_12_13__VI = 0x42AE; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_14_15__VI = 0x42AF; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_2_3__VI = 0x42A9; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_4_5__VI = 0x42AA; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_6_7__VI = 0x42AB; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_REGION_8_9__VI = 0x42AC; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_SLOPE_CNTL__VI = 0x42A5; +constexpr unsigned int mmDCP4_REGAMMA_CNTLA_START_CNTL__VI = 0x42A4; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_END_CNTL1__VI = 0x42B2; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_END_CNTL2__VI = 0x42B3; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_0_1__VI = 0x42B4; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_10_11__VI = 0x42B9; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_12_13__VI = 0x42BA; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_14_15__VI = 0x42BB; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_2_3__VI = 0x42B5; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_4_5__VI = 0x42B6; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_6_7__VI = 0x42B7; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_REGION_8_9__VI = 0x42B8; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_SLOPE_CNTL__VI = 0x42B1; +constexpr unsigned int mmDCP4_REGAMMA_CNTLB_START_CNTL__VI = 0x42B0; +constexpr unsigned int mmDCP4_REGAMMA_CONTROL__VI = 0x42A0; +constexpr unsigned int mmDCP4_REGAMMA_LUT_DATA__VI = 0x42A2; +constexpr unsigned int mmDCP4_REGAMMA_LUT_INDEX__VI = 0x42A1; +constexpr unsigned int mmDCP4_REGAMMA_LUT_WRITE_EN_MASK__VI = 0x42A3; +constexpr unsigned int mmDCP5_ALPHA_CONTROL__VI = 0x44BC; +constexpr unsigned int mmDCP5_COMM_MATRIXA_TRANS_C11_C12__VI = 0x4443; +constexpr unsigned int mmDCP5_COMM_MATRIXA_TRANS_C13_C14__VI = 0x4444; +constexpr unsigned int mmDCP5_COMM_MATRIXA_TRANS_C21_C22__VI = 0x4445; +constexpr unsigned int mmDCP5_COMM_MATRIXA_TRANS_C23_C24__VI = 0x4446; +constexpr unsigned int mmDCP5_COMM_MATRIXA_TRANS_C31_C32__VI = 0x4447; +constexpr unsigned int mmDCP5_COMM_MATRIXA_TRANS_C33_C34__VI = 0x4448; +constexpr unsigned int mmDCP5_COMM_MATRIXB_TRANS_C11_C12__VI = 0x4449; +constexpr unsigned int mmDCP5_COMM_MATRIXB_TRANS_C13_C14__VI = 0x444A; +constexpr unsigned int mmDCP5_COMM_MATRIXB_TRANS_C21_C22__VI = 0x444B; +constexpr unsigned int mmDCP5_COMM_MATRIXB_TRANS_C23_C24__VI = 0x444C; +constexpr unsigned int mmDCP5_COMM_MATRIXB_TRANS_C31_C32__VI = 0x444D; +constexpr unsigned int mmDCP5_COMM_MATRIXB_TRANS_C33_C34__VI = 0x444E; +constexpr unsigned int mmDCP5_CUR2_COLOR1__VI = 0x4475; +constexpr unsigned int mmDCP5_CUR2_COLOR2__VI = 0x4476; +constexpr unsigned int mmDCP5_CUR2_CONTROL__VI = 0x446F; +constexpr unsigned int mmDCP5_CUR2_HOT_SPOT__VI = 0x4474; +constexpr unsigned int mmDCP5_CUR2_POSITION__VI = 0x4473; +constexpr unsigned int mmDCP5_CUR2_SIZE__VI = 0x4471; +constexpr unsigned int mmDCP5_CUR2_STEREO_CONTROL__VI = 0x449B; +constexpr unsigned int mmDCP5_CUR2_SURFACE_ADDRESS__VI = 0x4470; +constexpr unsigned int mmDCP5_CUR2_SURFACE_ADDRESS_HIGH__VI = 0x4472; +constexpr unsigned int mmDCP5_CUR2_UPDATE__VI = 0x4477; +constexpr unsigned int mmDCP5_CUR_COLOR1__VI = 0x446C; +constexpr unsigned int mmDCP5_CUR_COLOR2__VI = 0x446D; +constexpr unsigned int mmDCP5_CUR_CONTROL__VI = 0x4466; +constexpr unsigned int mmDCP5_CUR_HOT_SPOT__VI = 0x446B; +constexpr unsigned int mmDCP5_CUR_POSITION__VI = 0x446A; +constexpr unsigned int mmDCP5_CUR_REQUEST_FILTER_CNTL__VI = 0x4499; +constexpr unsigned int mmDCP5_CUR_SIZE__VI = 0x4468; +constexpr unsigned int mmDCP5_CUR_STEREO_CONTROL__VI = 0x449A; +constexpr unsigned int mmDCP5_CUR_SURFACE_ADDRESS__VI = 0x4467; +constexpr unsigned int mmDCP5_CUR_SURFACE_ADDRESS_HIGH__VI = 0x4469; +constexpr unsigned int mmDCP5_CUR_UPDATE__VI = 0x446E; +constexpr unsigned int mmDCP5_DCP_CRC_CONTROL__VI = 0x4487; +constexpr unsigned int mmDCP5_DCP_CRC_CURRENT__VI = 0x4489; +constexpr unsigned int mmDCP5_DCP_CRC_LAST__VI = 0x448B; +constexpr unsigned int mmDCP5_DCP_CRC_MASK__VI = 0x4488; +constexpr unsigned int mmDCP5_DCP_DEBUG__VI = 0x448D; +constexpr unsigned int mmDCP5_DCP_DEBUG2__VI = 0x4498; +constexpr unsigned int mmDCP5_DCP_FP_CONVERTED_FIELD__VI = 0x4465; +constexpr unsigned int mmDCP5_DCP_GSL_CONTROL__VI = 0x4490; +constexpr unsigned int mmDCP5_DCP_LB_DATA_GAP_BETWEEN_CHUNK__VI = 0x4491; +constexpr unsigned int mmDCP5_DCP_RANDOM_SEEDS__VI = 0x4461; +constexpr unsigned int mmDCP5_DCP_SPATIAL_DITHER_CNTL__VI = 0x4460; +constexpr unsigned int mmDCP5_DCP_TEST_DEBUG_DATA__VI = 0x4496; +constexpr unsigned int mmDCP5_DCP_TEST_DEBUG_INDEX__VI = 0x4495; +constexpr unsigned int mmDCP5_DC_LUT_30_COLOR__VI = 0x447C; +constexpr unsigned int mmDCP5_DC_LUT_AUTOFILL__VI = 0x447F; +constexpr unsigned int mmDCP5_DC_LUT_BLACK_OFFSET_BLUE__VI = 0x4481; +constexpr unsigned int mmDCP5_DC_LUT_BLACK_OFFSET_GREEN__VI = 0x4482; +constexpr unsigned int mmDCP5_DC_LUT_BLACK_OFFSET_RED__VI = 0x4483; +constexpr unsigned int mmDCP5_DC_LUT_CONTROL__VI = 0x4480; +constexpr unsigned int mmDCP5_DC_LUT_PWL_DATA__VI = 0x447B; +constexpr unsigned int mmDCP5_DC_LUT_RW_INDEX__VI = 0x4479; +constexpr unsigned int mmDCP5_DC_LUT_RW_MODE__VI = 0x4478; +constexpr unsigned int mmDCP5_DC_LUT_SEQ_COLOR__VI = 0x447A; +constexpr unsigned int mmDCP5_DC_LUT_VGA_ACCESS_ENABLE__VI = 0x447D; +constexpr unsigned int mmDCP5_DC_LUT_WHITE_OFFSET_BLUE__VI = 0x4484; +constexpr unsigned int mmDCP5_DC_LUT_WHITE_OFFSET_GREEN__VI = 0x4485; +constexpr unsigned int mmDCP5_DC_LUT_WHITE_OFFSET_RED__VI = 0x4486; +constexpr unsigned int mmDCP5_DC_LUT_WRITE_EN_MASK__VI = 0x447E; +constexpr unsigned int mmDCP5_DEGAMMA_CONTROL__VI = 0x4458; +constexpr unsigned int mmDCP5_DENORM_CONTROL__VI = 0x4450; +constexpr unsigned int mmDCP5_GAMUT_REMAP_C11_C12__VI = 0x445A; +constexpr unsigned int mmDCP5_GAMUT_REMAP_C13_C14__VI = 0x445B; +constexpr unsigned int mmDCP5_GAMUT_REMAP_C21_C22__VI = 0x445C; +constexpr unsigned int mmDCP5_GAMUT_REMAP_C23_C24__VI = 0x445D; +constexpr unsigned int mmDCP5_GAMUT_REMAP_C31_C32__VI = 0x445E; +constexpr unsigned int mmDCP5_GAMUT_REMAP_C33_C34__VI = 0x445F; +constexpr unsigned int mmDCP5_GAMUT_REMAP_CONTROL__VI = 0x4459; +constexpr unsigned int mmDCP5_GRPH_COMPRESS_PITCH__VI = 0x441A; +constexpr unsigned int mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS__VI = 0x4419; +constexpr unsigned int mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__VI = 0x441B; +constexpr unsigned int mmDCP5_GRPH_CONTROL__SI__CI = 0x4901; +constexpr unsigned int mmDCP5_GRPH_CONTROL__VI = 0x4401; +constexpr unsigned int mmDCP5_GRPH_DFQ_CONTROL__VI = 0x4414; +constexpr unsigned int mmDCP5_GRPH_DFQ_STATUS__VI = 0x4415; +constexpr unsigned int mmDCP5_GRPH_ENABLE__VI = 0x4400; +constexpr unsigned int mmDCP5_GRPH_FLIP_CONTROL__SI__CI = 0x4912; +constexpr unsigned int mmDCP5_GRPH_FLIP_CONTROL__VI = 0x4412; +constexpr unsigned int mmDCP5_GRPH_FLIP_RATE_CNTL__VI = 0x448E; +constexpr unsigned int mmDCP5_GRPH_INTERRUPT_CONTROL__VI = 0x4417; +constexpr unsigned int mmDCP5_GRPH_INTERRUPT_STATUS__VI = 0x4416; +constexpr unsigned int mmDCP5_GRPH_LUT_10BIT_BYPASS__VI = 0x4402; +constexpr unsigned int mmDCP5_GRPH_PITCH__SI__CI = 0x4906; +constexpr unsigned int mmDCP5_GRPH_PITCH__VI = 0x4406; +constexpr unsigned int mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS__SI__CI = 0x4904; +constexpr unsigned int mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS__VI = 0x4404; +constexpr unsigned int mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__VI = 0x4407; +constexpr unsigned int mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS__VI = 0x4405; +constexpr unsigned int mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x4408; +constexpr unsigned int mmDCP5_GRPH_STEREOSYNC_FLIP__VI = 0x4497; +constexpr unsigned int mmDCP5_GRPH_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x4418; +constexpr unsigned int mmDCP5_GRPH_SURFACE_ADDRESS_INUSE__VI = 0x4413; +constexpr unsigned int mmDCP5_GRPH_SURFACE_OFFSET_X__VI = 0x4409; +constexpr unsigned int mmDCP5_GRPH_SURFACE_OFFSET_Y__VI = 0x440A; +constexpr unsigned int mmDCP5_GRPH_SWAP_CNTL__VI = 0x4403; +constexpr unsigned int mmDCP5_GRPH_UPDATE__SI__CI = 0x4911; +constexpr unsigned int mmDCP5_GRPH_UPDATE__VI = 0x4411; +constexpr unsigned int mmDCP5_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x449F; +constexpr unsigned int mmDCP5_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x44BF; +constexpr unsigned int mmDCP5_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x44BD; +constexpr unsigned int mmDCP5_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x44BE; +constexpr unsigned int mmDCP5_GRPH_X_END__VI = 0x440D; +constexpr unsigned int mmDCP5_GRPH_X_START__VI = 0x440B; +constexpr unsigned int mmDCP5_GRPH_Y_END__VI = 0x440E; +constexpr unsigned int mmDCP5_GRPH_Y_START__VI = 0x440C; +constexpr unsigned int mmDCP5_HW_ROTATION__VI = 0x449E; +constexpr unsigned int mmDCP5_INPUT_CSC_C11_C12__VI = 0x4436; +constexpr unsigned int mmDCP5_INPUT_CSC_C13_C14__VI = 0x4437; +constexpr unsigned int mmDCP5_INPUT_CSC_C21_C22__VI = 0x4438; +constexpr unsigned int mmDCP5_INPUT_CSC_C23_C24__VI = 0x4439; +constexpr unsigned int mmDCP5_INPUT_CSC_C31_C32__VI = 0x443A; +constexpr unsigned int mmDCP5_INPUT_CSC_C33_C34__VI = 0x443B; +constexpr unsigned int mmDCP5_INPUT_CSC_CONTROL__VI = 0x4435; +constexpr unsigned int mmDCP5_INPUT_GAMMA_CONTROL__VI = 0x4410; +constexpr unsigned int mmDCP5_KEY_CONTROL__VI = 0x4453; +constexpr unsigned int mmDCP5_KEY_RANGE_ALPHA__VI = 0x4454; +constexpr unsigned int mmDCP5_KEY_RANGE_BLUE__VI = 0x4457; +constexpr unsigned int mmDCP5_KEY_RANGE_GREEN__VI = 0x4456; +constexpr unsigned int mmDCP5_KEY_RANGE_RED__VI = 0x4455; +constexpr unsigned int mmDCP5_OUTPUT_CSC_C11_C12__VI = 0x443D; +constexpr unsigned int mmDCP5_OUTPUT_CSC_C13_C14__VI = 0x443E; +constexpr unsigned int mmDCP5_OUTPUT_CSC_C21_C22__VI = 0x443F; +constexpr unsigned int mmDCP5_OUTPUT_CSC_C23_C24__VI = 0x4440; +constexpr unsigned int mmDCP5_OUTPUT_CSC_C31_C32__VI = 0x4441; +constexpr unsigned int mmDCP5_OUTPUT_CSC_C33_C34__VI = 0x4442; +constexpr unsigned int mmDCP5_OUTPUT_CSC_CONTROL__VI = 0x443C; +constexpr unsigned int mmDCP5_OUT_CLAMP_CONTROL_B_CB__VI = 0x449D; +constexpr unsigned int mmDCP5_OUT_CLAMP_CONTROL_G_Y__VI = 0x449C; +constexpr unsigned int mmDCP5_OUT_CLAMP_CONTROL_R_CR__VI = 0x4452; +constexpr unsigned int mmDCP5_OUT_ROUND_CONTROL__VI = 0x4451; +constexpr unsigned int mmDCP5_OVLSCL_EDGE_PIXEL_CNTL__VI = 0x442C; +constexpr unsigned int mmDCP5_OVL_CONTROL1__VI = 0x441D; +constexpr unsigned int mmDCP5_OVL_CONTROL2__VI = 0x441E; +constexpr unsigned int mmDCP5_OVL_DFQ_CONTROL__VI = 0x4429; +constexpr unsigned int mmDCP5_OVL_DFQ_STATUS__VI = 0x442A; +constexpr unsigned int mmDCP5_OVL_ENABLE__VI = 0x441C; +constexpr unsigned int mmDCP5_OVL_END__VI = 0x4426; +constexpr unsigned int mmDCP5_OVL_PITCH__VI = 0x4421; +constexpr unsigned int mmDCP5_OVL_SECONDARY_SURFACE_ADDRESS__VI = 0x4492; +constexpr unsigned int mmDCP5_OVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x4494; +constexpr unsigned int mmDCP5_OVL_START__VI = 0x4425; +constexpr unsigned int mmDCP5_OVL_STEREOSYNC_FLIP__VI = 0x4493; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS__SI__CI = 0x4920; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS__VI = 0x4420; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS_HIGH__VI = 0x4422; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS_HIGH_INUSE__VI = 0x442B; +constexpr unsigned int mmDCP5_OVL_SURFACE_ADDRESS_INUSE__VI = 0x4428; +constexpr unsigned int mmDCP5_OVL_SURFACE_OFFSET_X__VI = 0x4423; +constexpr unsigned int mmDCP5_OVL_SURFACE_OFFSET_Y__VI = 0x4424; +constexpr unsigned int mmDCP5_OVL_SWAP_CNTL__VI = 0x441F; +constexpr unsigned int mmDCP5_OVL_UPDATE__VI = 0x4427; +constexpr unsigned int mmDCP5_PRESCALE_GRPH_CONTROL__VI = 0x442D; +constexpr unsigned int mmDCP5_PRESCALE_OVL_CONTROL__VI = 0x4431; +constexpr unsigned int mmDCP5_PRESCALE_VALUES_GRPH_B__VI = 0x4430; +constexpr unsigned int mmDCP5_PRESCALE_VALUES_GRPH_G__VI = 0x442F; +constexpr unsigned int mmDCP5_PRESCALE_VALUES_GRPH_R__VI = 0x442E; +constexpr unsigned int mmDCP5_PRESCALE_VALUES_OVL_CB__VI = 0x4432; +constexpr unsigned int mmDCP5_PRESCALE_VALUES_OVL_CR__VI = 0x4434; +constexpr unsigned int mmDCP5_PRESCALE_VALUES_OVL_Y__VI = 0x4433; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_END_CNTL1__VI = 0x44A6; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_END_CNTL2__VI = 0x44A7; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_0_1__VI = 0x44A8; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_10_11__VI = 0x44AD; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_12_13__VI = 0x44AE; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_14_15__VI = 0x44AF; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_2_3__VI = 0x44A9; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_4_5__VI = 0x44AA; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_6_7__VI = 0x44AB; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_REGION_8_9__VI = 0x44AC; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_SLOPE_CNTL__VI = 0x44A5; +constexpr unsigned int mmDCP5_REGAMMA_CNTLA_START_CNTL__VI = 0x44A4; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_END_CNTL1__VI = 0x44B2; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_END_CNTL2__VI = 0x44B3; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_0_1__VI = 0x44B4; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_10_11__VI = 0x44B9; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_12_13__VI = 0x44BA; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_14_15__VI = 0x44BB; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_2_3__VI = 0x44B5; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_4_5__VI = 0x44B6; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_6_7__VI = 0x44B7; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_REGION_8_9__VI = 0x44B8; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_SLOPE_CNTL__VI = 0x44B1; +constexpr unsigned int mmDCP5_REGAMMA_CNTLB_START_CNTL__VI = 0x44B0; +constexpr unsigned int mmDCP5_REGAMMA_CONTROL__VI = 0x44A0; +constexpr unsigned int mmDCP5_REGAMMA_LUT_DATA__VI = 0x44A2; +constexpr unsigned int mmDCP5_REGAMMA_LUT_INDEX__VI = 0x44A1; +constexpr unsigned int mmDCP5_REGAMMA_LUT_WRITE_EN_MASK__VI = 0x44A3; +constexpr unsigned int mmDCPG_TEST_DEBUG_DATA__VI = 0x02D7; +constexpr unsigned int mmDCPG_TEST_DEBUG_INDEX__VI = 0x02D6; +constexpr unsigned int mmDCP_DEBUG2__VI = 0x1A98; +constexpr unsigned int mmDCP_FP_CONVERTED_FIELD__VI = 0x1A65; +constexpr unsigned int mmDCP_GSL_CONTROL__VI = 0x1A90; +constexpr unsigned int mmDCP_RANDOM_SEEDS__VI = 0x1A61; +constexpr unsigned int mmDCP_SPATIAL_DITHER_CNTL__VI = 0x1A60; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED0__VI = 0x5A84; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED1__VI = 0x5A85; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED10__VI = 0x5A8E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED100__VI = 0x5AE8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED101__VI = 0x5AE9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED102__VI = 0x5AEA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED103__VI = 0x5AEB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED104__VI = 0x5AEC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED105__VI = 0x5AED; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED106__VI = 0x5AEE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED107__VI = 0x5AEF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED108__VI = 0x5AF0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED109__VI = 0x5AF1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED11__VI = 0x5A8F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED110__VI = 0x5AF2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED111__VI = 0x5AF3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED112__VI = 0x5AF4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED113__VI = 0x5AF5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED114__VI = 0x5AF6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED115__VI = 0x5AF7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED116__VI = 0x5AF8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED117__VI = 0x5AF9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED118__VI = 0x5AFA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED119__VI = 0x5AFB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED12__VI = 0x5A90; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED120__VI = 0x5AFC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED121__VI = 0x5AFD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED122__VI = 0x5AFE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED123__VI = 0x5AFF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED124__VI = 0x5B00; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED125__VI = 0x5B01; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED126__VI = 0x5B02; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED127__VI = 0x5B03; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED128__VI = 0x5B04; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED129__VI = 0x5B05; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED13__VI = 0x5A91; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED130__VI = 0x5B06; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED131__VI = 0x5B07; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED132__VI = 0x5B08; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED133__VI = 0x5B09; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED134__VI = 0x5B0A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED135__VI = 0x5B0B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED136__VI = 0x5B0C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED137__VI = 0x5B0D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED138__VI = 0x5B0E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED139__VI = 0x5B0F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED14__VI = 0x5A92; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED140__VI = 0x5B10; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED141__VI = 0x5B11; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED142__VI = 0x5B12; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED143__VI = 0x5B13; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED144__VI = 0x5B14; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED145__VI = 0x5B15; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED146__VI = 0x5B16; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED147__VI = 0x5B17; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED148__VI = 0x5B18; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED149__VI = 0x5B19; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED15__VI = 0x5A93; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED150__VI = 0x5B1A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED151__VI = 0x5B1B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED152__VI = 0x5B1C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED153__VI = 0x5B1D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED154__VI = 0x5B1E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED155__VI = 0x5B1F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED156__VI = 0x5B20; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED157__VI = 0x5B21; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED158__VI = 0x5B22; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED159__VI = 0x5B23; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED16__VI = 0x5A94; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED160__VI = 0x5B24; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED161__VI = 0x5B25; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED162__VI = 0x5B26; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED163__VI = 0x5B27; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED164__VI = 0x5B28; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED165__VI = 0x5B29; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED166__VI = 0x5B2A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED167__VI = 0x5B2B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED168__VI = 0x5B2C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED169__VI = 0x5B2D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED17__VI = 0x5A95; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED170__VI = 0x5B2E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED171__VI = 0x5B2F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED172__VI = 0x5B30; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED173__VI = 0x5B31; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED174__VI = 0x5B32; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED175__VI = 0x5B33; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED176__VI = 0x5B34; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED177__VI = 0x5B35; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED178__VI = 0x5B36; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED179__VI = 0x5B37; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED18__VI = 0x5A96; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED180__VI = 0x5B38; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED181__VI = 0x5B39; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED182__VI = 0x5B3A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED183__VI = 0x5B3B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED184__VI = 0x5B3C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED185__VI = 0x5B3D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED186__VI = 0x5B3E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED187__VI = 0x5B3F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED188__VI = 0x5B40; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED189__VI = 0x5B41; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED19__VI = 0x5A97; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED190__VI = 0x5B42; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED191__VI = 0x5B43; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED192__VI = 0x5B44; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED193__VI = 0x5B45; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED194__VI = 0x5B46; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED195__VI = 0x5B47; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED196__VI = 0x5B48; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED197__VI = 0x5B49; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED198__VI = 0x5B4A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED199__VI = 0x5B4B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED2__VI = 0x5A86; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED20__VI = 0x5A98; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED200__VI = 0x5B4C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED201__VI = 0x5B4D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED202__VI = 0x5B4E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED203__VI = 0x5B4F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED204__VI = 0x5B50; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED205__VI = 0x5B51; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED206__VI = 0x5B52; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED207__VI = 0x5B53; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED208__VI = 0x5B54; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED209__VI = 0x5B55; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED21__VI = 0x5A99; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED210__VI = 0x5B56; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED211__VI = 0x5B57; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED212__VI = 0x5B58; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED213__VI = 0x5B59; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED214__VI = 0x5B5A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED215__VI = 0x5B5B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED216__VI = 0x5B5C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED217__VI = 0x5B5D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED218__VI = 0x5B5E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED219__VI = 0x5B5F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED22__VI = 0x5A9A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED220__VI = 0x5B60; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED221__VI = 0x5B61; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED222__VI = 0x5B62; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED223__VI = 0x5B63; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED224__VI = 0x5B64; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED225__VI = 0x5B65; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED226__VI = 0x5B66; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED227__VI = 0x5B67; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED228__VI = 0x5B68; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED229__VI = 0x5B69; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED23__VI = 0x5A9B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED230__VI = 0x5B6A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED231__VI = 0x5B6B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED232__VI = 0x5B6C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED233__VI = 0x5B6D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED234__VI = 0x5B6E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED235__VI = 0x5B6F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED236__VI = 0x5B70; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED237__VI = 0x5B71; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED238__VI = 0x5B72; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED239__VI = 0x5B73; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED24__VI = 0x5A9C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED240__VI = 0x5B74; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED241__VI = 0x5B75; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED242__VI = 0x5B76; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED243__VI = 0x5B77; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED244__VI = 0x5B78; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED245__VI = 0x5B79; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED246__VI = 0x5B7A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED247__VI = 0x5B7B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED248__VI = 0x5B7C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED249__VI = 0x5B7D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED25__VI = 0x5A9D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED250__VI = 0x5B7E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED251__VI = 0x5B7F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED252__VI = 0x5B80; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED253__VI = 0x5B81; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED254__VI = 0x5B82; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED255__VI = 0x5B83; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED256__VI = 0x5B84; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED257__VI = 0x5B85; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED258__VI = 0x5B86; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED259__VI = 0x5B87; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED26__VI = 0x5A9E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED260__VI = 0x5B88; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED261__VI = 0x5B89; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED262__VI = 0x5B8A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED263__VI = 0x5B8B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED264__VI = 0x5B8C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED265__VI = 0x5B8D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED266__VI = 0x5B8E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED267__VI = 0x5B8F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED268__VI = 0x5B90; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED269__VI = 0x5B91; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED27__VI = 0x5A9F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED270__VI = 0x5B92; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED271__VI = 0x5B93; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED272__VI = 0x5B94; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED273__VI = 0x5B95; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED274__VI = 0x5B96; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED275__VI = 0x5B97; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED276__VI = 0x5B98; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED277__VI = 0x5B99; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED278__VI = 0x5B9A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED279__VI = 0x5B9B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED28__VI = 0x5AA0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED280__VI = 0x5B9C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED281__VI = 0x5B9D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED282__VI = 0x5B9E; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED283__VI = 0x5B9F; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED284__VI = 0x5BA0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED285__VI = 0x5BA1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED286__VI = 0x5BA2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED287__VI = 0x5BA3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED288__VI = 0x5BA4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED289__VI = 0x5BA5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED29__VI = 0x5AA1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED290__VI = 0x5BA6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED291__VI = 0x5BA7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED292__VI = 0x5BA8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED293__VI = 0x5BA9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED294__VI = 0x5BAA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED295__VI = 0x5BAB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED296__VI = 0x5BAC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED297__VI = 0x5BAD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED298__VI = 0x5BAE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED299__VI = 0x5BAF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED3__VI = 0x5A87; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED30__VI = 0x5AA2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED300__VI = 0x5BB0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED301__VI = 0x5BB1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED302__VI = 0x5BB2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED303__VI = 0x5BB3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED304__VI = 0x5BB4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED305__VI = 0x5BB5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED306__VI = 0x5BB6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED307__VI = 0x5BB7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED308__VI = 0x5BB8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED309__VI = 0x5BB9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED31__VI = 0x5AA3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED310__VI = 0x5BBA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED311__VI = 0x5BBB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED312__VI = 0x5BBC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED313__VI = 0x5BBD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED314__VI = 0x5BBE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED315__VI = 0x5BBF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED316__VI = 0x5BC0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED317__VI = 0x5BC1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED318__VI = 0x5BC2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED319__VI = 0x5BC3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED32__VI = 0x5AA4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED320__VI = 0x5BC4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED321__VI = 0x5BC5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED322__VI = 0x5BC6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED323__VI = 0x5BC7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED324__VI = 0x5BC8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED325__VI = 0x5BC9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED326__VI = 0x5BCA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED327__VI = 0x5BCB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED328__VI = 0x5BCC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED329__VI = 0x5BCD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED33__VI = 0x5AA5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED330__VI = 0x5BCE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED331__VI = 0x5BCF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED332__VI = 0x5BD0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED333__VI = 0x5BD1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED334__VI = 0x5BD2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED335__VI = 0x5BD3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED336__VI = 0x5BD4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED337__VI = 0x5BD5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED338__VI = 0x5BD6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED339__VI = 0x5BD7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED34__VI = 0x5AA6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED340__VI = 0x5BD8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED341__VI = 0x5BD9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED342__VI = 0x5BDA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED343__VI = 0x5BDB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED344__VI = 0x5BDC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED345__VI = 0x5BDD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED346__VI = 0x5BDE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED347__VI = 0x5BDF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED348__VI = 0x5BE0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED349__VI = 0x5BE1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED35__VI = 0x5AA7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED350__VI = 0x5BE2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED351__VI = 0x5BE3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED352__VI = 0x5BE4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED353__VI = 0x5BE5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED354__VI = 0x5BE6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED355__VI = 0x5BE7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED356__VI = 0x5BE8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED357__VI = 0x5BE9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED358__VI = 0x5BEA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED359__VI = 0x5BEB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED36__VI = 0x5AA8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED360__VI = 0x5BEC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED361__VI = 0x5BED; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED362__VI = 0x5BEE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED363__VI = 0x5BEF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED364__VI = 0x5BF0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED365__VI = 0x5BF1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED366__VI = 0x5BF2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED367__VI = 0x5BF3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED368__VI = 0x5BF4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED369__VI = 0x5BF5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED37__VI = 0x5AA9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED370__VI = 0x5BF6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED371__VI = 0x5BF7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED372__VI = 0x5BF8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED373__VI = 0x5BF9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED374__VI = 0x5BFA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED375__VI = 0x5BFB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED376__VI = 0x5BFC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED377__VI = 0x5BFD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED378__VI = 0x5BFE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED379__VI = 0x5BFF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED38__VI = 0x5AAA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED39__VI = 0x5AAB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED4__VI = 0x5A88; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED40__VI = 0x5AAC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED41__VI = 0x5AAD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED42__VI = 0x5AAE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED43__VI = 0x5AAF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED44__VI = 0x5AB0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED45__VI = 0x5AB1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED46__VI = 0x5AB2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED47__VI = 0x5AB3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED48__VI = 0x5AB4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED49__VI = 0x5AB5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED5__VI = 0x5A89; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED50__VI = 0x5AB6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED51__VI = 0x5AB7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED52__VI = 0x5AB8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED53__VI = 0x5AB9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED54__VI = 0x5ABA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED55__VI = 0x5ABB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED56__VI = 0x5ABC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED57__VI = 0x5ABD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED58__VI = 0x5ABE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED59__VI = 0x5ABF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED6__VI = 0x5A8A; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED60__VI = 0x5AC0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED61__VI = 0x5AC1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED62__VI = 0x5AC2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED63__VI = 0x5AC3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED64__VI = 0x5AC4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED65__VI = 0x5AC5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED66__VI = 0x5AC6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED67__VI = 0x5AC7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED68__VI = 0x5AC8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED69__VI = 0x5AC9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED7__VI = 0x5A8B; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED70__VI = 0x5ACA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED71__VI = 0x5ACB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED72__VI = 0x5ACC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED73__VI = 0x5ACD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED74__VI = 0x5ACE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED75__VI = 0x5ACF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED76__VI = 0x5AD0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED77__VI = 0x5AD1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED78__VI = 0x5AD2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED79__VI = 0x5AD3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED8__VI = 0x5A8C; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED80__VI = 0x5AD4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED81__VI = 0x5AD5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED82__VI = 0x5AD6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED83__VI = 0x5AD7; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED84__VI = 0x5AD8; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED85__VI = 0x5AD9; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED86__VI = 0x5ADA; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED87__VI = 0x5ADB; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED88__VI = 0x5ADC; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED89__VI = 0x5ADD; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED9__VI = 0x5A8D; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED90__VI = 0x5ADE; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED91__VI = 0x5ADF; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED92__VI = 0x5AE0; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED93__VI = 0x5AE1; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED94__VI = 0x5AE2; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED95__VI = 0x5AE3; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED96__VI = 0x5AE4; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED97__VI = 0x5AE5; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED98__VI = 0x5AE6; +constexpr unsigned int mmDCRX_PHY_MACRO_CNTL_RESERVED99__VI = 0x5AE7; +constexpr unsigned int mmDC_ABM1_OVERSCAN_PIXEL_VALUE__VI = 0x169B; +constexpr unsigned int mmDC_DVODATA_CONFIG__VI = 0x481A; +constexpr unsigned int mmDC_GENERICA__VI = 0x4800; +constexpr unsigned int mmDC_GENERICB__VI = 0x4801; +constexpr unsigned int mmDC_GPIO_DDC1_A__VI = 0x4869; +constexpr unsigned int mmDC_GPIO_DDC1_EN__VI = 0x486A; +constexpr unsigned int mmDC_GPIO_DDC1_MASK__VI = 0x4868; +constexpr unsigned int mmDC_GPIO_DDC1_Y__VI = 0x486B; +constexpr unsigned int mmDC_GPIO_DDC2_A__VI = 0x486D; +constexpr unsigned int mmDC_GPIO_DDC2_EN__VI = 0x486E; +constexpr unsigned int mmDC_GPIO_DDC2_MASK__VI = 0x486C; +constexpr unsigned int mmDC_GPIO_DDC2_Y__VI = 0x486F; +constexpr unsigned int mmDC_GPIO_DDC3_A__VI = 0x4871; +constexpr unsigned int mmDC_GPIO_DDC3_EN__VI = 0x4872; +constexpr unsigned int mmDC_GPIO_DDC3_MASK__VI = 0x4870; +constexpr unsigned int mmDC_GPIO_DDC3_Y__VI = 0x4873; +constexpr unsigned int mmDC_GPIO_DDC4_A__VI = 0x4875; +constexpr unsigned int mmDC_GPIO_DDC4_EN__VI = 0x4876; +constexpr unsigned int mmDC_GPIO_DDC4_MASK__VI = 0x4874; +constexpr unsigned int mmDC_GPIO_DDC4_Y__VI = 0x4877; +constexpr unsigned int mmDC_GPIO_DDC5_A__VI = 0x4879; +constexpr unsigned int mmDC_GPIO_DDC5_EN__VI = 0x487A; +constexpr unsigned int mmDC_GPIO_DDC5_MASK__VI = 0x4878; +constexpr unsigned int mmDC_GPIO_DDC5_Y__VI = 0x487B; +constexpr unsigned int mmDC_GPIO_DDC6_A__VI = 0x487D; +constexpr unsigned int mmDC_GPIO_DDC6_EN__VI = 0x487E; +constexpr unsigned int mmDC_GPIO_DDC6_MASK__VI = 0x487C; +constexpr unsigned int mmDC_GPIO_DDC6_Y__VI = 0x487F; +constexpr unsigned int mmDC_GPIO_DDCVGA_A__VI = 0x4881; +constexpr unsigned int mmDC_GPIO_DDCVGA_EN__VI = 0x4882; +constexpr unsigned int mmDC_GPIO_DDCVGA_MASK__VI = 0x4880; +constexpr unsigned int mmDC_GPIO_DDCVGA_Y__VI = 0x4883; +constexpr unsigned int mmDC_GPIO_DEBUG__VI = 0x4804; +constexpr unsigned int mmDC_GPIO_DVODATA_A__VI = 0x4865; +constexpr unsigned int mmDC_GPIO_DVODATA_EN__VI = 0x4866; +constexpr unsigned int mmDC_GPIO_DVODATA_MASK__VI = 0x4864; +constexpr unsigned int mmDC_GPIO_DVODATA_Y__VI = 0x4867; +constexpr unsigned int mmDC_GPIO_GENERIC_A__VI = 0x4861; +constexpr unsigned int mmDC_GPIO_GENERIC_EN__VI = 0x4862; +constexpr unsigned int mmDC_GPIO_GENERIC_MASK__VI = 0x4860; +constexpr unsigned int mmDC_GPIO_GENERIC_Y__VI = 0x4863; +constexpr unsigned int mmDC_GPIO_GENLK_A__VI = 0x4889; +constexpr unsigned int mmDC_GPIO_GENLK_EN__VI = 0x488A; +constexpr unsigned int mmDC_GPIO_GENLK_MASK__VI = 0x4888; +constexpr unsigned int mmDC_GPIO_GENLK_Y__VI = 0x488B; +constexpr unsigned int mmDC_GPIO_HPD_A__VI = 0x488D; +constexpr unsigned int mmDC_GPIO_HPD_EN__VI = 0x488E; +constexpr unsigned int mmDC_GPIO_HPD_MASK__VI = 0x488C; +constexpr unsigned int mmDC_GPIO_HPD_Y__VI = 0x488F; +constexpr unsigned int mmDC_GPIO_I2CPAD_A__VI = 0x4899; +constexpr unsigned int mmDC_GPIO_I2CPAD_EN__VI = 0x489A; +constexpr unsigned int mmDC_GPIO_I2CPAD_MASK__VI = 0x4898; +constexpr unsigned int mmDC_GPIO_I2CPAD_STRENGTH__VI = 0x489C; +constexpr unsigned int mmDC_GPIO_I2CPAD_Y__VI = 0x489B; +constexpr unsigned int mmDC_GPIO_PAD_STRENGTH_1__VI = 0x4894; +constexpr unsigned int mmDC_GPIO_PAD_STRENGTH_2__VI = 0x4895; +constexpr unsigned int mmDC_GPIO_PWRSEQ_A__VI = 0x4891; +constexpr unsigned int mmDC_GPIO_PWRSEQ_EN__VI = 0x4892; +constexpr unsigned int mmDC_GPIO_PWRSEQ_MASK__VI = 0x4890; +constexpr unsigned int mmDC_GPIO_PWRSEQ_Y__VI = 0x4893; +constexpr unsigned int mmDC_GPIO_SYNCA_A__VI = 0x4885; +constexpr unsigned int mmDC_GPIO_SYNCA_EN__VI = 0x4886; +constexpr unsigned int mmDC_GPIO_SYNCA_MASK__VI = 0x4884; +constexpr unsigned int mmDC_GPIO_SYNCA_Y__VI = 0x4887; +constexpr unsigned int mmDC_GPU_TIMER_READ__VI = 0x482B; +constexpr unsigned int mmDC_GPU_TIMER_READ_CNTL__VI = 0x482C; +constexpr unsigned int mmDC_GPU_TIMER_START_POSITION_P_FLIP__VI = 0x482A; +constexpr unsigned int mmDC_GPU_TIMER_START_POSITION_V_UPDATE__VI = 0x4829; +constexpr unsigned int mmDC_HPD_CONTROL__VI = 0x189A; +constexpr unsigned int mmDC_HPD_FAST_TRAIN_CNTL__VI = 0x189B; +constexpr unsigned int mmDC_HPD_INT_CONTROL__VI = 0x1899; +constexpr unsigned int mmDC_HPD_INT_STATUS__VI = 0x1898; +constexpr unsigned int mmDC_HPD_TOGGLE_FILT_CNTL__VI = 0x189C; +constexpr unsigned int mmDC_I2C_ARBITRATION__VI = 0x16D5; +constexpr unsigned int mmDC_I2C_CONTROL__VI = 0x16D4; +constexpr unsigned int mmDC_I2C_DATA__VI = 0x16EE; +constexpr unsigned int mmDC_I2C_DDC1_HW_STATUS__VI = 0x16D8; +constexpr unsigned int mmDC_I2C_DDC1_SETUP__VI = 0x16DF; +constexpr unsigned int mmDC_I2C_DDC1_SPEED__VI = 0x16DE; +constexpr unsigned int mmDC_I2C_DDC2_HW_STATUS__VI = 0x16D9; +constexpr unsigned int mmDC_I2C_DDC2_SETUP__VI = 0x16E1; +constexpr unsigned int mmDC_I2C_DDC2_SPEED__VI = 0x16E0; +constexpr unsigned int mmDC_I2C_DDC3_HW_STATUS__VI = 0x16DA; +constexpr unsigned int mmDC_I2C_DDC3_SETUP__VI = 0x16E3; +constexpr unsigned int mmDC_I2C_DDC3_SPEED__VI = 0x16E2; +constexpr unsigned int mmDC_I2C_DDC4_HW_STATUS__VI = 0x16DB; +constexpr unsigned int mmDC_I2C_DDC4_SETUP__VI = 0x16E5; +constexpr unsigned int mmDC_I2C_DDC4_SPEED__VI = 0x16E4; +constexpr unsigned int mmDC_I2C_DDC5_HW_STATUS__VI = 0x16DC; +constexpr unsigned int mmDC_I2C_DDC5_SETUP__VI = 0x16E7; +constexpr unsigned int mmDC_I2C_DDC5_SPEED__VI = 0x16E6; +constexpr unsigned int mmDC_I2C_DDC6_HW_STATUS__VI = 0x16DD; +constexpr unsigned int mmDC_I2C_DDC6_SETUP__VI = 0x16E9; +constexpr unsigned int mmDC_I2C_DDC6_SPEED__VI = 0x16E8; +constexpr unsigned int mmDC_I2C_DDCVGA_HW_STATUS__VI = 0x16EF; +constexpr unsigned int mmDC_I2C_DDCVGA_SETUP__VI = 0x16F1; +constexpr unsigned int mmDC_I2C_DDCVGA_SPEED__VI = 0x16F0; +constexpr unsigned int mmDC_I2C_EDID_DETECT_CTRL__VI = 0x16F2; +constexpr unsigned int mmDC_I2C_INTERRUPT_CONTROL__VI = 0x16D6; +constexpr unsigned int mmDC_I2C_SW_STATUS__VI = 0x16D7; +constexpr unsigned int mmDC_I2C_TRANSACTION0__VI = 0x16EA; +constexpr unsigned int mmDC_I2C_TRANSACTION1__VI = 0x16EB; +constexpr unsigned int mmDC_I2C_TRANSACTION2__VI = 0x16EC; +constexpr unsigned int mmDC_I2C_TRANSACTION3__VI = 0x16ED; +constexpr unsigned int mmDC_IP_REQUEST_CNTL__VI = 0x02D2; +constexpr unsigned int mmDC_LUT_VGA_ACCESS_ENABLE__VI = 0x1A7D; +constexpr unsigned int mmDC_MEM_GLOBAL_PWR_REQ_CNTL__VI = 0x0132; +constexpr unsigned int mmDC_MVP_LB_CONTROL__VI = 0x1AE3; +constexpr unsigned int mmDC_PAD_EXTERN_SIG__VI = 0x4802; +constexpr unsigned int mmDC_PERFMON0_PERFCOUNTER_CNTL__VI = 0x0170; +constexpr unsigned int mmDC_PERFMON0_PERFCOUNTER_STATE__VI = 0x0171; +constexpr unsigned int mmDC_PERFMON0_PERFMON_CNTL__VI = 0x0173; +constexpr unsigned int mmDC_PERFMON0_PERFMON_CNTL2__VI = 0x017A; +constexpr unsigned int mmDC_PERFMON0_PERFMON_CVALUE_INT_MISC__VI = 0x0172; +constexpr unsigned int mmDC_PERFMON0_PERFMON_CVALUE_LOW__VI = 0x0174; +constexpr unsigned int mmDC_PERFMON0_PERFMON_HI__VI = 0x0175; +constexpr unsigned int mmDC_PERFMON0_PERFMON_LOW__VI = 0x0176; +constexpr unsigned int mmDC_PERFMON0_PERFMON_TEST_DEBUG_DATA__VI = 0x0178; +constexpr unsigned int mmDC_PERFMON0_PERFMON_TEST_DEBUG_INDEX__VI = 0x0177; +constexpr unsigned int mmDC_PERFMON10_PERFCOUNTER_CNTL__VI = 0x59A0; +constexpr unsigned int mmDC_PERFMON10_PERFCOUNTER_STATE__VI = 0x59A1; +constexpr unsigned int mmDC_PERFMON10_PERFMON_CNTL__VI = 0x59A3; +constexpr unsigned int mmDC_PERFMON10_PERFMON_CNTL2__VI = 0x59AA; +constexpr unsigned int mmDC_PERFMON10_PERFMON_CVALUE_INT_MISC__VI = 0x59A2; +constexpr unsigned int mmDC_PERFMON10_PERFMON_CVALUE_LOW__VI = 0x59A4; +constexpr unsigned int mmDC_PERFMON10_PERFMON_HI__VI = 0x59A5; +constexpr unsigned int mmDC_PERFMON10_PERFMON_LOW__VI = 0x59A6; +constexpr unsigned int mmDC_PERFMON10_PERFMON_TEST_DEBUG_DATA__VI = 0x59A8; +constexpr unsigned int mmDC_PERFMON10_PERFMON_TEST_DEBUG_INDEX__VI = 0x59A7; +constexpr unsigned int mmDC_PERFMON11_PERFCOUNTER_CNTL__VI = 0x4724; +constexpr unsigned int mmDC_PERFMON11_PERFCOUNTER_STATE__VI = 0x4725; +constexpr unsigned int mmDC_PERFMON11_PERFMON_CNTL__VI = 0x4727; +constexpr unsigned int mmDC_PERFMON11_PERFMON_CNTL2__VI = 0x472E; +constexpr unsigned int mmDC_PERFMON11_PERFMON_CVALUE_INT_MISC__VI = 0x4726; +constexpr unsigned int mmDC_PERFMON11_PERFMON_CVALUE_LOW__VI = 0x4728; +constexpr unsigned int mmDC_PERFMON11_PERFMON_HI__VI = 0x4729; +constexpr unsigned int mmDC_PERFMON11_PERFMON_LOW__VI = 0x472A; +constexpr unsigned int mmDC_PERFMON11_PERFMON_TEST_DEBUG_DATA__VI = 0x472C; +constexpr unsigned int mmDC_PERFMON11_PERFMON_TEST_DEBUG_INDEX__VI = 0x472B; +constexpr unsigned int mmDC_PERFMON1_PERFCOUNTER_CNTL__VI = 0x0364; +constexpr unsigned int mmDC_PERFMON1_PERFCOUNTER_STATE__VI = 0x0365; +constexpr unsigned int mmDC_PERFMON1_PERFMON_CNTL__VI = 0x0367; +constexpr unsigned int mmDC_PERFMON1_PERFMON_CNTL2__VI = 0x036E; +constexpr unsigned int mmDC_PERFMON1_PERFMON_CVALUE_INT_MISC__VI = 0x0366; +constexpr unsigned int mmDC_PERFMON1_PERFMON_CVALUE_LOW__VI = 0x0368; +constexpr unsigned int mmDC_PERFMON1_PERFMON_HI__VI = 0x0369; +constexpr unsigned int mmDC_PERFMON1_PERFMON_LOW__VI = 0x036A; +constexpr unsigned int mmDC_PERFMON1_PERFMON_TEST_DEBUG_DATA__VI = 0x036C; +constexpr unsigned int mmDC_PERFMON1_PERFMON_TEST_DEBUG_INDEX__VI = 0x036B; +constexpr unsigned int mmDC_PERFMON2_PERFCOUNTER_CNTL__VI = 0x18C8; +constexpr unsigned int mmDC_PERFMON2_PERFCOUNTER_STATE__VI = 0x18C9; +constexpr unsigned int mmDC_PERFMON2_PERFMON_CNTL__VI = 0x18CB; +constexpr unsigned int mmDC_PERFMON2_PERFMON_CNTL2__VI = 0x18D2; +constexpr unsigned int mmDC_PERFMON2_PERFMON_CVALUE_INT_MISC__VI = 0x18CA; +constexpr unsigned int mmDC_PERFMON2_PERFMON_CVALUE_LOW__VI = 0x18CC; +constexpr unsigned int mmDC_PERFMON2_PERFMON_HI__VI = 0x18CD; +constexpr unsigned int mmDC_PERFMON2_PERFMON_LOW__VI = 0x18CE; +constexpr unsigned int mmDC_PERFMON2_PERFMON_TEST_DEBUG_DATA__VI = 0x18D0; +constexpr unsigned int mmDC_PERFMON2_PERFMON_TEST_DEBUG_INDEX__VI = 0x18CF; +constexpr unsigned int mmDC_PERFMON3_PERFCOUNTER_CNTL__VI = 0x1B24; +constexpr unsigned int mmDC_PERFMON3_PERFCOUNTER_STATE__VI = 0x1B25; +constexpr unsigned int mmDC_PERFMON3_PERFMON_CNTL__VI = 0x1B27; +constexpr unsigned int mmDC_PERFMON3_PERFMON_CNTL2__VI = 0x1B2E; +constexpr unsigned int mmDC_PERFMON3_PERFMON_CVALUE_INT_MISC__VI = 0x1B26; +constexpr unsigned int mmDC_PERFMON3_PERFMON_CVALUE_LOW__VI = 0x1B28; +constexpr unsigned int mmDC_PERFMON3_PERFMON_HI__VI = 0x1B29; +constexpr unsigned int mmDC_PERFMON3_PERFMON_LOW__VI = 0x1B2A; +constexpr unsigned int mmDC_PERFMON3_PERFMON_TEST_DEBUG_DATA__VI = 0x1B2C; +constexpr unsigned int mmDC_PERFMON3_PERFMON_TEST_DEBUG_INDEX__VI = 0x1B2B; +constexpr unsigned int mmDC_PERFMON4_PERFCOUNTER_CNTL__VI = 0x1D24; +constexpr unsigned int mmDC_PERFMON4_PERFCOUNTER_STATE__VI = 0x1D25; +constexpr unsigned int mmDC_PERFMON4_PERFMON_CNTL__VI = 0x1D27; +constexpr unsigned int mmDC_PERFMON4_PERFMON_CNTL2__VI = 0x1D2E; +constexpr unsigned int mmDC_PERFMON4_PERFMON_CVALUE_INT_MISC__VI = 0x1D26; +constexpr unsigned int mmDC_PERFMON4_PERFMON_CVALUE_LOW__VI = 0x1D28; +constexpr unsigned int mmDC_PERFMON4_PERFMON_HI__VI = 0x1D29; +constexpr unsigned int mmDC_PERFMON4_PERFMON_LOW__VI = 0x1D2A; +constexpr unsigned int mmDC_PERFMON4_PERFMON_TEST_DEBUG_DATA__VI = 0x1D2C; +constexpr unsigned int mmDC_PERFMON4_PERFMON_TEST_DEBUG_INDEX__VI = 0x1D2B; +constexpr unsigned int mmDC_PERFMON5_PERFCOUNTER_CNTL__VI = 0x1F24; +constexpr unsigned int mmDC_PERFMON5_PERFCOUNTER_STATE__VI = 0x1F25; +constexpr unsigned int mmDC_PERFMON5_PERFMON_CNTL__VI = 0x1F27; +constexpr unsigned int mmDC_PERFMON5_PERFMON_CNTL2__VI = 0x1F2E; +constexpr unsigned int mmDC_PERFMON5_PERFMON_CVALUE_INT_MISC__VI = 0x1F26; +constexpr unsigned int mmDC_PERFMON5_PERFMON_CVALUE_LOW__VI = 0x1F28; +constexpr unsigned int mmDC_PERFMON5_PERFMON_HI__VI = 0x1F29; +constexpr unsigned int mmDC_PERFMON5_PERFMON_LOW__VI = 0x1F2A; +constexpr unsigned int mmDC_PERFMON5_PERFMON_TEST_DEBUG_DATA__VI = 0x1F2C; +constexpr unsigned int mmDC_PERFMON5_PERFMON_TEST_DEBUG_INDEX__VI = 0x1F2B; +constexpr unsigned int mmDC_PERFMON6_PERFCOUNTER_CNTL__VI = 0x4124; +constexpr unsigned int mmDC_PERFMON6_PERFCOUNTER_STATE__VI = 0x4125; +constexpr unsigned int mmDC_PERFMON6_PERFMON_CNTL__VI = 0x4127; +constexpr unsigned int mmDC_PERFMON6_PERFMON_CNTL2__VI = 0x412E; +constexpr unsigned int mmDC_PERFMON6_PERFMON_CVALUE_INT_MISC__VI = 0x4126; +constexpr unsigned int mmDC_PERFMON6_PERFMON_CVALUE_LOW__VI = 0x4128; +constexpr unsigned int mmDC_PERFMON6_PERFMON_HI__VI = 0x4129; +constexpr unsigned int mmDC_PERFMON6_PERFMON_LOW__VI = 0x412A; +constexpr unsigned int mmDC_PERFMON6_PERFMON_TEST_DEBUG_DATA__VI = 0x412C; +constexpr unsigned int mmDC_PERFMON6_PERFMON_TEST_DEBUG_INDEX__VI = 0x412B; +constexpr unsigned int mmDC_PERFMON7_PERFCOUNTER_CNTL__VI = 0x4324; +constexpr unsigned int mmDC_PERFMON7_PERFCOUNTER_STATE__VI = 0x4325; +constexpr unsigned int mmDC_PERFMON7_PERFMON_CNTL__VI = 0x4327; +constexpr unsigned int mmDC_PERFMON7_PERFMON_CNTL2__VI = 0x432E; +constexpr unsigned int mmDC_PERFMON7_PERFMON_CVALUE_INT_MISC__VI = 0x4326; +constexpr unsigned int mmDC_PERFMON7_PERFMON_CVALUE_LOW__VI = 0x4328; +constexpr unsigned int mmDC_PERFMON7_PERFMON_HI__VI = 0x4329; +constexpr unsigned int mmDC_PERFMON7_PERFMON_LOW__VI = 0x432A; +constexpr unsigned int mmDC_PERFMON7_PERFMON_TEST_DEBUG_DATA__VI = 0x432C; +constexpr unsigned int mmDC_PERFMON7_PERFMON_TEST_DEBUG_INDEX__VI = 0x432B; +constexpr unsigned int mmDC_PERFMON8_PERFCOUNTER_CNTL__VI = 0x4524; +constexpr unsigned int mmDC_PERFMON8_PERFCOUNTER_STATE__VI = 0x4525; +constexpr unsigned int mmDC_PERFMON8_PERFMON_CNTL__VI = 0x4527; +constexpr unsigned int mmDC_PERFMON8_PERFMON_CNTL2__VI = 0x452E; +constexpr unsigned int mmDC_PERFMON8_PERFMON_CVALUE_INT_MISC__VI = 0x4526; +constexpr unsigned int mmDC_PERFMON8_PERFMON_CVALUE_LOW__VI = 0x4528; +constexpr unsigned int mmDC_PERFMON8_PERFMON_HI__VI = 0x4529; +constexpr unsigned int mmDC_PERFMON8_PERFMON_LOW__VI = 0x452A; +constexpr unsigned int mmDC_PERFMON8_PERFMON_TEST_DEBUG_DATA__VI = 0x452C; +constexpr unsigned int mmDC_PERFMON8_PERFMON_TEST_DEBUG_INDEX__VI = 0x452B; +constexpr unsigned int mmDC_PERFMON9_PERFCOUNTER_CNTL__VI = 0x5F68; +constexpr unsigned int mmDC_PERFMON9_PERFCOUNTER_STATE__VI = 0x5F69; +constexpr unsigned int mmDC_PERFMON9_PERFMON_CNTL__VI = 0x5F6B; +constexpr unsigned int mmDC_PERFMON9_PERFMON_CNTL2__VI = 0x5F72; +constexpr unsigned int mmDC_PERFMON9_PERFMON_CVALUE_INT_MISC__VI = 0x5F6A; +constexpr unsigned int mmDC_PERFMON9_PERFMON_CVALUE_LOW__VI = 0x5F6C; +constexpr unsigned int mmDC_PERFMON9_PERFMON_HI__VI = 0x5F6D; +constexpr unsigned int mmDC_PERFMON9_PERFMON_LOW__VI = 0x5F6E; +constexpr unsigned int mmDC_PERFMON9_PERFMON_TEST_DEBUG_DATA__VI = 0x5F70; +constexpr unsigned int mmDC_PERFMON9_PERFMON_TEST_DEBUG_INDEX__VI = 0x5F6F; +constexpr unsigned int mmDC_PGCNTL_STATUS_REG__VI = 0x02D5; +constexpr unsigned int mmDC_PGFSM_CONFIG_REG__VI = 0x02D3; +constexpr unsigned int mmDC_PGFSM_WRITE_REG__VI = 0x02D4; +constexpr unsigned int mmDC_PINSTRAPS__VI = 0x4818; +constexpr unsigned int mmDC_REF_CLK_CNTL__VI = 0x4803; +constexpr unsigned int mmDC_TEST_DEBUG_DATA__VI = 0x157D; +constexpr unsigned int mmDC_TEST_DEBUG_INDEX__VI = 0x157C; +constexpr unsigned int mmDEGAMMA_CONTROL__VI = 0x1A58; +constexpr unsigned int mmDENORM_CLAMP_CONTROL__VI = 0x46C3; +constexpr unsigned int mmDENORM_CLAMP_RANGE_B_CB__VI = 0x46C6; +constexpr unsigned int mmDENORM_CLAMP_RANGE_G_Y__VI = 0x46C5; +constexpr unsigned int mmDENORM_CLAMP_RANGE_R_CR__VI = 0x46C4; +constexpr unsigned int mmDENORM_CONTROL__VI = 0x1A50; +constexpr unsigned int mmDENTIST_DISPCLK_CNTL__VI = 0x0124; +constexpr unsigned int mmDIG0_AFMT_60958_0__VI = 0x4A38; +constexpr unsigned int mmDIG0_AFMT_60958_1__VI = 0x4A39; +constexpr unsigned int mmDIG0_AFMT_60958_2__VI = 0x4A3F; +constexpr unsigned int mmDIG0_AFMT_AUDIO_CRC_CONTROL__VI = 0x4A3A; +constexpr unsigned int mmDIG0_AFMT_AUDIO_CRC_RESULT__VI = 0x4A40; +constexpr unsigned int mmDIG0_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4A46; +constexpr unsigned int mmDIG0_AFMT_AUDIO_INFO0__VI = 0x4A36; +constexpr unsigned int mmDIG0_AFMT_AUDIO_INFO1__VI = 0x4A37; +constexpr unsigned int mmDIG0_AFMT_AUDIO_PACKET_CONTROL__VI = 0x4A42; +constexpr unsigned int mmDIG0_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x4A14; +constexpr unsigned int mmDIG0_AFMT_AUDIO_SRC_CONTROL__VI = 0x4A45; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO0__VI = 0x4A1E; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO1__VI = 0x4A1F; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO2__VI = 0x4A20; +constexpr unsigned int mmDIG0_AFMT_AVI_INFO3__VI = 0x4A21; +constexpr unsigned int mmDIG0_AFMT_GENERIC_0__VI = 0x4A25; +constexpr unsigned int mmDIG0_AFMT_GENERIC_1__VI = 0x4A26; +constexpr unsigned int mmDIG0_AFMT_GENERIC_2__VI = 0x4A27; +constexpr unsigned int mmDIG0_AFMT_GENERIC_3__VI = 0x4A28; +constexpr unsigned int mmDIG0_AFMT_GENERIC_4__VI = 0x4A29; +constexpr unsigned int mmDIG0_AFMT_GENERIC_5__VI = 0x4A2A; +constexpr unsigned int mmDIG0_AFMT_GENERIC_6__VI = 0x4A2B; +constexpr unsigned int mmDIG0_AFMT_GENERIC_7__VI = 0x4A2C; +constexpr unsigned int mmDIG0_AFMT_GENERIC_HDR__VI = 0x4A24; +constexpr unsigned int mmDIG0_AFMT_INFOFRAME_CONTROL0__VI = 0x4A44; +constexpr unsigned int mmDIG0_AFMT_ISRC1_0__VI = 0x4A15; +constexpr unsigned int mmDIG0_AFMT_ISRC1_1__VI = 0x4A16; +constexpr unsigned int mmDIG0_AFMT_ISRC1_2__VI = 0x4A17; +constexpr unsigned int mmDIG0_AFMT_ISRC1_3__VI = 0x4A18; +constexpr unsigned int mmDIG0_AFMT_ISRC1_4__VI = 0x4A19; +constexpr unsigned int mmDIG0_AFMT_ISRC2_0__VI = 0x4A1A; +constexpr unsigned int mmDIG0_AFMT_ISRC2_1__VI = 0x4A1B; +constexpr unsigned int mmDIG0_AFMT_ISRC2_2__VI = 0x4A1C; +constexpr unsigned int mmDIG0_AFMT_ISRC2_3__VI = 0x4A1D; +constexpr unsigned int mmDIG0_AFMT_MPEG_INFO0__VI = 0x4A22; +constexpr unsigned int mmDIG0_AFMT_MPEG_INFO1__VI = 0x4A23; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL0__VI = 0x4A3B; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL1__VI = 0x4A3C; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL2__VI = 0x4A3D; +constexpr unsigned int mmDIG0_AFMT_RAMP_CONTROL3__VI = 0x4A3E; +constexpr unsigned int mmDIG0_AFMT_STATUS__VI = 0x4A41; +constexpr unsigned int mmDIG0_AFMT_VBI_PACKET_CONTROL__VI = 0x4A43; +constexpr unsigned int mmDIG0_DIG_BE_CNTL__VI = 0x4A47; +constexpr unsigned int mmDIG0_DIG_BE_EN_CNTL__VI = 0x4A48; +constexpr unsigned int mmDIG0_DIG_CLOCK_PATTERN__VI = 0x4A03; +constexpr unsigned int mmDIG0_DIG_DISPCLK_SWITCH_CNTL__VI = 0x4A07; +constexpr unsigned int mmDIG0_DIG_DISPCLK_SWITCH_STATUS__VI = 0x4A08; +constexpr unsigned int mmDIG0_DIG_FE_CNTL__VI = 0x4A00; +constexpr unsigned int mmDIG0_DIG_FE_TEST_DEBUG_DATA__VI = 0x4A7D; +constexpr unsigned int mmDIG0_DIG_FE_TEST_DEBUG_INDEX__VI = 0x4A7C; +constexpr unsigned int mmDIG0_DIG_FIFO_STATUS__VI = 0x4A06; +constexpr unsigned int mmDIG0_DIG_LANE_ENABLE__VI = 0x4A79; +constexpr unsigned int mmDIG0_DIG_OUTPUT_CRC_CNTL__VI = 0x4A01; +constexpr unsigned int mmDIG0_DIG_OUTPUT_CRC_RESULT__VI = 0x4A02; +constexpr unsigned int mmDIG0_DIG_RANDOM_PATTERN_SEED__VI = 0x4A05; +constexpr unsigned int mmDIG0_DIG_TEST_DEBUG_DATA__VI = 0x4A7B; +constexpr unsigned int mmDIG0_DIG_TEST_DEBUG_INDEX__VI = 0x4A7A; +constexpr unsigned int mmDIG0_DIG_TEST_PATTERN__VI = 0x4A04; +constexpr unsigned int mmDIG0_HDMI_ACR_32_0__VI = 0x4A2E; +constexpr unsigned int mmDIG0_HDMI_ACR_32_1__VI = 0x4A2F; +constexpr unsigned int mmDIG0_HDMI_ACR_44_0__VI = 0x4A30; +constexpr unsigned int mmDIG0_HDMI_ACR_44_1__VI = 0x4A31; +constexpr unsigned int mmDIG0_HDMI_ACR_48_0__VI = 0x4A32; +constexpr unsigned int mmDIG0_HDMI_ACR_48_1__VI = 0x4A33; +constexpr unsigned int mmDIG0_HDMI_ACR_PACKET_CONTROL__VI = 0x4A0C; +constexpr unsigned int mmDIG0_HDMI_ACR_STATUS_0__VI = 0x4A34; +constexpr unsigned int mmDIG0_HDMI_ACR_STATUS_1__VI = 0x4A35; +constexpr unsigned int mmDIG0_HDMI_AUDIO_PACKET_CONTROL__VI = 0x4A0B; +constexpr unsigned int mmDIG0_HDMI_CONTROL__VI = 0x4A09; +constexpr unsigned int mmDIG0_HDMI_GC__VI = 0x4A13; +constexpr unsigned int mmDIG0_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x4A10; +constexpr unsigned int mmDIG0_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x4A2D; +constexpr unsigned int mmDIG0_HDMI_INFOFRAME_CONTROL0__VI = 0x4A0E; +constexpr unsigned int mmDIG0_HDMI_INFOFRAME_CONTROL1__VI = 0x4A0F; +constexpr unsigned int mmDIG0_HDMI_STATUS__VI = 0x4A0A; +constexpr unsigned int mmDIG0_HDMI_VBI_PACKET_CONTROL__VI = 0x4A0D; +constexpr unsigned int mmDIG0_LVDS_DATA_CNTL__VI = 0x4A78; +constexpr unsigned int mmDIG0_TMDS_CNTL__VI = 0x4A6B; +constexpr unsigned int mmDIG0_TMDS_CONTROL0_FEEDBACK__VI = 0x4A6D; +constexpr unsigned int mmDIG0_TMDS_CONTROL_CHAR__VI = 0x4A6C; +constexpr unsigned int mmDIG0_TMDS_CTL0_1_GEN_CNTL__VI = 0x4A75; +constexpr unsigned int mmDIG0_TMDS_CTL2_3_GEN_CNTL__VI = 0x4A76; +constexpr unsigned int mmDIG0_TMDS_CTL_BITS__VI = 0x4A72; +constexpr unsigned int mmDIG0_TMDS_DCBALANCER_CONTROL__VI = 0x4A73; +constexpr unsigned int mmDIG0_TMDS_DEBUG__VI = 0x4A71; +constexpr unsigned int mmDIG0_TMDS_STEREOSYNC_CTL_SEL__VI = 0x4A6E; +constexpr unsigned int mmDIG0_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4A6F; +constexpr unsigned int mmDIG0_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4A70; +constexpr unsigned int mmDIG1_AFMT_60958_0__VI = 0x4B38; +constexpr unsigned int mmDIG1_AFMT_60958_1__VI = 0x4B39; +constexpr unsigned int mmDIG1_AFMT_60958_2__VI = 0x4B3F; +constexpr unsigned int mmDIG1_AFMT_AUDIO_CRC_CONTROL__VI = 0x4B3A; +constexpr unsigned int mmDIG1_AFMT_AUDIO_CRC_RESULT__VI = 0x4B40; +constexpr unsigned int mmDIG1_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4B46; +constexpr unsigned int mmDIG1_AFMT_AUDIO_INFO0__VI = 0x4B36; +constexpr unsigned int mmDIG1_AFMT_AUDIO_INFO1__VI = 0x4B37; +constexpr unsigned int mmDIG1_AFMT_AUDIO_PACKET_CONTROL__VI = 0x4B42; +constexpr unsigned int mmDIG1_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x4B14; +constexpr unsigned int mmDIG1_AFMT_AUDIO_SRC_CONTROL__VI = 0x4B45; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO0__VI = 0x4B1E; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO1__VI = 0x4B1F; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO2__VI = 0x4B20; +constexpr unsigned int mmDIG1_AFMT_AVI_INFO3__VI = 0x4B21; +constexpr unsigned int mmDIG1_AFMT_GENERIC_0__VI = 0x4B25; +constexpr unsigned int mmDIG1_AFMT_GENERIC_1__VI = 0x4B26; +constexpr unsigned int mmDIG1_AFMT_GENERIC_2__VI = 0x4B27; +constexpr unsigned int mmDIG1_AFMT_GENERIC_3__VI = 0x4B28; +constexpr unsigned int mmDIG1_AFMT_GENERIC_4__VI = 0x4B29; +constexpr unsigned int mmDIG1_AFMT_GENERIC_5__VI = 0x4B2A; +constexpr unsigned int mmDIG1_AFMT_GENERIC_6__VI = 0x4B2B; +constexpr unsigned int mmDIG1_AFMT_GENERIC_7__VI = 0x4B2C; +constexpr unsigned int mmDIG1_AFMT_GENERIC_HDR__VI = 0x4B24; +constexpr unsigned int mmDIG1_AFMT_INFOFRAME_CONTROL0__VI = 0x4B44; +constexpr unsigned int mmDIG1_AFMT_ISRC1_0__VI = 0x4B15; +constexpr unsigned int mmDIG1_AFMT_ISRC1_1__VI = 0x4B16; +constexpr unsigned int mmDIG1_AFMT_ISRC1_2__VI = 0x4B17; +constexpr unsigned int mmDIG1_AFMT_ISRC1_3__VI = 0x4B18; +constexpr unsigned int mmDIG1_AFMT_ISRC1_4__VI = 0x4B19; +constexpr unsigned int mmDIG1_AFMT_ISRC2_0__VI = 0x4B1A; +constexpr unsigned int mmDIG1_AFMT_ISRC2_1__VI = 0x4B1B; +constexpr unsigned int mmDIG1_AFMT_ISRC2_2__VI = 0x4B1C; +constexpr unsigned int mmDIG1_AFMT_ISRC2_3__VI = 0x4B1D; +constexpr unsigned int mmDIG1_AFMT_MPEG_INFO0__VI = 0x4B22; +constexpr unsigned int mmDIG1_AFMT_MPEG_INFO1__VI = 0x4B23; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL0__VI = 0x4B3B; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL1__VI = 0x4B3C; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL2__VI = 0x4B3D; +constexpr unsigned int mmDIG1_AFMT_RAMP_CONTROL3__VI = 0x4B3E; +constexpr unsigned int mmDIG1_AFMT_STATUS__VI = 0x4B41; +constexpr unsigned int mmDIG1_AFMT_VBI_PACKET_CONTROL__VI = 0x4B43; +constexpr unsigned int mmDIG1_DIG_BE_CNTL__VI = 0x4B47; +constexpr unsigned int mmDIG1_DIG_BE_EN_CNTL__VI = 0x4B48; +constexpr unsigned int mmDIG1_DIG_CLOCK_PATTERN__VI = 0x4B03; +constexpr unsigned int mmDIG1_DIG_DISPCLK_SWITCH_CNTL__VI = 0x4B07; +constexpr unsigned int mmDIG1_DIG_DISPCLK_SWITCH_STATUS__VI = 0x4B08; +constexpr unsigned int mmDIG1_DIG_FE_CNTL__VI = 0x4B00; +constexpr unsigned int mmDIG1_DIG_FE_TEST_DEBUG_DATA__VI = 0x4B7D; +constexpr unsigned int mmDIG1_DIG_FE_TEST_DEBUG_INDEX__VI = 0x4B7C; +constexpr unsigned int mmDIG1_DIG_FIFO_STATUS__VI = 0x4B06; +constexpr unsigned int mmDIG1_DIG_LANE_ENABLE__VI = 0x4B79; +constexpr unsigned int mmDIG1_DIG_OUTPUT_CRC_CNTL__VI = 0x4B01; +constexpr unsigned int mmDIG1_DIG_OUTPUT_CRC_RESULT__VI = 0x4B02; +constexpr unsigned int mmDIG1_DIG_RANDOM_PATTERN_SEED__VI = 0x4B05; +constexpr unsigned int mmDIG1_DIG_TEST_DEBUG_DATA__VI = 0x4B7B; +constexpr unsigned int mmDIG1_DIG_TEST_DEBUG_INDEX__VI = 0x4B7A; +constexpr unsigned int mmDIG1_DIG_TEST_PATTERN__VI = 0x4B04; +constexpr unsigned int mmDIG1_HDMI_ACR_32_0__VI = 0x4B2E; +constexpr unsigned int mmDIG1_HDMI_ACR_32_1__VI = 0x4B2F; +constexpr unsigned int mmDIG1_HDMI_ACR_44_0__VI = 0x4B30; +constexpr unsigned int mmDIG1_HDMI_ACR_44_1__VI = 0x4B31; +constexpr unsigned int mmDIG1_HDMI_ACR_48_0__VI = 0x4B32; +constexpr unsigned int mmDIG1_HDMI_ACR_48_1__VI = 0x4B33; +constexpr unsigned int mmDIG1_HDMI_ACR_PACKET_CONTROL__VI = 0x4B0C; +constexpr unsigned int mmDIG1_HDMI_ACR_STATUS_0__VI = 0x4B34; +constexpr unsigned int mmDIG1_HDMI_ACR_STATUS_1__VI = 0x4B35; +constexpr unsigned int mmDIG1_HDMI_AUDIO_PACKET_CONTROL__VI = 0x4B0B; +constexpr unsigned int mmDIG1_HDMI_CONTROL__VI = 0x4B09; +constexpr unsigned int mmDIG1_HDMI_GC__VI = 0x4B13; +constexpr unsigned int mmDIG1_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x4B10; +constexpr unsigned int mmDIG1_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x4B2D; +constexpr unsigned int mmDIG1_HDMI_INFOFRAME_CONTROL0__VI = 0x4B0E; +constexpr unsigned int mmDIG1_HDMI_INFOFRAME_CONTROL1__VI = 0x4B0F; +constexpr unsigned int mmDIG1_HDMI_STATUS__VI = 0x4B0A; +constexpr unsigned int mmDIG1_HDMI_VBI_PACKET_CONTROL__VI = 0x4B0D; +constexpr unsigned int mmDIG1_LVDS_DATA_CNTL__VI = 0x4B78; +constexpr unsigned int mmDIG1_TMDS_CNTL__VI = 0x4B6B; +constexpr unsigned int mmDIG1_TMDS_CONTROL0_FEEDBACK__VI = 0x4B6D; +constexpr unsigned int mmDIG1_TMDS_CONTROL_CHAR__VI = 0x4B6C; +constexpr unsigned int mmDIG1_TMDS_CTL0_1_GEN_CNTL__VI = 0x4B75; +constexpr unsigned int mmDIG1_TMDS_CTL2_3_GEN_CNTL__VI = 0x4B76; +constexpr unsigned int mmDIG1_TMDS_CTL_BITS__VI = 0x4B72; +constexpr unsigned int mmDIG1_TMDS_DCBALANCER_CONTROL__VI = 0x4B73; +constexpr unsigned int mmDIG1_TMDS_DEBUG__VI = 0x4B71; +constexpr unsigned int mmDIG1_TMDS_STEREOSYNC_CTL_SEL__VI = 0x4B6E; +constexpr unsigned int mmDIG1_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4B6F; +constexpr unsigned int mmDIG1_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4B70; +constexpr unsigned int mmDIG2_AFMT_60958_0__VI = 0x4C38; +constexpr unsigned int mmDIG2_AFMT_60958_1__VI = 0x4C39; +constexpr unsigned int mmDIG2_AFMT_60958_2__VI = 0x4C3F; +constexpr unsigned int mmDIG2_AFMT_AUDIO_CRC_CONTROL__VI = 0x4C3A; +constexpr unsigned int mmDIG2_AFMT_AUDIO_CRC_RESULT__VI = 0x4C40; +constexpr unsigned int mmDIG2_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4C46; +constexpr unsigned int mmDIG2_AFMT_AUDIO_INFO0__VI = 0x4C36; +constexpr unsigned int mmDIG2_AFMT_AUDIO_INFO1__VI = 0x4C37; +constexpr unsigned int mmDIG2_AFMT_AUDIO_PACKET_CONTROL__VI = 0x4C42; +constexpr unsigned int mmDIG2_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x4C14; +constexpr unsigned int mmDIG2_AFMT_AUDIO_SRC_CONTROL__VI = 0x4C45; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO0__VI = 0x4C1E; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO1__VI = 0x4C1F; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO2__VI = 0x4C20; +constexpr unsigned int mmDIG2_AFMT_AVI_INFO3__VI = 0x4C21; +constexpr unsigned int mmDIG2_AFMT_GENERIC_0__VI = 0x4C25; +constexpr unsigned int mmDIG2_AFMT_GENERIC_1__VI = 0x4C26; +constexpr unsigned int mmDIG2_AFMT_GENERIC_2__VI = 0x4C27; +constexpr unsigned int mmDIG2_AFMT_GENERIC_3__VI = 0x4C28; +constexpr unsigned int mmDIG2_AFMT_GENERIC_4__VI = 0x4C29; +constexpr unsigned int mmDIG2_AFMT_GENERIC_5__VI = 0x4C2A; +constexpr unsigned int mmDIG2_AFMT_GENERIC_6__VI = 0x4C2B; +constexpr unsigned int mmDIG2_AFMT_GENERIC_7__VI = 0x4C2C; +constexpr unsigned int mmDIG2_AFMT_GENERIC_HDR__VI = 0x4C24; +constexpr unsigned int mmDIG2_AFMT_INFOFRAME_CONTROL0__VI = 0x4C44; +constexpr unsigned int mmDIG2_AFMT_ISRC1_0__VI = 0x4C15; +constexpr unsigned int mmDIG2_AFMT_ISRC1_1__VI = 0x4C16; +constexpr unsigned int mmDIG2_AFMT_ISRC1_2__VI = 0x4C17; +constexpr unsigned int mmDIG2_AFMT_ISRC1_3__VI = 0x4C18; +constexpr unsigned int mmDIG2_AFMT_ISRC1_4__VI = 0x4C19; +constexpr unsigned int mmDIG2_AFMT_ISRC2_0__VI = 0x4C1A; +constexpr unsigned int mmDIG2_AFMT_ISRC2_1__VI = 0x4C1B; +constexpr unsigned int mmDIG2_AFMT_ISRC2_2__VI = 0x4C1C; +constexpr unsigned int mmDIG2_AFMT_ISRC2_3__VI = 0x4C1D; +constexpr unsigned int mmDIG2_AFMT_MPEG_INFO0__VI = 0x4C22; +constexpr unsigned int mmDIG2_AFMT_MPEG_INFO1__VI = 0x4C23; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL0__VI = 0x4C3B; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL1__VI = 0x4C3C; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL2__VI = 0x4C3D; +constexpr unsigned int mmDIG2_AFMT_RAMP_CONTROL3__VI = 0x4C3E; +constexpr unsigned int mmDIG2_AFMT_STATUS__VI = 0x4C41; +constexpr unsigned int mmDIG2_AFMT_VBI_PACKET_CONTROL__VI = 0x4C43; +constexpr unsigned int mmDIG2_DIG_BE_CNTL__VI = 0x4C47; +constexpr unsigned int mmDIG2_DIG_BE_EN_CNTL__VI = 0x4C48; +constexpr unsigned int mmDIG2_DIG_CLOCK_PATTERN__VI = 0x4C03; +constexpr unsigned int mmDIG2_DIG_DISPCLK_SWITCH_CNTL__VI = 0x4C07; +constexpr unsigned int mmDIG2_DIG_DISPCLK_SWITCH_STATUS__VI = 0x4C08; +constexpr unsigned int mmDIG2_DIG_FE_CNTL__VI = 0x4C00; +constexpr unsigned int mmDIG2_DIG_FE_TEST_DEBUG_DATA__VI = 0x4C7D; +constexpr unsigned int mmDIG2_DIG_FE_TEST_DEBUG_INDEX__VI = 0x4C7C; +constexpr unsigned int mmDIG2_DIG_FIFO_STATUS__VI = 0x4C06; +constexpr unsigned int mmDIG2_DIG_LANE_ENABLE__VI = 0x4C79; +constexpr unsigned int mmDIG2_DIG_OUTPUT_CRC_CNTL__VI = 0x4C01; +constexpr unsigned int mmDIG2_DIG_OUTPUT_CRC_RESULT__VI = 0x4C02; +constexpr unsigned int mmDIG2_DIG_RANDOM_PATTERN_SEED__VI = 0x4C05; +constexpr unsigned int mmDIG2_DIG_TEST_DEBUG_DATA__VI = 0x4C7B; +constexpr unsigned int mmDIG2_DIG_TEST_DEBUG_INDEX__VI = 0x4C7A; +constexpr unsigned int mmDIG2_DIG_TEST_PATTERN__VI = 0x4C04; +constexpr unsigned int mmDIG2_HDMI_ACR_32_0__VI = 0x4C2E; +constexpr unsigned int mmDIG2_HDMI_ACR_32_1__VI = 0x4C2F; +constexpr unsigned int mmDIG2_HDMI_ACR_44_0__VI = 0x4C30; +constexpr unsigned int mmDIG2_HDMI_ACR_44_1__VI = 0x4C31; +constexpr unsigned int mmDIG2_HDMI_ACR_48_0__VI = 0x4C32; +constexpr unsigned int mmDIG2_HDMI_ACR_48_1__VI = 0x4C33; +constexpr unsigned int mmDIG2_HDMI_ACR_PACKET_CONTROL__VI = 0x4C0C; +constexpr unsigned int mmDIG2_HDMI_ACR_STATUS_0__VI = 0x4C34; +constexpr unsigned int mmDIG2_HDMI_ACR_STATUS_1__VI = 0x4C35; +constexpr unsigned int mmDIG2_HDMI_AUDIO_PACKET_CONTROL__VI = 0x4C0B; +constexpr unsigned int mmDIG2_HDMI_CONTROL__VI = 0x4C09; +constexpr unsigned int mmDIG2_HDMI_GC__VI = 0x4C13; +constexpr unsigned int mmDIG2_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x4C10; +constexpr unsigned int mmDIG2_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x4C2D; +constexpr unsigned int mmDIG2_HDMI_INFOFRAME_CONTROL0__VI = 0x4C0E; +constexpr unsigned int mmDIG2_HDMI_INFOFRAME_CONTROL1__VI = 0x4C0F; +constexpr unsigned int mmDIG2_HDMI_STATUS__VI = 0x4C0A; +constexpr unsigned int mmDIG2_HDMI_VBI_PACKET_CONTROL__VI = 0x4C0D; +constexpr unsigned int mmDIG2_LVDS_DATA_CNTL__VI = 0x4C78; +constexpr unsigned int mmDIG2_TMDS_CNTL__VI = 0x4C6B; +constexpr unsigned int mmDIG2_TMDS_CONTROL0_FEEDBACK__VI = 0x4C6D; +constexpr unsigned int mmDIG2_TMDS_CONTROL_CHAR__VI = 0x4C6C; +constexpr unsigned int mmDIG2_TMDS_CTL0_1_GEN_CNTL__VI = 0x4C75; +constexpr unsigned int mmDIG2_TMDS_CTL2_3_GEN_CNTL__VI = 0x4C76; +constexpr unsigned int mmDIG2_TMDS_CTL_BITS__VI = 0x4C72; +constexpr unsigned int mmDIG2_TMDS_DCBALANCER_CONTROL__VI = 0x4C73; +constexpr unsigned int mmDIG2_TMDS_DEBUG__VI = 0x4C71; +constexpr unsigned int mmDIG2_TMDS_STEREOSYNC_CTL_SEL__VI = 0x4C6E; +constexpr unsigned int mmDIG2_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4C6F; +constexpr unsigned int mmDIG2_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4C70; +constexpr unsigned int mmDIG3_AFMT_60958_0__VI = 0x4D38; +constexpr unsigned int mmDIG3_AFMT_60958_1__VI = 0x4D39; +constexpr unsigned int mmDIG3_AFMT_60958_2__VI = 0x4D3F; +constexpr unsigned int mmDIG3_AFMT_AUDIO_CRC_CONTROL__VI = 0x4D3A; +constexpr unsigned int mmDIG3_AFMT_AUDIO_CRC_RESULT__VI = 0x4D40; +constexpr unsigned int mmDIG3_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4D46; +constexpr unsigned int mmDIG3_AFMT_AUDIO_INFO0__VI = 0x4D36; +constexpr unsigned int mmDIG3_AFMT_AUDIO_INFO1__VI = 0x4D37; +constexpr unsigned int mmDIG3_AFMT_AUDIO_PACKET_CONTROL__VI = 0x4D42; +constexpr unsigned int mmDIG3_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x4D14; +constexpr unsigned int mmDIG3_AFMT_AUDIO_SRC_CONTROL__VI = 0x4D45; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO0__VI = 0x4D1E; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO1__VI = 0x4D1F; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO2__VI = 0x4D20; +constexpr unsigned int mmDIG3_AFMT_AVI_INFO3__VI = 0x4D21; +constexpr unsigned int mmDIG3_AFMT_GENERIC_0__VI = 0x4D25; +constexpr unsigned int mmDIG3_AFMT_GENERIC_1__VI = 0x4D26; +constexpr unsigned int mmDIG3_AFMT_GENERIC_2__VI = 0x4D27; +constexpr unsigned int mmDIG3_AFMT_GENERIC_3__VI = 0x4D28; +constexpr unsigned int mmDIG3_AFMT_GENERIC_4__VI = 0x4D29; +constexpr unsigned int mmDIG3_AFMT_GENERIC_5__VI = 0x4D2A; +constexpr unsigned int mmDIG3_AFMT_GENERIC_6__VI = 0x4D2B; +constexpr unsigned int mmDIG3_AFMT_GENERIC_7__VI = 0x4D2C; +constexpr unsigned int mmDIG3_AFMT_GENERIC_HDR__VI = 0x4D24; +constexpr unsigned int mmDIG3_AFMT_INFOFRAME_CONTROL0__VI = 0x4D44; +constexpr unsigned int mmDIG3_AFMT_ISRC1_0__VI = 0x4D15; +constexpr unsigned int mmDIG3_AFMT_ISRC1_1__VI = 0x4D16; +constexpr unsigned int mmDIG3_AFMT_ISRC1_2__VI = 0x4D17; +constexpr unsigned int mmDIG3_AFMT_ISRC1_3__VI = 0x4D18; +constexpr unsigned int mmDIG3_AFMT_ISRC1_4__VI = 0x4D19; +constexpr unsigned int mmDIG3_AFMT_ISRC2_0__VI = 0x4D1A; +constexpr unsigned int mmDIG3_AFMT_ISRC2_1__VI = 0x4D1B; +constexpr unsigned int mmDIG3_AFMT_ISRC2_2__VI = 0x4D1C; +constexpr unsigned int mmDIG3_AFMT_ISRC2_3__VI = 0x4D1D; +constexpr unsigned int mmDIG3_AFMT_MPEG_INFO0__VI = 0x4D22; +constexpr unsigned int mmDIG3_AFMT_MPEG_INFO1__VI = 0x4D23; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL0__VI = 0x4D3B; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL1__VI = 0x4D3C; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL2__VI = 0x4D3D; +constexpr unsigned int mmDIG3_AFMT_RAMP_CONTROL3__VI = 0x4D3E; +constexpr unsigned int mmDIG3_AFMT_STATUS__VI = 0x4D41; +constexpr unsigned int mmDIG3_AFMT_VBI_PACKET_CONTROL__VI = 0x4D43; +constexpr unsigned int mmDIG3_DIG_BE_CNTL__VI = 0x4D47; +constexpr unsigned int mmDIG3_DIG_BE_EN_CNTL__VI = 0x4D48; +constexpr unsigned int mmDIG3_DIG_CLOCK_PATTERN__VI = 0x4D03; +constexpr unsigned int mmDIG3_DIG_DISPCLK_SWITCH_CNTL__VI = 0x4D07; +constexpr unsigned int mmDIG3_DIG_DISPCLK_SWITCH_STATUS__VI = 0x4D08; +constexpr unsigned int mmDIG3_DIG_FE_CNTL__VI = 0x4D00; +constexpr unsigned int mmDIG3_DIG_FE_TEST_DEBUG_DATA__VI = 0x4D7D; +constexpr unsigned int mmDIG3_DIG_FE_TEST_DEBUG_INDEX__VI = 0x4D7C; +constexpr unsigned int mmDIG3_DIG_FIFO_STATUS__VI = 0x4D06; +constexpr unsigned int mmDIG3_DIG_LANE_ENABLE__VI = 0x4D79; +constexpr unsigned int mmDIG3_DIG_OUTPUT_CRC_CNTL__VI = 0x4D01; +constexpr unsigned int mmDIG3_DIG_OUTPUT_CRC_RESULT__VI = 0x4D02; +constexpr unsigned int mmDIG3_DIG_RANDOM_PATTERN_SEED__VI = 0x4D05; +constexpr unsigned int mmDIG3_DIG_TEST_DEBUG_DATA__VI = 0x4D7B; +constexpr unsigned int mmDIG3_DIG_TEST_DEBUG_INDEX__VI = 0x4D7A; +constexpr unsigned int mmDIG3_DIG_TEST_PATTERN__VI = 0x4D04; +constexpr unsigned int mmDIG3_HDMI_ACR_32_0__VI = 0x4D2E; +constexpr unsigned int mmDIG3_HDMI_ACR_32_1__VI = 0x4D2F; +constexpr unsigned int mmDIG3_HDMI_ACR_44_0__VI = 0x4D30; +constexpr unsigned int mmDIG3_HDMI_ACR_44_1__VI = 0x4D31; +constexpr unsigned int mmDIG3_HDMI_ACR_48_0__VI = 0x4D32; +constexpr unsigned int mmDIG3_HDMI_ACR_48_1__VI = 0x4D33; +constexpr unsigned int mmDIG3_HDMI_ACR_PACKET_CONTROL__VI = 0x4D0C; +constexpr unsigned int mmDIG3_HDMI_ACR_STATUS_0__VI = 0x4D34; +constexpr unsigned int mmDIG3_HDMI_ACR_STATUS_1__VI = 0x4D35; +constexpr unsigned int mmDIG3_HDMI_AUDIO_PACKET_CONTROL__VI = 0x4D0B; +constexpr unsigned int mmDIG3_HDMI_CONTROL__VI = 0x4D09; +constexpr unsigned int mmDIG3_HDMI_GC__VI = 0x4D13; +constexpr unsigned int mmDIG3_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x4D10; +constexpr unsigned int mmDIG3_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x4D2D; +constexpr unsigned int mmDIG3_HDMI_INFOFRAME_CONTROL0__VI = 0x4D0E; +constexpr unsigned int mmDIG3_HDMI_INFOFRAME_CONTROL1__VI = 0x4D0F; +constexpr unsigned int mmDIG3_HDMI_STATUS__VI = 0x4D0A; +constexpr unsigned int mmDIG3_HDMI_VBI_PACKET_CONTROL__VI = 0x4D0D; +constexpr unsigned int mmDIG3_LVDS_DATA_CNTL__VI = 0x4D78; +constexpr unsigned int mmDIG3_TMDS_CNTL__VI = 0x4D6B; +constexpr unsigned int mmDIG3_TMDS_CONTROL0_FEEDBACK__VI = 0x4D6D; +constexpr unsigned int mmDIG3_TMDS_CONTROL_CHAR__VI = 0x4D6C; +constexpr unsigned int mmDIG3_TMDS_CTL0_1_GEN_CNTL__VI = 0x4D75; +constexpr unsigned int mmDIG3_TMDS_CTL2_3_GEN_CNTL__VI = 0x4D76; +constexpr unsigned int mmDIG3_TMDS_CTL_BITS__VI = 0x4D72; +constexpr unsigned int mmDIG3_TMDS_DCBALANCER_CONTROL__VI = 0x4D73; +constexpr unsigned int mmDIG3_TMDS_DEBUG__VI = 0x4D71; +constexpr unsigned int mmDIG3_TMDS_STEREOSYNC_CTL_SEL__VI = 0x4D6E; +constexpr unsigned int mmDIG3_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4D6F; +constexpr unsigned int mmDIG3_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4D70; +constexpr unsigned int mmDIG4_AFMT_60958_0__VI = 0x4E38; +constexpr unsigned int mmDIG4_AFMT_60958_1__VI = 0x4E39; +constexpr unsigned int mmDIG4_AFMT_60958_2__VI = 0x4E3F; +constexpr unsigned int mmDIG4_AFMT_AUDIO_CRC_CONTROL__VI = 0x4E3A; +constexpr unsigned int mmDIG4_AFMT_AUDIO_CRC_RESULT__VI = 0x4E40; +constexpr unsigned int mmDIG4_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4E46; +constexpr unsigned int mmDIG4_AFMT_AUDIO_INFO0__VI = 0x4E36; +constexpr unsigned int mmDIG4_AFMT_AUDIO_INFO1__VI = 0x4E37; +constexpr unsigned int mmDIG4_AFMT_AUDIO_PACKET_CONTROL__VI = 0x4E42; +constexpr unsigned int mmDIG4_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x4E14; +constexpr unsigned int mmDIG4_AFMT_AUDIO_SRC_CONTROL__VI = 0x4E45; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO0__VI = 0x4E1E; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO1__VI = 0x4E1F; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO2__VI = 0x4E20; +constexpr unsigned int mmDIG4_AFMT_AVI_INFO3__VI = 0x4E21; +constexpr unsigned int mmDIG4_AFMT_GENERIC_0__VI = 0x4E25; +constexpr unsigned int mmDIG4_AFMT_GENERIC_1__VI = 0x4E26; +constexpr unsigned int mmDIG4_AFMT_GENERIC_2__VI = 0x4E27; +constexpr unsigned int mmDIG4_AFMT_GENERIC_3__VI = 0x4E28; +constexpr unsigned int mmDIG4_AFMT_GENERIC_4__VI = 0x4E29; +constexpr unsigned int mmDIG4_AFMT_GENERIC_5__VI = 0x4E2A; +constexpr unsigned int mmDIG4_AFMT_GENERIC_6__VI = 0x4E2B; +constexpr unsigned int mmDIG4_AFMT_GENERIC_7__VI = 0x4E2C; +constexpr unsigned int mmDIG4_AFMT_GENERIC_HDR__VI = 0x4E24; +constexpr unsigned int mmDIG4_AFMT_INFOFRAME_CONTROL0__VI = 0x4E44; +constexpr unsigned int mmDIG4_AFMT_ISRC1_0__VI = 0x4E15; +constexpr unsigned int mmDIG4_AFMT_ISRC1_1__VI = 0x4E16; +constexpr unsigned int mmDIG4_AFMT_ISRC1_2__VI = 0x4E17; +constexpr unsigned int mmDIG4_AFMT_ISRC1_3__VI = 0x4E18; +constexpr unsigned int mmDIG4_AFMT_ISRC1_4__VI = 0x4E19; +constexpr unsigned int mmDIG4_AFMT_ISRC2_0__VI = 0x4E1A; +constexpr unsigned int mmDIG4_AFMT_ISRC2_1__VI = 0x4E1B; +constexpr unsigned int mmDIG4_AFMT_ISRC2_2__VI = 0x4E1C; +constexpr unsigned int mmDIG4_AFMT_ISRC2_3__VI = 0x4E1D; +constexpr unsigned int mmDIG4_AFMT_MPEG_INFO0__VI = 0x4E22; +constexpr unsigned int mmDIG4_AFMT_MPEG_INFO1__VI = 0x4E23; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL0__VI = 0x4E3B; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL1__VI = 0x4E3C; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL2__VI = 0x4E3D; +constexpr unsigned int mmDIG4_AFMT_RAMP_CONTROL3__VI = 0x4E3E; +constexpr unsigned int mmDIG4_AFMT_STATUS__VI = 0x4E41; +constexpr unsigned int mmDIG4_AFMT_VBI_PACKET_CONTROL__VI = 0x4E43; +constexpr unsigned int mmDIG4_DIG_BE_CNTL__VI = 0x4E47; +constexpr unsigned int mmDIG4_DIG_BE_EN_CNTL__VI = 0x4E48; +constexpr unsigned int mmDIG4_DIG_CLOCK_PATTERN__VI = 0x4E03; +constexpr unsigned int mmDIG4_DIG_DISPCLK_SWITCH_CNTL__VI = 0x4E07; +constexpr unsigned int mmDIG4_DIG_DISPCLK_SWITCH_STATUS__VI = 0x4E08; +constexpr unsigned int mmDIG4_DIG_FE_CNTL__VI = 0x4E00; +constexpr unsigned int mmDIG4_DIG_FE_TEST_DEBUG_DATA__VI = 0x4E7D; +constexpr unsigned int mmDIG4_DIG_FE_TEST_DEBUG_INDEX__VI = 0x4E7C; +constexpr unsigned int mmDIG4_DIG_FIFO_STATUS__VI = 0x4E06; +constexpr unsigned int mmDIG4_DIG_LANE_ENABLE__VI = 0x4E79; +constexpr unsigned int mmDIG4_DIG_OUTPUT_CRC_CNTL__VI = 0x4E01; +constexpr unsigned int mmDIG4_DIG_OUTPUT_CRC_RESULT__VI = 0x4E02; +constexpr unsigned int mmDIG4_DIG_RANDOM_PATTERN_SEED__VI = 0x4E05; +constexpr unsigned int mmDIG4_DIG_TEST_DEBUG_DATA__VI = 0x4E7B; +constexpr unsigned int mmDIG4_DIG_TEST_DEBUG_INDEX__VI = 0x4E7A; +constexpr unsigned int mmDIG4_DIG_TEST_PATTERN__VI = 0x4E04; +constexpr unsigned int mmDIG4_HDMI_ACR_32_0__VI = 0x4E2E; +constexpr unsigned int mmDIG4_HDMI_ACR_32_1__VI = 0x4E2F; +constexpr unsigned int mmDIG4_HDMI_ACR_44_0__VI = 0x4E30; +constexpr unsigned int mmDIG4_HDMI_ACR_44_1__VI = 0x4E31; +constexpr unsigned int mmDIG4_HDMI_ACR_48_0__VI = 0x4E32; +constexpr unsigned int mmDIG4_HDMI_ACR_48_1__VI = 0x4E33; +constexpr unsigned int mmDIG4_HDMI_ACR_PACKET_CONTROL__VI = 0x4E0C; +constexpr unsigned int mmDIG4_HDMI_ACR_STATUS_0__VI = 0x4E34; +constexpr unsigned int mmDIG4_HDMI_ACR_STATUS_1__VI = 0x4E35; +constexpr unsigned int mmDIG4_HDMI_AUDIO_PACKET_CONTROL__VI = 0x4E0B; +constexpr unsigned int mmDIG4_HDMI_CONTROL__VI = 0x4E09; +constexpr unsigned int mmDIG4_HDMI_GC__VI = 0x4E13; +constexpr unsigned int mmDIG4_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x4E10; +constexpr unsigned int mmDIG4_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x4E2D; +constexpr unsigned int mmDIG4_HDMI_INFOFRAME_CONTROL0__VI = 0x4E0E; +constexpr unsigned int mmDIG4_HDMI_INFOFRAME_CONTROL1__VI = 0x4E0F; +constexpr unsigned int mmDIG4_HDMI_STATUS__VI = 0x4E0A; +constexpr unsigned int mmDIG4_HDMI_VBI_PACKET_CONTROL__VI = 0x4E0D; +constexpr unsigned int mmDIG4_LVDS_DATA_CNTL__VI = 0x4E78; +constexpr unsigned int mmDIG4_TMDS_CNTL__VI = 0x4E6B; +constexpr unsigned int mmDIG4_TMDS_CONTROL0_FEEDBACK__VI = 0x4E6D; +constexpr unsigned int mmDIG4_TMDS_CONTROL_CHAR__VI = 0x4E6C; +constexpr unsigned int mmDIG4_TMDS_CTL0_1_GEN_CNTL__VI = 0x4E75; +constexpr unsigned int mmDIG4_TMDS_CTL2_3_GEN_CNTL__VI = 0x4E76; +constexpr unsigned int mmDIG4_TMDS_CTL_BITS__VI = 0x4E72; +constexpr unsigned int mmDIG4_TMDS_DCBALANCER_CONTROL__VI = 0x4E73; +constexpr unsigned int mmDIG4_TMDS_DEBUG__VI = 0x4E71; +constexpr unsigned int mmDIG4_TMDS_STEREOSYNC_CTL_SEL__VI = 0x4E6E; +constexpr unsigned int mmDIG4_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4E6F; +constexpr unsigned int mmDIG4_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4E70; +constexpr unsigned int mmDIG5_AFMT_60958_0__VI = 0x4F38; +constexpr unsigned int mmDIG5_AFMT_60958_1__VI = 0x4F39; +constexpr unsigned int mmDIG5_AFMT_60958_2__VI = 0x4F3F; +constexpr unsigned int mmDIG5_AFMT_AUDIO_CRC_CONTROL__VI = 0x4F3A; +constexpr unsigned int mmDIG5_AFMT_AUDIO_CRC_RESULT__VI = 0x4F40; +constexpr unsigned int mmDIG5_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x4F46; +constexpr unsigned int mmDIG5_AFMT_AUDIO_INFO0__VI = 0x4F36; +constexpr unsigned int mmDIG5_AFMT_AUDIO_INFO1__VI = 0x4F37; +constexpr unsigned int mmDIG5_AFMT_AUDIO_PACKET_CONTROL__VI = 0x4F42; +constexpr unsigned int mmDIG5_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x4F14; +constexpr unsigned int mmDIG5_AFMT_AUDIO_SRC_CONTROL__VI = 0x4F45; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO0__VI = 0x4F1E; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO1__VI = 0x4F1F; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO2__VI = 0x4F20; +constexpr unsigned int mmDIG5_AFMT_AVI_INFO3__VI = 0x4F21; +constexpr unsigned int mmDIG5_AFMT_GENERIC_0__VI = 0x4F25; +constexpr unsigned int mmDIG5_AFMT_GENERIC_1__VI = 0x4F26; +constexpr unsigned int mmDIG5_AFMT_GENERIC_2__VI = 0x4F27; +constexpr unsigned int mmDIG5_AFMT_GENERIC_3__VI = 0x4F28; +constexpr unsigned int mmDIG5_AFMT_GENERIC_4__VI = 0x4F29; +constexpr unsigned int mmDIG5_AFMT_GENERIC_5__VI = 0x4F2A; +constexpr unsigned int mmDIG5_AFMT_GENERIC_6__VI = 0x4F2B; +constexpr unsigned int mmDIG5_AFMT_GENERIC_7__VI = 0x4F2C; +constexpr unsigned int mmDIG5_AFMT_GENERIC_HDR__VI = 0x4F24; +constexpr unsigned int mmDIG5_AFMT_INFOFRAME_CONTROL0__VI = 0x4F44; +constexpr unsigned int mmDIG5_AFMT_ISRC1_0__VI = 0x4F15; +constexpr unsigned int mmDIG5_AFMT_ISRC1_1__VI = 0x4F16; +constexpr unsigned int mmDIG5_AFMT_ISRC1_2__VI = 0x4F17; +constexpr unsigned int mmDIG5_AFMT_ISRC1_3__VI = 0x4F18; +constexpr unsigned int mmDIG5_AFMT_ISRC1_4__VI = 0x4F19; +constexpr unsigned int mmDIG5_AFMT_ISRC2_0__VI = 0x4F1A; +constexpr unsigned int mmDIG5_AFMT_ISRC2_1__VI = 0x4F1B; +constexpr unsigned int mmDIG5_AFMT_ISRC2_2__VI = 0x4F1C; +constexpr unsigned int mmDIG5_AFMT_ISRC2_3__VI = 0x4F1D; +constexpr unsigned int mmDIG5_AFMT_MPEG_INFO0__VI = 0x4F22; +constexpr unsigned int mmDIG5_AFMT_MPEG_INFO1__VI = 0x4F23; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL0__VI = 0x4F3B; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL1__VI = 0x4F3C; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL2__VI = 0x4F3D; +constexpr unsigned int mmDIG5_AFMT_RAMP_CONTROL3__VI = 0x4F3E; +constexpr unsigned int mmDIG5_AFMT_STATUS__VI = 0x4F41; +constexpr unsigned int mmDIG5_AFMT_VBI_PACKET_CONTROL__VI = 0x4F43; +constexpr unsigned int mmDIG5_DIG_BE_CNTL__VI = 0x4F47; +constexpr unsigned int mmDIG5_DIG_BE_EN_CNTL__VI = 0x4F48; +constexpr unsigned int mmDIG5_DIG_CLOCK_PATTERN__VI = 0x4F03; +constexpr unsigned int mmDIG5_DIG_DISPCLK_SWITCH_CNTL__VI = 0x4F07; +constexpr unsigned int mmDIG5_DIG_DISPCLK_SWITCH_STATUS__VI = 0x4F08; +constexpr unsigned int mmDIG5_DIG_FE_CNTL__VI = 0x4F00; +constexpr unsigned int mmDIG5_DIG_FE_TEST_DEBUG_DATA__VI = 0x4F7D; +constexpr unsigned int mmDIG5_DIG_FE_TEST_DEBUG_INDEX__VI = 0x4F7C; +constexpr unsigned int mmDIG5_DIG_FIFO_STATUS__VI = 0x4F06; +constexpr unsigned int mmDIG5_DIG_LANE_ENABLE__VI = 0x4F79; +constexpr unsigned int mmDIG5_DIG_OUTPUT_CRC_CNTL__VI = 0x4F01; +constexpr unsigned int mmDIG5_DIG_OUTPUT_CRC_RESULT__VI = 0x4F02; +constexpr unsigned int mmDIG5_DIG_RANDOM_PATTERN_SEED__VI = 0x4F05; +constexpr unsigned int mmDIG5_DIG_TEST_DEBUG_DATA__VI = 0x4F7B; +constexpr unsigned int mmDIG5_DIG_TEST_DEBUG_INDEX__VI = 0x4F7A; +constexpr unsigned int mmDIG5_DIG_TEST_PATTERN__VI = 0x4F04; +constexpr unsigned int mmDIG5_HDMI_ACR_32_0__VI = 0x4F2E; +constexpr unsigned int mmDIG5_HDMI_ACR_32_1__VI = 0x4F2F; +constexpr unsigned int mmDIG5_HDMI_ACR_44_0__VI = 0x4F30; +constexpr unsigned int mmDIG5_HDMI_ACR_44_1__VI = 0x4F31; +constexpr unsigned int mmDIG5_HDMI_ACR_48_0__VI = 0x4F32; +constexpr unsigned int mmDIG5_HDMI_ACR_48_1__VI = 0x4F33; +constexpr unsigned int mmDIG5_HDMI_ACR_PACKET_CONTROL__VI = 0x4F0C; +constexpr unsigned int mmDIG5_HDMI_ACR_STATUS_0__VI = 0x4F34; +constexpr unsigned int mmDIG5_HDMI_ACR_STATUS_1__VI = 0x4F35; +constexpr unsigned int mmDIG5_HDMI_AUDIO_PACKET_CONTROL__VI = 0x4F0B; +constexpr unsigned int mmDIG5_HDMI_CONTROL__VI = 0x4F09; +constexpr unsigned int mmDIG5_HDMI_GC__VI = 0x4F13; +constexpr unsigned int mmDIG5_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x4F10; +constexpr unsigned int mmDIG5_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x4F2D; +constexpr unsigned int mmDIG5_HDMI_INFOFRAME_CONTROL0__VI = 0x4F0E; +constexpr unsigned int mmDIG5_HDMI_INFOFRAME_CONTROL1__VI = 0x4F0F; +constexpr unsigned int mmDIG5_HDMI_STATUS__VI = 0x4F0A; +constexpr unsigned int mmDIG5_HDMI_VBI_PACKET_CONTROL__VI = 0x4F0D; +constexpr unsigned int mmDIG5_LVDS_DATA_CNTL__VI = 0x4F78; +constexpr unsigned int mmDIG5_TMDS_CNTL__VI = 0x4F6B; +constexpr unsigned int mmDIG5_TMDS_CONTROL0_FEEDBACK__VI = 0x4F6D; +constexpr unsigned int mmDIG5_TMDS_CONTROL_CHAR__VI = 0x4F6C; +constexpr unsigned int mmDIG5_TMDS_CTL0_1_GEN_CNTL__VI = 0x4F75; +constexpr unsigned int mmDIG5_TMDS_CTL2_3_GEN_CNTL__VI = 0x4F76; +constexpr unsigned int mmDIG5_TMDS_CTL_BITS__VI = 0x4F72; +constexpr unsigned int mmDIG5_TMDS_DCBALANCER_CONTROL__VI = 0x4F73; +constexpr unsigned int mmDIG5_TMDS_DEBUG__VI = 0x4F71; +constexpr unsigned int mmDIG5_TMDS_STEREOSYNC_CTL_SEL__VI = 0x4F6E; +constexpr unsigned int mmDIG5_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4F6F; +constexpr unsigned int mmDIG5_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4F70; +constexpr unsigned int mmDIG6_AFMT_60958_0__VI = 0x5438; +constexpr unsigned int mmDIG6_AFMT_60958_1__VI = 0x5439; +constexpr unsigned int mmDIG6_AFMT_60958_2__VI = 0x543F; +constexpr unsigned int mmDIG6_AFMT_AUDIO_CRC_CONTROL__VI = 0x543A; +constexpr unsigned int mmDIG6_AFMT_AUDIO_CRC_RESULT__VI = 0x5440; +constexpr unsigned int mmDIG6_AFMT_AUDIO_DBG_DTO_CNTL__VI = 0x5446; +constexpr unsigned int mmDIG6_AFMT_AUDIO_INFO0__VI = 0x5436; +constexpr unsigned int mmDIG6_AFMT_AUDIO_INFO1__VI = 0x5437; +constexpr unsigned int mmDIG6_AFMT_AUDIO_PACKET_CONTROL__VI = 0x5442; +constexpr unsigned int mmDIG6_AFMT_AUDIO_PACKET_CONTROL2__VI = 0x5414; +constexpr unsigned int mmDIG6_AFMT_AUDIO_SRC_CONTROL__VI = 0x5445; +constexpr unsigned int mmDIG6_AFMT_AVI_INFO0__VI = 0x541E; +constexpr unsigned int mmDIG6_AFMT_AVI_INFO1__VI = 0x541F; +constexpr unsigned int mmDIG6_AFMT_AVI_INFO2__VI = 0x5420; +constexpr unsigned int mmDIG6_AFMT_AVI_INFO3__VI = 0x5421; +constexpr unsigned int mmDIG6_AFMT_GENERIC_0__VI = 0x5425; +constexpr unsigned int mmDIG6_AFMT_GENERIC_1__VI = 0x5426; +constexpr unsigned int mmDIG6_AFMT_GENERIC_2__VI = 0x5427; +constexpr unsigned int mmDIG6_AFMT_GENERIC_3__VI = 0x5428; +constexpr unsigned int mmDIG6_AFMT_GENERIC_4__VI = 0x5429; +constexpr unsigned int mmDIG6_AFMT_GENERIC_5__VI = 0x542A; +constexpr unsigned int mmDIG6_AFMT_GENERIC_6__VI = 0x542B; +constexpr unsigned int mmDIG6_AFMT_GENERIC_7__VI = 0x542C; +constexpr unsigned int mmDIG6_AFMT_GENERIC_HDR__VI = 0x5424; +constexpr unsigned int mmDIG6_AFMT_INFOFRAME_CONTROL0__VI = 0x5444; +constexpr unsigned int mmDIG6_AFMT_ISRC1_0__VI = 0x5415; +constexpr unsigned int mmDIG6_AFMT_ISRC1_1__VI = 0x5416; +constexpr unsigned int mmDIG6_AFMT_ISRC1_2__VI = 0x5417; +constexpr unsigned int mmDIG6_AFMT_ISRC1_3__VI = 0x5418; +constexpr unsigned int mmDIG6_AFMT_ISRC1_4__VI = 0x5419; +constexpr unsigned int mmDIG6_AFMT_ISRC2_0__VI = 0x541A; +constexpr unsigned int mmDIG6_AFMT_ISRC2_1__VI = 0x541B; +constexpr unsigned int mmDIG6_AFMT_ISRC2_2__VI = 0x541C; +constexpr unsigned int mmDIG6_AFMT_ISRC2_3__VI = 0x541D; +constexpr unsigned int mmDIG6_AFMT_MPEG_INFO0__VI = 0x5422; +constexpr unsigned int mmDIG6_AFMT_MPEG_INFO1__VI = 0x5423; +constexpr unsigned int mmDIG6_AFMT_RAMP_CONTROL0__VI = 0x543B; +constexpr unsigned int mmDIG6_AFMT_RAMP_CONTROL1__VI = 0x543C; +constexpr unsigned int mmDIG6_AFMT_RAMP_CONTROL2__VI = 0x543D; +constexpr unsigned int mmDIG6_AFMT_RAMP_CONTROL3__VI = 0x543E; +constexpr unsigned int mmDIG6_AFMT_STATUS__VI = 0x5441; +constexpr unsigned int mmDIG6_AFMT_VBI_PACKET_CONTROL__VI = 0x5443; +constexpr unsigned int mmDIG6_DIG_BE_CNTL__VI = 0x5447; +constexpr unsigned int mmDIG6_DIG_BE_EN_CNTL__VI = 0x5448; +constexpr unsigned int mmDIG6_DIG_CLOCK_PATTERN__VI = 0x5403; +constexpr unsigned int mmDIG6_DIG_DISPCLK_SWITCH_CNTL__VI = 0x5407; +constexpr unsigned int mmDIG6_DIG_DISPCLK_SWITCH_STATUS__VI = 0x5408; +constexpr unsigned int mmDIG6_DIG_FE_CNTL__VI = 0x5400; +constexpr unsigned int mmDIG6_DIG_FE_TEST_DEBUG_DATA__VI = 0x547D; +constexpr unsigned int mmDIG6_DIG_FE_TEST_DEBUG_INDEX__VI = 0x547C; +constexpr unsigned int mmDIG6_DIG_FIFO_STATUS__VI = 0x5406; +constexpr unsigned int mmDIG6_DIG_LANE_ENABLE__VI = 0x5479; +constexpr unsigned int mmDIG6_DIG_OUTPUT_CRC_CNTL__VI = 0x5401; +constexpr unsigned int mmDIG6_DIG_OUTPUT_CRC_RESULT__VI = 0x5402; +constexpr unsigned int mmDIG6_DIG_RANDOM_PATTERN_SEED__VI = 0x5405; +constexpr unsigned int mmDIG6_DIG_TEST_DEBUG_DATA__VI = 0x547B; +constexpr unsigned int mmDIG6_DIG_TEST_DEBUG_INDEX__VI = 0x547A; +constexpr unsigned int mmDIG6_DIG_TEST_PATTERN__VI = 0x5404; +constexpr unsigned int mmDIG6_HDMI_ACR_32_0__VI = 0x542E; +constexpr unsigned int mmDIG6_HDMI_ACR_32_1__VI = 0x542F; +constexpr unsigned int mmDIG6_HDMI_ACR_44_0__VI = 0x5430; +constexpr unsigned int mmDIG6_HDMI_ACR_44_1__VI = 0x5431; +constexpr unsigned int mmDIG6_HDMI_ACR_48_0__VI = 0x5432; +constexpr unsigned int mmDIG6_HDMI_ACR_48_1__VI = 0x5433; +constexpr unsigned int mmDIG6_HDMI_ACR_PACKET_CONTROL__VI = 0x540C; +constexpr unsigned int mmDIG6_HDMI_ACR_STATUS_0__VI = 0x5434; +constexpr unsigned int mmDIG6_HDMI_ACR_STATUS_1__VI = 0x5435; +constexpr unsigned int mmDIG6_HDMI_AUDIO_PACKET_CONTROL__VI = 0x540B; +constexpr unsigned int mmDIG6_HDMI_CONTROL__VI = 0x5409; +constexpr unsigned int mmDIG6_HDMI_GC__VI = 0x5413; +constexpr unsigned int mmDIG6_HDMI_GENERIC_PACKET_CONTROL0__VI = 0x5410; +constexpr unsigned int mmDIG6_HDMI_GENERIC_PACKET_CONTROL1__VI = 0x542D; +constexpr unsigned int mmDIG6_HDMI_INFOFRAME_CONTROL0__VI = 0x540E; +constexpr unsigned int mmDIG6_HDMI_INFOFRAME_CONTROL1__VI = 0x540F; +constexpr unsigned int mmDIG6_HDMI_STATUS__VI = 0x540A; +constexpr unsigned int mmDIG6_HDMI_VBI_PACKET_CONTROL__VI = 0x540D; +constexpr unsigned int mmDIG6_LVDS_DATA_CNTL__VI = 0x5478; +constexpr unsigned int mmDIG6_TMDS_CNTL__VI = 0x546B; +constexpr unsigned int mmDIG6_TMDS_CONTROL0_FEEDBACK__VI = 0x546D; +constexpr unsigned int mmDIG6_TMDS_CONTROL_CHAR__VI = 0x546C; +constexpr unsigned int mmDIG6_TMDS_CTL0_1_GEN_CNTL__VI = 0x5475; +constexpr unsigned int mmDIG6_TMDS_CTL2_3_GEN_CNTL__VI = 0x5476; +constexpr unsigned int mmDIG6_TMDS_CTL_BITS__VI = 0x5472; +constexpr unsigned int mmDIG6_TMDS_DCBALANCER_CONTROL__VI = 0x5473; +constexpr unsigned int mmDIG6_TMDS_DEBUG__VI = 0x5471; +constexpr unsigned int mmDIG6_TMDS_STEREOSYNC_CTL_SEL__VI = 0x546E; +constexpr unsigned int mmDIG6_TMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x546F; +constexpr unsigned int mmDIG6_TMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x5470; +constexpr unsigned int mmDIG_BE_CNTL__VI = 0x4A47; +constexpr unsigned int mmDIG_BE_EN_CNTL__VI = 0x4A48; +constexpr unsigned int mmDIG_CLOCK_PATTERN__VI = 0x4A03; +constexpr unsigned int mmDIG_DISPCLK_SWITCH_CNTL__VI = 0x4A07; +constexpr unsigned int mmDIG_DISPCLK_SWITCH_STATUS__VI = 0x4A08; +constexpr unsigned int mmDIG_FE_CNTL__VI = 0x4A00; +constexpr unsigned int mmDIG_FE_TEST_DEBUG_DATA__VI = 0x4A7D; +constexpr unsigned int mmDIG_FE_TEST_DEBUG_INDEX__VI = 0x4A7C; +constexpr unsigned int mmDIG_FIFO_STATUS__VI = 0x4A06; +constexpr unsigned int mmDIG_LANE_ENABLE__VI = 0x4A79; +constexpr unsigned int mmDIG_OUTPUT_CRC_CNTL__VI = 0x4A01; +constexpr unsigned int mmDIG_OUTPUT_CRC_RESULT__VI = 0x4A02; +constexpr unsigned int mmDIG_RANDOM_PATTERN_SEED__VI = 0x4A05; +constexpr unsigned int mmDIG_SOFT_RESET__VI = 0x1872; +constexpr unsigned int mmDIG_TEST_DEBUG_DATA__VI = 0x4A7B; +constexpr unsigned int mmDIG_TEST_DEBUG_INDEX__VI = 0x4A7A; +constexpr unsigned int mmDIG_TEST_PATTERN__VI = 0x4A04; +constexpr unsigned int mmDISPCLK_CGTT_BLK_CTRL_REG__VI = 0x0135; +constexpr unsigned int mmDISPCLK_FREQ_CHANGE_CNTL__VI = 0x0131; +constexpr unsigned int mmDISPPLL_BG_CNTL__VI = 0x171E; +constexpr unsigned int mmDISP_INTERRUPT_STATUS__VI = 0x1857; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE__VI = 0x1858; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE2__VI = 0x1859; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE3__VI = 0x185A; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE4__VI = 0x185B; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE5__VI = 0x185C; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE6__VI = 0x185D; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE7__VI = 0x185E; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE8__VI = 0x185F; +constexpr unsigned int mmDISP_INTERRUPT_STATUS_CONTINUE9__VI = 0x1860; +constexpr unsigned int mmDMCU_DPRX_INTERRUPT_STATUS1__VI = 0x1634; +constexpr unsigned int mmDMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__VI = 0x1635; +constexpr unsigned int mmDMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__VI = 0x1636; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_STATUS1__VI = 0x1644; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_STATUS2__VI = 0x1645; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_STATUS3__VI = 0x1646; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_STATUS4__VI = 0x1647; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_STATUS5__VI = 0x1642; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_HOST_EN_MASK1__VI = 0x167C; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_HOST_EN_MASK2__VI = 0x167D; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_HOST_EN_MASK3__VI = 0x167E; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_HOST_EN_MASK4__VI = 0x167F; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_HOST_EN_MASK5__VI = 0x1633; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__VI = 0x1674; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__VI = 0x1675; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__VI = 0x1676; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__VI = 0x1677; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__VI = 0x1643; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__VI = 0x1678; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__VI = 0x1679; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__VI = 0x167A; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__VI = 0x167B; +constexpr unsigned int mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__VI = 0x1673; +constexpr unsigned int mmDMCU_SMU_INTERRUPT_CNTL__VI = 0x012C; +constexpr unsigned int mmDMCU_SS_INTERRUPT_CNTL_STATUS__VI = 0x1613; +constexpr unsigned int mmDMCU_UC_CLK_GATING_CNTL__VI = 0x161B; +constexpr unsigned int mmDMIF_ADDR_CALC__VI = 0x0303; +constexpr unsigned int mmDMIF_ADDR_CONFIG__VI = 0x02F5; +constexpr unsigned int mmDMIF_PG0_DPG_HW_DEBUG_11__VI = 0x1B3D; +constexpr unsigned int mmDMIF_PG0_DPG_HW_DEBUG_A__VI = 0x1B3B; +constexpr unsigned int mmDMIF_PG0_DPG_HW_DEBUG_B__VI = 0x1B3C; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x1B30; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x1B31; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_DPM_CONTROL__VI = 0x1B34; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x1B36; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL__VI = 0x1B35; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x1B37; +constexpr unsigned int mmDMIF_PG0_DPG_PIPE_URGENCY_CONTROL__VI = 0x1B33; +constexpr unsigned int mmDMIF_PG0_DPG_REPEATER_PROGRAM__VI = 0x1B3A; +constexpr unsigned int mmDMIF_PG0_DPG_TEST_DEBUG_DATA__VI = 0x1B39; +constexpr unsigned int mmDMIF_PG0_DPG_TEST_DEBUG_INDEX__VI = 0x1B38; +constexpr unsigned int mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL__VI = 0x1B32; +constexpr unsigned int mmDMIF_PG1_DPG_HW_DEBUG_11__VI = 0x1D3D; +constexpr unsigned int mmDMIF_PG1_DPG_HW_DEBUG_A__VI = 0x1D3B; +constexpr unsigned int mmDMIF_PG1_DPG_HW_DEBUG_B__VI = 0x1D3C; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x1D30; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x1D31; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_DPM_CONTROL__VI = 0x1D34; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x1D36; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL__VI = 0x1D35; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x1D37; +constexpr unsigned int mmDMIF_PG1_DPG_PIPE_URGENCY_CONTROL__VI = 0x1D33; +constexpr unsigned int mmDMIF_PG1_DPG_REPEATER_PROGRAM__VI = 0x1D3A; +constexpr unsigned int mmDMIF_PG1_DPG_TEST_DEBUG_DATA__VI = 0x1D39; +constexpr unsigned int mmDMIF_PG1_DPG_TEST_DEBUG_INDEX__VI = 0x1D38; +constexpr unsigned int mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL__VI = 0x1D32; +constexpr unsigned int mmDMIF_PG2_DPG_HW_DEBUG_11__VI = 0x1F3D; +constexpr unsigned int mmDMIF_PG2_DPG_HW_DEBUG_A__VI = 0x1F3B; +constexpr unsigned int mmDMIF_PG2_DPG_HW_DEBUG_B__VI = 0x1F3C; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x1F30; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x1F31; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_DPM_CONTROL__VI = 0x1F34; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x1F36; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL__VI = 0x1F35; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x1F37; +constexpr unsigned int mmDMIF_PG2_DPG_PIPE_URGENCY_CONTROL__VI = 0x1F33; +constexpr unsigned int mmDMIF_PG2_DPG_REPEATER_PROGRAM__VI = 0x1F3A; +constexpr unsigned int mmDMIF_PG2_DPG_TEST_DEBUG_DATA__VI = 0x1F39; +constexpr unsigned int mmDMIF_PG2_DPG_TEST_DEBUG_INDEX__VI = 0x1F38; +constexpr unsigned int mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL__VI = 0x1F32; +constexpr unsigned int mmDMIF_PG3_DPG_HW_DEBUG_11__VI = 0x413D; +constexpr unsigned int mmDMIF_PG3_DPG_HW_DEBUG_A__VI = 0x413B; +constexpr unsigned int mmDMIF_PG3_DPG_HW_DEBUG_B__VI = 0x413C; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x4130; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x4131; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_DPM_CONTROL__VI = 0x4134; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x4136; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL__VI = 0x4135; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x4137; +constexpr unsigned int mmDMIF_PG3_DPG_PIPE_URGENCY_CONTROL__VI = 0x4133; +constexpr unsigned int mmDMIF_PG3_DPG_REPEATER_PROGRAM__VI = 0x413A; +constexpr unsigned int mmDMIF_PG3_DPG_TEST_DEBUG_DATA__VI = 0x4139; +constexpr unsigned int mmDMIF_PG3_DPG_TEST_DEBUG_INDEX__VI = 0x4138; +constexpr unsigned int mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL__VI = 0x4132; +constexpr unsigned int mmDMIF_PG4_DPG_HW_DEBUG_11__VI = 0x433D; +constexpr unsigned int mmDMIF_PG4_DPG_HW_DEBUG_A__VI = 0x433B; +constexpr unsigned int mmDMIF_PG4_DPG_HW_DEBUG_B__VI = 0x433C; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x4330; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x4331; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_DPM_CONTROL__VI = 0x4334; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x4336; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL__VI = 0x4335; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x4337; +constexpr unsigned int mmDMIF_PG4_DPG_PIPE_URGENCY_CONTROL__VI = 0x4333; +constexpr unsigned int mmDMIF_PG4_DPG_REPEATER_PROGRAM__VI = 0x433A; +constexpr unsigned int mmDMIF_PG4_DPG_TEST_DEBUG_DATA__VI = 0x4339; +constexpr unsigned int mmDMIF_PG4_DPG_TEST_DEBUG_INDEX__VI = 0x4338; +constexpr unsigned int mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL__VI = 0x4332; +constexpr unsigned int mmDMIF_PG5_DPG_HW_DEBUG_11__VI = 0x453D; +constexpr unsigned int mmDMIF_PG5_DPG_HW_DEBUG_A__VI = 0x453B; +constexpr unsigned int mmDMIF_PG5_DPG_HW_DEBUG_B__VI = 0x453C; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x4530; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x4531; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_DPM_CONTROL__VI = 0x4534; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x4536; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL__VI = 0x4535; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x4537; +constexpr unsigned int mmDMIF_PG5_DPG_PIPE_URGENCY_CONTROL__VI = 0x4533; +constexpr unsigned int mmDMIF_PG5_DPG_REPEATER_PROGRAM__VI = 0x453A; +constexpr unsigned int mmDMIF_PG5_DPG_TEST_DEBUG_DATA__VI = 0x4539; +constexpr unsigned int mmDMIF_PG5_DPG_TEST_DEBUG_INDEX__VI = 0x4538; +constexpr unsigned int mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL__VI = 0x4532; +constexpr unsigned int mmDMIF_PG6_DPG_HW_DEBUG_11__VI = 0x473D; +constexpr unsigned int mmDMIF_PG6_DPG_HW_DEBUG_A__VI = 0x473B; +constexpr unsigned int mmDMIF_PG6_DPG_HW_DEBUG_B__VI = 0x473C; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_ARBITRATION_CONTROL1__VI = 0x4730; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_ARBITRATION_CONTROL2__VI = 0x4731; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_DPM_CONTROL__VI = 0x4734; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x4736; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_STUTTER_CONTROL__VI = 0x4735; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x4737; +constexpr unsigned int mmDMIF_PG6_DPG_PIPE_URGENCY_CONTROL__VI = 0x4733; +constexpr unsigned int mmDMIF_PG6_DPG_REPEATER_PROGRAM__VI = 0x473A; +constexpr unsigned int mmDMIF_PG6_DPG_TEST_DEBUG_DATA__VI = 0x4739; +constexpr unsigned int mmDMIF_PG6_DPG_TEST_DEBUG_INDEX__VI = 0x4738; +constexpr unsigned int mmDMIF_PG6_DPG_WATERMARK_MASK_CONTROL__VI = 0x4732; +constexpr unsigned int mmDMIF_P_VMID__VI = 0x0300; +constexpr unsigned int mmDMIF_STATUS2__VI = 0x0304; +constexpr unsigned int mmDMIF_TEST_DEBUG_DATA__VI = 0x0302; +constexpr unsigned int mmDMIF_TEST_DEBUG_INDEX__VI = 0x0301; +constexpr unsigned int mmDMIF_URG_OVERRIDE__VI = 0x0329; +constexpr unsigned int mmDP0_DP_CONFIG__VI = 0x4AA3; +constexpr unsigned int mmDP0_DP_DPHY_8B10B_CNTL__VI = 0x4AB4; +constexpr unsigned int mmDP0_DP_DPHY_CNTL__VI = 0x4AAF; +constexpr unsigned int mmDP0_DP_DPHY_CRC_CNTL__VI = 0x4AB8; +constexpr unsigned int mmDP0_DP_DPHY_CRC_EN__VI = 0x4AB7; +constexpr unsigned int mmDP0_DP_DPHY_CRC_MST_CNTL__VI = 0x4ABA; +constexpr unsigned int mmDP0_DP_DPHY_CRC_MST_STATUS__VI = 0x4ABB; +constexpr unsigned int mmDP0_DP_DPHY_CRC_RESULT__VI = 0x4AB9; +constexpr unsigned int mmDP0_DP_DPHY_FAST_TRAINING__VI = 0x4ABC; +constexpr unsigned int mmDP0_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x4ABD; +constexpr unsigned int mmDP0_DP_DPHY_PRBS_CNTL__VI = 0x4AB5; +constexpr unsigned int mmDP0_DP_DPHY_SYM0__VI = 0x4AB1; +constexpr unsigned int mmDP0_DP_DPHY_SYM1__VI = 0x4AB2; +constexpr unsigned int mmDP0_DP_DPHY_SYM2__VI = 0x4AB3; +constexpr unsigned int mmDP0_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4AB0; +constexpr unsigned int mmDP0_DP_FE_TEST_DEBUG_DATA__VI = 0x4ADB; +constexpr unsigned int mmDP0_DP_FE_TEST_DEBUG_INDEX__VI = 0x4ADA; +constexpr unsigned int mmDP0_DP_HBR2_EYE_PATTERN__VI = 0x4AAC; +constexpr unsigned int mmDP0_DP_LINK_CNTL__VI = 0x4AA0; +constexpr unsigned int mmDP0_DP_LINK_FRAMING_CNTL__VI = 0x4AAB; +constexpr unsigned int mmDP0_DP_MSA_COLORIMETRY__VI = 0x4AA2; +constexpr unsigned int mmDP0_DP_MSA_MISC__VI = 0x4AA6; +constexpr unsigned int mmDP0_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x4ABE; +constexpr unsigned int mmDP0_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x4ABF; +constexpr unsigned int mmDP0_DP_MSE_LINK_TIMING__VI = 0x4AD6; +constexpr unsigned int mmDP0_DP_MSE_MISC_CNTL__VI = 0x4AD7; +constexpr unsigned int mmDP0_DP_MSE_RATE_CNTL__VI = 0x4ACF; +constexpr unsigned int mmDP0_DP_MSE_RATE_UPDATE__VI = 0x4AD1; +constexpr unsigned int mmDP0_DP_MSE_SAT0__VI = 0x4AD2; +constexpr unsigned int mmDP0_DP_MSE_SAT1__VI = 0x4AD3; +constexpr unsigned int mmDP0_DP_MSE_SAT2__VI = 0x4AD4; +constexpr unsigned int mmDP0_DP_MSE_SAT_UPDATE__VI = 0x4AD5; +constexpr unsigned int mmDP0_DP_PIXEL_FORMAT__VI = 0x4AA1; +constexpr unsigned int mmDP0_DP_SEC_AUD_M__VI = 0x4ACB; +constexpr unsigned int mmDP0_DP_SEC_AUD_M_READBACK__VI = 0x4ACC; +constexpr unsigned int mmDP0_DP_SEC_AUD_N__VI = 0x4AC9; +constexpr unsigned int mmDP0_DP_SEC_AUD_N_READBACK__VI = 0x4ACA; +constexpr unsigned int mmDP0_DP_SEC_CNTL__VI = 0x4AC3; +constexpr unsigned int mmDP0_DP_SEC_CNTL1__VI = 0x4AC4; +constexpr unsigned int mmDP0_DP_SEC_FRAMING1__VI = 0x4AC5; +constexpr unsigned int mmDP0_DP_SEC_FRAMING2__VI = 0x4AC6; +constexpr unsigned int mmDP0_DP_SEC_FRAMING3__VI = 0x4AC7; +constexpr unsigned int mmDP0_DP_SEC_FRAMING4__VI = 0x4AC8; +constexpr unsigned int mmDP0_DP_SEC_PACKET_CNTL__VI = 0x4ACE; +constexpr unsigned int mmDP0_DP_SEC_TIMESTAMP__VI = 0x4ACD; +constexpr unsigned int mmDP0_DP_STEER_FIFO__VI = 0x4AA5; +constexpr unsigned int mmDP0_DP_TEST_DEBUG_DATA__VI = 0x4AD9; +constexpr unsigned int mmDP0_DP_TEST_DEBUG_INDEX__VI = 0x4AD8; +constexpr unsigned int mmDP0_DP_VID_INTERRUPT_CNTL__VI = 0x4AAE; +constexpr unsigned int mmDP0_DP_VID_M__VI = 0x4AAA; +constexpr unsigned int mmDP0_DP_VID_MSA_VBID__VI = 0x4AAD; +constexpr unsigned int mmDP0_DP_VID_N__VI = 0x4AA9; +constexpr unsigned int mmDP0_DP_VID_STREAM_CNTL__VI = 0x4AA4; +constexpr unsigned int mmDP0_DP_VID_TIMING__VI = 0x4AA8; +constexpr unsigned int mmDP1_DP_CONFIG__VI = 0x4BA3; +constexpr unsigned int mmDP1_DP_DPHY_8B10B_CNTL__VI = 0x4BB4; +constexpr unsigned int mmDP1_DP_DPHY_CNTL__VI = 0x4BAF; +constexpr unsigned int mmDP1_DP_DPHY_CRC_CNTL__VI = 0x4BB8; +constexpr unsigned int mmDP1_DP_DPHY_CRC_EN__VI = 0x4BB7; +constexpr unsigned int mmDP1_DP_DPHY_CRC_MST_CNTL__VI = 0x4BBA; +constexpr unsigned int mmDP1_DP_DPHY_CRC_MST_STATUS__VI = 0x4BBB; +constexpr unsigned int mmDP1_DP_DPHY_CRC_RESULT__VI = 0x4BB9; +constexpr unsigned int mmDP1_DP_DPHY_FAST_TRAINING__VI = 0x4BBC; +constexpr unsigned int mmDP1_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x4BBD; +constexpr unsigned int mmDP1_DP_DPHY_PRBS_CNTL__VI = 0x4BB5; +constexpr unsigned int mmDP1_DP_DPHY_SYM0__VI = 0x4BB1; +constexpr unsigned int mmDP1_DP_DPHY_SYM1__VI = 0x4BB2; +constexpr unsigned int mmDP1_DP_DPHY_SYM2__VI = 0x4BB3; +constexpr unsigned int mmDP1_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4BB0; +constexpr unsigned int mmDP1_DP_FE_TEST_DEBUG_DATA__VI = 0x4BDB; +constexpr unsigned int mmDP1_DP_FE_TEST_DEBUG_INDEX__VI = 0x4BDA; +constexpr unsigned int mmDP1_DP_HBR2_EYE_PATTERN__VI = 0x4BAC; +constexpr unsigned int mmDP1_DP_LINK_CNTL__VI = 0x4BA0; +constexpr unsigned int mmDP1_DP_LINK_FRAMING_CNTL__VI = 0x4BAB; +constexpr unsigned int mmDP1_DP_MSA_COLORIMETRY__VI = 0x4BA2; +constexpr unsigned int mmDP1_DP_MSA_MISC__VI = 0x4BA6; +constexpr unsigned int mmDP1_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x4BBE; +constexpr unsigned int mmDP1_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x4BBF; +constexpr unsigned int mmDP1_DP_MSE_LINK_TIMING__VI = 0x4BD6; +constexpr unsigned int mmDP1_DP_MSE_MISC_CNTL__VI = 0x4BD7; +constexpr unsigned int mmDP1_DP_MSE_RATE_CNTL__VI = 0x4BCF; +constexpr unsigned int mmDP1_DP_MSE_RATE_UPDATE__VI = 0x4BD1; +constexpr unsigned int mmDP1_DP_MSE_SAT0__VI = 0x4BD2; +constexpr unsigned int mmDP1_DP_MSE_SAT1__VI = 0x4BD3; +constexpr unsigned int mmDP1_DP_MSE_SAT2__VI = 0x4BD4; +constexpr unsigned int mmDP1_DP_MSE_SAT_UPDATE__VI = 0x4BD5; +constexpr unsigned int mmDP1_DP_PIXEL_FORMAT__VI = 0x4BA1; +constexpr unsigned int mmDP1_DP_SEC_AUD_M__VI = 0x4BCB; +constexpr unsigned int mmDP1_DP_SEC_AUD_M_READBACK__VI = 0x4BCC; +constexpr unsigned int mmDP1_DP_SEC_AUD_N__VI = 0x4BC9; +constexpr unsigned int mmDP1_DP_SEC_AUD_N_READBACK__VI = 0x4BCA; +constexpr unsigned int mmDP1_DP_SEC_CNTL__VI = 0x4BC3; +constexpr unsigned int mmDP1_DP_SEC_CNTL1__VI = 0x4BC4; +constexpr unsigned int mmDP1_DP_SEC_FRAMING1__VI = 0x4BC5; +constexpr unsigned int mmDP1_DP_SEC_FRAMING2__VI = 0x4BC6; +constexpr unsigned int mmDP1_DP_SEC_FRAMING3__VI = 0x4BC7; +constexpr unsigned int mmDP1_DP_SEC_FRAMING4__VI = 0x4BC8; +constexpr unsigned int mmDP1_DP_SEC_PACKET_CNTL__VI = 0x4BCE; +constexpr unsigned int mmDP1_DP_SEC_TIMESTAMP__VI = 0x4BCD; +constexpr unsigned int mmDP1_DP_STEER_FIFO__VI = 0x4BA5; +constexpr unsigned int mmDP1_DP_TEST_DEBUG_DATA__VI = 0x4BD9; +constexpr unsigned int mmDP1_DP_TEST_DEBUG_INDEX__VI = 0x4BD8; +constexpr unsigned int mmDP1_DP_VID_INTERRUPT_CNTL__VI = 0x4BAE; +constexpr unsigned int mmDP1_DP_VID_M__VI = 0x4BAA; +constexpr unsigned int mmDP1_DP_VID_MSA_VBID__VI = 0x4BAD; +constexpr unsigned int mmDP1_DP_VID_N__VI = 0x4BA9; +constexpr unsigned int mmDP1_DP_VID_STREAM_CNTL__VI = 0x4BA4; +constexpr unsigned int mmDP1_DP_VID_TIMING__VI = 0x4BA8; +constexpr unsigned int mmDP2_DP_CONFIG__VI = 0x4CA3; +constexpr unsigned int mmDP2_DP_DPHY_8B10B_CNTL__VI = 0x4CB4; +constexpr unsigned int mmDP2_DP_DPHY_CNTL__VI = 0x4CAF; +constexpr unsigned int mmDP2_DP_DPHY_CRC_CNTL__VI = 0x4CB8; +constexpr unsigned int mmDP2_DP_DPHY_CRC_EN__VI = 0x4CB7; +constexpr unsigned int mmDP2_DP_DPHY_CRC_MST_CNTL__VI = 0x4CBA; +constexpr unsigned int mmDP2_DP_DPHY_CRC_MST_STATUS__VI = 0x4CBB; +constexpr unsigned int mmDP2_DP_DPHY_CRC_RESULT__VI = 0x4CB9; +constexpr unsigned int mmDP2_DP_DPHY_FAST_TRAINING__VI = 0x4CBC; +constexpr unsigned int mmDP2_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x4CBD; +constexpr unsigned int mmDP2_DP_DPHY_PRBS_CNTL__VI = 0x4CB5; +constexpr unsigned int mmDP2_DP_DPHY_SYM0__VI = 0x4CB1; +constexpr unsigned int mmDP2_DP_DPHY_SYM1__VI = 0x4CB2; +constexpr unsigned int mmDP2_DP_DPHY_SYM2__VI = 0x4CB3; +constexpr unsigned int mmDP2_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4CB0; +constexpr unsigned int mmDP2_DP_FE_TEST_DEBUG_DATA__VI = 0x4CDB; +constexpr unsigned int mmDP2_DP_FE_TEST_DEBUG_INDEX__VI = 0x4CDA; +constexpr unsigned int mmDP2_DP_HBR2_EYE_PATTERN__VI = 0x4CAC; +constexpr unsigned int mmDP2_DP_LINK_CNTL__VI = 0x4CA0; +constexpr unsigned int mmDP2_DP_LINK_FRAMING_CNTL__VI = 0x4CAB; +constexpr unsigned int mmDP2_DP_MSA_COLORIMETRY__VI = 0x4CA2; +constexpr unsigned int mmDP2_DP_MSA_MISC__VI = 0x4CA6; +constexpr unsigned int mmDP2_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x4CBE; +constexpr unsigned int mmDP2_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x4CBF; +constexpr unsigned int mmDP2_DP_MSE_LINK_TIMING__VI = 0x4CD6; +constexpr unsigned int mmDP2_DP_MSE_MISC_CNTL__VI = 0x4CD7; +constexpr unsigned int mmDP2_DP_MSE_RATE_CNTL__VI = 0x4CCF; +constexpr unsigned int mmDP2_DP_MSE_RATE_UPDATE__VI = 0x4CD1; +constexpr unsigned int mmDP2_DP_MSE_SAT0__VI = 0x4CD2; +constexpr unsigned int mmDP2_DP_MSE_SAT1__VI = 0x4CD3; +constexpr unsigned int mmDP2_DP_MSE_SAT2__VI = 0x4CD4; +constexpr unsigned int mmDP2_DP_MSE_SAT_UPDATE__VI = 0x4CD5; +constexpr unsigned int mmDP2_DP_PIXEL_FORMAT__VI = 0x4CA1; +constexpr unsigned int mmDP2_DP_SEC_AUD_M__VI = 0x4CCB; +constexpr unsigned int mmDP2_DP_SEC_AUD_M_READBACK__VI = 0x4CCC; +constexpr unsigned int mmDP2_DP_SEC_AUD_N__VI = 0x4CC9; +constexpr unsigned int mmDP2_DP_SEC_AUD_N_READBACK__VI = 0x4CCA; +constexpr unsigned int mmDP2_DP_SEC_CNTL__VI = 0x4CC3; +constexpr unsigned int mmDP2_DP_SEC_CNTL1__VI = 0x4CC4; +constexpr unsigned int mmDP2_DP_SEC_FRAMING1__VI = 0x4CC5; +constexpr unsigned int mmDP2_DP_SEC_FRAMING2__VI = 0x4CC6; +constexpr unsigned int mmDP2_DP_SEC_FRAMING3__VI = 0x4CC7; +constexpr unsigned int mmDP2_DP_SEC_FRAMING4__VI = 0x4CC8; +constexpr unsigned int mmDP2_DP_SEC_PACKET_CNTL__VI = 0x4CCE; +constexpr unsigned int mmDP2_DP_SEC_TIMESTAMP__VI = 0x4CCD; +constexpr unsigned int mmDP2_DP_STEER_FIFO__VI = 0x4CA5; +constexpr unsigned int mmDP2_DP_TEST_DEBUG_DATA__VI = 0x4CD9; +constexpr unsigned int mmDP2_DP_TEST_DEBUG_INDEX__VI = 0x4CD8; +constexpr unsigned int mmDP2_DP_VID_INTERRUPT_CNTL__VI = 0x4CAE; +constexpr unsigned int mmDP2_DP_VID_M__VI = 0x4CAA; +constexpr unsigned int mmDP2_DP_VID_MSA_VBID__VI = 0x4CAD; +constexpr unsigned int mmDP2_DP_VID_N__VI = 0x4CA9; +constexpr unsigned int mmDP2_DP_VID_STREAM_CNTL__VI = 0x4CA4; +constexpr unsigned int mmDP2_DP_VID_TIMING__VI = 0x4CA8; +constexpr unsigned int mmDP3_DP_CONFIG__VI = 0x4DA3; +constexpr unsigned int mmDP3_DP_DPHY_8B10B_CNTL__VI = 0x4DB4; +constexpr unsigned int mmDP3_DP_DPHY_CNTL__VI = 0x4DAF; +constexpr unsigned int mmDP3_DP_DPHY_CRC_CNTL__VI = 0x4DB8; +constexpr unsigned int mmDP3_DP_DPHY_CRC_EN__VI = 0x4DB7; +constexpr unsigned int mmDP3_DP_DPHY_CRC_MST_CNTL__VI = 0x4DBA; +constexpr unsigned int mmDP3_DP_DPHY_CRC_MST_STATUS__VI = 0x4DBB; +constexpr unsigned int mmDP3_DP_DPHY_CRC_RESULT__VI = 0x4DB9; +constexpr unsigned int mmDP3_DP_DPHY_FAST_TRAINING__VI = 0x4DBC; +constexpr unsigned int mmDP3_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x4DBD; +constexpr unsigned int mmDP3_DP_DPHY_PRBS_CNTL__VI = 0x4DB5; +constexpr unsigned int mmDP3_DP_DPHY_SYM0__VI = 0x4DB1; +constexpr unsigned int mmDP3_DP_DPHY_SYM1__VI = 0x4DB2; +constexpr unsigned int mmDP3_DP_DPHY_SYM2__VI = 0x4DB3; +constexpr unsigned int mmDP3_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4DB0; +constexpr unsigned int mmDP3_DP_FE_TEST_DEBUG_DATA__VI = 0x4DDB; +constexpr unsigned int mmDP3_DP_FE_TEST_DEBUG_INDEX__VI = 0x4DDA; +constexpr unsigned int mmDP3_DP_HBR2_EYE_PATTERN__VI = 0x4DAC; +constexpr unsigned int mmDP3_DP_LINK_CNTL__VI = 0x4DA0; +constexpr unsigned int mmDP3_DP_LINK_FRAMING_CNTL__VI = 0x4DAB; +constexpr unsigned int mmDP3_DP_MSA_COLORIMETRY__VI = 0x4DA2; +constexpr unsigned int mmDP3_DP_MSA_MISC__VI = 0x4DA6; +constexpr unsigned int mmDP3_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x4DBE; +constexpr unsigned int mmDP3_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x4DBF; +constexpr unsigned int mmDP3_DP_MSE_LINK_TIMING__VI = 0x4DD6; +constexpr unsigned int mmDP3_DP_MSE_MISC_CNTL__VI = 0x4DD7; +constexpr unsigned int mmDP3_DP_MSE_RATE_CNTL__VI = 0x4DCF; +constexpr unsigned int mmDP3_DP_MSE_RATE_UPDATE__VI = 0x4DD1; +constexpr unsigned int mmDP3_DP_MSE_SAT0__VI = 0x4DD2; +constexpr unsigned int mmDP3_DP_MSE_SAT1__VI = 0x4DD3; +constexpr unsigned int mmDP3_DP_MSE_SAT2__VI = 0x4DD4; +constexpr unsigned int mmDP3_DP_MSE_SAT_UPDATE__VI = 0x4DD5; +constexpr unsigned int mmDP3_DP_PIXEL_FORMAT__VI = 0x4DA1; +constexpr unsigned int mmDP3_DP_SEC_AUD_M__VI = 0x4DCB; +constexpr unsigned int mmDP3_DP_SEC_AUD_M_READBACK__VI = 0x4DCC; +constexpr unsigned int mmDP3_DP_SEC_AUD_N__VI = 0x4DC9; +constexpr unsigned int mmDP3_DP_SEC_AUD_N_READBACK__VI = 0x4DCA; +constexpr unsigned int mmDP3_DP_SEC_CNTL__VI = 0x4DC3; +constexpr unsigned int mmDP3_DP_SEC_CNTL1__VI = 0x4DC4; +constexpr unsigned int mmDP3_DP_SEC_FRAMING1__VI = 0x4DC5; +constexpr unsigned int mmDP3_DP_SEC_FRAMING2__VI = 0x4DC6; +constexpr unsigned int mmDP3_DP_SEC_FRAMING3__VI = 0x4DC7; +constexpr unsigned int mmDP3_DP_SEC_FRAMING4__VI = 0x4DC8; +constexpr unsigned int mmDP3_DP_SEC_PACKET_CNTL__VI = 0x4DCE; +constexpr unsigned int mmDP3_DP_SEC_TIMESTAMP__VI = 0x4DCD; +constexpr unsigned int mmDP3_DP_STEER_FIFO__VI = 0x4DA5; +constexpr unsigned int mmDP3_DP_TEST_DEBUG_DATA__VI = 0x4DD9; +constexpr unsigned int mmDP3_DP_TEST_DEBUG_INDEX__VI = 0x4DD8; +constexpr unsigned int mmDP3_DP_VID_INTERRUPT_CNTL__VI = 0x4DAE; +constexpr unsigned int mmDP3_DP_VID_M__VI = 0x4DAA; +constexpr unsigned int mmDP3_DP_VID_MSA_VBID__VI = 0x4DAD; +constexpr unsigned int mmDP3_DP_VID_N__VI = 0x4DA9; +constexpr unsigned int mmDP3_DP_VID_STREAM_CNTL__VI = 0x4DA4; +constexpr unsigned int mmDP3_DP_VID_TIMING__VI = 0x4DA8; +constexpr unsigned int mmDP4_DP_CONFIG__VI = 0x4EA3; +constexpr unsigned int mmDP4_DP_DPHY_8B10B_CNTL__VI = 0x4EB4; +constexpr unsigned int mmDP4_DP_DPHY_CNTL__VI = 0x4EAF; +constexpr unsigned int mmDP4_DP_DPHY_CRC_CNTL__VI = 0x4EB8; +constexpr unsigned int mmDP4_DP_DPHY_CRC_EN__VI = 0x4EB7; +constexpr unsigned int mmDP4_DP_DPHY_CRC_MST_CNTL__VI = 0x4EBA; +constexpr unsigned int mmDP4_DP_DPHY_CRC_MST_STATUS__VI = 0x4EBB; +constexpr unsigned int mmDP4_DP_DPHY_CRC_RESULT__VI = 0x4EB9; +constexpr unsigned int mmDP4_DP_DPHY_FAST_TRAINING__VI = 0x4EBC; +constexpr unsigned int mmDP4_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x4EBD; +constexpr unsigned int mmDP4_DP_DPHY_PRBS_CNTL__VI = 0x4EB5; +constexpr unsigned int mmDP4_DP_DPHY_SYM0__VI = 0x4EB1; +constexpr unsigned int mmDP4_DP_DPHY_SYM1__VI = 0x4EB2; +constexpr unsigned int mmDP4_DP_DPHY_SYM2__VI = 0x4EB3; +constexpr unsigned int mmDP4_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4EB0; +constexpr unsigned int mmDP4_DP_FE_TEST_DEBUG_DATA__VI = 0x4EDB; +constexpr unsigned int mmDP4_DP_FE_TEST_DEBUG_INDEX__VI = 0x4EDA; +constexpr unsigned int mmDP4_DP_HBR2_EYE_PATTERN__VI = 0x4EAC; +constexpr unsigned int mmDP4_DP_LINK_CNTL__VI = 0x4EA0; +constexpr unsigned int mmDP4_DP_LINK_FRAMING_CNTL__VI = 0x4EAB; +constexpr unsigned int mmDP4_DP_MSA_COLORIMETRY__VI = 0x4EA2; +constexpr unsigned int mmDP4_DP_MSA_MISC__VI = 0x4EA6; +constexpr unsigned int mmDP4_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x4EBE; +constexpr unsigned int mmDP4_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x4EBF; +constexpr unsigned int mmDP4_DP_MSE_LINK_TIMING__VI = 0x4ED6; +constexpr unsigned int mmDP4_DP_MSE_MISC_CNTL__VI = 0x4ED7; +constexpr unsigned int mmDP4_DP_MSE_RATE_CNTL__VI = 0x4ECF; +constexpr unsigned int mmDP4_DP_MSE_RATE_UPDATE__VI = 0x4ED1; +constexpr unsigned int mmDP4_DP_MSE_SAT0__VI = 0x4ED2; +constexpr unsigned int mmDP4_DP_MSE_SAT1__VI = 0x4ED3; +constexpr unsigned int mmDP4_DP_MSE_SAT2__VI = 0x4ED4; +constexpr unsigned int mmDP4_DP_MSE_SAT_UPDATE__VI = 0x4ED5; +constexpr unsigned int mmDP4_DP_PIXEL_FORMAT__VI = 0x4EA1; +constexpr unsigned int mmDP4_DP_SEC_AUD_M__VI = 0x4ECB; +constexpr unsigned int mmDP4_DP_SEC_AUD_M_READBACK__VI = 0x4ECC; +constexpr unsigned int mmDP4_DP_SEC_AUD_N__VI = 0x4EC9; +constexpr unsigned int mmDP4_DP_SEC_AUD_N_READBACK__VI = 0x4ECA; +constexpr unsigned int mmDP4_DP_SEC_CNTL__VI = 0x4EC3; +constexpr unsigned int mmDP4_DP_SEC_CNTL1__VI = 0x4EC4; +constexpr unsigned int mmDP4_DP_SEC_FRAMING1__VI = 0x4EC5; +constexpr unsigned int mmDP4_DP_SEC_FRAMING2__VI = 0x4EC6; +constexpr unsigned int mmDP4_DP_SEC_FRAMING3__VI = 0x4EC7; +constexpr unsigned int mmDP4_DP_SEC_FRAMING4__VI = 0x4EC8; +constexpr unsigned int mmDP4_DP_SEC_PACKET_CNTL__VI = 0x4ECE; +constexpr unsigned int mmDP4_DP_SEC_TIMESTAMP__VI = 0x4ECD; +constexpr unsigned int mmDP4_DP_STEER_FIFO__VI = 0x4EA5; +constexpr unsigned int mmDP4_DP_TEST_DEBUG_DATA__VI = 0x4ED9; +constexpr unsigned int mmDP4_DP_TEST_DEBUG_INDEX__VI = 0x4ED8; +constexpr unsigned int mmDP4_DP_VID_INTERRUPT_CNTL__VI = 0x4EAE; +constexpr unsigned int mmDP4_DP_VID_M__VI = 0x4EAA; +constexpr unsigned int mmDP4_DP_VID_MSA_VBID__VI = 0x4EAD; +constexpr unsigned int mmDP4_DP_VID_N__VI = 0x4EA9; +constexpr unsigned int mmDP4_DP_VID_STREAM_CNTL__VI = 0x4EA4; +constexpr unsigned int mmDP4_DP_VID_TIMING__VI = 0x4EA8; +constexpr unsigned int mmDP5_DP_CONFIG__VI = 0x4FA3; +constexpr unsigned int mmDP5_DP_DPHY_8B10B_CNTL__VI = 0x4FB4; +constexpr unsigned int mmDP5_DP_DPHY_CNTL__VI = 0x4FAF; +constexpr unsigned int mmDP5_DP_DPHY_CRC_CNTL__VI = 0x4FB8; +constexpr unsigned int mmDP5_DP_DPHY_CRC_EN__VI = 0x4FB7; +constexpr unsigned int mmDP5_DP_DPHY_CRC_MST_CNTL__VI = 0x4FBA; +constexpr unsigned int mmDP5_DP_DPHY_CRC_MST_STATUS__VI = 0x4FBB; +constexpr unsigned int mmDP5_DP_DPHY_CRC_RESULT__VI = 0x4FB9; +constexpr unsigned int mmDP5_DP_DPHY_FAST_TRAINING__VI = 0x4FBC; +constexpr unsigned int mmDP5_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x4FBD; +constexpr unsigned int mmDP5_DP_DPHY_PRBS_CNTL__VI = 0x4FB5; +constexpr unsigned int mmDP5_DP_DPHY_SYM0__VI = 0x4FB1; +constexpr unsigned int mmDP5_DP_DPHY_SYM1__VI = 0x4FB2; +constexpr unsigned int mmDP5_DP_DPHY_SYM2__VI = 0x4FB3; +constexpr unsigned int mmDP5_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4FB0; +constexpr unsigned int mmDP5_DP_FE_TEST_DEBUG_DATA__VI = 0x4FDB; +constexpr unsigned int mmDP5_DP_FE_TEST_DEBUG_INDEX__VI = 0x4FDA; +constexpr unsigned int mmDP5_DP_HBR2_EYE_PATTERN__VI = 0x4FAC; +constexpr unsigned int mmDP5_DP_LINK_CNTL__VI = 0x4FA0; +constexpr unsigned int mmDP5_DP_LINK_FRAMING_CNTL__VI = 0x4FAB; +constexpr unsigned int mmDP5_DP_MSA_COLORIMETRY__VI = 0x4FA2; +constexpr unsigned int mmDP5_DP_MSA_MISC__VI = 0x4FA6; +constexpr unsigned int mmDP5_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x4FBE; +constexpr unsigned int mmDP5_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x4FBF; +constexpr unsigned int mmDP5_DP_MSE_LINK_TIMING__VI = 0x4FD6; +constexpr unsigned int mmDP5_DP_MSE_MISC_CNTL__VI = 0x4FD7; +constexpr unsigned int mmDP5_DP_MSE_RATE_CNTL__VI = 0x4FCF; +constexpr unsigned int mmDP5_DP_MSE_RATE_UPDATE__VI = 0x4FD1; +constexpr unsigned int mmDP5_DP_MSE_SAT0__VI = 0x4FD2; +constexpr unsigned int mmDP5_DP_MSE_SAT1__VI = 0x4FD3; +constexpr unsigned int mmDP5_DP_MSE_SAT2__VI = 0x4FD4; +constexpr unsigned int mmDP5_DP_MSE_SAT_UPDATE__VI = 0x4FD5; +constexpr unsigned int mmDP5_DP_PIXEL_FORMAT__VI = 0x4FA1; +constexpr unsigned int mmDP5_DP_SEC_AUD_M__VI = 0x4FCB; +constexpr unsigned int mmDP5_DP_SEC_AUD_M_READBACK__VI = 0x4FCC; +constexpr unsigned int mmDP5_DP_SEC_AUD_N__VI = 0x4FC9; +constexpr unsigned int mmDP5_DP_SEC_AUD_N_READBACK__VI = 0x4FCA; +constexpr unsigned int mmDP5_DP_SEC_CNTL__VI = 0x4FC3; +constexpr unsigned int mmDP5_DP_SEC_CNTL1__VI = 0x4FC4; +constexpr unsigned int mmDP5_DP_SEC_FRAMING1__VI = 0x4FC5; +constexpr unsigned int mmDP5_DP_SEC_FRAMING2__VI = 0x4FC6; +constexpr unsigned int mmDP5_DP_SEC_FRAMING3__VI = 0x4FC7; +constexpr unsigned int mmDP5_DP_SEC_FRAMING4__VI = 0x4FC8; +constexpr unsigned int mmDP5_DP_SEC_PACKET_CNTL__VI = 0x4FCE; +constexpr unsigned int mmDP5_DP_SEC_TIMESTAMP__VI = 0x4FCD; +constexpr unsigned int mmDP5_DP_STEER_FIFO__VI = 0x4FA5; +constexpr unsigned int mmDP5_DP_TEST_DEBUG_DATA__VI = 0x4FD9; +constexpr unsigned int mmDP5_DP_TEST_DEBUG_INDEX__VI = 0x4FD8; +constexpr unsigned int mmDP5_DP_VID_INTERRUPT_CNTL__VI = 0x4FAE; +constexpr unsigned int mmDP5_DP_VID_M__VI = 0x4FAA; +constexpr unsigned int mmDP5_DP_VID_MSA_VBID__VI = 0x4FAD; +constexpr unsigned int mmDP5_DP_VID_N__VI = 0x4FA9; +constexpr unsigned int mmDP5_DP_VID_STREAM_CNTL__VI = 0x4FA4; +constexpr unsigned int mmDP5_DP_VID_TIMING__VI = 0x4FA8; +constexpr unsigned int mmDP6_DP_CONFIG__VI = 0x54A3; +constexpr unsigned int mmDP6_DP_DPHY_8B10B_CNTL__VI = 0x54B4; +constexpr unsigned int mmDP6_DP_DPHY_CNTL__VI = 0x54AF; +constexpr unsigned int mmDP6_DP_DPHY_CRC_CNTL__VI = 0x54B8; +constexpr unsigned int mmDP6_DP_DPHY_CRC_EN__VI = 0x54B7; +constexpr unsigned int mmDP6_DP_DPHY_CRC_MST_CNTL__VI = 0x54BA; +constexpr unsigned int mmDP6_DP_DPHY_CRC_MST_STATUS__VI = 0x54BB; +constexpr unsigned int mmDP6_DP_DPHY_CRC_RESULT__VI = 0x54B9; +constexpr unsigned int mmDP6_DP_DPHY_FAST_TRAINING__VI = 0x54BC; +constexpr unsigned int mmDP6_DP_DPHY_FAST_TRAINING_STATUS__VI = 0x54BD; +constexpr unsigned int mmDP6_DP_DPHY_PRBS_CNTL__VI = 0x54B5; +constexpr unsigned int mmDP6_DP_DPHY_SYM0__VI = 0x54B1; +constexpr unsigned int mmDP6_DP_DPHY_SYM1__VI = 0x54B2; +constexpr unsigned int mmDP6_DP_DPHY_SYM2__VI = 0x54B3; +constexpr unsigned int mmDP6_DP_DPHY_TRAINING_PATTERN_SEL__VI = 0x54B0; +constexpr unsigned int mmDP6_DP_FE_TEST_DEBUG_DATA__VI = 0x54DB; +constexpr unsigned int mmDP6_DP_FE_TEST_DEBUG_INDEX__VI = 0x54DA; +constexpr unsigned int mmDP6_DP_HBR2_EYE_PATTERN__VI = 0x54AC; +constexpr unsigned int mmDP6_DP_LINK_CNTL__VI = 0x54A0; +constexpr unsigned int mmDP6_DP_LINK_FRAMING_CNTL__VI = 0x54AB; +constexpr unsigned int mmDP6_DP_MSA_COLORIMETRY__VI = 0x54A2; +constexpr unsigned int mmDP6_DP_MSA_MISC__VI = 0x54A6; +constexpr unsigned int mmDP6_DP_MSA_V_TIMING_OVERRIDE1__VI = 0x54BE; +constexpr unsigned int mmDP6_DP_MSA_V_TIMING_OVERRIDE2__VI = 0x54BF; +constexpr unsigned int mmDP6_DP_MSE_LINK_TIMING__VI = 0x54D6; +constexpr unsigned int mmDP6_DP_MSE_MISC_CNTL__VI = 0x54D7; +constexpr unsigned int mmDP6_DP_MSE_RATE_CNTL__VI = 0x54CF; +constexpr unsigned int mmDP6_DP_MSE_RATE_UPDATE__VI = 0x54D1; +constexpr unsigned int mmDP6_DP_MSE_SAT0__VI = 0x54D2; +constexpr unsigned int mmDP6_DP_MSE_SAT1__VI = 0x54D3; +constexpr unsigned int mmDP6_DP_MSE_SAT2__VI = 0x54D4; +constexpr unsigned int mmDP6_DP_MSE_SAT_UPDATE__VI = 0x54D5; +constexpr unsigned int mmDP6_DP_PIXEL_FORMAT__VI = 0x54A1; +constexpr unsigned int mmDP6_DP_SEC_AUD_M__VI = 0x54CB; +constexpr unsigned int mmDP6_DP_SEC_AUD_M_READBACK__VI = 0x54CC; +constexpr unsigned int mmDP6_DP_SEC_AUD_N__VI = 0x54C9; +constexpr unsigned int mmDP6_DP_SEC_AUD_N_READBACK__VI = 0x54CA; +constexpr unsigned int mmDP6_DP_SEC_CNTL__VI = 0x54C3; +constexpr unsigned int mmDP6_DP_SEC_CNTL1__VI = 0x54C4; +constexpr unsigned int mmDP6_DP_SEC_FRAMING1__VI = 0x54C5; +constexpr unsigned int mmDP6_DP_SEC_FRAMING2__VI = 0x54C6; +constexpr unsigned int mmDP6_DP_SEC_FRAMING3__VI = 0x54C7; +constexpr unsigned int mmDP6_DP_SEC_FRAMING4__VI = 0x54C8; +constexpr unsigned int mmDP6_DP_SEC_PACKET_CNTL__VI = 0x54CE; +constexpr unsigned int mmDP6_DP_SEC_TIMESTAMP__VI = 0x54CD; +constexpr unsigned int mmDP6_DP_STEER_FIFO__VI = 0x54A5; +constexpr unsigned int mmDP6_DP_TEST_DEBUG_DATA__VI = 0x54D9; +constexpr unsigned int mmDP6_DP_TEST_DEBUG_INDEX__VI = 0x54D8; +constexpr unsigned int mmDP6_DP_VID_INTERRUPT_CNTL__VI = 0x54AE; +constexpr unsigned int mmDP6_DP_VID_M__VI = 0x54AA; +constexpr unsigned int mmDP6_DP_VID_MSA_VBID__VI = 0x54AD; +constexpr unsigned int mmDP6_DP_VID_N__VI = 0x54A9; +constexpr unsigned int mmDP6_DP_VID_STREAM_CNTL__VI = 0x54A4; +constexpr unsigned int mmDP6_DP_VID_TIMING__VI = 0x54A8; +constexpr unsigned int mmDPDBG_CLK_FORCE_CONTROL__VI = 0x010D; +constexpr unsigned int mmDPDBG_CNTL__VI = 0x1866; +constexpr unsigned int mmDPDBG_INTERRUPT__VI = 0x1867; +constexpr unsigned int mmDPG_HW_DEBUG_11__VI = 0x1B3D; +constexpr unsigned int mmDPG_HW_DEBUG_A__VI = 0x1B3B; +constexpr unsigned int mmDPG_HW_DEBUG_B__VI = 0x1B3C; +constexpr unsigned int mmDPG_PIPE_ARBITRATION_CONTROL1__VI = 0x1B30; +constexpr unsigned int mmDPG_PIPE_ARBITRATION_CONTROL2__VI = 0x1B31; +constexpr unsigned int mmDPG_PIPE_DPM_CONTROL__VI = 0x1B34; +constexpr unsigned int mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL__VI = 0x1B36; +constexpr unsigned int mmDPG_PIPE_STUTTER_CONTROL__VI = 0x1B35; +constexpr unsigned int mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH__VI = 0x1B37; +constexpr unsigned int mmDPG_PIPE_URGENCY_CONTROL__VI = 0x1B33; +constexpr unsigned int mmDPG_REPEATER_PROGRAM__VI = 0x1B3A; +constexpr unsigned int mmDPG_TEST_DEBUG_DATA__VI = 0x1B39; +constexpr unsigned int mmDPG_TEST_DEBUG_INDEX__VI = 0x1B38; +constexpr unsigned int mmDPG_WATERMARK_MASK_CONTROL__VI = 0x1B32; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED0__VI = 0x5D98; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED1__VI = 0x5D99; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED10__VI = 0x5DA2; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED11__VI = 0x5DA3; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED12__VI = 0x5DA4; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED13__VI = 0x5DA5; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED14__VI = 0x5DA6; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED15__VI = 0x5DA7; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED16__VI = 0x5DA8; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED17__VI = 0x5DA9; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED18__VI = 0x5DAA; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED19__VI = 0x5DAB; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED2__VI = 0x5D9A; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED20__VI = 0x5DAC; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED21__VI = 0x5DAD; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED22__VI = 0x5DAE; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED23__VI = 0x5DAF; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED24__VI = 0x5DB0; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED25__VI = 0x5DB1; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED26__VI = 0x5DB2; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED27__VI = 0x5DB3; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED28__VI = 0x5DB4; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED29__VI = 0x5DB5; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED3__VI = 0x5D9B; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED30__VI = 0x5DB6; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED31__VI = 0x5DB7; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED32__VI = 0x5DB8; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED33__VI = 0x5DB9; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED34__VI = 0x5DBA; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED35__VI = 0x5DBB; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED36__VI = 0x5DBC; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED37__VI = 0x5DBD; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED38__VI = 0x5DBE; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED39__VI = 0x5DBF; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED4__VI = 0x5D9C; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED40__VI = 0x5DC0; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED41__VI = 0x5DC1; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED42__VI = 0x5DC2; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED43__VI = 0x5DC3; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED44__VI = 0x5DC4; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED45__VI = 0x5DC5; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED46__VI = 0x5DC6; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED47__VI = 0x5DC7; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED48__VI = 0x5DC8; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED49__VI = 0x5DC9; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED5__VI = 0x5D9D; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED50__VI = 0x5DCA; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED51__VI = 0x5DCB; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED52__VI = 0x5DCC; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED53__VI = 0x5DCD; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED54__VI = 0x5DCE; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED55__VI = 0x5DCF; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED56__VI = 0x5DD0; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED57__VI = 0x5DD1; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED58__VI = 0x5DD2; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED59__VI = 0x5DD3; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED6__VI = 0x5D9E; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED60__VI = 0x5DD4; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED61__VI = 0x5DD5; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED62__VI = 0x5DD6; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED63__VI = 0x5DD7; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED7__VI = 0x5D9F; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED8__VI = 0x5DA0; +constexpr unsigned int mmDPHY_MACRO_CNTL_RESERVED9__VI = 0x5DA1; +constexpr unsigned int mmDPREFCLK_CGTT_BLK_CTRL_REG__VI = 0x0108; +constexpr unsigned int mmDPREFCLK_CNTL__VI = 0x0118; +constexpr unsigned int mmDP_AUX0_AUX_ARB_CONTROL__VI = 0x5C02; +constexpr unsigned int mmDP_AUX0_AUX_CONTROL__VI = 0x5C00; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_RX_CONTROL0__VI = 0x5C0A; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_RX_CONTROL1__VI = 0x5C0B; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_RX_STATUS__VI = 0x5C0D; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_TX_CONTROL__VI = 0x5C09; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_TX_REF_CONTROL__VI = 0x5C08; +constexpr unsigned int mmDP_AUX0_AUX_DPHY_TX_STATUS__VI = 0x5C0C; +constexpr unsigned int mmDP_AUX0_AUX_GTC_SYNC_CONTROL__VI = 0x5C0E; +constexpr unsigned int mmDP_AUX0_AUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C10; +constexpr unsigned int mmDP_AUX0_AUX_GTC_SYNC_DATA__VI = 0x5C12; +constexpr unsigned int mmDP_AUX0_AUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C0F; +constexpr unsigned int mmDP_AUX0_AUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C13; +constexpr unsigned int mmDP_AUX0_AUX_GTC_SYNC_STATUS__VI = 0x5C11; +constexpr unsigned int mmDP_AUX0_AUX_INTERRUPT_CONTROL__VI = 0x5C03; +constexpr unsigned int mmDP_AUX0_AUX_LS_DATA__VI = 0x5C07; +constexpr unsigned int mmDP_AUX0_AUX_LS_STATUS__VI = 0x5C05; +constexpr unsigned int mmDP_AUX0_AUX_SW_CONTROL__VI = 0x5C01; +constexpr unsigned int mmDP_AUX0_AUX_SW_DATA__VI = 0x5C06; +constexpr unsigned int mmDP_AUX0_AUX_SW_STATUS__VI = 0x5C04; +constexpr unsigned int mmDP_AUX0_AUX_TEST_DEBUG_DATA__VI = 0x5C15; +constexpr unsigned int mmDP_AUX0_AUX_TEST_DEBUG_INDEX__VI = 0x5C14; +constexpr unsigned int mmDP_AUX1_AUX_ARB_CONTROL__VI = 0x5C1E; +constexpr unsigned int mmDP_AUX1_AUX_CONTROL__VI = 0x5C1C; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_RX_CONTROL0__VI = 0x5C26; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_RX_CONTROL1__VI = 0x5C27; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_RX_STATUS__VI = 0x5C29; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_TX_CONTROL__VI = 0x5C25; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_TX_REF_CONTROL__VI = 0x5C24; +constexpr unsigned int mmDP_AUX1_AUX_DPHY_TX_STATUS__VI = 0x5C28; +constexpr unsigned int mmDP_AUX1_AUX_GTC_SYNC_CONTROL__VI = 0x5C2A; +constexpr unsigned int mmDP_AUX1_AUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C2C; +constexpr unsigned int mmDP_AUX1_AUX_GTC_SYNC_DATA__VI = 0x5C2E; +constexpr unsigned int mmDP_AUX1_AUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C2B; +constexpr unsigned int mmDP_AUX1_AUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C2F; +constexpr unsigned int mmDP_AUX1_AUX_GTC_SYNC_STATUS__VI = 0x5C2D; +constexpr unsigned int mmDP_AUX1_AUX_INTERRUPT_CONTROL__VI = 0x5C1F; +constexpr unsigned int mmDP_AUX1_AUX_LS_DATA__VI = 0x5C23; +constexpr unsigned int mmDP_AUX1_AUX_LS_STATUS__VI = 0x5C21; +constexpr unsigned int mmDP_AUX1_AUX_SW_CONTROL__VI = 0x5C1D; +constexpr unsigned int mmDP_AUX1_AUX_SW_DATA__VI = 0x5C22; +constexpr unsigned int mmDP_AUX1_AUX_SW_STATUS__VI = 0x5C20; +constexpr unsigned int mmDP_AUX1_AUX_TEST_DEBUG_DATA__VI = 0x5C31; +constexpr unsigned int mmDP_AUX1_AUX_TEST_DEBUG_INDEX__VI = 0x5C30; +constexpr unsigned int mmDP_AUX2_AUX_ARB_CONTROL__VI = 0x5C3A; +constexpr unsigned int mmDP_AUX2_AUX_CONTROL__VI = 0x5C38; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_RX_CONTROL0__VI = 0x5C42; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_RX_CONTROL1__VI = 0x5C43; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_RX_STATUS__VI = 0x5C45; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_TX_CONTROL__VI = 0x5C41; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_TX_REF_CONTROL__VI = 0x5C40; +constexpr unsigned int mmDP_AUX2_AUX_DPHY_TX_STATUS__VI = 0x5C44; +constexpr unsigned int mmDP_AUX2_AUX_GTC_SYNC_CONTROL__VI = 0x5C46; +constexpr unsigned int mmDP_AUX2_AUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C48; +constexpr unsigned int mmDP_AUX2_AUX_GTC_SYNC_DATA__VI = 0x5C4A; +constexpr unsigned int mmDP_AUX2_AUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C47; +constexpr unsigned int mmDP_AUX2_AUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C4B; +constexpr unsigned int mmDP_AUX2_AUX_GTC_SYNC_STATUS__VI = 0x5C49; +constexpr unsigned int mmDP_AUX2_AUX_INTERRUPT_CONTROL__VI = 0x5C3B; +constexpr unsigned int mmDP_AUX2_AUX_LS_DATA__VI = 0x5C3F; +constexpr unsigned int mmDP_AUX2_AUX_LS_STATUS__VI = 0x5C3D; +constexpr unsigned int mmDP_AUX2_AUX_SW_CONTROL__VI = 0x5C39; +constexpr unsigned int mmDP_AUX2_AUX_SW_DATA__VI = 0x5C3E; +constexpr unsigned int mmDP_AUX2_AUX_SW_STATUS__VI = 0x5C3C; +constexpr unsigned int mmDP_AUX2_AUX_TEST_DEBUG_DATA__VI = 0x5C4D; +constexpr unsigned int mmDP_AUX2_AUX_TEST_DEBUG_INDEX__VI = 0x5C4C; +constexpr unsigned int mmDP_AUX3_AUX_ARB_CONTROL__VI = 0x5C56; +constexpr unsigned int mmDP_AUX3_AUX_CONTROL__VI = 0x5C54; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_RX_CONTROL0__VI = 0x5C5E; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_RX_CONTROL1__VI = 0x5C5F; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_RX_STATUS__VI = 0x5C61; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_TX_CONTROL__VI = 0x5C5D; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_TX_REF_CONTROL__VI = 0x5C5C; +constexpr unsigned int mmDP_AUX3_AUX_DPHY_TX_STATUS__VI = 0x5C60; +constexpr unsigned int mmDP_AUX3_AUX_GTC_SYNC_CONTROL__VI = 0x5C62; +constexpr unsigned int mmDP_AUX3_AUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C64; +constexpr unsigned int mmDP_AUX3_AUX_GTC_SYNC_DATA__VI = 0x5C66; +constexpr unsigned int mmDP_AUX3_AUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C63; +constexpr unsigned int mmDP_AUX3_AUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C67; +constexpr unsigned int mmDP_AUX3_AUX_GTC_SYNC_STATUS__VI = 0x5C65; +constexpr unsigned int mmDP_AUX3_AUX_INTERRUPT_CONTROL__VI = 0x5C57; +constexpr unsigned int mmDP_AUX3_AUX_LS_DATA__VI = 0x5C5B; +constexpr unsigned int mmDP_AUX3_AUX_LS_STATUS__VI = 0x5C59; +constexpr unsigned int mmDP_AUX3_AUX_SW_CONTROL__VI = 0x5C55; +constexpr unsigned int mmDP_AUX3_AUX_SW_DATA__VI = 0x5C5A; +constexpr unsigned int mmDP_AUX3_AUX_SW_STATUS__VI = 0x5C58; +constexpr unsigned int mmDP_AUX3_AUX_TEST_DEBUG_DATA__VI = 0x5C69; +constexpr unsigned int mmDP_AUX3_AUX_TEST_DEBUG_INDEX__VI = 0x5C68; +constexpr unsigned int mmDP_AUX4_AUX_ARB_CONTROL__VI = 0x5C72; +constexpr unsigned int mmDP_AUX4_AUX_CONTROL__VI = 0x5C70; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_RX_CONTROL0__VI = 0x5C7A; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_RX_CONTROL1__VI = 0x5C7B; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_RX_STATUS__VI = 0x5C7D; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_TX_CONTROL__VI = 0x5C79; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_TX_REF_CONTROL__VI = 0x5C78; +constexpr unsigned int mmDP_AUX4_AUX_DPHY_TX_STATUS__VI = 0x5C7C; +constexpr unsigned int mmDP_AUX4_AUX_GTC_SYNC_CONTROL__VI = 0x5C7E; +constexpr unsigned int mmDP_AUX4_AUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C80; +constexpr unsigned int mmDP_AUX4_AUX_GTC_SYNC_DATA__VI = 0x5C82; +constexpr unsigned int mmDP_AUX4_AUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C7F; +constexpr unsigned int mmDP_AUX4_AUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C83; +constexpr unsigned int mmDP_AUX4_AUX_GTC_SYNC_STATUS__VI = 0x5C81; +constexpr unsigned int mmDP_AUX4_AUX_INTERRUPT_CONTROL__VI = 0x5C73; +constexpr unsigned int mmDP_AUX4_AUX_LS_DATA__VI = 0x5C77; +constexpr unsigned int mmDP_AUX4_AUX_LS_STATUS__VI = 0x5C75; +constexpr unsigned int mmDP_AUX4_AUX_SW_CONTROL__VI = 0x5C71; +constexpr unsigned int mmDP_AUX4_AUX_SW_DATA__VI = 0x5C76; +constexpr unsigned int mmDP_AUX4_AUX_SW_STATUS__VI = 0x5C74; +constexpr unsigned int mmDP_AUX4_AUX_TEST_DEBUG_DATA__VI = 0x5C85; +constexpr unsigned int mmDP_AUX4_AUX_TEST_DEBUG_INDEX__VI = 0x5C84; +constexpr unsigned int mmDP_AUX5_AUX_ARB_CONTROL__VI = 0x5C8E; +constexpr unsigned int mmDP_AUX5_AUX_CONTROL__VI = 0x5C8C; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_RX_CONTROL0__VI = 0x5C96; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_RX_CONTROL1__VI = 0x5C97; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_RX_STATUS__VI = 0x5C99; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_TX_CONTROL__VI = 0x5C95; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_TX_REF_CONTROL__VI = 0x5C94; +constexpr unsigned int mmDP_AUX5_AUX_DPHY_TX_STATUS__VI = 0x5C98; +constexpr unsigned int mmDP_AUX5_AUX_GTC_SYNC_CONTROL__VI = 0x5C9A; +constexpr unsigned int mmDP_AUX5_AUX_GTC_SYNC_CONTROLLER_STATUS__VI = 0x5C9C; +constexpr unsigned int mmDP_AUX5_AUX_GTC_SYNC_DATA__VI = 0x5C9E; +constexpr unsigned int mmDP_AUX5_AUX_GTC_SYNC_ERROR_CONTROL__VI = 0x5C9B; +constexpr unsigned int mmDP_AUX5_AUX_GTC_SYNC_PHASE_OFFSET_OVERRIDE__VI = 0x5C9F; +constexpr unsigned int mmDP_AUX5_AUX_GTC_SYNC_STATUS__VI = 0x5C9D; +constexpr unsigned int mmDP_AUX5_AUX_INTERRUPT_CONTROL__VI = 0x5C8F; +constexpr unsigned int mmDP_AUX5_AUX_LS_DATA__VI = 0x5C93; +constexpr unsigned int mmDP_AUX5_AUX_LS_STATUS__VI = 0x5C91; +constexpr unsigned int mmDP_AUX5_AUX_SW_CONTROL__VI = 0x5C8D; +constexpr unsigned int mmDP_AUX5_AUX_SW_DATA__VI = 0x5C92; +constexpr unsigned int mmDP_AUX5_AUX_SW_STATUS__VI = 0x5C90; +constexpr unsigned int mmDP_AUX5_AUX_TEST_DEBUG_DATA__VI = 0x5CA1; +constexpr unsigned int mmDP_AUX5_AUX_TEST_DEBUG_INDEX__VI = 0x5CA0; +constexpr unsigned int mmDP_CONFIG__VI = 0x4AA3; +constexpr unsigned int mmDP_DPHY_8B10B_CNTL__VI = 0x4AB4; +constexpr unsigned int mmDP_DPHY_CNTL__VI = 0x4AAF; +constexpr unsigned int mmDP_DPHY_CRC_CNTL__VI = 0x4AB8; +constexpr unsigned int mmDP_DPHY_CRC_EN__VI = 0x4AB7; +constexpr unsigned int mmDP_DPHY_CRC_MST_CNTL__VI = 0x4ABA; +constexpr unsigned int mmDP_DPHY_CRC_MST_STATUS__VI = 0x4ABB; +constexpr unsigned int mmDP_DPHY_CRC_RESULT__VI = 0x4AB9; +constexpr unsigned int mmDP_DPHY_FAST_TRAINING__VI = 0x4ABC; +constexpr unsigned int mmDP_DPHY_FAST_TRAINING_STATUS__VI = 0x4ABD; +constexpr unsigned int mmDP_DPHY_PRBS_CNTL__VI = 0x4AB5; +constexpr unsigned int mmDP_DPHY_SYM0__VI = 0x4AB1; +constexpr unsigned int mmDP_DPHY_SYM1__VI = 0x4AB2; +constexpr unsigned int mmDP_DPHY_SYM2__VI = 0x4AB3; +constexpr unsigned int mmDP_DPHY_TRAINING_PATTERN_SEL__VI = 0x4AB0; +constexpr unsigned int mmDP_DTO0_MODULO__VI = 0x0142; +constexpr unsigned int mmDP_DTO0_PHASE__VI = 0x0141; +constexpr unsigned int mmDP_DTO1_MODULO__VI = 0x0146; +constexpr unsigned int mmDP_DTO1_PHASE__VI = 0x0145; +constexpr unsigned int mmDP_DTO2_MODULO__VI = 0x014A; +constexpr unsigned int mmDP_DTO2_PHASE__VI = 0x0149; +constexpr unsigned int mmDP_DTO3_MODULO__VI = 0x014E; +constexpr unsigned int mmDP_DTO3_PHASE__VI = 0x014D; +constexpr unsigned int mmDP_DTO4_MODULO__VI = 0x0152; +constexpr unsigned int mmDP_DTO4_PHASE__VI = 0x0151; +constexpr unsigned int mmDP_DTO5_MODULO__VI = 0x0156; +constexpr unsigned int mmDP_DTO5_PHASE__VI = 0x0155; +constexpr unsigned int mmDP_FE_TEST_DEBUG_DATA__VI = 0x4ADB; +constexpr unsigned int mmDP_FE_TEST_DEBUG_INDEX__VI = 0x4ADA; +constexpr unsigned int mmDP_HBR2_EYE_PATTERN__VI = 0x4AAC; +constexpr unsigned int mmDP_LINK_CNTL__VI = 0x4AA0; +constexpr unsigned int mmDP_LINK_FRAMING_CNTL__VI = 0x4AAB; +constexpr unsigned int mmDP_MSA_COLORIMETRY__VI = 0x4AA2; +constexpr unsigned int mmDP_MSA_MISC__VI = 0x4AA6; +constexpr unsigned int mmDP_MSA_V_TIMING_OVERRIDE1__VI = 0x4ABE; +constexpr unsigned int mmDP_MSA_V_TIMING_OVERRIDE2__VI = 0x4ABF; +constexpr unsigned int mmDP_MSE_LINK_TIMING__VI = 0x4AD6; +constexpr unsigned int mmDP_MSE_MISC_CNTL__VI = 0x4AD7; +constexpr unsigned int mmDP_MSE_RATE_CNTL__VI = 0x4ACF; +constexpr unsigned int mmDP_MSE_RATE_UPDATE__VI = 0x4AD1; +constexpr unsigned int mmDP_MSE_SAT0__VI = 0x4AD2; +constexpr unsigned int mmDP_MSE_SAT1__VI = 0x4AD3; +constexpr unsigned int mmDP_MSE_SAT2__VI = 0x4AD4; +constexpr unsigned int mmDP_MSE_SAT_UPDATE__VI = 0x4AD5; +constexpr unsigned int mmDP_PIXEL_FORMAT__VI = 0x4AA1; +constexpr unsigned int mmDP_SEC_AUD_M__VI = 0x4ACB; +constexpr unsigned int mmDP_SEC_AUD_M_READBACK__VI = 0x4ACC; +constexpr unsigned int mmDP_SEC_AUD_N__VI = 0x4AC9; +constexpr unsigned int mmDP_SEC_AUD_N_READBACK__VI = 0x4ACA; +constexpr unsigned int mmDP_SEC_CNTL__VI = 0x4AC3; +constexpr unsigned int mmDP_SEC_CNTL1__VI = 0x4AC4; +constexpr unsigned int mmDP_SEC_FRAMING1__VI = 0x4AC5; +constexpr unsigned int mmDP_SEC_FRAMING2__VI = 0x4AC6; +constexpr unsigned int mmDP_SEC_FRAMING3__VI = 0x4AC7; +constexpr unsigned int mmDP_SEC_FRAMING4__VI = 0x4AC8; +constexpr unsigned int mmDP_SEC_PACKET_CNTL__VI = 0x4ACE; +constexpr unsigned int mmDP_SEC_TIMESTAMP__VI = 0x4ACD; +constexpr unsigned int mmDP_STEER_FIFO__VI = 0x4AA5; +constexpr unsigned int mmDP_TEST_DEBUG_DATA__VI = 0x4AD9; +constexpr unsigned int mmDP_TEST_DEBUG_INDEX__VI = 0x4AD8; +constexpr unsigned int mmDP_VID_INTERRUPT_CNTL__VI = 0x4AAE; +constexpr unsigned int mmDP_VID_M__VI = 0x4AAA; +constexpr unsigned int mmDP_VID_MSA_VBID__VI = 0x4AAD; +constexpr unsigned int mmDP_VID_N__VI = 0x4AA9; +constexpr unsigned int mmDP_VID_STREAM_CNTL__VI = 0x4AA4; +constexpr unsigned int mmDP_VID_TIMING__VI = 0x4AA8; +constexpr unsigned int mmDVOACLKC_CNTL__VI = 0x016A; +constexpr unsigned int mmDVOACLKC_MVP_CNTL__VI = 0x0169; +constexpr unsigned int mmDVOACLKD_CNTL__VI = 0x0168; +constexpr unsigned int mmDVO_CLK_ENABLE__VI = 0x0129; +constexpr unsigned int mmDVO_CONTROL__VI = 0x16A3; +constexpr unsigned int mmDVO_CRC2_SIG_MASK__VI = 0x16A5; +constexpr unsigned int mmDVO_CRC2_SIG_RESULT__VI = 0x16A6; +constexpr unsigned int mmDVO_CRC_EN__VI = 0x16A4; +constexpr unsigned int mmDVO_ENABLE__VI = 0x16A0; +constexpr unsigned int mmDVO_FIFO_ERROR_STATUS__VI = 0x16A7; +constexpr unsigned int mmDVO_OUTPUT__VI = 0x16A2; +constexpr unsigned int mmDVO_SKEW_ADJUST__VI = 0x489F; +constexpr unsigned int mmDVO_SOURCE_SELECT__VI = 0x16A1; +constexpr unsigned int mmDVO_STRENGTH_CONTROL__VI = 0x489D; +constexpr unsigned int mmDVO_TEST_DEBUG_DATA__VI = 0x16A9; +constexpr unsigned int mmDVO_TEST_DEBUG_INDEX__VI = 0x16A8; +constexpr unsigned int mmDVO_VREF_CONTROL__VI = 0x489E; +constexpr unsigned int mmFBC_CLIENT_REGION_MASK__VI = 0x029B; +constexpr unsigned int mmFBC_CNTL__VI = 0x0280; +constexpr unsigned int mmFBC_COMP_CNTL__VI = 0x0284; +constexpr unsigned int mmFBC_COMP_MODE__VI = 0x0285; +constexpr unsigned int mmFBC_CSM_REGION_OFFSET_01__VI = 0x0299; +constexpr unsigned int mmFBC_CSM_REGION_OFFSET_23__VI = 0x029A; +constexpr unsigned int mmFBC_DEBUG0__VI = 0x0286; +constexpr unsigned int mmFBC_DEBUG1__VI = 0x0287; +constexpr unsigned int mmFBC_DEBUG2__VI = 0x0288; +constexpr unsigned int mmFBC_DEBUG_COMP__VI = 0x029C; +constexpr unsigned int mmFBC_DEBUG_CSR__VI = 0x029D; +constexpr unsigned int mmFBC_DEBUG_CSR_RDATA__VI = 0x029E; +constexpr unsigned int mmFBC_DEBUG_CSR_RDATA_HI__VI = 0x02A0; +constexpr unsigned int mmFBC_DEBUG_CSR_WDATA__VI = 0x029F; +constexpr unsigned int mmFBC_DEBUG_CSR_WDATA_HI__VI = 0x02A1; +constexpr unsigned int mmFBC_IDLE_FORCE_CLEAR_MASK__VI = 0x0282; +constexpr unsigned int mmFBC_IDLE_MASK__VI = 0x0281; +constexpr unsigned int mmFBC_IND_LUT0__VI = 0x0289; +constexpr unsigned int mmFBC_IND_LUT1__VI = 0x028A; +constexpr unsigned int mmFBC_IND_LUT10__VI = 0x0293; +constexpr unsigned int mmFBC_IND_LUT11__VI = 0x0294; +constexpr unsigned int mmFBC_IND_LUT12__VI = 0x0295; +constexpr unsigned int mmFBC_IND_LUT13__VI = 0x0296; +constexpr unsigned int mmFBC_IND_LUT14__VI = 0x0297; +constexpr unsigned int mmFBC_IND_LUT15__VI = 0x0298; +constexpr unsigned int mmFBC_IND_LUT2__VI = 0x028B; +constexpr unsigned int mmFBC_IND_LUT3__VI = 0x028C; +constexpr unsigned int mmFBC_IND_LUT4__VI = 0x028D; +constexpr unsigned int mmFBC_IND_LUT5__VI = 0x028E; +constexpr unsigned int mmFBC_IND_LUT6__VI = 0x028F; +constexpr unsigned int mmFBC_IND_LUT7__VI = 0x0290; +constexpr unsigned int mmFBC_IND_LUT8__VI = 0x0291; +constexpr unsigned int mmFBC_IND_LUT9__VI = 0x0292; +constexpr unsigned int mmFBC_MISC__VI = 0x02A2; +constexpr unsigned int mmFBC_START_STOP_DELAY__VI = 0x0283; +constexpr unsigned int mmFBC_STATUS__VI = 0x02A3; +constexpr unsigned int mmFBC_TEST_DEBUG_DATA__VI = 0x02A5; +constexpr unsigned int mmFBC_TEST_DEBUG_INDEX__VI = 0x02A4; +constexpr unsigned int mmFMT0_FMT_CLAMP_COMPONENT_B__VI = 0x1BEA; +constexpr unsigned int mmFMT0_FMT_CLAMP_COMPONENT_G__VI = 0x1BE9; +constexpr unsigned int mmFMT0_FMT_CLAMP_COMPONENT_R__VI = 0x1BE8; +constexpr unsigned int mmFMT0_FMT_TEST_DEBUG_DATA__VI = 0x1BEC; +constexpr unsigned int mmFMT0_FMT_TEST_DEBUG_INDEX__VI = 0x1BEB; +constexpr unsigned int mmFMT1_FMT_BIT_DEPTH_CONTROL__VI = 0x1DF2; +constexpr unsigned int mmFMT1_FMT_CLAMP_CNTL__VI = 0x1DF9; +constexpr unsigned int mmFMT1_FMT_CLAMP_COMPONENT_B__VI = 0x1DEA; +constexpr unsigned int mmFMT1_FMT_CLAMP_COMPONENT_G__VI = 0x1DE9; +constexpr unsigned int mmFMT1_FMT_CLAMP_COMPONENT_R__VI = 0x1DE8; +constexpr unsigned int mmFMT1_FMT_CONTROL__VI = 0x1DEE; +constexpr unsigned int mmFMT1_FMT_CRC_CNTL__VI = 0x1DFA; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_BLUE_CONTROL__VI = 0x1DFE; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_BLUE_CONTROL_MASK__VI = 0x1DFC; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_RED_GREEN__VI = 0x1DFD; +constexpr unsigned int mmFMT1_FMT_CRC_SIG_RED_GREEN_MASK__VI = 0x1DFB; +constexpr unsigned int mmFMT1_FMT_DEBUG_CNTL__VI = 0x1DFF; +constexpr unsigned int mmFMT1_FMT_DITHER_RAND_B_SEED__VI = 0x1DF5; +constexpr unsigned int mmFMT1_FMT_DITHER_RAND_G_SEED__VI = 0x1DF4; +constexpr unsigned int mmFMT1_FMT_DITHER_RAND_R_SEED__VI = 0x1DF3; +constexpr unsigned int mmFMT1_FMT_DYNAMIC_EXP_CNTL__VI = 0x1DED; +constexpr unsigned int mmFMT1_FMT_FORCE_DATA_0_1__VI = 0x1DF0; +constexpr unsigned int mmFMT1_FMT_FORCE_DATA_2_3__VI = 0x1DF1; +constexpr unsigned int mmFMT1_FMT_FORCE_OUTPUT_CNTL__VI = 0x1DEF; +constexpr unsigned int mmFMT1_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__VI = 0x1DF6; +constexpr unsigned int mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__VI = 0x1DF7; +constexpr unsigned int mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__VI = 0x1DF8; +constexpr unsigned int mmFMT1_FMT_TEST_DEBUG_DATA__VI = 0x1DEC; +constexpr unsigned int mmFMT1_FMT_TEST_DEBUG_INDEX__VI = 0x1DEB; +constexpr unsigned int mmFMT2_FMT_BIT_DEPTH_CONTROL__VI = 0x1FF2; +constexpr unsigned int mmFMT2_FMT_CLAMP_CNTL__VI = 0x1FF9; +constexpr unsigned int mmFMT2_FMT_CLAMP_COMPONENT_B__VI = 0x1FEA; +constexpr unsigned int mmFMT2_FMT_CLAMP_COMPONENT_G__VI = 0x1FE9; +constexpr unsigned int mmFMT2_FMT_CLAMP_COMPONENT_R__VI = 0x1FE8; +constexpr unsigned int mmFMT2_FMT_CONTROL__VI = 0x1FEE; +constexpr unsigned int mmFMT2_FMT_CRC_CNTL__VI = 0x1FFA; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_BLUE_CONTROL__VI = 0x1FFE; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_BLUE_CONTROL_MASK__VI = 0x1FFC; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_RED_GREEN__VI = 0x1FFD; +constexpr unsigned int mmFMT2_FMT_CRC_SIG_RED_GREEN_MASK__VI = 0x1FFB; +constexpr unsigned int mmFMT2_FMT_DEBUG_CNTL__VI = 0x1FFF; +constexpr unsigned int mmFMT2_FMT_DITHER_RAND_B_SEED__VI = 0x1FF5; +constexpr unsigned int mmFMT2_FMT_DITHER_RAND_G_SEED__VI = 0x1FF4; +constexpr unsigned int mmFMT2_FMT_DITHER_RAND_R_SEED__VI = 0x1FF3; +constexpr unsigned int mmFMT2_FMT_DYNAMIC_EXP_CNTL__VI = 0x1FED; +constexpr unsigned int mmFMT2_FMT_FORCE_DATA_0_1__VI = 0x1FF0; +constexpr unsigned int mmFMT2_FMT_FORCE_DATA_2_3__VI = 0x1FF1; +constexpr unsigned int mmFMT2_FMT_FORCE_OUTPUT_CNTL__VI = 0x1FEF; +constexpr unsigned int mmFMT2_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__VI = 0x1FF6; +constexpr unsigned int mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__VI = 0x1FF7; +constexpr unsigned int mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__VI = 0x1FF8; +constexpr unsigned int mmFMT2_FMT_TEST_DEBUG_DATA__VI = 0x1FEC; +constexpr unsigned int mmFMT2_FMT_TEST_DEBUG_INDEX__VI = 0x1FEB; +constexpr unsigned int mmFMT3_FMT_BIT_DEPTH_CONTROL__VI = 0x41F2; +constexpr unsigned int mmFMT3_FMT_CLAMP_CNTL__VI = 0x41F9; +constexpr unsigned int mmFMT3_FMT_CLAMP_COMPONENT_B__VI = 0x41EA; +constexpr unsigned int mmFMT3_FMT_CLAMP_COMPONENT_G__VI = 0x41E9; +constexpr unsigned int mmFMT3_FMT_CLAMP_COMPONENT_R__VI = 0x41E8; +constexpr unsigned int mmFMT3_FMT_CONTROL__VI = 0x41EE; +constexpr unsigned int mmFMT3_FMT_CRC_CNTL__VI = 0x41FA; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_BLUE_CONTROL__VI = 0x41FE; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_BLUE_CONTROL_MASK__VI = 0x41FC; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_RED_GREEN__VI = 0x41FD; +constexpr unsigned int mmFMT3_FMT_CRC_SIG_RED_GREEN_MASK__VI = 0x41FB; +constexpr unsigned int mmFMT3_FMT_DEBUG_CNTL__VI = 0x41FF; +constexpr unsigned int mmFMT3_FMT_DITHER_RAND_B_SEED__VI = 0x41F5; +constexpr unsigned int mmFMT3_FMT_DITHER_RAND_G_SEED__VI = 0x41F4; +constexpr unsigned int mmFMT3_FMT_DITHER_RAND_R_SEED__VI = 0x41F3; +constexpr unsigned int mmFMT3_FMT_DYNAMIC_EXP_CNTL__VI = 0x41ED; +constexpr unsigned int mmFMT3_FMT_FORCE_DATA_0_1__VI = 0x41F0; +constexpr unsigned int mmFMT3_FMT_FORCE_DATA_2_3__VI = 0x41F1; +constexpr unsigned int mmFMT3_FMT_FORCE_OUTPUT_CNTL__VI = 0x41EF; +constexpr unsigned int mmFMT3_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__VI = 0x41F6; +constexpr unsigned int mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__VI = 0x41F7; +constexpr unsigned int mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__VI = 0x41F8; +constexpr unsigned int mmFMT3_FMT_TEST_DEBUG_DATA__VI = 0x41EC; +constexpr unsigned int mmFMT3_FMT_TEST_DEBUG_INDEX__VI = 0x41EB; +constexpr unsigned int mmFMT4_FMT_BIT_DEPTH_CONTROL__VI = 0x43F2; +constexpr unsigned int mmFMT4_FMT_CLAMP_CNTL__VI = 0x43F9; +constexpr unsigned int mmFMT4_FMT_CLAMP_COMPONENT_B__VI = 0x43EA; +constexpr unsigned int mmFMT4_FMT_CLAMP_COMPONENT_G__VI = 0x43E9; +constexpr unsigned int mmFMT4_FMT_CLAMP_COMPONENT_R__VI = 0x43E8; +constexpr unsigned int mmFMT4_FMT_CONTROL__VI = 0x43EE; +constexpr unsigned int mmFMT4_FMT_CRC_CNTL__VI = 0x43FA; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_BLUE_CONTROL__VI = 0x43FE; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_BLUE_CONTROL_MASK__VI = 0x43FC; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_RED_GREEN__VI = 0x43FD; +constexpr unsigned int mmFMT4_FMT_CRC_SIG_RED_GREEN_MASK__VI = 0x43FB; +constexpr unsigned int mmFMT4_FMT_DEBUG_CNTL__VI = 0x43FF; +constexpr unsigned int mmFMT4_FMT_DITHER_RAND_B_SEED__VI = 0x43F5; +constexpr unsigned int mmFMT4_FMT_DITHER_RAND_G_SEED__VI = 0x43F4; +constexpr unsigned int mmFMT4_FMT_DITHER_RAND_R_SEED__VI = 0x43F3; +constexpr unsigned int mmFMT4_FMT_DYNAMIC_EXP_CNTL__VI = 0x43ED; +constexpr unsigned int mmFMT4_FMT_FORCE_DATA_0_1__VI = 0x43F0; +constexpr unsigned int mmFMT4_FMT_FORCE_DATA_2_3__VI = 0x43F1; +constexpr unsigned int mmFMT4_FMT_FORCE_OUTPUT_CNTL__VI = 0x43EF; +constexpr unsigned int mmFMT4_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__VI = 0x43F6; +constexpr unsigned int mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__VI = 0x43F7; +constexpr unsigned int mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__VI = 0x43F8; +constexpr unsigned int mmFMT4_FMT_TEST_DEBUG_DATA__VI = 0x43EC; +constexpr unsigned int mmFMT4_FMT_TEST_DEBUG_INDEX__VI = 0x43EB; +constexpr unsigned int mmFMT5_FMT_BIT_DEPTH_CONTROL__VI = 0x45F2; +constexpr unsigned int mmFMT5_FMT_CLAMP_CNTL__VI = 0x45F9; +constexpr unsigned int mmFMT5_FMT_CLAMP_COMPONENT_B__VI = 0x45EA; +constexpr unsigned int mmFMT5_FMT_CLAMP_COMPONENT_G__VI = 0x45E9; +constexpr unsigned int mmFMT5_FMT_CLAMP_COMPONENT_R__VI = 0x45E8; +constexpr unsigned int mmFMT5_FMT_CONTROL__VI = 0x45EE; +constexpr unsigned int mmFMT5_FMT_CRC_CNTL__VI = 0x45FA; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_BLUE_CONTROL__VI = 0x45FE; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_BLUE_CONTROL_MASK__VI = 0x45FC; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_RED_GREEN__VI = 0x45FD; +constexpr unsigned int mmFMT5_FMT_CRC_SIG_RED_GREEN_MASK__VI = 0x45FB; +constexpr unsigned int mmFMT5_FMT_DEBUG_CNTL__VI = 0x45FF; +constexpr unsigned int mmFMT5_FMT_DITHER_RAND_B_SEED__VI = 0x45F5; +constexpr unsigned int mmFMT5_FMT_DITHER_RAND_G_SEED__VI = 0x45F4; +constexpr unsigned int mmFMT5_FMT_DITHER_RAND_R_SEED__VI = 0x45F3; +constexpr unsigned int mmFMT5_FMT_DYNAMIC_EXP_CNTL__VI = 0x45ED; +constexpr unsigned int mmFMT5_FMT_FORCE_DATA_0_1__VI = 0x45F0; +constexpr unsigned int mmFMT5_FMT_FORCE_DATA_2_3__VI = 0x45F1; +constexpr unsigned int mmFMT5_FMT_FORCE_OUTPUT_CNTL__VI = 0x45EF; +constexpr unsigned int mmFMT5_FMT_TEMPORAL_DITHER_PATTERN_CONTROL__VI = 0x45F6; +constexpr unsigned int mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__VI = 0x45F7; +constexpr unsigned int mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__VI = 0x45F8; +constexpr unsigned int mmFMT5_FMT_TEST_DEBUG_DATA__VI = 0x45EC; +constexpr unsigned int mmFMT5_FMT_TEST_DEBUG_INDEX__VI = 0x45EB; +constexpr unsigned int mmFMT_CLAMP_COMPONENT_B__VI = 0x1BEA; +constexpr unsigned int mmFMT_CLAMP_COMPONENT_G__VI = 0x1BE9; +constexpr unsigned int mmFMT_CLAMP_COMPONENT_R__VI = 0x1BE8; +constexpr unsigned int mmFMT_TEST_DEBUG_DATA__VI = 0x1BEC; +constexpr unsigned int mmFMT_TEST_DEBUG_INDEX__VI = 0x1BEB; +constexpr unsigned int mmGAMMA_CORR_CNTLA_END_CNTL1__VI = 0x46CE; +constexpr unsigned int mmGAMMA_CORR_CNTLA_END_CNTL2__VI = 0x46CF; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_0_1__VI = 0x46D0; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_10_11__VI = 0x46D5; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_12_13__VI = 0x46D6; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_14_15__VI = 0x46D7; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_2_3__VI = 0x46D1; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_4_5__VI = 0x46D2; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_6_7__VI = 0x46D3; +constexpr unsigned int mmGAMMA_CORR_CNTLA_REGION_8_9__VI = 0x46D4; +constexpr unsigned int mmGAMMA_CORR_CNTLA_SLOPE_CNTL__VI = 0x46CD; +constexpr unsigned int mmGAMMA_CORR_CNTLA_START_CNTL__VI = 0x46CC; +constexpr unsigned int mmGAMMA_CORR_CNTLB_END_CNTL1__VI = 0x46DA; +constexpr unsigned int mmGAMMA_CORR_CNTLB_END_CNTL2__VI = 0x46DB; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_0_1__VI = 0x46DC; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_10_11__VI = 0x46E1; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_12_13__VI = 0x46E2; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_14_15__VI = 0x46E3; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_2_3__VI = 0x46DD; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_4_5__VI = 0x46DE; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_6_7__VI = 0x46DF; +constexpr unsigned int mmGAMMA_CORR_CNTLB_REGION_8_9__VI = 0x46E0; +constexpr unsigned int mmGAMMA_CORR_CNTLB_SLOPE_CNTL__VI = 0x46D9; +constexpr unsigned int mmGAMMA_CORR_CNTLB_START_CNTL__VI = 0x46D8; +constexpr unsigned int mmGAMMA_CORR_CONTROL__VI = 0x46C8; +constexpr unsigned int mmGAMMA_CORR_LUT_DATA__VI = 0x46CA; +constexpr unsigned int mmGAMMA_CORR_LUT_INDEX__VI = 0x46C9; +constexpr unsigned int mmGAMMA_CORR_LUT_WRITE_EN_MASK__VI = 0x46CB; +constexpr unsigned int mmGAMUT_REMAP_C11_C12__VI = 0x1A5A; +constexpr unsigned int mmGAMUT_REMAP_C13_C14__VI = 0x1A5B; +constexpr unsigned int mmGAMUT_REMAP_C21_C22__VI = 0x1A5C; +constexpr unsigned int mmGAMUT_REMAP_C23_C24__VI = 0x1A5D; +constexpr unsigned int mmGAMUT_REMAP_C31_C32__VI = 0x1A5E; +constexpr unsigned int mmGAMUT_REMAP_C33_C34__VI = 0x1A5F; +constexpr unsigned int mmGAMUT_REMAP_CONTROL__VI = 0x1A59; +constexpr unsigned int mmGARLIC_COHE_CP_DMA_ME_COMMAND__VI = 0x141B; +constexpr unsigned int mmGARLIC_COHE_CP_DMA_PFP_COMMAND__VI = 0x141C; +constexpr unsigned int mmGARLIC_COHE_CP_DMA_PIO_COMMAND__VI = 0x1424; +constexpr unsigned int mmGARLIC_COHE_CP_RB0_WPTR__VI = 0x1415; +constexpr unsigned int mmGARLIC_COHE_CP_RB1_WPTR__VI = 0x1416; +constexpr unsigned int mmGARLIC_COHE_CP_RB2_WPTR__VI = 0x1417; +constexpr unsigned int mmGARLIC_COHE_GARLIC_FLUSH_REQ__VI = 0x1425; +constexpr unsigned int mmGARLIC_COHE_SAM_SAB_RBI_WPTR__VI = 0x141D; +constexpr unsigned int mmGARLIC_COHE_SAM_SAB_RBO_WPTR__VI = 0x141E; +constexpr unsigned int mmGARLIC_COHE_SDMA0_GFX_RB_WPTR__VI = 0x1419; +constexpr unsigned int mmGARLIC_COHE_SDMA1_GFX_RB_WPTR__VI = 0x141A; +constexpr unsigned int mmGARLIC_COHE_SDMA2_GFX_RB_WPTR__VI = 0x1422; +constexpr unsigned int mmGARLIC_COHE_SDMA3_GFX_RB_WPTR__VI = 0x1423; +constexpr unsigned int mmGARLIC_COHE_UVD_RBC_RB_WPTR__VI = 0x1418; +constexpr unsigned int mmGARLIC_COHE_VCE_OUT_RB_WPTR__VI = 0x141F; +constexpr unsigned int mmGARLIC_COHE_VCE_RB_WPTR__VI = 0x1421; +constexpr unsigned int mmGARLIC_COHE_VCE_RB_WPTR2__VI = 0x1420; +constexpr unsigned int mmGC_CAC_CGTT_CLK_CTRL__VI = 0x3292; +constexpr unsigned int mmGC_CAC_LKG_AGGR_LOWER__VI = 0x3296; +constexpr unsigned int mmGC_CAC_LKG_AGGR_UPPER__VI = 0x3297; +constexpr unsigned int mmGC_USER_SHADER_RATE_CONFIG__VI = 0x2313; +constexpr unsigned int mmGDS_CS_CTXSW_CNT0__VI = 0x334E; +constexpr unsigned int mmGDS_CS_CTXSW_CNT1__VI = 0x334F; +constexpr unsigned int mmGDS_CS_CTXSW_CNT2__VI = 0x3350; +constexpr unsigned int mmGDS_CS_CTXSW_CNT3__VI = 0x3351; +constexpr unsigned int mmGDS_CS_CTXSW_STATUS__VI = 0x334D; +constexpr unsigned int mmGDS_DSM_CNTL__VI = 0x25CA; +constexpr unsigned int mmGDS_EDC_CNT__VI = 0x25C5; +constexpr unsigned int mmGDS_EDC_GRBM_CNT__VI = 0x25C6; +constexpr unsigned int mmGDS_EDC_OA_DED__VI = 0x25C7; +constexpr unsigned int mmGDS_GFX_CTXSW_STATUS__VI = 0x3352; +constexpr unsigned int mmGDS_PS0_CTXSW_CNT0__VI = 0x3357; +constexpr unsigned int mmGDS_PS0_CTXSW_CNT1__VI = 0x3358; +constexpr unsigned int mmGDS_PS0_CTXSW_CNT2__VI = 0x3359; +constexpr unsigned int mmGDS_PS0_CTXSW_CNT3__VI = 0x335A; +constexpr unsigned int mmGDS_PS1_CTXSW_CNT0__VI = 0x335B; +constexpr unsigned int mmGDS_PS1_CTXSW_CNT1__VI = 0x335C; +constexpr unsigned int mmGDS_PS1_CTXSW_CNT2__VI = 0x335D; +constexpr unsigned int mmGDS_PS1_CTXSW_CNT3__VI = 0x335E; +constexpr unsigned int mmGDS_PS2_CTXSW_CNT0__VI = 0x335F; +constexpr unsigned int mmGDS_PS2_CTXSW_CNT1__VI = 0x3360; +constexpr unsigned int mmGDS_PS2_CTXSW_CNT2__VI = 0x3361; +constexpr unsigned int mmGDS_PS2_CTXSW_CNT3__VI = 0x3362; +constexpr unsigned int mmGDS_PS3_CTXSW_CNT0__VI = 0x3363; +constexpr unsigned int mmGDS_PS3_CTXSW_CNT1__VI = 0x3364; +constexpr unsigned int mmGDS_PS3_CTXSW_CNT2__VI = 0x3365; +constexpr unsigned int mmGDS_PS3_CTXSW_CNT3__VI = 0x3366; +constexpr unsigned int mmGDS_PS4_CTXSW_CNT0__VI = 0x3367; +constexpr unsigned int mmGDS_PS4_CTXSW_CNT1__VI = 0x3368; +constexpr unsigned int mmGDS_PS4_CTXSW_CNT2__VI = 0x3369; +constexpr unsigned int mmGDS_PS4_CTXSW_CNT3__VI = 0x336A; +constexpr unsigned int mmGDS_PS5_CTXSW_CNT0__VI = 0x336B; +constexpr unsigned int mmGDS_PS5_CTXSW_CNT1__VI = 0x336C; +constexpr unsigned int mmGDS_PS5_CTXSW_CNT2__VI = 0x336D; +constexpr unsigned int mmGDS_PS5_CTXSW_CNT3__VI = 0x336E; +constexpr unsigned int mmGDS_PS6_CTXSW_CNT0__VI = 0x336F; +constexpr unsigned int mmGDS_PS6_CTXSW_CNT1__VI = 0x3370; +constexpr unsigned int mmGDS_PS6_CTXSW_CNT2__VI = 0x3371; +constexpr unsigned int mmGDS_PS6_CTXSW_CNT3__VI = 0x3372; +constexpr unsigned int mmGDS_PS7_CTXSW_CNT0__VI = 0x3373; +constexpr unsigned int mmGDS_PS7_CTXSW_CNT1__VI = 0x3374; +constexpr unsigned int mmGDS_PS7_CTXSW_CNT2__VI = 0x3375; +constexpr unsigned int mmGDS_PS7_CTXSW_CNT3__VI = 0x3376; +constexpr unsigned int mmGDS_VS_CTXSW_CNT0__VI = 0x3353; +constexpr unsigned int mmGDS_VS_CTXSW_CNT1__VI = 0x3354; +constexpr unsigned int mmGDS_VS_CTXSW_CNT2__VI = 0x3355; +constexpr unsigned int mmGDS_VS_CTXSW_CNT3__VI = 0x3356; +constexpr unsigned int mmGENERIC_I2C_CONTROL__VI = 0x16F4; +constexpr unsigned int mmGENERIC_I2C_DATA__VI = 0x16FA; +constexpr unsigned int mmGENERIC_I2C_INTERRUPT_CONTROL__VI = 0x16F5; +constexpr unsigned int mmGENERIC_I2C_PIN_DEBUG__VI = 0x16FC; +constexpr unsigned int mmGENERIC_I2C_PIN_SELECTION__VI = 0x16FB; +constexpr unsigned int mmGENERIC_I2C_SETUP__VI = 0x16F8; +constexpr unsigned int mmGENERIC_I2C_SPEED__VI = 0x16F7; +constexpr unsigned int mmGENERIC_I2C_STATUS__VI = 0x16F6; +constexpr unsigned int mmGENERIC_I2C_TRANSACTION__VI = 0x16F9; +constexpr unsigned int mmGMCON_LPT_TARGET__VI = 0x0D53; +constexpr unsigned int mmGPU_BIST_CONTROL__VI = 0xF835; +constexpr unsigned int mmGRBM_CAM_DATA__SI__CI = 0x3001; +constexpr unsigned int mmGRBM_CAM_DATA__VI = 0xF83F; +constexpr unsigned int mmGRBM_CAM_INDEX__SI__CI = 0x3000; +constexpr unsigned int mmGRBM_CAM_INDEX__VI = 0xF83E; +constexpr unsigned int mmGRBM_DSM_BYPASS__VI = 0x201E; +constexpr unsigned int mmGRBM_HYP_CAM_DATA__VI = 0xF83F; +constexpr unsigned int mmGRBM_HYP_CAM_INDEX__VI = 0xF83E; +constexpr unsigned int mmGRBM_TRAP_ADDR__VI = 0x201A; +constexpr unsigned int mmGRBM_TRAP_ADDR_MSK__VI = 0x201B; +constexpr unsigned int mmGRBM_TRAP_OP__VI = 0x2019; +constexpr unsigned int mmGRBM_TRAP_WD__VI = 0x201C; +constexpr unsigned int mmGRBM_TRAP_WD_MSK__VI = 0x201D; +constexpr unsigned int mmGRBM_WRITE_ERROR__VI = 0x201F; +constexpr unsigned int mmGRPH_FLIP_RATE_CNTL__VI = 0x1A8E; +constexpr unsigned int mmGRPH_STEREOSYNC_FLIP__VI = 0x1A97; +constexpr unsigned int mmGRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__VI = 0x1A9F; +constexpr unsigned int mmGRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__VI = 0x1ABF; +constexpr unsigned int mmGRPH_XDMA_RECOVERY_SURFACE_ADDRESS__VI = 0x1ABD; +constexpr unsigned int mmGRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__VI = 0x1ABE; +constexpr unsigned int mmGSKT_CONTROL__VI = 0x14BF; +constexpr unsigned int mmHDMI_ACR_32_0__VI = 0x4A2E; +constexpr unsigned int mmHDMI_ACR_32_1__VI = 0x4A2F; +constexpr unsigned int mmHDMI_ACR_44_0__VI = 0x4A30; +constexpr unsigned int mmHDMI_ACR_44_1__VI = 0x4A31; +constexpr unsigned int mmHDMI_ACR_48_0__VI = 0x4A32; +constexpr unsigned int mmHDMI_ACR_48_1__VI = 0x4A33; +constexpr unsigned int mmHDMI_ACR_PACKET_CONTROL__VI = 0x4A0C; +constexpr unsigned int mmHDMI_ACR_STATUS_0__VI = 0x4A34; +constexpr unsigned int mmHDMI_ACR_STATUS_1__VI = 0x4A35; +constexpr unsigned int mmHDMI_AUDIO_PACKET_CONTROL__VI = 0x4A0B; +constexpr unsigned int mmHDMI_CONTROL__VI = 0x4A09; +constexpr unsigned int mmHDMI_GC__VI = 0x4A13; +constexpr unsigned int mmHDMI_GENERIC_PACKET_CONTROL0__VI = 0x4A10; +constexpr unsigned int mmHDMI_GENERIC_PACKET_CONTROL1__VI = 0x4A2D; +constexpr unsigned int mmHDMI_INFOFRAME_CONTROL0__VI = 0x4A0E; +constexpr unsigned int mmHDMI_INFOFRAME_CONTROL1__VI = 0x4A0F; +constexpr unsigned int mmHDMI_STATUS__VI = 0x4A0A; +constexpr unsigned int mmHDMI_VBI_PACKET_CONTROL__VI = 0x4A0D; +constexpr unsigned int mmHDP_ADDR_CONFIG__VI = 0x0BD2; +constexpr unsigned int mmHDP_MEMIO_ADDR__VI = 0x0BF7; +constexpr unsigned int mmHDP_MEMIO_CNTL__VI = 0x0BF6; +constexpr unsigned int mmHDP_MEMIO_RD_DATA__VI = 0x0BFA; +constexpr unsigned int mmHDP_MEMIO_STATUS__VI = 0x0BF8; +constexpr unsigned int mmHDP_MEMIO_WR_DATA__VI = 0x0BF9; +constexpr unsigned int mmHDP_MEM_POWER_LS__VI = 0x0BD4; +constexpr unsigned int mmHDP_MISC_CNTL__VI = 0x0BD3; +constexpr unsigned int mmHDP_NONSURFACE_PREFETCH__VI = 0x0BD5; +constexpr unsigned int mmHDP_VF_ENABLE__VI = 0x0BFB; +constexpr unsigned int mmHDP_XDP_BARS_ADDR_39_36__VI = 0x0C44; +constexpr unsigned int mmHPD0_DC_HPD_CONTROL__VI = 0x189A; +constexpr unsigned int mmHPD0_DC_HPD_FAST_TRAIN_CNTL__VI = 0x189B; +constexpr unsigned int mmHPD0_DC_HPD_INT_CONTROL__VI = 0x1899; +constexpr unsigned int mmHPD0_DC_HPD_INT_STATUS__VI = 0x1898; +constexpr unsigned int mmHPD0_DC_HPD_TOGGLE_FILT_CNTL__VI = 0x189C; +constexpr unsigned int mmHPD1_DC_HPD_CONTROL__VI = 0x18A2; +constexpr unsigned int mmHPD1_DC_HPD_FAST_TRAIN_CNTL__VI = 0x18A3; +constexpr unsigned int mmHPD1_DC_HPD_INT_CONTROL__VI = 0x18A1; +constexpr unsigned int mmHPD1_DC_HPD_INT_STATUS__VI = 0x18A0; +constexpr unsigned int mmHPD1_DC_HPD_TOGGLE_FILT_CNTL__VI = 0x18A4; +constexpr unsigned int mmHPD2_DC_HPD_CONTROL__VI = 0x18AA; +constexpr unsigned int mmHPD2_DC_HPD_FAST_TRAIN_CNTL__VI = 0x18AB; +constexpr unsigned int mmHPD2_DC_HPD_INT_CONTROL__VI = 0x18A9; +constexpr unsigned int mmHPD2_DC_HPD_INT_STATUS__VI = 0x18A8; +constexpr unsigned int mmHPD2_DC_HPD_TOGGLE_FILT_CNTL__VI = 0x18AC; +constexpr unsigned int mmHPD3_DC_HPD_CONTROL__VI = 0x18B2; +constexpr unsigned int mmHPD3_DC_HPD_FAST_TRAIN_CNTL__VI = 0x18B3; +constexpr unsigned int mmHPD3_DC_HPD_INT_CONTROL__VI = 0x18B1; +constexpr unsigned int mmHPD3_DC_HPD_INT_STATUS__VI = 0x18B0; +constexpr unsigned int mmHPD3_DC_HPD_TOGGLE_FILT_CNTL__VI = 0x18B4; +constexpr unsigned int mmHPD4_DC_HPD_CONTROL__VI = 0x18BA; +constexpr unsigned int mmHPD4_DC_HPD_FAST_TRAIN_CNTL__VI = 0x18BB; +constexpr unsigned int mmHPD4_DC_HPD_INT_CONTROL__VI = 0x18B9; +constexpr unsigned int mmHPD4_DC_HPD_INT_STATUS__VI = 0x18B8; +constexpr unsigned int mmHPD4_DC_HPD_TOGGLE_FILT_CNTL__VI = 0x18BC; +constexpr unsigned int mmHPD5_DC_HPD_CONTROL__VI = 0x18C2; +constexpr unsigned int mmHPD5_DC_HPD_FAST_TRAIN_CNTL__VI = 0x18C3; +constexpr unsigned int mmHPD5_DC_HPD_INT_CONTROL__VI = 0x18C1; +constexpr unsigned int mmHPD5_DC_HPD_INT_STATUS__VI = 0x18C0; +constexpr unsigned int mmHPD5_DC_HPD_TOGGLE_FILT_CNTL__VI = 0x18C4; +constexpr unsigned int mmHW_ROTATION__VI = 0x1A9E; +constexpr unsigned int mmIH_ACTIVE_FCN_ID__VI = 0x0E43; +constexpr unsigned int mmIH_CLIENT_MAY_SEND_INCOMPLETE_INT__VI = 0x0E4B; +constexpr unsigned int mmIH_CNTL__SI__CI = 0x0F86; +constexpr unsigned int mmIH_CNTL__VI = 0x0E36; +constexpr unsigned int mmIH_DEBUG__VI = 0x0E3C; +constexpr unsigned int mmIH_DOORBELL_RPTR__VI = 0x0E42; +constexpr unsigned int mmIH_DSM_MATCH_DATA_CONTROL__VI = 0x0E41; +constexpr unsigned int mmIH_DSM_MATCH_FIELD_CONTROL__VI = 0x0E40; +constexpr unsigned int mmIH_DSM_MATCH_VALUE_BIT_31_0__VI = 0x0E3D; +constexpr unsigned int mmIH_DSM_MATCH_VALUE_BIT_63_32__VI = 0x0E3E; +constexpr unsigned int mmIH_DSM_MATCH_VALUE_BIT_95_64__VI = 0x0E3F; +constexpr unsigned int mmIH_LEVEL_INTR_MASK__VI = 0x0E49; +constexpr unsigned int mmIH_LEVEL_STATUS__SI__CI = 0x0F87; +constexpr unsigned int mmIH_LEVEL_STATUS__VI = 0x0E37; +constexpr unsigned int mmIH_PERFCOUNTER0_RESULT__VI = 0x0E3A; +constexpr unsigned int mmIH_PERFCOUNTER1_RESULT__VI = 0x0E3B; +constexpr unsigned int mmIH_PERFMON_CNTL__VI = 0x0E39; +constexpr unsigned int mmIH_RB_BASE__SI__CI = 0x0F81; +constexpr unsigned int mmIH_RB_BASE__VI = 0x0E31; +constexpr unsigned int mmIH_RB_CNTL__SI__CI = 0x0F80; +constexpr unsigned int mmIH_RB_CNTL__VI = 0x0E30; +constexpr unsigned int mmIH_RB_RPTR__SI__CI = 0x0F82; +constexpr unsigned int mmIH_RB_RPTR__VI = 0x0E32; +constexpr unsigned int mmIH_RB_WPTR__SI__CI = 0x0F83; +constexpr unsigned int mmIH_RB_WPTR__VI = 0x0E33; +constexpr unsigned int mmIH_RB_WPTR_ADDR_HI__SI__CI = 0x0F84; +constexpr unsigned int mmIH_RB_WPTR_ADDR_HI__VI = 0x0E34; +constexpr unsigned int mmIH_RB_WPTR_ADDR_LO__SI__CI = 0x0F85; +constexpr unsigned int mmIH_RB_WPTR_ADDR_LO__VI = 0x0E35; +constexpr unsigned int mmIH_RESET_INCOMPLETE_INT_CNTL__VI = 0x0E4A; +constexpr unsigned int mmIH_STATUS__SI__CI = 0x0F88; +constexpr unsigned int mmIH_STATUS__VI = 0x0E38; +constexpr unsigned int mmIH_VERSION__VI = 0x0E48; +constexpr unsigned int mmIH_VF_ENABLE__VI = 0x0E45; +constexpr unsigned int mmIH_VF_RB_BIF_STATUS__VI = 0x0E47; +constexpr unsigned int mmIH_VF_RB_STATUS__VI = 0x0E44; +constexpr unsigned int mmIH_VIRT_RESET_REQ__VI = 0x0E46; +constexpr unsigned int mmIH_VMID_0_LUT__VI = 0x0E00; +constexpr unsigned int mmIH_VMID_10_LUT__VI = 0x0E0A; +constexpr unsigned int mmIH_VMID_11_LUT__VI = 0x0E0B; +constexpr unsigned int mmIH_VMID_12_LUT__VI = 0x0E0C; +constexpr unsigned int mmIH_VMID_13_LUT__VI = 0x0E0D; +constexpr unsigned int mmIH_VMID_14_LUT__VI = 0x0E0E; +constexpr unsigned int mmIH_VMID_15_LUT__VI = 0x0E0F; +constexpr unsigned int mmIH_VMID_1_LUT__VI = 0x0E01; +constexpr unsigned int mmIH_VMID_2_LUT__VI = 0x0E02; +constexpr unsigned int mmIH_VMID_3_LUT__VI = 0x0E03; +constexpr unsigned int mmIH_VMID_4_LUT__VI = 0x0E04; +constexpr unsigned int mmIH_VMID_5_LUT__VI = 0x0E05; +constexpr unsigned int mmIH_VMID_6_LUT__VI = 0x0E06; +constexpr unsigned int mmIH_VMID_7_LUT__VI = 0x0E07; +constexpr unsigned int mmIH_VMID_8_LUT__VI = 0x0E08; +constexpr unsigned int mmIH_VMID_9_LUT__VI = 0x0E09; +constexpr unsigned int mmINPUT_CSC_C11_C12__VI = 0x1A36; +constexpr unsigned int mmINPUT_CSC_C11_C12_A__VI = 0x46A6; +constexpr unsigned int mmINPUT_CSC_C11_C12_B__VI = 0x46AC; +constexpr unsigned int mmINPUT_CSC_C13_C14__VI = 0x1A37; +constexpr unsigned int mmINPUT_CSC_C13_C14_A__VI = 0x46A7; +constexpr unsigned int mmINPUT_CSC_C13_C14_B__VI = 0x46AD; +constexpr unsigned int mmINPUT_CSC_C21_C22__VI = 0x1A38; +constexpr unsigned int mmINPUT_CSC_C21_C22_A__VI = 0x46A8; +constexpr unsigned int mmINPUT_CSC_C21_C22_B__VI = 0x46AE; +constexpr unsigned int mmINPUT_CSC_C23_C24__VI = 0x1A39; +constexpr unsigned int mmINPUT_CSC_C23_C24_A__VI = 0x46A9; +constexpr unsigned int mmINPUT_CSC_C23_C24_B__VI = 0x46AF; +constexpr unsigned int mmINPUT_CSC_C31_C32__VI = 0x1A3A; +constexpr unsigned int mmINPUT_CSC_C31_C32_A__VI = 0x46AA; +constexpr unsigned int mmINPUT_CSC_C31_C32_B__VI = 0x46B0; +constexpr unsigned int mmINPUT_CSC_C33_C34__VI = 0x1A3B; +constexpr unsigned int mmINPUT_CSC_C33_C34_A__VI = 0x46AB; +constexpr unsigned int mmINPUT_CSC_C33_C34_B__VI = 0x46B1; +constexpr unsigned int mmINPUT_CSC_CONTROL__VI = 0x1A35; +constexpr unsigned int mmINPUT_GAMMA_CONTROL__VI = 0x1A10; +constexpr unsigned int mmKEY_CONTROL__VI = 0x1A53; +constexpr unsigned int mmKEY_RANGE_ALPHA__VI = 0x1A54; +constexpr unsigned int mmKEY_RANGE_BLUE__VI = 0x1A57; +constexpr unsigned int mmKEY_RANGE_GREEN__VI = 0x1A56; +constexpr unsigned int mmKEY_RANGE_RED__VI = 0x1A55; +constexpr unsigned int mmLB0_DC_MVP_LB_CONTROL__VI = 0x1AE3; +constexpr unsigned int mmLB0_LB_BLACK_KEYER_B_CB__VI = 0x1ACF; +constexpr unsigned int mmLB0_LB_BLACK_KEYER_G_Y__VI = 0x1ACE; +constexpr unsigned int mmLB0_LB_BLACK_KEYER_R_CR__VI = 0x1ACD; +constexpr unsigned int mmLB0_LB_BUFFER_LEVEL_STATUS__VI = 0x1AD7; +constexpr unsigned int mmLB0_LB_BUFFER_STATUS__VI = 0x1ADA; +constexpr unsigned int mmLB0_LB_BUFFER_URGENCY_CTRL__VI = 0x1AD8; +constexpr unsigned int mmLB0_LB_BUFFER_URGENCY_STATUS__VI = 0x1AD9; +constexpr unsigned int mmLB0_LB_DATA_FORMAT__VI = 0x1AC0; +constexpr unsigned int mmLB0_LB_DEBUG__VI = 0x1AE4; +constexpr unsigned int mmLB0_LB_DEBUG2__VI = 0x1AE5; +constexpr unsigned int mmLB0_LB_DEBUG3__VI = 0x1AE6; +constexpr unsigned int mmLB0_LB_DESKTOP_HEIGHT__VI = 0x1AC3; +constexpr unsigned int mmLB0_LB_INTERRUPT_MASK__VI = 0x1AC8; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_B_CB__VI = 0x1AD3; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_CTRL__VI = 0x1AD0; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_G_Y__VI = 0x1AD2; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_REP_B_CB__VI = 0x1AD6; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_REP_G_Y__VI = 0x1AD5; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_REP_R_CR__VI = 0x1AD4; +constexpr unsigned int mmLB0_LB_KEYER_COLOR_R_CR__VI = 0x1AD1; +constexpr unsigned int mmLB0_LB_MEMORY_CTRL__VI = 0x1AC1; +constexpr unsigned int mmLB0_LB_MEMORY_SIZE_STATUS__VI = 0x1AC2; +constexpr unsigned int mmLB0_LB_NO_OUTSTANDING_REQ_STATUS__VI = 0x1ADC; +constexpr unsigned int mmLB0_LB_SNAPSHOT_V_COUNTER__VI = 0x1AC7; +constexpr unsigned int mmLB0_LB_SYNC_RESET_SEL__VI = 0x1ACC; +constexpr unsigned int mmLB0_LB_VBLANK_STATUS__VI = 0x1ACB; +constexpr unsigned int mmLB0_LB_VLINE2_START_END__VI = 0x1AC5; +constexpr unsigned int mmLB0_LB_VLINE2_STATUS__VI = 0x1ACA; +constexpr unsigned int mmLB0_LB_VLINE_START_END__VI = 0x1AC4; +constexpr unsigned int mmLB0_LB_VLINE_STATUS__VI = 0x1AC9; +constexpr unsigned int mmLB0_LB_V_COUNTER__VI = 0x1AC6; +constexpr unsigned int mmLB0_MVP_AFR_FLIP_FIFO_CNTL__VI = 0x1AE1; +constexpr unsigned int mmLB0_MVP_AFR_FLIP_MODE__VI = 0x1AE0; +constexpr unsigned int mmLB0_MVP_FLIP_LINE_NUM_INSERT__VI = 0x1AE2; +constexpr unsigned int mmLB1_DC_MVP_LB_CONTROL__VI = 0x1CE3; +constexpr unsigned int mmLB1_LB_BLACK_KEYER_B_CB__VI = 0x1CCF; +constexpr unsigned int mmLB1_LB_BLACK_KEYER_G_Y__VI = 0x1CCE; +constexpr unsigned int mmLB1_LB_BLACK_KEYER_R_CR__VI = 0x1CCD; +constexpr unsigned int mmLB1_LB_BUFFER_LEVEL_STATUS__VI = 0x1CD7; +constexpr unsigned int mmLB1_LB_BUFFER_STATUS__VI = 0x1CDA; +constexpr unsigned int mmLB1_LB_BUFFER_URGENCY_CTRL__VI = 0x1CD8; +constexpr unsigned int mmLB1_LB_BUFFER_URGENCY_STATUS__VI = 0x1CD9; +constexpr unsigned int mmLB1_LB_DATA_FORMAT__VI = 0x1CC0; +constexpr unsigned int mmLB1_LB_DEBUG__VI = 0x1CE4; +constexpr unsigned int mmLB1_LB_DEBUG2__VI = 0x1CE5; +constexpr unsigned int mmLB1_LB_DEBUG3__VI = 0x1CE6; +constexpr unsigned int mmLB1_LB_DESKTOP_HEIGHT__VI = 0x1CC3; +constexpr unsigned int mmLB1_LB_INTERRUPT_MASK__VI = 0x1CC8; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_B_CB__VI = 0x1CD3; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_CTRL__VI = 0x1CD0; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_G_Y__VI = 0x1CD2; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_REP_B_CB__VI = 0x1CD6; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_REP_G_Y__VI = 0x1CD5; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_REP_R_CR__VI = 0x1CD4; +constexpr unsigned int mmLB1_LB_KEYER_COLOR_R_CR__VI = 0x1CD1; +constexpr unsigned int mmLB1_LB_MEMORY_CTRL__VI = 0x1CC1; +constexpr unsigned int mmLB1_LB_MEMORY_SIZE_STATUS__VI = 0x1CC2; +constexpr unsigned int mmLB1_LB_NO_OUTSTANDING_REQ_STATUS__VI = 0x1CDC; +constexpr unsigned int mmLB1_LB_SNAPSHOT_V_COUNTER__VI = 0x1CC7; +constexpr unsigned int mmLB1_LB_SYNC_RESET_SEL__VI = 0x1CCC; +constexpr unsigned int mmLB1_LB_TEST_DEBUG_DATA__VI = 0x1CFF; +constexpr unsigned int mmLB1_LB_TEST_DEBUG_INDEX__VI = 0x1CFE; +constexpr unsigned int mmLB1_LB_VBLANK_STATUS__VI = 0x1CCB; +constexpr unsigned int mmLB1_LB_VLINE2_START_END__VI = 0x1CC5; +constexpr unsigned int mmLB1_LB_VLINE2_STATUS__VI = 0x1CCA; +constexpr unsigned int mmLB1_LB_VLINE_START_END__VI = 0x1CC4; +constexpr unsigned int mmLB1_LB_VLINE_STATUS__VI = 0x1CC9; +constexpr unsigned int mmLB1_LB_V_COUNTER__VI = 0x1CC6; +constexpr unsigned int mmLB1_MVP_AFR_FLIP_FIFO_CNTL__VI = 0x1CE1; +constexpr unsigned int mmLB1_MVP_AFR_FLIP_MODE__VI = 0x1CE0; +constexpr unsigned int mmLB1_MVP_FLIP_LINE_NUM_INSERT__VI = 0x1CE2; +constexpr unsigned int mmLB2_DC_MVP_LB_CONTROL__VI = 0x1EE3; +constexpr unsigned int mmLB2_LB_BLACK_KEYER_B_CB__VI = 0x1ECF; +constexpr unsigned int mmLB2_LB_BLACK_KEYER_G_Y__VI = 0x1ECE; +constexpr unsigned int mmLB2_LB_BLACK_KEYER_R_CR__VI = 0x1ECD; +constexpr unsigned int mmLB2_LB_BUFFER_LEVEL_STATUS__VI = 0x1ED7; +constexpr unsigned int mmLB2_LB_BUFFER_STATUS__VI = 0x1EDA; +constexpr unsigned int mmLB2_LB_BUFFER_URGENCY_CTRL__VI = 0x1ED8; +constexpr unsigned int mmLB2_LB_BUFFER_URGENCY_STATUS__VI = 0x1ED9; +constexpr unsigned int mmLB2_LB_DATA_FORMAT__VI = 0x1EC0; +constexpr unsigned int mmLB2_LB_DEBUG__VI = 0x1EE4; +constexpr unsigned int mmLB2_LB_DEBUG2__VI = 0x1EE5; +constexpr unsigned int mmLB2_LB_DEBUG3__VI = 0x1EE6; +constexpr unsigned int mmLB2_LB_DESKTOP_HEIGHT__VI = 0x1EC3; +constexpr unsigned int mmLB2_LB_INTERRUPT_MASK__VI = 0x1EC8; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_B_CB__VI = 0x1ED3; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_CTRL__VI = 0x1ED0; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_G_Y__VI = 0x1ED2; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_REP_B_CB__VI = 0x1ED6; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_REP_G_Y__VI = 0x1ED5; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_REP_R_CR__VI = 0x1ED4; +constexpr unsigned int mmLB2_LB_KEYER_COLOR_R_CR__VI = 0x1ED1; +constexpr unsigned int mmLB2_LB_MEMORY_CTRL__VI = 0x1EC1; +constexpr unsigned int mmLB2_LB_MEMORY_SIZE_STATUS__VI = 0x1EC2; +constexpr unsigned int mmLB2_LB_NO_OUTSTANDING_REQ_STATUS__VI = 0x1EDC; +constexpr unsigned int mmLB2_LB_SNAPSHOT_V_COUNTER__VI = 0x1EC7; +constexpr unsigned int mmLB2_LB_SYNC_RESET_SEL__VI = 0x1ECC; +constexpr unsigned int mmLB2_LB_TEST_DEBUG_DATA__VI = 0x1EFF; +constexpr unsigned int mmLB2_LB_TEST_DEBUG_INDEX__VI = 0x1EFE; +constexpr unsigned int mmLB2_LB_VBLANK_STATUS__VI = 0x1ECB; +constexpr unsigned int mmLB2_LB_VLINE2_START_END__VI = 0x1EC5; +constexpr unsigned int mmLB2_LB_VLINE2_STATUS__VI = 0x1ECA; +constexpr unsigned int mmLB2_LB_VLINE_START_END__VI = 0x1EC4; +constexpr unsigned int mmLB2_LB_VLINE_STATUS__VI = 0x1EC9; +constexpr unsigned int mmLB2_LB_V_COUNTER__VI = 0x1EC6; +constexpr unsigned int mmLB2_MVP_AFR_FLIP_FIFO_CNTL__VI = 0x1EE1; +constexpr unsigned int mmLB2_MVP_AFR_FLIP_MODE__VI = 0x1EE0; +constexpr unsigned int mmLB2_MVP_FLIP_LINE_NUM_INSERT__VI = 0x1EE2; +constexpr unsigned int mmLB3_DC_MVP_LB_CONTROL__VI = 0x40E3; +constexpr unsigned int mmLB3_LB_BLACK_KEYER_B_CB__VI = 0x40CF; +constexpr unsigned int mmLB3_LB_BLACK_KEYER_G_Y__VI = 0x40CE; +constexpr unsigned int mmLB3_LB_BLACK_KEYER_R_CR__VI = 0x40CD; +constexpr unsigned int mmLB3_LB_BUFFER_LEVEL_STATUS__VI = 0x40D7; +constexpr unsigned int mmLB3_LB_BUFFER_STATUS__VI = 0x40DA; +constexpr unsigned int mmLB3_LB_BUFFER_URGENCY_CTRL__VI = 0x40D8; +constexpr unsigned int mmLB3_LB_BUFFER_URGENCY_STATUS__VI = 0x40D9; +constexpr unsigned int mmLB3_LB_DATA_FORMAT__VI = 0x40C0; +constexpr unsigned int mmLB3_LB_DEBUG__VI = 0x40E4; +constexpr unsigned int mmLB3_LB_DEBUG2__VI = 0x40E5; +constexpr unsigned int mmLB3_LB_DEBUG3__VI = 0x40E6; +constexpr unsigned int mmLB3_LB_DESKTOP_HEIGHT__VI = 0x40C3; +constexpr unsigned int mmLB3_LB_INTERRUPT_MASK__VI = 0x40C8; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_B_CB__VI = 0x40D3; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_CTRL__VI = 0x40D0; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_G_Y__VI = 0x40D2; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_REP_B_CB__VI = 0x40D6; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_REP_G_Y__VI = 0x40D5; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_REP_R_CR__VI = 0x40D4; +constexpr unsigned int mmLB3_LB_KEYER_COLOR_R_CR__VI = 0x40D1; +constexpr unsigned int mmLB3_LB_MEMORY_CTRL__VI = 0x40C1; +constexpr unsigned int mmLB3_LB_MEMORY_SIZE_STATUS__VI = 0x40C2; +constexpr unsigned int mmLB3_LB_NO_OUTSTANDING_REQ_STATUS__VI = 0x40DC; +constexpr unsigned int mmLB3_LB_SNAPSHOT_V_COUNTER__VI = 0x40C7; +constexpr unsigned int mmLB3_LB_SYNC_RESET_SEL__VI = 0x40CC; +constexpr unsigned int mmLB3_LB_TEST_DEBUG_DATA__VI = 0x40FF; +constexpr unsigned int mmLB3_LB_TEST_DEBUG_INDEX__VI = 0x40FE; +constexpr unsigned int mmLB3_LB_VBLANK_STATUS__VI = 0x40CB; +constexpr unsigned int mmLB3_LB_VLINE2_START_END__VI = 0x40C5; +constexpr unsigned int mmLB3_LB_VLINE2_STATUS__VI = 0x40CA; +constexpr unsigned int mmLB3_LB_VLINE_START_END__VI = 0x40C4; +constexpr unsigned int mmLB3_LB_VLINE_STATUS__VI = 0x40C9; +constexpr unsigned int mmLB3_LB_V_COUNTER__VI = 0x40C6; +constexpr unsigned int mmLB3_MVP_AFR_FLIP_FIFO_CNTL__VI = 0x40E1; +constexpr unsigned int mmLB3_MVP_AFR_FLIP_MODE__VI = 0x40E0; +constexpr unsigned int mmLB3_MVP_FLIP_LINE_NUM_INSERT__VI = 0x40E2; +constexpr unsigned int mmLB4_DC_MVP_LB_CONTROL__VI = 0x42E3; +constexpr unsigned int mmLB4_LB_BLACK_KEYER_B_CB__VI = 0x42CF; +constexpr unsigned int mmLB4_LB_BLACK_KEYER_G_Y__VI = 0x42CE; +constexpr unsigned int mmLB4_LB_BLACK_KEYER_R_CR__VI = 0x42CD; +constexpr unsigned int mmLB4_LB_BUFFER_LEVEL_STATUS__VI = 0x42D7; +constexpr unsigned int mmLB4_LB_BUFFER_STATUS__VI = 0x42DA; +constexpr unsigned int mmLB4_LB_BUFFER_URGENCY_CTRL__VI = 0x42D8; +constexpr unsigned int mmLB4_LB_BUFFER_URGENCY_STATUS__VI = 0x42D9; +constexpr unsigned int mmLB4_LB_DATA_FORMAT__VI = 0x42C0; +constexpr unsigned int mmLB4_LB_DEBUG__VI = 0x42E4; +constexpr unsigned int mmLB4_LB_DEBUG2__VI = 0x42E5; +constexpr unsigned int mmLB4_LB_DEBUG3__VI = 0x42E6; +constexpr unsigned int mmLB4_LB_DESKTOP_HEIGHT__VI = 0x42C3; +constexpr unsigned int mmLB4_LB_INTERRUPT_MASK__VI = 0x42C8; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_B_CB__VI = 0x42D3; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_CTRL__VI = 0x42D0; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_G_Y__VI = 0x42D2; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_REP_B_CB__VI = 0x42D6; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_REP_G_Y__VI = 0x42D5; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_REP_R_CR__VI = 0x42D4; +constexpr unsigned int mmLB4_LB_KEYER_COLOR_R_CR__VI = 0x42D1; +constexpr unsigned int mmLB4_LB_MEMORY_CTRL__VI = 0x42C1; +constexpr unsigned int mmLB4_LB_MEMORY_SIZE_STATUS__VI = 0x42C2; +constexpr unsigned int mmLB4_LB_NO_OUTSTANDING_REQ_STATUS__VI = 0x42DC; +constexpr unsigned int mmLB4_LB_SNAPSHOT_V_COUNTER__VI = 0x42C7; +constexpr unsigned int mmLB4_LB_SYNC_RESET_SEL__VI = 0x42CC; +constexpr unsigned int mmLB4_LB_TEST_DEBUG_DATA__VI = 0x42FF; +constexpr unsigned int mmLB4_LB_TEST_DEBUG_INDEX__VI = 0x42FE; +constexpr unsigned int mmLB4_LB_VBLANK_STATUS__VI = 0x42CB; +constexpr unsigned int mmLB4_LB_VLINE2_START_END__VI = 0x42C5; +constexpr unsigned int mmLB4_LB_VLINE2_STATUS__VI = 0x42CA; +constexpr unsigned int mmLB4_LB_VLINE_START_END__VI = 0x42C4; +constexpr unsigned int mmLB4_LB_VLINE_STATUS__VI = 0x42C9; +constexpr unsigned int mmLB4_LB_V_COUNTER__VI = 0x42C6; +constexpr unsigned int mmLB4_MVP_AFR_FLIP_FIFO_CNTL__VI = 0x42E1; +constexpr unsigned int mmLB4_MVP_AFR_FLIP_MODE__VI = 0x42E0; +constexpr unsigned int mmLB4_MVP_FLIP_LINE_NUM_INSERT__VI = 0x42E2; +constexpr unsigned int mmLB5_DC_MVP_LB_CONTROL__VI = 0x44E3; +constexpr unsigned int mmLB5_LB_BLACK_KEYER_B_CB__VI = 0x44CF; +constexpr unsigned int mmLB5_LB_BLACK_KEYER_G_Y__VI = 0x44CE; +constexpr unsigned int mmLB5_LB_BLACK_KEYER_R_CR__VI = 0x44CD; +constexpr unsigned int mmLB5_LB_BUFFER_LEVEL_STATUS__VI = 0x44D7; +constexpr unsigned int mmLB5_LB_BUFFER_STATUS__VI = 0x44DA; +constexpr unsigned int mmLB5_LB_BUFFER_URGENCY_CTRL__VI = 0x44D8; +constexpr unsigned int mmLB5_LB_BUFFER_URGENCY_STATUS__VI = 0x44D9; +constexpr unsigned int mmLB5_LB_DATA_FORMAT__VI = 0x44C0; +constexpr unsigned int mmLB5_LB_DEBUG__VI = 0x44E4; +constexpr unsigned int mmLB5_LB_DEBUG2__VI = 0x44E5; +constexpr unsigned int mmLB5_LB_DEBUG3__VI = 0x44E6; +constexpr unsigned int mmLB5_LB_DESKTOP_HEIGHT__VI = 0x44C3; +constexpr unsigned int mmLB5_LB_INTERRUPT_MASK__VI = 0x44C8; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_B_CB__VI = 0x44D3; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_CTRL__VI = 0x44D0; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_G_Y__VI = 0x44D2; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_REP_B_CB__VI = 0x44D6; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_REP_G_Y__VI = 0x44D5; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_REP_R_CR__VI = 0x44D4; +constexpr unsigned int mmLB5_LB_KEYER_COLOR_R_CR__VI = 0x44D1; +constexpr unsigned int mmLB5_LB_MEMORY_CTRL__VI = 0x44C1; +constexpr unsigned int mmLB5_LB_MEMORY_SIZE_STATUS__VI = 0x44C2; +constexpr unsigned int mmLB5_LB_NO_OUTSTANDING_REQ_STATUS__VI = 0x44DC; +constexpr unsigned int mmLB5_LB_SNAPSHOT_V_COUNTER__VI = 0x44C7; +constexpr unsigned int mmLB5_LB_SYNC_RESET_SEL__VI = 0x44CC; +constexpr unsigned int mmLB5_LB_TEST_DEBUG_DATA__VI = 0x44FF; +constexpr unsigned int mmLB5_LB_TEST_DEBUG_INDEX__VI = 0x44FE; +constexpr unsigned int mmLB5_LB_VBLANK_STATUS__VI = 0x44CB; +constexpr unsigned int mmLB5_LB_VLINE2_START_END__VI = 0x44C5; +constexpr unsigned int mmLB5_LB_VLINE2_STATUS__VI = 0x44CA; +constexpr unsigned int mmLB5_LB_VLINE_START_END__VI = 0x44C4; +constexpr unsigned int mmLB5_LB_VLINE_STATUS__VI = 0x44C9; +constexpr unsigned int mmLB5_LB_V_COUNTER__VI = 0x44C6; +constexpr unsigned int mmLB5_MVP_AFR_FLIP_FIFO_CNTL__VI = 0x44E1; +constexpr unsigned int mmLB5_MVP_AFR_FLIP_MODE__VI = 0x44E0; +constexpr unsigned int mmLB5_MVP_FLIP_LINE_NUM_INSERT__VI = 0x44E2; +constexpr unsigned int mmLBV_BLACK_KEYER_B_CB__VI = 0x464D; +constexpr unsigned int mmLBV_BLACK_KEYER_G_Y__VI = 0x464C; +constexpr unsigned int mmLBV_BLACK_KEYER_R_CR__VI = 0x464B; +constexpr unsigned int mmLBV_BUFFER_LEVEL_STATUS__VI = 0x4655; +constexpr unsigned int mmLBV_BUFFER_STATUS__VI = 0x4658; +constexpr unsigned int mmLBV_BUFFER_URGENCY_CTRL__VI = 0x4656; +constexpr unsigned int mmLBV_BUFFER_URGENCY_STATUS__VI = 0x4657; +constexpr unsigned int mmLBV_DATA_FORMAT__VI = 0x463C; +constexpr unsigned int mmLBV_DEBUG__VI = 0x465A; +constexpr unsigned int mmLBV_DEBUG2__VI = 0x465B; +constexpr unsigned int mmLBV_DEBUG3__VI = 0x465C; +constexpr unsigned int mmLBV_DESKTOP_HEIGHT__VI = 0x463F; +constexpr unsigned int mmLBV_INTERRUPT_MASK__VI = 0x4646; +constexpr unsigned int mmLBV_KEYER_COLOR_B_CB__VI = 0x4651; +constexpr unsigned int mmLBV_KEYER_COLOR_CTRL__VI = 0x464E; +constexpr unsigned int mmLBV_KEYER_COLOR_G_Y__VI = 0x4650; +constexpr unsigned int mmLBV_KEYER_COLOR_REP_B_CB__VI = 0x4654; +constexpr unsigned int mmLBV_KEYER_COLOR_REP_G_Y__VI = 0x4653; +constexpr unsigned int mmLBV_KEYER_COLOR_REP_R_CR__VI = 0x4652; +constexpr unsigned int mmLBV_KEYER_COLOR_R_CR__VI = 0x464F; +constexpr unsigned int mmLBV_MEMORY_CTRL__VI = 0x463D; +constexpr unsigned int mmLBV_MEMORY_SIZE_STATUS__VI = 0x463E; +constexpr unsigned int mmLBV_NO_OUTSTANDING_REQ_STATUS__VI = 0x4659; +constexpr unsigned int mmLBV_SNAPSHOT_V_COUNTER__VI = 0x4643; +constexpr unsigned int mmLBV_SNAPSHOT_V_COUNTER_CHROMA__VI = 0x4645; +constexpr unsigned int mmLBV_SYNC_RESET_SEL__VI = 0x464A; +constexpr unsigned int mmLBV_TEST_DEBUG_DATA__VI = 0x4667; +constexpr unsigned int mmLBV_TEST_DEBUG_INDEX__VI = 0x4666; +constexpr unsigned int mmLBV_VBLANK_STATUS__VI = 0x4649; +constexpr unsigned int mmLBV_VLINE2_START_END__VI = 0x4641; +constexpr unsigned int mmLBV_VLINE2_STATUS__VI = 0x4648; +constexpr unsigned int mmLBV_VLINE_START_END__VI = 0x4640; +constexpr unsigned int mmLBV_VLINE_STATUS__VI = 0x4647; +constexpr unsigned int mmLBV_V_COUNTER__VI = 0x4642; +constexpr unsigned int mmLBV_V_COUNTER_CHROMA__VI = 0x4644; +constexpr unsigned int mmLB_BLACK_KEYER_B_CB__VI = 0x1ACF; +constexpr unsigned int mmLB_BLACK_KEYER_G_Y__VI = 0x1ACE; +constexpr unsigned int mmLB_BLACK_KEYER_R_CR__VI = 0x1ACD; +constexpr unsigned int mmLB_BUFFER_LEVEL_STATUS__VI = 0x1AD7; +constexpr unsigned int mmLB_BUFFER_STATUS__VI = 0x1ADA; +constexpr unsigned int mmLB_BUFFER_URGENCY_CTRL__VI = 0x1AD8; +constexpr unsigned int mmLB_BUFFER_URGENCY_STATUS__VI = 0x1AD9; +constexpr unsigned int mmLB_DATA_FORMAT__VI = 0x1AC0; +constexpr unsigned int mmLB_DEBUG__VI = 0x1AE4; +constexpr unsigned int mmLB_DEBUG2__VI = 0x1AE5; +constexpr unsigned int mmLB_DEBUG3__VI = 0x1AE6; +constexpr unsigned int mmLB_DESKTOP_HEIGHT__VI = 0x1AC3; +constexpr unsigned int mmLB_INTERRUPT_MASK__VI = 0x1AC8; +constexpr unsigned int mmLB_KEYER_COLOR_B_CB__VI = 0x1AD3; +constexpr unsigned int mmLB_KEYER_COLOR_CTRL__VI = 0x1AD0; +constexpr unsigned int mmLB_KEYER_COLOR_G_Y__VI = 0x1AD2; +constexpr unsigned int mmLB_KEYER_COLOR_REP_B_CB__VI = 0x1AD6; +constexpr unsigned int mmLB_KEYER_COLOR_REP_G_Y__VI = 0x1AD5; +constexpr unsigned int mmLB_KEYER_COLOR_REP_R_CR__VI = 0x1AD4; +constexpr unsigned int mmLB_KEYER_COLOR_R_CR__VI = 0x1AD1; +constexpr unsigned int mmLB_MEMORY_CTRL__VI = 0x1AC1; +constexpr unsigned int mmLB_MEMORY_SIZE_STATUS__VI = 0x1AC2; +constexpr unsigned int mmLB_NO_OUTSTANDING_REQ_STATUS__VI = 0x1ADC; +constexpr unsigned int mmLB_SNAPSHOT_V_COUNTER__VI = 0x1AC7; +constexpr unsigned int mmLB_SYNC_RESET_SEL__VI = 0x1ACC; +constexpr unsigned int mmLB_VBLANK_STATUS__VI = 0x1ACB; +constexpr unsigned int mmLB_VLINE2_START_END__VI = 0x1AC5; +constexpr unsigned int mmLB_VLINE2_STATUS__VI = 0x1ACA; +constexpr unsigned int mmLB_VLINE_START_END__VI = 0x1AC4; +constexpr unsigned int mmLB_VLINE_STATUS__VI = 0x1AC9; +constexpr unsigned int mmLB_V_COUNTER__VI = 0x1AC6; +constexpr unsigned int mmLOW_POWER_TILING_CONTROL__VI = 0x030B; +constexpr unsigned int mmLVDS_DATA_CNTL__VI = 0x4A78; +constexpr unsigned int mmLVTMA_PWRSEQ_CNTL__VI = 0x481B; +constexpr unsigned int mmLVTMA_PWRSEQ_DELAY1__VI = 0x481E; +constexpr unsigned int mmLVTMA_PWRSEQ_DELAY2__VI = 0x481F; +constexpr unsigned int mmLVTMA_PWRSEQ_REF_DIV__VI = 0x481D; +constexpr unsigned int mmLVTMA_PWRSEQ_STATE__VI = 0x481C; +constexpr unsigned int mmMAILBOX_CONTROL__VI = 0x14D0; +constexpr unsigned int mmMAILBOX_INDEX__VI = 0x14C6; +constexpr unsigned int mmMAILBOX_INT_CNTL__VI = 0x14D1; +constexpr unsigned int mmMAILBOX_MSGBUF_RCV_DW0__VI = 0x14CC; +constexpr unsigned int mmMAILBOX_MSGBUF_RCV_DW1__VI = 0x14CD; +constexpr unsigned int mmMAILBOX_MSGBUF_RCV_DW2__VI = 0x14CE; +constexpr unsigned int mmMAILBOX_MSGBUF_RCV_DW3__VI = 0x14CF; +constexpr unsigned int mmMAILBOX_MSGBUF_TRN_DW0__VI = 0x14C8; +constexpr unsigned int mmMAILBOX_MSGBUF_TRN_DW1__VI = 0x14C9; +constexpr unsigned int mmMAILBOX_MSGBUF_TRN_DW2__VI = 0x14CA; +constexpr unsigned int mmMAILBOX_MSGBUF_TRN_DW3__VI = 0x14CB; +constexpr unsigned int mmMCIF_CONTROL__VI = 0x030C; +constexpr unsigned int mmMCIF_MEM_CONTROL__VI = 0x0311; +constexpr unsigned int mmMCIF_TEST_DEBUG_DATA__VI = 0x030F; +constexpr unsigned int mmMCIF_TEST_DEBUG_INDEX__VI = 0x030E; +constexpr unsigned int mmMCIF_VMID__VI = 0x0310; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_ARBITRATION_CONTROL__VI = 0x5E84; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUFMGR_CUR_LINE_R__VI = 0x5E79; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUFMGR_STATUS__VI = 0x5E7A; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL__VI = 0x5E78; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL__VI = 0x5E98; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_1_ADDR_C__VI = 0x5E8A; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET__VI = 0x5E8B; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_1_ADDR_Y__VI = 0x5E88; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET__VI = 0x5E89; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_1_STATUS__VI = 0x5E7C; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_1_STATUS2__VI = 0x5E7D; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_2_ADDR_C__VI = 0x5E8E; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET__VI = 0x5E8F; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_2_ADDR_Y__VI = 0x5E8C; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET__VI = 0x5E8D; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_2_STATUS__VI = 0x5E7E; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_2_STATUS2__VI = 0x5E7F; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_3_ADDR_C__VI = 0x5E92; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET__VI = 0x5E93; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_3_ADDR_Y__VI = 0x5E90; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET__VI = 0x5E91; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_3_STATUS__VI = 0x5E80; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_3_STATUS2__VI = 0x5E81; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_4_ADDR_C__VI = 0x5E96; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET__VI = 0x5E97; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_4_ADDR_Y__VI = 0x5E94; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET__VI = 0x5E95; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_4_STATUS__VI = 0x5E82; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_4_STATUS2__VI = 0x5E83; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_BUF_PITCH__VI = 0x5E7B; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_HVVMID_CONTROL__VI = 0x5E99; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_TEST_DEBUG_DATA__VI = 0x5E87; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_TEST_DEBUG_INDEX__VI = 0x5E86; +constexpr unsigned int mmMCIF_WB0_MCIF_WB_URGENCY_WATERMARK__VI = 0x5E85; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_ARBITRATION_CONTROL__VI = 0x5EC4; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUFMGR_CUR_LINE_R__VI = 0x5EB9; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUFMGR_STATUS__VI = 0x5EBA; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUFMGR_SW_CONTROL__VI = 0x5EB8; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUFMGR_VCE_CONTROL__VI = 0x5ED8; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_1_ADDR_C__VI = 0x5ECA; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_1_ADDR_C_OFFSET__VI = 0x5ECB; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_1_ADDR_Y__VI = 0x5EC8; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_1_ADDR_Y_OFFSET__VI = 0x5EC9; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_1_STATUS__VI = 0x5EBC; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_1_STATUS2__VI = 0x5EBD; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_2_ADDR_C__VI = 0x5ECE; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_2_ADDR_C_OFFSET__VI = 0x5ECF; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_2_ADDR_Y__VI = 0x5ECC; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_2_ADDR_Y_OFFSET__VI = 0x5ECD; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_2_STATUS__VI = 0x5EBE; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_2_STATUS2__VI = 0x5EBF; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_3_ADDR_C__VI = 0x5ED2; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_3_ADDR_C_OFFSET__VI = 0x5ED3; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_3_ADDR_Y__VI = 0x5ED0; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_3_ADDR_Y_OFFSET__VI = 0x5ED1; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_3_STATUS__VI = 0x5EC0; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_3_STATUS2__VI = 0x5EC1; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_4_ADDR_C__VI = 0x5ED6; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_4_ADDR_C_OFFSET__VI = 0x5ED7; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_4_ADDR_Y__VI = 0x5ED4; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_4_ADDR_Y_OFFSET__VI = 0x5ED5; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_4_STATUS__VI = 0x5EC2; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_4_STATUS2__VI = 0x5EC3; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_BUF_PITCH__VI = 0x5EBB; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_HVVMID_CONTROL__VI = 0x5ED9; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_TEST_DEBUG_DATA__VI = 0x5EC7; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_TEST_DEBUG_INDEX__VI = 0x5EC6; +constexpr unsigned int mmMCIF_WB1_MCIF_WB_URGENCY_WATERMARK__VI = 0x5EC5; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_ARBITRATION_CONTROL__VI = 0x5F04; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUFMGR_CUR_LINE_R__VI = 0x5EF9; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUFMGR_STATUS__VI = 0x5EFA; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUFMGR_SW_CONTROL__VI = 0x5EF8; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUFMGR_VCE_CONTROL__VI = 0x5F18; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_1_ADDR_C__VI = 0x5F0A; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_1_ADDR_C_OFFSET__VI = 0x5F0B; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_1_ADDR_Y__VI = 0x5F08; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_1_ADDR_Y_OFFSET__VI = 0x5F09; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_1_STATUS__VI = 0x5EFC; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_1_STATUS2__VI = 0x5EFD; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_2_ADDR_C__VI = 0x5F0E; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_2_ADDR_C_OFFSET__VI = 0x5F0F; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_2_ADDR_Y__VI = 0x5F0C; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_2_ADDR_Y_OFFSET__VI = 0x5F0D; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_2_STATUS__VI = 0x5EFE; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_2_STATUS2__VI = 0x5EFF; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_3_ADDR_C__VI = 0x5F12; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_3_ADDR_C_OFFSET__VI = 0x5F13; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_3_ADDR_Y__VI = 0x5F10; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_3_ADDR_Y_OFFSET__VI = 0x5F11; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_3_STATUS__VI = 0x5F00; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_3_STATUS2__VI = 0x5F01; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_4_ADDR_C__VI = 0x5F16; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_4_ADDR_C_OFFSET__VI = 0x5F17; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_4_ADDR_Y__VI = 0x5F14; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_4_ADDR_Y_OFFSET__VI = 0x5F15; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_4_STATUS__VI = 0x5F02; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_4_STATUS2__VI = 0x5F03; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_BUF_PITCH__VI = 0x5EFB; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_HVVMID_CONTROL__VI = 0x5F19; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_TEST_DEBUG_DATA__VI = 0x5F07; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_TEST_DEBUG_INDEX__VI = 0x5F06; +constexpr unsigned int mmMCIF_WB2_MCIF_WB_URGENCY_WATERMARK__VI = 0x5F05; +constexpr unsigned int mmMCIF_WB_ARBITRATION_CONTROL__VI = 0x5E84; +constexpr unsigned int mmMCIF_WB_BUFMGR_CUR_LINE_R__VI = 0x5E79; +constexpr unsigned int mmMCIF_WB_BUFMGR_STATUS__VI = 0x5E7A; +constexpr unsigned int mmMCIF_WB_BUFMGR_SW_CONTROL__VI = 0x5E78; +constexpr unsigned int mmMCIF_WB_BUFMGR_VCE_CONTROL__VI = 0x5E98; +constexpr unsigned int mmMCIF_WB_BUF_1_ADDR_C__VI = 0x5E8A; +constexpr unsigned int mmMCIF_WB_BUF_1_ADDR_C_OFFSET__VI = 0x5E8B; +constexpr unsigned int mmMCIF_WB_BUF_1_ADDR_Y__VI = 0x5E88; +constexpr unsigned int mmMCIF_WB_BUF_1_ADDR_Y_OFFSET__VI = 0x5E89; +constexpr unsigned int mmMCIF_WB_BUF_1_STATUS__VI = 0x5E7C; +constexpr unsigned int mmMCIF_WB_BUF_1_STATUS2__VI = 0x5E7D; +constexpr unsigned int mmMCIF_WB_BUF_2_ADDR_C__VI = 0x5E8E; +constexpr unsigned int mmMCIF_WB_BUF_2_ADDR_C_OFFSET__VI = 0x5E8F; +constexpr unsigned int mmMCIF_WB_BUF_2_ADDR_Y__VI = 0x5E8C; +constexpr unsigned int mmMCIF_WB_BUF_2_ADDR_Y_OFFSET__VI = 0x5E8D; +constexpr unsigned int mmMCIF_WB_BUF_2_STATUS__VI = 0x5E7E; +constexpr unsigned int mmMCIF_WB_BUF_2_STATUS2__VI = 0x5E7F; +constexpr unsigned int mmMCIF_WB_BUF_3_ADDR_C__VI = 0x5E92; +constexpr unsigned int mmMCIF_WB_BUF_3_ADDR_C_OFFSET__VI = 0x5E93; +constexpr unsigned int mmMCIF_WB_BUF_3_ADDR_Y__VI = 0x5E90; +constexpr unsigned int mmMCIF_WB_BUF_3_ADDR_Y_OFFSET__VI = 0x5E91; +constexpr unsigned int mmMCIF_WB_BUF_3_STATUS__VI = 0x5E80; +constexpr unsigned int mmMCIF_WB_BUF_3_STATUS2__VI = 0x5E81; +constexpr unsigned int mmMCIF_WB_BUF_4_ADDR_C__VI = 0x5E96; +constexpr unsigned int mmMCIF_WB_BUF_4_ADDR_C_OFFSET__VI = 0x5E97; +constexpr unsigned int mmMCIF_WB_BUF_4_ADDR_Y__VI = 0x5E94; +constexpr unsigned int mmMCIF_WB_BUF_4_ADDR_Y_OFFSET__VI = 0x5E95; +constexpr unsigned int mmMCIF_WB_BUF_4_STATUS__VI = 0x5E82; +constexpr unsigned int mmMCIF_WB_BUF_4_STATUS2__VI = 0x5E83; +constexpr unsigned int mmMCIF_WB_BUF_PITCH__VI = 0x5E7B; +constexpr unsigned int mmMCIF_WB_HVVMID_CONTROL__VI = 0x5E99; +constexpr unsigned int mmMCIF_WB_TEST_DEBUG_DATA__VI = 0x5E87; +constexpr unsigned int mmMCIF_WB_TEST_DEBUG_INDEX__VI = 0x5E86; +constexpr unsigned int mmMCIF_WB_URGENCY_WATERMARK__VI = 0x5E85; +constexpr unsigned int mmMCIF_WRITE_COMBINE_CONTROL__VI = 0x030D; +constexpr unsigned int mmMC_ARB_ATOMIC__VI = 0x09BE; +constexpr unsigned int mmMC_ARB_GRUB__VI = 0x09C8; +constexpr unsigned int mmMC_ARB_GRUB2__VI = 0x0A01; +constexpr unsigned int mmMC_ARB_GRUB_PRIORITY1_RD__VI = 0x0DD8; +constexpr unsigned int mmMC_ARB_GRUB_PRIORITY1_WR__VI = 0x0DD9; +constexpr unsigned int mmMC_ARB_GRUB_PRIORITY2_RD__VI = 0x0DDA; +constexpr unsigned int mmMC_ARB_GRUB_PRIORITY2_WR__VI = 0x0DDB; +constexpr unsigned int mmMC_ARB_GRUB_PROMOTE__VI = 0x09CE; +constexpr unsigned int mmMC_ARB_GRUB_REALTIME_RD__VI = 0x09F9; +constexpr unsigned int mmMC_ARB_GRUB_REALTIME_WR__VI = 0x09FB; +constexpr unsigned int mmMC_ARB_PERF_CID__VI = 0x09C6; +constexpr unsigned int mmMC_ARB_SNOOP__VI = 0x09C7; +constexpr unsigned int mmMC_BIST_CMD__VI = 0x0A85; +constexpr unsigned int mmMC_BIST_CNTL__SI__CI = 0x0A05; +constexpr unsigned int mmMC_BIST_CNTL__VI = 0x0A84; +constexpr unsigned int mmMC_BIST_DAT__VI = 0x0A86; +constexpr unsigned int mmMC_BIST_DATA_WORD0__SI__CI = 0x0A0A; +constexpr unsigned int mmMC_BIST_DATA_WORD0__VI = 0x0A8A; +constexpr unsigned int mmMC_BIST_DATA_WORD1__SI__CI = 0x0A0B; +constexpr unsigned int mmMC_BIST_DATA_WORD1__VI = 0x0A8B; +constexpr unsigned int mmMC_BIST_DATA_WORD2__SI__CI = 0x0A0C; +constexpr unsigned int mmMC_BIST_DATA_WORD2__VI = 0x0A8C; +constexpr unsigned int mmMC_BIST_DATA_WORD3__SI__CI = 0x0A0D; +constexpr unsigned int mmMC_BIST_DATA_WORD3__VI = 0x0A8D; +constexpr unsigned int mmMC_BIST_DATA_WORD4__SI__CI = 0x0A0E; +constexpr unsigned int mmMC_BIST_DATA_WORD4__VI = 0x0A8E; +constexpr unsigned int mmMC_BIST_DATA_WORD5__SI__CI = 0x0A0F; +constexpr unsigned int mmMC_BIST_DATA_WORD5__VI = 0x0A8F; +constexpr unsigned int mmMC_BIST_DATA_WORD6__SI__CI = 0x0A10; +constexpr unsigned int mmMC_BIST_DATA_WORD6__VI = 0x0A90; +constexpr unsigned int mmMC_BIST_DATA_WORD7__SI__CI = 0x0A11; +constexpr unsigned int mmMC_BIST_DATA_WORD7__VI = 0x0A91; +constexpr unsigned int mmMC_BIST_MISMATCH_ADDR__SI__CI = 0x0A13; +constexpr unsigned int mmMC_BIST_MISMATCH_ADDR__VI = 0x0A93; +constexpr unsigned int mmMC_BIST_RDATA_WORD0__SI__CI = 0x0A14; +constexpr unsigned int mmMC_BIST_RDATA_WORD0__VI = 0x0A94; +constexpr unsigned int mmMC_BIST_RDATA_WORD1__SI__CI = 0x0A15; +constexpr unsigned int mmMC_BIST_RDATA_WORD1__VI = 0x0A95; +constexpr unsigned int mmMC_BIST_RDATA_WORD2__SI__CI = 0x0A16; +constexpr unsigned int mmMC_BIST_RDATA_WORD2__VI = 0x0A96; +constexpr unsigned int mmMC_BIST_RDATA_WORD3__SI__CI = 0x0A17; +constexpr unsigned int mmMC_BIST_RDATA_WORD3__VI = 0x0A97; +constexpr unsigned int mmMC_BIST_RDATA_WORD4__SI__CI = 0x0A18; +constexpr unsigned int mmMC_BIST_RDATA_WORD4__VI = 0x0A98; +constexpr unsigned int mmMC_BIST_RDATA_WORD5__SI__CI = 0x0A19; +constexpr unsigned int mmMC_BIST_RDATA_WORD5__VI = 0x0A99; +constexpr unsigned int mmMC_BIST_RDATA_WORD6__SI__CI = 0x0A1A; +constexpr unsigned int mmMC_BIST_RDATA_WORD6__VI = 0x0A9A; +constexpr unsigned int mmMC_BIST_RDATA_WORD7__SI__CI = 0x0A1B; +constexpr unsigned int mmMC_BIST_RDATA_WORD7__VI = 0x0A9B; +constexpr unsigned int mmMC_CG_DATAPORT__SI__CI = 0x0A21; +constexpr unsigned int mmMC_CG_DATAPORT__VI = 0x0A32; +constexpr unsigned int mmMC_CITF_CREDITS_ARB_RD2__VI = 0x097E; +constexpr unsigned int mmMC_DC_INTERFACE_NACK_STATUS__VI = 0x0313; +constexpr unsigned int mmMC_FUS_ARB_GARLIC_CNTL__VI = 0x0A20; +constexpr unsigned int mmMC_FUS_ARB_GARLIC_ISOC_PRI__VI = 0x0A1F; +constexpr unsigned int mmMC_FUS_ARB_GARLIC_WR_PRI__VI = 0x0A21; +constexpr unsigned int mmMC_FUS_ARB_GARLIC_WR_PRI2__VI = 0x0A22; +constexpr unsigned int mmMC_FUS_DRAM0_BANK_ADDR_MAPPING__VI = 0x0A11; +constexpr unsigned int mmMC_FUS_DRAM0_CS0_BASE__VI = 0x0A05; +constexpr unsigned int mmMC_FUS_DRAM0_CS1_BASE__VI = 0x0A07; +constexpr unsigned int mmMC_FUS_DRAM0_CS2_BASE__VI = 0x0A09; +constexpr unsigned int mmMC_FUS_DRAM0_CS3_BASE__VI = 0x0A0B; +constexpr unsigned int mmMC_FUS_DRAM0_CTL_BASE__VI = 0x0A13; +constexpr unsigned int mmMC_FUS_DRAM0_CTL_LIMIT__VI = 0x0A15; +constexpr unsigned int mmMC_FUS_DRAM1_BANK_ADDR_MAPPING__VI = 0x0A12; +constexpr unsigned int mmMC_FUS_DRAM1_CS0_BASE__VI = 0x0A06; +constexpr unsigned int mmMC_FUS_DRAM1_CS1_BASE__VI = 0x0A08; +constexpr unsigned int mmMC_FUS_DRAM1_CS2_BASE__VI = 0x0A0A; +constexpr unsigned int mmMC_FUS_DRAM1_CS3_BASE__VI = 0x0A0C; +constexpr unsigned int mmMC_FUS_DRAM1_CTL_BASE__VI = 0x0A14; +constexpr unsigned int mmMC_FUS_DRAM1_CTL_LIMIT__VI = 0x0A16; +constexpr unsigned int mmMC_FUS_DRAM_APER_BASE__VI = 0x0A1A; +constexpr unsigned int mmMC_FUS_DRAM_APER_DEF__VI = 0x0A1E; +constexpr unsigned int mmMC_FUS_DRAM_APER_TOP__VI = 0x0A1B; +constexpr unsigned int mmMC_FUS_DRAM_CTL_HIGH_01__VI = 0x0A17; +constexpr unsigned int mmMC_FUS_DRAM_CTL_HIGH_23__VI = 0x0A18; +constexpr unsigned int mmMC_FUS_DRAM_MODE__VI = 0x0A19; +constexpr unsigned int mmMC_GRUB_FEATURES__VI = 0x0A36; +constexpr unsigned int mmMC_GRUB_PERFCOUNTER0_CFG__VI = 0x07E6; +constexpr unsigned int mmMC_GRUB_PERFCOUNTER1_CFG__VI = 0x07E7; +constexpr unsigned int mmMC_GRUB_PERFCOUNTER_HI__VI = 0x07E5; +constexpr unsigned int mmMC_GRUB_PERFCOUNTER_LO__VI = 0x07E4; +constexpr unsigned int mmMC_GRUB_PERFCOUNTER_RSLT_CNTL__VI = 0x07E8; +constexpr unsigned int mmMC_GRUB_POST_PROBE_DELAY__VI = 0x0A34; +constexpr unsigned int mmMC_GRUB_PROBE_CREDITS__VI = 0x0A35; +constexpr unsigned int mmMC_GRUB_PROBE_MAP__VI = 0x0A33; +constexpr unsigned int mmMC_GRUB_TCB_DATA_HI__VI = 0x0A3A; +constexpr unsigned int mmMC_GRUB_TCB_DATA_LO__VI = 0x0A39; +constexpr unsigned int mmMC_GRUB_TCB_INDEX__VI = 0x0A38; +constexpr unsigned int mmMC_GRUB_TX_CREDITS__VI = 0x0A37; +constexpr unsigned int mmMC_HUB_MISC_ATOMIC_IDLE_STATUS__VI = 0x084F; +constexpr unsigned int mmMC_HUB_RDREQ_ACPG__VI = 0x0881; +constexpr unsigned int mmMC_HUB_RDREQ_ACPO__VI = 0x0882; +constexpr unsigned int mmMC_HUB_RDREQ_BYPASS_GBL0__VI = 0x084C; +constexpr unsigned int mmMC_HUB_RDREQ_DMIF__VI = 0x0862; +constexpr unsigned int mmMC_HUB_RDREQ_HDP__VI = 0x085A; +constexpr unsigned int mmMC_HUB_RDREQ_ISP_CCPU__VI = 0x0DE2; +constexpr unsigned int mmMC_HUB_RDREQ_ISP_MPM__VI = 0x0DE1; +constexpr unsigned int mmMC_HUB_RDREQ_ISP_SPM__VI = 0x0DE0; +constexpr unsigned int mmMC_HUB_RDREQ_MCDS__VI = 0x0DE7; +constexpr unsigned int mmMC_HUB_RDREQ_MCDT__VI = 0x0DE8; +constexpr unsigned int mmMC_HUB_RDREQ_MCDU__VI = 0x0DE9; +constexpr unsigned int mmMC_HUB_RDREQ_MCDV__VI = 0x0DEA; +constexpr unsigned int mmMC_HUB_RDREQ_MCIF__VI = 0x0863; +constexpr unsigned int mmMC_HUB_RDREQ_RLC__VI = 0x085C; +constexpr unsigned int mmMC_HUB_RDREQ_SAMMSP__VI = 0x0883; +constexpr unsigned int mmMC_HUB_RDREQ_SDMA0__VI = 0x0859; +constexpr unsigned int mmMC_HUB_RDREQ_SDMA1__VI = 0x085B; +constexpr unsigned int mmMC_HUB_RDREQ_SEM__VI = 0x085D; +constexpr unsigned int mmMC_HUB_RDREQ_TLS__VI = 0x0861; +constexpr unsigned int mmMC_HUB_RDREQ_UMC__VI = 0x085F; +constexpr unsigned int mmMC_HUB_RDREQ_UVD__VI = 0x0860; +constexpr unsigned int mmMC_HUB_RDREQ_VCE0__VI = 0x085E; +constexpr unsigned int mmMC_HUB_RDREQ_VCE1__VI = 0x0DFC; +constexpr unsigned int mmMC_HUB_RDREQ_VCEU0__VI = 0x0865; +constexpr unsigned int mmMC_HUB_RDREQ_VCEU1__VI = 0x0DFD; +constexpr unsigned int mmMC_HUB_RDREQ_VMC__VI = 0x0864; +constexpr unsigned int mmMC_HUB_RDREQ_VP8__VI = 0x0884; +constexpr unsigned int mmMC_HUB_RDREQ_VP8U__VI = 0x0885; +constexpr unsigned int mmMC_HUB_RDREQ_XDMAM__VI = 0x0880; +constexpr unsigned int mmMC_HUB_WDP_ACPG__VI = 0x0885; +constexpr unsigned int mmMC_HUB_WDP_ACPO__VI = 0x0886; +constexpr unsigned int mmMC_HUB_WDP_BP2__VI = 0x0DFB; +constexpr unsigned int mmMC_HUB_WDP_BYPASS_GBL0__VI = 0x084A; +constexpr unsigned int mmMC_HUB_WDP_BYPASS_GBL1__VI = 0x084B; +constexpr unsigned int mmMC_HUB_WDP_CREDITS2__VI = 0x0840; +constexpr unsigned int mmMC_HUB_WDP_CREDITS3__VI = 0x0843; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDS__VI = 0x0DF7; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDT__VI = 0x0DF8; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDU__VI = 0x0DF9; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDV__VI = 0x0DFA; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDW__VI = 0x0DF3; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDX__VI = 0x0DF4; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDY__VI = 0x0DF5; +constexpr unsigned int mmMC_HUB_WDP_CREDITS_MCDZ__VI = 0x0DF6; +constexpr unsigned int mmMC_HUB_WDP_HDP__VI = 0x0877; +constexpr unsigned int mmMC_HUB_WDP_IH__VI = 0x0870; +constexpr unsigned int mmMC_HUB_WDP_ISP_CCPU__VI = 0x0DE6; +constexpr unsigned int mmMC_HUB_WDP_ISP_MPM__VI = 0x0DE5; +constexpr unsigned int mmMC_HUB_WDP_ISP_MPS__VI = 0x0DE4; +constexpr unsigned int mmMC_HUB_WDP_ISP_SPM__VI = 0x0DE3; +constexpr unsigned int mmMC_HUB_WDP_MCDS__VI = 0x0DEB; +constexpr unsigned int mmMC_HUB_WDP_MCDT__VI = 0x0DEC; +constexpr unsigned int mmMC_HUB_WDP_MCDU__VI = 0x0DED; +constexpr unsigned int mmMC_HUB_WDP_MCDV__VI = 0x0DEE; +constexpr unsigned int mmMC_HUB_WDP_MCDW__VI = 0x0866; +constexpr unsigned int mmMC_HUB_WDP_MCDX__VI = 0x0867; +constexpr unsigned int mmMC_HUB_WDP_MCDY__VI = 0x0868; +constexpr unsigned int mmMC_HUB_WDP_MCDZ__VI = 0x0869; +constexpr unsigned int mmMC_HUB_WDP_MCIF__VI = 0x086D; +constexpr unsigned int mmMC_HUB_WDP_RLC__VI = 0x0871; +constexpr unsigned int mmMC_HUB_WDP_SAMMSP__VI = 0x0887; +constexpr unsigned int mmMC_HUB_WDP_SDMA0__VI = 0x0878; +constexpr unsigned int mmMC_HUB_WDP_SDMA1__VI = 0x086B; +constexpr unsigned int mmMC_HUB_WDP_SEM__VI = 0x0872; +constexpr unsigned int mmMC_HUB_WDP_SH0__VI = 0x086C; +constexpr unsigned int mmMC_HUB_WDP_SH1__VI = 0x0874; +constexpr unsigned int mmMC_HUB_WDP_SIP__VI = 0x086A; +constexpr unsigned int mmMC_HUB_WDP_SMU__VI = 0x0873; +constexpr unsigned int mmMC_HUB_WDP_UMC__VI = 0x0875; +constexpr unsigned int mmMC_HUB_WDP_UVD__VI = 0x0876; +constexpr unsigned int mmMC_HUB_WDP_VCE0__VI = 0x086E; +constexpr unsigned int mmMC_HUB_WDP_VCE1__VI = 0x0DFE; +constexpr unsigned int mmMC_HUB_WDP_VCEU0__VI = 0x087D; +constexpr unsigned int mmMC_HUB_WDP_VCEU1__VI = 0x0DFF; +constexpr unsigned int mmMC_HUB_WDP_VIN0__VI = 0x0850; +constexpr unsigned int mmMC_HUB_WDP_VP8__VI = 0x0888; +constexpr unsigned int mmMC_HUB_WDP_VP8U__VI = 0x088A; +constexpr unsigned int mmMC_HUB_WDP_XDMA__VI = 0x087F; +constexpr unsigned int mmMC_HUB_WDP_XDMAM__VI = 0x087E; +constexpr unsigned int mmMC_HUB_WDP_XDP__VI = 0x086F; +constexpr unsigned int mmMC_HUB_WRRET_MCDS__VI = 0x0DEF; +constexpr unsigned int mmMC_HUB_WRRET_MCDT__VI = 0x0DF0; +constexpr unsigned int mmMC_HUB_WRRET_MCDU__VI = 0x0DF1; +constexpr unsigned int mmMC_HUB_WRRET_MCDV__VI = 0x0DF2; +constexpr unsigned int mmMC_HUB_WRRET_MCDW__VI = 0x0879; +constexpr unsigned int mmMC_HUB_WRRET_MCDX__VI = 0x087A; +constexpr unsigned int mmMC_HUB_WRRET_MCDY__VI = 0x087B; +constexpr unsigned int mmMC_HUB_WRRET_MCDZ__VI = 0x087C; +constexpr unsigned int mmMC_PMG_CFG__SI__CI = 0x0A84; +constexpr unsigned int mmMC_PMG_CFG__VI = 0x0A54; +constexpr unsigned int mmMC_PMG_CMD_EMRS__SI__CI = 0x0A83; +constexpr unsigned int mmMC_PMG_CMD_EMRS__VI = 0x0A4A; +constexpr unsigned int mmMC_PMG_CMD_MRS__SI__CI = 0x0AAB; +constexpr unsigned int mmMC_PMG_CMD_MRS__VI = 0x0A4C; +constexpr unsigned int mmMC_PMG_CMD_MRS1__SI__CI = 0x0AD1; +constexpr unsigned int mmMC_PMG_CMD_MRS1__VI = 0x0A4E; +constexpr unsigned int mmMC_PMG_CMD_MRS2__SI__CI = 0x0AD7; +constexpr unsigned int mmMC_PMG_CMD_MRS2__VI = 0x0A50; +constexpr unsigned int mmMC_RPB_TCI_CNTL__VI = 0x095C; +constexpr unsigned int mmMC_RPB_TCI_CNTL2__VI = 0x095D; +constexpr unsigned int mmMC_SEQ_CAS_TIMING__SI__CI = 0x0A29; +constexpr unsigned int mmMC_SEQ_CAS_TIMING__VI = 0x0A2B; +constexpr unsigned int mmMC_SEQ_CAS_TIMING_LP__SI__CI = 0x0A9C; +constexpr unsigned int mmMC_SEQ_CAS_TIMING_LP__VI = 0x0A2C; +constexpr unsigned int mmMC_SEQ_CG__SI__CI = 0x0A9A; +constexpr unsigned int mmMC_SEQ_CG__VI = 0x0A7B; +constexpr unsigned int mmMC_SEQ_CMD__SI__CI = 0x0A31; +constexpr unsigned int mmMC_SEQ_CMD__VI = 0x0A47; +constexpr unsigned int mmMC_SEQ_CNTL__SI__CI = 0x0A25; +constexpr unsigned int mmMC_SEQ_CNTL__VI = 0x0A24; +constexpr unsigned int mmMC_SEQ_CNTL_2__SI__CI = 0x0AD4; +constexpr unsigned int mmMC_SEQ_CNTL_2__VI = 0x0A25; +constexpr unsigned int mmMC_SEQ_CNTL_3__VI = 0x0A26; +constexpr unsigned int mmMC_SEQ_DRAM__SI__CI = 0x0A26; +constexpr unsigned int mmMC_SEQ_DRAM__VI = 0x0A27; +constexpr unsigned int mmMC_SEQ_DRAM_2__SI__CI = 0x0A27; +constexpr unsigned int mmMC_SEQ_DRAM_2__VI = 0x0A28; +constexpr unsigned int mmMC_SEQ_FIFO_CTL__SI__CI = 0x0A57; +constexpr unsigned int mmMC_SEQ_FIFO_CTL__VI = 0x0A5D; +constexpr unsigned int mmMC_SEQ_IO_DEBUG_DATA__SI__CI = 0x0A92; +constexpr unsigned int mmMC_SEQ_IO_DEBUG_DATA__VI = 0x0ABD; +constexpr unsigned int mmMC_SEQ_IO_DEBUG_INDEX__SI__CI = 0x0A91; +constexpr unsigned int mmMC_SEQ_IO_DEBUG_INDEX__VI = 0x0ABC; +constexpr unsigned int mmMC_SEQ_IO_RESERVE__VI = 0x0A61; +constexpr unsigned int mmMC_SEQ_MISC0__SI__CI = 0x0A80; +constexpr unsigned int mmMC_SEQ_MISC0__VI = 0x0A71; +constexpr unsigned int mmMC_SEQ_MISC1__SI__CI = 0x0A81; +constexpr unsigned int mmMC_SEQ_MISC1__VI = 0x0A72; +constexpr unsigned int mmMC_SEQ_MISC3__SI__CI = 0x0A8B; +constexpr unsigned int mmMC_SEQ_MISC3__VI = 0x0A74; +constexpr unsigned int mmMC_SEQ_MISC4__SI__CI = 0x0A8C; +constexpr unsigned int mmMC_SEQ_MISC4__VI = 0x0A75; +constexpr unsigned int mmMC_SEQ_MISC5__SI__CI = 0x0A95; +constexpr unsigned int mmMC_SEQ_MISC5__VI = 0x0A76; +constexpr unsigned int mmMC_SEQ_MISC6__SI__CI = 0x0A96; +constexpr unsigned int mmMC_SEQ_MISC6__VI = 0x0A77; +constexpr unsigned int mmMC_SEQ_MISC7__SI__CI = 0x0A99; +constexpr unsigned int mmMC_SEQ_MISC7__VI = 0x0A78; +constexpr unsigned int mmMC_SEQ_MISC8__SI__CI = 0x0A5F; +constexpr unsigned int mmMC_SEQ_MISC8__VI = 0x0A79; +constexpr unsigned int mmMC_SEQ_MISC9__SI__CI = 0x0AE7; +constexpr unsigned int mmMC_SEQ_MISC9__VI = 0x0A7A; +constexpr unsigned int mmMC_SEQ_MISC_TIMING__SI__CI = 0x0A2A; +constexpr unsigned int mmMC_SEQ_MISC_TIMING__VI = 0x0A2D; +constexpr unsigned int mmMC_SEQ_MISC_TIMING2__SI__CI = 0x0A2B; +constexpr unsigned int mmMC_SEQ_MISC_TIMING2__VI = 0x0A2F; +constexpr unsigned int mmMC_SEQ_MISC_TIMING2_LP__SI__CI = 0x0A9E; +constexpr unsigned int mmMC_SEQ_MISC_TIMING2_LP__VI = 0x0A30; +constexpr unsigned int mmMC_SEQ_MISC_TIMING_LP__SI__CI = 0x0A9D; +constexpr unsigned int mmMC_SEQ_MISC_TIMING_LP__VI = 0x0A2E; +constexpr unsigned int mmMC_SEQ_PMG_TIMING__SI__CI = 0x0A2C; +constexpr unsigned int mmMC_SEQ_PMG_TIMING__VI = 0x0A31; +constexpr unsigned int mmMC_SEQ_PMG_TIMING_LP__SI__CI = 0x0AD3; +constexpr unsigned int mmMC_SEQ_PMG_TIMING_LP__VI = 0x0A32; +constexpr unsigned int mmMC_SEQ_RAS_TIMING__SI__CI = 0x0A28; +constexpr unsigned int mmMC_SEQ_RAS_TIMING__VI = 0x0A29; +constexpr unsigned int mmMC_SEQ_RAS_TIMING_LP__SI__CI = 0x0A9B; +constexpr unsigned int mmMC_SEQ_RAS_TIMING_LP__VI = 0x0A2A; +constexpr unsigned int mmMC_SEQ_RD_CTL_D0__SI__CI = 0x0A2D; +constexpr unsigned int mmMC_SEQ_RD_CTL_D0__VI = 0x0A33; +constexpr unsigned int mmMC_SEQ_RD_CTL_D0_LP__SI__CI = 0x0AC7; +constexpr unsigned int mmMC_SEQ_RD_CTL_D0_LP__VI = 0x0A34; +constexpr unsigned int mmMC_SEQ_RD_CTL_D1__SI__CI = 0x0A2E; +constexpr unsigned int mmMC_SEQ_RD_CTL_D1__VI = 0x0A35; +constexpr unsigned int mmMC_SEQ_RD_CTL_D1_LP__SI__CI = 0x0AC8; +constexpr unsigned int mmMC_SEQ_RD_CTL_D1_LP__VI = 0x0A36; +constexpr unsigned int mmMC_SEQ_RESERVE_0_S__SI__CI = 0x0A1E; +constexpr unsigned int mmMC_SEQ_RESERVE_0_S__VI = 0x0A07; +constexpr unsigned int mmMC_SEQ_RESERVE_1_S__SI__CI = 0x0A1F; +constexpr unsigned int mmMC_SEQ_RESERVE_1_S__VI = 0x0A08; +constexpr unsigned int mmMC_SEQ_RESERVE_M__SI__CI = 0x0A82; +constexpr unsigned int mmMC_SEQ_RESERVE_M__VI = 0x0A60; +constexpr unsigned int mmMC_SEQ_SREG_READ__VI = 0x0A7F; +constexpr unsigned int mmMC_SEQ_SREG_STATUS__VI = 0x0A80; +constexpr unsigned int mmMC_SEQ_STATUS_M__SI__CI = 0x0A7D; +constexpr unsigned int mmMC_SEQ_STATUS_M__VI = 0x0A5E; +constexpr unsigned int mmMC_SEQ_STATUS_S__SI__CI = 0x0A20; +constexpr unsigned int mmMC_SEQ_STATUS_S__VI = 0x0A05; +constexpr unsigned int mmMC_SEQ_SUP_CNTL__SI__CI = 0x0A32; +constexpr unsigned int mmMC_SEQ_SUP_CNTL__VI = 0x0A63; +constexpr unsigned int mmMC_SEQ_SUP_DEC_STAT__SI__CI = 0x0A88; +constexpr unsigned int mmMC_SEQ_SUP_DEC_STAT__VI = 0x0A6A; +constexpr unsigned int mmMC_SEQ_SUP_GP0_STAT__SI__CI = 0x0A8F; +constexpr unsigned int mmMC_SEQ_SUP_GP0_STAT__VI = 0x0A65; +constexpr unsigned int mmMC_SEQ_SUP_GP1_STAT__SI__CI = 0x0A90; +constexpr unsigned int mmMC_SEQ_SUP_GP1_STAT__VI = 0x0A66; +constexpr unsigned int mmMC_SEQ_SUP_GP2_STAT__SI__CI = 0x0A85; +constexpr unsigned int mmMC_SEQ_SUP_GP2_STAT__VI = 0x0A67; +constexpr unsigned int mmMC_SEQ_SUP_GP3_STAT__SI__CI = 0x0A86; +constexpr unsigned int mmMC_SEQ_SUP_GP3_STAT__VI = 0x0A68; +constexpr unsigned int mmMC_SEQ_SUP_IR_STAT__SI__CI = 0x0A87; +constexpr unsigned int mmMC_SEQ_SUP_IR_STAT__VI = 0x0A69; +constexpr unsigned int mmMC_SEQ_SUP_PGM__SI__CI = 0x0A33; +constexpr unsigned int mmMC_SEQ_SUP_PGM__VI = 0x0A64; +constexpr unsigned int mmMC_SEQ_SUP_PGM_STAT__SI__CI = 0x0A89; +constexpr unsigned int mmMC_SEQ_SUP_PGM_STAT__VI = 0x0A6B; +constexpr unsigned int mmMC_SEQ_SUP_R_PGM__SI__CI = 0x0A8A; +constexpr unsigned int mmMC_SEQ_SUP_R_PGM__VI = 0x0A6C; +constexpr unsigned int mmMC_SEQ_TIMER_RD__SI__CI = 0x0ACA; +constexpr unsigned int mmMC_SEQ_TIMER_RD__VI = 0x0A7D; +constexpr unsigned int mmMC_SEQ_TIMER_WR__SI__CI = 0x0AC9; +constexpr unsigned int mmMC_SEQ_TIMER_WR__VI = 0x0A7C; +constexpr unsigned int mmMC_SEQ_TRAIN_CAPTURE__SI__CI = 0x0A3E; +constexpr unsigned int mmMC_SEQ_TRAIN_CAPTURE__VI = 0x0A5B; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_CLEAR__SI__CI = 0x0A3F; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_CLEAR__VI = 0x0A5C; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_CNTL__SI__CI = 0x0A3A; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_CNTL__VI = 0x0A57; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_EDGE__SI__CI = 0x0A3C; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_EDGE__VI = 0x0A58; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_MASK__SI__CI = 0x0A3D; +constexpr unsigned int mmMC_SEQ_TRAIN_WAKEUP_MASK__VI = 0x0A59; +constexpr unsigned int mmMC_SEQ_WR_CTL_D0__SI__CI = 0x0A2F; +constexpr unsigned int mmMC_SEQ_WR_CTL_D0__VI = 0x0A3B; +constexpr unsigned int mmMC_SEQ_WR_CTL_D0_LP__SI__CI = 0x0A9F; +constexpr unsigned int mmMC_SEQ_WR_CTL_D0_LP__VI = 0x0A3C; +constexpr unsigned int mmMC_SEQ_WR_CTL_D1__SI__CI = 0x0A30; +constexpr unsigned int mmMC_SEQ_WR_CTL_D1__VI = 0x0A3D; +constexpr unsigned int mmMC_SEQ_WR_CTL_D1_LP__SI__CI = 0x0AA0; +constexpr unsigned int mmMC_SEQ_WR_CTL_D1_LP__VI = 0x0A3E; +constexpr unsigned int mmMC_SHARED_ACTIVE_FCN_ID__VI = 0x081F; +constexpr unsigned int mmMC_SHARED_CHREMAP2__VI = 0x081C; +constexpr unsigned int mmMC_SHARED_VF_ENABLE__VI = 0x081D; +constexpr unsigned int mmMC_SHARED_VIRT_RESET_REQ__VI = 0x081E; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF0__VI = 0xF980; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF1__VI = 0xF981; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF10__VI = 0xF98A; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF11__VI = 0xF98B; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF12__VI = 0xF98C; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF13__VI = 0xF98D; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF14__VI = 0xF98E; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF15__VI = 0xF98F; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF2__VI = 0xF982; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF3__VI = 0xF983; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF4__VI = 0xF984; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF5__VI = 0xF985; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF6__VI = 0xF986; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF7__VI = 0xF987; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF8__VI = 0xF988; +constexpr unsigned int mmMC_VM_FB_SIZE_OFFSET_VF9__VI = 0xF989; +constexpr unsigned int mmMC_VM_MARC_BASE_HI_0__VI = 0xF999; +constexpr unsigned int mmMC_VM_MARC_BASE_HI_1__VI = 0xF99F; +constexpr unsigned int mmMC_VM_MARC_BASE_HI_2__VI = 0xF9A5; +constexpr unsigned int mmMC_VM_MARC_BASE_HI_3__VI = 0xF9AB; +constexpr unsigned int mmMC_VM_MARC_BASE_LO_0__VI = 0xF998; +constexpr unsigned int mmMC_VM_MARC_BASE_LO_1__VI = 0xF99E; +constexpr unsigned int mmMC_VM_MARC_BASE_LO_2__VI = 0xF9A4; +constexpr unsigned int mmMC_VM_MARC_BASE_LO_3__VI = 0xF9AA; +constexpr unsigned int mmMC_VM_MARC_CNTL__VI = 0xF9B0; +constexpr unsigned int mmMC_VM_MARC_LEN_HI_0__VI = 0xF99D; +constexpr unsigned int mmMC_VM_MARC_LEN_HI_1__VI = 0xF9A3; +constexpr unsigned int mmMC_VM_MARC_LEN_HI_2__VI = 0xF9A9; +constexpr unsigned int mmMC_VM_MARC_LEN_HI_3__VI = 0xF9AF; +constexpr unsigned int mmMC_VM_MARC_LEN_LO_0__VI = 0xF99C; +constexpr unsigned int mmMC_VM_MARC_LEN_LO_1__VI = 0xF9A2; +constexpr unsigned int mmMC_VM_MARC_LEN_LO_2__VI = 0xF9A8; +constexpr unsigned int mmMC_VM_MARC_LEN_LO_3__VI = 0xF9AE; +constexpr unsigned int mmMC_VM_MARC_RELOC_HI_0__VI = 0xF99B; +constexpr unsigned int mmMC_VM_MARC_RELOC_HI_1__VI = 0xF9A1; +constexpr unsigned int mmMC_VM_MARC_RELOC_HI_2__VI = 0xF9A7; +constexpr unsigned int mmMC_VM_MARC_RELOC_HI_3__VI = 0xF9AD; +constexpr unsigned int mmMC_VM_MARC_RELOC_LO_0__VI = 0xF99A; +constexpr unsigned int mmMC_VM_MARC_RELOC_LO_1__VI = 0xF9A0; +constexpr unsigned int mmMC_VM_MARC_RELOC_LO_2__VI = 0xF9A6; +constexpr unsigned int mmMC_VM_MARC_RELOC_LO_3__VI = 0xF9AC; +constexpr unsigned int mmMC_VM_MB_L1_TLB1_DEBUG__VI = 0x0892; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL0__VI = 0xF9B1; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL1__VI = 0xF9B4; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL2__VI = 0xF9B7; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL3__VI = 0xF9BA; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL4__VI = 0xF9BD; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL5__VI = 0xF9C0; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL6__VI = 0xF9C3; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL7__VI = 0xF9C6; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_CNTL8__VI = 0xF9C9; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR0__VI = 0xF9B3; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR1__VI = 0xF9B6; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR2__VI = 0xF9B9; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR3__VI = 0xF9BC; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR4__VI = 0xF9BF; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR5__VI = 0xF9C2; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR6__VI = 0xF9C5; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR7__VI = 0xF9C8; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_END_ADDR8__VI = 0xF9CB; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_PROTECTION_FAULT_ADDR__VI = 0xF9CD; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_PROTECTION_FAULT_STATUS__VI = 0xF9CC; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR0__VI = 0xF9B2; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR1__VI = 0xF9B5; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR2__VI = 0xF9B8; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR3__VI = 0xF9BB; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR4__VI = 0xF9BE; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR5__VI = 0xF9C1; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR6__VI = 0xF9C4; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR7__VI = 0xF9C7; +constexpr unsigned int mmMC_VM_MB_L1_TLS0_START_ADDR8__VI = 0xF9CA; +constexpr unsigned int mmMC_VM_NB_LOWER_TOP_OF_DRAM2__VI = 0xF995; +constexpr unsigned int mmMC_VM_NB_MMIOBASE__VI = 0xF990; +constexpr unsigned int mmMC_VM_NB_MMIOLIMIT__VI = 0xF991; +constexpr unsigned int mmMC_VM_NB_PCI_ARB__VI = 0xF993; +constexpr unsigned int mmMC_VM_NB_PCI_CTRL__VI = 0xF992; +constexpr unsigned int mmMC_VM_NB_TOP_OF_DRAM3__VI = 0xF997; +constexpr unsigned int mmMC_VM_NB_TOP_OF_DRAM_SLOT1__VI = 0xF994; +constexpr unsigned int mmMC_VM_NB_UPPER_TOP_OF_DRAM2__VI = 0xF996; +constexpr unsigned int mmMC_XBAR_FIFO_MON_CNTL0__VI = 0x0C8F; +constexpr unsigned int mmMC_XBAR_FIFO_MON_CNTL1__VI = 0x0C90; +constexpr unsigned int mmMC_XBAR_FIFO_MON_CNTL2__VI = 0x0C91; +constexpr unsigned int mmMC_XBAR_FIFO_MON_MAX_THSH__VI = 0x0C96; +constexpr unsigned int mmMC_XBAR_FIFO_MON_RSLT0__VI = 0x0C92; +constexpr unsigned int mmMC_XBAR_FIFO_MON_RSLT1__VI = 0x0C93; +constexpr unsigned int mmMC_XBAR_FIFO_MON_RSLT2__VI = 0x0C94; +constexpr unsigned int mmMC_XBAR_FIFO_MON_RSLT3__VI = 0x0C95; +constexpr unsigned int mmMICROSECOND_TIME_BASE_DIV__VI = 0x013B; +constexpr unsigned int mmMILLISECOND_TIME_BASE_DIV__VI = 0x0130; +constexpr unsigned int mmMP_FPS_CNT__VI = 0x0235; +constexpr unsigned int mmMVP_AFR_FLIP_FIFO_CNTL__VI = 0x1AE1; +constexpr unsigned int mmMVP_AFR_FLIP_MODE__VI = 0x1AE0; +constexpr unsigned int mmMVP_BLACK_KEYER__VI = 0x02B2; +constexpr unsigned int mmMVP_CONTROL1__VI = 0x02AC; +constexpr unsigned int mmMVP_CONTROL2__VI = 0x02AD; +constexpr unsigned int mmMVP_CONTROL3__VI = 0x02B6; +constexpr unsigned int mmMVP_CRC_CNTL__VI = 0x02B3; +constexpr unsigned int mmMVP_CRC_RESULT_BLUE_GREEN__VI = 0x02B4; +constexpr unsigned int mmMVP_CRC_RESULT_RED__VI = 0x02B5; +constexpr unsigned int mmMVP_DEBUG__VI = 0x02BB; +constexpr unsigned int mmMVP_FIFO_CONTROL__VI = 0x02AE; +constexpr unsigned int mmMVP_FIFO_STATUS__VI = 0x02AF; +constexpr unsigned int mmMVP_FLIP_LINE_NUM_INSERT__VI = 0x1AE2; +constexpr unsigned int mmMVP_INBAND_CNTL_CAP__VI = 0x02B1; +constexpr unsigned int mmMVP_RECEIVE_CNT_CNTL1__VI = 0x02B7; +constexpr unsigned int mmMVP_RECEIVE_CNT_CNTL2__VI = 0x02B8; +constexpr unsigned int mmMVP_SLAVE_STATUS__VI = 0x02B0; +constexpr unsigned int mmMVP_TEST_DEBUG_DATA__VI = 0x02BA; +constexpr unsigned int mmMVP_TEST_DEBUG_INDEX__VI = 0x02B9; +constexpr unsigned int mmOUTPUT_CSC_C11_C12__VI = 0x1A3D; +constexpr unsigned int mmOUTPUT_CSC_C11_C12_A__VI = 0x46B7; +constexpr unsigned int mmOUTPUT_CSC_C11_C12_B__VI = 0x46BD; +constexpr unsigned int mmOUTPUT_CSC_C13_C14__VI = 0x1A3E; +constexpr unsigned int mmOUTPUT_CSC_C13_C14_A__VI = 0x46B8; +constexpr unsigned int mmOUTPUT_CSC_C13_C14_B__VI = 0x46BE; +constexpr unsigned int mmOUTPUT_CSC_C21_C22__VI = 0x1A3F; +constexpr unsigned int mmOUTPUT_CSC_C21_C22_A__VI = 0x46B9; +constexpr unsigned int mmOUTPUT_CSC_C21_C22_B__VI = 0x46BF; +constexpr unsigned int mmOUTPUT_CSC_C23_C24__VI = 0x1A40; +constexpr unsigned int mmOUTPUT_CSC_C23_C24_A__VI = 0x46BA; +constexpr unsigned int mmOUTPUT_CSC_C23_C24_B__VI = 0x46C0; +constexpr unsigned int mmOUTPUT_CSC_C31_C32__VI = 0x1A41; +constexpr unsigned int mmOUTPUT_CSC_C31_C32_A__VI = 0x46BB; +constexpr unsigned int mmOUTPUT_CSC_C31_C32_B__VI = 0x46C1; +constexpr unsigned int mmOUTPUT_CSC_C33_C34__VI = 0x1A42; +constexpr unsigned int mmOUTPUT_CSC_C33_C34_A__VI = 0x46BC; +constexpr unsigned int mmOUTPUT_CSC_C33_C34_B__VI = 0x46C2; +constexpr unsigned int mmOUTPUT_CSC_CONTROL__VI = 0x1A3C; +constexpr unsigned int mmOUT_CLAMP_CONTROL_B_CB__VI = 0x1A9D; +constexpr unsigned int mmOUT_CLAMP_CONTROL_G_Y__VI = 0x1A9C; +constexpr unsigned int mmOUT_CLAMP_CONTROL_R_CR__VI = 0x1A52; +constexpr unsigned int mmOUT_ROUND_CONTROL__VI = 0x1A51; +constexpr unsigned int mmOVL_SECONDARY_SURFACE_ADDRESS__VI = 0x1A92; +constexpr unsigned int mmOVL_SECONDARY_SURFACE_ADDRESS_HIGH__VI = 0x1A94; +constexpr unsigned int mmOVL_STEREOSYNC_FLIP__VI = 0x1A93; +constexpr unsigned int mmPCIE_EFUSE__VI = 0x0FC0; +constexpr unsigned int mmPCIE_EFUSE2__VI = 0x0FC1; +constexpr unsigned int mmPCIE_EFUSE3__VI = 0x0FC2; +constexpr unsigned int mmPCIE_EFUSE4__VI = 0x0FC3; +constexpr unsigned int mmPCIE_EFUSE5__VI = 0x0FC4; +constexpr unsigned int mmPCIE_EFUSE6__VI = 0x0FC5; +constexpr unsigned int mmPCIE_EFUSE7__VI = 0x0FC6; +constexpr unsigned int mmPERFCOUNTER_CNTL__VI = 0x0170; +constexpr unsigned int mmPERFCOUNTER_STATE__VI = 0x0171; +constexpr unsigned int mmPERFMON_CNTL__VI = 0x0173; +constexpr unsigned int mmPERFMON_CNTL2__VI = 0x017A; +constexpr unsigned int mmPERFMON_CVALUE_INT_MISC__VI = 0x0172; +constexpr unsigned int mmPERFMON_CVALUE_LOW__VI = 0x0174; +constexpr unsigned int mmPERFMON_HI__VI = 0x0175; +constexpr unsigned int mmPERFMON_LOW__VI = 0x0176; +constexpr unsigned int mmPERFMON_TEST_DEBUG_DATA__VI = 0x0178; +constexpr unsigned int mmPERFMON_TEST_DEBUG_INDEX__VI = 0x0177; +constexpr unsigned int mmPHY_AUX_CNTL__VI = 0x4897; +constexpr unsigned int mmPIPE0_ARBITRATION_CONTROL3__VI = 0x02FA; +constexpr unsigned int mmPIPE0_DMIF_BUFFER_CONTROL__VI = 0x0321; +constexpr unsigned int mmPIPE0_MAX_REQUESTS__VI = 0x0305; +constexpr unsigned int mmPIPE0_PG_CONFIG__VI = 0x02C0; +constexpr unsigned int mmPIPE0_PG_ENABLE__VI = 0x02C1; +constexpr unsigned int mmPIPE0_PG_STATUS__VI = 0x02C2; +constexpr unsigned int mmPIPE1_ARBITRATION_CONTROL3__VI = 0x02FB; +constexpr unsigned int mmPIPE1_DMIF_BUFFER_CONTROL__VI = 0x0322; +constexpr unsigned int mmPIPE1_MAX_REQUESTS__VI = 0x0306; +constexpr unsigned int mmPIPE1_PG_CONFIG__VI = 0x02C3; +constexpr unsigned int mmPIPE1_PG_ENABLE__VI = 0x02C4; +constexpr unsigned int mmPIPE1_PG_STATUS__VI = 0x02C5; +constexpr unsigned int mmPIPE2_ARBITRATION_CONTROL3__VI = 0x02FC; +constexpr unsigned int mmPIPE2_DMIF_BUFFER_CONTROL__VI = 0x0323; +constexpr unsigned int mmPIPE2_MAX_REQUESTS__VI = 0x0307; +constexpr unsigned int mmPIPE2_PG_CONFIG__VI = 0x02C6; +constexpr unsigned int mmPIPE2_PG_ENABLE__VI = 0x02C7; +constexpr unsigned int mmPIPE2_PG_STATUS__VI = 0x02C8; +constexpr unsigned int mmPIPE3_ARBITRATION_CONTROL3__VI = 0x02FD; +constexpr unsigned int mmPIPE3_DMIF_BUFFER_CONTROL__VI = 0x0324; +constexpr unsigned int mmPIPE3_MAX_REQUESTS__VI = 0x0308; +constexpr unsigned int mmPIPE3_PG_CONFIG__VI = 0x02C9; +constexpr unsigned int mmPIPE3_PG_ENABLE__VI = 0x02CA; +constexpr unsigned int mmPIPE3_PG_STATUS__VI = 0x02CB; +constexpr unsigned int mmPIPE4_ARBITRATION_CONTROL3__VI = 0x02FE; +constexpr unsigned int mmPIPE4_DMIF_BUFFER_CONTROL__VI = 0x0325; +constexpr unsigned int mmPIPE4_MAX_REQUESTS__VI = 0x0309; +constexpr unsigned int mmPIPE4_PG_CONFIG__VI = 0x02CC; +constexpr unsigned int mmPIPE4_PG_ENABLE__VI = 0x02CD; +constexpr unsigned int mmPIPE4_PG_STATUS__VI = 0x02CE; +constexpr unsigned int mmPIPE5_ARBITRATION_CONTROL3__VI = 0x02FF; +constexpr unsigned int mmPIPE5_DMIF_BUFFER_CONTROL__VI = 0x0326; +constexpr unsigned int mmPIPE5_MAX_REQUESTS__VI = 0x030A; +constexpr unsigned int mmPIPE5_PG_CONFIG__VI = 0x02CF; +constexpr unsigned int mmPIPE5_PG_ENABLE__VI = 0x02D0; +constexpr unsigned int mmPIPE5_PG_STATUS__VI = 0x02D1; +constexpr unsigned int mmPIPE6_ARBITRATION_CONTROL3__VI = 0x032A; +constexpr unsigned int mmPIPE6_MAX_REQUESTS__VI = 0x032C; +constexpr unsigned int mmPIPE7_ARBITRATION_CONTROL3__VI = 0x032B; +constexpr unsigned int mmPIPE7_MAX_REQUESTS__VI = 0x032D; +constexpr unsigned int mmPIXCLK0_RESYNC_CNTL__VI = 0x013A; +constexpr unsigned int mmPIXCLK1_RESYNC_CNTL__VI = 0x0138; +constexpr unsigned int mmPIXCLK2_RESYNC_CNTL__VI = 0x0139; +constexpr unsigned int mmPLL_ANALOG__VI = 0x1708; +constexpr unsigned int mmPLL_ANALOG_CNTL__VI = 0x1711; +constexpr unsigned int mmPLL_CNTL__VI = 0x1707; +constexpr unsigned int mmPLL_DEBUG_CNTL__VI = 0x170B; +constexpr unsigned int mmPLL_DS_CNTL__VI = 0x1705; +constexpr unsigned int mmPLL_FB_DIV__VI = 0x1701; +constexpr unsigned int mmPLL_IDCLK_CNTL__VI = 0x1706; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED0__VI = 0x1700; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED1__VI = 0x1701; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED10__VI = 0x170A; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED11__VI = 0x170B; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED12__VI = 0x170C; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED13__VI = 0x170D; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED14__VI = 0x170E; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED15__VI = 0x170F; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED16__VI = 0x1710; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED17__VI = 0x1711; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED18__VI = 0x1712; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED19__VI = 0x1713; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED2__VI = 0x1702; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED20__VI = 0x1714; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED21__VI = 0x1715; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED22__VI = 0x1716; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED23__VI = 0x1717; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED24__VI = 0x1718; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED25__VI = 0x1719; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED26__VI = 0x171A; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED27__VI = 0x171B; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED28__VI = 0x171C; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED29__VI = 0x171D; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED3__VI = 0x1703; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED30__VI = 0x171E; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED31__VI = 0x171F; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED32__VI = 0x1720; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED33__VI = 0x1721; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED34__VI = 0x1722; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED35__VI = 0x1723; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED36__VI = 0x1724; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED37__VI = 0x1725; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED38__VI = 0x1726; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED39__VI = 0x1727; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED4__VI = 0x1704; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED40__VI = 0x1728; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED41__VI = 0x1729; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED5__VI = 0x1705; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED6__VI = 0x1706; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED7__VI = 0x1707; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED8__VI = 0x1708; +constexpr unsigned int mmPLL_MACRO_CNTL_RESERVED9__VI = 0x1709; +constexpr unsigned int mmPLL_POST_DIV__VI = 0x1702; +constexpr unsigned int mmPLL_REF_DIV__VI = 0x1700; +constexpr unsigned int mmPLL_SS_AMOUNT_DSFRAC__VI = 0x1703; +constexpr unsigned int mmPLL_SS_CNTL__VI = 0x1704; +constexpr unsigned int mmPLL_UNLOCK_DETECT_CNTL__VI = 0x170A; +constexpr unsigned int mmPLL_UPDATE_CNTL__VI = 0x170D; +constexpr unsigned int mmPLL_UPDATE_LOCK__VI = 0x170C; +constexpr unsigned int mmPLL_VREG_CNTL__VI = 0x1709; +constexpr unsigned int mmPLL_XOR_LOCK__VI = 0x1710; +constexpr unsigned int mmPPLL_DEBUG_MUX_CNTL__VI = 0x1721; +constexpr unsigned int mmPPLL_DIV_UPDATE_DEBUG__VI = 0x171F; +constexpr unsigned int mmPPLL_SPARE0__VI = 0x1722; +constexpr unsigned int mmPPLL_SPARE1__VI = 0x1723; +constexpr unsigned int mmPPLL_STATUS_DEBUG__VI = 0x1720; +constexpr unsigned int mmPRESCALE_CONTROL__VI = 0x46B2; +constexpr unsigned int mmPRESCALE_GRPH_CONTROL__VI = 0x1A2D; +constexpr unsigned int mmPRESCALE_OVL_CONTROL__VI = 0x1A31; +constexpr unsigned int mmPRESCALE_VALUES_B__VI = 0x46B5; +constexpr unsigned int mmPRESCALE_VALUES_G__VI = 0x46B4; +constexpr unsigned int mmPRESCALE_VALUES_GRPH_B__VI = 0x1A30; +constexpr unsigned int mmPRESCALE_VALUES_GRPH_G__VI = 0x1A2F; +constexpr unsigned int mmPRESCALE_VALUES_GRPH_R__VI = 0x1A2E; +constexpr unsigned int mmPRESCALE_VALUES_OVL_CB__VI = 0x1A32; +constexpr unsigned int mmPRESCALE_VALUES_OVL_CR__VI = 0x1A34; +constexpr unsigned int mmPRESCALE_VALUES_OVL_Y__VI = 0x1A33; +constexpr unsigned int mmPRESCALE_VALUES_R__VI = 0x46B3; +constexpr unsigned int mmRAS_TA_SIGNATURE1__VI = 0x33A0; +constexpr unsigned int mmRBBMIF_STATUS__VI = 0x0315; +constexpr unsigned int mmRBBMIF_STATUS_FLAG__VI = 0x0327; +constexpr unsigned int mmRBBMIF_TIMEOUT__VI = 0x0314; +constexpr unsigned int mmRBBMIF_TIMEOUT_DIS__VI = 0x0316; +constexpr unsigned int mmREFCLK_CGTT_BLK_CTRL_REG__VI = 0x010B; +constexpr unsigned int mmREFCLK_CNTL__VI = 0x0109; +constexpr unsigned int mmREGAMMA_CNTLA_END_CNTL1__VI = 0x1AA6; +constexpr unsigned int mmREGAMMA_CNTLA_END_CNTL2__VI = 0x1AA7; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_0_1__VI = 0x1AA8; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_10_11__VI = 0x1AAD; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_12_13__VI = 0x1AAE; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_14_15__VI = 0x1AAF; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_2_3__VI = 0x1AA9; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_4_5__VI = 0x1AAA; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_6_7__VI = 0x1AAB; +constexpr unsigned int mmREGAMMA_CNTLA_REGION_8_9__VI = 0x1AAC; +constexpr unsigned int mmREGAMMA_CNTLA_SLOPE_CNTL__VI = 0x1AA5; +constexpr unsigned int mmREGAMMA_CNTLA_START_CNTL__VI = 0x1AA4; +constexpr unsigned int mmREGAMMA_CNTLB_END_CNTL1__VI = 0x1AB2; +constexpr unsigned int mmREGAMMA_CNTLB_END_CNTL2__VI = 0x1AB3; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_0_1__VI = 0x1AB4; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_10_11__VI = 0x1AB9; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_12_13__VI = 0x1ABA; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_14_15__VI = 0x1ABB; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_2_3__VI = 0x1AB5; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_4_5__VI = 0x1AB6; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_6_7__VI = 0x1AB7; +constexpr unsigned int mmREGAMMA_CNTLB_REGION_8_9__VI = 0x1AB8; +constexpr unsigned int mmREGAMMA_CNTLB_SLOPE_CNTL__VI = 0x1AB1; +constexpr unsigned int mmREGAMMA_CNTLB_START_CNTL__VI = 0x1AB0; +constexpr unsigned int mmREGAMMA_CONTROL__VI = 0x1AA0; +constexpr unsigned int mmREGAMMA_LUT_DATA__VI = 0x1AA2; +constexpr unsigned int mmREGAMMA_LUT_INDEX__VI = 0x1AA1; +constexpr unsigned int mmREGAMMA_LUT_WRITE_EN_MASK__VI = 0x1AA3; +constexpr unsigned int mmREMAP_HDP_MEM_FLUSH_CNTL__VI = 0x1426; +constexpr unsigned int mmREMAP_HDP_REG_FLUSH_CNTL__VI = 0x1427; +constexpr unsigned int mmRLC_AUTO_PG_CTRL__VI = 0xEC55; +constexpr unsigned int mmRLC_CAPTURE_GPU_CLOCK_COUNT__VI = 0xEC26; +constexpr unsigned int mmRLC_CGCG_CGLS_CTRL__VI = 0xEC49; +constexpr unsigned int mmRLC_CGCG_RAMP_CTRL__VI = 0xEC4A; +constexpr unsigned int mmRLC_CGTT_MGCG_OVERRIDE__VI = 0xEC48; +constexpr unsigned int mmRLC_CNTL__SI__CI = 0x30C0; +constexpr unsigned int mmRLC_CNTL__VI = 0xEC00; +constexpr unsigned int mmRLC_CP_RESPONSE0__VI = 0xECA5; +constexpr unsigned int mmRLC_CP_RESPONSE1__VI = 0xECA6; +constexpr unsigned int mmRLC_CP_RESPONSE2__VI = 0xECA7; +constexpr unsigned int mmRLC_CP_RESPONSE3__VI = 0xECA8; +constexpr unsigned int mmRLC_CP_SCHEDULERS__VI = 0xECAA; +constexpr unsigned int mmRLC_CSIB_ADDR_HI__VI = 0xECA3; +constexpr unsigned int mmRLC_CSIB_ADDR_LO__VI = 0xECA2; +constexpr unsigned int mmRLC_CSIB_LENGTH__VI = 0xECA4; +constexpr unsigned int mmRLC_CU_STATUS__VI = 0xEC4E; +constexpr unsigned int mmRLC_DEBUG__VI = 0xEC02; +constexpr unsigned int mmRLC_DEBUG_SELECT__VI = 0xEC01; +constexpr unsigned int mmRLC_DRIVER_CPDMA_STATUS__VI = 0xEC1E; +constexpr unsigned int mmRLC_DYN_PG_REQUEST__VI = 0xEC4C; +constexpr unsigned int mmRLC_DYN_PG_STATUS__VI = 0xEC4B; +constexpr unsigned int mmRLC_GPM_CU_PD_TIMEOUT__VI = 0xEC6B; +constexpr unsigned int mmRLC_GPM_DEBUG__VI = 0xEC21; +constexpr unsigned int mmRLC_GPM_DEBUG_SELECT__VI = 0xEC20; +constexpr unsigned int mmRLC_GPM_GENERAL_0__VI = 0xEC63; +constexpr unsigned int mmRLC_GPM_GENERAL_1__VI = 0xEC64; +constexpr unsigned int mmRLC_GPM_GENERAL_2__VI = 0xEC65; +constexpr unsigned int mmRLC_GPM_GENERAL_3__VI = 0xEC66; +constexpr unsigned int mmRLC_GPM_GENERAL_4__VI = 0xEC67; +constexpr unsigned int mmRLC_GPM_GENERAL_5__VI = 0xEC68; +constexpr unsigned int mmRLC_GPM_GENERAL_6__VI = 0xEC69; +constexpr unsigned int mmRLC_GPM_GENERAL_7__VI = 0xEC6A; +constexpr unsigned int mmRLC_GPM_INT_DISABLE_TH0__VI = 0xEC7C; +constexpr unsigned int mmRLC_GPM_INT_DISABLE_TH1__VI = 0xEC7D; +constexpr unsigned int mmRLC_GPM_INT_FORCE_TH0__VI = 0xEC7E; +constexpr unsigned int mmRLC_GPM_INT_FORCE_TH1__VI = 0xEC7F; +constexpr unsigned int mmRLC_GPM_LOG_ADDR__VI = 0xEC76; +constexpr unsigned int mmRLC_GPM_LOG_CONT__VI = 0xEC7B; +constexpr unsigned int mmRLC_GPM_LOG_SIZE__VI = 0xEC77; +constexpr unsigned int mmRLC_GPM_PERF_COUNT_0__VI = 0xEC6F; +constexpr unsigned int mmRLC_GPM_PERF_COUNT_1__VI = 0xEC70; +constexpr unsigned int mmRLC_GPM_SCRATCH_ADDR__VI = 0xEC6C; +constexpr unsigned int mmRLC_GPM_SCRATCH_DATA__VI = 0xEC6D; +constexpr unsigned int mmRLC_GPM_STAT__VI = 0xEC40; +constexpr unsigned int mmRLC_GPM_THREAD_ENABLE__VI = 0xEC45; +constexpr unsigned int mmRLC_GPM_THREAD_PRIORITY__VI = 0xEC44; +constexpr unsigned int mmRLC_GPM_THREAD_RESET__VI = 0xEC28; +constexpr unsigned int mmRLC_GPM_UCODE_ADDR__VI = 0xF83C; +constexpr unsigned int mmRLC_GPM_UCODE_DATA__VI = 0xF83D; +constexpr unsigned int mmRLC_GPM_VMID_THREAD0__VI = 0xEC46; +constexpr unsigned int mmRLC_GPM_VMID_THREAD1__VI = 0xEC47; +constexpr unsigned int mmRLC_GPM_VMID_THREAD2__VI = 0xFB41; +constexpr unsigned int mmRLC_GPR_REG1__VI = 0xEC79; +constexpr unsigned int mmRLC_GPR_REG2__VI = 0xEC7A; +constexpr unsigned int mmRLC_GPU_CLOCK_32__VI = 0xEC42; +constexpr unsigned int mmRLC_GPU_CLOCK_32_RES_SEL__VI = 0xEC41; +constexpr unsigned int mmRLC_GPU_CLOCK_COUNT_LSB__VI = 0xEC24; +constexpr unsigned int mmRLC_GPU_CLOCK_COUNT_MSB__VI = 0xEC25; +constexpr unsigned int mmRLC_GPU_IOV_ACTIVE_FCN_ID__VI = 0xFB40; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG1__VI = 0xFB01; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG10__VI = 0xFB22; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG11__VI = 0xFB23; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG12__VI = 0xFB24; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG13__VI = 0xFB25; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG14__VI = 0xFB26; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG15__VI = 0xFB27; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG2__VI = 0xFB02; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG6__VI = 0xFB06; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG8__VI = 0xFB08; +constexpr unsigned int mmRLC_GPU_IOV_CFG_REG9__VI = 0xFB21; +constexpr unsigned int mmRLC_GPU_IOV_F32_CNTL__VI = 0xFB46; +constexpr unsigned int mmRLC_GPU_IOV_F32_RESET__VI = 0xFB47; +constexpr unsigned int mmRLC_GPU_IOV_INT_DISABLE__VI = 0xFB4E; +constexpr unsigned int mmRLC_GPU_IOV_INT_FORCE__VI = 0xFB4F; +constexpr unsigned int mmRLC_GPU_IOV_RLC_RESPONSE__VI = 0xFB4D; +constexpr unsigned int mmRLC_GPU_IOV_SCH_0__VI = 0xFB52; +constexpr unsigned int mmRLC_GPU_IOV_SCH_1__VI = 0xFB53; +constexpr unsigned int mmRLC_GPU_IOV_SCH_2__VI = 0xFB54; +constexpr unsigned int mmRLC_GPU_IOV_SCH_3__VI = 0xFB55; +constexpr unsigned int mmRLC_GPU_IOV_SCH_INT__VI = 0xFB56; +constexpr unsigned int mmRLC_GPU_IOV_SCRATCH_ADDR__VI = 0xFB44; +constexpr unsigned int mmRLC_GPU_IOV_SCRATCH_DATA__VI = 0xFB45; +constexpr unsigned int mmRLC_GPU_IOV_SDMA0_BUSY_STATUS__VI = 0xFB50; +constexpr unsigned int mmRLC_GPU_IOV_SDMA0_STATUS__VI = 0xFB48; +constexpr unsigned int mmRLC_GPU_IOV_SDMA1_BUSY_STATUS__VI = 0xFB51; +constexpr unsigned int mmRLC_GPU_IOV_SDMA1_STATUS__VI = 0xFB49; +constexpr unsigned int mmRLC_GPU_IOV_SMU_RESPONSE__VI = 0xFB4A; +constexpr unsigned int mmRLC_GPU_IOV_UCODE_ADDR__VI = 0xFB42; +constexpr unsigned int mmRLC_GPU_IOV_UCODE_DATA__VI = 0xFB43; +constexpr unsigned int mmRLC_GPU_IOV_VF_ENABLE__VI = 0xFB00; +constexpr unsigned int mmRLC_GPU_IOV_VIRT_RESET_REQ__VI = 0xFB4C; +constexpr unsigned int mmRLC_HYP_GPM_UCODE_ADDR__VI = 0xF83C; +constexpr unsigned int mmRLC_HYP_GPM_UCODE_DATA__VI = 0xF83D; +constexpr unsigned int mmRLC_JUMP_TABLE_RESTORE__VI = 0xEC1E; +constexpr unsigned int mmRLC_LB_ALWAYS_ACTIVE_CU_MASK__VI = 0xEC50; +constexpr unsigned int mmRLC_LB_CNTL__VI = 0xEC19; +constexpr unsigned int mmRLC_LB_CNTR_INIT__VI = 0xEC1B; +constexpr unsigned int mmRLC_LB_CNTR_MAX__VI = 0xEC12; +constexpr unsigned int mmRLC_LB_INIT_CU_MASK__VI = 0xEC4F; +constexpr unsigned int mmRLC_LB_PARAMS__VI = 0xEC51; +constexpr unsigned int mmRLC_LOAD_BALANCE_CNTR__VI = 0xEC1C; +constexpr unsigned int mmRLC_MAX_PG_CU__VI = 0xEC54; +constexpr unsigned int mmRLC_MC_CNTL__VI = 0xEC03; +constexpr unsigned int mmRLC_MEM_SLP_CNTL__VI = 0xEC06; +constexpr unsigned int mmRLC_MGCG_CTRL__VI = 0xEC1A; +constexpr unsigned int mmRLC_PERFMON_CLK_CNTL__VI = 0xDCBF; +constexpr unsigned int mmRLC_PG_ALWAYS_ON_CU_MASK__VI = 0xEC53; +constexpr unsigned int mmRLC_PG_CNTL__VI = 0xEC43; +constexpr unsigned int mmRLC_PG_DELAY__VI = 0xEC4D; +constexpr unsigned int mmRLC_PG_DELAY_2__VI = 0xEC1F; +constexpr unsigned int mmRLC_PG_DELAY_3__VI = 0xEC78; +constexpr unsigned int mmRLC_RLCV_COMMAND__VI = 0xEC0A; +constexpr unsigned int mmRLC_RLCV_SAFE_MODE__VI = 0xEC08; +constexpr unsigned int mmRLC_ROM_CNTL__VI = 0xF836; +constexpr unsigned int mmRLC_SAFE_MODE__VI = 0xEC05; +constexpr unsigned int mmRLC_SAVE_AND_RESTORE_BASE__VI = 0xEC1D; +constexpr unsigned int mmRLC_SERDES_CU_MASTER_BUSY__VI = 0xEC61; +constexpr unsigned int mmRLC_SERDES_NONCU_MASTER_BUSY__VI = 0xEC62; +constexpr unsigned int mmRLC_SERDES_RD_DATA_0__VI = 0xEC5A; +constexpr unsigned int mmRLC_SERDES_RD_DATA_1__VI = 0xEC5B; +constexpr unsigned int mmRLC_SERDES_RD_DATA_2__VI = 0xEC5C; +constexpr unsigned int mmRLC_SERDES_RD_MASTER_INDEX__VI = 0xEC59; +constexpr unsigned int mmRLC_SERDES_WR_CTRL__VI = 0xEC5F; +constexpr unsigned int mmRLC_SERDES_WR_CU_MASTER_MASK__VI = 0xEC5D; +constexpr unsigned int mmRLC_SERDES_WR_DATA__VI = 0xEC60; +constexpr unsigned int mmRLC_SERDES_WR_NONCU_MASTER_MASK__VI = 0xEC5E; +constexpr unsigned int mmRLC_SMU_COMMAND__VI = 0xECA9; +constexpr unsigned int mmRLC_SMU_GRBM_REG_SAVE_CTRL__VI = 0xEC56; +constexpr unsigned int mmRLC_SMU_MESSAGE__VI = 0xEC76; +constexpr unsigned int mmRLC_SMU_PG_CTRL__VI = 0xEC57; +constexpr unsigned int mmRLC_SMU_PG_WAKE_UP_CTRL__VI = 0xEC58; +constexpr unsigned int mmRLC_SMU_SAFE_MODE__VI = 0xEC09; +constexpr unsigned int mmRLC_SOFT_RESET_GPU__VI = 0xEC05; +constexpr unsigned int mmRLC_SPM_CBR0_PERFMON_SAMPLE_DELAY__VI = 0xDCA1; +constexpr unsigned int mmRLC_SPM_CBR1_PERFMON_SAMPLE_DELAY__VI = 0xDCA2; +constexpr unsigned int mmRLC_SPM_DBR0_PERFMON_SAMPLE_DELAY__VI = 0xDC9F; +constexpr unsigned int mmRLC_SPM_DBR1_PERFMON_SAMPLE_DELAY__VI = 0xDCA0; +constexpr unsigned int mmRLC_SPM_DEBUG__VI = 0xEC75; +constexpr unsigned int mmRLC_SPM_DEBUG_SELECT__VI = 0xEC74; +constexpr unsigned int mmRLC_SPM_INT_CNTL__VI = 0xEC72; +constexpr unsigned int mmRLC_SPM_INT_STATUS__VI = 0xEC73; +constexpr unsigned int mmRLC_SPM_VMID__VI = 0xEC71; +constexpr unsigned int mmRLC_SRM_ARAM_ADDR__VI = 0xEC83; +constexpr unsigned int mmRLC_SRM_ARAM_DATA__VI = 0xEC84; +constexpr unsigned int mmRLC_SRM_CNTL__VI = 0xEC80; +constexpr unsigned int mmRLC_SRM_DEBUG__VI = 0xEC82; +constexpr unsigned int mmRLC_SRM_DEBUG_SELECT__VI = 0xEC81; +constexpr unsigned int mmRLC_SRM_DRAM_ADDR__VI = 0xEC85; +constexpr unsigned int mmRLC_SRM_DRAM_DATA__VI = 0xEC86; +constexpr unsigned int mmRLC_SRM_GPM_ABORT__VI = 0xEC9C; +constexpr unsigned int mmRLC_SRM_GPM_COMMAND__VI = 0xEC87; +constexpr unsigned int mmRLC_SRM_GPM_COMMAND_STATUS__VI = 0xEC88; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_0__VI = 0xEC8B; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_1__VI = 0xEC8C; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_2__VI = 0xEC8D; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_3__VI = 0xEC8E; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_4__VI = 0xEC8F; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_5__VI = 0xEC90; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_6__VI = 0xEC91; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_ADDR_7__VI = 0xEC92; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_0__VI = 0xEC93; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_1__VI = 0xEC94; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_2__VI = 0xEC95; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_3__VI = 0xEC96; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_4__VI = 0xEC97; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_5__VI = 0xEC98; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_6__VI = 0xEC99; +constexpr unsigned int mmRLC_SRM_INDEX_CNTL_DATA_7__VI = 0xEC9A; +constexpr unsigned int mmRLC_SRM_RLCV_COMMAND__VI = 0xEC89; +constexpr unsigned int mmRLC_SRM_RLCV_COMMAND_STATUS__VI = 0xEC8A; +constexpr unsigned int mmRLC_SRM_STAT__VI = 0xEC9B; +constexpr unsigned int mmRLC_STAT__VI = 0xEC04; +constexpr unsigned int mmRLC_STATIC_PG_STATUS__VI = 0xEC6E; +constexpr unsigned int mmRLC_THREAD1_DELAY__VI = 0xEC52; +constexpr unsigned int mmRLC_UCODE_CNTL__VI = 0xEC27; +constexpr unsigned int mmSAM_IH_EXT_ERR_INTR__VI = 0x8810; +constexpr unsigned int mmSAM_IH_EXT_ERR_INTR_STATUS__VI = 0x8812; +constexpr unsigned int mmSCL0_SCL_DEBUG2__VI = 0x1B69; +constexpr unsigned int mmSCL0_SCL_HORZ_FILTER_CONTROL__VI = 0x1B48; +constexpr unsigned int mmSCL0_SCL_HORZ_FILTER_INIT__VI = 0x1B4A; +constexpr unsigned int mmSCL0_SCL_HORZ_FILTER_SCALE_RATIO__VI = 0x1B49; +constexpr unsigned int mmSCL0_SCL_MODE__VI = 0x1B42; +constexpr unsigned int mmSCL0_SCL_ROUND_OFFSET__VI = 0x1B4F; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_CONTROL__VI = 0x1B4B; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_INIT__VI = 0x1B4D; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_INIT_BOT__VI = 0x1B4E; +constexpr unsigned int mmSCL0_SCL_VERT_FILTER_SCALE_RATIO__VI = 0x1B4C; +constexpr unsigned int mmSCL0_VIEWPORT_START_SECONDARY__VI = 0x1B5B; +constexpr unsigned int mmSCL1_EXT_OVERSCAN_LEFT_RIGHT__VI = 0x1D5E; +constexpr unsigned int mmSCL1_EXT_OVERSCAN_TOP_BOTTOM__VI = 0x1D5F; +constexpr unsigned int mmSCL1_SCL_ALU_CONTROL__VI = 0x1D54; +constexpr unsigned int mmSCL1_SCL_AUTOMATIC_MODE_CONTROL__VI = 0x1D47; +constexpr unsigned int mmSCL1_SCL_BYPASS_CONTROL__VI = 0x1D45; +constexpr unsigned int mmSCL1_SCL_COEF_RAM_CONFLICT_STATUS__VI = 0x1D55; +constexpr unsigned int mmSCL1_SCL_COEF_RAM_SELECT__VI = 0x1D40; +constexpr unsigned int mmSCL1_SCL_COEF_RAM_TAP_DATA__VI = 0x1D41; +constexpr unsigned int mmSCL1_SCL_CONTROL__VI = 0x1D44; +constexpr unsigned int mmSCL1_SCL_DEBUG__VI = 0x1D6A; +constexpr unsigned int mmSCL1_SCL_DEBUG2__VI = 0x1D69; +constexpr unsigned int mmSCL1_SCL_F_SHARP_CONTROL__VI = 0x1D53; +constexpr unsigned int mmSCL1_SCL_HORZ_FILTER_CONTROL__VI = 0x1D48; +constexpr unsigned int mmSCL1_SCL_HORZ_FILTER_INIT__VI = 0x1D4A; +constexpr unsigned int mmSCL1_SCL_HORZ_FILTER_SCALE_RATIO__VI = 0x1D49; +constexpr unsigned int mmSCL1_SCL_MANUAL_REPLICATE_CONTROL__VI = 0x1D46; +constexpr unsigned int mmSCL1_SCL_MODE__VI = 0x1D42; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_DET1__VI = 0x1D60; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_DET2__VI = 0x1D61; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_DET3__VI = 0x1D62; +constexpr unsigned int mmSCL1_SCL_MODE_CHANGE_MASK__VI = 0x1D63; +constexpr unsigned int mmSCL1_SCL_ROUND_OFFSET__VI = 0x1D4F; +constexpr unsigned int mmSCL1_SCL_TAP_CONTROL__VI = 0x1D43; +constexpr unsigned int mmSCL1_SCL_TEST_DEBUG_DATA__VI = 0x1D6C; +constexpr unsigned int mmSCL1_SCL_TEST_DEBUG_INDEX__VI = 0x1D6B; +constexpr unsigned int mmSCL1_SCL_UPDATE__VI = 0x1D51; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_CONTROL__VI = 0x1D4B; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_INIT__VI = 0x1D4D; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_INIT_BOT__VI = 0x1D4E; +constexpr unsigned int mmSCL1_SCL_VERT_FILTER_SCALE_RATIO__VI = 0x1D4C; +constexpr unsigned int mmSCL1_VIEWPORT_SIZE__VI = 0x1D5D; +constexpr unsigned int mmSCL1_VIEWPORT_START__VI = 0x1D5C; +constexpr unsigned int mmSCL1_VIEWPORT_START_SECONDARY__VI = 0x1D5B; +constexpr unsigned int mmSCL2_EXT_OVERSCAN_LEFT_RIGHT__VI = 0x1F5E; +constexpr unsigned int mmSCL2_EXT_OVERSCAN_TOP_BOTTOM__VI = 0x1F5F; +constexpr unsigned int mmSCL2_SCL_ALU_CONTROL__VI = 0x1F54; +constexpr unsigned int mmSCL2_SCL_AUTOMATIC_MODE_CONTROL__VI = 0x1F47; +constexpr unsigned int mmSCL2_SCL_BYPASS_CONTROL__VI = 0x1F45; +constexpr unsigned int mmSCL2_SCL_COEF_RAM_CONFLICT_STATUS__VI = 0x1F55; +constexpr unsigned int mmSCL2_SCL_COEF_RAM_SELECT__VI = 0x1F40; +constexpr unsigned int mmSCL2_SCL_COEF_RAM_TAP_DATA__VI = 0x1F41; +constexpr unsigned int mmSCL2_SCL_CONTROL__VI = 0x1F44; +constexpr unsigned int mmSCL2_SCL_DEBUG__VI = 0x1F6A; +constexpr unsigned int mmSCL2_SCL_DEBUG2__VI = 0x1F69; +constexpr unsigned int mmSCL2_SCL_F_SHARP_CONTROL__VI = 0x1F53; +constexpr unsigned int mmSCL2_SCL_HORZ_FILTER_CONTROL__VI = 0x1F48; +constexpr unsigned int mmSCL2_SCL_HORZ_FILTER_INIT__VI = 0x1F4A; +constexpr unsigned int mmSCL2_SCL_HORZ_FILTER_SCALE_RATIO__VI = 0x1F49; +constexpr unsigned int mmSCL2_SCL_MANUAL_REPLICATE_CONTROL__VI = 0x1F46; +constexpr unsigned int mmSCL2_SCL_MODE__VI = 0x1F42; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_DET1__VI = 0x1F60; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_DET2__VI = 0x1F61; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_DET3__VI = 0x1F62; +constexpr unsigned int mmSCL2_SCL_MODE_CHANGE_MASK__VI = 0x1F63; +constexpr unsigned int mmSCL2_SCL_ROUND_OFFSET__VI = 0x1F4F; +constexpr unsigned int mmSCL2_SCL_TAP_CONTROL__VI = 0x1F43; +constexpr unsigned int mmSCL2_SCL_TEST_DEBUG_DATA__VI = 0x1F6C; +constexpr unsigned int mmSCL2_SCL_TEST_DEBUG_INDEX__VI = 0x1F6B; +constexpr unsigned int mmSCL2_SCL_UPDATE__VI = 0x1F51; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_CONTROL__VI = 0x1F4B; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_INIT__VI = 0x1F4D; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_INIT_BOT__VI = 0x1F4E; +constexpr unsigned int mmSCL2_SCL_VERT_FILTER_SCALE_RATIO__VI = 0x1F4C; +constexpr unsigned int mmSCL2_VIEWPORT_SIZE__VI = 0x1F5D; +constexpr unsigned int mmSCL2_VIEWPORT_START__VI = 0x1F5C; +constexpr unsigned int mmSCL2_VIEWPORT_START_SECONDARY__VI = 0x1F5B; +constexpr unsigned int mmSCL3_EXT_OVERSCAN_LEFT_RIGHT__VI = 0x415E; +constexpr unsigned int mmSCL3_EXT_OVERSCAN_TOP_BOTTOM__VI = 0x415F; +constexpr unsigned int mmSCL3_SCL_ALU_CONTROL__VI = 0x4154; +constexpr unsigned int mmSCL3_SCL_AUTOMATIC_MODE_CONTROL__VI = 0x4147; +constexpr unsigned int mmSCL3_SCL_BYPASS_CONTROL__VI = 0x4145; +constexpr unsigned int mmSCL3_SCL_COEF_RAM_CONFLICT_STATUS__VI = 0x4155; +constexpr unsigned int mmSCL3_SCL_COEF_RAM_SELECT__VI = 0x4140; +constexpr unsigned int mmSCL3_SCL_COEF_RAM_TAP_DATA__VI = 0x4141; +constexpr unsigned int mmSCL3_SCL_CONTROL__VI = 0x4144; +constexpr unsigned int mmSCL3_SCL_DEBUG__VI = 0x416A; +constexpr unsigned int mmSCL3_SCL_DEBUG2__VI = 0x4169; +constexpr unsigned int mmSCL3_SCL_F_SHARP_CONTROL__VI = 0x4153; +constexpr unsigned int mmSCL3_SCL_HORZ_FILTER_CONTROL__VI = 0x4148; +constexpr unsigned int mmSCL3_SCL_HORZ_FILTER_INIT__VI = 0x414A; +constexpr unsigned int mmSCL3_SCL_HORZ_FILTER_SCALE_RATIO__VI = 0x4149; +constexpr unsigned int mmSCL3_SCL_MANUAL_REPLICATE_CONTROL__VI = 0x4146; +constexpr unsigned int mmSCL3_SCL_MODE__VI = 0x4142; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_DET1__VI = 0x4160; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_DET2__VI = 0x4161; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_DET3__VI = 0x4162; +constexpr unsigned int mmSCL3_SCL_MODE_CHANGE_MASK__VI = 0x4163; +constexpr unsigned int mmSCL3_SCL_ROUND_OFFSET__VI = 0x414F; +constexpr unsigned int mmSCL3_SCL_TAP_CONTROL__VI = 0x4143; +constexpr unsigned int mmSCL3_SCL_TEST_DEBUG_DATA__VI = 0x416C; +constexpr unsigned int mmSCL3_SCL_TEST_DEBUG_INDEX__VI = 0x416B; +constexpr unsigned int mmSCL3_SCL_UPDATE__VI = 0x4151; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_CONTROL__VI = 0x414B; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_INIT__VI = 0x414D; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_INIT_BOT__VI = 0x414E; +constexpr unsigned int mmSCL3_SCL_VERT_FILTER_SCALE_RATIO__VI = 0x414C; +constexpr unsigned int mmSCL3_VIEWPORT_SIZE__VI = 0x415D; +constexpr unsigned int mmSCL3_VIEWPORT_START__VI = 0x415C; +constexpr unsigned int mmSCL3_VIEWPORT_START_SECONDARY__VI = 0x415B; +constexpr unsigned int mmSCL4_EXT_OVERSCAN_LEFT_RIGHT__VI = 0x435E; +constexpr unsigned int mmSCL4_EXT_OVERSCAN_TOP_BOTTOM__VI = 0x435F; +constexpr unsigned int mmSCL4_SCL_ALU_CONTROL__VI = 0x4354; +constexpr unsigned int mmSCL4_SCL_AUTOMATIC_MODE_CONTROL__VI = 0x4347; +constexpr unsigned int mmSCL4_SCL_BYPASS_CONTROL__VI = 0x4345; +constexpr unsigned int mmSCL4_SCL_COEF_RAM_CONFLICT_STATUS__VI = 0x4355; +constexpr unsigned int mmSCL4_SCL_COEF_RAM_SELECT__VI = 0x4340; +constexpr unsigned int mmSCL4_SCL_COEF_RAM_TAP_DATA__VI = 0x4341; +constexpr unsigned int mmSCL4_SCL_CONTROL__VI = 0x4344; +constexpr unsigned int mmSCL4_SCL_DEBUG__VI = 0x436A; +constexpr unsigned int mmSCL4_SCL_DEBUG2__VI = 0x4369; +constexpr unsigned int mmSCL4_SCL_F_SHARP_CONTROL__VI = 0x4353; +constexpr unsigned int mmSCL4_SCL_HORZ_FILTER_CONTROL__VI = 0x4348; +constexpr unsigned int mmSCL4_SCL_HORZ_FILTER_INIT__VI = 0x434A; +constexpr unsigned int mmSCL4_SCL_HORZ_FILTER_SCALE_RATIO__VI = 0x4349; +constexpr unsigned int mmSCL4_SCL_MANUAL_REPLICATE_CONTROL__VI = 0x4346; +constexpr unsigned int mmSCL4_SCL_MODE__VI = 0x4342; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_DET1__VI = 0x4360; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_DET2__VI = 0x4361; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_DET3__VI = 0x4362; +constexpr unsigned int mmSCL4_SCL_MODE_CHANGE_MASK__VI = 0x4363; +constexpr unsigned int mmSCL4_SCL_ROUND_OFFSET__VI = 0x434F; +constexpr unsigned int mmSCL4_SCL_TAP_CONTROL__VI = 0x4343; +constexpr unsigned int mmSCL4_SCL_TEST_DEBUG_DATA__VI = 0x436C; +constexpr unsigned int mmSCL4_SCL_TEST_DEBUG_INDEX__VI = 0x436B; +constexpr unsigned int mmSCL4_SCL_UPDATE__VI = 0x4351; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_CONTROL__VI = 0x434B; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_INIT__VI = 0x434D; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_INIT_BOT__VI = 0x434E; +constexpr unsigned int mmSCL4_SCL_VERT_FILTER_SCALE_RATIO__VI = 0x434C; +constexpr unsigned int mmSCL4_VIEWPORT_SIZE__VI = 0x435D; +constexpr unsigned int mmSCL4_VIEWPORT_START__VI = 0x435C; +constexpr unsigned int mmSCL4_VIEWPORT_START_SECONDARY__VI = 0x435B; +constexpr unsigned int mmSCL5_EXT_OVERSCAN_LEFT_RIGHT__VI = 0x455E; +constexpr unsigned int mmSCL5_EXT_OVERSCAN_TOP_BOTTOM__VI = 0x455F; +constexpr unsigned int mmSCL5_SCL_ALU_CONTROL__VI = 0x4554; +constexpr unsigned int mmSCL5_SCL_AUTOMATIC_MODE_CONTROL__VI = 0x4547; +constexpr unsigned int mmSCL5_SCL_BYPASS_CONTROL__VI = 0x4545; +constexpr unsigned int mmSCL5_SCL_COEF_RAM_CONFLICT_STATUS__VI = 0x4555; +constexpr unsigned int mmSCL5_SCL_COEF_RAM_SELECT__VI = 0x4540; +constexpr unsigned int mmSCL5_SCL_COEF_RAM_TAP_DATA__VI = 0x4541; +constexpr unsigned int mmSCL5_SCL_CONTROL__VI = 0x4544; +constexpr unsigned int mmSCL5_SCL_DEBUG__VI = 0x456A; +constexpr unsigned int mmSCL5_SCL_DEBUG2__VI = 0x4569; +constexpr unsigned int mmSCL5_SCL_F_SHARP_CONTROL__VI = 0x4553; +constexpr unsigned int mmSCL5_SCL_HORZ_FILTER_CONTROL__VI = 0x4548; +constexpr unsigned int mmSCL5_SCL_HORZ_FILTER_INIT__VI = 0x454A; +constexpr unsigned int mmSCL5_SCL_HORZ_FILTER_SCALE_RATIO__VI = 0x4549; +constexpr unsigned int mmSCL5_SCL_MANUAL_REPLICATE_CONTROL__VI = 0x4546; +constexpr unsigned int mmSCL5_SCL_MODE__VI = 0x4542; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_DET1__VI = 0x4560; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_DET2__VI = 0x4561; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_DET3__VI = 0x4562; +constexpr unsigned int mmSCL5_SCL_MODE_CHANGE_MASK__VI = 0x4563; +constexpr unsigned int mmSCL5_SCL_ROUND_OFFSET__VI = 0x454F; +constexpr unsigned int mmSCL5_SCL_TAP_CONTROL__VI = 0x4543; +constexpr unsigned int mmSCL5_SCL_TEST_DEBUG_DATA__VI = 0x456C; +constexpr unsigned int mmSCL5_SCL_TEST_DEBUG_INDEX__VI = 0x456B; +constexpr unsigned int mmSCL5_SCL_UPDATE__VI = 0x4551; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_CONTROL__VI = 0x454B; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_INIT__VI = 0x454D; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_INIT_BOT__VI = 0x454E; +constexpr unsigned int mmSCL5_SCL_VERT_FILTER_SCALE_RATIO__VI = 0x454C; +constexpr unsigned int mmSCL5_VIEWPORT_SIZE__VI = 0x455D; +constexpr unsigned int mmSCL5_VIEWPORT_START__VI = 0x455C; +constexpr unsigned int mmSCL5_VIEWPORT_START_SECONDARY__VI = 0x455B; +constexpr unsigned int mmSCLK_CGTT_BLK_CTRL_REG__VI = 0x0136; +constexpr unsigned int mmSCLV_ALU_CONTROL__VI = 0x4685; +constexpr unsigned int mmSCLV_AUTOMATIC_MODE_CONTROL__VI = 0x4676; +constexpr unsigned int mmSCLV_COEF_RAM_SELECT__VI = 0x4670; +constexpr unsigned int mmSCLV_COEF_RAM_TAP_DATA__VI = 0x4671; +constexpr unsigned int mmSCLV_CONTROL__VI = 0x4674; +constexpr unsigned int mmSCLV_DEBUG__VI = 0x4693; +constexpr unsigned int mmSCLV_DEBUG2__VI = 0x4692; +constexpr unsigned int mmSCLV_EXT_OVERSCAN_LEFT_RIGHT__VI = 0x468C; +constexpr unsigned int mmSCLV_EXT_OVERSCAN_TOP_BOTTOM__VI = 0x468D; +constexpr unsigned int mmSCLV_HORZ_FILTER_CONTROL__VI = 0x4677; +constexpr unsigned int mmSCLV_HORZ_FILTER_INIT__VI = 0x4679; +constexpr unsigned int mmSCLV_HORZ_FILTER_INIT_C__VI = 0x467B; +constexpr unsigned int mmSCLV_HORZ_FILTER_SCALE_RATIO__VI = 0x4678; +constexpr unsigned int mmSCLV_HORZ_FILTER_SCALE_RATIO_C__VI = 0x467A; +constexpr unsigned int mmSCLV_MANUAL_REPLICATE_CONTROL__VI = 0x4675; +constexpr unsigned int mmSCLV_MODE__VI = 0x4672; +constexpr unsigned int mmSCLV_MODE_CHANGE_DET1__VI = 0x468E; +constexpr unsigned int mmSCLV_MODE_CHANGE_DET2__VI = 0x468F; +constexpr unsigned int mmSCLV_MODE_CHANGE_DET3__VI = 0x4690; +constexpr unsigned int mmSCLV_MODE_CHANGE_MASK__VI = 0x4691; +constexpr unsigned int mmSCLV_ROUND_OFFSET__VI = 0x4683; +constexpr unsigned int mmSCLV_TAP_CONTROL__VI = 0x4673; +constexpr unsigned int mmSCLV_TEST_DEBUG_DATA__VI = 0x4695; +constexpr unsigned int mmSCLV_TEST_DEBUG_INDEX__VI = 0x4694; +constexpr unsigned int mmSCLV_UPDATE__VI = 0x4684; +constexpr unsigned int mmSCLV_VERT_FILTER_CONTROL__VI = 0x467C; +constexpr unsigned int mmSCLV_VERT_FILTER_INIT__VI = 0x467E; +constexpr unsigned int mmSCLV_VERT_FILTER_INIT_BOT__VI = 0x467F; +constexpr unsigned int mmSCLV_VERT_FILTER_INIT_BOT_C__VI = 0x4682; +constexpr unsigned int mmSCLV_VERT_FILTER_INIT_C__VI = 0x4681; +constexpr unsigned int mmSCLV_VERT_FILTER_SCALE_RATIO__VI = 0x467D; +constexpr unsigned int mmSCLV_VERT_FILTER_SCALE_RATIO_C__VI = 0x4680; +constexpr unsigned int mmSCLV_VIEWPORT_SIZE__VI = 0x4688; +constexpr unsigned int mmSCLV_VIEWPORT_SIZE_C__VI = 0x468B; +constexpr unsigned int mmSCLV_VIEWPORT_START__VI = 0x4686; +constexpr unsigned int mmSCLV_VIEWPORT_START_C__VI = 0x4689; +constexpr unsigned int mmSCLV_VIEWPORT_START_SECONDARY__VI = 0x4687; +constexpr unsigned int mmSCLV_VIEWPORT_START_SECONDARY_C__VI = 0x468A; +constexpr unsigned int mmSCL_DEBUG2__VI = 0x1B69; +constexpr unsigned int mmSCL_HORZ_FILTER_CONTROL__VI = 0x1B48; +constexpr unsigned int mmSCL_HORZ_FILTER_INIT__VI = 0x1B4A; +constexpr unsigned int mmSCL_HORZ_FILTER_SCALE_RATIO__VI = 0x1B49; +constexpr unsigned int mmSCL_MODE__VI = 0x1B42; +constexpr unsigned int mmSCL_ROUND_OFFSET__VI = 0x1B4F; +constexpr unsigned int mmSCL_VERT_FILTER_CONTROL__VI = 0x1B4B; +constexpr unsigned int mmSCL_VERT_FILTER_INIT__VI = 0x1B4D; +constexpr unsigned int mmSCL_VERT_FILTER_INIT_BOT__VI = 0x1B4E; +constexpr unsigned int mmSCL_VERT_FILTER_SCALE_RATIO__VI = 0x1B4C; +constexpr unsigned int mmSDMA0_ACTIVE_FCN_ID__VI = 0x341F; +constexpr unsigned int mmSDMA0_ATOMIC_CNTL__VI = 0x342E; +constexpr unsigned int mmSDMA0_ATOMIC_PREOP_HI__VI = 0x3430; +constexpr unsigned int mmSDMA0_ATOMIC_PREOP_LO__VI = 0x342F; +constexpr unsigned int mmSDMA0_BA_THRESHOLD__VI = 0x342B; +constexpr unsigned int mmSDMA0_CONTEXT_REG_TYPE0__VI = 0x3478; +constexpr unsigned int mmSDMA0_CONTEXT_REG_TYPE1__VI = 0x3479; +constexpr unsigned int mmSDMA0_CONTEXT_REG_TYPE2__VI = 0x347A; +constexpr unsigned int mmSDMA0_EDC_CONFIG__VI = 0x341A; +constexpr unsigned int mmSDMA0_GFX_CSA_ADDR_HI__VI = 0x34AD; +constexpr unsigned int mmSDMA0_GFX_CSA_ADDR_LO__VI = 0x34AC; +constexpr unsigned int mmSDMA0_GFX_DOORBELL__VI = 0x3492; +constexpr unsigned int mmSDMA0_GFX_DOORBELL_LOG__VI = 0x34A9; +constexpr unsigned int mmSDMA0_GFX_DUMMY_REG__VI = 0x34B1; +constexpr unsigned int mmSDMA0_GFX_IB_SUB_REMAIN__VI = 0x34AF; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_CNTL__VI = 0x34C7; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_DATA0__VI = 0x34C1; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_DATA1__VI = 0x34C2; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_DATA2__VI = 0x34C3; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_DATA3__VI = 0x34C4; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_DATA4__VI = 0x34C5; +constexpr unsigned int mmSDMA0_GFX_MIDCMD_DATA5__VI = 0x34C6; +constexpr unsigned int mmSDMA0_GFX_PREEMPT__VI = 0x34B0; +constexpr unsigned int mmSDMA0_GFX_WATERMARK__VI = 0x34AA; +constexpr unsigned int mmSDMA0_ID__VI = 0x342C; +constexpr unsigned int mmSDMA0_PERFCOUNTER0_RESULT__VI = 0x9001; +constexpr unsigned int mmSDMA0_PERFCOUNTER1_RESULT__VI = 0x9002; +constexpr unsigned int mmSDMA0_PERFMON_CNTL__VI = 0x9000; +constexpr unsigned int mmSDMA0_PERF_REG_TYPE0__VI = 0x3477; +constexpr unsigned int mmSDMA0_POWER_CNTL_IDLE__VI = 0x342C; +constexpr unsigned int mmSDMA0_PUB_REG_TYPE0__VI = 0x347C; +constexpr unsigned int mmSDMA0_PUB_REG_TYPE1__VI = 0x347D; +constexpr unsigned int mmSDMA0_RD_BURST_CNTL__VI = 0x340F; +constexpr unsigned int mmSDMA0_RLC0_CSA_ADDR_HI__VI = 0x352D; +constexpr unsigned int mmSDMA0_RLC0_CSA_ADDR_LO__VI = 0x352C; +constexpr unsigned int mmSDMA0_RLC0_DUMMY_REG__VI = 0x3531; +constexpr unsigned int mmSDMA0_RLC0_IB_SUB_REMAIN__VI = 0x352F; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_CNTL__VI = 0x3547; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_DATA0__VI = 0x3541; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_DATA1__VI = 0x3542; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_DATA2__VI = 0x3543; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_DATA3__VI = 0x3544; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_DATA4__VI = 0x3545; +constexpr unsigned int mmSDMA0_RLC0_MIDCMD_DATA5__VI = 0x3546; +constexpr unsigned int mmSDMA0_RLC0_PREEMPT__VI = 0x3530; +constexpr unsigned int mmSDMA0_RLC0_WATERMARK__VI = 0x352A; +constexpr unsigned int mmSDMA0_RLC1_CSA_ADDR_HI__VI = 0x35AD; +constexpr unsigned int mmSDMA0_RLC1_CSA_ADDR_LO__VI = 0x35AC; +constexpr unsigned int mmSDMA0_RLC1_DUMMY_REG__VI = 0x35B1; +constexpr unsigned int mmSDMA0_RLC1_IB_SUB_REMAIN__VI = 0x35AF; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_CNTL__VI = 0x35C7; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_DATA0__VI = 0x35C1; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_DATA1__VI = 0x35C2; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_DATA2__VI = 0x35C3; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_DATA3__VI = 0x35C4; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_DATA4__VI = 0x35C5; +constexpr unsigned int mmSDMA0_RLC1_MIDCMD_DATA5__VI = 0x35C6; +constexpr unsigned int mmSDMA0_RLC1_PREEMPT__VI = 0x35B0; +constexpr unsigned int mmSDMA0_RLC1_WATERMARK__VI = 0x35AA; +constexpr unsigned int mmSDMA0_STATUS2_REG__VI = 0x341E; +constexpr unsigned int mmSDMA0_VERSION__VI = 0x342D; +constexpr unsigned int mmSDMA0_VF_ENABLE__VI = 0x342A; +constexpr unsigned int mmSDMA0_VIRT_RESET_REQ__VI = 0x3421; +constexpr unsigned int mmSDMA0_VM_CNTL__VI = 0x341B; +constexpr unsigned int mmSDMA0_VM_CTX_CNTL__VI = 0x3420; +constexpr unsigned int mmSDMA0_VM_CTX_HI__VI = 0x341D; +constexpr unsigned int mmSDMA0_VM_CTX_LO__VI = 0x341C; +constexpr unsigned int mmSDMA1_ACTIVE_FCN_ID__VI = 0x361F; +constexpr unsigned int mmSDMA1_ATOMIC_CNTL__VI = 0x362E; +constexpr unsigned int mmSDMA1_ATOMIC_PREOP_HI__VI = 0x3630; +constexpr unsigned int mmSDMA1_ATOMIC_PREOP_LO__VI = 0x362F; +constexpr unsigned int mmSDMA1_BA_THRESHOLD__VI = 0x362B; +constexpr unsigned int mmSDMA1_CONTEXT_REG_TYPE0__VI = 0x3678; +constexpr unsigned int mmSDMA1_CONTEXT_REG_TYPE1__VI = 0x3679; +constexpr unsigned int mmSDMA1_CONTEXT_REG_TYPE2__VI = 0x367A; +constexpr unsigned int mmSDMA1_EDC_CONFIG__VI = 0x361A; +constexpr unsigned int mmSDMA1_GFX_CSA_ADDR_HI__VI = 0x36AD; +constexpr unsigned int mmSDMA1_GFX_CSA_ADDR_LO__VI = 0x36AC; +constexpr unsigned int mmSDMA1_GFX_DOORBELL__VI = 0x3692; +constexpr unsigned int mmSDMA1_GFX_DOORBELL_LOG__VI = 0x36A9; +constexpr unsigned int mmSDMA1_GFX_DUMMY_REG__VI = 0x36B1; +constexpr unsigned int mmSDMA1_GFX_IB_SUB_REMAIN__VI = 0x36AF; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_CNTL__VI = 0x36C7; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_DATA0__VI = 0x36C1; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_DATA1__VI = 0x36C2; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_DATA2__VI = 0x36C3; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_DATA3__VI = 0x36C4; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_DATA4__VI = 0x36C5; +constexpr unsigned int mmSDMA1_GFX_MIDCMD_DATA5__VI = 0x36C6; +constexpr unsigned int mmSDMA1_GFX_PREEMPT__VI = 0x36B0; +constexpr unsigned int mmSDMA1_GFX_WATERMARK__VI = 0x36AA; +constexpr unsigned int mmSDMA1_ID__VI = 0x362C; +constexpr unsigned int mmSDMA1_PERFCOUNTER0_RESULT__VI = 0x9011; +constexpr unsigned int mmSDMA1_PERFCOUNTER1_RESULT__VI = 0x9012; +constexpr unsigned int mmSDMA1_PERFMON_CNTL__VI = 0x9010; +constexpr unsigned int mmSDMA1_PERF_REG_TYPE0__VI = 0x3677; +constexpr unsigned int mmSDMA1_POWER_CNTL_IDLE__VI = 0x362C; +constexpr unsigned int mmSDMA1_PUB_REG_TYPE0__VI = 0x367C; +constexpr unsigned int mmSDMA1_PUB_REG_TYPE1__VI = 0x367D; +constexpr unsigned int mmSDMA1_RD_BURST_CNTL__VI = 0x360F; +constexpr unsigned int mmSDMA1_RLC0_CSA_ADDR_HI__VI = 0x372D; +constexpr unsigned int mmSDMA1_RLC0_CSA_ADDR_LO__VI = 0x372C; +constexpr unsigned int mmSDMA1_RLC0_DUMMY_REG__VI = 0x3731; +constexpr unsigned int mmSDMA1_RLC0_IB_SUB_REMAIN__VI = 0x372F; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_CNTL__VI = 0x3747; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_DATA0__VI = 0x3741; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_DATA1__VI = 0x3742; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_DATA2__VI = 0x3743; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_DATA3__VI = 0x3744; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_DATA4__VI = 0x3745; +constexpr unsigned int mmSDMA1_RLC0_MIDCMD_DATA5__VI = 0x3746; +constexpr unsigned int mmSDMA1_RLC0_PREEMPT__VI = 0x3730; +constexpr unsigned int mmSDMA1_RLC0_WATERMARK__VI = 0x372A; +constexpr unsigned int mmSDMA1_RLC1_CSA_ADDR_HI__VI = 0x37AD; +constexpr unsigned int mmSDMA1_RLC1_CSA_ADDR_LO__VI = 0x37AC; +constexpr unsigned int mmSDMA1_RLC1_DUMMY_REG__VI = 0x37B1; +constexpr unsigned int mmSDMA1_RLC1_IB_SUB_REMAIN__VI = 0x37AF; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_CNTL__VI = 0x37C7; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_DATA0__VI = 0x37C1; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_DATA1__VI = 0x37C2; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_DATA2__VI = 0x37C3; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_DATA3__VI = 0x37C4; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_DATA4__VI = 0x37C5; +constexpr unsigned int mmSDMA1_RLC1_MIDCMD_DATA5__VI = 0x37C6; +constexpr unsigned int mmSDMA1_RLC1_PREEMPT__VI = 0x37B0; +constexpr unsigned int mmSDMA1_RLC1_WATERMARK__VI = 0x37AA; +constexpr unsigned int mmSDMA1_STATUS2_REG__VI = 0x361E; +constexpr unsigned int mmSDMA1_VERSION__VI = 0x362D; +constexpr unsigned int mmSDMA1_VF_ENABLE__VI = 0x362A; +constexpr unsigned int mmSDMA1_VIRT_RESET_REQ__VI = 0x3621; +constexpr unsigned int mmSDMA1_VM_CNTL__VI = 0x361B; +constexpr unsigned int mmSDMA1_VM_CTX_CNTL__VI = 0x3620; +constexpr unsigned int mmSDMA1_VM_CTX_HI__VI = 0x361D; +constexpr unsigned int mmSDMA1_VM_CTX_LO__VI = 0x361C; +constexpr unsigned int mmSEM_ACTIVE_FCN_ID__VI = 0x0F97; +constexpr unsigned int mmSEM_MAILBOX_CLIENTCONFIG_EXTRA__VI = 0x0F9F; +constexpr unsigned int mmSEM_PERFCOUNTER0_RESULT__VI = 0x0F92; +constexpr unsigned int mmSEM_PERFCOUNTER1_RESULT__VI = 0x0F93; +constexpr unsigned int mmSEM_PERFMON_CNTL__VI = 0x0F91; +constexpr unsigned int mmSEM_VF_ENABLE__VI = 0x0F95; +constexpr unsigned int mmSEM_VIRT_RESET_REQ__VI = 0x0F98; +constexpr unsigned int mmSE_CAC_CGTT_CLK_CTRL__VI = 0x3293; +constexpr unsigned int mmSMBCLK_PAD_CNTL__VI = 0x15ED; +constexpr unsigned int mmSMBDAT_PAD_CNTL__VI = 0x15EC; +constexpr unsigned int mmSMBUS_BACO_DUMMY__VI = 0x15EB; +constexpr unsigned int mmSMC_MSG_ARG_11__VI = 0x0093; +constexpr unsigned int mmSMU_BIF_VDDGFX_PWR_STATUS__VI = 0x14F8; +constexpr unsigned int mmSMU_CONTROL__VI = 0x012D; +constexpr unsigned int mmSMU_IND_DATA_0__VI = 0x01A7; +constexpr unsigned int mmSMU_IND_DATA_1__VI = 0x01A9; +constexpr unsigned int mmSMU_IND_DATA_2__VI = 0x01AB; +constexpr unsigned int mmSMU_IND_DATA_3__VI = 0x01AD; +constexpr unsigned int mmSMU_IND_DATA_4__VI = 0x01AF; +constexpr unsigned int mmSMU_IND_DATA_5__VI = 0x01B1; +constexpr unsigned int mmSMU_IND_DATA_6__VI = 0x01B3; +constexpr unsigned int mmSMU_IND_DATA_7__VI = 0x01B5; +constexpr unsigned int mmSMU_IND_INDEX_0__VI = 0x01A6; +constexpr unsigned int mmSMU_IND_INDEX_1__VI = 0x01A8; +constexpr unsigned int mmSMU_IND_INDEX_2__VI = 0x01AA; +constexpr unsigned int mmSMU_IND_INDEX_3__VI = 0x01AC; +constexpr unsigned int mmSMU_IND_INDEX_4__VI = 0x01AE; +constexpr unsigned int mmSMU_IND_INDEX_5__VI = 0x01B0; +constexpr unsigned int mmSMU_IND_INDEX_6__VI = 0x01B2; +constexpr unsigned int mmSMU_IND_INDEX_7__VI = 0x01B4; +constexpr unsigned int mmSMU_INTERRUPT_CONTROL__VI = 0x012E; +constexpr unsigned int mmSMU_MP1_RLC2MP_RESP__VI = 0x01F4; +constexpr unsigned int mmSMU_MP1_SRBM2P_MSG_5__VI = 0x01C5; +constexpr unsigned int mmSMU_RLC_RESPONSE__VI = 0xEC07; +constexpr unsigned int mmSM_CONTROL2__VI = 0x1B6E; +constexpr unsigned int mmSPI_COMPUTE_WF_CTX_SAVE__VI = 0x31FC; +constexpr unsigned int mmSPI_CONFIG_CNTL_2__VI = 0x2451; +constexpr unsigned int mmSPI_DSM_CNTL__VI = 0x2443; +constexpr unsigned int mmSPI_EDC_CNT__VI = 0x2444; +constexpr unsigned int mmSPI_GFX_CNTL__VI = 0x243C; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_12__VI = 0x31F4; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_13__VI = 0x31F5; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_14__VI = 0x31F6; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_CU_15__VI = 0x31F7; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_12__VI = 0x31F8; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_13__VI = 0x31F9; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_14__VI = 0x31FA; +constexpr unsigned int mmSPI_RESOURCE_RESERVE_EN_CU_15__VI = 0x31FB; +constexpr unsigned int mmSPI_START_PHASE__VI = 0x243B; +constexpr unsigned int mmSQC_ATC_EDC_GATCL1_CNT__VI = 0x23B3; +constexpr unsigned int mmSQC_DSM_CNTL__VI = 0x230F; +constexpr unsigned int mmSQC_EDC_CNT__VI = 0x23A0; +constexpr unsigned int mmSQC_GATCL1_CNTL__VI = 0x23B2; +constexpr unsigned int mmSQC_WRITEBACK__VI = 0xC349; +constexpr unsigned int mmSQ_DSM_CNTL__VI = 0x2306; +constexpr unsigned int mmSQ_EDC_DED_CNT__VI = 0x23A2; +constexpr unsigned int mmSQ_EDC_INFO__VI = 0x23A3; +constexpr unsigned int mmSQ_EDC_SEC_CNT__VI = 0x23A1; +constexpr unsigned int mmSQ_M0_GPR_IDX_WORD__VI = 0x23D2; +constexpr unsigned int mmSQ_SMEM_0__VI = 0x237F; +constexpr unsigned int mmSQ_SMEM_1__VI = 0x237F; +constexpr unsigned int mmSQ_THREAD_TRACE_BASE__SI__CI = 0x2380; +constexpr unsigned int mmSQ_THREAD_TRACE_BASE__VI = 0xC330; +constexpr unsigned int mmSQ_THREAD_TRACE_BASE2__VI = 0xC337; +constexpr unsigned int mmSQ_THREAD_TRACE_CTRL__SI__CI = 0x238F; +constexpr unsigned int mmSQ_THREAD_TRACE_CTRL__VI = 0xC335; +constexpr unsigned int mmSQ_THREAD_TRACE_HIWATER__SI__CI = 0x2392; +constexpr unsigned int mmSQ_THREAD_TRACE_HIWATER__VI = 0xC33B; +constexpr unsigned int mmSQ_THREAD_TRACE_MASK__SI__CI = 0x2382; +constexpr unsigned int mmSQ_THREAD_TRACE_MASK__VI = 0xC332; +constexpr unsigned int mmSQ_THREAD_TRACE_MODE__SI__CI = 0x238E; +constexpr unsigned int mmSQ_THREAD_TRACE_MODE__VI = 0xC336; +constexpr unsigned int mmSQ_THREAD_TRACE_PERF_MASK__SI__CI = 0x2384; +constexpr unsigned int mmSQ_THREAD_TRACE_PERF_MASK__VI = 0xC334; +constexpr unsigned int mmSQ_THREAD_TRACE_SIZE__SI__CI = 0x2381; +constexpr unsigned int mmSQ_THREAD_TRACE_SIZE__VI = 0xC331; +constexpr unsigned int mmSQ_THREAD_TRACE_STATUS__SI__CI = 0x238D; +constexpr unsigned int mmSQ_THREAD_TRACE_STATUS__VI = 0xC33A; +constexpr unsigned int mmSQ_THREAD_TRACE_TOKEN_MASK__SI__CI = 0x2383; +constexpr unsigned int mmSQ_THREAD_TRACE_TOKEN_MASK__VI = 0xC333; +constexpr unsigned int mmSQ_THREAD_TRACE_TOKEN_MASK2__VI = 0xC338; +constexpr unsigned int mmSQ_THREAD_TRACE_WPTR__SI__CI = 0x238C; +constexpr unsigned int mmSQ_THREAD_TRACE_WPTR__VI = 0xC339; +constexpr unsigned int mmSQ_VOP_DPP__VI = 0x237F; +constexpr unsigned int mmSQ_VOP_SDWA__VI = 0x237F; +constexpr unsigned int mmSQ_WREXEC_EXEC_HI__VI = 0x23B1; +constexpr unsigned int mmSQ_WREXEC_EXEC_LO__VI = 0x23B1; +constexpr unsigned int mmSRBM_CAM_DATA__SI__CI = 0x0397; +constexpr unsigned int mmSRBM_CAM_DATA__VI = 0xFE35; +constexpr unsigned int mmSRBM_CAM_INDEX__SI__CI = 0x0396; +constexpr unsigned int mmSRBM_CAM_INDEX__VI = 0xFE34; +constexpr unsigned int mmSRBM_CREDIT_RECOVER__VI = 0x039D; +constexpr unsigned int mmSRBM_CREDIT_RECOVER_CNTL__VI = 0x039C; +constexpr unsigned int mmSRBM_CREDIT_RESET__VI = 0x039E; +constexpr unsigned int mmSRBM_DEBUG_SNAPSHOT2__VI = 0x03AD; +constexpr unsigned int mmSRBM_DSM_TRIG_CNTL0__VI = 0x03AF; +constexpr unsigned int mmSRBM_DSM_TRIG_CNTL1__VI = 0x03B0; +constexpr unsigned int mmSRBM_DSM_TRIG_MASK0__VI = 0x03B1; +constexpr unsigned int mmSRBM_DSM_TRIG_MASK1__VI = 0x03B2; +constexpr unsigned int mmSRBM_FIREWALL_ERROR_ADDR__VI = 0x03AC; +constexpr unsigned int mmSRBM_FIREWALL_ERROR_SRC__VI = 0x03AB; +constexpr unsigned int mmSRBM_GFX_CNTL_DATA__VI = 0xFA2F; +constexpr unsigned int mmSRBM_GFX_CNTL_SELECT__VI = 0xFA2E; +constexpr unsigned int mmSRBM_ISP_CLKEN_CNTL__VI = 0x03B9; +constexpr unsigned int mmSRBM_ISP_DOMAIN_ADDR0__VI = 0xFA20; +constexpr unsigned int mmSRBM_ISP_DOMAIN_ADDR1__VI = 0xFA21; +constexpr unsigned int mmSRBM_ISP_DOMAIN_ADDR2__VI = 0xFA22; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR0__VI = 0xFA00; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR1__VI = 0xFA01; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR2__VI = 0xFA02; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR3__VI = 0xFA03; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR4__VI = 0xFA04; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR5__VI = 0xFA05; +constexpr unsigned int mmSRBM_MC_DOMAIN_ADDR6__VI = 0xFA06; +constexpr unsigned int mmSRBM_PERFCOUNTER0_HI__SI__CI = 0x0704; +constexpr unsigned int mmSRBM_PERFCOUNTER0_HI__VI = 0x7C04; +constexpr unsigned int mmSRBM_PERFCOUNTER0_LO__SI__CI = 0x0703; +constexpr unsigned int mmSRBM_PERFCOUNTER0_LO__VI = 0x7C03; +constexpr unsigned int mmSRBM_PERFCOUNTER0_SELECT__SI__CI = 0x0701; +constexpr unsigned int mmSRBM_PERFCOUNTER0_SELECT__VI = 0x7C01; +constexpr unsigned int mmSRBM_PERFCOUNTER1_HI__SI__CI = 0x0706; +constexpr unsigned int mmSRBM_PERFCOUNTER1_HI__VI = 0x7C06; +constexpr unsigned int mmSRBM_PERFCOUNTER1_LO__SI__CI = 0x0705; +constexpr unsigned int mmSRBM_PERFCOUNTER1_LO__VI = 0x7C05; +constexpr unsigned int mmSRBM_PERFCOUNTER1_SELECT__SI__CI = 0x0702; +constexpr unsigned int mmSRBM_PERFCOUNTER1_SELECT__VI = 0x7C02; +constexpr unsigned int mmSRBM_PERFMON_CNTL__SI__CI = 0x0700; +constexpr unsigned int mmSRBM_PERFMON_CNTL__VI = 0x7C00; +constexpr unsigned int mmSRBM_READ_CNTL__VI = 0x0392; +constexpr unsigned int mmSRBM_READ_ERROR2__VI = 0x03AE; +constexpr unsigned int mmSRBM_SAM_DOMAIN_ADDR0__VI = 0xFA1C; +constexpr unsigned int mmSRBM_SAM_DOMAIN_ADDR1__VI = 0xFA1D; +constexpr unsigned int mmSRBM_SAM_DOMAIN_ADDR2__VI = 0xFA1E; +constexpr unsigned int mmSRBM_SDMA_DOMAIN_ADDR0__VI = 0xFA10; +constexpr unsigned int mmSRBM_SDMA_DOMAIN_ADDR1__VI = 0xFA11; +constexpr unsigned int mmSRBM_SDMA_DOMAIN_ADDR2__VI = 0xFA12; +constexpr unsigned int mmSRBM_SDMA_DOMAIN_ADDR3__VI = 0xFA13; +constexpr unsigned int mmSRBM_STATUS3__VI = 0x0395; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR0__VI = 0xFA08; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR1__VI = 0xFA09; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR2__VI = 0xFA0A; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR3__VI = 0xFA0B; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR4__VI = 0xFA0C; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR5__VI = 0xFA0D; +constexpr unsigned int mmSRBM_SYS_DOMAIN_ADDR6__VI = 0xFA0E; +constexpr unsigned int mmSRBM_UVD_DOMAIN_ADDR0__VI = 0xFA14; +constexpr unsigned int mmSRBM_UVD_DOMAIN_ADDR1__VI = 0xFA15; +constexpr unsigned int mmSRBM_UVD_DOMAIN_ADDR2__VI = 0xFA16; +constexpr unsigned int mmSRBM_VCE_DOMAIN_ADDR0__VI = 0xFA18; +constexpr unsigned int mmSRBM_VCE_DOMAIN_ADDR1__VI = 0xFA19; +constexpr unsigned int mmSRBM_VCE_DOMAIN_ADDR2__VI = 0xFA1A; +constexpr unsigned int mmSRBM_VF_ENABLE__VI = 0xFA30; +constexpr unsigned int mmSRBM_VIRT_CNTL__VI = 0xFA31; +constexpr unsigned int mmSRBM_VIRT_RESET_REQ__VI = 0xFA32; +constexpr unsigned int mmSRBM_VP8_CLKEN_CNTL__VI = 0x03BA; +constexpr unsigned int mmSRBM_VP8_DOMAIN_ADDR0__VI = 0xFA24; +constexpr unsigned int mmSWRST_COMMAND_0__VI = 0x14A2; +constexpr unsigned int mmSWRST_COMMAND_1__VI = 0x14A3; +constexpr unsigned int mmSWRST_COMMAND_STATUS__VI = 0x14A0; +constexpr unsigned int mmSWRST_CONTROL_0__VI = 0x14A4; +constexpr unsigned int mmSWRST_CONTROL_1__VI = 0x14A5; +constexpr unsigned int mmSWRST_CONTROL_2__VI = 0x14A6; +constexpr unsigned int mmSWRST_CONTROL_3__VI = 0x14A7; +constexpr unsigned int mmSWRST_CONTROL_4__VI = 0x14A8; +constexpr unsigned int mmSWRST_CONTROL_5__VI = 0x14A9; +constexpr unsigned int mmSWRST_CONTROL_6__VI = 0x14AA; +constexpr unsigned int mmSWRST_EP_COMMAND_0__VI = 0x14AB; +constexpr unsigned int mmSWRST_EP_CONTROL_0__VI = 0x14AC; +constexpr unsigned int mmSWRST_GENERAL_CONTROL__VI = 0x14A1; +constexpr unsigned int mmSX_BLEND_OPT_CONTROL__VI = 0xA1D7; +constexpr unsigned int mmSX_BLEND_OPT_EPSILON__VI = 0xA1D6; +constexpr unsigned int mmSX_MRT0_BLEND_OPT__VI = 0xA1D8; +constexpr unsigned int mmSX_MRT1_BLEND_OPT__VI = 0xA1D9; +constexpr unsigned int mmSX_MRT2_BLEND_OPT__VI = 0xA1DA; +constexpr unsigned int mmSX_MRT3_BLEND_OPT__VI = 0xA1DB; +constexpr unsigned int mmSX_MRT4_BLEND_OPT__VI = 0xA1DC; +constexpr unsigned int mmSX_MRT5_BLEND_OPT__VI = 0xA1DD; +constexpr unsigned int mmSX_MRT6_BLEND_OPT__VI = 0xA1DE; +constexpr unsigned int mmSX_MRT7_BLEND_OPT__VI = 0xA1DF; +constexpr unsigned int mmSX_PS_DOWNCONVERT__VI = 0xA1D5; +constexpr unsigned int mmSYMCLKA_CLOCK_ENABLE__VI = 0x0160; +constexpr unsigned int mmSYMCLKB_CLOCK_ENABLE__VI = 0x0161; +constexpr unsigned int mmSYMCLKC_CLOCK_ENABLE__VI = 0x0162; +constexpr unsigned int mmSYMCLKD_CLOCK_ENABLE__VI = 0x0163; +constexpr unsigned int mmSYMCLKE_CLOCK_ENABLE__VI = 0x0164; +constexpr unsigned int mmSYMCLKF_CLOCK_ENABLE__VI = 0x0165; +constexpr unsigned int mmSYMCLKG_CLOCK_ENABLE__VI = 0x0117; +constexpr unsigned int mmSYS_GRBM_GFX_INDEX_DATA__VI = 0xFA2D; +constexpr unsigned int mmSYS_GRBM_GFX_INDEX_SELECT__VI = 0xFA2C; +constexpr unsigned int mmTCC_DSM_CNTL__VI = 0x2B85; +constexpr unsigned int mmTCC_EDC_CNT__VI = 0x2B82; +constexpr unsigned int mmTCC_EXE_DISABLE__VI = 0x2B84; +constexpr unsigned int mmTCP_ATC_EDC_GATCL1_CNT__VI = 0x32B1; +constexpr unsigned int mmTCP_CNTL2__VI = 0x32B4; +constexpr unsigned int mmTCP_DSM_CNTL__VI = 0x32B3; +constexpr unsigned int mmTCP_EDC_CNT__VI = 0x2B17; +constexpr unsigned int mmTCP_GATCL1_CNTL__VI = 0x32B0; +constexpr unsigned int mmTCP_GATCL1_DSM_CNTL__VI = 0x32B2; +constexpr unsigned int mmTD_DSM_CNTL__VI = 0x252F; +constexpr unsigned int mmTMDS_CNTL__VI = 0x4A6B; +constexpr unsigned int mmTMDS_CONTROL0_FEEDBACK__VI = 0x4A6D; +constexpr unsigned int mmTMDS_CONTROL_CHAR__VI = 0x4A6C; +constexpr unsigned int mmTMDS_CTL0_1_GEN_CNTL__VI = 0x4A75; +constexpr unsigned int mmTMDS_CTL2_3_GEN_CNTL__VI = 0x4A76; +constexpr unsigned int mmTMDS_CTL_BITS__VI = 0x4A72; +constexpr unsigned int mmTMDS_DCBALANCER_CONTROL__VI = 0x4A73; +constexpr unsigned int mmTMDS_DEBUG__VI = 0x4A71; +constexpr unsigned int mmTMDS_STEREOSYNC_CTL_SEL__VI = 0x4A6E; +constexpr unsigned int mmTMDS_SYNC_CHAR_PATTERN_0_1__VI = 0x4A6F; +constexpr unsigned int mmTMDS_SYNC_CHAR_PATTERN_2_3__VI = 0x4A70; +constexpr unsigned int mmUNIPHYA_CHANNEL_XBAR_CNTL__VI = 0x4806; +constexpr unsigned int mmUNIPHYA_LINK_CNTL__VI = 0x4805; +constexpr unsigned int mmUNIPHYB_CHANNEL_XBAR_CNTL__VI = 0x4808; +constexpr unsigned int mmUNIPHYB_LINK_CNTL__VI = 0x4807; +constexpr unsigned int mmUNIPHYC_CHANNEL_XBAR_CNTL__VI = 0x480A; +constexpr unsigned int mmUNIPHYC_LINK_CNTL__VI = 0x4809; +constexpr unsigned int mmUNIPHYD_CHANNEL_XBAR_CNTL__VI = 0x480C; +constexpr unsigned int mmUNIPHYD_LINK_CNTL__VI = 0x480B; +constexpr unsigned int mmUNIPHYE_CHANNEL_XBAR_CNTL__VI = 0x480E; +constexpr unsigned int mmUNIPHYE_LINK_CNTL__VI = 0x480D; +constexpr unsigned int mmUNIPHYF_CHANNEL_XBAR_CNTL__VI = 0x4810; +constexpr unsigned int mmUNIPHYF_LINK_CNTL__VI = 0x480F; +constexpr unsigned int mmUNIPHYG_CHANNEL_XBAR_CNTL__VI = 0x4812; +constexpr unsigned int mmUNIPHYG_LINK_CNTL__VI = 0x4811; +constexpr unsigned int mmUNIPHY_ANG_BIST_CNTL__VI = 0x48CC; +constexpr unsigned int mmUNIPHY_DATA_SYNCHRONIZATION__VI = 0x48CA; +constexpr unsigned int mmUNIPHY_DEBUG__VI = 0x48D6; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKA__VI = 0x4838; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKB__VI = 0x4839; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKC__VI = 0x483F; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKD__VI = 0x4840; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKE__VI = 0x4843; +constexpr unsigned int mmUNIPHY_IMPCAL_LINKF__VI = 0x4844; +constexpr unsigned int mmUNIPHY_IMPCAL_PERIOD__VI = 0x483A; +constexpr unsigned int mmUNIPHY_IMPCAL_PSW_AB__VI = 0x483E; +constexpr unsigned int mmUNIPHY_IMPCAL_PSW_CD__VI = 0x4842; +constexpr unsigned int mmUNIPHY_IMPCAL_PSW_EF__VI = 0x4846; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED0__VI = 0x48C0; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED1__VI = 0x48C1; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED10__VI = 0x48CA; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED11__VI = 0x48CB; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED12__VI = 0x48CC; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED13__VI = 0x48CD; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED14__VI = 0x48CE; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED15__VI = 0x48CF; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED16__VI = 0x48D0; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED17__VI = 0x48D1; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED18__VI = 0x48D2; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED19__VI = 0x48D3; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED2__VI = 0x48C2; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED20__VI = 0x48D4; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED21__VI = 0x48D5; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED22__VI = 0x48D6; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED23__VI = 0x48D7; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED24__VI = 0x48D8; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED25__VI = 0x48D9; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED26__VI = 0x48DA; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED27__VI = 0x48DB; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED28__VI = 0x48DC; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED29__VI = 0x48DD; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED3__VI = 0x48C3; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED30__VI = 0x48DE; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED31__VI = 0x48DF; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED4__VI = 0x48C4; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED5__VI = 0x48C5; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED6__VI = 0x48C6; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED7__VI = 0x48C7; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED8__VI = 0x48C8; +constexpr unsigned int mmUNIPHY_MACRO_CNTL_RESERVED9__VI = 0x48C9; +constexpr unsigned int mmUNIPHY_PLL_CONTROL1__VI = 0x48C6; +constexpr unsigned int mmUNIPHY_PLL_CONTROL2__VI = 0x48C7; +constexpr unsigned int mmUNIPHY_PLL_FBDIV__VI = 0x48C5; +constexpr unsigned int mmUNIPHY_PLL_SS_CNTL__VI = 0x48C9; +constexpr unsigned int mmUNIPHY_PLL_SS_STEP_SIZE__VI = 0x48C8; +constexpr unsigned int mmUNIPHY_POWER_CONTROL__VI = 0x48C4; +constexpr unsigned int mmUNIPHY_REG_TEST_OUTPUT__VI = 0x48CB; +constexpr unsigned int mmUNIPHY_REG_TEST_OUTPUT2__VI = 0x48CD; +constexpr unsigned int mmUNIPHY_TPG_CONTROL__VI = 0x48D4; +constexpr unsigned int mmUNIPHY_TPG_SEED__VI = 0x48D5; +constexpr unsigned int mmUNIPHY_TX_CONTROL1__VI = 0x48C0; +constexpr unsigned int mmUNIPHY_TX_CONTROL2__VI = 0x48C1; +constexpr unsigned int mmUNIPHY_TX_CONTROL3__VI = 0x48C2; +constexpr unsigned int mmUNIPHY_TX_CONTROL4__VI = 0x48C3; +constexpr unsigned int mmUNP_CRC_CONTROL__VI = 0x4630; +constexpr unsigned int mmUNP_CRC_CURRENT__VI = 0x4632; +constexpr unsigned int mmUNP_CRC_LAST__VI = 0x4633; +constexpr unsigned int mmUNP_CRC_MASK__VI = 0x4631; +constexpr unsigned int mmUNP_DEBUG__VI = 0x4636; +constexpr unsigned int mmUNP_DEBUG2__VI = 0x4637; +constexpr unsigned int mmUNP_GRPH_CONTROL__VI = 0x4601; +constexpr unsigned int mmUNP_GRPH_CONTROL_EXP__VI = 0x4603; +constexpr unsigned int mmUNP_GRPH_DFQ_CONTROL__VI = 0x4629; +constexpr unsigned int mmUNP_GRPH_DFQ_STATUS__VI = 0x462A; +constexpr unsigned int mmUNP_GRPH_ENABLE__VI = 0x4600; +constexpr unsigned int mmUNP_GRPH_FLIP_RATE_CNTL__VI = 0x462F; +constexpr unsigned int mmUNP_GRPH_INTERRUPT_CONTROL__VI = 0x462C; +constexpr unsigned int mmUNP_GRPH_INTERRUPT_STATUS__VI = 0x462B; +constexpr unsigned int mmUNP_GRPH_PITCH_C__VI = 0x4617; +constexpr unsigned int mmUNP_GRPH_PITCH_L__VI = 0x4616; +constexpr unsigned int mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C__VI = 0x460B; +constexpr unsigned int mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__VI = 0x460D; +constexpr unsigned int mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__VI = 0x460C; +constexpr unsigned int mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L__VI = 0x460A; +constexpr unsigned int mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__VI = 0x4607; +constexpr unsigned int mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__VI = 0x4609; +constexpr unsigned int mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__VI = 0x4608; +constexpr unsigned int mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__VI = 0x4606; +constexpr unsigned int mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C__VI = 0x4613; +constexpr unsigned int mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__VI = 0x4615; +constexpr unsigned int mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__VI = 0x4614; +constexpr unsigned int mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L__VI = 0x4612; +constexpr unsigned int mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_C__VI = 0x460F; +constexpr unsigned int mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C__VI = 0x4611; +constexpr unsigned int mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L__VI = 0x4610; +constexpr unsigned int mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_L__VI = 0x460E; +constexpr unsigned int mmUNP_GRPH_STEREOSYNC_FLIP__VI = 0x462E; +constexpr unsigned int mmUNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_C__VI = 0x4628; +constexpr unsigned int mmUNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_L__VI = 0x4627; +constexpr unsigned int mmUNP_GRPH_SURFACE_ADDRESS_INUSE_C__VI = 0x4626; +constexpr unsigned int mmUNP_GRPH_SURFACE_ADDRESS_INUSE_L__VI = 0x4625; +constexpr unsigned int mmUNP_GRPH_SURFACE_OFFSET_X_C__VI = 0x4619; +constexpr unsigned int mmUNP_GRPH_SURFACE_OFFSET_X_L__VI = 0x4618; +constexpr unsigned int mmUNP_GRPH_SURFACE_OFFSET_Y_C__VI = 0x461B; +constexpr unsigned int mmUNP_GRPH_SURFACE_OFFSET_Y_L__VI = 0x461A; +constexpr unsigned int mmUNP_GRPH_SWAP_CNTL__VI = 0x4605; +constexpr unsigned int mmUNP_GRPH_UPDATE__VI = 0x4624; +constexpr unsigned int mmUNP_GRPH_X_END_C__VI = 0x4621; +constexpr unsigned int mmUNP_GRPH_X_END_L__VI = 0x4620; +constexpr unsigned int mmUNP_GRPH_X_START_C__VI = 0x461D; +constexpr unsigned int mmUNP_GRPH_X_START_L__VI = 0x461C; +constexpr unsigned int mmUNP_GRPH_Y_END_C__VI = 0x4623; +constexpr unsigned int mmUNP_GRPH_Y_END_L__VI = 0x4622; +constexpr unsigned int mmUNP_GRPH_Y_START_C__VI = 0x461F; +constexpr unsigned int mmUNP_GRPH_Y_START_L__VI = 0x461E; +constexpr unsigned int mmUNP_HW_ROTATION__VI = 0x4635; +constexpr unsigned int mmUNP_LB_DATA_GAP_BETWEEN_CHUNK__VI = 0x4634; +constexpr unsigned int mmUNP_TEST_DEBUG_DATA__VI = 0x4639; +constexpr unsigned int mmUNP_TEST_DEBUG_INDEX__VI = 0x4638; +constexpr unsigned int mmUVD_CGC_UDEC_STATUS__VI = 0x3D2D; +constexpr unsigned int mmUVD_JPEG_ADDR_CONFIG__VI = 0x3A1F; +constexpr unsigned int mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH__VI = 0x3C66; +constexpr unsigned int mmUVD_LMI_RBC_IB_64BIT_BAR_LOW__VI = 0x3C67; +constexpr unsigned int mmUVD_LMI_RBC_IB_VMID__VI = 0x3DA1; +constexpr unsigned int mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH__VI = 0x3C68; +constexpr unsigned int mmUVD_LMI_RBC_RB_64BIT_BAR_LOW__VI = 0x3C69; +constexpr unsigned int mmUVD_LMI_RBC_RB_VMID__VI = 0x3DA3; +constexpr unsigned int mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH__VI = 0x3C5E; +constexpr unsigned int mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW__VI = 0x3C5F; +constexpr unsigned int mmUVD_MIF_CURR_ADDR_CONFIG__VI = 0x3992; +constexpr unsigned int mmUVD_MIF_RECON1_ADDR_CONFIG__VI = 0x39C5; +constexpr unsigned int mmUVD_MIF_REF_ADDR_CONFIG__VI = 0x3993; +constexpr unsigned int mmUVD_PGFSM_CONFIG__VI = 0x38C0; +constexpr unsigned int mmUVD_PGFSM_READ_TILE1__VI = 0x38C2; +constexpr unsigned int mmUVD_PGFSM_READ_TILE2__VI = 0x38C3; +constexpr unsigned int mmUVD_PGFSM_READ_TILE3__VI = 0x38C5; +constexpr unsigned int mmUVD_PGFSM_READ_TILE4__VI = 0x38C6; +constexpr unsigned int mmUVD_PGFSM_READ_TILE5__VI = 0x38C8; +constexpr unsigned int mmUVD_PGFSM_READ_TILE6__VI = 0x38EE; +constexpr unsigned int mmUVD_PGFSM_READ_TILE7__VI = 0x38EF; +constexpr unsigned int mmUVD_POWER_STATUS__VI = 0x38C4; +constexpr unsigned int mmUVD_SUVD_CGC_CTRL__VI = 0x3BE6; +constexpr unsigned int mmUVD_SUVD_CGC_GATE__VI = 0x3BE4; +constexpr unsigned int mmUVD_SUVD_CGC_STATUS__VI = 0x3BE5; +constexpr unsigned int mmUVD_UDEC_ADDR_CONFIG__VI = 0x3BD3; +constexpr unsigned int mmUVD_UDEC_DBW_ADDR_CONFIG__VI = 0x3BD5; +constexpr unsigned int mmUVD_UDEC_DB_ADDR_CONFIG__VI = 0x3BD4; +constexpr unsigned int mmVCE_LMI_CACHE_CTRL__VI = 0x85BD; +constexpr unsigned int mmVCE_LMI_CTRL__VI = 0x85A6; +constexpr unsigned int mmVCE_LMI_CTRL2__VI = 0x859D; +constexpr unsigned int mmVCE_LMI_SWAP_CNTL__VI = 0x85AD; +constexpr unsigned int mmVCE_LMI_SWAP_CNTL1__VI = 0x85AE; +constexpr unsigned int mmVCE_LMI_SWAP_CNTL2__VI = 0x85B3; +constexpr unsigned int mmVCE_LMI_SWAP_CNTL3__VI = 0x859E; +constexpr unsigned int mmVCE_LMI_VCPU_CACHE_40BIT_BAR__VI = 0x8597; +constexpr unsigned int mmVCE_RB_ARB_CTRL__VI = 0x809F; +constexpr unsigned int mmVCE_RB_BASE_HI__VI = 0x8061; +constexpr unsigned int mmVCE_RB_BASE_HI2__VI = 0x805C; +constexpr unsigned int mmVCE_RB_BASE_HI3__VI = 0x80D5; +constexpr unsigned int mmVCE_RB_BASE_LO__VI = 0x8060; +constexpr unsigned int mmVCE_RB_BASE_LO2__VI = 0x805B; +constexpr unsigned int mmVCE_RB_BASE_LO3__VI = 0x80D4; +constexpr unsigned int mmVCE_RB_RPTR__VI = 0x8063; +constexpr unsigned int mmVCE_RB_RPTR2__VI = 0x805E; +constexpr unsigned int mmVCE_RB_RPTR3__VI = 0x80D7; +constexpr unsigned int mmVCE_RB_SIZE__VI = 0x8062; +constexpr unsigned int mmVCE_RB_SIZE2__VI = 0x805D; +constexpr unsigned int mmVCE_RB_SIZE3__VI = 0x80D6; +constexpr unsigned int mmVCE_RB_WPTR__VI = 0x8064; +constexpr unsigned int mmVCE_RB_WPTR2__VI = 0x805F; +constexpr unsigned int mmVCE_RB_WPTR3__VI = 0x80D8; +constexpr unsigned int mmVCE_SOFT_RESET__VI = 0x8048; +constexpr unsigned int mmVCE_STATUS__VI = 0x8001; +constexpr unsigned int mmVCE_SYS_INT_ACK__VI = 0x8541; +constexpr unsigned int mmVCE_SYS_INT_EN__VI = 0x8540; +constexpr unsigned int mmVCE_SYS_INT_STATUS__VI = 0x8541; +constexpr unsigned int mmVCE_UENC_DMA_DCLK_CTRL__VI = 0x8390; +constexpr unsigned int mmVCE_VCPU_CACHE_OFFSET0__VI = 0x8009; +constexpr unsigned int mmVCE_VCPU_CACHE_OFFSET1__VI = 0x800B; +constexpr unsigned int mmVCE_VCPU_CACHE_OFFSET2__VI = 0x800D; +constexpr unsigned int mmVCE_VCPU_CACHE_SIZE0__VI = 0x800A; +constexpr unsigned int mmVCE_VCPU_CACHE_SIZE1__VI = 0x800C; +constexpr unsigned int mmVCE_VCPU_CACHE_SIZE2__VI = 0x800E; +constexpr unsigned int mmVCE_VCPU_CNTL__VI = 0x8005; +constexpr unsigned int mmVGA25_PPLL_ANALOG__VI = 0x171B; +constexpr unsigned int mmVGA25_PPLL_FB_DIV__VI = 0x1715; +constexpr unsigned int mmVGA25_PPLL_POST_DIV__VI = 0x1718; +constexpr unsigned int mmVGA25_PPLL_REF_DIV__VI = 0x1712; +constexpr unsigned int mmVGA28_PPLL_ANALOG__VI = 0x171C; +constexpr unsigned int mmVGA28_PPLL_FB_DIV__VI = 0x1716; +constexpr unsigned int mmVGA28_PPLL_POST_DIV__VI = 0x1719; +constexpr unsigned int mmVGA28_PPLL_REF_DIV__VI = 0x1713; +constexpr unsigned int mmVGA41_PPLL_ANALOG__VI = 0x171D; +constexpr unsigned int mmVGA41_PPLL_FB_DIV__VI = 0x1717; +constexpr unsigned int mmVGA41_PPLL_POST_DIV__VI = 0x171A; +constexpr unsigned int mmVGA41_PPLL_REF_DIV__VI = 0x1714; +constexpr unsigned int mmVGT_DISPATCH_DRAW_INDEX__VI = 0xA2DD; +constexpr unsigned int mmVGT_TESS_DISTRIBUTION__VI = 0xA2D4; +constexpr unsigned int mmVIEWPORT_START_SECONDARY__VI = 0x1B5B; +constexpr unsigned int mmVM_INIT_STATUS__VI = 0x14D3; +constexpr unsigned int mmVM_L2_BANK_SELECT_RESERVED_CID__VI = 0x0579; +constexpr unsigned int mmVM_L2_BANK_SELECT_RESERVED_CID2__VI = 0x057A; +constexpr unsigned int mmVM_L2_CNTL4__VI = 0x0578; +constexpr unsigned int mmWB_DBG_MODE__VI = 0x5E31; +constexpr unsigned int mmWB_DEBUG_CTRL__VI = 0x5E30; +constexpr unsigned int mmWB_EC_CONFIG__VI = 0x5E19; +constexpr unsigned int mmWB_ENABLE__VI = 0x5E18; +constexpr unsigned int mmWB_HW_DEBUG__VI = 0x5E32; +constexpr unsigned int mmWB_SOFT_RESET__VI = 0x5E36; +constexpr unsigned int mmWD_QOS__VI = 0x2242; +constexpr unsigned int mmXDMA_AON_TEST_DEBUG_DATA__VI = 0x03FD; +constexpr unsigned int mmXDMA_AON_TEST_DEBUG_INDEX__VI = 0x03FC; +constexpr unsigned int mmXDMA_CLOCK_GATING_CNTL__VI = 0x03E4; +constexpr unsigned int mmXDMA_IF_BIF_STATUS__VI = 0x03E7; +constexpr unsigned int mmXDMA_IF_STATUS__VI = 0x03E9; +constexpr unsigned int mmXDMA_INTERRUPT__VI = 0x03E3; +constexpr unsigned int mmXDMA_LOCAL_SURFACE_TILING1__VI = 0x03E1; +constexpr unsigned int mmXDMA_LOCAL_SURFACE_TILING2__VI = 0x03E2; +constexpr unsigned int mmXDMA_MC_PCIE_CLIENT_CONFIG__VI = 0x03E0; +constexpr unsigned int mmXDMA_MEM_POWER_CNTL__VI = 0x03E6; +constexpr unsigned int mmXDMA_MSTR_CACHE__VI = 0x040A; +constexpr unsigned int mmXDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0408; +constexpr unsigned int mmXDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0409; +constexpr unsigned int mmXDMA_MSTR_CHANNEL_DIM__VI = 0x0402; +constexpr unsigned int mmXDMA_MSTR_CHANNEL_START__VI = 0x040B; +constexpr unsigned int mmXDMA_MSTR_CMD_URGENT_CNTL__VI = 0x03F2; +constexpr unsigned int mmXDMA_MSTR_CNTL__VI = 0x03EC; +constexpr unsigned int mmXDMA_MSTR_HEIGHT__VI = 0x0403; +constexpr unsigned int mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__VI = 0x03EF; +constexpr unsigned int mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__VI = 0x03F0; +constexpr unsigned int mmXDMA_MSTR_LOCAL_SURFACE_PITCH__VI = 0x03F1; +constexpr unsigned int mmXDMA_MSTR_MEM_CLIENT_CONFIG__VI = 0x03EE; +constexpr unsigned int mmXDMA_MSTR_MEM_NACK_STATUS__VI = 0x03F6; +constexpr unsigned int mmXDMA_MSTR_MEM_URGENT_CNTL__VI = 0x03F3; +constexpr unsigned int mmXDMA_MSTR_PCIE_NACK_STATUS__VI = 0x03F5; +constexpr unsigned int mmXDMA_MSTR_PERFMEAS_CNTL__VI = 0x040F; +constexpr unsigned int mmXDMA_MSTR_PERFMEAS_STATUS__VI = 0x040E; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_CACHE__VI = 0x040A; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0408; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0409; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_CHANNEL_DIM__VI = 0x0402; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_CHANNEL_START__VI = 0x040B; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_HEIGHT__VI = 0x0403; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_PERFMEAS_CNTL__VI = 0x040F; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_PERFMEAS_STATUS__VI = 0x040E; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_PIPE_CNTL__VI = 0x0400; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_READ_COMMAND__VI = 0x0401; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0406; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0407; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0404; +constexpr unsigned int mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0405; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_CACHE__VI = 0x041A; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0418; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0419; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_CHANNEL_DIM__VI = 0x0412; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_CHANNEL_START__VI = 0x041B; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_HEIGHT__VI = 0x0413; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_PERFMEAS_CNTL__VI = 0x041F; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_PERFMEAS_STATUS__VI = 0x041E; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_PIPE_CNTL__VI = 0x0410; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_READ_COMMAND__VI = 0x0411; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0416; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0417; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0414; +constexpr unsigned int mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0415; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_CACHE__VI = 0x042A; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0428; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0429; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_CHANNEL_DIM__VI = 0x0422; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_CHANNEL_START__VI = 0x042B; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_HEIGHT__VI = 0x0423; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_PERFMEAS_CNTL__VI = 0x042F; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_PERFMEAS_STATUS__VI = 0x042E; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_PIPE_CNTL__VI = 0x0420; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_READ_COMMAND__VI = 0x0421; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0426; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0427; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0424; +constexpr unsigned int mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0425; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_CACHE__VI = 0x043A; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0438; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0439; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_CHANNEL_DIM__VI = 0x0432; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_CHANNEL_START__VI = 0x043B; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_HEIGHT__VI = 0x0433; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_PERFMEAS_CNTL__VI = 0x043F; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_PERFMEAS_STATUS__VI = 0x043E; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_PIPE_CNTL__VI = 0x0430; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_READ_COMMAND__VI = 0x0431; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0436; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0437; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0434; +constexpr unsigned int mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0435; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_CACHE__VI = 0x044A; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0448; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0449; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_CHANNEL_DIM__VI = 0x0442; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_CHANNEL_START__VI = 0x044B; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_HEIGHT__VI = 0x0443; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_PERFMEAS_CNTL__VI = 0x044F; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_PERFMEAS_STATUS__VI = 0x044E; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_PIPE_CNTL__VI = 0x0440; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_READ_COMMAND__VI = 0x0441; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0446; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0447; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0444; +constexpr unsigned int mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0445; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_CACHE__VI = 0x045A; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_CACHE_BASE_ADDR__VI = 0x0458; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_CACHE_BASE_ADDR_HIGH__VI = 0x0459; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_CHANNEL_DIM__VI = 0x0452; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_CHANNEL_START__VI = 0x045B; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_HEIGHT__VI = 0x0453; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_PERFMEAS_CNTL__VI = 0x045F; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_PERFMEAS_STATUS__VI = 0x045E; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_PIPE_CNTL__VI = 0x0450; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_READ_COMMAND__VI = 0x0451; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0456; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0457; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0454; +constexpr unsigned int mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0455; +constexpr unsigned int mmXDMA_MSTR_PIPE_CNTL__VI = 0x0400; +constexpr unsigned int mmXDMA_MSTR_READ_COMMAND__VI = 0x0401; +constexpr unsigned int mmXDMA_MSTR_REMOTE_GPU_ADDRESS__VI = 0x0406; +constexpr unsigned int mmXDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0407; +constexpr unsigned int mmXDMA_MSTR_REMOTE_SURFACE_BASE__VI = 0x0404; +constexpr unsigned int mmXDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__VI = 0x0405; +constexpr unsigned int mmXDMA_MSTR_STATUS__VI = 0x03ED; +constexpr unsigned int mmXDMA_MSTR_VSYNC_GSL_CHECK__VI = 0x03F7; +constexpr unsigned int mmXDMA_PERF_MEAS_STATUS__VI = 0x03E8; +constexpr unsigned int mmXDMA_PG_CONTROL__VI = 0x03F9; +constexpr unsigned int mmXDMA_PG_STATUS__VI = 0x03FB; +constexpr unsigned int mmXDMA_PG_WDATA__VI = 0x03FA; +constexpr unsigned int mmXDMA_RBBMIF_RDWR_CNTL__VI = 0x03F8; +constexpr unsigned int mmXDMA_SLV_CHANNEL0_XDMA_SLV_CHANNEL_CNTL__VI = 0x0470; +constexpr unsigned int mmXDMA_SLV_CHANNEL0_XDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0471; +constexpr unsigned int mmXDMA_SLV_CHANNEL0_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0472; +constexpr unsigned int mmXDMA_SLV_CHANNEL1_XDMA_SLV_CHANNEL_CNTL__VI = 0x0478; +constexpr unsigned int mmXDMA_SLV_CHANNEL1_XDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0479; +constexpr unsigned int mmXDMA_SLV_CHANNEL1_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x047A; +constexpr unsigned int mmXDMA_SLV_CHANNEL2_XDMA_SLV_CHANNEL_CNTL__VI = 0x0480; +constexpr unsigned int mmXDMA_SLV_CHANNEL2_XDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0481; +constexpr unsigned int mmXDMA_SLV_CHANNEL2_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0482; +constexpr unsigned int mmXDMA_SLV_CHANNEL3_XDMA_SLV_CHANNEL_CNTL__VI = 0x0488; +constexpr unsigned int mmXDMA_SLV_CHANNEL3_XDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0489; +constexpr unsigned int mmXDMA_SLV_CHANNEL3_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x048A; +constexpr unsigned int mmXDMA_SLV_CHANNEL4_XDMA_SLV_CHANNEL_CNTL__VI = 0x0490; +constexpr unsigned int mmXDMA_SLV_CHANNEL4_XDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0491; +constexpr unsigned int mmXDMA_SLV_CHANNEL4_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0492; +constexpr unsigned int mmXDMA_SLV_CHANNEL5_XDMA_SLV_CHANNEL_CNTL__VI = 0x0498; +constexpr unsigned int mmXDMA_SLV_CHANNEL5_XDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0499; +constexpr unsigned int mmXDMA_SLV_CHANNEL5_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x049A; +constexpr unsigned int mmXDMA_SLV_CHANNEL_CNTL__VI = 0x0470; +constexpr unsigned int mmXDMA_SLV_CNTL__VI = 0x0460; +constexpr unsigned int mmXDMA_SLV_MEM_CLIENT_CONFIG__VI = 0x0461; +constexpr unsigned int mmXDMA_SLV_MEM_NACK_STATUS__VI = 0x0469; +constexpr unsigned int mmXDMA_SLV_PCIE_NACK_STATUS__VI = 0x0468; +constexpr unsigned int mmXDMA_SLV_RDRET_BUF_STATUS__VI = 0x046A; +constexpr unsigned int mmXDMA_SLV_READ_LATENCY_AVE__VI = 0x0467; +constexpr unsigned int mmXDMA_SLV_READ_LATENCY_MINMAX__VI = 0x0466; +constexpr unsigned int mmXDMA_SLV_READ_LATENCY_TIMER__VI = 0x046B; +constexpr unsigned int mmXDMA_SLV_READ_URGENT_CNTL__VI = 0x0463; +constexpr unsigned int mmXDMA_SLV_REMOTE_GPU_ADDRESS__VI = 0x0471; +constexpr unsigned int mmXDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__VI = 0x0472; +constexpr unsigned int mmXDMA_SLV_SLS_PITCH__VI = 0x0462; +constexpr unsigned int mmXDMA_SLV_WB_RATE_CNTL__VI = 0x0465; +constexpr unsigned int mmXDMA_SLV_WRITE_URGENT_CNTL__VI = 0x0464; +constexpr unsigned int mmXDMA_TEST_DEBUG_DATA__VI = 0x03EB; +constexpr unsigned int mmXDMA_TEST_DEBUG_INDEX__VI = 0x03EA; +#define offset_HEADER__VI +constexpr unsigned int pciMSI_MASK__VI = 0x002B; +constexpr unsigned int pciMSI_MASK_64__VI = 0x002C; +constexpr unsigned int pciMSI_PENDING__VI = 0x002C; +constexpr unsigned int pciMSI_PENDING_64__VI = 0x002D; +constexpr unsigned int pciPCIE_ARI_CAP__VI = 0x00CB; +constexpr unsigned int pciPCIE_ARI_CNTL__VI = 0x00CB; +constexpr unsigned int pciPCIE_ARI_ENH_CAP_LIST__VI = 0x00CA; +constexpr unsigned int pciPCIE_LTR_CAP__VI = 0x00C9; +constexpr unsigned int pciPCIE_LTR_ENH_CAP_LIST__VI = 0x00C8; +constexpr unsigned int pciPCIE_MC_ADDR0__VI = 0x00BE; +constexpr unsigned int pciPCIE_MC_ADDR1__VI = 0x00BF; +constexpr unsigned int pciPCIE_MC_BLOCK_ALL0__VI = 0x00C2; +constexpr unsigned int pciPCIE_MC_BLOCK_ALL1__VI = 0x00C3; +constexpr unsigned int pciPCIE_MC_BLOCK_UNTRANSLATED_0__VI = 0x00C4; +constexpr unsigned int pciPCIE_MC_BLOCK_UNTRANSLATED_1__VI = 0x00C5; +constexpr unsigned int pciPCIE_MC_CAP__VI = 0x00BD; +constexpr unsigned int pciPCIE_MC_CNTL__VI = 0x00BD; +constexpr unsigned int pciPCIE_MC_ENH_CAP_LIST__VI = 0x00BC; +constexpr unsigned int pciPCIE_MC_RCV0__VI = 0x00C0; +constexpr unsigned int pciPCIE_MC_RCV1__VI = 0x00C1; +constexpr unsigned int pciPCIE_SRIOV_CAP__VI = 0x00CD; +constexpr unsigned int pciPCIE_SRIOV_CONTROL__VI = 0x00CE; +constexpr unsigned int pciPCIE_SRIOV_ENH_CAP_LIST__VI = 0x00CC; +constexpr unsigned int pciPCIE_SRIOV_FIRST_VF_OFFSET__VI = 0x00D1; +constexpr unsigned int pciPCIE_SRIOV_FUNC_DEP_LINK__VI = 0x00D0; +constexpr unsigned int pciPCIE_SRIOV_INITIAL_VFS__VI = 0x00CF; +constexpr unsigned int pciPCIE_SRIOV_NUM_VFS__VI = 0x00D0; +constexpr unsigned int pciPCIE_SRIOV_STATUS__VI = 0x00CE; +constexpr unsigned int pciPCIE_SRIOV_SUPPORTED_PAGE_SIZE__VI = 0x00D3; +constexpr unsigned int pciPCIE_SRIOV_SYSTEM_PAGE_SIZE__VI = 0x00D4; +constexpr unsigned int pciPCIE_SRIOV_TOTAL_VFS__VI = 0x00CF; +constexpr unsigned int pciPCIE_SRIOV_VF_BASE_ADDR_0__VI = 0x00D5; +constexpr unsigned int pciPCIE_SRIOV_VF_BASE_ADDR_1__VI = 0x00D6; +constexpr unsigned int pciPCIE_SRIOV_VF_BASE_ADDR_2__VI = 0x00D7; +constexpr unsigned int pciPCIE_SRIOV_VF_BASE_ADDR_3__VI = 0x00D8; +constexpr unsigned int pciPCIE_SRIOV_VF_BASE_ADDR_4__VI = 0x00D9; +constexpr unsigned int pciPCIE_SRIOV_VF_BASE_ADDR_5__VI = 0x00DA; +constexpr unsigned int pciPCIE_SRIOV_VF_DEVICE_ID__VI = 0x00D2; +constexpr unsigned int pciPCIE_SRIOV_VF_MIGRATION_STATE_ARRAY_OFFSET__VI = 0x00DB; +constexpr unsigned int pciPCIE_SRIOV_VF_STRIDE__VI = 0x00D1; +constexpr unsigned int pciPCIE_TPH_REQR_CAP__VI = 0x00B9; +constexpr unsigned int pciPCIE_TPH_REQR_CNTL__VI = 0x00BA; +constexpr unsigned int pciPCIE_TPH_REQR_ENH_CAP_LIST__VI = 0x00B8; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC_ENH_CAP_LIST_GPUIOV__VI = 0x0100; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC_HDR_GPUIOV__VI = 0x0101; +constexpr unsigned int pciPCIE_VENDOR_SPECIFIC_HDR_GPUIOV_RESET_CONTROL__VI = 0x0105; +} // inline namespace Chip +} // namespace Gfx6 +} // namespace Pal + +#endif diff --git a/externals/gcn/include/gcn/si_ci_vi_merged_pm4_it_opcodes.h b/externals/gcn/include/gcn/si_ci_vi_merged_pm4_it_opcodes.h new file mode 100644 index 000000000..0c2ac3abc --- /dev/null +++ b/externals/gcn/include/gcn/si_ci_vi_merged_pm4_it_opcodes.h @@ -0,0 +1,117 @@ +/* + *********************************************************************************************************************** + * + * Copyright (c) 2015-2021 Advanced Micro Devices, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************************************************************************/ + +#ifndef PM4_IT_OPCODES_H +#define PM4_IT_OPCODES_H + +enum IT_OpCodeType { + IT_NOP = 0x10, + IT_SET_BASE = 0x11, + IT_CLEAR_STATE = 0x12, + IT_INDEX_BUFFER_SIZE = 0x13, + IT_DISPATCH_DIRECT = 0x15, + IT_DISPATCH_INDIRECT = 0x16, + IT_ATOMIC_GDS = 0x1D, + IT_ATOMIC = 0x1E, + IT_OCCLUSION_QUERY = 0x1F, + IT_SET_PREDICATION = 0x20, + IT_REG_RMW = 0x21, + IT_COND_EXEC = 0x22, + IT_PRED_EXEC = 0x23, + IT_DRAW_INDIRECT = 0x24, + IT_DRAW_INDEX_INDIRECT = 0x25, + IT_INDEX_BASE = 0x26, + IT_DRAW_INDEX_2 = 0x27, + IT_CONTEXT_CONTROL = 0x28, + IT_INDEX_TYPE = 0x2A, + IT_DRAW_INDIRECT_MULTI = 0x2C, + IT_DRAW_INDEX_AUTO = 0x2D, + IT_NUM_INSTANCES = 0x2F, + IT_DRAW_INDEX_MULTI_AUTO = 0x30, + IT_INDIRECT_BUFFER_CNST = 0x33, + IT_STRMOUT_BUFFER_UPDATE = 0x34, + IT_DRAW_INDEX_OFFSET_2 = 0x35, + IT_WRITE_DATA = 0x37, + IT_DRAW_INDEX_INDIRECT_MULTI = 0x38, + IT_MEM_SEMAPHORE = 0x39, + IT_COPY_DW__SI__CI = 0x3B, + IT_WAIT_REG_MEM = 0x3C, + IT_INDIRECT_BUFFER = 0x3F, + IT_COND_INDIRECT_BUFFER = 0x3F, + IT_COPY_DATA = 0x40, + IT_CP_DMA = 0x41, + IT_PFP_SYNC_ME = 0x42, + IT_SURFACE_SYNC = 0x43, + IT_COND_WRITE = 0x45, + IT_EVENT_WRITE = 0x46, + IT_EVENT_WRITE_EOP = 0x47, + IT_EVENT_WRITE_EOS = 0x48, + IT_PREAMBLE_CNTL = 0x4A, + IT_CONTEXT_REG_RMW = 0x51, + IT_LOAD_SH_REG = 0x5F, + IT_LOAD_CONFIG_REG = 0x60, + IT_LOAD_CONTEXT_REG = 0x61, + IT_SET_CONFIG_REG = 0x68, + IT_SET_CONTEXT_REG = 0x69, + IT_SET_CONTEXT_REG_INDIRECT = 0x73, + IT_SET_SH_REG = 0x76, + IT_SET_SH_REG_OFFSET = 0x77, + IT_SCRATCH_RAM_WRITE = 0x7D, + IT_SCRATCH_RAM_READ = 0x7E, + IT_LOAD_CONST_RAM = 0x80, + IT_WRITE_CONST_RAM = 0x81, + IT_DUMP_CONST_RAM = 0x83, + IT_INCREMENT_CE_COUNTER = 0x84, + IT_INCREMENT_DE_COUNTER = 0x85, + IT_WAIT_ON_CE_COUNTER = 0x86, + IT_WAIT_ON_DE_COUNTER__SI = 0x87, + IT_WAIT_ON_DE_COUNTER_DIFF = 0x88, + IT_SWITCH_BUFFER = 0x8B, + IT_DRAW_PREAMBLE__CI__VI = 0x36, + IT_RELEASE_MEM__CI__VI = 0x49, + IT_DMA_DATA__CI__VI = 0x50, + IT_ACQUIRE_MEM__CI__VI = 0x58, + IT_REWIND__CI__VI = 0x59, + IT_LOAD_UCONFIG_REG__CI__VI = 0x5E, + IT_SET_QUEUE_REG__CI__VI = 0x78, + IT_SET_UCONFIG_REG__CI__VI = 0x79, + IT_INDEX_ATTRIBUTES_INDIRECT__CI__VI = 0x91, + IT_SET_SH_REG_INDEX__CI__VI = 0x9B, + IT_SET_RESOURCES__CI__VI = 0xA0, + IT_MAP_PROCESS__CI__VI = 0xA1, + IT_MAP_QUEUES__CI__VI = 0xA2, + IT_UNMAP_QUEUES__CI__VI = 0xA3, + IT_QUERY_STATUS__CI__VI = 0xA4, + IT_RUN_LIST__CI__VI = 0xA5, + IT_LOAD_SH_REG_INDEX__VI = 0x63, + IT_LOAD_CONTEXT_REG_INDEX__VI = 0x9F, + IT_DUMP_CONST_RAM_OFFSET__VI = 0x9E, +}; + +#define PM4_TYPE_0 0 +#define PM4_TYPE_2 2 +#define PM4_TYPE_3 3 + +#endif diff --git a/externals/glslang b/externals/glslang index d59c84d38..e61d7bb30 160000 --- a/externals/glslang +++ b/externals/glslang @@ -1 +1 @@ -Subproject commit d59c84d388c805022e2bddea08aa41cbe7e43e55 +Subproject commit e61d7bb3006f451968714e2f653412081871e1ee diff --git a/externals/half b/externals/half new file mode 160000 index 000000000..1ddada225 --- /dev/null +++ b/externals/half @@ -0,0 +1 @@ +Subproject commit 1ddada225144cac0de8f6b5c0dd9acffd99a2e68 diff --git a/externals/magic_enum b/externals/magic_enum index dae6bbf16..126539e13 160000 --- a/externals/magic_enum +++ b/externals/magic_enum @@ -1 +1 @@ -Subproject commit dae6bbf16c363e9ead4e628a47fdb02956a634f3 +Subproject commit 126539e13cccdc2e75ce770e94f3c26403099fa5 diff --git a/externals/pugixml b/externals/pugixml new file mode 160000 index 000000000..3b1718437 --- /dev/null +++ b/externals/pugixml @@ -0,0 +1 @@ +Subproject commit 3b17184379fcaaeb7f1fbe08018b7fedf2640b3b diff --git a/externals/robin-map b/externals/robin-map index 1115dad3f..fe845fd78 160000 --- a/externals/robin-map +++ b/externals/robin-map @@ -1 +1 @@ -Subproject commit 1115dad3ffa0994e3f43b693d9b9cc99944c64c1 +Subproject commit fe845fd7852ef541c5479ae23b3d36b57f8608ee diff --git a/externals/sdl3 b/externals/sdl3 index 4cc3410dc..54e622c2e 160000 --- a/externals/sdl3 +++ b/externals/sdl3 @@ -1 +1 @@ -Subproject commit 4cc3410dce50cefce98d3cf3cf1bc8eca83b862a +Subproject commit 54e622c2e6af456bfef382fae44c17682d5ac88a diff --git a/externals/sirit b/externals/sirit index 8db09231c..6cecb95d6 160000 --- a/externals/sirit +++ b/externals/sirit @@ -1 +1 @@ -Subproject commit 8db09231c448b913ae905d5237ce2eca46e3fe87 +Subproject commit 6cecb95d679c82c413d1f989e0b7ad9af130600d diff --git a/externals/toml11 b/externals/toml11 index cc0bee4fd..f925e7f28 160000 --- a/externals/toml11 +++ b/externals/toml11 @@ -1 +1 @@ -Subproject commit cc0bee4fd46ea1f5db147d63ea545208cc9e8405 +Subproject commit f925e7f287c0008813c2294798cf9ca167fd9ffd diff --git a/externals/vma b/externals/vma index e1bdbca9b..1c35ba99c 160000 --- a/externals/vma +++ b/externals/vma @@ -1 +1 @@ -Subproject commit e1bdbca9baf4d682fb6066b380f4aa4a7bdbb58a +Subproject commit 1c35ba99ce775f8342d87a83a3f0f696f99c2a39 diff --git a/externals/vulkan-headers b/externals/vulkan-headers index d205aff40..d91597a82 160000 --- a/externals/vulkan-headers +++ b/externals/vulkan-headers @@ -1 +1 @@ -Subproject commit d205aff40b4e15d4c568523ee6a26f85138126d9 +Subproject commit d91597a82f881d473887b560a03a7edf2720b72c diff --git a/externals/xbyak b/externals/xbyak index aabb091ae..d067f0d3f 160000 --- a/externals/xbyak +++ b/externals/xbyak @@ -1 +1 @@ -Subproject commit aabb091ae37068498751fd58202a9854408ecb0e +Subproject commit d067f0d3f55696ae8bc9a25ad7012ee80f221d54 diff --git a/externals/xxhash b/externals/xxhash index dbea33e47..d4ad85e4a 160000 --- a/externals/xxhash +++ b/externals/xxhash @@ -1 +1 @@ -Subproject commit dbea33e47e7c0fe0b7c8592cd931c7430c1f130d +Subproject commit d4ad85e4afaad5c780f54db1dc967fff5a869ffd diff --git a/externals/zydis b/externals/zydis index bd73bc03b..9d298eb80 160000 --- a/externals/zydis +++ b/externals/zydis @@ -1 +1 @@ -Subproject commit bd73bc03b0aacaa89c9c203b9b43cd08f1b1843b +Subproject commit 9d298eb8067ff62a237203d1e1470785033e185c diff --git a/scripts/aerolib.inl b/scripts/aerolib.inl index a87c3cc4e..64ee32ea2 100644 --- a/scripts/aerolib.inl +++ b/scripts/aerolib.inl @@ -114108,7 +114108,7 @@ STUB( _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V124RequestCompetitiveResultEE7add_refEv) STUB("efPahl2FufA", _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V35Error8fromJsonERKNS_4Json5ValueE) -STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlemetId) +STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlementId) STUB("efXnxYFN5oE", _ZNSt11range_errorD0Ev) STUB("efcwuDLsAM0", _ZThn120_NK7WebCore16HTMLMediaElement5mutedEv) STUB("efhGArzWdxE", _ZN7bmalloc6IsoTLS15s_didInitializeE) @@ -129493,7 +129493,7 @@ STUB( STUB("kJlYH5uMAWI", sceNetResolverDestroy) STUB("kJmdxo4uM+8", _ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE5_InitERKSt8_Locinfo) -STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlemetId) +STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlementId) STUB( "kJoY9lMIFzY", _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_21AdvancedPlayerProfile2V138MatchCompletionRateDisconnectedMetricsEEEEmmEi) diff --git a/scripts/file_formats/sfo.hexpat b/scripts/file_formats/sfo.hexpat new file mode 100644 index 000000000..cfc1f8789 --- /dev/null +++ b/scripts/file_formats/sfo.hexpat @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +import std.io; +import std.sys; + +struct Header { + u32 magic; + u32 version; + u32 key_table_offset; + u32 data_table_offset; + u32 index_table_entries; +}; + +struct KeyEntry { + char name[]; +} [[inline]]; + +struct DataEntry { + if (fmt == 0x0404) { + u32 int_value; + } else if(fmt == 0x0004) { + char bin_value[size]; + } else if(fmt == 0x0204) { + char str_value[size]; + } else { + std::warning("unknown fmt type"); + } +} [[inline]]; + +struct IndexEntry { + u16 key_offset; + u16 param_fmt; + u32 param_len; + u32 param_max_len; + u32 data_offset; +}; + +struct Entry { + u64 begin = $; + IndexEntry index; + KeyEntry key @ KeyTableOffset + index.key_offset; + DataEntry data @ DataTableOffset + index.data_offset; + u8 data_empty[index.param_max_len - index.param_len] @ DataTableOffset + index.data_offset + index.param_len; + $ = begin + sizeof(IndexEntry); +}; + +Header header @ 0; +std::assert(header.magic == 0x46535000, "Miss match magic"); +std::assert(header.version == 0x00000101, "Miss match version"); + +Entry list[header.index_table_entries] @ 0x14; \ No newline at end of file diff --git a/scripts/ps4_names.txt b/scripts/ps4_names.txt index caad2b4df..6f95cc734 100644 --- a/scripts/ps4_names.txt +++ b/scripts/ps4_names.txt @@ -80897,10 +80897,10 @@ sceAppCheckerExecute sceAppCheckerExecuteEx sceAppContentAddcontDelete sceAppContentAddcontEnqueueDownload -sceAppContentAddcontEnqueueDownloadByEntitlemetId +sceAppContentAddcontEnqueueDownloadByEntitlementId sceAppContentAddcontEnqueueDownloadSp sceAppContentAddcontMount -sceAppContentAddcontMountByEntitlemetId +sceAppContentAddcontMountByEntitlementId sceAppContentAddcontShrink sceAppContentAddcontUnmount sceAppContentAppParamGetInt diff --git a/src/audio_core/sdl_audio.cpp b/src/audio_core/sdl_audio.cpp index f544c52f9..7fed42a44 100644 --- a/src/audio_core/sdl_audio.cpp +++ b/src/audio_core/sdl_audio.cpp @@ -14,7 +14,9 @@ namespace Audio { -int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, +constexpr int AUDIO_STREAM_BUFFER_THRESHOLD = 65536; // Define constant for buffer threshold + +s32 SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, Libraries::AudioOut::OrbisAudioOutParamFormat format) { using Libraries::AudioOut::OrbisAudioOutParamFormat; std::unique_lock lock{m_mutex}; @@ -80,7 +82,7 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, SDL_zero(fmt); fmt.format = sampleFormat; fmt.channels = port.channels_num; - fmt.freq = 48000; + fmt.freq = freq; // Set frequency from the argument port.stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, NULL, NULL); SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream)); @@ -88,7 +90,8 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, } } - return -1; // all ports are used + LOG_ERROR(Lib_AudioOut, "Audio ports are full"); + return ORBIS_AUDIO_OUT_ERROR_PORT_FULL; // all ports are used } s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) { @@ -97,27 +100,28 @@ s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) { if (!port.isOpen) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - if (ptr == nullptr) { - return 0; - } - // TODO mixing channels - int result = SDL_PutAudioStreamData(port.stream, ptr, - port.samples_num * port.sample_size * port.channels_num); - // TODO find a correct value 8192 is estimated - while (SDL_GetAudioStreamAvailable(port.stream) > 65536) { + + const size_t data_size = port.samples_num * port.sample_size * port.channels_num; + + bool result = SDL_PutAudioStreamData(port.stream, ptr, data_size); + + lock.unlock(); // Unlock only after necessary operations + + while (SDL_GetAudioStreamAvailable(port.stream) > AUDIO_STREAM_BUFFER_THRESHOLD) { SDL_Delay(0); } - return result; + return result ? ORBIS_OK : -1; } -bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) { +s32 SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) { using Libraries::AudioOut::OrbisAudioOutParamFormat; std::shared_lock lock{m_mutex}; auto& port = portsOut[handle - 1]; if (!port.isOpen) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } + for (int i = 0; i < port.channels_num; i++, bitflag >>= 1u) { auto bit = bitflag & 0x1u; @@ -147,16 +151,16 @@ bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) { } } - return true; + return ORBIS_OK; } -bool SDLAudio::AudioOutGetStatus(s32 handle, int* type, int* channels_num) { +s32 SDLAudio::AudioOutGetStatus(s32 handle, int* type, int* channels_num) { std::shared_lock lock{m_mutex}; auto& port = portsOut[handle - 1]; *type = port.type; *channels_num = port.channels_num; - return true; + return ORBIS_OK; } } // namespace Audio diff --git a/src/audio_core/sdl_audio.h b/src/audio_core/sdl_audio.h index 7844bd61b..0d4783f19 100644 --- a/src/audio_core/sdl_audio.h +++ b/src/audio_core/sdl_audio.h @@ -14,27 +14,26 @@ public: SDLAudio() = default; virtual ~SDLAudio() = default; - int AudioOutOpen(int type, u32 samples_num, u32 freq, + s32 AudioOutOpen(int type, u32 samples_num, u32 freq, Libraries::AudioOut::OrbisAudioOutParamFormat format); s32 AudioOutOutput(s32 handle, const void* ptr); - bool AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume); - bool AudioOutGetStatus(s32 handle, int* type, int* channels_num); + s32 AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume); + s32 AudioOutGetStatus(s32 handle, int* type, int* channels_num); private: struct PortOut { - bool isOpen = false; - int type = 0; + SDL_AudioStream* stream = nullptr; u32 samples_num = 0; - u8 sample_size = 0; u32 freq = 0; u32 format = -1; + int type = 0; int channels_num = 0; int volume[8] = {}; - SDL_AudioStream* stream = nullptr; + u8 sample_size = 0; + bool isOpen = false; }; std::shared_mutex m_mutex; - std::array portsOut; // main up to 8 ports , BGM 1 port , voice up to 4 ports , - // personal up to 4 ports , padspk up to 5 ports , aux 1 port + std::array portsOut; }; } // namespace Audio diff --git a/src/common/alignment.h b/src/common/alignment.h index 367efb6bb..8480fae26 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h @@ -28,4 +28,16 @@ template return (value & 0x3FFF) == 0; } +template + requires std::is_integral_v +[[nodiscard]] constexpr bool Is64KBAligned(T value) { + return (value & 0xFFFF) == 0; +} + +template + requires std::is_integral_v +[[nodiscard]] constexpr bool Is2MBAligned(T value) { + return (value & 0x1FFFFF) == 0; +} + } // namespace Common diff --git a/src/common/arch.h b/src/common/arch.h new file mode 100644 index 000000000..b22366cb7 --- /dev/null +++ b/src/common/arch.h @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#if defined(__x86_64__) || defined(_M_X64) +#define ARCH_X86_64 1 +#elif defined(__aarch64__) || defined(_M_ARM64) +#define ARCH_ARM64 1 +#endif diff --git a/src/common/assert.cpp b/src/common/assert.cpp index 3a49c9396..be0feb71d 100644 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp @@ -1,10 +1,17 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/arch.h" #include "common/assert.h" #include "common/logging/backend.h" +#if defined(ARCH_X86_64) #define Crash() __asm__ __volatile__("int $3") +#elif defined(ARCH_ARM64) +#define Crash() __asm__ __volatile__("brk 0") +#else +#error "Missing Crash() implementation for target CPU architecture." +#endif void assert_fail_impl() { Common::Log::Stop(); @@ -18,3 +25,8 @@ void assert_fail_impl() { Crash(); throw std::runtime_error("Unreachable code"); } + +void assert_fail_debug_msg(const char* msg) { + LOG_CRITICAL(Debug, "Assertion Failed!\n{}", msg); + assert_fail_impl(); +} diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 72af7b5cd..bc8a2763c 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -81,7 +81,9 @@ #pragma pack(1) template struct BitField { -private: + + using Type = T; + // UnderlyingType is T for non-enum types and the underlying type of T if // T is an enumeration. Note that T is wrapped within an enable_if in the // former case to workaround compile errors which arise when using @@ -92,7 +94,6 @@ private: // We store the value as the unsigned type to avoid undefined behaviour on value shifting using StorageType = std::make_unsigned_t; -public: /// Constants to allow limited introspection of fields if needed static constexpr std::size_t position = Position; static constexpr std::size_t bits = Bits; diff --git a/src/common/config.cpp b/src/common/config.cpp index ddd1d3257..1dde7223c 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -3,33 +3,68 @@ #include #include +#include #include +#include // for wstring support #include +#include "common/logging/formatter.h" +#include "common/path_util.h" #include "config.h" +namespace toml { +template +std::filesystem::path find_fs_path_or(const basic_value& v, const K& ky, + std::filesystem::path opt) { + try { + auto str = find(v, ky); + if (str.empty()) { + return opt; + } + std::u8string u8str{(char8_t*)&str.front(), (char8_t*)&str.back() + 1}; + return std::filesystem::path{u8str}; + } catch (...) { + return opt; + } +} +} // namespace toml + namespace Config { static bool isNeo = false; static bool isFullscreen = false; +static bool playBGM = false; +static int BGMvolume = 50; +static bool enableDiscordRPC = false; static u32 screenWidth = 1280; static u32 screenHeight = 720; static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select static std::string logFilter; static std::string logType = "async"; static std::string userName = "shadPS4"; +static std::string updateChannel; +static std::string backButtonBehavior = "left"; +static bool useSpecialPad = false; +static int specialPadClass = 1; static bool isDebugDump = false; static bool isShowSplash = false; +static bool isAutoUpdate = false; static bool isNullGpu = false; +static bool shouldCopyGPUBuffers = false; static bool shouldDumpShaders = false; -static bool shouldDumpPM4 = false; static u32 vblankDivider = 1; static bool vkValidation = false; static bool vkValidationSync = false; static bool vkValidationGpu = false; static bool rdocEnable = false; -static bool rdocMarkersEnable = false; +static bool vkMarkers = false; +static bool vkCrashDiagnostic = false; +static s16 cursorState = HideCursorState::Idle; +static int cursorHideTimeout = 5; // 5 seconds (default) +static bool separateupdatefolder = false; + // Gui -std::string settings_install_dir = ""; +std::vector settings_install_dirs = {}; +std::filesystem::path settings_addon_install_dir = {}; u32 main_window_geometry_x = 400; u32 main_window_geometry_y = 400; u32 main_window_geometry_w = 1280; @@ -45,6 +80,7 @@ u32 m_window_size_H = 720; std::vector m_pkg_viewer; std::vector m_elf_viewer; std::vector m_recent_files; +std::string emulator_language = "en"; // Settings u32 m_language = 1; // english @@ -56,6 +92,26 @@ bool isFullscreenMode() { return isFullscreen; } +bool getPlayBGM() { + return playBGM; +} + +int getBGMvolume() { + return BGMvolume; +} + +bool getEnableDiscordRPC() { + return enableDiscordRPC; +} + +s16 getCursorState() { + return cursorState; +} + +int getCursorHideTimeout() { + return cursorHideTimeout; +} + u32 getScreenWidth() { return screenWidth; } @@ -80,6 +136,22 @@ std::string getUserName() { return userName; } +std::string getUpdateChannel() { + return updateChannel; +} + +std::string getBackButtonBehavior() { + return backButtonBehavior; +} + +bool getUseSpecialPad() { + return useSpecialPad; +} + +int getSpecialPadClass() { + return specialPadClass; +} + bool debugDump() { return isDebugDump; } @@ -88,16 +160,20 @@ bool showSplash() { return isShowSplash; } +bool autoUpdate() { + return isAutoUpdate; +} + bool nullGpu() { return isNullGpu; } -bool dumpShaders() { - return shouldDumpShaders; +bool copyGPUCmdBuffers() { + return shouldCopyGPUBuffers; } -bool dumpPM4() { - return shouldDumpPM4; +bool dumpShaders() { + return shouldDumpShaders; } bool isRdocEnabled() { @@ -105,7 +181,7 @@ bool isRdocEnabled() { } bool isMarkersEnabled() { - return rdocMarkersEnable; + return vkMarkers; } u32 vblankDiv() { @@ -124,6 +200,18 @@ bool vkValidationGpuEnabled() { return vkValidationGpu; } +bool vkMarkersEnabled() { + return vkMarkers || vkCrashDiagnostic; // Crash diagnostic forces markers on +} + +bool vkCrashDiagnosticEnabled() { + return vkCrashDiagnostic; +} + +bool getSeparateUpdateEnabled() { + return separateupdatefolder; +} + void setGpuId(s32 selectedGpuId) { gpuId = selectedGpuId; } @@ -144,16 +232,20 @@ void setShowSplash(bool enable) { isShowSplash = enable; } +void setAutoUpdate(bool enable) { + isAutoUpdate = enable; +} + void setNullGpu(bool enable) { isNullGpu = enable; } -void setDumpShaders(bool enable) { - shouldDumpShaders = enable; +void setCopyGPUCmdBuffers(bool enable) { + shouldCopyGPUBuffers = enable; } -void setDumpPM4(bool enable) { - shouldDumpPM4 = enable; +void setDumpShaders(bool enable) { + shouldDumpShaders = enable; } void setVkValidation(bool enable) { @@ -176,6 +268,26 @@ void setFullscreenMode(bool enable) { isFullscreen = enable; } +void setPlayBGM(bool enable) { + playBGM = enable; +} + +void setBGMvolume(int volume) { + BGMvolume = volume; +} + +void setEnableDiscordRPC(bool enable) { + enableDiscordRPC = enable; +} + +void setCursorState(s16 newCursorState) { + cursorState = newCursorState; +} + +void setCursorHideTimeout(int newcursorHideTimeout) { + cursorHideTimeout = newcursorHideTimeout; +} + void setLanguage(u32 language) { m_language = language; } @@ -196,14 +308,48 @@ void setUserName(const std::string& type) { userName = type; } +void setUpdateChannel(const std::string& type) { + updateChannel = type; +} + +void setBackButtonBehavior(const std::string& type) { + backButtonBehavior = type; +} + +void setUseSpecialPad(bool use) { + useSpecialPad = use; +} + +void setSpecialPadClass(int type) { + specialPadClass = type; +} + +void setSeparateUpdateEnabled(bool use) { + separateupdatefolder = use; +} + void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) { main_window_geometry_x = x; main_window_geometry_y = y; main_window_geometry_w = w; main_window_geometry_h = h; } -void setGameInstallDir(const std::string& dir) { - settings_install_dir = dir; +bool addGameInstallDir(const std::filesystem::path& dir) { + if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) == + settings_install_dirs.end()) { + settings_install_dirs.push_back(dir); + return true; + } + return false; +} +void removeGameInstallDir(const std::filesystem::path& dir) { + auto iterator = std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir); + if (iterator != settings_install_dirs.end()) { + settings_install_dirs.erase(iterator); + } +} +void setAddonInstallDir(const std::filesystem::path& dir) { + settings_addon_install_dir = dir; } void setMainWindowTheme(u32 theme) { mw_themes = theme; @@ -214,10 +360,10 @@ void setIconSize(u32 size) { void setIconSizeGrid(u32 size) { m_icon_size_grid = size; } -void setSliderPositon(u32 pos) { +void setSliderPosition(u32 pos) { m_slider_pos = pos; } -void setSliderPositonGrid(u32 pos) { +void setSliderPositionGrid(u32 pos) { m_slider_pos_grid = pos; } void setTableMode(u32 mode) { @@ -242,6 +388,10 @@ void setRecentFiles(const std::vector& recentFiles) { m_recent_files = recentFiles; } +void setEmulatorLanguage(std::string language) { + emulator_language = language; +} + u32 getMainWindowGeometryX() { return main_window_geometry_x; } @@ -254,8 +404,15 @@ u32 getMainWindowGeometryW() { u32 getMainWindowGeometryH() { return main_window_geometry_h; } -std::string getGameInstallDir() { - return settings_install_dir; +const std::vector& getGameInstallDirs() { + return settings_install_dirs; +} +std::filesystem::path getAddonInstallDir() { + if (settings_addon_install_dir.empty()) { + // Default for users without a config file or a config file from before this option existed + return Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "addcont"; + } + return settings_addon_install_dir; } u32 getMainWindowTheme() { return mw_themes; @@ -266,10 +423,10 @@ u32 getIconSize() { u32 getIconSizeGrid() { return m_icon_size_grid; } -u32 getSliderPositon() { +u32 getSliderPosition() { return m_slider_pos; } -u32 getSliderPositonGrid() { +u32 getSliderPositionGrid() { return m_slider_pos_grid; } u32 getTableMode() { @@ -291,6 +448,10 @@ std::vector getRecentFiles() { return m_recent_files; } +std::string getEmulatorLanguage() { + return emulator_language; +} + u32 GetLanguage() { return m_language; } @@ -305,7 +466,10 @@ void load(const std::filesystem::path& path) { toml::value data; try { - data = toml::parse(path); + std::ifstream ifs; + ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); + ifs.open(path, std::ios_base::binary); + data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data}); } catch (std::exception& ex) { fmt::print("Got exception trying to load config file. Exception: {}\n", ex.what()); return; @@ -315,10 +479,30 @@ void load(const std::filesystem::path& path) { isNeo = toml::find_or(general, "isPS4Pro", false); isFullscreen = toml::find_or(general, "Fullscreen", false); + playBGM = toml::find_or(general, "playBGM", false); + BGMvolume = toml::find_or(general, "BGMvolume", 50); + enableDiscordRPC = toml::find_or(general, "enableDiscordRPC", true); logFilter = toml::find_or(general, "logFilter", ""); logType = toml::find_or(general, "logType", "sync"); userName = toml::find_or(general, "userName", "shadPS4"); + if (Common::isRelease) { + updateChannel = toml::find_or(general, "updateChannel", "Release"); + } else { + updateChannel = toml::find_or(general, "updateChannel", "Nightly"); + } isShowSplash = toml::find_or(general, "showSplash", true); + isAutoUpdate = toml::find_or(general, "autoUpdate", false); + separateupdatefolder = toml::find_or(general, "separateUpdateEnabled", false); + } + + if (data.contains("Input")) { + const toml::value& input = data.at("Input"); + + cursorState = toml::find_or(input, "cursorState", HideCursorState::Idle); + cursorHideTimeout = toml::find_or(input, "cursorHideTimeout", 5); + backButtonBehavior = toml::find_or(input, "backButtonBehavior", "left"); + useSpecialPad = toml::find_or(input, "useSpecialPad", false); + specialPadClass = toml::find_or(input, "specialPadClass", 1); } if (data.contains("GPU")) { @@ -327,8 +511,8 @@ void load(const std::filesystem::path& path) { screenWidth = toml::find_or(gpu, "screenWidth", screenWidth); screenHeight = toml::find_or(gpu, "screenHeight", screenHeight); isNullGpu = toml::find_or(gpu, "nullGpu", false); + shouldCopyGPUBuffers = toml::find_or(gpu, "copyGPUBuffers", false); shouldDumpShaders = toml::find_or(gpu, "dumpShaders", false); - shouldDumpPM4 = toml::find_or(gpu, "dumpPM4", false); vblankDivider = toml::find_or(gpu, "vblankDivider", 1); } @@ -340,7 +524,8 @@ void load(const std::filesystem::path& path) { vkValidationSync = toml::find_or(vk, "validation_sync", false); vkValidationGpu = toml::find_or(vk, "validation_gpu", true); rdocEnable = toml::find_or(vk, "rdocEnable", false); - rdocMarkersEnable = toml::find_or(vk, "rdocMarkersEnable", false); + vkMarkers = toml::find_or(vk, "rdocMarkersEnable", false); + vkCrashDiagnostic = toml::find_or(vk, "crashDiagnostic", false); } if (data.contains("Debug")) { @@ -359,7 +544,20 @@ void load(const std::filesystem::path& path) { mw_themes = toml::find_or(gui, "theme", 0); m_window_size_W = toml::find_or(gui, "mw_width", 0); m_window_size_H = toml::find_or(gui, "mw_height", 0); - settings_install_dir = toml::find_or(gui, "installDir", ""); + + // TODO Migration code, after a major release this should be removed. + auto old_game_install_dir = toml::find_fs_path_or(gui, "installDir", {}); + if (!old_game_install_dir.empty()) { + addGameInstallDir(std::filesystem::path{old_game_install_dir}); + } else { + const auto install_dir_array = + toml::find_or>(gui, "installDirs", {}); + for (const auto& dir : install_dir_array) { + addGameInstallDir(std::filesystem::path{dir}); + } + } + + settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); main_window_geometry_x = toml::find_or(gui, "geometry_x", 0); main_window_geometry_y = toml::find_or(gui, "geometry_y", 0); main_window_geometry_w = toml::find_or(gui, "geometry_w", 0); @@ -368,6 +566,7 @@ void load(const std::filesystem::path& path) { m_elf_viewer = toml::find_or>(gui, "elfDirs", {}); m_recent_files = toml::find_or>(gui, "recentFiles", {}); m_table_mode = toml::find_or(gui, "gameTableMode", 0); + emulator_language = toml::find_or(gui, "emulatorLanguage", "en"); } if (data.contains("Settings")) { @@ -382,37 +581,51 @@ void save(const std::filesystem::path& path) { std::error_code error; if (std::filesystem::exists(path, error)) { try { - data = toml::parse(path); + std::ifstream ifs; + ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); + ifs.open(path, std::ios_base::binary); + data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data}); } catch (const std::exception& ex) { fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what()); return; } } else { if (error) { - fmt::print("Filesystem error accessing {} (error: {})\n", path.string(), - error.message().c_str()); + fmt::print("Filesystem error: {}\n", error.message()); } - fmt::print("Saving new configuration file {}\n", path.string()); + fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string())); } data["General"]["isPS4Pro"] = isNeo; data["General"]["Fullscreen"] = isFullscreen; + data["General"]["playBGM"] = playBGM; + data["General"]["BGMvolume"] = BGMvolume; + data["General"]["enableDiscordRPC"] = enableDiscordRPC; data["General"]["logFilter"] = logFilter; data["General"]["logType"] = logType; data["General"]["userName"] = userName; + data["General"]["updateChannel"] = updateChannel; data["General"]["showSplash"] = isShowSplash; + data["General"]["autoUpdate"] = isAutoUpdate; + data["General"]["separateUpdateEnabled"] = separateupdatefolder; + data["Input"]["cursorState"] = cursorState; + data["Input"]["cursorHideTimeout"] = cursorHideTimeout; + data["Input"]["backButtonBehavior"] = backButtonBehavior; + data["Input"]["useSpecialPad"] = useSpecialPad; + data["Input"]["specialPadClass"] = specialPadClass; data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenHeight"] = screenHeight; data["GPU"]["nullGpu"] = isNullGpu; + data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers; data["GPU"]["dumpShaders"] = shouldDumpShaders; - data["GPU"]["dumpPM4"] = shouldDumpPM4; data["GPU"]["vblankDivider"] = vblankDivider; data["Vulkan"]["gpuId"] = gpuId; data["Vulkan"]["validation"] = vkValidation; data["Vulkan"]["validation_sync"] = vkValidationSync; data["Vulkan"]["validation_gpu"] = vkValidationGpu; data["Vulkan"]["rdocEnable"] = rdocEnable; - data["Vulkan"]["rdocMarkersEnable"] = rdocMarkersEnable; + data["Vulkan"]["rdocMarkersEnable"] = vkMarkers; + data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic; data["Debug"]["DebugDump"] = isDebugDump; data["GUI"]["theme"] = mw_themes; data["GUI"]["iconSize"] = m_icon_size; @@ -422,7 +635,15 @@ void save(const std::filesystem::path& path) { data["GUI"]["gameTableMode"] = m_table_mode; data["GUI"]["mw_width"] = m_window_size_W; data["GUI"]["mw_height"] = m_window_size_H; - data["GUI"]["installDir"] = settings_install_dir; + + std::vector install_dirs; + for (const auto& dirString : settings_install_dirs) { + install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data}); + } + data["GUI"]["installDirs"] = install_dirs; + + data["GUI"]["addonInstallDir"] = + std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; data["GUI"]["geometry_x"] = main_window_geometry_x; data["GUI"]["geometry_y"] = main_window_geometry_y; data["GUI"]["geometry_w"] = main_window_geometry_w; @@ -430,9 +651,13 @@ void save(const std::filesystem::path& path) { data["GUI"]["pkgDirs"] = m_pkg_viewer; data["GUI"]["elfDirs"] = m_elf_viewer; data["GUI"]["recentFiles"] = m_recent_files; + data["GUI"]["emulatorLanguage"] = emulator_language; data["Settings"]["consoleLanguage"] = m_language; + // TODO Migration code, after a major release this should be removed. + data.at("GUI").as_table().erase("installDir"); + std::ofstream file(path, std::ios::out); file << data; file.close(); @@ -441,19 +666,37 @@ void save(const std::filesystem::path& path) { void setDefaultValues() { isNeo = false; isFullscreen = false; + playBGM = false; + BGMvolume = 50; + enableDiscordRPC = true; screenWidth = 1280; screenHeight = 720; logFilter = ""; logType = "async"; userName = "shadPS4"; + if (Common::isRelease) { + updateChannel = "Release"; + } else { + updateChannel = "Nightly"; + } + cursorState = HideCursorState::Idle; + cursorHideTimeout = 5; + backButtonBehavior = "left"; + useSpecialPad = false; + specialPadClass = 1; isDebugDump = false; isShowSplash = false; + isAutoUpdate = false; isNullGpu = false; shouldDumpShaders = false; - shouldDumpPM4 = false; vblankDivider = 1; vkValidation = false; + vkValidationSync = false; + vkValidationGpu = false; rdocEnable = false; + vkMarkers = false; + vkCrashDiagnostic = false; + emulator_language = "en"; m_language = 1; gpuId = -1; } diff --git a/src/common/config.h b/src/common/config.h index 9bf91e692..9c71c96a8 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -8,14 +8,29 @@ #include "types.h" namespace Config { + +enum HideCursorState : s16 { Never, Idle, Always }; + void load(const std::filesystem::path& path); void save(const std::filesystem::path& path); bool isNeoMode(); bool isFullscreenMode(); +bool getPlayBGM(); +int getBGMvolume(); +bool getEnableDiscordRPC(); +bool getSeparateUpdateEnabled(); + std::string getLogFilter(); std::string getLogType(); std::string getUserName(); +std::string getUpdateChannel(); + +s16 getCursorState(); +int getCursorHideTimeout(); +std::string getBackButtonBehavior(); +bool getUseSpecialPad(); +int getSpecialPadClass(); u32 getScreenWidth(); u32 getScreenHeight(); @@ -23,26 +38,38 @@ s32 getGpuId(); bool debugDump(); bool showSplash(); +bool autoUpdate(); bool nullGpu(); +bool copyGPUCmdBuffers(); bool dumpShaders(); -bool dumpPM4(); bool isRdocEnabled(); -bool isMarkersEnabled(); u32 vblankDiv(); void setDebugDump(bool enable); void setShowSplash(bool enable); +void setAutoUpdate(bool enable); void setNullGpu(bool enable); +void setCopyGPUCmdBuffers(bool enable); void setDumpShaders(bool enable); -void setDumpPM4(bool enable); void setVblankDiv(u32 value); void setGpuId(s32 selectedGpuId); void setScreenWidth(u32 width); void setScreenHeight(u32 height); void setFullscreenMode(bool enable); +void setPlayBGM(bool enable); +void setBGMvolume(int volume); +void setEnableDiscordRPC(bool enable); void setLanguage(u32 language); void setNeoMode(bool enable); void setUserName(const std::string& type); +void setUpdateChannel(const std::string& type); +void setSeparateUpdateEnabled(bool use); + +void setCursorState(s16 cursorState); +void setCursorHideTimeout(int newcursorHideTimeout); +void setBackButtonBehavior(const std::string& type); +void setUseSpecialPad(bool use); +void setSpecialPadClass(int type); void setLogType(const std::string& type); void setLogFilter(const std::string& type); @@ -54,38 +81,45 @@ void setRdocEnabled(bool enable); bool vkValidationEnabled(); bool vkValidationSyncEnabled(); bool vkValidationGpuEnabled(); +bool vkMarkersEnabled(); +bool vkCrashDiagnosticEnabled(); // Gui void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h); -void setGameInstallDir(const std::string& dir); +bool addGameInstallDir(const std::filesystem::path& dir); +void removeGameInstallDir(const std::filesystem::path& dir); +void setAddonInstallDir(const std::filesystem::path& dir); void setMainWindowTheme(u32 theme); void setIconSize(u32 size); void setIconSizeGrid(u32 size); -void setSliderPositon(u32 pos); -void setSliderPositonGrid(u32 pos); +void setSliderPosition(u32 pos); +void setSliderPositionGrid(u32 pos); void setTableMode(u32 mode); void setMainWindowWidth(u32 width); void setMainWindowHeight(u32 height); void setPkgViewer(const std::vector& pkgList); void setElfViewer(const std::vector& elfList); void setRecentFiles(const std::vector& recentFiles); +void setEmulatorLanguage(std::string language); u32 getMainWindowGeometryX(); u32 getMainWindowGeometryY(); u32 getMainWindowGeometryW(); u32 getMainWindowGeometryH(); -std::string getGameInstallDir(); +const std::vector& getGameInstallDirs(); +std::filesystem::path getAddonInstallDir(); u32 getMainWindowTheme(); u32 getIconSize(); u32 getIconSizeGrid(); -u32 getSliderPositon(); -u32 getSliderPositonGrid(); +u32 getSliderPosition(); +u32 getSliderPositionGrid(); u32 getTableMode(); u32 getMainWindowWidth(); u32 getMainWindowHeight(); std::vector getPkgViewer(); std::vector getElfViewer(); std::vector getRecentFiles(); +std::string getEmulatorLanguage(); void setDefaultValues(); diff --git a/src/common/cstring.h b/src/common/cstring.h new file mode 100644 index 000000000..45c291c14 --- /dev/null +++ b/src/common/cstring.h @@ -0,0 +1,171 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "assert.h" + +namespace Common { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-undefined-compare" + +/** + * @brief A null-terminated string with a fixed maximum length + * This class is not meant to be used as a general-purpose string class + * It is meant to be used as `char[N]` where memory layout is fixed + * @tparam N Maximum length of the string + * @tparam T Type of character + */ +template +class CString { + T data[N]{}; + +public: + class Iterator; + + CString() = default; + + template + explicit CString(const CString& other) + requires(M <= N) + { + if (this == nullptr) { + return; + } + std::ranges::copy(other.begin(), other.end(), data); + } + + void FromString(const std::basic_string_view& str) { + if (this == nullptr) { + return; + } + size_t p = str.copy(data, N - 1); + data[p] = '\0'; + } + + void Zero() { + if (this == nullptr) { + return; + } + std::ranges::fill(data, 0); + } + + explicit(false) operator std::basic_string_view() const { + if (this == nullptr) { + return {}; + } + return std::basic_string_view{data}; + } + + explicit operator std::basic_string() const { + if (this == nullptr) { + return {}; + } + return std::basic_string{data}; + } + + std::basic_string to_string() const { + if (this == nullptr) { + return {}; + } + return std::basic_string{data}; + } + + std::basic_string_view to_view() const { + if (this == nullptr) { + return {}; + } + return std::basic_string_view{data}; + } + + T* begin() { + if (this == nullptr) { + return nullptr; + } + return data; + } + + const T* begin() const { + if (this == nullptr) { + return nullptr; + } + return data; + } + + T* end() { + if (this == nullptr) { + return nullptr; + } + return data + N; + } + + const T* end() const { + if (this == nullptr) { + return nullptr; + } + return data + N; + } + + constexpr std::size_t capacity() const { + return N; + } + + std::size_t size() const { + return std::char_traits::length(data); + } + + T& operator[](size_t idx) { + return data[idx]; + } + + const T& operator[](size_t idx) const { + return data[idx]; + } + + class Iterator { + T* ptr; + T* end; + + public: + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = T*; + using reference = T&; + using iterator_category = std::random_access_iterator_tag; + + Iterator() = default; + explicit Iterator(T* ptr) : ptr(ptr), end(ptr + N) {} + + Iterator& operator++() { + ++ptr; + return *this; + } + + Iterator operator++(int) { + Iterator tmp = *this; + ++ptr; + return tmp; + } + + operator T*() { + ASSERT_MSG(ptr >= end, "CString iterator out of bounds"); + return ptr; + } + }; +}; + +static_assert(sizeof(CString<13>) == sizeof(char[13])); // Ensure size still matches a simple array +static_assert(std::weakly_incrementable::Iterator>); + +template +using CWString = CString; + +template +using CU16String = CString; + +#pragma clang diagnostic pop + +} // namespace Common \ No newline at end of file diff --git a/src/common/debug.h b/src/common/debug.h index 50022a156..596ad7b84 100644 --- a/src/common/debug.h +++ b/src/common/debug.h @@ -29,7 +29,7 @@ static inline bool IsProfilerConnected() { #define TRACK_ALLOC(ptr, size, pool) TracyAllocN(std::bit_cast(ptr), (size), (pool)) #define TRACK_FREE(ptr, pool) TracyFreeN(std::bit_cast(ptr), (pool)) -enum MarkersPallete : int { +enum MarkersPalette : int { EmulatorMarkerColor = 0x264653, RendererMarkerColor = 0x2a9d8f, HleMarkerColor = 0xe9c46a, diff --git a/src/common/disassembler.cpp b/src/common/decoder.cpp similarity index 65% rename from src/common/disassembler.cpp rename to src/common/decoder.cpp index 2d1264a4e..249907419 100644 --- a/src/common/disassembler.cpp +++ b/src/common/decoder.cpp @@ -2,18 +2,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include "common/disassembler.h" +#include "common/decoder.h" namespace Common { -Disassembler::Disassembler() { +DecoderImpl::DecoderImpl() { ZydisDecoderInit(&m_decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); ZydisFormatterInit(&m_formatter, ZYDIS_FORMATTER_STYLE_INTEL); } -Disassembler::~Disassembler() = default; +DecoderImpl::~DecoderImpl() = default; -void Disassembler::printInstruction(void* code, u64 address) { +void DecoderImpl::printInstruction(void* code, u64 address) { ZydisDecodedInstruction instruction; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE]; ZyanStatus status = @@ -25,8 +25,8 @@ void Disassembler::printInstruction(void* code, u64 address) { } } -void Disassembler::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, - u64 address) { +void DecoderImpl::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, + u64 address) { const int bufLen = 256; char szBuffer[bufLen]; ZydisFormatterFormatInstruction(&m_formatter, &inst, operands, inst.operand_count_visible, @@ -34,4 +34,9 @@ void Disassembler::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* fmt::print("instruction: {}\n", szBuffer); } +ZyanStatus DecoderImpl::decodeInstruction(ZydisDecodedInstruction& inst, + ZydisDecodedOperand* operands, void* data, u64 size) { + return ZydisDecoderDecodeFull(&m_decoder, data, size, &inst, operands); +} + } // namespace Common diff --git a/src/common/disassembler.h b/src/common/decoder.h similarity index 60% rename from src/common/disassembler.h rename to src/common/decoder.h index b81f9e31b..1f2219596 100644 --- a/src/common/disassembler.h +++ b/src/common/decoder.h @@ -4,21 +4,26 @@ #pragma once #include +#include "common/singleton.h" #include "common/types.h" namespace Common { -class Disassembler { +class DecoderImpl { public: - Disassembler(); - ~Disassembler(); + DecoderImpl(); + ~DecoderImpl(); void printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, u64 address); void printInstruction(void* code, u64 address); + ZyanStatus decodeInstruction(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, + void* data, u64 size = 15); private: ZydisDecoder m_decoder; ZydisFormatter m_formatter; }; +using Decoder = Common::Singleton; + } // namespace Common diff --git a/src/common/discord.cpp b/src/common/discord.cpp deleted file mode 100644 index cce799a32..000000000 --- a/src/common/discord.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include "common/discord.h" - -namespace Discord { - -void RPC::init() { - DiscordEventHandlers handlers{}; - Discord_Initialize("1139939140494971051", &handlers, 1, nullptr); - - startTimestamp = time(nullptr); - enabled = true; -} - -void RPC::update(Discord::RPCStatus status, const std::string& game) { - DiscordRichPresence rpc{}; - - if (status == Discord::RPCStatus::Playing) { - rpc.details = "Playing a game"; - rpc.state = game.c_str(); - } else { - rpc.details = "Idle"; - } - - rpc.largeImageKey = "shadps4"; - rpc.largeImageText = "ShadPS4 is a PS4 emulator"; - rpc.startTimestamp = startTimestamp; - - Discord_UpdatePresence(&rpc); -} - -void RPC::stop() { - if (enabled) { - enabled = false; - Discord_ClearPresence(); - Discord_Shutdown(); - } -} - -} // namespace Discord diff --git a/src/common/discord_rpc_handler.cpp b/src/common/discord_rpc_handler.cpp new file mode 100644 index 000000000..91b278a15 --- /dev/null +++ b/src/common/discord_rpc_handler.cpp @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include "src/common/discord_rpc_handler.h" + +namespace DiscordRPCHandler { + +void RPC::init() { + DiscordEventHandlers handlers{}; + + Discord_Initialize("1139939140494971051", &handlers, 1, nullptr); + startTimestamp = time(nullptr); + rpcEnabled = true; +} + +void RPC::setStatusIdling() { + DiscordRichPresence rpc{}; + rpc.largeImageKey = "https://github.com/shadps4-emu/shadPS4/raw/main/.github/shadps4.png"; + rpc.largeImageText = "shadPS4 is a PS4 emulator"; + rpc.startTimestamp = startTimestamp; + rpc.details = "Idle"; + + status = RPCStatus::Idling; + Discord_UpdatePresence(&rpc); +} + +void RPC::setStatusPlaying(const std::string& game_name, const std::string& game_id) { + DiscordRichPresence rpc{}; + + rpc.details = "Playing"; + rpc.state = game_name.c_str(); + std::string largeImageUrl = + "https://store.playstation.com/store/api/chihiro/00_09_000/titlecontainer/US/en/999/" + + game_id + "_00/image"; + rpc.largeImageKey = largeImageUrl.c_str(); + rpc.largeImageText = game_name.c_str(); + rpc.startTimestamp = startTimestamp; + + status = RPCStatus::Playing; + Discord_UpdatePresence(&rpc); +} + +void RPC::shutdown() { + if (rpcEnabled) { + rpcEnabled = false; + Discord_ClearPresence(); + Discord_Shutdown(); + } +} + +bool RPC::getRPCEnabled() { + return rpcEnabled; +} + +} // namespace DiscordRPCHandler diff --git a/src/common/discord.h b/src/common/discord_rpc_handler.h similarity index 53% rename from src/common/discord.h rename to src/common/discord_rpc_handler.h index 54aa6c17c..1e451e181 100644 --- a/src/common/discord.h +++ b/src/common/discord_rpc_handler.h @@ -7,7 +7,7 @@ #include #include -namespace Discord { +namespace DiscordRPCHandler { enum class RPCStatus { Idling, @@ -16,12 +16,15 @@ enum class RPCStatus { class RPC { std::uint64_t startTimestamp; - bool enabled = false; + bool rpcEnabled = false; + RPCStatus status; public: void init(); - void update(RPCStatus status, const std::string& title); - void stop(); + void setStatusIdling(); + void setStatusPlaying(const std::string& game_name, const std::string& game_id); + void shutdown(); + bool getRPCEnabled(); }; -} // namespace Discord +} // namespace DiscordRPCHandler diff --git a/src/common/elf_info.h b/src/common/elf_info.h new file mode 100644 index 000000000..5a2c914e0 --- /dev/null +++ b/src/common/elf_info.h @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "assert.h" +#include "singleton.h" +#include "types.h" + +namespace Core { +class Emulator; +} + +namespace Common { + +class ElfInfo { + friend class Core::Emulator; + + bool initialized = false; + + std::string game_serial{}; + std::string title{}; + std::string app_ver{}; + u32 firmware_ver = 0; + u32 raw_firmware_ver = 0; + +public: + static constexpr u32 FW_15 = 0x1500000; + static constexpr u32 FW_16 = 0x1600000; + static constexpr u32 FW_17 = 0x1700000; + static constexpr u32 FW_20 = 0x2000000; + static constexpr u32 FW_25 = 0x2500000; + static constexpr u32 FW_30 = 0x3000000; + static constexpr u32 FW_40 = 0x4000000; + static constexpr u32 FW_45 = 0x4500000; + static constexpr u32 FW_50 = 0x5000000; + static constexpr u32 FW_80 = 0x8000000; + + static ElfInfo& Instance() { + return *Singleton::Instance(); + } + + [[nodiscard]] std::string_view GameSerial() const { + ASSERT(initialized); + return Instance().game_serial; + } + + [[nodiscard]] std::string_view Title() const { + ASSERT(initialized); + return title; + } + + [[nodiscard]] std::string_view AppVer() const { + ASSERT(initialized); + return app_ver; + } + + [[nodiscard]] u32 FirmwareVer() const { + ASSERT(initialized); + return firmware_ver; + } + + [[nodiscard]] u32 RawFirmwareVer() const { + ASSERT(initialized); + return raw_firmware_ver; + } +}; + +} // namespace Common diff --git a/src/common/fixed_value.h b/src/common/fixed_value.h new file mode 100644 index 000000000..e32a795f2 --- /dev/null +++ b/src/common/fixed_value.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +/** + * @brief A template class that encapsulates a fixed, compile-time constant value. + * + * @tparam T The type of the value. + * @tparam Value The fixed value of type T. + * + * This class provides a way to encapsulate a value that is constant and known at compile-time. + * The value is stored as a private member and cannot be changed. Any attempt to assign a new + * value to an object of this class will reset it to the fixed value. + */ +template +class FixedValue { + T m_value{Value}; + +public: + constexpr FixedValue() = default; + + constexpr explicit(false) operator T() const { + return m_value; + } + + FixedValue& operator=(const T&) { + m_value = Value; + return *this; + } + FixedValue& operator=(T&&) noexcept { + m_value = {Value}; + return *this; + } +}; diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp index fbc37a10c..dd3a40cae 100644 --- a/src/common/io_file.cpp +++ b/src/common/io_file.cpp @@ -192,8 +192,9 @@ int IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileS #endif if (!IsOpen()) { - LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}", - PathToUTF8String(file_path)); + const auto ec = std::error_code{result, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, error_message={}", + PathToUTF8String(file_path), ec.message()); } return result; @@ -230,7 +231,7 @@ void IOFile::Unlink() { // Mark the file for deletion // TODO: Also remove the file path? -#if _WIN64 +#ifdef _WIN64 FILE_DISPOSITION_INFORMATION disposition; IO_STATUS_BLOCK iosb; @@ -241,7 +242,11 @@ void IOFile::Unlink() { NtSetInformationFile(hfile, &iosb, &disposition, sizeof(disposition), FileDispositionInformation); #else - UNREACHABLE_MSG("Missing Linux implementation"); + if (unlink(file_path.c_str()) != 0) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to unlink the file at path={}, ec_message={}", + PathToUTF8String(file_path), ec.message()); + } #endif } @@ -372,6 +377,18 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const { return false; } + u64 size = GetSize(); + if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) { + LOG_ERROR(Common_Filesystem, "Seeking past the end of the file"); + return false; + } else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) { + LOG_ERROR(Common_Filesystem, "Seeking past the end of the file"); + return false; + } else if (origin == SeekOrigin::End && offset > 0) { + LOG_ERROR(Common_Filesystem, "Seeking past the end of the file"); + return false; + } + errno = 0; const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0; @@ -396,4 +413,18 @@ s64 IOFile::Tell() const { return ftello(file); } +u64 GetDirectorySize(const std::filesystem::path& path) { + if (!fs::exists(path)) { + return 0; + } + + u64 total = 0; + for (const auto& entry : fs::recursive_directory_iterator(path)) { + if (fs::is_regular_file(entry.path())) { + total += fs::file_size(entry.path()); + } + } + return total; +} + } // namespace Common::FS diff --git a/src/common/io_file.h b/src/common/io_file.h index 2c3df3f69..8fed4981f 100644 --- a/src/common/io_file.h +++ b/src/common/io_file.h @@ -205,9 +205,9 @@ public: return WriteSpan(string); } - static void WriteBytes(const std::filesystem::path path, std::span data) { + static size_t WriteBytes(const std::filesystem::path path, std::span data) { IOFile out(path, FileAccessMode::Write); - out.Write(data); + return out.Write(data); } private: @@ -219,4 +219,6 @@ private: uintptr_t file_mapping = 0; }; +u64 GetDirectorySize(const std::filesystem::path& path); + } // namespace Common::FS diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index a21af8bba..7802977f5 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -144,6 +144,10 @@ public: initialization_in_progress_suppress_logging = false; } + static bool IsActive() { + return instance != nullptr; + } + static void Start() { instance->StartBackendThread(); } @@ -275,6 +279,10 @@ void Initialize(std::string_view log_file) { Impl::Initialize(log_file.empty() ? LOG_FILE : log_file); } +bool IsActive() { + return Impl::IsActive(); +} + void Start() { Impl::Start(); } diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 91c9da832..a1ad66369 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -13,6 +13,8 @@ class Filter; /// Initializes the logging system. This should be the first thing called in main. void Initialize(std::string_view log_file = ""); +bool IsActive(); + /// Starts the logging threads. void Start(); diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index ab3468ca0..051bbd79e 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -113,10 +113,17 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, ImeDialog) \ SUB(Lib, AvPlayer) \ SUB(Lib, Ngs2) \ + SUB(Lib, Audio3d) \ + SUB(Lib, Ime) \ + SUB(Lib, GameLiveStreaming) \ + SUB(Lib, Remoteplay) \ + SUB(Lib, SharePlay) \ + SUB(Lib, Fiber) \ CLS(Frontend) \ CLS(Render) \ SUB(Render, Vulkan) \ SUB(Render, Recompiler) \ + CLS(ImGui) \ CLS(Input) \ CLS(Tty) \ CLS(Loader) diff --git a/src/common/logging/formatter.h b/src/common/logging/formatter.h index f80905cc3..fad8451e9 100644 --- a/src/common/logging/formatter.h +++ b/src/common/logging/formatter.h @@ -19,3 +19,24 @@ struct fmt::formatter, char>> } }; #endif + +namespace fmt { +template +struct UTF { + T data; + + explicit UTF(const std::u8string_view view) { + data = view.empty() ? T{} : T{(const char*)&view.front(), (const char*)&view.back() + 1}; + } + + explicit UTF(const std::u8string& str) : UTF(std::u8string_view{str}) {} +}; +} // namespace fmt + +template <> +struct fmt::formatter, char> : formatter { + template + auto format(const UTF& wrapper, FormatContext& ctx) const { + return formatter::format(wrapper.data, ctx); + } +}; \ No newline at end of file diff --git a/src/common/logging/types.h b/src/common/logging/types.h index dd2376ea6..39319d0dc 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -29,65 +29,72 @@ enum class Level : u8 { * filter.cpp. */ enum class Class : u8 { - Log, ///< Messages about the log system itself - Common, ///< Library routines - Common_Filesystem, ///< Filesystem interface library - Common_Memory, ///< Memory mapping and management functions - Core, ///< LLE emulation core - Core_Linker, ///< The module linker - Config, ///< Emulator configuration (including commandline) - Debug, ///< Debugging tools - Kernel, ///< The HLE implementation of the PS4 kernel. - Kernel_Pthread, ///< The pthread implementation of the kernel. - Kernel_Fs, ///< The filesystem implementation of the kernel. - Kernel_Vmm, ///< The virtual memory implementation of the kernel. - Kernel_Event, ///< The event management implementation of the kernel. - Kernel_Sce, ///< The sony specific interfaces provided by the kernel. - Lib, ///< HLE implementation of system library. Each major library - ///< should have its own subclass. - Lib_LibC, ///< The LibC implementation. - Lib_Kernel, ///< The LibKernel implementation. - Lib_Pad, ///< The LibScePad implementation. - Lib_GnmDriver, ///< The LibSceGnmDriver implementation. - Lib_SystemService, ///< The LibSceSystemService implementation. - Lib_UserService, ///< The LibSceUserService implementation. - Lib_VideoOut, ///< The LibSceVideoOut implementation. - Lib_CommonDlg, ///< The LibSceCommonDialog implementation. - Lib_MsgDlg, ///< The LibSceMsgDialog implementation. - Lib_AudioOut, ///< The LibSceAudioOut implementation. - Lib_AudioIn, ///< The LibSceAudioIn implementation. - Lib_Net, ///< The LibSceNet implementation. - Lib_NetCtl, ///< The LibSecNetCtl implementation. - Lib_SaveData, ///< The LibSceSaveData implementation. - Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation. - Lib_Ssl, ///< The LibSceSsl implementation. - Lib_Http, ///< The LibSceHttp implementation. - Lib_SysModule, ///< The LibSceSysModule implementation - Lib_NpManager, ///< The LibSceNpManager implementation - Lib_NpScore, ///< The LibSceNpScore implementation - Lib_NpTrophy, ///< The LibSceNpTrophy implementation - Lib_Screenshot, ///< The LibSceScreenshot implementation - Lib_LibCInternal, ///< The LibCInternal implementation. - Lib_AppContent, ///< The LibSceAppContent implementation. - Lib_Rtc, ///< The LibSceRtc implementation. - Lib_DiscMap, ///< The LibSceDiscMap implementation. - Lib_Png, ///< The LibScePng implementation. - Lib_PlayGo, ///< The LibScePlayGo implementation. - Lib_Random, ///< The libSceRandom implementation. - Lib_Usbd, ///< The LibSceUsbd implementation. - Lib_Ajm, ///< The LibSceAjm implementation. - Lib_ErrorDialog, ///< The LibSceErrorDialog implementation. - Lib_ImeDialog, ///< The LibSceImeDialog implementation. - Lib_AvPlayer, ///< The LibSceAvPlayer implementation. - Lib_Ngs2, ///< The LibSceNgs2 implementation. - Frontend, ///< Emulator UI - Render, ///< Video Core - Render_Vulkan, ///< Vulkan backend - Render_Recompiler, ///< Shader recompiler - Loader, ///< ROM loader - Input, ///< Input emulation - Tty, ///< Debug output from emu - Count ///< Total number of logging classes + Log, ///< Messages about the log system itself + Common, ///< Library routines + Common_Filesystem, ///< Filesystem interface library + Common_Memory, ///< Memory mapping and management functions + Core, ///< LLE emulation core + Core_Linker, ///< The module linker + Config, ///< Emulator configuration (including commandline) + Debug, ///< Debugging tools + Kernel, ///< The HLE implementation of the PS4 kernel. + Kernel_Pthread, ///< The pthread implementation of the kernel. + Kernel_Fs, ///< The filesystem implementation of the kernel. + Kernel_Vmm, ///< The virtual memory implementation of the kernel. + Kernel_Event, ///< The event management implementation of the kernel. + Kernel_Sce, ///< The sony specific interfaces provided by the kernel. + Lib, ///< HLE implementation of system library. Each major library + ///< should have its own subclass. + Lib_LibC, ///< The LibC implementation. + Lib_Kernel, ///< The LibKernel implementation. + Lib_Pad, ///< The LibScePad implementation. + Lib_GnmDriver, ///< The LibSceGnmDriver implementation. + Lib_SystemService, ///< The LibSceSystemService implementation. + Lib_UserService, ///< The LibSceUserService implementation. + Lib_VideoOut, ///< The LibSceVideoOut implementation. + Lib_CommonDlg, ///< The LibSceCommonDialog implementation. + Lib_MsgDlg, ///< The LibSceMsgDialog implementation. + Lib_AudioOut, ///< The LibSceAudioOut implementation. + Lib_AudioIn, ///< The LibSceAudioIn implementation. + Lib_Net, ///< The LibSceNet implementation. + Lib_NetCtl, ///< The LibSecNetCtl implementation. + Lib_SaveData, ///< The LibSceSaveData implementation. + Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation. + Lib_Ssl, ///< The LibSceSsl implementation. + Lib_Http, ///< The LibSceHttp implementation. + Lib_SysModule, ///< The LibSceSysModule implementation + Lib_NpManager, ///< The LibSceNpManager implementation + Lib_NpScore, ///< The LibSceNpScore implementation + Lib_NpTrophy, ///< The LibSceNpTrophy implementation + Lib_Screenshot, ///< The LibSceScreenshot implementation + Lib_LibCInternal, ///< The LibCInternal implementation. + Lib_AppContent, ///< The LibSceAppContent implementation. + Lib_Rtc, ///< The LibSceRtc implementation. + Lib_DiscMap, ///< The LibSceDiscMap implementation. + Lib_Png, ///< The LibScePng implementation. + Lib_PlayGo, ///< The LibScePlayGo implementation. + Lib_Random, ///< The libSceRandom implementation. + Lib_Usbd, ///< The LibSceUsbd implementation. + Lib_Ajm, ///< The LibSceAjm implementation. + Lib_ErrorDialog, ///< The LibSceErrorDialog implementation. + Lib_ImeDialog, ///< The LibSceImeDialog implementation. + Lib_AvPlayer, ///< The LibSceAvPlayer implementation. + Lib_Ngs2, ///< The LibSceNgs2 implementation. + Lib_Audio3d, ///< The LibSceAudio3d implementation. + Lib_Ime, ///< The LibSceIme implementation + Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation + Lib_Remoteplay, ///< The LibSceRemotePlay implementation + Lib_SharePlay, ///< The LibSceSharePlay implemenation + Lib_Fiber, ///< The LibSceFiber implementation. + Frontend, ///< Emulator UI + Render, ///< Video Core + Render_Vulkan, ///< Vulkan backend + Render_Recompiler, ///< Shader recompiler + ImGui, ///< ImGui + Loader, ///< ROM loader + Input, ///< Input emulation + Tty, ///< Debug output from emu + Count ///< Total number of logging classes }; } // namespace Common::Log diff --git a/src/common/memory_patcher.cpp b/src/common/memory_patcher.cpp new file mode 100644 index 000000000..d2930cf5e --- /dev/null +++ b/src/common/memory_patcher.cpp @@ -0,0 +1,446 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#ifdef ENABLE_QT_GUI +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include "common/logging/log.h" +#include "common/path_util.h" +#include "memory_patcher.h" + +namespace MemoryPatcher { + +uintptr_t g_eboot_address; +uint64_t g_eboot_image_size; +std::string g_game_serial; +std::string patchFile; +std::vector pending_patches; + +std::string toHex(unsigned long long value, size_t byteSize) { + std::stringstream ss; + ss << std::hex << std::setfill('0') << std::setw(byteSize * 2) << value; + return ss.str(); +} + +std::string convertValueToHex(const std::string type, const std::string valueStr) { + std::string result; + + if (type == "byte") { + unsigned int value = std::stoul(valueStr, nullptr, 16); + result = toHex(value, 1); + } else if (type == "bytes16") { + unsigned int value = std::stoul(valueStr, nullptr, 16); + result = toHex(value, 2); + } else if (type == "bytes32") { + unsigned long value = std::stoul(valueStr, nullptr, 16); + result = toHex(value, 4); + } else if (type == "bytes64") { + unsigned long long value = std::stoull(valueStr, nullptr, 16); + result = toHex(value, 8); + } else if (type == "float32") { + union { + float f; + uint32_t i; + } floatUnion; + floatUnion.f = std::stof(valueStr); + result = toHex(floatUnion.i, sizeof(floatUnion.i)); + } else if (type == "float64") { + union { + double d; + uint64_t i; + } doubleUnion; + doubleUnion.d = std::stod(valueStr); + result = toHex(doubleUnion.i, sizeof(doubleUnion.i)); + } else if (type == "utf8") { + std::vector byteArray = + std::vector(valueStr.begin(), valueStr.end()); + byteArray.push_back('\0'); + std::stringstream ss; + for (unsigned char c : byteArray) { + ss << std::hex << std::setfill('0') << std::setw(2) << static_cast(c); + } + result = ss.str(); + } else if (type == "utf16") { + std::wstring wide_str(valueStr.size(), L'\0'); + std::mbstowcs(&wide_str[0], valueStr.c_str(), valueStr.size()); + wide_str.resize(std::wcslen(wide_str.c_str())); + + std::u16string valueStringU16; + + for (wchar_t wc : wide_str) { + if (wc <= 0xFFFF) { + valueStringU16.push_back(static_cast(wc)); + } else { + wc -= 0x10000; + valueStringU16.push_back(static_cast(0xD800 | (wc >> 10))); + valueStringU16.push_back(static_cast(0xDC00 | (wc & 0x3FF))); + } + } + + std::vector byteArray; + // convert to little endian + for (char16_t ch : valueStringU16) { + unsigned char low_byte = static_cast(ch & 0x00FF); + unsigned char high_byte = static_cast((ch >> 8) & 0x00FF); + + byteArray.push_back(low_byte); + byteArray.push_back(high_byte); + } + byteArray.push_back('\0'); + byteArray.push_back('\0'); + std::stringstream ss; + + for (unsigned char ch : byteArray) { + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(ch); + } + result = ss.str(); + } else if (type == "bytes") { + result = valueStr; + } else if (type == "mask" || type == "mask_jump32") { + result = valueStr; + } else { + LOG_INFO(Loader, "Error applying Patch, unknown type: {}", type); + } + return result; +} + +void OnGameLoaded() { + + if (!patchFile.empty()) { + std::filesystem::path patchDir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir); + + auto filePath = (patchDir / patchFile).native(); + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(filePath.c_str()); + + if (result) { + auto patchXML = doc.child("Patch"); + for (pugi::xml_node_iterator it = patchXML.children().begin(); + it != patchXML.children().end(); ++it) { + + if (std::string(it->name()) == "Metadata") { + if (std::string(it->attribute("isEnabled").value()) == "true") { + auto patchList = it->first_child(); + + std::string currentPatchName = it->attribute("Name").value(); + + for (pugi::xml_node_iterator patchLineIt = patchList.children().begin(); + patchLineIt != patchList.children().end(); ++patchLineIt) { + + std::string type = patchLineIt->attribute("Type").value(); + std::string address = patchLineIt->attribute("Address").value(); + std::string patchValue = patchLineIt->attribute("Value").value(); + std::string maskOffsetStr = patchLineIt->attribute("type").value(); + + patchValue = convertValueToHex(type, patchValue); + + bool littleEndian = false; + + if (type == "bytes16") { + littleEndian = true; + } else if (type == "bytes32") { + littleEndian = true; + } else if (type == "bytes64") { + littleEndian = true; + } + + MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None; + int maskOffsetValue = 0; + + if (type == "mask") { + patchMask = MemoryPatcher::PatchMask::Mask; + + // im not sure if this works, there is no games to test the mask + // offset on yet + if (!maskOffsetStr.empty()) + maskOffsetValue = std::stoi(maskOffsetStr, 0, 10); + } + + if (type == "mask_jump32") + patchMask = MemoryPatcher::PatchMask::Mask_Jump32; + + MemoryPatcher::PatchMemory(currentPatchName, address, patchValue, false, + littleEndian, patchMask); + } + } + } + } + } else + LOG_ERROR(Loader, "couldnt patch parse xml : {}", result.description()); + + ApplyPendingPatches(); + return; + } + +#ifdef ENABLE_QT_GUI + // We use the QT headers for the xml and json parsing, this define is only true on QT builds + QString patchDir; + Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString repositories[] = {"GoldHEN", "shadPS4"}; + + for (const QString& repository : repositories) { + QString filesJsonPath = patchDir + "/" + repository + "/files.json"; + + QFile jsonFile(filesJsonPath); + if (!jsonFile.open(QIODevice::ReadOnly)) { + LOG_ERROR(Loader, "Unable to open files.json for reading."); + continue; + } + + QByteArray jsonData = jsonFile.readAll(); + jsonFile.close(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + + QString selectedFileName; + QString serial = QString::fromStdString(g_game_serial); + + for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) { + QString filePath = it.key(); + QJsonArray idsArray = it.value().toArray(); + + if (idsArray.contains(QJsonValue(serial))) { + selectedFileName = filePath; + break; + } + } + + if (selectedFileName.isEmpty()) { + LOG_ERROR(Loader, "No patch file found for the current serial."); + continue; + } + + QString filePath = patchDir + "/" + repository + "/" + selectedFileName; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + LOG_ERROR(Loader, "Unable to open the file for reading."); + continue; + } + + QByteArray xmlData = file.readAll(); + file.close(); + + QString newXmlData; + + QXmlStreamReader xmlReader(xmlData); + bool insideMetadata = false; + + bool isEnabled = false; + std::string currentPatchName; + while (!xmlReader.atEnd()) { + xmlReader.readNext(); + + if (xmlReader.isStartElement()) { + QJsonArray patchLines; + if (xmlReader.name() == QStringLiteral("Metadata")) { + insideMetadata = true; + + QString name = xmlReader.attributes().value("Name").toString(); + currentPatchName = name.toStdString(); + + // Check and update the isEnabled attribute + for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { + if (attr.name() == QStringLiteral("isEnabled")) { + if (attr.value().toString() == "true") { + isEnabled = true; + } else + isEnabled = false; + } + } + } else if (xmlReader.name() == QStringLiteral("PatchList")) { + QJsonArray linesArray; + while (!xmlReader.atEnd() && + !(xmlReader.tokenType() == QXmlStreamReader::EndElement && + xmlReader.name() == QStringLiteral("PatchList"))) { + xmlReader.readNext(); + if (xmlReader.tokenType() == QXmlStreamReader::StartElement && + xmlReader.name() == QStringLiteral("Line")) { + QXmlStreamAttributes attributes = xmlReader.attributes(); + QJsonObject lineObject; + lineObject["Type"] = attributes.value("Type").toString(); + lineObject["Address"] = attributes.value("Address").toString(); + lineObject["Value"] = attributes.value("Value").toString(); + linesArray.append(lineObject); + } + } + + patchLines = linesArray; + if (isEnabled) { + foreach (const QJsonValue& value, patchLines) { + QJsonObject lineObject = value.toObject(); + QString type = lineObject["Type"].toString(); + QString address = lineObject["Address"].toString(); + QString patchValue = lineObject["Value"].toString(); + QString maskOffsetStr = lineObject["Offset"].toString(); + + patchValue = QString::fromStdString( + convertValueToHex(type.toStdString(), patchValue.toStdString())); + + bool littleEndian = false; + + if (type == "bytes16") { + littleEndian = true; + } else if (type == "bytes32") { + littleEndian = true; + } else if (type == "bytes64") { + littleEndian = true; + } + + MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None; + int maskOffsetValue = 0; + + if (type == "mask") { + patchMask = MemoryPatcher::PatchMask::Mask; + + // im not sure if this works, there is no games to test the mask + // offset on yet + if (!maskOffsetStr.toStdString().empty()) + maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); + } + + if (type == "mask_jump32") + patchMask = MemoryPatcher::PatchMask::Mask_Jump32; + + MemoryPatcher::PatchMemory(currentPatchName, address.toStdString(), + patchValue.toStdString(), false, + littleEndian, patchMask); + } + } + } + } + } + + if (xmlReader.hasError()) { + LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial); + } else { + LOG_INFO(Loader, "Patches loaded successfully"); + } + ApplyPendingPatches(); + } +#endif +} + +void AddPatchToQueue(patchInfo patchToAdd) { + pending_patches.push_back(patchToAdd); +} + +void ApplyPendingPatches() { + + for (size_t i = 0; i < pending_patches.size(); ++i) { + patchInfo currentPatch = pending_patches[i]; + + if (currentPatch.gameSerial != g_game_serial) + continue; + + PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, + currentPatch.isOffset, currentPatch.littleEndian, currentPatch.patchMask, + currentPatch.maskOffset); + } + + pending_patches.clear(); +} + +void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset, + bool littleEndian, PatchMask patchMask, int maskOffset) { + // Send a request to modify the process memory. + void* cheatAddress = nullptr; + + if (patchMask == PatchMask::None) { + if (isOffset) { + cheatAddress = reinterpret_cast(g_eboot_address + std::stoi(offsetStr, 0, 16)); + } else { + cheatAddress = + reinterpret_cast(g_eboot_address + (std::stoi(offsetStr, 0, 16) - 0x400000)); + } + } + + if (patchMask == PatchMask::Mask) { + cheatAddress = reinterpret_cast(PatternScan(offsetStr) + maskOffset); + } + + // TODO: implement mask_jump32 + + if (cheatAddress == nullptr) { + LOG_ERROR(Loader, "Failed to get address for patch {}", modNameStr); + return; + } + + std::vector bytePatch; + + for (size_t i = 0; i < valueStr.length(); i += 2) { + unsigned char byte = + static_cast(std::strtol(valueStr.substr(i, 2).c_str(), nullptr, 16)); + + bytePatch.push_back(byte); + } + + if (littleEndian) { + std::reverse(bytePatch.begin(), bytePatch.end()); + } + + std::memcpy(cheatAddress, bytePatch.data(), bytePatch.size()); + + LOG_INFO(Loader, "Applied patch: {}, Offset: {}, Value: {}", modNameStr, + (uintptr_t)cheatAddress, valueStr); +} + +static std::vector PatternToByte(const std::string& pattern) { + std::vector bytes; + const char* start = pattern.data(); + const char* end = start + pattern.size(); + + for (const char* current = start; current < end; ++current) { + if (*current == '?') { + ++current; + if (*current == '?') + ++current; + bytes.push_back(-1); + } else { + bytes.push_back(strtoul(current, const_cast(¤t), 16)); + } + } + + return bytes; +} + +uintptr_t PatternScan(const std::string& signature) { + std::vector patternBytes = PatternToByte(signature); + const auto scanBytes = static_cast((void*)g_eboot_address); + + const int32_t* sigPtr = patternBytes.data(); + const size_t sigSize = patternBytes.size(); + + uint32_t foundResults = 0; + for (uint32_t i = 0; i < g_eboot_image_size - sigSize; ++i) { + bool found = true; + for (uint32_t j = 0; j < sigSize; ++j) { + if (scanBytes[i + j] != sigPtr[j] && sigPtr[j] != -1) { + found = false; + break; + } + } + + if (found) { + foundResults++; + return reinterpret_cast(&scanBytes[i]); + } + } + + return 0; +} + +} // namespace MemoryPatcher \ No newline at end of file diff --git a/src/common/memory_patcher.h b/src/common/memory_patcher.h new file mode 100644 index 000000000..899ffccb1 --- /dev/null +++ b/src/common/memory_patcher.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include +#include +#include + +namespace MemoryPatcher { + +extern uintptr_t g_eboot_address; +extern uint64_t g_eboot_image_size; +extern std::string g_game_serial; +extern std::string patchFile; + +enum PatchMask : uint8_t { + None, + Mask, + Mask_Jump32, +}; + +struct patchInfo { + std::string gameSerial; + std::string modNameStr; + std::string offsetStr; + std::string valueStr; + bool isOffset; + bool littleEndian; + PatchMask patchMask; + int maskOffset; +}; + +extern std::vector pending_patches; + +std::string convertValueToHex(const std::string type, const std::string valueStr); + +void OnGameLoaded(); +void AddPatchToQueue(patchInfo patchToAdd); +void ApplyPendingPatches(); + +void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset, + bool littleEndian, PatchMask patchMask = PatchMask::None, int maskOffset = 0); + +static std::vector PatternToByte(const std::string& pattern); +uintptr_t PatternScan(const std::string& signature); + +} // namespace MemoryPatcher \ No newline at end of file diff --git a/src/common/native_clock.cpp b/src/common/native_clock.cpp index 20d0737a6..c3fa637aa 100644 --- a/src/common/native_clock.cpp +++ b/src/common/native_clock.cpp @@ -18,16 +18,16 @@ NativeClock::NativeClock() us_rdtsc_factor{GetFixedPoint64Factor(std::micro::den, rdtsc_frequency)}, ms_rdtsc_factor{GetFixedPoint64Factor(std::milli::den, rdtsc_frequency)} {} -u64 NativeClock::GetTimeNS() const { - return MultiplyHigh(GetUptime(), ns_rdtsc_factor); +u64 NativeClock::GetTimeNS(u64 base_ptc /*= 0*/) const { + return MultiplyHigh(GetUptime() - base_ptc, ns_rdtsc_factor); } -u64 NativeClock::GetTimeUS() const { - return MultiplyHigh(GetUptime(), us_rdtsc_factor); +u64 NativeClock::GetTimeUS(u64 base_ptc /*= 0*/) const { + return MultiplyHigh(GetUptime() - base_ptc, us_rdtsc_factor); } -u64 NativeClock::GetTimeMS() const { - return MultiplyHigh(GetUptime(), ms_rdtsc_factor); +u64 NativeClock::GetTimeMS(u64 base_ptc /*= 0*/) const { + return MultiplyHigh(GetUptime() - base_ptc, ms_rdtsc_factor); } u64 NativeClock::GetUptime() const { diff --git a/src/common/native_clock.h b/src/common/native_clock.h index 227c8d1ae..b5e389452 100644 --- a/src/common/native_clock.h +++ b/src/common/native_clock.h @@ -16,9 +16,9 @@ public: return rdtsc_frequency; } - u64 GetTimeNS() const; - u64 GetTimeUS() const; - u64 GetTimeMS() const; + u64 GetTimeNS(u64 base_ptc = 0) const; + u64 GetTimeUS(u64 base_ptc = 0) const; + u64 GetTimeMS(u64 base_ptc = 0) const; u64 GetUptime() const; u64 GetProcessTimeUS() const; diff --git a/src/common/number_utils.cpp b/src/common/number_utils.cpp new file mode 100644 index 000000000..af29e5cd3 --- /dev/null +++ b/src/common/number_utils.cpp @@ -0,0 +1,161 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#include "common/number_utils.h" +#include "video_core/amdgpu/pixel_format.h" +#include "video_core/amdgpu/types.h" + +#define UF11_EXPONENT_SHIFT 6 +#define UF10_EXPONENT_SHIFT 5 + +#define RGB9E5_MANTISSA_BITS 9 +#define RGB9E5_EXP_BIAS 1 + +#define F32_INFINITY 0x7f800000 + +namespace NumberUtils { + +float Uf11ToF32(u16 val) { + union { + float f; + u32 ui; + } f32; + + int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT; + int mantissa = (val & 0x003f); + + f32.f = 0.0; + + if (exponent == 0) { + if (mantissa != 0) { + const float scale = 1.0 / (1 << 20); + f32.f = scale * mantissa; + } + } else if (exponent == 31) { + f32.ui = F32_INFINITY | mantissa; + } else { + float scale, decimal; + exponent -= 15; + if (exponent < 0) { + scale = 1.0f / (1 << -exponent); + } else { + scale = (float)(1 << exponent); + } + decimal = 1.0f + (float)mantissa / 64; + f32.f = scale * decimal; + } + + return f32.f; +} + +float Uf10ToF32(u16 val) { + union { + float f; + u32 ui; + } f32; + + int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT; + int mantissa = (val & 0x001f); + + f32.f = 0.0; + + if (exponent == 0) { + if (mantissa != 0) { + const float scale = 1.0 / (1 << 19); + f32.f = scale * mantissa; + } + } else if (exponent == 31) { + f32.ui = F32_INFINITY | mantissa; + } else { + float scale, decimal; + exponent -= 15; + if (exponent < 0) { + scale = 1.0f / (1 << -exponent); + } else { + scale = (float)(1 << exponent); + } + decimal = 1.0f + (float)mantissa / 32; + f32.f = scale * decimal; + } + + return f32.f; +} + +float Uf16ToF32(u16 val) { + return half_float::half_cast(reinterpret_cast(val)); +} + +float U2ToUnorm(u8 val) { + static constexpr auto c = 1.0f / 3.0f; + return float(val * c); +} + +float S2ToSnorm(s8 val) { + static constexpr auto c = 1.0f / 1.0f; + return float(val * c); +} + +float U4ToUnorm(u8 val) { + static constexpr auto c = 1.0f / 15.0f; + return float(val * c); +} + +float S4ToSnorm(s8 val) { + static constexpr auto c = 1.0f / 7.0f; + return float(val * c); +} + +float U5ToUnorm(u8 val) { + static constexpr auto c = 1.0f / 31.0f; + return float(val * c); +} + +float S5ToSnorm(s8 val) { + static constexpr auto c = 1.0f / 15.0f; + return float(val * c); +} + +float U6ToUnorm(u8 val) { + static constexpr auto c = 1.0f / 63.0f; + return float(val * c); +} + +float S6ToSnorm(s8 val) { + static constexpr auto c = 1.0f / 31.0f; + return float(val * c); +} + +float U8ToUnorm(u8 val) { + static constexpr auto c = 1.0f / 255.0f; + return float(val * c); +} + +float S8ToSnorm(s8 val) { + static constexpr auto c = 1.0f / 127.0f; + return float(val * c); +} + +float U10ToUnorm(u16 val) { + static constexpr auto c = 1.0f / 1023.0f; + return float(val * c); +} + +float S10ToSnorm(s16 val) { + static constexpr auto c = 1.0f / 511.0f; + return float(val * c); +} + +float U16ToUnorm(u16 val) { + static constexpr auto c = 1.0f / 65535.0f; + return float(val * c); +} + +float S16ToSnorm(s16 val) { + static constexpr auto c = 1.0f / 32767.0f; + return float(val * c); +} + +} // namespace NumberUtils \ No newline at end of file diff --git a/src/common/number_utils.h b/src/common/number_utils.h new file mode 100644 index 000000000..05c62a1cb --- /dev/null +++ b/src/common/number_utils.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace NumberUtils { + +float Uf11ToF32(u16 val); +float Uf10ToF32(u16 val); +float Uf16ToF32(u16 val); +float U2ToUnorm(u8 val); +float S2ToSnorm(s8 val); +float U4ToUnorm(u8 val); +float S4ToSnorm(s8 val); +float U5ToUnorm(u8 val); +float S5ToSnorm(s8 val); +float U6ToUnorm(u8 val); +float S6ToSnorm(s8 val); +float U8ToUnorm(u8 val); +float S8ToSnorm(s8 val); +float U10ToUnorm(u16 val); +float S10ToSnorm(s16 val); +float U16ToUnorm(u16 val); +float S16ToSnorm(s16 val); + +} // namespace NumberUtils diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index d69f72163..7551d3b05 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -22,6 +22,10 @@ #endif #endif +#ifdef ENABLE_QT_GUI +#include +#endif + namespace Common::FS { namespace fs = std::filesystem; @@ -82,11 +86,32 @@ static std::filesystem::path GetBundleParentDirectory() { static auto UserPaths = [] { #ifdef __APPLE__ - std::filesystem::current_path(GetBundleParentDirectory()); + // Start by assuming the base directory is the bundle's parent directory. + std::filesystem::path base_dir = GetBundleParentDirectory(); + std::filesystem::path user_dir = base_dir / PORTABLE_DIR; + // Check if the "user" directory exists in the current path: + if (!std::filesystem::exists(user_dir)) { + // If it doesn't exist, use the new hardcoded path: + user_dir = + std::filesystem::path(getenv("HOME")) / "Library" / "Application Support" / "shadPS4"; + } +#elif defined(__linux__) + auto user_dir = std::filesystem::current_path() / PORTABLE_DIR; + // Check if the "user" directory exists in the current path: + if (!std::filesystem::exists(user_dir)) { + // If it doesn't exist, use XDG_DATA_HOME if it is set, and provide a standard default + const char* xdg_data_home = getenv("XDG_DATA_HOME"); + if (xdg_data_home != nullptr && strlen(xdg_data_home) > 0) { + user_dir = std::filesystem::path(xdg_data_home) / "shadPS4"; + } else { + user_dir = std::filesystem::path(getenv("HOME")) / ".local" / "share" / "shadPS4"; + } + } +#else + const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR; #endif std::unordered_map paths; - const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR; const auto create_path = [&](PathType shad_path, const fs::path& new_path) { std::filesystem::create_directory(new_path); @@ -97,13 +122,15 @@ static auto UserPaths = [] { create_path(PathType::LogDir, user_dir / LOG_DIR); create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR); create_path(PathType::ShaderDir, user_dir / SHADER_DIR); - create_path(PathType::PM4Dir, user_dir / PM4_DIR); create_path(PathType::SaveDataDir, user_dir / SAVEDATA_DIR); create_path(PathType::GameDataDir, user_dir / GAMEDATA_DIR); create_path(PathType::TempDataDir, user_dir / TEMPDATA_DIR); create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR); create_path(PathType::DownloadDir, user_dir / DOWNLOAD_DIR); create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR); + create_path(PathType::CheatsDir, user_dir / CHEATS_DIR); + create_path(PathType::PatchesDir, user_dir / PATCHES_DIR); + create_path(PathType::MetaDataDir, user_dir / METADATA_DIR); return paths; }(); @@ -152,4 +179,22 @@ void SetUserPath(PathType shad_path, const fs::path& new_path) { UserPaths.insert_or_assign(shad_path, new_path); } -} // namespace Common::FS +#ifdef ENABLE_QT_GUI +void PathToQString(QString& result, const std::filesystem::path& path) { +#ifdef _WIN32 + result = QString::fromStdWString(path.wstring()); +#else + result = QString::fromStdString(path.string()); +#endif +} + +std::filesystem::path PathFromQString(const QString& path) { +#ifdef _WIN32 + return std::filesystem::path(path.toStdWString()); +#else + return std::filesystem::path(path.toStdString()); +#endif +} +#endif + +} // namespace Common::FS \ No newline at end of file diff --git a/src/common/path_util.h b/src/common/path_util.h index 263edd46e..09b7a3337 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -6,6 +6,10 @@ #include #include +#ifdef ENABLE_QT_GUI +class QString; // to avoid including in this header +#endif + namespace Common::FS { enum class PathType { @@ -13,13 +17,15 @@ enum class PathType { LogDir, // Where log files are stored. ScreenshotsDir, // Where screenshots are stored. ShaderDir, // Where shaders are stored. - PM4Dir, // Where command lists are stored. SaveDataDir, // Where guest save data is stored. TempDataDir, // Where game temp data is stored. GameDataDir, // Where game data is stored. SysModuleDir, // Where system modules are stored. DownloadDir, // Where downloads/temp files are stored. CapturesDir, // Where rdoc captures are stored. + CheatsDir, // Where cheats are stored. + PatchesDir, // Where patches are stored. + MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored. }; constexpr auto PORTABLE_DIR = "user"; @@ -28,13 +34,15 @@ constexpr auto PORTABLE_DIR = "user"; constexpr auto LOG_DIR = "log"; constexpr auto SCREENSHOTS_DIR = "screenshots"; constexpr auto SHADER_DIR = "shader"; -constexpr auto PM4_DIR = "pm4"; constexpr auto SAVEDATA_DIR = "savedata"; constexpr auto GAMEDATA_DIR = "data"; constexpr auto TEMPDATA_DIR = "temp"; constexpr auto SYSMODULES_DIR = "sys_modules"; constexpr auto DOWNLOAD_DIR = "download"; constexpr auto CAPTURES_DIR = "captures"; +constexpr auto CHEATS_DIR = "cheats"; +constexpr auto PATCHES_DIR = "patches"; +constexpr auto METADATA_DIR = "game_data"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; @@ -88,4 +96,23 @@ constexpr auto LOG_FILE = "shad_log.txt"; */ void SetUserPath(PathType user_path, const std::filesystem::path& new_path); +#ifdef ENABLE_QT_GUI +/** + * Converts an std::filesystem::path to a QString. + * The native underlying string of a path is wstring on Windows and string on POSIX. + * + * @param result The resulting QString + * @param path The path to convert + */ +void PathToQString(QString& result, const std::filesystem::path& path); + +/** + * Converts a QString to an std::filesystem::path. + * The native underlying string of a path is wstring on Windows and string on POSIX. + * + * @param path The path to convert + */ +[[nodiscard]] std::filesystem::path PathFromQString(const QString& path); +#endif + } // namespace Common::FS diff --git a/src/common/rdtsc.h b/src/common/rdtsc.h index 3180273e5..4e4d58436 100644 --- a/src/common/rdtsc.h +++ b/src/common/rdtsc.h @@ -3,6 +3,8 @@ #pragma once +#include "common/arch.h" + #ifdef _MSC_VER #include #endif @@ -13,15 +15,20 @@ namespace Common { #ifdef _MSC_VER __forceinline static u64 FencedRDTSC() { +#ifdef ARCH_X86_64 _mm_lfence(); _ReadWriteBarrier(); const u64 result = __rdtsc(); _mm_lfence(); _ReadWriteBarrier(); return result; +#else +#error "Missing FencedRDTSC() implementation for target CPU architecture." +#endif } #else static inline u64 FencedRDTSC() { +#ifdef ARCH_X86_64 u64 eax; u64 edx; asm volatile("lfence\n\t" @@ -29,6 +36,16 @@ static inline u64 FencedRDTSC() { "lfence\n\t" : "=a"(eax), "=d"(edx)); return (edx << 32) | eax; +#elif defined(ARCH_ARM64) + u64 ret; + asm volatile("isb\n\t" + "mrs %0, cntvct_el0\n\t" + "isb\n\t" + : "=r"(ret)::"memory"); + return ret; +#else +#error "Missing FencedRDTSC() implementation for target CPU architecture." +#endif } #endif diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 7f6fba9ed..642e6373d 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -6,12 +6,14 @@ #define GIT_REV "@GIT_REV@" #define GIT_BRANCH "@GIT_BRANCH@" #define GIT_DESC "@GIT_DESC@" +#define BUILD_DATE "@BUILD_DATE@" namespace Common { const char g_scm_rev[] = GIT_REV; const char g_scm_branch[] = GIT_BRANCH; const char g_scm_desc[] = GIT_DESC; +const char g_scm_date[] = BUILD_DATE; } // namespace diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index 877a01272..005099d2d 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -8,5 +8,6 @@ namespace Common { extern const char g_scm_rev[]; extern const char g_scm_branch[]; extern const char g_scm_desc[]; +extern const char g_scm_date[]; } // namespace Common diff --git a/src/common/signal_context.cpp b/src/common/signal_context.cpp new file mode 100644 index 000000000..112160bc8 --- /dev/null +++ b/src/common/signal_context.cpp @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/arch.h" +#include "common/assert.h" +#include "common/signal_context.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace Common { + +void* GetXmmPointer(void* ctx, u8 index) { +#if defined(_WIN32) +#define CASE(index) \ + case index: \ + return (void*)(&((EXCEPTION_POINTERS*)ctx)->ContextRecord->Xmm##index.Low) +#elif defined(__APPLE__) +#define CASE(index) \ + case index: \ + return (void*)(&((ucontext_t*)ctx)->uc_mcontext->__fs.__fpu_xmm##index); +#else +#define CASE(index) \ + case index: \ + return (void*)(&((ucontext_t*)ctx)->uc_mcontext.fpregs->_xmm[index].element[0]) +#endif + switch (index) { + CASE(0); + CASE(1); + CASE(2); + CASE(3); + CASE(4); + CASE(5); + CASE(6); + CASE(7); + CASE(8); + CASE(9); + CASE(10); + CASE(11); + CASE(12); + CASE(13); + CASE(14); + CASE(15); + default: { + UNREACHABLE_MSG("Invalid XMM register index: {}", index); + return nullptr; + } + } +#undef CASE +} + +void* GetRip(void* ctx) { +#if defined(_WIN32) + return (void*)((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip; +#elif defined(__APPLE__) + return (void*)((ucontext_t*)ctx)->uc_mcontext->__ss.__rip; +#else + return (void*)((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP]; +#endif +} + +void IncrementRip(void* ctx, u64 length) { +#if defined(_WIN32) + ((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip += length; +#elif defined(__APPLE__) + ((ucontext_t*)ctx)->uc_mcontext->__ss.__rip += length; +#else + ((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP] += length; +#endif +} + +bool IsWriteError(void* ctx) { +#if defined(_WIN32) + return ((EXCEPTION_POINTERS*)ctx)->ExceptionRecord->ExceptionInformation[0] == 1; +#elif defined(__APPLE__) +#if defined(ARCH_X86_64) + return ((ucontext_t*)ctx)->uc_mcontext->__es.__err & 0x2; +#elif defined(ARCH_ARM64) + return ((ucontext_t*)ctx)->uc_mcontext->__es.__esr & 0x40; +#endif +#else +#if defined(ARCH_X86_64) + return ((ucontext_t*)ctx)->uc_mcontext.gregs[REG_ERR] & 0x2; +#else +#error "Unsupported architecture" +#endif +#endif +} +} // namespace Common \ No newline at end of file diff --git a/src/common/signal_context.h b/src/common/signal_context.h new file mode 100644 index 000000000..b09da64f2 --- /dev/null +++ b/src/common/signal_context.h @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Common { + +void* GetXmmPointer(void* ctx, u8 index); + +void* GetRip(void* ctx); + +void IncrementRip(void* ctx, u64 length); + +bool IsWriteError(void* ctx); + +} // namespace Common \ No newline at end of file diff --git a/src/common/slot_vector.h b/src/common/slot_vector.h index f0982e290..36e647971 100644 --- a/src/common/slot_vector.h +++ b/src/common/slot_vector.h @@ -28,9 +28,13 @@ struct SlotId { template class SlotVector { - constexpr static std::size_t InitialCapacity = 1024; + constexpr static std::size_t InitialCapacity = 2048; public: + SlotVector() { + Reserve(InitialCapacity); + } + ~SlotVector() noexcept { std::size_t index = 0; for (u64 bits : stored_bitset) { @@ -67,19 +71,6 @@ public: return SlotId{index}; } - template - [[nodiscard]] SlotId swap_and_insert(SlotId existing_id, Args&&... args) noexcept { - const u32 index = FreeValueIndex(); - T& existing_value = values[existing_id.index].object; - - new (&values[index].object) T(std::move(existing_value)); - existing_value.~T(); - new (&values[existing_id.index].object) T(std::forward(args)...); - SetStorageBit(index); - - return SlotId{index}; - } - void erase(SlotId id) noexcept { values[id.index].object.~T(); free_list.push_back(id.index); @@ -151,7 +142,8 @@ private: const std::size_t old_free_size = free_list.size(); free_list.resize(old_free_size + (new_capacity - values_capacity)); - std::iota(free_list.begin() + old_free_size, free_list.end(), + const std::size_t new_free_size = free_list.size(); + std::iota(free_list.rbegin(), free_list.rbegin() + new_free_size - old_free_size, static_cast(values_capacity)); delete[] values; diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 29e6aeb4f..6d5a254cd 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -14,12 +14,17 @@ namespace Common { -std::string ToLower(std::string str) { - std::transform(str.begin(), str.end(), str.begin(), - [](unsigned char c) { return static_cast(std::tolower(c)); }); +std::string ToLower(std::string_view input) { + std::string str; + str.resize(input.size()); + std::ranges::transform(input, str.begin(), tolower); return str; } +void ToLowerInPlace(std::string& str) { + std::ranges::transform(str, str.begin(), tolower); +} + std::vector SplitString(const std::string& str, char delimiter) { std::istringstream iss(str); std::vector output(1); diff --git a/src/common/string_util.h b/src/common/string_util.h index 8dae6c75b..23e82b93c 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -10,7 +10,9 @@ namespace Common { /// Make a string lowercase -[[nodiscard]] std::string ToLower(std::string str); +[[nodiscard]] std::string ToLower(std::string_view str); + +void ToLowerInPlace(std::string& str); std::vector SplitString(const std::string& str, char delimiter); diff --git a/src/common/thread.cpp b/src/common/thread.cpp index f08b36faa..46df68c38 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -3,12 +3,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "common/error.h" #include "common/logging/log.h" #include "common/thread.h" +#include "ntapi.h" #ifdef __APPLE__ #include +#include #include #elif defined(_WIN32) #include @@ -31,6 +34,48 @@ namespace Common { +#ifdef __APPLE__ + +void SetCurrentThreadRealtime(const std::chrono::nanoseconds period_ns) { + // CPU time to grant. + const std::chrono::nanoseconds computation_ns = period_ns / 2; + + // Determine the timebase for converting time to ticks. + struct mach_timebase_info timebase {}; + mach_timebase_info(&timebase); + const auto ticks_per_ns = + static_cast(timebase.denom) / static_cast(timebase.numer); + + const auto period_ticks = + static_cast(static_cast(period_ns.count()) * ticks_per_ns); + const auto computation_ticks = + static_cast(static_cast(computation_ns.count()) * ticks_per_ns); + + thread_time_constraint_policy policy = { + .period = period_ticks, + .computation = computation_ticks, + // Should not matter since preemptible is false, but needs to be >= computation regardless. + .constraint = computation_ticks, + .preemptible = false, + }; + + int ret = thread_policy_set( + pthread_mach_thread_np(pthread_self()), THREAD_TIME_CONSTRAINT_POLICY, + reinterpret_cast(&policy), THREAD_TIME_CONSTRAINT_POLICY_COUNT); + if (ret != KERN_SUCCESS) { + LOG_ERROR(Common, "Could not set thread to real-time with period {} ns: {}", + period_ns.count(), ret); + } +} + +#else + +void SetCurrentThreadRealtime(const std::chrono::nanoseconds period_ns) { + // Not implemented +} + +#endif + #ifdef _WIN32 void SetCurrentThreadPriority(ThreadPriority new_priority) { @@ -59,6 +104,16 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) { SetThreadPriority(handle, windows_priority); } +static void AccurateSleep(std::chrono::nanoseconds duration) { + LARGE_INTEGER interval{ + .QuadPart = -1 * (duration.count() / 100u), + }; + HANDLE timer = ::CreateWaitableTimer(NULL, TRUE, NULL); + SetWaitableTimer(timer, &interval, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + ::CloseHandle(timer); +} + #else void SetCurrentThreadPriority(ThreadPriority new_priority) { @@ -79,6 +134,10 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) { pthread_setschedparam(this_thread, scheduling_type, ¶ms); } +static void AccurateSleep(std::chrono::nanoseconds duration) { + std::this_thread::sleep_for(duration); +} + #endif #ifdef _MSC_VER @@ -121,4 +180,22 @@ void SetCurrentThreadName(const char*) { #endif +AccurateTimer::AccurateTimer(std::chrono::nanoseconds target_interval) + : target_interval(target_interval) {} + +void AccurateTimer::Start() { + auto begin_sleep = std::chrono::high_resolution_clock::now(); + if (total_wait.count() > 0) { + AccurateSleep(total_wait); + } + start_time = std::chrono::high_resolution_clock::now(); + total_wait -= std::chrono::duration_cast(start_time - begin_sleep); +} + +void AccurateTimer::End() { + auto now = std::chrono::high_resolution_clock::now(); + total_wait += + target_interval - std::chrono::duration_cast(now - start_time); +} + } // namespace Common diff --git a/src/common/thread.h b/src/common/thread.h index 39acc1db5..fd962f8e5 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -4,6 +4,7 @@ #pragma once +#include #include "common/types.h" namespace Common { @@ -16,8 +17,24 @@ enum class ThreadPriority : u32 { Critical = 4, }; +void SetCurrentThreadRealtime(std::chrono::nanoseconds period_ns); + void SetCurrentThreadPriority(ThreadPriority new_priority); void SetCurrentThreadName(const char* name); +class AccurateTimer { + std::chrono::nanoseconds target_interval{}; + std::chrono::nanoseconds total_wait{}; + + std::chrono::high_resolution_clock::time_point start_time; + +public: + explicit AccurateTimer(std::chrono::nanoseconds target_interval); + + void Start(); + + void End(); +}; + } // namespace Common diff --git a/src/common/version.h b/src/common/version.h index 80de187b0..12fd17041 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -8,7 +8,7 @@ namespace Common { -constexpr char VERSION[] = "0.2.1 WIP"; +constexpr char VERSION[] = "0.3.1 WIP"; constexpr bool isRelease = false; } // namespace Common diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index 235113700..8ba99e32d 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -3,11 +3,13 @@ #include #include "common/alignment.h" +#include "common/arch.h" #include "common/assert.h" #include "common/error.h" #include "core/address_space.h" #include "core/libraries/kernel/memory_management.h" #include "core/memory.h" +#include "libraries/error_codes.h" #ifdef _WIN32 #include @@ -16,26 +18,25 @@ #include #endif -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(ARCH_X86_64) // Reserve space for the system address space using a zerofill section. asm(".zerofill GUEST_SYSTEM,GUEST_SYSTEM,__guest_system,0xFBFC00000"); #endif namespace Core { -static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE; +static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE_PRO; #ifdef _WIN32 [[nodiscard]] constexpr u64 ToWindowsProt(Core::MemoryProt prot) { - switch (prot) { - case Core::MemoryProt::NoAccess: - default: - return PAGE_NOACCESS; - case Core::MemoryProt::CpuRead: - return PAGE_READONLY; - case Core::MemoryProt::CpuReadWrite: + if (True(prot & Core::MemoryProt::CpuReadWrite) || + True(prot & Core::MemoryProt::GpuReadWrite)) { return PAGE_READWRITE; + } else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) { + return PAGE_READONLY; + } else { + return PAGE_NOACCESS; } } @@ -70,7 +71,8 @@ struct AddressSpace::Impl { } reduction += ReductionOnFail; } - ASSERT_MSG(virtual_base, "Unable to reserve virtual address space!"); + ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}", + Common::GetLastErrorMsg()); // Take the reduction off of the system managed area, and leave the others unchanged. system_managed_base = virtual_base; @@ -231,27 +233,36 @@ struct AddressSpace::Impl { void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) { DWORD new_flags{}; - if (read && write) { + + if (read && write && execute) { + new_flags = PAGE_EXECUTE_READWRITE; + } else if (read && write) { new_flags = PAGE_READWRITE; } else if (read && !write) { new_flags = PAGE_READONLY; - } else if (!read && !write) { + } else if (execute && !read && not write) { + new_flags = PAGE_EXECUTE; + } else if (!read && !write && !execute) { new_flags = PAGE_NOACCESS; } else { - UNIMPLEMENTED_MSG("Protection flag combination read={} write={}", read, write); + LOG_CRITICAL(Common_Memory, + "Unsupported protection flag combination for address {:#x}, size {}", + virtual_addr, size); + return; } - const VAddr virtual_end = virtual_addr + size; - auto [it, end] = placeholders.equal_range({virtual_addr, virtual_end}); - while (it != end) { - const size_t offset = std::max(it->lower(), virtual_addr); - const size_t protect_length = std::min(it->upper(), virtual_end) - offset; - DWORD old_flags{}; - if (!VirtualProtect(virtual_base + offset, protect_length, new_flags, &old_flags)) { - LOG_CRITICAL(Common_Memory, "Failed to change virtual memory protect rules"); - } - ++it; + DWORD old_flags{}; + bool success = + VirtualProtect(reinterpret_cast(virtual_addr), size, new_flags, &old_flags); + + if (!success) { + LOG_ERROR(Common_Memory, + "Failed to change virtual memory protection for address {:#x}, size {}", + virtual_addr, size); } + + // Use assert to ensure success in debug builds + DEBUG_ASSERT(success && "Failed to change virtual memory protection"); } HANDLE process{}; @@ -278,14 +289,13 @@ enum PosixPageProtection { }; [[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) { - switch (prot) { - case Core::MemoryProt::NoAccess: - default: - return PAGE_NOACCESS; - case Core::MemoryProt::CpuRead: - return PAGE_READONLY; - case Core::MemoryProt::CpuReadWrite: + if (True(prot & Core::MemoryProt::CpuReadWrite) || + True(prot & Core::MemoryProt::GpuReadWrite)) { return PAGE_READWRITE; + } else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) { + return PAGE_READONLY; + } else { + return PAGE_NOACCESS; } } @@ -298,12 +308,12 @@ struct AddressSpace::Impl { constexpr int protection_flags = PROT_READ | PROT_WRITE; constexpr int base_map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; -#ifdef __APPLE__ - // On ARM64 Macs, we run into limitations due to the commpage from 0xFC0000000 - 0xFFFFFFFFF - // and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. We can allocate the system - // managed region, as well as system reserved if reduced in size slightly, but we cannot map - // the user region where we want, so we must let the OS put it wherever possible and hope - // the game won't rely on its location. +#if defined(__APPLE__) && defined(ARCH_X86_64) + // On ARM64 Macs under Rosetta 2, we run into limitations due to the commpage from + // 0xFC0000000 - 0xFFFFFFFFF and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. + // We can allocate the system managed region, as well as system reserved if reduced in size + // slightly, but we cannot map the user region where we want, so we must let the OS put it + // wherever possible and hope the game won't rely on its location. system_managed_base = reinterpret_cast( mmap(reinterpret_cast(SYSTEM_MANAGED_MIN), system_managed_size, protection_flags, base_map_flags | MAP_FIXED, -1, 0)); @@ -315,12 +325,22 @@ struct AddressSpace::Impl { protection_flags, base_map_flags, -1, 0)); #else const auto virtual_size = system_managed_size + system_reserved_size + user_size; +#if defined(ARCH_X86_64) const auto virtual_base = reinterpret_cast(mmap(reinterpret_cast(SYSTEM_MANAGED_MIN), virtual_size, protection_flags, base_map_flags | MAP_FIXED, -1, 0)); system_managed_base = virtual_base; system_reserved_base = reinterpret_cast(SYSTEM_RESERVED_MIN); user_base = reinterpret_cast(USER_MIN); +#else + // Map memory wherever possible and instruction translation can handle offsetting to the + // base. + const auto virtual_base = reinterpret_cast( + mmap(nullptr, virtual_size, protection_flags, base_map_flags, -1, 0)); + system_managed_base = virtual_base; + system_reserved_base = virtual_base + SYSTEM_RESERVED_MIN - SYSTEM_MANAGED_MIN; + user_base = virtual_base + USER_MIN - SYSTEM_MANAGED_MIN; +#endif #endif if (system_managed_base == MAP_FAILED || system_reserved_base == MAP_FAILED || user_base == MAP_FAILED) { @@ -420,9 +440,11 @@ struct AddressSpace::Impl { if (write) { flags |= PROT_WRITE; } +#ifdef ARCH_X86_64 if (execute) { flags |= PROT_EXEC; } +#endif int ret = mprotect(reinterpret_cast(virtual_addr), size, flags); ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); } @@ -453,8 +475,14 @@ AddressSpace::~AddressSpace() = default; void* AddressSpace::Map(VAddr virtual_addr, size_t size, u64 alignment, PAddr phys_addr, bool is_exec) { - return impl->Map(virtual_addr, phys_addr, size, - is_exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); +#if ARCH_X86_64 + const auto prot = is_exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; +#else + // On non-native architectures, we can simplify things by ignoring the execute flag for the + // canonical copy of the memory and rely on the JIT to map translated code as executable. + constexpr auto prot = PAGE_READWRITE; +#endif + return impl->Map(virtual_addr, phys_addr, size, prot); } void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, u32 prot, @@ -493,7 +521,10 @@ void AddressSpace::Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VA } void AddressSpace::Protect(VAddr virtual_addr, size_t size, MemoryPermission perms) { - return impl->Protect(virtual_addr, size, true, true, true); + const bool read = True(perms & MemoryPermission::Read); + const bool write = True(perms & MemoryPermission::Write); + const bool execute = True(perms & MemoryPermission::Execute); + return impl->Protect(virtual_addr, size, read, write, execute); } } // namespace Core diff --git a/src/core/address_space.h b/src/core/address_space.h index 2a3488d57..3233c7588 100644 --- a/src/core/address_space.h +++ b/src/core/address_space.h @@ -4,6 +4,7 @@ #pragma once #include +#include "common/arch.h" #include "common/enum.h" #include "common/types.h" @@ -23,7 +24,7 @@ constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL; constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL; constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL; constexpr VAddr SYSTEM_RESERVED_MIN = 0x07FFFFC000ULL; -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(ARCH_X86_64) // Can only comfortably reserve the first 0x7C0000000 of system reserved space. constexpr VAddr SYSTEM_RESERVED_MAX = 0xFBFFFFFFFULL; #else diff --git a/src/core/aerolib/aerolib.inl b/src/core/aerolib/aerolib.inl index a87c3cc4e..64ee32ea2 100644 --- a/src/core/aerolib/aerolib.inl +++ b/src/core/aerolib/aerolib.inl @@ -114108,7 +114108,7 @@ STUB( _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V124RequestCompetitiveResultEE7add_refEv) STUB("efPahl2FufA", _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V35Error8fromJsonERKNS_4Json5ValueE) -STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlemetId) +STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlementId) STUB("efXnxYFN5oE", _ZNSt11range_errorD0Ev) STUB("efcwuDLsAM0", _ZThn120_NK7WebCore16HTMLMediaElement5mutedEv) STUB("efhGArzWdxE", _ZN7bmalloc6IsoTLS15s_didInitializeE) @@ -129493,7 +129493,7 @@ STUB( STUB("kJlYH5uMAWI", sceNetResolverDestroy) STUB("kJmdxo4uM+8", _ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE5_InitERKSt8_Locinfo) -STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlemetId) +STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlementId) STUB( "kJoY9lMIFzY", _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_21AdvancedPlayerProfile2V138MatchCompletionRateDisconnectedMetricsEEEEmmEi) diff --git a/src/core/aerolib/stubs.cpp b/src/core/aerolib/stubs.cpp index 5e2d55cdc..2634fc46a 100644 --- a/src/core/aerolib/stubs.cpp +++ b/src/core/aerolib/stubs.cpp @@ -13,7 +13,7 @@ namespace Core::AeroLib { // on lookup, setting up the nid_entry they are matched with // // If it runs out of stubs with name information, it will return -// a default implemetnation without function name details +// a default implementation without function name details // Up to 512, larger values lead to more resolve stub slots // and to longer compile / CI times diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp index 42318822b..b812e5444 100644 --- a/src/core/cpu_patches.cpp +++ b/src/core/cpu_patches.cpp @@ -1,12 +1,20 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include +#include #include #include +#include +#include "common/alignment.h" +#include "common/arch.h" #include "common/assert.h" +#include "common/decoder.h" +#include "common/signal_context.h" #include "common/types.h" +#include "core/signals.h" #include "core/tls.h" #include "cpu_patches.h" @@ -15,12 +23,23 @@ #else #include #ifdef __APPLE__ +#include #include #endif #endif using namespace Xbyak::util; +#define MAYBE_AVX(OPCODE, ...) \ + [&] { \ + Cpu cpu; \ + if (cpu.has(Cpu::tAVX)) { \ + c.v##OPCODE(__VA_ARGS__); \ + } else { \ + c.OPCODE(__VA_ARGS__); \ + } \ + }() + namespace Core { static Xbyak::Reg ZydisToXbyakRegister(const ZydisRegister reg) { @@ -30,6 +49,12 @@ static Xbyak::Reg ZydisToXbyakRegister(const ZydisRegister reg) { if (reg >= ZYDIS_REGISTER_RAX && reg <= ZYDIS_REGISTER_R15) { return Xbyak::Reg64(reg - ZYDIS_REGISTER_RAX + Xbyak::Operand::RAX); } + if (reg >= ZYDIS_REGISTER_XMM0 && reg <= ZYDIS_REGISTER_XMM31) { + return Xbyak::Xmm(reg - ZYDIS_REGISTER_XMM0 + xmm0.getIdx()); + } + if (reg >= ZYDIS_REGISTER_YMM0 && reg <= ZYDIS_REGISTER_YMM31) { + return Xbyak::Ymm(reg - ZYDIS_REGISTER_YMM0 + ymm0.getIdx()); + } UNREACHABLE_MSG("Unsupported register: {}", static_cast(reg)); } @@ -66,6 +91,12 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera return ptr[expression]; } +static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) { + ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE, + "Expected immediate operand, got type: {}", static_cast(operand.type)); + return operand.imm.value.u; +} + static std::unique_ptr ZydisToXbyakOperand(const ZydisDecodedOperand& operand) { switch (operand.type) { case ZYDIS_OPERAND_TYPE_REGISTER: { @@ -110,51 +141,134 @@ static Xbyak::Reg AllocateScratchRegister( #ifdef __APPLE__ -static constexpr u32 MaxSavedRegisters = 3; -static pthread_key_t register_save_slots[MaxSavedRegisters]; -static std::once_flag register_save_init_flag; +static pthread_key_t stack_pointer_slot; +static pthread_key_t patch_stack_slot; +static std::once_flag patch_context_slots_init_flag; +static constexpr u32 patch_stack_size = 0x1000; static_assert(sizeof(void*) == sizeof(u64), "Cannot fit a register inside a thread local storage slot."); -static void InitializeRegisterSaveSlots() { - for (u32 i = 0; i < MaxSavedRegisters; i++) { - ASSERT_MSG(pthread_key_create(®ister_save_slots[i], nullptr) == 0, - "Unable to allocate thread-local register save slot {}", i); - } +static void FreePatchStack(void* patch_stack) { + // Subtract back to the bottom of the stack for free. + std::free(static_cast(patch_stack) - patch_stack_size); } +static void InitializePatchContextSlots() { + ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0, + "Unable to allocate thread-local register for stack pointer."); + ASSERT_MSG(pthread_key_create(&patch_stack_slot, FreePatchStack) == 0, + "Unable to allocate thread-local register for patch stack."); +} + +void InitializeThreadPatchStack() { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + pthread_setspecific(patch_stack_slot, + static_cast(std::malloc(patch_stack_size)) + patch_stack_size); +} + +/// Saves the stack pointer to thread local storage and loads the patch stack. +static void SaveStack(Xbyak::CodeGenerator& c) { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + // Save original stack pointer and load patch stack. + c.putSeg(gs); + c.mov(qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))], rsp); + c.putSeg(gs); + c.mov(rsp, qword[reinterpret_cast(patch_stack_slot * sizeof(void*))]); +} + +/// Restores the stack pointer from thread local storage. +static void RestoreStack(Xbyak::CodeGenerator& c) { + std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots); + + // Save patch stack pointer and load original stack. + c.putSeg(gs); + c.mov(qword[reinterpret_cast(patch_stack_slot * sizeof(void*))], rsp); + c.putSeg(gs); + c.mov(rsp, qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))]); +} + +#else + +// These utilities are not implemented as we can't save anything to thread local storage without +// temporary registers. +void InitializeThreadPatchStack() { + // No-op +} + +/// Saves the stack pointer to thread local storage and loads the patch stack. +static void SaveStack(Xbyak::CodeGenerator& c) { + UNIMPLEMENTED(); +} + +/// Restores the stack pointer from thread local storage. +static void RestoreStack(Xbyak::CodeGenerator& c) { + UNIMPLEMENTED(); +} + +#endif + +/// Switches to the patch stack, saves registers, and restores the original stack. static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list regs) { - ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to save {} registers.", - regs.size()); - - std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots); - - u32 index = 0; + SaveStack(c); for (const auto& reg : regs) { - const auto offset = reinterpret_cast(register_save_slots[index++] * sizeof(void*)); - - c.putSeg(gs); - c.mov(qword[offset], reg.cvt64()); + c.push(reg.cvt64()); } + RestoreStack(c); } +/// Switches to the patch stack, restores registers, and restores the original stack. static void RestoreRegisters(Xbyak::CodeGenerator& c, const std::initializer_list regs) { - ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to restore {} registers.", - regs.size()); - - std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots); - - u32 index = 0; + SaveStack(c); for (const auto& reg : regs) { - const auto offset = reinterpret_cast(register_save_slots[index++] * sizeof(void*)); + c.pop(reg.cvt64()); + } + RestoreStack(c); +} - c.putSeg(gs); - c.mov(reg.cvt64(), qword[offset]); +/// Switches to the patch stack and stores all registers. +static void SaveContext(Xbyak::CodeGenerator& c, bool save_flags = false) { + SaveStack(c); + for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) { + c.push(Xbyak::Reg64(reg)); + } + for (int reg = 0; reg <= 7; reg++) { + c.lea(rsp, ptr[rsp - 32]); + c.vmovdqu(ptr[rsp], Xbyak::Ymm(reg)); + } + if (save_flags) { + c.pushfq(); } } +/// Restores all registers and restores the original stack. +/// If the destination is a register, it is not restored to preserve the output. +static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst, + bool restore_flags = false) { + if (restore_flags) { + c.popfq(); + } + for (int reg = 7; reg >= 0; reg--) { + if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) { + c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp]); + } + c.lea(rsp, ptr[rsp + 32]); + } + for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) { + if (!dst.isREG() || dst.getIdx() != reg) { + c.pop(Xbyak::Reg64(reg)); + } else { + c.lea(rsp, ptr[rsp + 8]); + } + } + RestoreStack(c); +} + +#ifdef __APPLE__ + static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { const auto dst = ZydisToXbyakRegisterOperand(operands[0]); const auto src1 = ZydisToXbyakRegisterOperand(operands[1]); @@ -204,9 +318,9 @@ static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenera c.and_(dst, scratch2); if (dst.getIdx() == shift.getIdx()) { - RestoreRegisters(c, {scratch1, scratch2}); + RestoreRegisters(c, {scratch2, scratch1}); } else { - RestoreRegisters(c, {scratch1, scratch2, shift}); + RestoreRegisters(c, {shift, scratch2, scratch1}); } } @@ -218,9 +332,22 @@ static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat SaveRegisters(c, {scratch}); + // BLSI sets CF to zero if source is zero, otherwise it sets CF to one. + Xbyak::Label clear_carry, end; + c.mov(scratch, *src); - c.neg(scratch); + c.neg(scratch); // NEG, like BLSI, clears CF if the source is zero and sets it otherwise + c.jnc(clear_carry); + c.and_(scratch, *src); + c.stc(); // setting/clearing carry needs to happen after the AND because that clears CF + c.jmp(end); + + c.L(clear_carry); + c.and_(scratch, *src); + // We don't need to clear carry here since AND does that for us + + c.L(end); c.mov(dst, scratch); RestoreRegisters(c, {scratch}); @@ -234,9 +361,24 @@ static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGener SaveRegisters(c, {scratch}); + Xbyak::Label clear_carry, end; + + // BLSMSK sets CF to zero if source is NOT zero, otherwise it sets CF to one. c.mov(scratch, *src); + c.test(scratch, scratch); + c.jnz(clear_carry); + c.dec(scratch); c.xor_(scratch, *src); + c.stc(); + c.jmp(end); + + c.L(clear_carry); + c.dec(scratch); + c.xor_(scratch, *src); + // We don't need to clear carry here since XOR does that for us + + c.L(end); c.mov(dst, scratch); RestoreRegisters(c, {scratch}); @@ -250,24 +392,167 @@ static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat SaveRegisters(c, {scratch}); + Xbyak::Label clear_carry, end; + + // BLSR sets CF to zero if source is NOT zero, otherwise it sets CF to one. c.mov(scratch, *src); + c.test(scratch, scratch); + c.jnz(clear_carry); + c.dec(scratch); c.and_(scratch, *src); + c.stc(); + c.jmp(end); + + c.L(clear_carry); + c.dec(scratch); + c.and_(scratch, *src); + // We don't need to clear carry here since AND does that for us + + c.L(end); c.mov(dst, scratch); RestoreRegisters(c, {scratch}); } -bool FilterRosetta2Only(const ZydisDecodedOperand*) { +static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in, + const u32 count) { + for (u32 i = 0; i < count; i++) { + out[i] = half_float::half_cast(in[i]); + } +} + +static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { + const auto dst = ZydisToXbyakRegisterOperand(operands[0]); + const auto src = ZydisToXbyakOperand(operands[1]); + + const auto float_count = dst.getBit() / 32; + const auto byte_count = float_count * 4; + + SaveContext(c, true); + + // Allocate stack space for outputs and load into first parameter. + c.sub(rsp, byte_count); + c.mov(rdi, rsp); + + if (src->isXMM()) { + // Allocate stack space for inputs and load into second parameter. + c.sub(rsp, byte_count); + c.mov(rsi, rsp); + + // Move input to the allocated space. + c.movdqu(ptr[rsp], *reinterpret_cast(src.get())); + } else { + c.lea(rsi, src->getAddress()); + } + + // Load float count into third parameter. + c.mov(rdx, float_count); + + c.mov(rax, reinterpret_cast(PerformVCVTPH2PS)); + c.call(rax); + + if (src->isXMM()) { + // Clean up after inputs space. + c.add(rsp, byte_count); + } + + // Load outputs into destination register and clean up space. + if (dst.isYMM()) { + c.vmovdqu(*reinterpret_cast(&dst), ptr[rsp]); + } else { + c.movdqu(*reinterpret_cast(&dst), ptr[rsp]); + } + c.add(rsp, byte_count); + + RestoreContext(c, dst, true); +} + +using SingleToHalfFloatConverter = half_float::half (*)(float); +static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = { + half_float::half_cast, + half_float::half_cast, + half_float::half_cast, + half_float::half_cast, +}; + +static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in, + const u32 count, const u8 rounding_mode) { + const auto conversion_func = SingleToHalfFloatConverters[rounding_mode]; + + for (u32 i = 0; i < count; i++) { + out[i] = conversion_func(in[i]); + } +} + +static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { + const auto dst = ZydisToXbyakOperand(operands[0]); + const auto src = ZydisToXbyakRegisterOperand(operands[1]); + const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]); + + const auto float_count = src.getBit() / 32; + const auto byte_count = float_count * 4; + + SaveContext(c, true); + + if (dst->isXMM()) { + // Allocate stack space for outputs and load into first parameter. + c.sub(rsp, byte_count); + c.mov(rdi, rsp); + } else { + c.lea(rdi, dst->getAddress()); + } + + // Allocate stack space for inputs and load into second parameter. + c.sub(rsp, byte_count); + c.mov(rsi, rsp); + + // Move input to the allocated space. + if (src.isYMM()) { + c.vmovdqu(ptr[rsp], *reinterpret_cast(&src)); + } else { + c.movdqu(ptr[rsp], *reinterpret_cast(&src)); + } + + // Load float count into third parameter. + c.mov(rdx, float_count); + + // Load rounding mode into fourth parameter. + if (ctrl & 4) { + // Load from MXCSR.RC. + c.stmxcsr(ptr[rsp - 4]); + c.mov(rcx, ptr[rsp - 4]); + c.shr(rcx, 13); + c.and_(rcx, 3); + } else { + c.mov(rcx, ctrl & 3); + } + + c.mov(rax, reinterpret_cast(PerformVCVTPS2PH)); + c.call(rax); + + // Clean up after inputs space. + c.add(rsp, byte_count); + + if (dst->isXMM()) { + // Load outputs into destination register and clean up space. + c.movdqu(*reinterpret_cast(dst.get()), ptr[rsp]); + c.add(rsp, byte_count); + } + + RestoreContext(c, *dst, true); +} + +static bool FilterRosetta2Only(const ZydisDecodedOperand*) { int ret = 0; size_t size = sizeof(ret); - if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) != 0) { + if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) { return false; } return ret; } -#endif // __APPLE__ +#else // __APPLE__ static bool FilterTcbAccess(const ZydisDecodedOperand* operands) { const auto& dst_op = operands[0]; @@ -282,7 +567,6 @@ static bool FilterTcbAccess(const ZydisDecodedOperand* operands) { static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { const auto dst = ZydisToXbyakRegisterOperand(operands[0]); - const auto slot = GetTcbKey(); #if defined(_WIN32) // The following logic is based on the Kernel32.dll asm of TlsGetValue @@ -290,6 +574,8 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe static constexpr u32 TlsExpansionSlotsOffset = 0x1780; static constexpr u32 TlsMinimumAvailable = 64; + const auto slot = GetTcbKey(); + // Load the pointer to the table of TLS slots. c.putSeg(gs); if (slot < TlsMinimumAvailable) { @@ -303,11 +589,6 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe // Load the pointer to our buffer. c.mov(dst, qword[dst + tls_index * sizeof(LPVOID)]); } -#elif defined(__APPLE__) - // The following logic is based on the Darwin implementation of _os_tsd_get_direct, used by - // pthread_getspecific https://github.com/apple/darwin-xnu/blob/main/libsyscall/os/tsd.h#L89-L96 - c.putSeg(gs); - c.mov(dst, qword[reinterpret_cast(slot * sizeof(void*))]); #else const auto src = ZydisToXbyakMemoryOperand(operands[1]); @@ -317,6 +598,275 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe #endif } +#endif // __APPLE__ + +static bool FilterNoSSE4a(const ZydisDecodedOperand*) { + Cpu cpu; + return !cpu.has(Cpu::tSSE4a); +} + +static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { + bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + + ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER, "operand 0 must be a register"); + + const auto dst = ZydisToXbyakRegisterOperand(operands[0]); + + ASSERT_MSG(dst.isXMM(), "operand 0 must be an XMM register"); + + Xbyak::Xmm xmm_dst = *reinterpret_cast(&dst); + + if (immediateForm) { + u8 length = operands[1].imm.value.u & 0x3F; + u8 index = operands[2].imm.value.u & 0x3F; + + LOG_DEBUG(Core, "Patching immediate form EXTRQ, length: {}, index: {}", length, index); + + const Xbyak::Reg64 scratch1 = rax; + const Xbyak::Reg64 scratch2 = rcx; + + // Set rsp to before red zone and save scratch registers + c.lea(rsp, ptr[rsp - 128]); + c.pushfq(); + c.push(scratch1); + c.push(scratch2); + + u64 mask; + if (length == 0) { + length = 64; // for the check below + mask = 0xFFFF'FFFF'FFFF'FFFF; + } else { + mask = (1ULL << length) - 1; + } + + ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64."); + + // Get lower qword from xmm register + MAYBE_AVX(movq, scratch1, xmm_dst); + + if (index != 0) { + c.shr(scratch1, index); + } + + // We need to move mask to a register because we can't use all the possible + // immediate values with `and reg, imm32` + c.mov(scratch2, mask); + c.and_(scratch1, scratch2); + + // Writeback to xmm register, extrq instruction says top 64-bits are undefined so we don't + // care to preserve them + MAYBE_AVX(movq, xmm_dst, scratch1); + + c.pop(scratch2); + c.pop(scratch1); + c.popfq(); + c.lea(rsp, ptr[rsp + 128]); + } else { + ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && + operands[0].reg.value >= ZYDIS_REGISTER_XMM0 && + operands[0].reg.value <= ZYDIS_REGISTER_XMM15 && + operands[1].reg.value >= ZYDIS_REGISTER_XMM0 && + operands[1].reg.value <= ZYDIS_REGISTER_XMM15, + "Unexpected operand types for EXTRQ instruction"); + + const auto src = ZydisToXbyakRegisterOperand(operands[1]); + + ASSERT_MSG(src.isXMM(), "operand 1 must be an XMM register"); + + Xbyak::Xmm xmm_src = *reinterpret_cast(&src); + + const Xbyak::Reg64 scratch1 = rax; + const Xbyak::Reg64 scratch2 = rcx; + const Xbyak::Reg64 mask = rdx; + + Xbyak::Label length_zero, end; + + c.lea(rsp, ptr[rsp - 128]); + c.pushfq(); + c.push(scratch1); + c.push(scratch2); + c.push(mask); + + // Construct the mask out of the length that resides in bottom 6 bits of source xmm + MAYBE_AVX(movq, scratch1, xmm_src); + c.mov(scratch2, scratch1); + c.and_(scratch2, 0x3F); + c.jz(length_zero); + + // mask = (1ULL << length) - 1 + c.mov(mask, 1); + c.shl(mask, cl); + c.dec(mask); + c.jmp(end); + + c.L(length_zero); + c.mov(mask, 0xFFFF'FFFF'FFFF'FFFF); + + c.L(end); + + // Get the shift amount and store it in scratch2 + c.shr(scratch1, 8); + c.and_(scratch1, 0x3F); + c.mov(scratch2, scratch1); // cl now contains the shift amount + + MAYBE_AVX(movq, scratch1, xmm_dst); + c.shr(scratch1, cl); + c.and_(scratch1, mask); + MAYBE_AVX(movq, xmm_dst, scratch1); + + c.pop(mask); + c.pop(scratch2); + c.pop(scratch1); + c.popfq(); + c.lea(rsp, ptr[rsp + 128]); + } +} + +static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) { + bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + + ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER, + "operands 0 and 1 must be registers."); + + const auto dst = ZydisToXbyakRegisterOperand(operands[0]); + const auto src = ZydisToXbyakRegisterOperand(operands[1]); + + ASSERT_MSG(dst.isXMM() && src.isXMM(), "operands 0 and 1 must be xmm registers."); + + Xbyak::Xmm xmm_dst = *reinterpret_cast(&dst); + Xbyak::Xmm xmm_src = *reinterpret_cast(&src); + + if (immediateForm) { + u8 length = operands[2].imm.value.u & 0x3F; + u8 index = operands[3].imm.value.u & 0x3F; + + const Xbyak::Reg64 scratch1 = rax; + const Xbyak::Reg64 scratch2 = rcx; + const Xbyak::Reg64 mask = rdx; + + // Set rsp to before red zone and save scratch registers + c.lea(rsp, ptr[rsp - 128]); + c.pushfq(); + c.push(scratch1); + c.push(scratch2); + c.push(mask); + + u64 mask_value; + if (length == 0) { + length = 64; // for the check below + mask_value = 0xFFFF'FFFF'FFFF'FFFF; + } else { + mask_value = (1ULL << length) - 1; + } + + ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64."); + + MAYBE_AVX(movq, scratch1, xmm_src); + MAYBE_AVX(movq, scratch2, xmm_dst); + c.mov(mask, mask_value); + + // src &= mask + c.and_(scratch1, mask); + + // src <<= index + c.shl(scratch1, index); + + // dst &= ~(mask << index) + mask_value = ~(mask_value << index); + c.mov(mask, mask_value); + c.and_(scratch2, mask); + + // dst |= src + c.or_(scratch2, scratch1); + + // Insert scratch2 into low 64 bits of dst, upper 64 bits are unaffected + Cpu cpu; + if (cpu.has(Cpu::tAVX)) { + c.vpinsrq(xmm_dst, xmm_dst, scratch2, 0); + } else { + c.pinsrq(xmm_dst, scratch2, 0); + } + + c.pop(mask); + c.pop(scratch2); + c.pop(scratch1); + c.popfq(); + c.lea(rsp, ptr[rsp + 128]); + } else { + ASSERT_MSG(operands[2].type == ZYDIS_OPERAND_TYPE_UNUSED && + operands[3].type == ZYDIS_OPERAND_TYPE_UNUSED, + "operands 2 and 3 must be unused for register form."); + + const Xbyak::Reg64 scratch1 = rax; + const Xbyak::Reg64 scratch2 = rcx; + const Xbyak::Reg64 index = rdx; + const Xbyak::Reg64 mask = rbx; + + Xbyak::Label length_zero, end; + + c.lea(rsp, ptr[rsp - 128]); + c.pushfq(); + c.push(scratch1); + c.push(scratch2); + c.push(index); + c.push(mask); + + // Get upper 64 bits of src and copy it to mask and index + MAYBE_AVX(pextrq, index, xmm_src, 1); + c.mov(mask, index); + + // When length is 0, set it to 64 + c.and_(mask, 0x3F); // mask now holds the length + c.jz(length_zero); // Check if length is 0 and set mask to all 1s if it is + + // Create a mask out of the length + c.mov(cl, mask.cvt8()); + c.mov(mask, 1); + c.shl(mask, cl); + c.dec(mask); + c.jmp(end); + + c.L(length_zero); + c.mov(mask, 0xFFFF'FFFF'FFFF'FFFF); + + c.L(end); + // Get index to insert at + c.shr(index, 8); + c.and_(index, 0x3F); + + // src &= mask + MAYBE_AVX(movq, scratch1, xmm_src); + c.and_(scratch1, mask); + + // mask = ~(mask << index) + c.mov(cl, index.cvt8()); + c.shl(mask, cl); + c.not_(mask); + + // src <<= index + c.shl(scratch1, cl); + + // dst = (dst & mask) | src + MAYBE_AVX(movq, scratch2, xmm_dst); + c.and_(scratch2, mask); + c.or_(scratch2, scratch1); + + // Upper 64 bits are undefined in insertq + MAYBE_AVX(movq, xmm_dst, scratch2); + + c.pop(mask); + c.pop(index); + c.pop(scratch2); + c.pop(scratch1); + c.popfq(); + c.lea(rsp, ptr[rsp + 128]); + } +} + using PatchFilter = bool (*)(const ZydisDecodedOperand*); using InstructionGenerator = void (*)(const ZydisDecodedOperand*, Xbyak::CodeGenerator&); struct PatchInfo { @@ -331,81 +881,362 @@ struct PatchInfo { }; static const std::unordered_map Patches = { -#if defined(_WIN32) || defined(__APPLE__) - // Windows and Apple need a trampoline. +#if defined(_WIN32) + // Windows needs a trampoline. {ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}}, -#else +#elif !defined(__APPLE__) {ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}}, #endif + {ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}}, + {ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}}, + #ifdef __APPLE__ - // BMI1 instructions that are not supported by Rosetta 2 on Apple Silicon. + // Patches for instruction sets not supported by Rosetta 2. + // BMI1 {ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}}, {ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}}, {ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}}, {ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}}, {ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}}, + // F16C + {ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}}, + {ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}}, #endif }; -void PatchInstructions(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c) { - if (Patches.empty()) { - // Nothing to patch on this platform. +static std::once_flag init_flag; + +struct PatchModule { + /// Mutex controlling access to module code regions. + std::mutex mutex{}; + + /// Start of the module. + u8* start; + + /// End of the module. + u8* end; + + /// Tracker for patched code locations. + std::set patched; + + /// Code generator for patching the module. + Xbyak::CodeGenerator patch_gen; + + /// Code generator for writing trampoline patches. + Xbyak::CodeGenerator trampoline_gen; + + PatchModule(u8* module_ptr, const u64 module_size, u8* trampoline_ptr, + const u64 trampoline_size) + : start(module_ptr), end(module_ptr + module_size), patch_gen(module_size, module_ptr), + trampoline_gen(trampoline_size, trampoline_ptr) {} +}; +static std::map modules; + +static PatchModule* GetModule(const void* ptr) { + auto upper_bound = modules.upper_bound(reinterpret_cast(ptr)); + if (upper_bound == modules.begin()) { + return nullptr; + } + return &(std::prev(upper_bound)->second); +} + +/// Returns a boolean indicating whether the instruction was patched, and the offset to advance past +/// whatever is at the current code pointer. +static std::pair TryPatch(u8* code, PatchModule* module) { + ZydisDecodedInstruction instruction; + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; + const auto status = Common::Decoder::Instance()->decodeInstruction(instruction, operands, code, + module->end - code); + if (!ZYAN_SUCCESS(status)) { + return std::make_pair(false, 1); + } + + if (Patches.contains(instruction.mnemonic)) { + const auto& patch_info = Patches.at(instruction.mnemonic); + bool needs_trampoline = patch_info.trampoline; + if (patch_info.filter(operands)) { + auto& patch_gen = module->patch_gen; + + if (needs_trampoline && instruction.length < 5) { + // Trampoline is needed but instruction is too short to patch. + // Return false and length to fall back to the illegal instruction handler, + // or to signal to AOT compilation that this instruction should be skipped and + // handled at runtime. + return std::make_pair(false, instruction.length); + } + + // Reset state and move to current code position. + patch_gen.reset(); + patch_gen.setSize(code - patch_gen.getCode()); + + if (needs_trampoline) { + auto& trampoline_gen = module->trampoline_gen; + const auto trampoline_ptr = trampoline_gen.getCurr(); + + patch_info.generator(operands, trampoline_gen); + + // Return to the following instruction at the end of the trampoline. + trampoline_gen.jmp(code + instruction.length); + + // Replace instruction with near jump to the trampoline. + patch_gen.jmp(trampoline_ptr, Xbyak::CodeGenerator::LabelType::T_NEAR); + } else { + patch_info.generator(operands, patch_gen); + } + + const auto patch_size = patch_gen.getCurr() - code; + if (patch_size > 0) { + ASSERT_MSG(instruction.length >= patch_size, + "Instruction {} with length {} is too short to replace at: {}", + ZydisMnemonicGetString(instruction.mnemonic), instruction.length, + fmt::ptr(code)); + + // Fill remaining space with nops. + patch_gen.nop(instruction.length - patch_size); + + module->patched.insert(code); + LOG_DEBUG(Core, "Patched instruction '{}' at: {}", + ZydisMnemonicGetString(instruction.mnemonic), fmt::ptr(code)); + return std::make_pair(true, instruction.length); + } + } + } + + return std::make_pair(false, instruction.length); +} + +#if defined(ARCH_X86_64) + +static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) { + ZydisDecodedInstruction instruction; + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; + const auto status = + Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address); + + switch (instruction.mnemonic) { + case ZYDIS_MNEMONIC_EXTRQ: { + bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + if (immediateForm) { + LOG_CRITICAL(Core, "EXTRQ immediate form should have been patched at code address: {}", + fmt::ptr(code_address)); + return false; + } else { + ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && + operands[0].reg.value >= ZYDIS_REGISTER_XMM0 && + operands[0].reg.value <= ZYDIS_REGISTER_XMM15 && + operands[1].reg.value >= ZYDIS_REGISTER_XMM0 && + operands[1].reg.value <= ZYDIS_REGISTER_XMM15, + "Unexpected operand types for EXTRQ instruction"); + + const auto dstIndex = operands[0].reg.value - ZYDIS_REGISTER_XMM0; + const auto srcIndex = operands[1].reg.value - ZYDIS_REGISTER_XMM0; + + const auto dst = Common::GetXmmPointer(ctx, dstIndex); + const auto src = Common::GetXmmPointer(ctx, srcIndex); + + u64 lowQWordSrc; + memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc)); + + u64 lowQWordDst; + memcpy(&lowQWordDst, dst, sizeof(lowQWordDst)); + + u64 length = lowQWordSrc & 0x3F; + u64 mask; + if (length == 0) { + length = 64; // for the check below + mask = 0xFFFF'FFFF'FFFF'FFFF; + } else { + mask = (1ULL << length) - 1; + } + + u64 index = (lowQWordSrc >> 8) & 0x3F; + if (length + index > 64) { + // Undefined behavior if length + index is bigger than 64 according to the spec, + // we'll warn and continue execution. + LOG_WARNING(Core, + "extrq at {} with length {} and index {} is bigger than 64, " + "undefined behavior", + fmt::ptr(code_address), length, index); + } + + lowQWordDst >>= index; + lowQWordDst &= mask; + + memcpy(dst, &lowQWordDst, sizeof(lowQWordDst)); + + Common::IncrementRip(ctx, instruction.length); + + return true; + } + break; + } + case ZYDIS_MNEMONIC_INSERTQ: { + bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + if (immediateForm) { + LOG_CRITICAL(Core, + "INSERTQ immediate form should have been patched at code address: {}", + fmt::ptr(code_address)); + return false; + } else { + ASSERT_MSG(operands[2].type == ZYDIS_OPERAND_TYPE_UNUSED && + operands[3].type == ZYDIS_OPERAND_TYPE_UNUSED, + "operands 2 and 3 must be unused for register form."); + + ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER, + "operands 0 and 1 must be registers."); + + const auto dstIndex = operands[0].reg.value - ZYDIS_REGISTER_XMM0; + const auto srcIndex = operands[1].reg.value - ZYDIS_REGISTER_XMM0; + + const auto dst = Common::GetXmmPointer(ctx, dstIndex); + const auto src = Common::GetXmmPointer(ctx, srcIndex); + + u64 lowQWordSrc, highQWordSrc; + memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc)); + memcpy(&highQWordSrc, (u8*)src + 8, sizeof(highQWordSrc)); + + u64 lowQWordDst; + memcpy(&lowQWordDst, dst, sizeof(lowQWordDst)); + + u64 length = highQWordSrc & 0x3F; + u64 mask; + if (length == 0) { + length = 64; // for the check below + mask = 0xFFFF'FFFF'FFFF'FFFF; + } else { + mask = (1ULL << length) - 1; + } + + u64 index = (highQWordSrc >> 8) & 0x3F; + if (length + index > 64) { + // Undefined behavior if length + index is bigger than 64 according to the spec, + // we'll warn and continue execution. + LOG_WARNING(Core, + "insertq at {} with length {} and index {} is bigger than 64, " + "undefined behavior", + fmt::ptr(code_address), length, index); + } + + lowQWordSrc &= mask; + lowQWordDst &= ~(mask << index); + lowQWordDst |= lowQWordSrc << index; + + memcpy(dst, &lowQWordDst, sizeof(lowQWordDst)); + + Common::IncrementRip(ctx, instruction.length); + + return true; + } + break; + } + default: { + LOG_ERROR(Core, "Unhandled illegal instruction at code address {}: {}", + fmt::ptr(code_address), ZydisMnemonicGetString(instruction.mnemonic)); + return false; + } + } + + UNREACHABLE(); +} +#elif defined(ARCH_ARM64) +// These functions shouldn't be needed for ARM as it will use a JIT so there's no need to patch +// instructions. +static bool TryExecuteIllegalInstruction(void*, void*) { + return false; +} +#else +#error "Unsupported architecture" +#endif + +static bool TryPatchJit(void* code_address) { + auto* code = static_cast(code_address); + auto* module = GetModule(code); + if (module == nullptr) { + return false; + } + + std::unique_lock lock{module->mutex}; + + // Return early if already patched, in case multiple threads signaled at the same time. + if (std::ranges::find(module->patched, code) != module->patched.end()) { + return true; + } + + return TryPatch(code, module).first; +} + +static void TryPatchAot(void* code_address, u64 code_size) { + auto* code = static_cast(code_address); + auto* module = GetModule(code); + if (module == nullptr) { return; } - ZydisDecoder instr_decoder; - ZydisDecodedInstruction instruction; - ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - ZydisDecoderInit(&instr_decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); + std::unique_lock lock{module->mutex}; - u8* code = reinterpret_cast(segment_addr); - u8* end = code + segment_size; + const auto* end = code + code_size; while (code < end) { - ZyanStatus status = - ZydisDecoderDecodeFull(&instr_decoder, code, end - code, &instruction, operands); - if (!ZYAN_SUCCESS(status)) { - code++; - continue; - } - - if (Patches.contains(instruction.mnemonic)) { - auto patch_info = Patches.at(instruction.mnemonic); - if (patch_info.filter(operands)) { - auto patch_gen = Xbyak::CodeGenerator(instruction.length, code); - - if (patch_info.trampoline) { - const auto trampoline_ptr = c.getCurr(); - - patch_info.generator(operands, c); - - // Return to the following instruction at the end of the trampoline. - c.jmp(code + instruction.length); - - // Replace instruction with near jump to the trampoline. - patch_gen.jmp(trampoline_ptr, Xbyak::CodeGenerator::LabelType::T_NEAR); - } else { - patch_info.generator(operands, patch_gen); - } - - const auto patch_size = patch_gen.getCurr() - code; - if (patch_size > 0) { - ASSERT_MSG(instruction.length >= patch_size, - "Instruction {} with length {} is too short to replace at: {}", - ZydisMnemonicGetString(instruction.mnemonic), instruction.length, - fmt::ptr(code)); - - // Fill remaining space with nops. - patch_gen.nop(instruction.length - patch_size); - - LOG_DEBUG(Core, "Patched instruction '{}' at: {}", - ZydisMnemonicGetString(instruction.mnemonic), fmt::ptr(code)); - } - } - } - - code += instruction.length; + code += TryPatch(code, module).second; } } +static bool PatchesAccessViolationHandler(void* context, void* /* fault_address */) { + return TryPatchJit(Common::GetRip(context)); +} + +static bool PatchesIllegalInstructionHandler(void* context) { + void* code_address = Common::GetRip(context); + if (!TryPatchJit(code_address)) { + return TryExecuteIllegalInstruction(context, code_address); + } + return true; +} + +static void PatchesInit() { + if (!Patches.empty()) { + auto* signals = Signals::Instance(); + // Should be called last. + constexpr auto priority = std::numeric_limits::max(); + signals->RegisterAccessViolationHandler(PatchesAccessViolationHandler, priority); + signals->RegisterIllegalInstructionHandler(PatchesIllegalInstructionHandler, priority); + } +} + +void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr, + u64 trampoline_area_size) { + std::call_once(init_flag, PatchesInit); + + const auto module_addr = reinterpret_cast(module_ptr); + modules.emplace(std::piecewise_construct, std::forward_as_tuple(module_addr), + std::forward_as_tuple(static_cast(module_ptr), module_size, + static_cast(trampoline_area_ptr), + trampoline_area_size)); +} + +void PrePatchInstructions(u64 segment_addr, u64 segment_size) { +#if defined(__APPLE__) + // HACK: For some reason patching in the signal handler at the start of a page does not work + // under Rosetta 2. Patch any instructions at the start of a page ahead of time. + if (!Patches.empty()) { + auto* code_page = reinterpret_cast(Common::AlignUp(segment_addr, 0x1000)); + const auto* end_page = code_page + Common::AlignUp(segment_size, 0x1000); + while (code_page < end_page) { + TryPatchJit(code_page); + code_page += 0x1000; + } + } +#elif !defined(_WIN32) + // Linux and others have an FS segment pointing to valid memory, so continue to do full + // ahead-of-time patching for now until a better solution is worked out. + if (!Patches.empty()) { + TryPatchAot(reinterpret_cast(segment_addr), segment_size); + } +#endif +} + } // namespace Core diff --git a/src/core/cpu_patches.h b/src/core/cpu_patches.h index 45adbeda3..f9f7fe646 100644 --- a/src/core/cpu_patches.h +++ b/src/core/cpu_patches.h @@ -3,13 +3,19 @@ #pragma once -namespace Xbyak { -class CodeGenerator; -} - namespace Core { -/// Patches CPU instructions that cannot run as-is on the host. -void PatchInstructions(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c); +/// Initializes a stack for the current thread for use by patch implementations. +void InitializeThreadPatchStack(); + +/// Cleans up the patch stack for the current thread. +void CleanupThreadPatchStack(); + +/// Registers a module for patching, providing an area to generate trampoline code. +void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr, + u64 trampoline_area_size); + +/// Applies CPU patches that need to be done before beginning executions. +void PrePatchInstructions(u64 segment_addr, u64 segment_size); } // namespace Core diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp index 630faa344..aa1c96724 100644 --- a/src/core/crypto/crypto.cpp +++ b/src/core/crypto/crypto.cpp @@ -6,18 +6,18 @@ CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() { CryptoPP::InvertibleRSAFunction params; - params.SetPrime1(CryptoPP::Integer(pkg_derived_key3_keyset.Prime1, 0x80)); - params.SetPrime2(CryptoPP::Integer(pkg_derived_key3_keyset.Prime2, 0x80)); + params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80)); + params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80)); - params.SetPublicExponent(CryptoPP::Integer(pkg_derived_key3_keyset.PublicExponent, 4)); - params.SetPrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.PrivateExponent, 0x100)); + params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4)); + params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100)); - params.SetModPrime1PrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.Exponent1, 0x80)); - params.SetModPrime2PrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.Exponent2, 0x80)); + params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80)); + params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80)); - params.SetModulus(CryptoPP::Integer(pkg_derived_key3_keyset.Modulus, 0x100)); + params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100)); params.SetMultiplicativeInverseOfPrime2ModPrime1( - CryptoPP::Integer(pkg_derived_key3_keyset.Coefficient, 0x80)); + CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80)); CryptoPP::RSA::PrivateKey privateKey(params); @@ -26,18 +26,18 @@ CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() { CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() { CryptoPP::InvertibleRSAFunction params; - params.SetPrime1(CryptoPP::Integer(FakeKeyset_keyset.Prime1, 0x80)); - params.SetPrime2(CryptoPP::Integer(FakeKeyset_keyset.Prime2, 0x80)); + params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80)); + params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80)); - params.SetPublicExponent(CryptoPP::Integer(FakeKeyset_keyset.PublicExponent, 4)); - params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.PrivateExponent, 0x100)); + params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4)); + params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100)); - params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.Exponent1, 0x80)); - params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.Exponent2, 0x80)); + params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80)); + params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80)); - params.SetModulus(CryptoPP::Integer(FakeKeyset_keyset.Modulus, 0x100)); + params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100)); params.SetMultiplicativeInverseOfPrime2ModPrime1( - CryptoPP::Integer(FakeKeyset_keyset.Coefficient, 0x80)); + CryptoPP::Integer(FakeKeyset::Coefficient, 0x80)); CryptoPP::RSA::PrivateKey privateKey(params); @@ -46,25 +46,22 @@ CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() { CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() { CryptoPP::InvertibleRSAFunction params; - params.SetPrime1( - CryptoPP::Integer(DebugRifKeyset_keyset.Prime1, sizeof(DebugRifKeyset_keyset.Prime1))); - params.SetPrime2( - CryptoPP::Integer(DebugRifKeyset_keyset.Prime2, sizeof(DebugRifKeyset_keyset.Prime2))); + params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1))); + params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2))); - params.SetPublicExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent, - sizeof(DebugRifKeyset_keyset.PrivateExponent))); - params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent, - sizeof(DebugRifKeyset_keyset.PrivateExponent))); + params.SetPublicExponent( + CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent))); + params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent, + sizeof(DebugRifKeyset::PrivateExponent))); - params.SetModPrime1PrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.Exponent1, - sizeof(DebugRifKeyset_keyset.Exponent1))); - params.SetModPrime2PrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.Exponent2, - sizeof(DebugRifKeyset_keyset.Exponent2))); + params.SetModPrime1PrivateExponent( + CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1))); + params.SetModPrime2PrivateExponent( + CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2))); - params.SetModulus( - CryptoPP::Integer(DebugRifKeyset_keyset.Modulus, sizeof(DebugRifKeyset_keyset.Modulus))); - params.SetMultiplicativeInverseOfPrime2ModPrime1(CryptoPP::Integer( - DebugRifKeyset_keyset.Coefficient, sizeof(DebugRifKeyset_keyset.Coefficient))); + params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus))); + params.SetMultiplicativeInverseOfPrime2ModPrime1( + CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient))); CryptoPP::RSA::PrivateKey privateKey(params); diff --git a/src/core/crypto/crypto.h b/src/core/crypto/crypto.h index 0c5bc9955..83249bd7d 100644 --- a/src/core/crypto/crypto.h +++ b/src/core/crypto/crypto.h @@ -17,10 +17,6 @@ class Crypto { public: - PkgDerivedKey3Keyset pkg_derived_key3_keyset; - FakeKeyset FakeKeyset_keyset; - DebugRifKeyset DebugRifKeyset_keyset; - CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init(); CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init(); CryptoPP::RSA::PrivateKey DebugRifKeyset_init(); diff --git a/src/core/crypto/keys.h b/src/core/crypto/keys.h index 37b66bd09..441082481 100644 --- a/src/core/crypto/keys.h +++ b/src/core/crypto/keys.h @@ -7,384 +7,299 @@ class FakeKeyset { public: // Constructor - const CryptoPP::byte* Exponent1; + static constexpr CryptoPP::byte Exponent1[] = { + 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7, + 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9, + 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6, + 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6, + 0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC, + 0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF, + 0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8, + 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E, + 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25}; // exponent2 = d mod (q - 1) - const CryptoPP::byte* Exponent2; + static constexpr CryptoPP::byte Exponent2[] = { + 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60, + 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8, + 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75, + 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18, + 0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16, + 0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C, + 0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD, + 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA, + 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D}; // e - const CryptoPP::byte* PublicExponent; + static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1}; // (InverseQ)(q) = 1 mod p - const CryptoPP::byte* Coefficient; + static constexpr CryptoPP::byte Coefficient[] = { + 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD, + 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D, + 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B, + 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69, + 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15, + 0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8, + 0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6, + 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67, + 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5}; // n = p * q - const CryptoPP::byte* Modulus; + static constexpr CryptoPP::byte Modulus[] = { + 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E, + 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D, + 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B, + 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7, + 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C, + 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33, + 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01, + 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A, + 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96, + 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80, + 0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F, + 0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53, + 0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22, + 0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F, + 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40, + 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9, + 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E, + 0x27}; // p - const CryptoPP::byte* Prime1; + static constexpr CryptoPP::byte Prime1[] = { + 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35, + 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24, + 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9, + 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F, + 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C, + 0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A, + 0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40, + 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89, + 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D}; // q - const CryptoPP::byte* Prime2; - const CryptoPP::byte* PrivateExponent; - - // Constructor - FakeKeyset() { - // Initialize PrivateExponent - PrivateExponent = new CryptoPP::byte[0x100]{ - 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, - 0xFA, 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, - 0xDB, 0xFD, 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, - 0xB1, 0x22, 0x5C, 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, - 0xD1, 0x49, 0x2C, 0x8F, 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, - 0xD2, 0x21, 0x28, 0x83, 0x09, 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, - 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14, 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, - 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77, 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, - 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90, 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, - 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22, 0x58, 0xD5, 0x43, 0x82, 0x49, - 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0, 0xCE, 0x3D, 0xDF, 0xF4, - 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93, 0x23, 0xDB, 0xBA, - 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5, 0x71, 0x67, - 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5, 0x6C, - 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1, - 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, - 0x85, 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, - 0xEC, 0x39, 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, - 0x79, 0x89, 0xC6, 0xB1}; - - // Initialize Exponent1 - Exponent1 = new CryptoPP::byte[0x80]{ - 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, - 0xD2, 0xC7, 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, - 0x1D, 0xB7, 0xBC, 0xB9, 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, - 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6, 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, - 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6, 0x5A, 0xA0, 0xBE, 0x05, 0x70, - 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC, 0xC1, 0x62, 0x3D, - 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF, 0x08, - 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, - 0xE8, 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, - 0xF0, 0x17, 0x1E, 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25 - - }; - - Exponent2 = new CryptoPP::byte[0x80]{ - 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, - 0xBF, 0x60, 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, - 0xA7, 0xBF, 0xD0, 0xE8, 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, - 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75, 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, - 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18, 0x96, 0x80, 0x11, 0xDB, 0x68, - 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16, 0x0D, 0x3E, 0x12, - 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C, 0xD6, - 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, - 0xAD, 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, - 0xBC, 0x6C, 0xAA, 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D}; - - PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1}; - - Coefficient = new CryptoPP::byte[0x80]{ - 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, - 0x55, 0xFD, 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, - 0xA0, 0x16, 0x27, 0x3D, 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, - 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B, 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, - 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69, 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, - 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15, 0x07, 0x15, 0x6E, - 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8, 0x0A, - 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, - 0xA6, 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, - 0xDA, 0xF1, 0x67, 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5}; - - Modulus = new CryptoPP::byte[0x100]{ - 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, - 0x0E, 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, - 0x35, 0x9D, 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, - 0x02, 0x68, 0x2B, 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, - 0x48, 0x03, 0xC9, 0xE7, 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, - 0xE7, 0x9D, 0xFF, 0x77, 0x0C, 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, - 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33, 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, - 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01, 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, - 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A, 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, - 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96, 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, - 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80, 0x69, 0x2E, 0xFE, 0xFF, - 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F, 0xBB, 0xB7, 0x79, - 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53, 0xC2, 0x69, - 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22, 0xFD, - 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F, - 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, - 0x40, 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, - 0xD1, 0xF9, 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, - 0x7C, 0xBD, 0x3E, 0x27}; - - Prime1 = new CryptoPP::byte[0x80]{ - 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, - 0xE4, 0x35, 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, - 0x19, 0xD1, 0x04, 0x24, 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, - 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9, 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, - 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F, 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, - 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C, 0x21, 0x33, 0x12, - 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A, 0x1B, - 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, - 0x40, 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, - 0xC9, 0x31, 0x89, 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D}; - - Prime2 = new CryptoPP::byte[0x80]{ - 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, - 0xA8, 0x97, 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, - 0x8E, 0x57, 0xEF, 0xF0, 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, - 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D, 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, - 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47, 0x97, 0xCC, 0x90, 0x39, 0x15, - 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92, 0xBE, 0x97, 0xBF, - 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A, 0x7E, - 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, - 0x79, 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, - 0x2A, 0xFE, 0x51, 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23}; - }; + static constexpr CryptoPP::byte Prime2[] = { + 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97, + 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0, + 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D, + 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47, + 0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92, + 0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A, + 0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79, + 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51, + 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23}; + static constexpr CryptoPP::byte PrivateExponent[] = { + 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA, + 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD, + 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C, + 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F, + 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09, + 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14, + 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77, + 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90, + 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22, + 0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0, + 0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93, + 0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5, + 0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5, + 0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1, + 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85, + 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39, + 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6, + 0xB1}; }; class DebugRifKeyset { public: - // Constructor // std::uint8_t* PrivateExponent; - const CryptoPP::byte* Exponent1; + static constexpr CryptoPP::byte Exponent1[] = { + 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56, + 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C, + 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F, + 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87, + 0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F, + 0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6, + 0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69, + 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6, + 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9}; // exponent2 = d mod (q - 1) - const CryptoPP::byte* Exponent2; + static constexpr CryptoPP::byte Exponent2[] = { + 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44, + 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B, + 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91, + 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88, + 0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B, + 0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7, + 0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF, + 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F, + 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05}; // e - const CryptoPP::byte* PublicExponent; + static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01}; // (InverseQ)(q) = 1 mod p - const CryptoPP::byte* Coefficient; + static constexpr CryptoPP::byte Coefficient[] = { + 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C, + 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4, + 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4, + 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD, + 0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A, + 0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7, + 0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75, + 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A, + 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB}; // n = p * q - const CryptoPP::byte* Modulus; + static constexpr CryptoPP::byte Modulus[] = { + 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A, + 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB, + 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B, + 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD, + 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53, + 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F, + 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30, + 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A, + 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4, + 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B, + 0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E, + 0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87, + 0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19, + 0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A, + 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C, + 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58, + 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64, + 0xC1}; // p - const CryptoPP::byte* Prime1; + static constexpr CryptoPP::byte Prime1[] = { + 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6, + 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34, + 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8, + 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5, + 0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5, + 0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8, + 0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39, + 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F, + 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05}; // q - const CryptoPP::byte* Prime2; - const CryptoPP::byte* PrivateExponent; - - // Constructor - DebugRifKeyset() { - // Initialize PrivateExponent - PrivateExponent = new CryptoPP::byte[0x100]{ - 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, - 0x01, 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, - 0x64, 0xEC, 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, - 0xC6, 0xA3, 0x73, 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, - 0x23, 0xD8, 0x1B, 0x61, 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, - 0x03, 0x4A, 0xBF, 0xFE, 0xF9, 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, - 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28, 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, - 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36, 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, - 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E, 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, - 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14, 0x3D, 0x90, 0xE4, 0xDE, 0x5D, - 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97, 0x2D, 0x89, 0x2A, 0x51, - 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F, 0xA1, 0x8A, 0x69, - 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C, 0xC7, 0xE8, - 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61, 0xB9, - 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49, - 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, - 0xB3, 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, - 0xAF, 0x6E, 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, - 0xF1, 0xCF, 0x14, 0xA5}; - - // Initialize Exponent1 - Exponent1 = new CryptoPP::byte[0x80]{ - 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, - 0xB7, 0x56, 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, - 0x7F, 0x49, 0xA2, 0x9C, 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, - 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F, 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, - 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87, 0x98, 0x78, 0xBF, 0x26, 0xB5, - 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F, 0xFA, 0x1C, 0x64, - 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6, 0x9C, - 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, - 0x69, 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, - 0xA4, 0x10, 0xB6, 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9 - - }; - - Exponent2 = new CryptoPP::byte[0x80]{ - 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, - 0xDB, 0x44, 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, - 0xC5, 0xFC, 0xFE, 0x4B, 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, - 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91, 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, - 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88, 0x5F, 0x71, 0x03, 0x99, 0x79, - 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B, 0x30, 0x74, 0x57, - 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7, 0x6B, - 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, - 0xDF, 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, - 0x22, 0xD7, 0x7F, 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05}; - - PublicExponent = new CryptoPP::byte[4]{0x00, 0x01, 0x00, 0x01}; - - Coefficient = new CryptoPP::byte[0x80]{ - 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, - 0x94, 0x6C, 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, - 0xEB, 0x2C, 0xFB, 0xD4, 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, - 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4, 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, - 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD, 0xE2, 0xBD, 0x94, 0xA6, 0x2B, - 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A, 0x6C, 0xBF, 0x3C, - 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7, 0x3C, - 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, - 0x75, 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, - 0xC1, 0x8A, 0x4A, 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB}; - - Modulus = new CryptoPP::byte[0x100]{ - 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, - 0x8A, 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, - 0x02, 0xBB, 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, - 0x5A, 0xE0, 0x3B, 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, - 0x34, 0x9A, 0x5B, 0xAD, 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, - 0xB3, 0xDA, 0xB3, 0xB2, 0x53, 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, - 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F, 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, - 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30, 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, - 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A, 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, - 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4, 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, - 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B, 0x32, 0x03, 0xA3, 0x09, - 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E, 0x49, 0xF8, 0xB5, - 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87, 0xED, 0x19, - 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19, 0x3C, - 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A, - 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, - 0x7C, 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, - 0x1B, 0x58, 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, - 0x42, 0x9F, 0x64, 0xC1}; - - Prime1 = new CryptoPP::byte[0x80]{ - 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, - 0xC4, 0xB6, 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, - 0x9C, 0x01, 0x5E, 0x34, 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, - 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8, 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, - 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5, 0x51, 0x3E, 0x7B, 0xE3, 0x53, - 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5, 0x35, 0x0E, 0x6F, - 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8, 0xD7, - 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, - 0x39, 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, - 0x35, 0x48, 0x6F, 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05}; - - Prime2 = new CryptoPP::byte[0x80]{ - 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, - 0x12, 0x9C, 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, - 0xFD, 0xF0, 0xAD, 0x38, 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, - 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D, 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, - 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2, 0x08, 0x92, 0xA7, 0x85, 0xF5, - 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31, 0x20, 0x34, 0x49, - 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE, 0x9A, - 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, - 0x81, 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, - 0x54, 0x91, 0x6B, 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D}; - }; + static constexpr CryptoPP::byte Prime2[] = { + 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C, + 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38, + 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D, + 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2, + 0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31, + 0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE, + 0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81, + 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B, + 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D}; + static constexpr CryptoPP::byte PrivateExponent[] = { + 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01, + 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC, + 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73, + 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61, + 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9, + 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28, + 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36, + 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E, + 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14, + 0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97, + 0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F, + 0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C, + 0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61, + 0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49, + 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3, + 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E, + 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14, + 0xA5}; }; class PkgDerivedKey3Keyset { public: - // PkgDerivedKey3Keyset(); - //~PkgDerivedKey3Keyset(); - - // Constructor // std::uint8_t* PrivateExponent; - const CryptoPP::byte* Exponent1; + static constexpr CryptoPP::byte Exponent1[] = { + 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1, + 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7, + 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36, + 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43, + 0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0, + 0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E, + 0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D, + 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC, + 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13}; // exponent2 = d mod (q - 1) - const CryptoPP::byte* Exponent2; + static constexpr CryptoPP::byte Exponent2[] = { + 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5, + 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71, + 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51, + 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D, + 0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00, + 0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98, + 0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1, + 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57, + 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37}; // e - const CryptoPP::byte* PublicExponent; + static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1}; // (InverseQ)(q) = 1 mod p - const CryptoPP::byte* Coefficient; + static constexpr CryptoPP::byte Coefficient[] = { + 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42, + 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3, + 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE, + 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C, + 0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF, + 0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D, + 0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17, + 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6, + 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3}; // n = p * q - const CryptoPP::byte* Modulus; + static constexpr CryptoPP::byte Modulus[] = { + 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27, + 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb, + 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb, + 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef, + 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a, + 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99, + 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d, + 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44, + 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c, + 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65, + 0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6, + 0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65, + 0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f, + 0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01, + 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09, + 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95, + 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3, + 0xc1}; // p - const CryptoPP::byte* Prime1; + static constexpr CryptoPP::byte Prime1[] = { + 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D, + 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42, + 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE, + 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52, + 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D, + 0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23, + 0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80, + 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE, + 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB}; // q - const CryptoPP::byte* Prime2; - const CryptoPP::byte* PrivateExponent; - - PkgDerivedKey3Keyset() { - - Prime1 = new CryptoPP::byte[0x80]{ - 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, - 0xB3, 0x4D, 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, - 0xC7, 0x3F, 0xC3, 0x42, 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, - 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE, 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, - 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52, 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, - 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D, 0xB3, 0xCB, 0x3C, - 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23, 0x63, - 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, - 0x80, 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, - 0x89, 0x8E, 0xAE, 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB}; - - Prime2 = new CryptoPP::byte[0x80]{ - 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, - 0xD9, 0x40, 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, - 0xF9, 0xC3, 0x61, 0x0F, 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, - 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89, 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, - 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9, 0xB4, 0xC7, 0xB5, 0x1B, 0x05, - 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E, 0x5C, 0xFB, 0x92, - 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C, 0x07, - 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, - 0x53, 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, - 0x01, 0xEE, 0x10, 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73}; - PrivateExponent = new CryptoPP::byte[0x100]{ - 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, - 0xB3, 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, - 0xDF, 0xC1, 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, - 0x64, 0xB0, 0xBE, 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, - 0xD7, 0x76, 0x01, 0x41, 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, - 0x5A, 0xE2, 0xA0, 0xBC, 0x2D, 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, - 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F, 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, - 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3, 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, - 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB, 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, - 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD, 0x35, 0xE1, 0x20, 0xF8, 0xAD, - 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB, 0x52, 0x08, 0xFD, 0x06, - 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F, 0xAA, 0x10, 0x30, - 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80, 0xEC, 0x8F, - 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65, 0x3E, - 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64, - 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, - 0x1A, 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, - 0xD9, 0x08, 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, - 0xFF, 0x77, 0xFC, 0x0D}; - Exponent1 = new CryptoPP::byte[0x80]{ - 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, - 0x45, 0xD1, 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, - 0xAB, 0x6E, 0x2A, 0xA7, 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, - 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36, 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, - 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43, 0x2A, 0xC0, 0xE5, 0x98, 0xC9, - 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0, 0x6D, 0x88, 0xF2, - 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E, 0xF6, - 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, - 0x3D, 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, - 0x16, 0xC4, 0xAC, 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13}; - Exponent2 = new CryptoPP::byte[0x80]{ - 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, - 0x95, 0xD5, 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, - 0xBB, 0xBF, 0x89, 0x71, 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, - 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51, 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, - 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D, 0x42, 0xD8, 0x03, 0xB7, 0x68, - 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00, 0xC8, 0xF5, 0xEF, - 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98, 0xC0, - 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, - 0xA1, 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, - 0x31, 0x21, 0x57, 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37}; - Coefficient = new CryptoPP::byte[0x80]{ - 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, - 0xAA, 0x42, 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, - 0x6E, 0x3E, 0x32, 0xE3, 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, - 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE, 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, - 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C, 0x26, 0xC8, 0x25, 0xFF, 0x34, - 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF, 0xEB, 0xBA, 0xE3, - 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D, 0xE9, - 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, - 0x17, 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, - 0x62, 0xA7, 0xD6, 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3}; - Modulus = new CryptoPP::byte[0x100]{ - 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, - 0x27, 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, - 0x8c, 0xfb, 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, - 0xcd, 0x2a, 0xbb, 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, - 0x8e, 0xda, 0x4b, 0xef, 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, - 0x32, 0x6a, 0x58, 0x31, 0x2a, 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, - 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99, 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, - 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d, 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, - 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44, 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, - 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c, 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, - 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65, 0x47, 0x84, 0x1e, 0xe5, - 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6, 0x40, 0x98, 0x2c, - 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65, 0xc1, 0xaa, - 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f, 0x61, - 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01, - 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, - 0x09, 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, - 0x0b, 0x95, 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, - 0xf9, 0xc9, 0xa3, 0xc1}; - PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1}; - }; + static constexpr CryptoPP::byte Prime2[] = { + 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40, + 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F, + 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89, + 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9, + 0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E, + 0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C, + 0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53, + 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10, + 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73}; + static constexpr CryptoPP::byte PrivateExponent[] = { + 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3, + 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1, + 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE, + 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41, + 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D, + 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F, + 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3, + 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB, + 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD, + 0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB, + 0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F, + 0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80, + 0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65, + 0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64, + 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A, + 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08, + 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC, + 0x0D}; }; \ No newline at end of file diff --git a/src/core/debug_state.cpp b/src/core/debug_state.cpp new file mode 100644 index 000000000..adcb0cadb --- /dev/null +++ b/src/core/debug_state.cpp @@ -0,0 +1,178 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "common/assert.h" +#include "common/native_clock.h" +#include "common/singleton.h" +#include "debug_state.h" +#include "devtools/widget/common.h" +#include "libraries/kernel/time_management.h" +#include "libraries/system/msgdialog.h" +#include "video_core/amdgpu/pm4_cmds.h" + +using namespace DebugStateType; + +DebugStateImpl& DebugState = *Common::Singleton::Instance(); + +static ThreadID ThisThreadID() { +#ifdef _WIN32 + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +static void PauseThread(ThreadID id) { +#ifdef _WIN32 + auto handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, id); + SuspendThread(handle); + CloseHandle(handle); +#else + pthread_kill(id, SIGUSR1); +#endif +} + +static void ResumeThread(ThreadID id) { +#ifdef _WIN32 + auto handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, id); + ResumeThread(handle); + CloseHandle(handle); +#else + pthread_kill(id, SIGUSR1); +#endif +} + +void DebugStateImpl::AddCurrentThreadToGuestList() { + std::lock_guard lock{guest_threads_mutex}; + const ThreadID id = ThisThreadID(); + guest_threads.push_back(id); +} + +void DebugStateImpl::RemoveCurrentThreadFromGuestList() { + std::lock_guard lock{guest_threads_mutex}; + const ThreadID id = ThisThreadID(); + std::erase_if(guest_threads, [&](const ThreadID& v) { return v == id; }); +} + +void DebugStateImpl::PauseGuestThreads() { + using namespace Libraries::MsgDialog; + std::unique_lock lock{guest_threads_mutex}; + if (is_guest_threads_paused) { + return; + } + if (ShouldPauseInSubmit()) { + waiting_submit_pause = false; + should_show_frame_dump = true; + } + bool self_guest = false; + ThreadID self_id = ThisThreadID(); + for (const auto& id : guest_threads) { + if (id == self_id) { + self_guest = true; + } else { + PauseThread(id); + } + } + pause_time = Libraries::Kernel::Dev::GetClock()->GetUptime(); + is_guest_threads_paused = true; + lock.unlock(); + if (self_guest) { + PauseThread(self_id); + } +} + +void DebugStateImpl::ResumeGuestThreads() { + std::lock_guard lock{guest_threads_mutex}; + if (!is_guest_threads_paused) { + return; + } + + u64 delta_time = Libraries::Kernel::Dev::GetClock()->GetUptime() - pause_time; + Libraries::Kernel::Dev::GetInitialPtc() += delta_time; + for (const auto& id : guest_threads) { + ResumeThread(id); + } + is_guest_threads_paused = false; +} + +void DebugStateImpl::RequestFrameDump(s32 count) { + ASSERT(!DumpingCurrentFrame()); + gnm_frame_dump_request_count = count; + frame_dump_list.clear(); + frame_dump_list.resize(count); + const auto f = gnm_frame_count.load() + 1; + for (size_t i = 0; i < count; ++i) { + frame_dump_list[i].frame_id = f + i; + } + waiting_submit_pause = true; +} + +void DebugStateImpl::PushQueueDump(QueueDump dump) { + ASSERT(DumpingCurrentFrame()); + std::unique_lock lock{frame_dump_list_mutex}; + auto& frame = GetFrameDump(); + { // Find draw calls + auto data = std::span{dump.data}; + auto initial_data = data.data(); + while (!data.empty()) { + const auto* header = reinterpret_cast(data.data()); + const auto type = header->type; + if (type == 2) { + data = data.subspan(1); + } else if (type != 3) { + UNREACHABLE(); + } + const AmdGpu::PM4ItOpcode opcode = header->opcode; + if (Core::Devtools::Widget::IsDrawCall(opcode)) { + const auto offset = + reinterpret_cast(header) - reinterpret_cast(initial_data); + const auto addr = dump.base_addr + offset; + waiting_reg_dumps.emplace(addr, &frame); + waiting_reg_dumps_dbg.emplace( + addr, + fmt::format("#{} h({}) queue {} {} {}", + frame_dump_list.size() - gnm_frame_dump_request_count, addr, + magic_enum::enum_name(dump.type), dump.submit_num, dump.num2)); + } + data = data.subspan(header->NumWords() + 1); + } + } + frame.queues.push_back(std::move(dump)); +} + +void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, + const AmdGpu::Liverpool::Regs& regs, bool is_compute) { + std::scoped_lock lock{frame_dump_list_mutex}; + const auto it = waiting_reg_dumps.find(header_addr); + if (it == waiting_reg_dumps.end()) { + return; + } + auto& frame = *it->second; + waiting_reg_dumps.erase(it); + waiting_reg_dumps_dbg.erase(waiting_reg_dumps_dbg.find(header_addr)); + auto& dump = frame.regs[header_addr - base_addr]; + dump.regs = regs; + if (is_compute) { + dump.is_compute = true; + const auto& cs = dump.regs.cs_program; + dump.cs_data = ComputerShaderDump{ + .cs_program = cs, + .code = std::vector{cs.Code().begin(), cs.Code().end()}, + }; + } else { + for (int i = 0; i < RegDump::MaxShaderStages; i++) { + if (regs.stage_enable.IsStageEnabled(i)) { + auto stage = regs.ProgramForStage(i); + if (stage->address_lo != 0) { + auto code = stage->Code(); + dump.stages[i] = ShaderDump{ + .user_data = *stage, + .code = std::vector{code.begin(), code.end()}, + }; + } + } + } + } +} diff --git a/src/core/debug_state.h b/src/core/debug_state.h new file mode 100644 index 000000000..cd1c6aa93 --- /dev/null +++ b/src/core/debug_state.h @@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "common/types.h" +#include "video_core/amdgpu/liverpool.h" +#include "video_core/renderer_vulkan/vk_pipeline_cache.h" + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include +using ThreadID = DWORD; +#else +#include +#include +using ThreadID = pthread_t; +#endif + +namespace Core::Devtools { +class Layer; +namespace Widget { +class FrameGraph; +} +} // namespace Core::Devtools + +namespace DebugStateType { + +enum class QueueType { + dcb = 0, + ccb = 1, + acb = 2, +}; + +struct QueueDump { + QueueType type; + u32 submit_num; + u32 num2; // acb: queue_num; else: buffer_in_submit + std::vector data; + uintptr_t base_addr; +}; + +struct ShaderDump { + Vulkan::Liverpool::ShaderProgram user_data{}; + std::vector code{}; +}; + +struct ComputerShaderDump { + Vulkan::Liverpool::ComputeProgram cs_program{}; + std::vector code{}; +}; + +struct RegDump { + bool is_compute{false}; + static constexpr size_t MaxShaderStages = 5; + Vulkan::Liverpool::Regs regs{}; + std::array stages{}; + ComputerShaderDump cs_data{}; +}; + +struct FrameDump { + u32 frame_id; + std::vector queues; + std::unordered_map regs; // address -> reg dump +}; + +class DebugStateImpl { + friend class Core::Devtools::Layer; + friend class Core::Devtools::Widget::FrameGraph; + + std::mutex guest_threads_mutex{}; + std::vector guest_threads{}; + std::atomic_bool is_guest_threads_paused = false; + u64 pause_time{}; + + std::atomic_int32_t flip_frame_count = 0; + std::atomic_int32_t gnm_frame_count = 0; + + s32 gnm_frame_dump_request_count = -1; + std::unordered_map waiting_reg_dumps; + std::unordered_map waiting_reg_dumps_dbg; + bool waiting_submit_pause = false; + bool should_show_frame_dump = false; + + std::shared_mutex frame_dump_list_mutex; + std::vector frame_dump_list{}; + + std::queue debug_message_popup; + +public: + void ShowDebugMessage(std::string message) { + if (message.empty()) { + return; + } + debug_message_popup.push(std::move(message)); + } + + void AddCurrentThreadToGuestList(); + + void RemoveCurrentThreadFromGuestList(); + + void PauseGuestThreads(); + + void ResumeGuestThreads(); + + bool IsGuestThreadsPaused() const { + return is_guest_threads_paused; + } + + void IncFlipFrameNum() { + ++flip_frame_count; + } + + void IncGnmFrameNum() { + ++gnm_frame_count; + --gnm_frame_dump_request_count; + } + + u32 GetFrameNum() const { + return flip_frame_count; + } + + bool DumpingCurrentFrame() const { + return gnm_frame_dump_request_count > 0; + } + + bool DumpingCurrentReg() { + std::shared_lock lock{frame_dump_list_mutex}; + return !waiting_reg_dumps.empty(); + } + + bool ShouldPauseInSubmit() const { + return waiting_submit_pause && gnm_frame_dump_request_count == 0; + } + + void RequestFrameDump(s32 count = 1); + + FrameDump& GetFrameDump() { + return frame_dump_list[frame_dump_list.size() - gnm_frame_dump_request_count]; + } + + void PushQueueDump(QueueDump dump); + + void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, + const AmdGpu::Liverpool::Regs& regs, bool is_compute = false); +}; +} // namespace DebugStateType + +extern DebugStateType::DebugStateImpl& DebugState; diff --git a/src/core/devtools/gcn/gcn_context_regs.cpp b/src/core/devtools/gcn/gcn_context_regs.cpp new file mode 100644 index 000000000..843ba9e65 --- /dev/null +++ b/src/core/devtools/gcn/gcn_context_regs.cpp @@ -0,0 +1,297 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Credits to https://github.com/psucien/tlg-emu-tools/ + +#include "common/types.h" +#include "gcn/si_ci_vi_merged_offset.h" + +using namespace Pal::Gfx6; + +namespace Core::Devtools::Gcn { +const char* GetContextRegName(u32 reg_offset) { + switch (reg_offset) { + case mmDB_SHADER_CONTROL: + return "mmDB_SHADER_CONTROL"; + case mmCB_SHADER_MASK: + return "mmCB_SHADER_MASK"; + case mmPA_CL_CLIP_CNTL: + return "mmPA_CL_CLIP_CNTL"; + case mmVGT_INSTANCE_STEP_RATE_0: + return "mmVGT_INSTANCE_STEP_RATE_0"; + case mmVGT_INSTANCE_STEP_RATE_1: + return "mmVGT_INSTANCE_STEP_RATE_1"; + case mmVGT_INDX_OFFSET: + return "mmVGT_INDX_OFFSET"; + case mmVGT_SHADER_STAGES_EN: + return "mmVGT_SHADER_STAGES_EN"; + case mmVGT_GS_MODE: + return "mmVGT_GS_MODE"; + case mmVGT_STRMOUT_CONFIG: + return "mmVGT_STRMOUT_CONFIG"; + case mmVGT_OUT_DEALLOC_CNTL: + return "mmVGT_OUT_DEALLOC_CNTL"; + case mmVGT_VTX_CNT_EN: + return "mmVGT_VTX_CNT_EN"; + case mmVGT_MAX_VTX_INDX: + return "mmVGT_MAX_VTX_INDX"; + case mmVGT_MULTI_PRIM_IB_RESET_INDX: + return "mmVGT_MULTI_PRIM_IB_RESET_INDX"; + case mmVGT_OUTPUT_PATH_CNTL: + return "mmVGT_OUTPUT_PATH_CNTL"; + case mmVGT_GS_PER_ES: + return "mmVGT_GS_PER_ES"; + case mmVGT_ES_PER_GS: + return "mmVGT_ES_PER_GS"; + case mmVGT_GS_PER_VS: + return "mmVGT_GS_PER_VS"; + case mmCB_COLOR0_BASE: + return "mmCB_COLOR0_BASE"; + case mmCB_COLOR0_INFO: + return "mmCB_COLOR0_INFO"; + case mmCB_COLOR0_CMASK_SLICE: + return "mmCB_COLOR0_CMASK_SLICE"; + case mmCB_COLOR0_CLEAR_WORD0: + return "mmCB_COLOR0_CLEAR_WORD0"; + case mmCB_COLOR0_CLEAR_WORD1: + return "mmCB_COLOR0_CLEAR_WORD1"; + case mmCB_COLOR0_PITCH: + return "mmCB_COLOR0_PITCH"; + case mmCB_COLOR0_SLICE: + return "mmCB_COLOR0_SLICE"; + case mmCB_COLOR0_VIEW: + return "mmCB_COLOR0_VIEW"; + case mmCB_COLOR0_DCC_CONTROL__VI: + return "mmCB_COLOR0_DCC_CONTROL"; + case mmCB_COLOR0_CMASK: + return "mmCB_COLOR0_CMASK"; + case mmCB_COLOR0_FMASK_SLICE: + return "mmCB_COLOR0_FMASK_SLICE"; + case mmCB_COLOR0_FMASK: + return "mmCB_COLOR0_FMASK"; + case mmCB_COLOR0_DCC_BASE__VI: + return "mmCB_COLOR0_DCC_BASE"; + case mmCB_COLOR0_ATTRIB: + return "mmCB_COLOR0_ATTRIB"; + case mmCB_COLOR1_BASE: + return "mmCB_COLOR1_BASE"; + case mmCB_COLOR1_INFO: + return "mmCB_COLOR1_INFO"; + case mmCB_COLOR1_ATTRIB: + return "mmCB_COLOR1_ATTRIB"; + case mmCB_COLOR1_CMASK_SLICE: + return "mmCB_COLOR1_CMASK_SLICE"; + case mmCB_COLOR1_CLEAR_WORD0: + return "mmCB_COLOR1_CLEAR_WORD0"; + case mmCB_COLOR1_CLEAR_WORD1: + return "mmCB_COLOR1_CLEAR_WORD1"; + case mmCB_COLOR1_PITCH: + return "mmCB_COLOR1_PITCH"; + case mmCB_COLOR1_VIEW: + return "mmCB_COLOR1_VIEW"; + case mmCB_COLOR2_INFO: + return "mmCB_COLOR2_INFO"; + case mmCB_COLOR2_ATTRIB: + return "mmCB_COLOR2_ATTRIB"; + case mmCB_COLOR2_CMASK_SLICE: + return "mmCB_COLOR2_CMASK_SLICE"; + case mmCB_COLOR2_CLEAR_WORD0: + return "mmCB_COLOR2_CLEAR_WORD0"; + case mmCB_COLOR2_CLEAR_WORD1: + return "mmCB_COLOR2_CLEAR_WORD1"; + case mmCB_COLOR2_PITCH: + return "mmCB_COLOR2_PITCH"; + case mmCB_COLOR2_VIEW: + return "mmCB_COLOR2_VIEW"; + case mmCB_COLOR3_INFO: + return "mmCB_COLOR3_INFO"; + case mmCB_COLOR3_CMASK_SLICE: + return "mmCB_COLOR3_CMASK_SLICE"; + case mmCB_COLOR4_INFO: + return "mmCB_COLOR4_INFO"; + case mmCB_COLOR5_INFO: + return "mmCB_COLOR5_INFO"; + case mmCB_COLOR6_INFO: + return "mmCB_COLOR6_INFO"; + case mmCB_COLOR7_INFO: + return "mmCB_COLOR7_INFO"; + case mmDB_SRESULTS_COMPARE_STATE0: + return "mmDB_SRESULTS_COMPARE_STATE0"; + case mmDB_SRESULTS_COMPARE_STATE1: + return "mmDB_SRESULTS_COMPARE_STATE1"; + case mmDB_DEPTH_CONTROL: + return "mmDB_DEPTH_CONTROL"; + case mmDB_EQAA: + return "mmDB_EQAA"; + case mmPA_SU_POINT_SIZE: + return "mmPA_SU_POINT_SIZE"; + case mmPA_SU_POINT_MINMAX: + return "mmPA_SU_POINT_MINMAX"; + case mmPA_SU_SC_MODE_CNTL: + return "mmPA_SU_SC_MODE_CNTL"; + case mmPA_SU_POLY_OFFSET_DB_FMT_CNTL: + return "mmPA_SU_POLY_OFFSET_DB_FMT_CNTL"; + case mmPA_SC_CLIPRECT_RULE: + return "mmPA_SC_CLIPRECT_RULE"; + case mmPA_SC_MODE_CNTL_0: + return "mmPA_SC_MODE_CNTL_0"; + case mmPA_SC_MODE_CNTL_1: + return "mmPA_SC_MODE_CNTL_1"; + case mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0: + return "mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0"; + case mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0: + return "mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0"; + case mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0: + return "mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0"; + case mmPA_SC_AA_MASK_X0Y0_X1Y0: + return "mmPA_SC_AA_MASK_X0Y0_X1Y0"; + case mmPA_SC_AA_MASK_X0Y1_X1Y1: + return "mmPA_SC_AA_MASK_X0Y1_X1Y1"; + case mmPA_SC_CENTROID_PRIORITY_0: + return "mmPA_SC_CENTROID_PRIORITY_0"; + case mmPA_SC_CENTROID_PRIORITY_1: + return "mmPA_SC_CENTROID_PRIORITY_1"; + case mmPA_SC_AA_CONFIG: + return "mmPA_SC_AA_CONFIG"; + case mmDB_RENDER_CONTROL: + return "mmDB_RENDER_CONTROL"; + case mmDB_STENCIL_CONTROL: + return "mmDB_STENCIL_CONTROL"; + case mmDB_STENCILREFMASK: + return "mmDB_STENCILREFMASK"; + case mmDB_STENCILREFMASK_BF: + return "mmDB_STENCILREFMASK_BF"; + case mmDB_STENCIL_CLEAR: + return "mmDB_STENCIL_CLEAR"; + case mmDB_DEPTH_CLEAR: + return "mmDB_DEPTH_CLEAR"; + case mmCB_TARGET_MASK: + return "mmCB_TARGET_MASK"; + case mmDB_Z_INFO: + return "mmDB_Z_INFO"; + case mmDB_STENCIL_INFO: + return "mmDB_STENCIL_INFO"; + case mmDB_Z_READ_BASE: + return "mmDB_Z_READ_BASE"; + case mmDB_STENCIL_READ_BASE: + return "mmDB_STENCIL_READ_BASE"; + case mmDB_Z_WRITE_BASE: + return "mmDB_Z_WRITE_BASE"; + case mmDB_STENCIL_WRITE_BASE: + return "mmDB_STENCIL_WRITE_BASE"; + case mmDB_DEPTH_INFO: + return "mmDB_DEPTH_INFO"; + case mmDB_DEPTH_VIEW: + return "mmDB_DEPTH_VIEW"; + case mmDB_DEPTH_SLICE: + return "mmDB_DEPTH_SLICE"; + case mmDB_DEPTH_SIZE: + return "mmDB_DEPTH_SIZE"; + case mmTA_BC_BASE_ADDR: + return "mmTA_BC_BASE_ADDR"; + case mmCB_BLEND_RED: + return "mmCB_BLEND_RED"; + case mmCB_BLEND_GREEN: + return "mmCB_BLEND_GREEN"; + case mmCB_BLEND_BLUE: + return "mmCB_BLEND_BLUE"; + case mmDB_ALPHA_TO_MASK: + return "mmDB_ALPHA_TO_MASK"; + case mmCB_BLEND0_CONTROL: + return "mmCB_BLEND0_CONTROL"; + case mmCB_BLEND1_CONTROL: + return "mmCB_BLEND1_CONTROL"; + case mmCB_BLEND2_CONTROL: + return "mmCB_BLEND2_CONTROL"; + case mmCB_BLEND3_CONTROL: + return "mmCB_BLEND3_CONTROL"; + case mmCB_BLEND4_CONTROL: + return "mmCB_BLEND4_CONTROL"; + case mmCB_BLEND5_CONTROL: + return "mmCB_BLEND5_CONTROL"; + case mmCB_BLEND6_CONTROL: + return "mmCB_BLEND6_CONTROL"; + case mmCB_BLEND7_CONTROL: + return "mmCB_BLEND7_CONTROL"; + case mmDB_HTILE_DATA_BASE: + return "mmDB_HTILE_DATA_BASE"; + case mmDB_HTILE_SURFACE: + return "mmDB_HTILE_SURFACE"; + case mmPA_SU_LINE_CNTL: + return "mmPA_SU_LINE_CNTL"; + case mmPA_SC_VPORT_ZMIN_0: + return "mmPA_SC_VPORT_ZMIN_0"; + case mmPA_SC_VPORT_ZMAX_0: + return "mmPA_SC_VPORT_ZMAX_0"; + case mmPA_SC_VPORT_SCISSOR_0_TL: + return "mmPA_SC_VPORT_SCISSOR_0_TL"; + case mmPA_SC_VPORT_SCISSOR_0_BR: + return "mmPA_SC_VPORT_SCISSOR_0_BR"; + case mmPA_SC_GENERIC_SCISSOR_TL: + return "mmPA_SC_GENERIC_SCISSOR_TL"; + case mmPA_SC_GENERIC_SCISSOR_BR: + return "mmPA_SC_GENERIC_SCISSOR_BR"; + case mmPA_CL_VPORT_XSCALE: + return "mmPA_CL_VPORT_XSCALE"; + case mmPA_CL_VPORT_YSCALE: + return "mmPA_CL_VPORT_YSCALE"; + case mmPA_CL_VPORT_ZSCALE: + return "mmPA_CL_VPORT_ZSCALE"; + case mmPA_CL_VPORT_XOFFSET: + return "mmPA_CL_VPORT_XOFFSET"; + case mmPA_CL_VPORT_YOFFSET: + return "mmPA_CL_VPORT_YOFFSET"; + case mmPA_CL_VPORT_ZOFFSET: + return "mmPA_CL_VPORT_ZOFFSET"; + case mmPA_CL_VTE_CNTL: + return "mmPA_CL_VTE_CNTL"; + case mmPA_SC_SCREEN_SCISSOR_TL: + return "mmPA_SC_SCREEN_SCISSOR_TL"; + case mmPA_SC_SCREEN_SCISSOR_BR: + return "mmPA_SC_SCREEN_SCISSOR_BR"; + case mmPA_SU_HARDWARE_SCREEN_OFFSET: + return "mmPA_SU_HARDWARE_SCREEN_OFFSET"; + case mmPA_SU_VTX_CNTL: + return "mmPA_SU_VTX_CNTL"; + case mmPA_CL_GB_VERT_CLIP_ADJ: + return "mmPA_CL_GB_VERT_CLIP_ADJ"; + case mmPA_CL_GB_HORZ_CLIP_ADJ: + return "mmPA_CL_GB_HORZ_CLIP_ADJ"; + case mmPA_CL_GB_VERT_DISC_ADJ: + return "mmPA_CL_GB_VERT_DISC_ADJ"; + case mmPA_CL_GB_HORZ_DISC_ADJ: + return "mmPA_CL_GB_HORZ_DISC_ADJ"; + case mmCB_COLOR_CONTROL: + return "mmCB_COLOR_CONTROL"; + case mmSPI_SHADER_Z_FORMAT: + return "mmSPI_SHADER_Z_FORMAT"; + case mmSPI_SHADER_COL_FORMAT: + return "mmSPI_SHADER_COL_FORMAT"; + case mmPA_CL_VS_OUT_CNTL: + return "mmPA_CL_VS_OUT_CNTL"; + case mmSPI_VS_OUT_CONFIG: + return "mmSPI_VS_OUT_CONFIG"; + case mmSPI_SHADER_POS_FORMAT: + return "mmSPI_SHADER_POS_FORMAT"; + case mmSPI_PS_INPUT_ENA: + return "mmSPI_PS_INPUT_ENA"; + case mmSPI_PS_INPUT_ADDR: + return "mmSPI_PS_INPUT_ADDR"; + case mmSPI_PS_IN_CONTROL: + return "mmSPI_PS_IN_CONTROL"; + case mmSPI_BARYC_CNTL: + return "mmSPI_BARYC_CNTL"; + case mmSPI_PS_INPUT_CNTL_0: + return "mmSPI_PS_INPUT_CNTL_0"; + case mmSPI_PS_INPUT_CNTL_1: + return "mmSPI_PS_INPUT_CNTL_1"; + case mmSPI_PS_INPUT_CNTL_2: + return "mmSPI_PS_INPUT_CNTL_2"; + case mmSPI_PS_INPUT_CNTL_3: + return "mmSPI_PS_INPUT_CNTL_3"; + default: + break; + } + return ""; +} +} // namespace Core::Devtools::Gcn \ No newline at end of file diff --git a/src/core/devtools/gcn/gcn_op_names.cpp b/src/core/devtools/gcn/gcn_op_names.cpp new file mode 100644 index 000000000..6684b660e --- /dev/null +++ b/src/core/devtools/gcn/gcn_op_names.cpp @@ -0,0 +1,118 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Credits to https://github.com/psucien/tlg-emu-tools/ + +#include "common/types.h" +#include "gcn/si_ci_vi_merged_pm4_it_opcodes.h" + +namespace Core::Devtools::Gcn { +const char* GetOpCodeName(u32 op) { + switch (op) { + case IT_NOP: + return "IT_NOP"; + case IT_SET_BASE: + return "IT_SET_BASE"; + case IT_INDEX_BUFFER_SIZE: + return "IT_INDEX_BUFFER_SIZE"; + case IT_SET_PREDICATION: + return "IT_SET_PREDICATION"; + case IT_COND_EXEC: + return "IT_COND_EXEC"; + case IT_INDEX_BASE: + return "IT_INDEX_BASE"; + case IT_INDEX_TYPE: + return "IT_INDEX_TYPE"; + case IT_NUM_INSTANCES: + return "IT_NUM_INSTANCES"; + case IT_STRMOUT_BUFFER_UPDATE: + return "IT_STRMOUT_BUFFER_UPDATE"; + case IT_WRITE_DATA: + return "IT_WRITE_DATA"; + case IT_MEM_SEMAPHORE: + return "IT_MEM_SEMAPHORE"; + case IT_WAIT_REG_MEM: + return "IT_WAIT_REG_MEM"; + case IT_INDIRECT_BUFFER: + return "IT_INDIRECT_BUFFER"; + case IT_PFP_SYNC_ME: + return "IT_PFP_SYNC_ME"; + case IT_EVENT_WRITE: + return "IT_EVENT_WRITE"; + case IT_EVENT_WRITE_EOP: + return "IT_EVENT_WRITE_EOP"; + case IT_EVENT_WRITE_EOS: + return "IT_EVENT_WRITE_EOS"; + case IT_DMA_DATA__CI__VI: + return "IT_DMA_DATA"; + case IT_ACQUIRE_MEM__CI__VI: + return "IT_ACQUIRE_MEM"; + case IT_REWIND__CI__VI: + return "IT_REWIND"; + case IT_SET_CONFIG_REG: + return "IT_SET_CONFIG_REG"; + case IT_SET_CONTEXT_REG: + return "IT_SET_CONTEXT_REG"; + case IT_SET_SH_REG: + return "IT_SET_SH_REG"; + case IT_SET_UCONFIG_REG__CI__VI: + return "IT_SET_UCONFIG_REG"; + case IT_INCREMENT_DE_COUNTER: + return "IT_INCREMENT_DE_COUNTER"; + case IT_WAIT_ON_CE_COUNTER: + return "IT_WAIT_ON_CE_COUNTER"; + case IT_DISPATCH_DIRECT: + return "IT_DISPATCH_DIRECT"; + case IT_DISPATCH_INDIRECT: + return "IT_DISPATCH_INDIRECT"; + case IT_OCCLUSION_QUERY: + return "IT_OCCLUSION_QUERY"; + case IT_REG_RMW: + return "IT_REG_RMW"; + case IT_PRED_EXEC: + return "IT_PRED_EXEC"; + case IT_DRAW_INDIRECT: + return "IT_DRAW_INDIRECT"; + case IT_DRAW_INDEX_INDIRECT: + return "IT_DRAW_INDEX_INDIRECT"; + case IT_DRAW_INDEX_2: + return "IT_DRAW_INDEX_2"; + case IT_DRAW_INDEX_OFFSET_2: + return "IT_DRAW_INDEX_OFFSET_2"; + case IT_CONTEXT_CONTROL: + return "IT_CONTEXT_CONTROL"; + case IT_DRAW_INDIRECT_MULTI: + return "IT_DRAW_INDIRECT_MULTI"; + case IT_DRAW_INDEX_AUTO: + return "IT_DRAW_INDEX_AUTO"; + case IT_DRAW_INDEX_MULTI_AUTO: + return "IT_DRAW_INDEX_MULTI_AUTO"; + case IT_COPY_DATA: + return "IT_COPY_DATA"; + case IT_CP_DMA: + return "IT_CP_DMA"; + case IT_SURFACE_SYNC: + return "IT_SURFACE_SYNC"; + case IT_COND_WRITE: + return "IT_COND_WRITE"; + case IT_RELEASE_MEM__CI__VI: + return "IT_RELEASE_MEM"; + case IT_WRITE_CONST_RAM: + return "IT_WRITE_CONST_RAM"; // used in CCB + case IT_WAIT_ON_DE_COUNTER_DIFF: + return "IT_WAIT_ON_DE_COUNTER_DIFF"; // used in CCB + case IT_DUMP_CONST_RAM: + return "IT_DUMP_CONST_RAM"; // used in CCB + case IT_INCREMENT_CE_COUNTER: + return "IT_INCREMENT_CE_COUNTER"; // used in CCB + case IT_CLEAR_STATE: + return "IT_CLEAR_STATE"; + case 0xFF: + return ""; + default: + break; + } + + return ""; +} +} // namespace Core::Devtools::Gcn \ No newline at end of file diff --git a/src/core/devtools/gcn/gcn_shader_regs.cpp b/src/core/devtools/gcn/gcn_shader_regs.cpp new file mode 100644 index 000000000..16778dd07 --- /dev/null +++ b/src/core/devtools/gcn/gcn_shader_regs.cpp @@ -0,0 +1,171 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Credits to https://github.com/psucien/tlg-emu-tools/ + +#include "common/types.h" +#include "gcn/si_ci_vi_merged_offset.h" + +using namespace Pal::Gfx6; + +namespace Core::Devtools::Gcn { +const char* GetShaderRegName(u32 reg_offset) { + switch (reg_offset) { + case mmSPI_SHADER_PGM_LO_VS: + return "mmSPI_SHADER_PGM_LO_VS"; + case mmSPI_SHADER_PGM_HI_VS: + return "mmSPI_SHADER_PGM_HI_VS"; + case mmSPI_SHADER_PGM_LO_PS: + return "mmSPI_SHADER_PGM_LO_PS"; + case mmSPI_SHADER_PGM_HI_PS: + return "mmSPI_SHADER_PGM_HI_PS"; + case mmSPI_SHADER_PGM_RSRC1_VS: + return "mmSPI_SHADER_PGM_RSRC1_VS"; + case mmSPI_SHADER_PGM_RSRC2_VS: + return "mmSPI_SHADER_PGM_RSRC2_VS"; + case mmSPI_SHADER_PGM_RSRC3_VS__CI__VI: + return "mmSPI_SHADER_PGM_RSRC3_VS__CI__VI"; + case mmSPI_SHADER_PGM_RSRC1_PS: + return "mmSPI_SHADER_PGM_RSRC1_PS"; + case mmSPI_SHADER_PGM_RSRC2_PS: + return "mmSPI_SHADER_PGM_RSRC2_PS"; + case mmSPI_SHADER_PGM_RSRC3_PS__CI__VI: + return "mmSPI_SHADER_PGM_RSRC3_PS__CI__VI"; + case mmSPI_SHADER_USER_DATA_PS_0: + return "mmSPI_SHADER_USER_DATA_PS_0"; + case mmSPI_SHADER_USER_DATA_PS_1: + return "mmSPI_SHADER_USER_DATA_PS_1"; + case mmSPI_SHADER_USER_DATA_PS_2: + return "mmSPI_SHADER_USER_DATA_PS_2"; + case mmSPI_SHADER_USER_DATA_PS_3: + return "mmSPI_SHADER_USER_DATA_PS_3"; + case mmSPI_SHADER_USER_DATA_PS_4: + return "mmSPI_SHADER_USER_DATA_PS_4"; + case mmSPI_SHADER_USER_DATA_PS_5: + return "mmSPI_SHADER_USER_DATA_PS_5"; + case mmSPI_SHADER_USER_DATA_PS_6: + return "mmSPI_SHADER_USER_DATA_PS_6"; + case mmSPI_SHADER_USER_DATA_PS_7: + return "mmSPI_SHADER_USER_DATA_PS_7"; + case mmSPI_SHADER_USER_DATA_PS_8: + return "mmSPI_SHADER_USER_DATA_PS_8"; + case mmSPI_SHADER_USER_DATA_PS_9: + return "mmSPI_SHADER_USER_DATA_PS_9"; + case mmSPI_SHADER_USER_DATA_PS_10: + return "mmSPI_SHADER_USER_DATA_PS_10"; + case mmSPI_SHADER_USER_DATA_PS_11: + return "mmSPI_SHADER_USER_DATA_PS_11"; + case mmSPI_SHADER_USER_DATA_PS_12: + return "mmSPI_SHADER_USER_DATA_PS_12"; + case mmSPI_SHADER_USER_DATA_PS_13: + return "mmSPI_SHADER_USER_DATA_PS_13"; + case mmSPI_SHADER_USER_DATA_PS_14: + return "mmSPI_SHADER_USER_DATA_PS_14"; + case mmSPI_SHADER_USER_DATA_PS_15: + return "mmSPI_SHADER_USER_DATA_PS_15"; + case mmCOMPUTE_TMPRING_SIZE: + return "mmCOMPUTE_TMPRING_SIZE"; + case mmCOMPUTE_PGM_LO: + return "mmCOMPUTE_PGM_LO"; + case mmCOMPUTE_PGM_HI: + return "mmCOMPUTE_PGM_HI"; + case mmCOMPUTE_PGM_RSRC1: + return "mmCOMPUTE_PGM_RSRC1"; + case mmCOMPUTE_PGM_RSRC2: + return "mmCOMPUTE_PGM_RSRC2"; + case mmCOMPUTE_USER_DATA_0: + return "mmCOMPUTE_USER_DATA_0"; + case mmCOMPUTE_USER_DATA_1: + return "mmCOMPUTE_USER_DATA_1"; + case mmCOMPUTE_USER_DATA_2: + return "mmCOMPUTE_USER_DATA_2"; + case mmCOMPUTE_USER_DATA_3: + return "mmCOMPUTE_USER_DATA_3"; + case mmCOMPUTE_USER_DATA_4: + return "mmCOMPUTE_USER_DATA_4"; + case mmCOMPUTE_USER_DATA_5: + return "mmCOMPUTE_USER_DATA_5"; + case mmCOMPUTE_USER_DATA_6: + return "mmCOMPUTE_USER_DATA_6"; + case mmCOMPUTE_USER_DATA_7: + return "mmCOMPUTE_USER_DATA_7"; + case mmCOMPUTE_USER_DATA_8: + return "mmCOMPUTE_USER_DATA_8"; + case mmCOMPUTE_USER_DATA_9: + return "mmCOMPUTE_USER_DATA_9"; + case mmCOMPUTE_USER_DATA_10: + return "mmCOMPUTE_USER_DATA_10"; + case mmCOMPUTE_USER_DATA_11: + return "mmCOMPUTE_USER_DATA_11"; + case mmCOMPUTE_USER_DATA_12: + return "mmCOMPUTE_USER_DATA_12"; + case mmCOMPUTE_USER_DATA_13: + return "mmCOMPUTE_USER_DATA_13"; + case mmCOMPUTE_USER_DATA_14: + return "mmCOMPUTE_USER_DATA_14"; + case mmCOMPUTE_USER_DATA_15: + return "mmCOMPUTE_USER_DATA_15"; + case mmCOMPUTE_NUM_THREAD_X: + return "mmCOMPUTE_NUM_THREAD_X"; + case mmCOMPUTE_NUM_THREAD_Y: + return "mmCOMPUTE_NUM_THREAD_Y"; + case mmCOMPUTE_NUM_THREAD_Z: + return "mmCOMPUTE_NUM_THREAD_Z"; + case mmCOMPUTE_STATIC_THREAD_MGMT_SE0: + return "mmCOMPUTE_STATIC_THREAD_MGMT_SE0"; + case mmCOMPUTE_STATIC_THREAD_MGMT_SE1: + return "mmCOMPUTE_STATIC_THREAD_MGMT_SE1"; + case mmCOMPUTE_RESOURCE_LIMITS: + return "mmCOMPUTE_RESOURCE_LIMITS"; + case mmSPI_SHADER_USER_DATA_VS_0: + return "mmSPI_SHADER_USER_DATA_VS_0"; + case mmSPI_SHADER_USER_DATA_VS_1: + return "mmSPI_SHADER_USER_DATA_VS_1"; + case mmSPI_SHADER_USER_DATA_VS_2: + return "mmSPI_SHADER_USER_DATA_VS_2"; + case mmSPI_SHADER_USER_DATA_VS_3: + return "mmSPI_SHADER_USER_DATA_VS_3"; + case mmSPI_SHADER_USER_DATA_VS_4: + return "mmSPI_SHADER_USER_DATA_VS_4"; + case mmSPI_SHADER_USER_DATA_VS_5: + return "mmSPI_SHADER_USER_DATA_VS_5"; + case mmSPI_SHADER_USER_DATA_VS_6: + return "mmSPI_SHADER_USER_DATA_VS_6"; + case mmSPI_SHADER_USER_DATA_VS_7: + return "mmSPI_SHADER_USER_DATA_VS_7"; + case mmSPI_SHADER_USER_DATA_VS_8: + return "mmSPI_SHADER_USER_DATA_VS_8"; + case mmSPI_SHADER_USER_DATA_VS_9: + return "mmSPI_SHADER_USER_DATA_VS_9"; + case mmSPI_SHADER_USER_DATA_VS_10: + return "mmSPI_SHADER_USER_DATA_VS_10"; + case mmSPI_SHADER_USER_DATA_VS_11: + return "mmSPI_SHADER_USER_DATA_VS_11"; + case mmSPI_SHADER_USER_DATA_VS_12: + return "mmSPI_SHADER_USER_DATA_VS_12"; + case mmSPI_SHADER_USER_DATA_VS_13: + return "mmSPI_SHADER_USER_DATA_VS_13"; + case mmSPI_SHADER_USER_DATA_VS_14: + return "mmSPI_SHADER_USER_DATA_VS_14"; + case mmSPI_SHADER_USER_DATA_VS_15: + return "mmSPI_SHADER_USER_DATA_VS_15"; + case mmSPI_SHADER_USER_DATA_HS_0: + return "mmSPI_SHADER_USER_DATA_HS_0"; + case mmSPI_SHADER_USER_DATA_HS_1: + return "mmSPI_SHADER_USER_DATA_HS_1"; + case mmSPI_SHADER_USER_DATA_HS_9: + return "mmSPI_SHADER_USER_DATA_HS_9"; + case mmSPI_SHADER_PGM_RSRC3_GS__CI__VI: + return "mmSPI_SHADER_PGM_RSRC3_GS__CI__VI"; + case mmSPI_SHADER_PGM_RSRC3_ES__CI__VI: + return "mmSPI_SHADER_PGM_RSRC3_ES__CI__VI"; + case mmSPI_SHADER_PGM_RSRC3_LS__CI__VI: + return "mmSPI_SHADER_PGM_RSRC3_LS__CI__VI"; + case mmSPI_SHADER_LATE_ALLOC_VS__CI__VI: + return "mmSPI_SHADER_LATE_ALLOC_VS__CI__VI"; + default: + break; + } + return ""; +} +} // namespace Core::Devtools::Gcn \ No newline at end of file diff --git a/src/core/devtools/help.txt b/src/core/devtools/help.txt new file mode 100644 index 000000000..9670c5cea --- /dev/null +++ b/src/core/devtools/help.txt @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later +R"( +* If you hold shift, you can move the window without docking it. +* You don't need to close every window you open. When a parent window is closed, all its children will be closed too. +* If you want to inspect or compare more than 1 frame dump without undocking, there's a option to keep showing opened popups even when in hide/minimize the frame dump window. +* To use the disassembly viewer, you need to set up a cli to use a external disassembler and use "{src}" as a placeholder for the source code file, e.g. dis.exe --some-opt "{src}" +)" \ No newline at end of file diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp new file mode 100644 index 000000000..38b17c863 --- /dev/null +++ b/src/core/devtools/layer.cpp @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "common/config.h" +#include "common/singleton.h" +#include "common/types.h" +#include "core/debug_state.h" +#include "imgui/imgui_std.h" +#include "imgui_internal.h" +#include "layer.h" +#include "options.h" +#include "widget/frame_dump.h" +#include "widget/frame_graph.h" + +using namespace ImGui; +using namespace Core::Devtools; +using L = Core::Devtools::Layer; + +static bool show_simple_fps = false; + +static float fps_scale = 1.0f; +static bool show_advanced_debug = false; +static int dump_frame_count = 1; + +static Widget::FrameGraph frame_graph; +static std::vector frame_viewers; + +static float debug_popup_timing = 3.0f; + +static bool just_opened_options = false; + +// clang-format off +static std::string help_text = +#include "help.txt" + ; +// clang-format on + +void L::DrawMenuBar() { + const auto& ctx = *GImGui; + const auto& io = ctx.IO; + + auto isSystemPaused = DebugState.IsGuestThreadsPaused(); + + bool open_popup_options = false; + bool open_popup_help = false; + + if (BeginMainMenuBar()) { + if (BeginMenu("Options")) { + if (MenuItemEx("Emulator Paused", nullptr, nullptr, isSystemPaused)) { + if (isSystemPaused) { + DebugState.ResumeGuestThreads(); + } else { + DebugState.PauseGuestThreads(); + } + } + ImGui::EndMenu(); + } + if (BeginMenu("GPU Tools")) { + MenuItem("Show frame info", nullptr, &frame_graph.is_open); + if (BeginMenu("Dump frames")) { + SliderInt("Count", &dump_frame_count, 1, 5); + if (MenuItem("Dump", "Ctrl+Alt+F9", nullptr, !DebugState.DumpingCurrentFrame())) { + DebugState.RequestFrameDump(dump_frame_count); + } + ImGui::EndMenu(); + } + open_popup_options = MenuItem("Options"); + open_popup_help = MenuItem("Help & Tips"); + ImGui::EndMenu(); + } + EndMainMenuBar(); + } + + if (IsKeyPressed(ImGuiKey_F9, false)) { + if (io.KeyCtrl && io.KeyAlt) { + if (!DebugState.ShouldPauseInSubmit()) { + DebugState.RequestFrameDump(dump_frame_count); + } + } + if (!io.KeyCtrl && !io.KeyAlt) { + if (isSystemPaused) { + DebugState.ResumeGuestThreads(); + } else { + DebugState.PauseGuestThreads(); + } + } + } + + if (open_popup_options) { + OpenPopup("GPU Tools Options"); + just_opened_options = true; + } + if (open_popup_help) { + OpenPopup("HelpTips"); + } +} + +void L::DrawAdvanced() { + DrawMenuBar(); + + const auto& ctx = *GImGui; + const auto& io = ctx.IO; + + auto isSystemPaused = DebugState.IsGuestThreadsPaused(); + + frame_graph.Draw(); + + if (isSystemPaused) { + GetForegroundDrawList(GetMainViewport()) + ->AddText({10.0f, io.DisplaySize.y - 40.0f}, IM_COL32_WHITE, "Emulator paused"); + } + + if (DebugState.should_show_frame_dump && DebugState.waiting_reg_dumps.empty()) { + DebugState.should_show_frame_dump = false; + std::unique_lock lock{DebugState.frame_dump_list_mutex}; + while (!DebugState.frame_dump_list.empty()) { + const auto& frame_dump = DebugState.frame_dump_list.back(); + frame_viewers.emplace_back(frame_dump); + DebugState.frame_dump_list.pop_back(); + } + static bool first_time = true; + if (first_time) { + first_time = false; + DebugState.ShowDebugMessage("Tip: You can shift+click any\n" + "popup to open a new window"); + } + } + + for (auto it = frame_viewers.begin(); it != frame_viewers.end();) { + if (it->is_open) { + it->Draw(); + ++it; + } else { + it = frame_viewers.erase(it); + } + } + + if (!DebugState.debug_message_popup.empty()) { + if (debug_popup_timing > 0.0f) { + debug_popup_timing -= io.DeltaTime; + if (Begin("##devtools_msg", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove)) { + BringWindowToDisplayFront(GetCurrentWindow()); + const auto display_size = io.DisplaySize; + const auto& msg = DebugState.debug_message_popup.front(); + const auto padding = GetStyle().WindowPadding; + const auto txt_size = CalcTextSize(&msg.front(), &msg.back() + 1, false, 250.0f); + SetWindowPos({display_size.x - padding.x * 2.0f - txt_size.x, 50.0f}); + SetWindowSize({txt_size.x + padding.x * 2.0f, txt_size.y + padding.y * 2.0f}); + PushTextWrapPos(250.0f); + TextEx(&msg.front(), &msg.back() + 1); + PopTextWrapPos(); + } + End(); + } else { + DebugState.debug_message_popup.pop(); + debug_popup_timing = 3.0f; + } + } + + bool close_popup_options = true; + if (BeginPopupModal("GPU Tools Options", &close_popup_options, + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) { + static char disassembly_cli[512]; + static bool frame_dump_render_on_collapse; + + if (just_opened_options) { + just_opened_options = false; + auto s = Options.disassembly_cli.copy(disassembly_cli, sizeof(disassembly_cli) - 1); + disassembly_cli[s] = '\0'; + frame_dump_render_on_collapse = Options.frame_dump_render_on_collapse; + } + + InputText("Shader disassembler: ", disassembly_cli, sizeof(disassembly_cli)); + if (IsItemHovered()) { + SetTooltip(R"(Command to disassemble shaders. Example "dis.exe" --raw "{src}")"); + } + Checkbox("Show frame dump popups even when collapsed", &frame_dump_render_on_collapse); + if (IsItemHovered()) { + SetTooltip("When a frame dump is collapsed, it will keep\n" + "showing all opened popups related to it"); + } + + if (Button("Save")) { + Options.disassembly_cli = disassembly_cli; + Options.frame_dump_render_on_collapse = frame_dump_render_on_collapse; + SaveIniSettingsToDisk(io.IniFilename); + CloseCurrentPopup(); + } + EndPopup(); + } + + if (BeginPopup("HelpTips", ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove)) { + CentralizeWindow(); + + PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{10.0f}); + PushTextWrapPos(600.0f); + + const char* begin = help_text.data(); + TextUnformatted(begin, begin + help_text.size()); + + PopTextWrapPos(); + PopStyleVar(); + + EndPopup(); + } +} + +void L::DrawSimple() { + const auto io = GetIO(); + Text("Frame time: %.3f ms (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); +} + +static void LoadSettings(const char* line) { + int i; + float f; + if (sscanf(line, "fps_scale=%f", &f) == 1) { + fps_scale = f; + return; + } + if (sscanf(line, "show_advanced_debug=%d", &i) == 1) { + show_advanced_debug = i != 0; + return; + } + if (sscanf(line, "show_frame_graph=%d", &i) == 1) { + frame_graph.is_open = i != 0; + return; + } + if (sscanf(line, "dump_frame_count=%d", &i) == 1) { + dump_frame_count = i; + return; + } +} + +void L::SetupSettings() { + frame_graph.is_open = true; + + using SettingLoader = void (*)(const char*); + + ImGuiSettingsHandler handler{}; + handler.TypeName = "DevtoolsLayer"; + handler.TypeHash = ImHashStr(handler.TypeName); + handler.ReadOpenFn = [](ImGuiContext*, ImGuiSettingsHandler*, const char* name) { + if (std::string_view("Data") == name) { + static_assert(std::is_same_v); + return (void*)&LoadSettings; + } + if (std::string_view("CmdList") == name) { + static_assert( + std::is_same_v); + return (void*)&Widget::CmdListViewer::LoadConfig; + } + if (std::string_view("Options") == name) { + static_assert(std::is_same_v); + return (void*)&LoadOptionsConfig; + } + return (void*)nullptr; + }; + handler.ReadLineFn = [](ImGuiContext*, ImGuiSettingsHandler*, void* handle, const char* line) { + if (handle != nullptr) { + reinterpret_cast(handle)(line); + } + }; + handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) { + buf->appendf("[%s][Data]\n", handler->TypeName); + buf->appendf("fps_scale=%f\n", fps_scale); + buf->appendf("show_advanced_debug=%d\n", show_advanced_debug); + buf->appendf("show_frame_graph=%d\n", frame_graph.is_open); + buf->appendf("dump_frame_count=%d\n", dump_frame_count); + buf->append("\n"); + buf->appendf("[%s][CmdList]\n", handler->TypeName); + Widget::CmdListViewer::SerializeConfig(buf); + buf->append("\n"); + buf->appendf("[%s][Options]\n", handler->TypeName); + SerializeOptionsConfig(buf); + buf->append("\n"); + }; + AddSettingsHandler(&handler); + + const ImGuiID dock_id = ImHashStr("FrameDumpDock"); + DockBuilderAddNode(dock_id, 0); + DockBuilderSetNodePos(dock_id, ImVec2{450.0, 150.0}); + DockBuilderSetNodeSize(dock_id, ImVec2{400.0, 500.0}); + DockBuilderFinish(dock_id); +} + +void L::Draw() { + const auto io = GetIO(); + PushID("DevtoolsLayer"); + + if (!DebugState.IsGuestThreadsPaused()) { + const auto fn = DebugState.flip_frame_count.load(); + frame_graph.AddFrame(fn, io.DeltaTime); + } + + if (IsKeyPressed(ImGuiKey_F10, false)) { + if (io.KeyCtrl) { + show_advanced_debug = !show_advanced_debug; + } else { + show_simple_fps = !show_simple_fps; + } + } + + if (show_simple_fps) { + if (Begin("Video Info", nullptr, + ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking)) { + SetWindowPos("Video Info", {999999.0f, 0.0f}, ImGuiCond_FirstUseEver); + if (BeginPopupContextWindow()) { +#define M(label, value) \ + if (MenuItem(label, nullptr, fps_scale == value)) \ + fps_scale = value + M("0.5x", 0.5f); + M("1.0x", 1.0f); + M("1.5x", 1.5f); + M("2.0x", 2.0f); + M("2.5x", 2.5f); + EndPopup(); +#undef M + } + KeepWindowInside(); + SetWindowFontScale(fps_scale); + DrawSimple(); + } + End(); + } + + if (show_advanced_debug) { + PushFont(io.Fonts->Fonts[IMGUI_FONT_MONO]); + PushID("DevtoolsLayer"); + DrawAdvanced(); + PopID(); + PopFont(); + } + + PopID(); +} diff --git a/src/core/devtools/layer.h b/src/core/devtools/layer.h new file mode 100644 index 000000000..5bb53fbdb --- /dev/null +++ b/src/core/devtools/layer.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "imgui/imgui_layer.h" + +namespace Core::Devtools { + +class Layer final : public ImGui::Layer { + + static void DrawMenuBar(); + + static void DrawAdvanced(); + + static void DrawSimple(); + +public: + static void SetupSettings(); + + void Draw() override; +}; + +} // namespace Core::Devtools diff --git a/src/core/devtools/options.cpp b/src/core/devtools/options.cpp new file mode 100644 index 000000000..1b49da76b --- /dev/null +++ b/src/core/devtools/options.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "options.h" + +namespace Core::Devtools { + +TOptions Options; + +void LoadOptionsConfig(const char* line) { + char str[512]; + int i; + if (sscanf(line, "disassembly_cli=%511[^\n]", str) == 1) { + Options.disassembly_cli = str; + return; + } + if (sscanf(line, "frame_dump_render_on_collapse=%d", &i) == 1) { + Options.frame_dump_render_on_collapse = i != 0; + return; + } +} + +void SerializeOptionsConfig(ImGuiTextBuffer* buf) { + buf->appendf("disassembly_cli=%s\n", Options.disassembly_cli.c_str()); + buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse); +} + +} // namespace Core::Devtools diff --git a/src/core/devtools/options.h b/src/core/devtools/options.h new file mode 100644 index 000000000..c3a8aaf31 --- /dev/null +++ b/src/core/devtools/options.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +struct ImGuiTextBuffer; + +namespace Core::Devtools { + +struct TOptions { + std::string disassembly_cli{}; + bool frame_dump_render_on_collapse{false}; +}; + +extern TOptions Options; + +void LoadOptionsConfig(const char* line); +void SerializeOptionsConfig(ImGuiTextBuffer* buf); + +} // namespace Core::Devtools diff --git a/src/core/devtools/widget/cmd_list.cpp b/src/core/devtools/widget/cmd_list.cpp new file mode 100644 index 000000000..9a42f8238 --- /dev/null +++ b/src/core/devtools/widget/cmd_list.cpp @@ -0,0 +1,1482 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Credits to https://github.com/psucien/tlg-emu-tools/ + +#include +#include +#include + +#include "cmd_list.h" +#include "frame_dump.h" +#include "imgui_internal.h" +#include "imgui_memory_editor.h" +#include "video_core/amdgpu/liverpool.h" +#include "video_core/amdgpu/pm4_cmds.h" + +#define CONTEXT_SPACE_START 0x0000a000 +#define PERSISTENT_SPACE_START 0x00002c00 + +using namespace ImGui; +using namespace Pal::Gfx6; +using Liverpool = AmdGpu::Liverpool; +using magic_enum::enum_name; + +namespace Core::Devtools::Gcn { + +const char* GetContextRegName(u32 reg_offset); +const char* GetShaderRegName(u32 reg_offset); +const char* GetOpCodeName(u32 op); + +} // namespace Core::Devtools::Gcn + +namespace Core::Devtools::Widget { + +static bool group_batches = true; +static bool show_markers = false; + +void CmdListViewer::LoadConfig(const char* line) { + int i; + if (sscanf(line, "group_batches=%d", &i) == 1) { + group_batches = i != 0; + return; + } + if (sscanf(line, "show_markers=%d", &i) == 1) { + show_markers = i != 0; + return; + } +} + +void CmdListViewer::SerializeConfig(ImGuiTextBuffer* buf) { + buf->appendf("group_batches=%d\n", group_batches); + buf->appendf("show_markers=%d\n", show_markers); +} + +template +static HdrType GetNext(HdrType this_pm4, uint32_t n) { + HdrType curr_pm4 = this_pm4; + while (n) { + curr_pm4 = reinterpret_cast(reinterpret_cast(curr_pm4) + + curr_pm4->count + 2); + --n; + } + return curr_pm4; +} + +void ParsePolygonControl(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("CULL_FRONT"); + TableSetColumnIndex(1); + Text("%X", reg.cull_front.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("CULL_BACK"); + TableSetColumnIndex(1); + Text("%X", reg.cull_back.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FACE"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.front_face.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("POLY_MODE"); + TableSetColumnIndex(1); + Text("%X", reg.enable_polygon_mode.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("POLYMODE_FRONT_PTYPE"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.polygon_mode_front.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("POLYMODE_BACK_PTYPE"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.polygon_mode_back.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("POLY_OFFSET_FRONT_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.enable_polygon_offset_front.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("POLY_OFFSET_BACK_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.enable_polygon_offset_back.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("POLY_OFFSET_PARA_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.enable_polygon_offset_para.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VTX_WINDOW_OFFSET_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.enable_window_offset.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("PROVOKING_VTX_LAST"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.provoking_vtx_last.Value(), + enum_name(reg.provoking_vtx_last.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("PERSP_CORR_DIS"); + TableSetColumnIndex(1); + Text("%X", reg.persp_corr_dis.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("MULTI_PRIM_IB_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.multi_prim_ib_ena.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseAaConfig(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("MSAA_NUM_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.msaa_num_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("AA_MASK_CENTROID_DTMN"); + TableSetColumnIndex(1); + Text("%X", reg.aa_mask_centroid_dtmn.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("MAX_SAMPLE_DIST"); + TableSetColumnIndex(1); + Text("%X", reg.max_sample_dst.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("MSAA_EXPOSED_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.msaa_exposed_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DETAIL_TO_EXPOSED_MODE"); + TableSetColumnIndex(1); + Text("%X", reg.detail_to_exposed_mode.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseViewportControl(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("VPORT_X_SCALE_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.xscale_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VPORT_X_OFFSET_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.yoffset_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VPORT_Y_SCALE_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.yscale_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VPORT_Y_OFFSET_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.yoffset_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VPORT_Z_SCALE_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.zscale_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VPORT_Z_OFFSET_ENA"); + TableSetColumnIndex(1); + Text("%X", reg.zoffset_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VTX_XY_FMT"); + TableSetColumnIndex(1); + Text("%X", reg.xy_transformed.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VTX_Z_FMT"); + TableSetColumnIndex(1); + Text("%X", reg.z_transformed.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("VTX_W0_FMT"); + TableSetColumnIndex(1); + Text("%X", reg.w_transformed.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("PERFCOUNTER_REF"); + TableSetColumnIndex(1); + Text("%X", reg.perfcounter_ref.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseColorControl(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("DISABLE_DUAL_QUAD__VI"); + TableSetColumnIndex(1); + Text("%X", reg.disable_dual_quad.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DEGAMMA_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.degamma_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("MODE"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.mode.Value(), enum_name(reg.mode.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ROP3"); + TableSetColumnIndex(1); + Text("%X", reg.rop3.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseColor0Info(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("ENDIAN"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.endian.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FORMAT"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.format.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("LINEAR_GENERAL"); + TableSetColumnIndex(1); + Text("%X", reg.linear_general.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("NUMBER_TYPE"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.number_type.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("COMP_SWAP"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.comp_swap.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FAST_CLEAR"); + TableSetColumnIndex(1); + Text("%X", reg.fast_clear.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("COMPRESSION"); + TableSetColumnIndex(1); + Text("%X", reg.compression.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("BLEND_CLAMP"); + TableSetColumnIndex(1); + Text("%X", reg.blend_clamp.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("BLEND_BYPASS"); + TableSetColumnIndex(1); + Text("%X", reg.blend_bypass.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("SIMPLE_FLOAT"); + TableSetColumnIndex(1); + Text("%X", reg.simple_float.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ROUND_MODE"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.round_mode.Value(), enum_name(reg.round_mode.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("CMASK_IS_LINEAR"); + TableSetColumnIndex(1); + Text("%X", reg.cmask_is_linear.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("BLEND_OPT_DONT_RD_DST"); + TableSetColumnIndex(1); + Text("%X", reg.blend_opt_dont_rd_dst.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("BLEND_OPT_DISCARD_PIXEL"); + TableSetColumnIndex(1); + Text("%X", reg.blend_opt_discard_pixel.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FMASK_COMPRESSION_DISABLE__CI__VI"); + TableSetColumnIndex(1); + Text("%X", reg.fmask_compression_disable_ci.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FMASK_COMPRESS_1FRAG_ONLY__VI"); + TableSetColumnIndex(1); + Text("%X", reg.fmask_compress_1frag_only.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DCC_ENABLE__VI"); + TableSetColumnIndex(1); + Text("%X", reg.dcc_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("CMASK_ADDR_TYPE__VI"); + TableSetColumnIndex(1); + Text("%X", reg.cmask_addr_type.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseColor0Attrib(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("TILE_MODE_INDEX"); + TableSetColumnIndex(1); + Text("%s", enum_name(reg.tile_mode_index.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FMASK_TILE_MODE_INDEX"); + TableSetColumnIndex(1); + Text("%X", reg.fmask_tile_mode_index.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FMASK_BANK_HEIGHT"); + TableSetColumnIndex(1); + Text("%X", reg.fmask_bank_height.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("NUM_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.num_samples_log2.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("NUM_FRAGMENTS"); + TableSetColumnIndex(1); + Text("%X", reg.num_fragments_log2.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("FORCE_DST_ALPHA_1"); + TableSetColumnIndex(1); + Text("%X", reg.force_dst_alpha_1.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseBlendControl(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("COLOR_SRCBLEND"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.color_src_factor.Value(), + enum_name(reg.color_src_factor.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("COLOR_COMB_FCN"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.color_func.Value(), enum_name(reg.color_func.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("COLOR_DESTBLEND"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.color_dst_factor.Value(), + enum_name(reg.color_dst_factor.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ALPHA_SRCBLEND"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.alpha_src_factor.Value(), + enum_name(reg.alpha_src_factor.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ALPHA_COMB_FCN"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.alpha_func.Value(), enum_name(reg.alpha_func.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ALPHA_DESTBLEND"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.alpha_dst_factor.Value(), + enum_name(reg.alpha_dst_factor.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("SEPARATE_ALPHA_BLEND"); + TableSetColumnIndex(1); + Text("%X", reg.separate_alpha_blend.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DISABLE_ROP3"); + TableSetColumnIndex(1); + Text("%X", reg.disable_rop3.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseDepthRenderControl(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("DEPTH_CLEAR_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.depth_clear_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("STENCIL_CLEAR_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.stencil_clear_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DEPTH_COPY"); + TableSetColumnIndex(1); + Text("%X", reg.depth_clear_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("STENCIL_COPY"); + TableSetColumnIndex(1); + Text("%X", reg.stencil_copy.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("RESUMMARIZE_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.resummarize_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("STENCIL_COMPRESS_DISABLE"); + TableSetColumnIndex(1); + Text("%X", reg.stencil_compress_disable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DEPTH_COMPRESS_DISABLE"); + TableSetColumnIndex(1); + Text("%X", reg.depth_compress_disable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("COPY_CENTROID"); + TableSetColumnIndex(1); + Text("%X", reg.copy_centroid.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("COPY_SAMPLE"); + TableSetColumnIndex(1); + Text("%X", reg.copy_sample.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DECOMPRESS_ENABLE__VI"); + TableSetColumnIndex(1); + Text("%X", reg.decompress_enable.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseDepthControl(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("STENCIL_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.stencil_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("Z_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.depth_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("Z_WRITE_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.depth_write_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DEPTH_BOUNDS_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.depth_bounds_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ZFUNC"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.depth_func.Value(), enum_name(reg.depth_func.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("BACKFACE_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.backface_enable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("STENCILFUNC"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.stencil_ref_func.Value(), + enum_name(reg.stencil_ref_func.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("STENCILFUNC_BF"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.stencil_bf_func.Value(), + enum_name(reg.stencil_bf_func.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ENABLE_COLOR_WRITES_ON_DEPTH_FAIL"); + TableSetColumnIndex(1); + Text("%X", reg.enable_color_writes_on_depth_fail.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DISABLE_COLOR_WRITES_ON_DEPTH_PASS"); + TableSetColumnIndex(1); + Text("%X", reg.disable_color_writes_on_depth_pass.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseEqaa(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("MAX_ANCHOR_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.max_anchor_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("PS_ITER_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.ps_iter_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("MASK_EXPORT_NUM_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.mask_export_num_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ALPHA_TO_MASK_NUM_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.alpha_to_mask_num_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("HIGH_QUALITY_INTERSECTIONS"); + TableSetColumnIndex(1); + Text("%X", reg.high_quality_intersections.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("INCOHERENT_EQAA_READS"); + TableSetColumnIndex(1); + Text("%X", reg.incoherent_eqaa_reads.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("INTERPOLATE_COMP_Z"); + TableSetColumnIndex(1); + Text("%X", reg.interpolate_comp_z.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("INTERPOLATE_SRC_Z"); + TableSetColumnIndex(1); + Text("%X", reg.interpolate_src_z.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("STATIC_ANCHOR_ASSOCIATIONS"); + TableSetColumnIndex(1); + Text("%X", reg.static_anchor_associations.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ALPHA_TO_MASK_EQAA_DISABLE"); + TableSetColumnIndex(1); + Text("%X", reg.alpha_to_mask_eqaa_disable.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("OVERRASTERIZATION_AMOUNT"); + TableSetColumnIndex(1); + Text("%X", reg.overrasterization_amount.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ENABLE_POSTZ_OVERRASTERIZATION"); + TableSetColumnIndex(1); + Text("%X", reg.enable_postz_overrasterization.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void ParseZInfo(u32 value, bool begin_table) { + auto const reg = reinterpret_cast(value); + + if (!begin_table || + BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + TableNextRow(); + TableSetColumnIndex(0); + Text("FORMAT"); + TableSetColumnIndex(1); + Text("%X (%s)", (u32)reg.format.Value(), enum_name(reg.format.Value()).data()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("NUM_SAMPLES"); + TableSetColumnIndex(1); + Text("%X", reg.num_samples.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("TILE_SPLIT__CI__VI"); + TableSetColumnIndex(1); + Text("%X", reg.tile_split.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("TILE_MODE_INDEX"); + TableSetColumnIndex(1); + Text("%X", reg.tile_mode_index.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("DECOMPRESS_ON_N_ZPLANES__VI"); + TableSetColumnIndex(1); + Text("%X", reg.decompress_on_n_zplanes.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ALLOW_EXPCLEAR"); + TableSetColumnIndex(1); + Text("%X", reg.allow_expclear.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("READ_SIZE"); + TableSetColumnIndex(1); + Text("%X", reg.read_size.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("TILE_SURFACE_ENABLE"); + TableSetColumnIndex(1); + Text("%X", reg.tile_surface_en.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("CLEAR_DISALLOWED__VI"); + TableSetColumnIndex(1); + Text("%X", reg.clear_disallowed.Value()); + + TableNextRow(); + TableSetColumnIndex(0); + Text("ZRANGE_PRECISION"); + TableSetColumnIndex(1); + Text("%X", reg.zrange_precision.Value()); + + if (begin_table) { + EndTable(); + } + } +} + +void CmdListViewer::OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body) { + using namespace std::string_view_literals; + +#define NOP_PAYLOAD \ + P(PUSH_MARKER, 0x68750001) \ + P(POP_MARKER, 0x68750002) \ + P(SET_MARKER, 0x68750003) \ + P(SET_VSHARP, 0x68750004) \ + P(SET_TSHARP, 0x68750005) \ + P(SET_SSHARP, 0x68750006) \ + P(ACB_SUBMIT_MRK, 0x68750013) \ + P(SET_USER_DATA, 0x6875000D) \ + P(PATCHED_FLIP, 0x68750776) \ + P(PREPARE_FLIP, 0x68750777) \ + P(PREPARE_FLIP_LABEL, 0x68750778) \ + P(PREPARE_FLIP_INTERRUPT, 0x68750780) \ + P(PREPARE_FLIP_INTERRUPT_LABEL, 0x68750781) \ + P(ALLOC_ALIGN8, 0x68753000) + + auto get_nop_payload_text = [](u32 const nop_payload) { + switch (nop_payload) { +#define P(name, value) \ + case value: \ + return #name##sv; + NOP_PAYLOAD +#undef P + default: + return ""sv; + } + }; + + Separator(); + BeginGroup(); + + auto const* pkt = reinterpret_cast(header); + auto const* payload = &body[0]; + + // Dump payload + for (unsigned i = 0; i < pkt->header.count + 1; ++i) { + Text("%02X: %08X", i, payload[i]); + if ((payload[i] & 0xffff0000) == 0x68750000) { + const auto& e = get_nop_payload_text(payload[i]); + if (!e.empty()) { + SameLine(); + Text("(%s)", e.data()); + } + } + } + + EndGroup(); +} +void CmdListViewer::OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* body) { + Separator(); + BeginGroup(); + + // auto const* pkt = reinterpret_cast(header); + Text("BASE_INDEX: %08X", body[0]); + Text("ADDRESS0 : %08X", body[1]); + Text("ADDRESS1 : %08X", body[2]); + + EndGroup(); +} + +void CmdListViewer::OnSetContextReg(AmdGpu::PM4Type3Header const* header, u32 const* body) { + Separator(); + BeginGroup(); + + auto const* pkt = reinterpret_cast(header); + + for (auto i = 0u; i < header->count; ++i) { + auto const absOffset = CONTEXT_SPACE_START + pkt->reg_offset + i; + Text("reg: %4X (%s)", pkt->reg_offset + i, Gcn::GetContextRegName(absOffset)); + Text("[%08X]", body[i + 1]); + + switch (absOffset) { + case mmPA_SU_SC_MODE_CNTL: { + if (IsItemHovered() && BeginTooltip()) { + ParsePolygonControl(body[1]); + EndTooltip(); + } + break; + } + case mmPA_SC_AA_CONFIG: { + if (IsItemHovered() && BeginTooltip()) { + ParseAaConfig(body[1]); + EndTooltip(); + } + break; + } + case mmPA_CL_VTE_CNTL: { + if (IsItemHovered() && BeginTooltip()) { + ParseViewportControl(body[1]); + EndTooltip(); + } + break; + } + case mmCB_COLOR_CONTROL: + if (IsItemHovered() && BeginTooltip()) { + ParseColorControl(body[1]); + EndTooltip(); + } + break; + case mmCB_COLOR0_INFO: + [[fallthrough]]; + case mmCB_COLOR1_INFO: + [[fallthrough]]; + case mmCB_COLOR2_INFO: + [[fallthrough]]; + case mmCB_COLOR3_INFO: + [[fallthrough]]; + case mmCB_COLOR4_INFO: + [[fallthrough]]; + case mmCB_COLOR5_INFO: + [[fallthrough]]; + case mmCB_COLOR6_INFO: + [[fallthrough]]; + case mmCB_COLOR7_INFO: { + if (IsItemHovered() && BeginTooltip()) { + ParseColor0Info(body[i + 1]); + EndTooltip(); + } + break; + } + case mmCB_COLOR0_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR1_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR2_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR3_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR4_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR5_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR6_ATTRIB: + [[fallthrough]]; + case mmCB_COLOR7_ATTRIB: { + if (IsItemHovered() && BeginTooltip()) { + ParseColor0Attrib(body[i + 1]); + EndTooltip(); + } + break; + } + case mmCB_BLEND0_CONTROL: + [[fallthrough]]; + case mmCB_BLEND1_CONTROL: + [[fallthrough]]; + case mmCB_BLEND2_CONTROL: + [[fallthrough]]; + case mmCB_BLEND3_CONTROL: + [[fallthrough]]; + case mmCB_BLEND4_CONTROL: + [[fallthrough]]; + case mmCB_BLEND5_CONTROL: + [[fallthrough]]; + case mmCB_BLEND6_CONTROL: + [[fallthrough]]; + case mmCB_BLEND7_CONTROL: { + if (IsItemHovered() && BeginTooltip()) { + ParseBlendControl(body[i + 1]); + EndTooltip(); + } + break; + } + case mmDB_RENDER_CONTROL: { + if (IsItemHovered() && BeginTooltip()) { + ParseDepthRenderControl(body[1]); + EndTooltip(); + } + break; + } + case mmDB_DEPTH_CONTROL: { + if (IsItemHovered() && BeginTooltip()) { + ParseDepthControl(body[1]); + EndTooltip(); + } + break; + } + case mmDB_EQAA: { + if (IsItemHovered() && BeginTooltip()) { + ParseEqaa(body[1]); + EndTooltip(); + } + break; + } + case mmDB_Z_INFO: { + if (IsItemHovered() && BeginTooltip()) { + ParseZInfo(body[1]); + EndTooltip(); + } + break; + } + case mmDB_HTILE_DATA_BASE: { + auto const& reg = reinterpret_cast(body[1]); + Text("addr: %08x", reg * 256u); + break; + } + default: + break; + } + + //... + } + + EndGroup(); +} + +void CmdListViewer::OnSetShReg(AmdGpu::PM4Type3Header const* header, u32 const* body) { + Separator(); + BeginGroup(); + + auto const* pkt = reinterpret_cast(header); + + for (auto i = 0u; i < header->count; ++i) { + auto const absOffset = PERSISTENT_SPACE_START + pkt->reg_offset + i; + Text("reg: %4X (%s)", pkt->reg_offset + i, Gcn::GetShaderRegName(absOffset)); + + Text("%08X", *((uint32_t*)header + 2 + i)); + + //... + } + + EndGroup(); +} + +void CmdListViewer::OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* body) { + Separator(); + BeginGroup(); + + auto const* pkt = reinterpret_cast(header); + + Text("DIM_X : %d", pkt->dim_x); + Text("DIM_Y : %d", pkt->dim_y); + Text("DIM_Z : %d", pkt->dim_z); + Text("INITIATOR: %X", pkt->dispatch_initiator); + if (IsItemHovered() && BeginTooltip()) { + // TODO: dump_reg + EndTooltip(); + } + + EndGroup(); +} + +CmdListViewer::CmdListViewer(DebugStateType::FrameDump* _frame_dump, + const std::vector& cmd_list, uintptr_t _base_addr, + std::string _name) + : frame_dump(_frame_dump), base_addr(_base_addr), name(std::move(_name)) { + using namespace AmdGpu; + + cmdb_addr = (uintptr_t)cmd_list.data(); + cmdb_size = cmd_list.size() * sizeof(u32); + + cmdb_view_name = fmt::format("[GFX] Command buffer {}###cmdview_hex_{}", this->name, cmdb_addr); + cmdb_view.Open = false; + cmdb_view.ReadOnly = true; + + auto const* pm4_hdr = reinterpret_cast(cmdb_addr); + + size_t processed_size = 0; + size_t prev_offset = 0; + u32 batch_id = 0; + + std::string marker{}; + + if (cmdb_size > 0) { + events.emplace_back(BatchBegin{.id = 0}); + } + + while (processed_size < cmdb_size) { + auto* next_pm4_hdr = GetNext(pm4_hdr, 1); + auto processed_len = + reinterpret_cast(next_pm4_hdr) - reinterpret_cast(pm4_hdr); + processed_size += processed_len; + + if (pm4_hdr->type == PM4Type3Header::TYPE) { + + auto const* pm4_t3 = reinterpret_cast(pm4_hdr); + auto opcode = pm4_t3->opcode; + + if (opcode == PM4ItOpcode::Nop) { + auto const* it_body = reinterpret_cast(pm4_hdr + 1); + switch (it_body[0]) { + case PM4CmdNop::PayloadType::DebugSetMarker: + marker = std::string{(char*)&it_body[1]}; + break; + case PM4CmdNop::PayloadType::DebugMarkerPush: + events.emplace_back(PushMarker{ + .name = std::string{(char*)&it_body[1]}, + }); + break; + case PM4CmdNop::PayloadType::DebugMarkerPop: + events.emplace_back(PopMarker{}); + break; + default: + break; + } + } + + if (IsDrawCall(opcode)) { + // All these commands are terminated by NOP at the end, so + // it is safe to skip it to be even with CP + // next_pm4_hdr = get_next(next_pm4_hdr, 1); + // auto constexpr nop_len = 0x10; + // processed_len += nop_len; + // processed_size += nop_len; + + events.emplace_back(BatchInfo{ + .id = batch_id++, + .marker = marker, + .start_addr = prev_offset, + .end_addr = processed_size, + .command_addr = processed_size - processed_len, + .type = opcode, + }); + prev_offset = processed_size; + marker.clear(); + events.emplace_back(BatchBegin{.id = batch_id}); + } + } + + pm4_hdr = next_pm4_hdr; + } + + // state batch (last) + if (processed_size - prev_offset > 0) { + events.emplace_back(BatchInfo{ + .id = batch_id++, + .marker = marker, + .start_addr = prev_offset, + .end_addr = processed_size, + .command_addr = 0, + .type = static_cast(0xFF), + }); + } + if (!events.empty() && std::holds_alternative(events.back())) { + events.pop_back(); + } +} + +void CmdListViewer::Draw(bool only_batches_view) { + const auto& ctx = *GetCurrentContext(); + + if (batch_view.open) { + batch_view.Draw(); + } + for (auto it = extra_batch_view.begin(); it != extra_batch_view.end();) { + if (!it->open) { + it = extra_batch_view.erase(it); + continue; + } + it->Draw(); + ++it; + } + + if (only_batches_view) { + return; + } + + if (cmdb_view.Open) { + MemoryEditor::Sizes s; + cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr); + SetNextWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}, ImGuiCond_FirstUseEver); + SetNextWindowSizeConstraints({0.0f}, {s.WindowWidth, FLT_MAX}); + if (Begin(cmdb_view_name.c_str(), &cmdb_view.Open, + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) { + cmdb_view.DrawContents((void*)cmdb_addr, cmdb_size, base_addr); + if (cmdb_view.ContentsWidthChanged) { + cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr); + SetWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}); + } + } + End(); + } + + PushID(name.c_str()); + if (BeginChild("cmd_queue", {})) { + + Checkbox("Group batches", &group_batches); + SameLine(); + Checkbox("Show markers", &show_markers); + + char queue_name[32]{}; + if (vqid < 254) { + std::snprintf(queue_name, sizeof(queue_name), "%s %d", vqid > 254 ? "GFX" : "ASC", + vqid); + } else { + std::snprintf(queue_name, sizeof(queue_name), "%s", vqid > 254 ? "GFX" : "ASC"); + } + + Text("queue : %s", queue_name); + Text("base addr: %08llX", cmdb_addr); + SameLine(); + if (SmallButton("Memory >")) { + cmdb_view.Open ^= true; + } + Text("size : %04llX", cmdb_size); + Separator(); + + { + int tree_depth = 0; + int tree_depth_show = 0; + + u32 last_batch_id = ~0u; + if (!events.empty() && std::holds_alternative(events.back())) { + last_batch_id = std::get(events.back()).id; + } + + u32 batch_id = ~0u; + u32 current_highlight_batch = ~0u; + + int id = 0; + PushID(0); + for (const auto& event : events) { + PopID(); + PushID(id++); + + if (std::holds_alternative(event)) { + batch_id = std::get(event).id; + } + + if (show_markers) { + if (std::holds_alternative(event)) { + if (tree_depth_show >= tree_depth) { + auto& marker = std::get(event); + bool show = TreeNode(&event, "%s", marker.name.c_str()); + if (show) { + tree_depth_show++; + } + } + tree_depth++; + continue; + } + if (std::holds_alternative(event)) { + if (tree_depth_show >= tree_depth) { + tree_depth_show--; + TreePop(); + } + tree_depth--; + continue; + } + if (tree_depth_show < tree_depth) { + continue; + } + } + + if (!std::holds_alternative(event)) { + continue; + } + + auto& batch = std::get(event); + auto const* pm4_hdr = + reinterpret_cast(cmdb_addr + batch.start_addr); + + bool ignore_header = false; + char batch_hdr[128]; + if (batch.type == static_cast(0xFF)) { + ignore_header = true; + } else if (!batch.marker.empty()) { + snprintf(batch_hdr, sizeof(batch_hdr), "%08llX: batch-%03d %s | %s", + cmdb_addr + batch.start_addr, batch.id, + Gcn::GetOpCodeName(static_cast(batch.type)), + batch.marker.c_str()); + } else { + snprintf(batch_hdr, sizeof(batch_hdr), "%08llX: batch-%03d %s", + cmdb_addr + batch.start_addr, batch.id, + Gcn::GetOpCodeName(static_cast(batch.type))); + } + + if (batch.id == batch_bp) { // highlight batch at breakpoint + PushStyleColor(ImGuiCol_Header, ImVec4{1.0f, 0.5f, 0.5f, 0.5f}); + } + if (batch.id == highlight_batch) { + PushStyleColor(ImGuiCol_Text, ImVec4{1.0f, 0.7f, 0.7f, 1.0f}); + } + + const auto open_batch_view = [&, this] { + if (frame_dump->regs.contains(batch.command_addr)) { + auto data = frame_dump->regs.at(batch.command_addr); + if (GetIO().KeyShift) { + auto& pop = extra_batch_view.emplace_back(); + pop.SetData(data, name, batch_id); + pop.open = true; + } else { + if (batch_view.open && + this->last_selected_batch == static_cast(batch_id)) { + batch_view.open = false; + } else { + this->last_selected_batch = static_cast(batch_id); + batch_view.SetData(data, name, batch_id); + if (!batch_view.open || !batch_view.moved) { + batch_view.open = true; + const auto pos = GetItemRectMax() + ImVec2{5.0f, 0.0f}; + batch_view.SetPos(pos); + } + } + } + } + }; + + bool show_batch_content = true; + + if (group_batches && !ignore_header) { + show_batch_content = + CollapsingHeader(batch_hdr, ImGuiTreeNodeFlags_AllowOverlap); + SameLine(GetContentRegionAvail().x - 40.0f); + const char* text = + last_selected_batch == static_cast(batch_id) && batch_view.open ? "X" + : "->"; + if (Button(text, {40.0f, 0.0f})) { + open_batch_view(); + } + } + + if (show_batch_content) { + auto processed_size = 0ull; + auto bb = ctx.LastItemData.Rect; + if (group_batches && !ignore_header) { + Indent(); + } + auto const batch_sz = batch.end_addr - batch.start_addr; + + while (processed_size < batch_sz) { + AmdGpu::PM4ItOpcode op{0xFFu}; + + if (pm4_hdr->type == AmdGpu::PM4Type3Header::TYPE) { + auto const* pm4_t3 = + reinterpret_cast(pm4_hdr); + op = pm4_t3->opcode; + + char header_name[128]; + sprintf(header_name, "%08llX: %s", + cmdb_addr + batch.start_addr + processed_size, + Gcn::GetOpCodeName((u32)op)); + + bool open_pm4 = TreeNode(header_name); + if (!group_batches) { + if (IsDrawCall(op)) { + SameLine(GetContentRegionAvail().x - 40.0f); + const char* text = + last_selected_batch == static_cast(batch_id) && + batch_view.open + ? "X" + : "->"; + if (Button(text, {40.0f, 0.0f})) { + open_batch_view(); + } + } + if (IsItemHovered() && ctx.IO.KeyShift) { + if (BeginTooltip()) { + Text("Batch %d", batch_id); + EndTooltip(); + } + } + } + if (open_pm4) { + if (IsItemToggledOpen()) { + // Editor + cmdb_view.GotoAddrAndHighlight( + reinterpret_cast(pm4_hdr) - cmdb_addr, + reinterpret_cast(pm4_hdr) - cmdb_addr + + (pm4_hdr->count + 2) * 4); + } + + if (BeginTable("split", 1)) { + TableNextColumn(); + Text("size: %d", pm4_hdr->count + 1); + + auto const* it_body = + reinterpret_cast(pm4_hdr + 1); + + switch (op) { + case AmdGpu::PM4ItOpcode::Nop: { + OnNop(pm4_t3, it_body); + break; + } + case AmdGpu::PM4ItOpcode::SetBase: { + OnSetBase(pm4_t3, it_body); + break; + } + case AmdGpu::PM4ItOpcode::SetContextReg: { + OnSetContextReg(pm4_t3, it_body); + break; + } + case AmdGpu::PM4ItOpcode::SetShReg: { + OnSetShReg(pm4_t3, it_body); + break; + } + case AmdGpu::PM4ItOpcode::DispatchDirect: { + OnDispatch(pm4_t3, it_body); + break; + } + default: { + auto const* payload = &it_body[0]; + for (unsigned i = 0; i < pm4_hdr->count + 1; ++i) { + Text("%02X: %08X", i, payload[i]); + } + } + } + + EndTable(); + } + TreePop(); + } + + } else { + Text(""); + } + + auto const* next_pm4_hdr = GetNext(pm4_hdr, 1); + auto const processed_len = reinterpret_cast(next_pm4_hdr) - + reinterpret_cast(pm4_hdr); + pm4_hdr = next_pm4_hdr; + processed_size += processed_len; + } + + if (group_batches && !ignore_header) { + Unindent(); + }; + bb = {{0.0f, bb.Max.y}, ctx.LastItemData.Rect.Max}; + if (bb.Contains(ctx.IO.MousePos)) { + current_highlight_batch = batch.id; + } + } + + if (batch.id == highlight_batch) { + PopStyleColor(); + } + + if (batch.id == batch_bp) { + PopStyleColor(); + } + + if (batch.id == last_batch_id) { + Separator(); + } + } + PopID(); + + highlight_batch = current_highlight_batch; + } + } + EndChild(); + PopID(); +} + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/cmd_list.h b/src/core/devtools/widget/cmd_list.h new file mode 100644 index 000000000..ed71d0b76 --- /dev/null +++ b/src/core/devtools/widget/cmd_list.h @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Credits to https://github.com/psucien/tlg-emu-tools/ + +#pragma once + +#include +#include +#include + +#include "common.h" +#include "common/types.h" +#include "imgui_memory_editor.h" +#include "reg_view.h" + +namespace AmdGpu { +union PM4Type3Header; +enum class PM4ItOpcode : u32; +} // namespace AmdGpu + +namespace Core::Devtools::Widget { + +class FrameDumpViewer; + +void ParsePolygonControl(u32 value, bool begin_table = true); +void ParseAaConfig(u32 value, bool begin_table = true); +void ParseViewportControl(u32 value, bool begin_table = true); +void ParseColorControl(u32 value, bool begin_table = true); +void ParseColor0Info(u32 value, bool begin_table = true); +void ParseColor0Attrib(u32 value, bool begin_table = true); +void ParseBlendControl(u32 value, bool begin_table = true); +void ParseDepthRenderControl(u32 value, bool begin_table = true); +void ParseDepthControl(u32 value, bool begin_table = true); +void ParseEqaa(u32 value, bool begin_table = true); +void ParseZInfo(u32 value, bool begin_table = true); + +class CmdListViewer { + + DebugStateType::FrameDump* frame_dump; + + uintptr_t base_addr; + std::string name; + std::vector events{}; + uintptr_t cmdb_addr; + size_t cmdb_size; + + std::string cmdb_view_name; + MemoryEditor cmdb_view; + + int batch_bp{-1}; + int vqid{255}; + u32 highlight_batch{~0u}; + + RegView batch_view; + int last_selected_batch{-1}; + + std::vector extra_batch_view; + + static void OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnSetContextReg(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnSetShReg(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* body); + +public: + static void LoadConfig(const char* line); + static void SerializeConfig(ImGuiTextBuffer* buf); + + 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); +}; + +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/common.h b/src/core/devtools/widget/common.h new file mode 100644 index 000000000..e650f5fc7 --- /dev/null +++ b/src/core/devtools/widget/common.h @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#include + +#include "common/bit_field.h" +#include "common/types.h" +#include "video_core/amdgpu/pm4_opcodes.h" + +namespace Core::Devtools::Widget { +/* + * Generic PM4 header + */ +union PM4Header { + struct { + u32 reserved : 16; + u32 count : 14; + u32 type : 2; // PM4_TYPE + }; + u32 u32All; +}; + +struct PushMarker { + std::string name{}; +}; + +struct PopMarker {}; + +struct BatchBegin { + u32 id; +}; + +struct BatchInfo { + u32 id; + std::string marker{}; + size_t start_addr; + size_t end_addr; + size_t command_addr; + AmdGpu::PM4ItOpcode type; + bool bypass{false}; +}; + +using GPUEvent = std::variant; + +template +void DrawRow(const char* text, const char* fmt, Args... args) { + ImGui::TableNextColumn(); + ImGui::TextUnformatted(text); + ImGui::TableNextColumn(); + char buf[128]; + snprintf(buf, sizeof(buf), fmt, args...); + ImGui::TextUnformatted(buf); +} + +template +void DrawValueRow(const char* text, T value) { + if constexpr (std::is_enum_v) { + return DrawRow(text, "%X (%s)", value, magic_enum::enum_name(value).data()); + } else if constexpr (std::is_integral_v) { + return DrawRow(text, "%X", value); + } else if constexpr (std::is_base_of_v, T>) { + return DrawValueRow(text, value.Value()); + } else { + static_assert(false, "Unsupported type"); + } +} + +template +void DrawValueRowList(const char* text, V arg, Extra&&... extra_args) { + DrawValueRow(text, arg); + if constexpr (sizeof...(extra_args) > 0) { + DrawValueRowList(std::forward(extra_args)...); + } +} + +template +static void DoTooltip(const char* str_id, Args&&... args) { + if (ImGui::BeginTooltip()) { + if (ImGui::BeginTable(str_id, 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + DrawMultipleRow(std::forward(args)...); + ImGui::EndTable(); + } + ImGui::EndTooltip(); + } +} + +static bool IsDrawCall(AmdGpu::PM4ItOpcode opcode) { + using AmdGpu::PM4ItOpcode; + switch (opcode) { + case PM4ItOpcode::DrawIndex2: + case PM4ItOpcode::DrawIndexOffset2: + case PM4ItOpcode::DrawIndexAuto: + case PM4ItOpcode::DrawIndirect: + case PM4ItOpcode::DrawIndexIndirect: + case PM4ItOpcode::DispatchDirect: + case PM4ItOpcode::DispatchIndirect: + return true; + default: + return false; + } +} + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/frame_dump.cpp b/src/core/devtools/widget/frame_dump.cpp new file mode 100644 index 000000000..86ba7b86e --- /dev/null +++ b/src/core/devtools/widget/frame_dump.cpp @@ -0,0 +1,197 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include + +#include "common/io_file.h" +#include "core/devtools/options.h" +#include "frame_dump.h" +#include "imgui_internal.h" +#include "imgui_memory_editor.h" + +using namespace ImGui; +using namespace DebugStateType; + +#define C_V(label, value, var, out) \ + if (Selectable(label, var == value)) { \ + var = value; \ + selected_cmd = -1; \ + out = true; \ + } + +// 00 to 99 +static std::array small_int_to_str(const s32 i) { + std::array label{}; + if (i == -1) { + label[0] = 'N'; + label[1] = 'A'; + } else { + label[0] = i / 10 + '0'; + label[1] = i % 10 + '0'; + } + return label; +} + +namespace Core::Devtools::Widget { + +FrameDumpViewer::FrameDumpViewer(const FrameDump& _frame_dump) + : frame_dump(std::make_shared(_frame_dump)) { + static int unique_id = 0; + id = unique_id++; + + selected_queue_type = QueueType::dcb; + selected_submit_num = 0; + selected_queue_num2 = 0; + + has_queue_type.fill(false); + cmd_list_viewer.reserve(frame_dump->queues.size()); + for (const auto& cmd : frame_dump->queues) { + if (!cmd.data.empty()) { + has_queue_type[static_cast(cmd.type)] = true; + } + const auto fname = fmt::format("F{} {}_{:02}_{:02}", frame_dump->frame_id, + magic_enum::enum_name(cmd.type), cmd.submit_num, cmd.num2); + cmd_list_viewer.emplace_back(frame_dump.get(), cmd.data, cmd.base_addr, fname); + if (cmd.type == QueueType::dcb && cmd.submit_num == 0 && cmd.num2 == 0) { + selected_cmd = static_cast(cmd_list_viewer.size() - 1); + } + } +} + +FrameDumpViewer::~FrameDumpViewer() = default; + +void FrameDumpViewer::Draw() { + if (!is_open) { + return; + } + + const auto try_select = [&, this] { + const auto it = std::ranges::find_if(frame_dump->queues, [&](const auto& cmd) { + return cmd.type == selected_queue_type && + (selected_submit_num == -1 || cmd.submit_num == selected_submit_num) && + (selected_queue_num2 == -1 || cmd.num2 == selected_queue_num2); + }); + if (it != frame_dump->queues.end()) { + selected_cmd = static_cast(std::distance(frame_dump->queues.begin(), it)); + selected_submit_num = static_cast(frame_dump->queues[selected_cmd].submit_num); + selected_queue_num2 = static_cast(frame_dump->queues[selected_cmd].num2); + } + }; + + bool is_showing = Options.frame_dump_render_on_collapse; + bool is_collapsed = true; + + char name[32]; + snprintf(name, sizeof(name), "Frame #%d dump", frame_dump->frame_id); + if (Begin(name, &is_open, ImGuiWindowFlags_NoSavedSettings)) { + is_showing = true; + is_collapsed = false; + + if (IsWindowAppearing()) { + auto window = GetCurrentWindow(); + static ImGuiID dock_id = ImHashStr("FrameDumpDock"); + SetWindowDock(window, dock_id, ImGuiCond_Once | ImGuiCond_FirstUseEver); + SetWindowSize(window, ImVec2{470.0f, 600.0f}); + } + BeginGroup(); + TextEx("Queue type"); + SameLine(); + if (BeginCombo("##select_queue_type", magic_enum::enum_name(selected_queue_type).data(), + ImGuiComboFlags_WidthFitPreview)) { + bool selected = false; +#define COMBO(x) \ + if (has_queue_type[static_cast(x)]) \ + C_V(magic_enum::enum_name(x).data(), x, selected_queue_type, selected) + COMBO(QueueType::dcb); + COMBO(QueueType::ccb); + COMBO(QueueType::acb); + if (selected) { + selected_submit_num = selected_queue_num2 = -1; + try_select(); + } + EndCombo(); + } + SameLine(); + BeginDisabled(selected_cmd == -1); + if (SmallButton("Dump cmd")) { + auto now_time = fmt::localtime(std::time(nullptr)); + const auto fname = fmt::format("{:%F %H-%M-%S} {}_{}_{}.bin", now_time, + magic_enum::enum_name(selected_queue_type), + selected_submit_num, selected_queue_num2); + Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write); + const auto& data = frame_dump->queues[selected_cmd].data; + if (file.IsOpen()) { + DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname)); + file.Write(data); + } else { + DebugState.ShowDebugMessage(fmt::format("Failed to save {}", fname)); + LOG_ERROR(Core, "Failed to open file {}", fname); + } + } + EndDisabled(); + + TextEx("Submit num"); + SameLine(); + if (BeginCombo("##select_submit_num", small_int_to_str(selected_submit_num).data(), + ImGuiComboFlags_WidthFitPreview)) { + std::array available_submits{false}; + for (const auto& cmd : frame_dump->queues) { + if (cmd.type == selected_queue_type && !cmd.data.empty()) { + available_submits[cmd.submit_num] = true; + } + } + bool selected = false; + for (int i = 0; i < available_submits.size(); ++i) { + if (available_submits[i]) { + char label[3]{}; + label[0] = i / 10 + '0'; + label[1] = i % 10 + '0'; + C_V(label, i, selected_submit_num, selected); + } + } + if (selected) { + selected_queue_num2 = -1; + try_select(); + } + EndCombo(); + } + SameLine(); + TextEx(selected_queue_type == QueueType::acb ? "Queue num" : "Buffer num"); + SameLine(); + if (BeginCombo("##select_queue_num2", small_int_to_str(selected_queue_num2).data(), + ImGuiComboFlags_WidthFitPreview)) { + std::array available_queues{false}; + for (const auto& cmd : frame_dump->queues) { + if (cmd.type == selected_queue_type && cmd.submit_num == selected_submit_num && + !cmd.data.empty()) { + available_queues[cmd.num2] = true; + } + } + bool selected = false; + for (int i = 0; i < available_queues.size(); ++i) { + if (available_queues[i]) { + char label[3]{}; + label[0] = i / 10 + '0'; + label[1] = i % 10 + '0'; + C_V(label, i, selected_queue_num2, selected); + } + } + if (selected) { + try_select(); + } + EndCombo(); + } + EndGroup(); + } + if (is_showing && selected_cmd != -1) { + cmd_list_viewer[selected_cmd].Draw(is_collapsed); + } + End(); +} + +} // namespace Core::Devtools::Widget + +#undef C_V \ No newline at end of file diff --git a/src/core/devtools/widget/frame_dump.h b/src/core/devtools/widget/frame_dump.h new file mode 100644 index 000000000..cc4fe6381 --- /dev/null +++ b/src/core/devtools/widget/frame_dump.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "cmd_list.h" +#include "core/debug_state.h" + +namespace Core::Devtools::Widget { + +class CmdListViewer; + +class FrameDumpViewer { + friend class CmdListViewer; + + std::shared_ptr frame_dump; + int id; + + std::vector cmd_list_viewer; + std::array has_queue_type; + + DebugStateType::QueueType selected_queue_type; + s32 selected_submit_num; + s32 selected_queue_num2; + s32 selected_cmd = -1; + +public: + bool is_open = true; + + explicit FrameDumpViewer(const DebugStateType::FrameDump& frame_dump); + + ~FrameDumpViewer(); + + void Draw(); +}; + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/frame_graph.cpp b/src/core/devtools/widget/frame_graph.cpp new file mode 100644 index 000000000..952f50c34 --- /dev/null +++ b/src/core/devtools/widget/frame_graph.cpp @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "frame_graph.h" + +#include "common/config.h" +#include "common/singleton.h" +#include "core/debug_state.h" +#include "imgui.h" +#include "imgui_internal.h" + +using namespace ImGui; + +namespace Core::Devtools::Widget { + +constexpr float TARGET_FPS = 60.0f; +constexpr float BAR_WIDTH_MULT = 1.4f; +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::Draw() { + if (!is_open) { + return; + } + SetNextWindowSize({340.0, 185.0f}, ImGuiCond_FirstUseEver); + if (Begin("Video debug info", &is_open)) { + const auto& ctx = *GImGui; + const auto& io = ctx.IO; + const auto& window = *ctx.CurrentWindow; + auto& draw_list = *window.DrawList; + + auto isSystemPaused = DebugState.IsGuestThreadsPaused(); + + static float deltaTime; + static float frameRate; + + if (!isSystemPaused) { + deltaTime = io.DeltaTime * 1000.0f; + frameRate = 1000.0f / deltaTime; + } + + 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(); + } + End(); +} + +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/frame_graph.h b/src/core/devtools/widget/frame_graph.h new file mode 100644 index 000000000..700b6b2a2 --- /dev/null +++ b/src/core/devtools/widget/frame_graph.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::Devtools::Widget { + +class FrameGraph { + static constexpr u32 FRAME_BUFFER_SIZE = 1024; + struct FrameInfo { + u32 num; + float delta; + }; + + std::array frame_list{}; + +public: + bool is_open = true; + + void Draw(); + + void AddFrame(u32 num, float delta) { + frame_list[num % FRAME_BUFFER_SIZE] = FrameInfo{num, delta}; + } +}; + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/imgui_memory_editor.h b/src/core/devtools/widget/imgui_memory_editor.h new file mode 100644 index 000000000..fb1f46767 --- /dev/null +++ b/src/core/devtools/widget/imgui_memory_editor.h @@ -0,0 +1,942 @@ +// SPDX-FileCopyrightText: 2024 Dear ImGui Club Contributors +// SPDX-License-Identifier: MIT + +// Mini memory editor for Dear ImGui (to embed in your game/tools) +// Get latest version at http://www.github.com/ocornut/imgui_club +// Licensed under The MIT License (MIT) + +// Right-click anywhere to access the Options menu! +// You can adjust the keyboard repeat delay/rate in ImGuiIO. +// The code assume a mono-space font for simplicity! +// If you don't use the default font, use ImGui::PushFont()/PopFont() to switch to a mono-space font +// before calling this. +// +// Usage: +// // Create a window and draw memory editor inside it: +// static MemoryEditor mem_edit_1; +// static char data[0x10000]; +// size_t data_size = 0x10000; +// mem_edit_1.DrawWindow("Memory Editor", data, data_size); +// +// Usage: +// // If you already have a window, use DrawContents() instead: +// static MemoryEditor mem_edit_2; +// ImGui::Begin("MyWindow") +// mem_edit_2.DrawContents(this, sizeof(*this), (size_t)this); +// ImGui::End(); +// +// Changelog: +// - v0.10: initial version +// - v0.23 (2017/08/17): added to github. fixed right-arrow triggering a byte write. +// - v0.24 (2018/06/02): changed DragInt("Rows" to use a %d data format (which is desirable since +// imgui 1.61). +// - v0.25 (2018/07/11): fixed wording: all occurrences of "Rows" renamed to "Columns". +// - v0.26 (2018/08/02): fixed clicking on hex region +// - v0.30 (2018/08/02): added data preview for common data types +// - v0.31 (2018/10/10): added OptUpperCaseHex option to select lower/upper casing display +// [@samhocevar] +// - v0.32 (2018/10/10): changed signatures to use void* instead of unsigned char* +// - v0.33 (2018/10/10): added OptShowOptions option to hide all the interactive option setting. +// - v0.34 (2019/05/07): binary preview now applies endianness setting [@nicolasnoble] +// - v0.35 (2020/01/29): using ImGuiDataType available since Dear ImGui 1.69. +// - v0.36 (2020/05/05): minor tweaks, minor refactor. +// - v0.40 (2020/10/04): fix misuse of ImGuiListClipper API, broke with Dear ImGui 1.79. made cursor +// position appears on left-side of edit box. option popup appears on mouse release. fix MSVC +// warnings where _CRT_SECURE_NO_WARNINGS wasn't working in recent versions. +// - v0.41 (2020/10/05): fix when using with keyboard/gamepad navigation enabled. +// - v0.42 (2020/10/14): fix for . character in ASCII view always being greyed out. +// - v0.43 (2021/03/12): added OptFooterExtraHeight to allow for custom drawing at the bottom of the +// editor [@leiradel] +// - v0.44 (2021/03/12): use ImGuiInputTextFlags_AlwaysOverwrite in 1.82 + fix hardcoded width. +// - v0.50 (2021/11/12): various fixes for recent dear imgui versions (fixed misuse of clipper, +// relying on SetKeyboardFocusHere() handling scrolling from 1.85). added default size. +// - v0.51 (2024/02/22): fix for layout change in 1.89 when using IMGUI_DISABLE_OBSOLETE_FUNCTIONS. +// (#34) +// - v0.52 (2024/03/08): removed unnecessary GetKeyIndex() calls, they are a no-op since 1.87. +// - v0.53 (2024/05/27): fixed right-click popup from not appearing when using DrawContents(). +// warning fixes. (#35) +// - v0.54 (2024/07/29): allow ReadOnly mode to still select and preview data. (#46) [@DeltaGW2]) +// - v0.55 (2024/08/19): added BgColorFn to allow setting background colors independently from +// highlighted selection. (#27) [@StrikerX3] +// added MouseHoveredAddr public readable field. (#47, #27) [@StrikerX3] +// fixed a data preview crash with 1.91.0 WIP. fixed contiguous highlight +// color when using data preview. *BREAKING* added UserData field passed to +// all optional function handlers: ReadFn, WriteFn, HighlightFn, BgColorFn. +// (#50) [@silverweed] +// +// TODO: +// - This is generally old/crappy code, it should work but isn't very good.. to be rewritten some +// day. +// - PageUp/PageDown are not supported because we use _NoNav. This is a good test scenario for +// working out idioms of how to mix natural nav and our own... +// - Arrows are being sent to the InputText() about to disappear which for LeftArrow makes the text +// cursor appear at position 1 for one frame. +// - Using InputText() is awkward and maybe overkill here, consider implementing something custom. + +#pragma once + +#include // uint8_t, etc. +#include // sprintf, scanf + +#if defined(_MSC_VER) || defined(_UCRT) +#define _PRISizeT "I" +#define ImSnprintf _snprintf +#else +#define _PRISizeT "z" +#define ImSnprintf snprintf +#endif + +#if defined(_MSC_VER) || defined(_UCRT) +#pragma warning(push) +#pragma warning( \ + disable : 4996) // warning C4996: 'sprintf': This function or variable may be unsafe. +#endif + +struct MemoryEditor { + enum DataFormat { + DataFormat_Bin = 0, + DataFormat_Dec = 1, + DataFormat_Hex = 2, + DataFormat_COUNT + }; + + // Settings + bool Open; // = true // set to false when DrawWindow() was closed. ignore if not using + // DrawWindow(). + bool ReadOnly; // = false // disable any editing. + int Cols; // = 16 // number of columns to display. + bool OptShowOptions; // = true // display options button/context menu. when disabled, options + // will be locked unless you provide your own UI for them. + bool OptShowDataPreview; // = false // display a footer previewing the decimal/binary/hex/float + // representation of the currently selected bytes. + bool OptShowHexII; // = false // display values in HexII representation instead of regular + // hexadecimal: hide null/zero bytes, ascii values as ".X". + bool OptShowAscii; // = true // display ASCII representation on the right side. + bool OptGreyOutZeroes; // = true // display null/zero bytes using the TextDisabled color. + bool OptUpperCaseHex; // = true // display hexadecimal values as "FF" instead of "ff". + int OptMidColsCount; // = 8 // set to 0 to disable extra spacing between every mid-cols. + int OptAddrDigitsCount; // = 0 // number of addr digits to display (default calculated + // based on maximum displayed addr). + float OptFooterExtraHeight; // = 0 // space to reserve at the bottom of the widget to add + // custom widgets + ImU32 HighlightColor; // // background color of highlighted bytes. + + // Function handlers + ImU8 (*ReadFn)(const ImU8* mem, size_t off, + void* user_data); // = 0 // optional handler to read bytes. + void (*WriteFn)(ImU8* mem, size_t off, ImU8 d, + void* user_data); // = 0 // optional handler to write bytes. + bool (*HighlightFn)(const ImU8* mem, size_t off, + void* user_data); // = 0 // optional handler to return Highlight + // property (to support non-contiguous highlighting). + ImU32 (*BgColorFn)(const ImU8* mem, size_t off, + void* user_data); // = 0 // optional handler to return custom background + // color of individual bytes. + void* UserData; // = NULL // user data forwarded to the function handlers + + // Public read-only data + bool MouseHovered; // set when mouse is hovering a value. + size_t MouseHoveredAddr; // the address currently being hovered if MouseHovered is set. + + // [Internal State] + bool ContentsWidthChanged; + size_t DataPreviewAddr; + size_t DataEditingAddr; + bool DataEditingTakeFocus; + char DataInputBuf[32]; + char AddrInputBuf[32]; + size_t GotoAddr; + size_t HighlightMin, HighlightMax; + int PreviewEndianness; + ImGuiDataType PreviewDataType; + + MemoryEditor() { + // Settings + Open = true; + ReadOnly = false; + Cols = 16; + OptShowOptions = true; + OptShowDataPreview = false; + OptShowHexII = false; + OptShowAscii = true; + OptGreyOutZeroes = true; + OptUpperCaseHex = true; + OptMidColsCount = 8; + OptAddrDigitsCount = 0; + OptFooterExtraHeight = 0.0f; + HighlightColor = IM_COL32(255, 255, 255, 50); + ReadFn = nullptr; + WriteFn = nullptr; + HighlightFn = nullptr; + BgColorFn = nullptr; + UserData = nullptr; + + // State/Internals + ContentsWidthChanged = false; + DataPreviewAddr = DataEditingAddr = (size_t)-1; + DataEditingTakeFocus = false; + memset(DataInputBuf, 0, sizeof(DataInputBuf)); + memset(AddrInputBuf, 0, sizeof(AddrInputBuf)); + GotoAddr = (size_t)-1; + MouseHovered = false; + MouseHoveredAddr = 0; + HighlightMin = HighlightMax = (size_t)-1; + PreviewEndianness = 0; + PreviewDataType = ImGuiDataType_S32; + } + + void GotoAddrAndHighlight(size_t addr_min, size_t addr_max) { + GotoAddr = addr_min; + HighlightMin = addr_min; + HighlightMax = addr_max; + } + + struct Sizes { + int AddrDigitsCount; + float LineHeight; + float GlyphWidth; + float HexCellWidth; + float SpacingBetweenMidCols; + float PosHexStart; + float PosHexEnd; + float PosAsciiStart; + float PosAsciiEnd; + float WindowWidth; + + Sizes() { + memset(this, 0, sizeof(*this)); + } + }; + + void CalcSizes(Sizes& s, size_t mem_size, size_t base_display_addr) { + ImGuiStyle& style = ImGui::GetStyle(); + s.AddrDigitsCount = OptAddrDigitsCount; + if (s.AddrDigitsCount == 0) + for (size_t n = base_display_addr + mem_size - 1; n > 0; n >>= 4) + s.AddrDigitsCount++; + s.LineHeight = ImGui::GetTextLineHeight(); + s.GlyphWidth = ImGui::CalcTextSize("F").x + 1; // We assume the font is mono-space + s.HexCellWidth = + (float)(int)(s.GlyphWidth * 2.5f); // "FF " we include trailing space in the width to + // easily catch clicks everywhere + s.SpacingBetweenMidCols = + (float)(int)(s.HexCellWidth * + 0.25f); // Every OptMidColsCount columns we add a bit of extra spacing + s.PosHexStart = (s.AddrDigitsCount + 2) * s.GlyphWidth; + s.PosHexEnd = s.PosHexStart + (s.HexCellWidth * Cols); + s.PosAsciiStart = s.PosAsciiEnd = s.PosHexEnd; + if (OptShowAscii) { + s.PosAsciiStart = s.PosHexEnd + s.GlyphWidth * 1; + if (OptMidColsCount > 0) + s.PosAsciiStart += (float)((Cols + OptMidColsCount - 1) / OptMidColsCount) * + s.SpacingBetweenMidCols; + s.PosAsciiEnd = s.PosAsciiStart + Cols * s.GlyphWidth; + } + s.WindowWidth = + s.PosAsciiEnd + style.ScrollbarSize + style.WindowPadding.x * 2 + s.GlyphWidth; + } + + // Standalone Memory Editor window + void DrawWindow(const char* title, void* mem_data, size_t mem_size, + size_t base_display_addr = 0x0000) { + Sizes s; + CalcSizes(s, mem_size, base_display_addr); + ImGui::SetNextWindowSize(ImVec2(s.WindowWidth, s.WindowWidth * 0.60f), + ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(s.WindowWidth, FLT_MAX)); + + Open = true; + if (ImGui::Begin(title, &Open, ImGuiWindowFlags_NoScrollbar)) { + DrawContents(mem_data, mem_size, base_display_addr); + if (ContentsWidthChanged) { + CalcSizes(s, mem_size, base_display_addr); + ImGui::SetWindowSize(ImVec2(s.WindowWidth, ImGui::GetWindowSize().y)); + } + } + ImGui::End(); + } + + // Memory Editor contents only + void DrawContents(void* mem_data_void, size_t mem_size, size_t base_display_addr = 0x0000) { + if (Cols < 1) + Cols = 1; + + ImU8* mem_data = (ImU8*)mem_data_void; + Sizes s; + CalcSizes(s, mem_size, base_display_addr); + ImGuiStyle& style = ImGui::GetStyle(); + + const ImVec2 contents_pos_start = ImGui::GetCursorScreenPos(); + + // We begin into our scrolling region with the 'ImGuiWindowFlags_NoMove' in order to prevent + // click from moving the window. This is used as a facility since our main click detection + // code doesn't assign an ActiveId so the click would normally be caught as a window-move. + const float height_separator = style.ItemSpacing.y; + float footer_height = OptFooterExtraHeight; + if (OptShowOptions) + footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1; + if (OptShowDataPreview) + footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1 + + ImGui::GetTextLineHeightWithSpacing() * 3; + ImGui::BeginChild("##scrolling", ImVec2(-FLT_MIN, -footer_height), ImGuiChildFlags_None, + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); + + // We are not really using the clipper API correctly here, because we rely on + // visible_start_addr/visible_end_addr for our scrolling function. + const int line_total_count = (int)((mem_size + Cols - 1) / Cols); + ImGuiListClipper clipper; + clipper.Begin(line_total_count, s.LineHeight); + + bool data_next = false; + + if (DataEditingAddr >= mem_size) + DataEditingAddr = (size_t)-1; + if (DataPreviewAddr >= mem_size) + DataPreviewAddr = (size_t)-1; + + size_t preview_data_type_size = OptShowDataPreview ? DataTypeGetSize(PreviewDataType) : 0; + + size_t data_editing_addr_next = (size_t)-1; + if (DataEditingAddr != (size_t)-1) { + // Move cursor but only apply on next frame so scrolling with be synchronized (because + // currently we can't change the scrolling while the window is being rendered) + if (ImGui::IsKeyPressed(ImGuiKey_UpArrow) && + (ptrdiff_t)DataEditingAddr >= (ptrdiff_t)Cols) { + data_editing_addr_next = DataEditingAddr - Cols; + } else if (ImGui::IsKeyPressed(ImGuiKey_DownArrow) && + (ptrdiff_t)DataEditingAddr < (ptrdiff_t)mem_size - Cols) { + data_editing_addr_next = DataEditingAddr + Cols; + } else if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow) && + (ptrdiff_t)DataEditingAddr > (ptrdiff_t)0) { + data_editing_addr_next = DataEditingAddr - 1; + } else if (ImGui::IsKeyPressed(ImGuiKey_RightArrow) && + (ptrdiff_t)DataEditingAddr < (ptrdiff_t)mem_size - 1) { + data_editing_addr_next = DataEditingAddr + 1; + } + } + + // Draw vertical separator + ImVec2 window_pos = ImGui::GetWindowPos(); + if (OptShowAscii) + draw_list->AddLine( + ImVec2(window_pos.x + s.PosAsciiStart - s.GlyphWidth, window_pos.y), + ImVec2(window_pos.x + s.PosAsciiStart - s.GlyphWidth, window_pos.y + 9999), + ImGui::GetColorU32(ImGuiCol_Border)); + + const ImU32 color_text = ImGui::GetColorU32(ImGuiCol_Text); + const ImU32 color_disabled = + OptGreyOutZeroes ? ImGui::GetColorU32(ImGuiCol_TextDisabled) : color_text; + + const char* format_address = + OptUpperCaseHex ? "%0*" _PRISizeT "X: " : "%0*" _PRISizeT "x: "; + const char* format_data = OptUpperCaseHex ? "%0*" _PRISizeT "X" : "%0*" _PRISizeT "x"; + const char* format_byte = OptUpperCaseHex ? "%02X" : "%02x"; + const char* format_byte_space = OptUpperCaseHex ? "%02X " : "%02x "; + + MouseHovered = false; + MouseHoveredAddr = 0; + + while (clipper.Step()) + for (int line_i = clipper.DisplayStart; line_i < clipper.DisplayEnd; + line_i++) // display only visible lines + { + size_t addr = (size_t)line_i * Cols; + ImGui::Text(format_address, s.AddrDigitsCount, base_display_addr + addr); + + // Draw Hexadecimal + for (int n = 0; n < Cols && addr < mem_size; n++, addr++) { + float byte_pos_x = s.PosHexStart + s.HexCellWidth * n; + if (OptMidColsCount > 0) + byte_pos_x += (float)(n / OptMidColsCount) * s.SpacingBetweenMidCols; + ImGui::SameLine(byte_pos_x); + + // Draw highlight or custom background color + const bool is_highlight_from_user_range = + (addr >= HighlightMin && addr < HighlightMax); + const bool is_highlight_from_user_func = + (HighlightFn && HighlightFn(mem_data, addr, UserData)); + const bool is_highlight_from_preview = + (addr >= DataPreviewAddr && + addr < DataPreviewAddr + preview_data_type_size); + + ImU32 bg_color = 0; + bool is_next_byte_highlighted = false; + if (is_highlight_from_user_range || is_highlight_from_user_func || + is_highlight_from_preview) { + is_next_byte_highlighted = + (addr + 1 < mem_size) && + ((HighlightMax != (size_t)-1 && addr + 1 < HighlightMax) || + (HighlightFn && HighlightFn(mem_data, addr + 1, UserData)) || + (addr + 1 < DataPreviewAddr + preview_data_type_size)); + bg_color = HighlightColor; + } else if (BgColorFn != nullptr) { + is_next_byte_highlighted = + (addr + 1 < mem_size) && + ((BgColorFn(mem_data, addr + 1, UserData) & IM_COL32_A_MASK) != 0); + bg_color = BgColorFn(mem_data, addr, UserData); + } + if (bg_color != 0) { + float bg_width = s.GlyphWidth * 2; + if (is_next_byte_highlighted || (n + 1 == Cols)) { + bg_width = s.HexCellWidth; + if (OptMidColsCount > 0 && n > 0 && (n + 1) < Cols && + ((n + 1) % OptMidColsCount) == 0) + bg_width += s.SpacingBetweenMidCols; + } + ImVec2 pos = ImGui::GetCursorScreenPos(); + draw_list->AddRectFilled( + pos, ImVec2(pos.x + bg_width, pos.y + s.LineHeight), bg_color); + } + + if (DataEditingAddr == addr) { + // Display text input on current byte + bool data_write = false; + ImGui::PushID((void*)addr); + if (DataEditingTakeFocus) { + ImGui::SetKeyboardFocusHere(0); + ImSnprintf(AddrInputBuf, 32, format_data, s.AddrDigitsCount, + base_display_addr + addr); + ImSnprintf(DataInputBuf, 32, format_byte, + ReadFn ? ReadFn(mem_data, addr, UserData) : mem_data[addr]); + } + struct InputTextUserData { + // FIXME: We should have a way to retrieve the text edit cursor position + // more easily in the API, this is rather tedious. This is such a ugly + // mess we may be better off not using InputText() at all here. + static int Callback(ImGuiInputTextCallbackData* data) { + InputTextUserData* user_data = (InputTextUserData*)data->UserData; + if (!data->HasSelection()) + user_data->CursorPos = data->CursorPos; +#if IMGUI_VERSION_NUM < 19102 + if (data->Flags & ImGuiInputTextFlags_ReadOnly) + return 0; +#endif + if (data->SelectionStart == 0 && + data->SelectionEnd == data->BufTextLen) { + // When not editing a byte, always refresh its InputText content + // pulled from underlying memory data (this is a bit tricky, + // since InputText technically "owns" the master copy of the + // buffer we edit it in there) + data->DeleteChars(0, data->BufTextLen); + data->InsertChars(0, user_data->CurrentBufOverwrite); + data->SelectionStart = 0; + data->SelectionEnd = 2; + data->CursorPos = 0; + } + return 0; + } + char CurrentBufOverwrite[3]; // Input + int CursorPos; // Output + }; + InputTextUserData input_text_user_data; + input_text_user_data.CursorPos = -1; + ImSnprintf(input_text_user_data.CurrentBufOverwrite, 3, format_byte, + ReadFn ? ReadFn(mem_data, addr, UserData) : mem_data[addr]); + ImGuiInputTextFlags flags = ImGuiInputTextFlags_CharsHexadecimal | + ImGuiInputTextFlags_EnterReturnsTrue | + ImGuiInputTextFlags_AutoSelectAll | + ImGuiInputTextFlags_NoHorizontalScroll | + ImGuiInputTextFlags_CallbackAlways; + if (ReadOnly) + flags |= ImGuiInputTextFlags_ReadOnly; + flags |= + ImGuiInputTextFlags_AlwaysOverwrite; // was + // ImGuiInputTextFlags_AlwaysInsertMode + ImGui::SetNextItemWidth(s.GlyphWidth * 2); + if (ImGui::InputText("##data", DataInputBuf, IM_ARRAYSIZE(DataInputBuf), + flags, InputTextUserData::Callback, + &input_text_user_data)) + data_write = data_next = true; + else if (!DataEditingTakeFocus && !ImGui::IsItemActive()) + DataEditingAddr = data_editing_addr_next = (size_t)-1; + DataEditingTakeFocus = false; + if (input_text_user_data.CursorPos >= 2) + data_write = data_next = true; + if (data_editing_addr_next != (size_t)-1) + data_write = data_next = false; + unsigned int data_input_value = 0; + if (!ReadOnly && data_write && + sscanf(DataInputBuf, "%X", &data_input_value) == 1) { + if (WriteFn) + WriteFn(mem_data, addr, (ImU8)data_input_value, UserData); + else + mem_data[addr] = (ImU8)data_input_value; + } + ImGui::PopID(); + } else { + // NB: The trailing space is not visible but ensure there's no gap that the + // mouse cannot click on. + ImU8 b = ReadFn ? ReadFn(mem_data, addr, UserData) : mem_data[addr]; + + if (OptShowHexII) { + if ((b >= 32 && b < 128)) + ImGui::Text(".%c ", b); + else if (b == 0xFF && OptGreyOutZeroes) + ImGui::TextDisabled("## "); + else if (b == 0x00) + ImGui::Text(" "); + else + ImGui::Text(format_byte_space, b); + } else { + if (b == 0 && OptGreyOutZeroes) + ImGui::TextDisabled("00 "); + else + ImGui::Text(format_byte_space, b); + } + if (ImGui::IsItemHovered()) { + MouseHovered = true; + MouseHoveredAddr = addr; + if (ImGui::IsMouseClicked(0)) { + DataEditingTakeFocus = true; + data_editing_addr_next = addr; + } + } + } + } + + if (OptShowAscii) { + // Draw ASCII values + ImGui::SameLine(s.PosAsciiStart); + ImVec2 pos = ImGui::GetCursorScreenPos(); + addr = (size_t)line_i * Cols; + + const float mouse_off_x = ImGui::GetIO().MousePos.x - pos.x; + const size_t mouse_addr = + (mouse_off_x >= 0.0f && mouse_off_x < s.PosAsciiEnd - s.PosAsciiStart) + ? addr + (size_t)(mouse_off_x / s.GlyphWidth) + : (size_t)-1; + + ImGui::PushID(line_i); + if (ImGui::InvisibleButton( + "ascii", ImVec2(s.PosAsciiEnd - s.PosAsciiStart, s.LineHeight))) { + DataEditingAddr = DataPreviewAddr = mouse_addr; + DataEditingTakeFocus = true; + } + if (ImGui::IsItemHovered()) { + MouseHovered = true; + MouseHoveredAddr = mouse_addr; + } + ImGui::PopID(); + for (int n = 0; n < Cols && addr < mem_size; n++, addr++) { + if (addr == DataEditingAddr) { + draw_list->AddRectFilled( + pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), + ImGui::GetColorU32(ImGuiCol_FrameBg)); + draw_list->AddRectFilled( + pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), + ImGui::GetColorU32(ImGuiCol_TextSelectedBg)); + } else if (BgColorFn) { + draw_list->AddRectFilled( + pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), + BgColorFn(mem_data, addr, UserData)); + } + unsigned char c = + ReadFn ? ReadFn(mem_data, addr, UserData) : mem_data[addr]; + char display_c = (c < 32 || c >= 128) ? '.' : c; + draw_list->AddText(pos, (display_c == c) ? color_text : color_disabled, + &display_c, &display_c + 1); + pos.x += s.GlyphWidth; + } + } + } + ImGui::PopStyleVar(2); + const float child_width = ImGui::GetWindowSize().x; + ImGui::EndChild(); + + // Notify the main window of our ideal child content size (FIXME: we are missing an API to + // get the contents size from the child) + ImGui::SetCursorPosX(s.WindowWidth); + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + + if (data_next && DataEditingAddr + 1 < mem_size) { + DataEditingAddr = DataPreviewAddr = DataEditingAddr + 1; + DataEditingTakeFocus = true; + } else if (data_editing_addr_next != (size_t)-1) { + DataEditingAddr = DataPreviewAddr = data_editing_addr_next; + DataEditingTakeFocus = true; + } + + const bool lock_show_data_preview = OptShowDataPreview; + if (OptShowOptions) { + ImGui::Separator(); + DrawOptionsLine(s, mem_data, mem_size, base_display_addr); + } + + if (lock_show_data_preview) { + ImGui::Separator(); + DrawPreviewLine(s, mem_data, mem_size, base_display_addr); + } + + const ImVec2 contents_pos_end(contents_pos_start.x + child_width, + ImGui::GetCursorScreenPos().y); + // ImGui::GetForegroundDrawList()->AddRect(contents_pos_start, contents_pos_end, + // IM_COL32(255, 0, 0, 255)); + if (OptShowOptions) + if (ImGui::IsMouseHoveringRect(contents_pos_start, contents_pos_end)) + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) && + ImGui::IsMouseReleased(ImGuiMouseButton_Right)) + ImGui::OpenPopup("OptionsPopup"); + + if (ImGui::BeginPopup("OptionsPopup")) { + ImGui::SetNextItemWidth(s.GlyphWidth * 7 + style.FramePadding.x * 2.0f); + if (ImGui::DragInt("##cols", &Cols, 0.2f, 4, 32, "%d cols")) { + ContentsWidthChanged = true; + if (Cols < 1) + Cols = 1; + } + ImGui::Checkbox("Show Data Preview", &OptShowDataPreview); + ImGui::Checkbox("Show HexII", &OptShowHexII); + if (ImGui::Checkbox("Show Ascii", &OptShowAscii)) { + ContentsWidthChanged = true; + } + ImGui::Checkbox("Grey out zeroes", &OptGreyOutZeroes); + ImGui::Checkbox("Uppercase Hex", &OptUpperCaseHex); + + ImGui::EndPopup(); + } + } + + void DrawOptionsLine(const Sizes& s, void* mem_data, size_t mem_size, + size_t base_display_addr) { + IM_UNUSED(mem_data); + ImGuiStyle& style = ImGui::GetStyle(); + const char* format_range = OptUpperCaseHex ? "Range %0*" _PRISizeT "X..%0*" _PRISizeT "X" + : "Range %0*" _PRISizeT "x..%0*" _PRISizeT "x"; + + // Options menu + if (ImGui::Button("Options")) + ImGui::OpenPopup("OptionsPopup"); + + ImGui::SameLine(); + ImGui::Text(format_range, s.AddrDigitsCount, base_display_addr, s.AddrDigitsCount, + base_display_addr + mem_size - 1); + ImGui::SameLine(); + ImGui::SetNextItemWidth((s.AddrDigitsCount + 1) * s.GlyphWidth + + style.FramePadding.x * 2.0f); + if (ImGui::InputText("##addr", AddrInputBuf, IM_ARRAYSIZE(AddrInputBuf), + ImGuiInputTextFlags_CharsHexadecimal | + ImGuiInputTextFlags_EnterReturnsTrue)) { + size_t goto_addr; + if (sscanf(AddrInputBuf, "%" _PRISizeT "X", &goto_addr) == 1) { + GotoAddr = goto_addr - base_display_addr; + HighlightMin = HighlightMax = (size_t)-1; + } + } + + if (GotoAddr != (size_t)-1) { + if (GotoAddr < mem_size) { + ImGui::BeginChild("##scrolling"); + ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + + (GotoAddr / Cols) * ImGui::GetTextLineHeight()); + ImGui::EndChild(); + DataEditingAddr = DataPreviewAddr = GotoAddr; + DataEditingTakeFocus = true; + } + GotoAddr = (size_t)-1; + } + + // if (MouseHovered) + //{ + // ImGui::SameLine(); + // ImGui::Text("Hovered: %p", MouseHoveredAddr); + // } + } + + void DrawPreviewLine(const Sizes& s, void* mem_data_void, size_t mem_size, + size_t base_display_addr) { + IM_UNUSED(base_display_addr); + ImU8* mem_data = (ImU8*)mem_data_void; + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::AlignTextToFramePadding(); + ImGui::Text("Preview as:"); + ImGui::SameLine(); + ImGui::SetNextItemWidth((s.GlyphWidth * 10.0f) + style.FramePadding.x * 2.0f + + style.ItemInnerSpacing.x); + + static const ImGuiDataType supported_data_types[] = { + ImGuiDataType_S8, ImGuiDataType_U8, ImGuiDataType_S16, ImGuiDataType_U16, + ImGuiDataType_S32, ImGuiDataType_U32, ImGuiDataType_S64, ImGuiDataType_U64, + ImGuiDataType_Float, ImGuiDataType_Double}; + if (ImGui::BeginCombo("##combo_type", DataTypeGetDesc(PreviewDataType), + ImGuiComboFlags_HeightLargest)) { + for (int n = 0; n < IM_ARRAYSIZE(supported_data_types); n++) { + ImGuiDataType data_type = supported_data_types[n]; + if (ImGui::Selectable(DataTypeGetDesc(data_type), PreviewDataType == data_type)) + PreviewDataType = data_type; + } + ImGui::EndCombo(); + } + ImGui::SameLine(); + ImGui::SetNextItemWidth((s.GlyphWidth * 6.0f) + style.FramePadding.x * 2.0f + + style.ItemInnerSpacing.x); + ImGui::Combo("##combo_endianness", &PreviewEndianness, "LE\0BE\0\0"); + + char buf[128] = ""; + float x = s.GlyphWidth * 6.0f; + bool has_value = DataPreviewAddr != (size_t)-1; + if (has_value) + DrawPreviewData(DataPreviewAddr, mem_data, mem_size, PreviewDataType, DataFormat_Dec, + buf, (size_t)IM_ARRAYSIZE(buf)); + ImGui::Text("Dec"); + ImGui::SameLine(x); + ImGui::TextUnformatted(has_value ? buf : "N/A"); + if (has_value) + DrawPreviewData(DataPreviewAddr, mem_data, mem_size, PreviewDataType, DataFormat_Hex, + buf, (size_t)IM_ARRAYSIZE(buf)); + ImGui::Text("Hex"); + ImGui::SameLine(x); + ImGui::TextUnformatted(has_value ? buf : "N/A"); + if (has_value) + DrawPreviewData(DataPreviewAddr, mem_data, mem_size, PreviewDataType, DataFormat_Bin, + buf, (size_t)IM_ARRAYSIZE(buf)); + buf[IM_ARRAYSIZE(buf) - 1] = 0; + ImGui::Text("Bin"); + ImGui::SameLine(x); + ImGui::TextUnformatted(has_value ? buf : "N/A"); + } + + // Utilities for Data Preview (since we don't access imgui_internal.h) + // FIXME: This technically depends on ImGuiDataType order. + const char* DataTypeGetDesc(ImGuiDataType data_type) const { + const char* descs[] = {"Int8", "Uint8", "Int16", "Uint16", "Int32", + "Uint32", "Int64", "Uint64", "Float", "Double"}; + IM_ASSERT(data_type >= 0 && data_type < IM_ARRAYSIZE(descs)); + return descs[data_type]; + } + + size_t DataTypeGetSize(ImGuiDataType data_type) const { + const size_t sizes[] = {1, 1, 2, 2, 4, 4, 8, 8, sizeof(float), sizeof(double)}; + IM_ASSERT(data_type >= 0 && data_type < IM_ARRAYSIZE(sizes)); + return sizes[data_type]; + } + + const char* DataFormatGetDesc(DataFormat data_format) const { + const char* descs[] = {"Bin", "Dec", "Hex"}; + IM_ASSERT(data_format >= 0 && data_format < DataFormat_COUNT); + return descs[data_format]; + } + + bool IsBigEndian() const { + uint16_t x = 1; + char c[2]; + memcpy(c, &x, 2); + return c[0] != 0; + } + + static void* EndiannessCopyBigEndian(void* _dst, void* _src, size_t s, int is_little_endian) { + if (is_little_endian) { + uint8_t* dst = (uint8_t*)_dst; + uint8_t* src = (uint8_t*)_src + s - 1; + for (int i = 0, n = (int)s; i < n; ++i) + memcpy(dst++, src--, 1); + return _dst; + } else { + return memcpy(_dst, _src, s); + } + } + + static void* EndiannessCopyLittleEndian(void* _dst, void* _src, size_t s, + int is_little_endian) { + if (is_little_endian) { + return memcpy(_dst, _src, s); + } else { + uint8_t* dst = (uint8_t*)_dst; + uint8_t* src = (uint8_t*)_src + s - 1; + for (int i = 0, n = (int)s; i < n; ++i) + memcpy(dst++, src--, 1); + return _dst; + } + } + + void* EndiannessCopy(void* dst, void* src, size_t size) const { + static void* (*fp)(void*, void*, size_t, int) = nullptr; + if (fp == nullptr) + fp = IsBigEndian() ? EndiannessCopyBigEndian : EndiannessCopyLittleEndian; + return fp(dst, src, size, PreviewEndianness); + } + + const char* FormatBinary(const uint8_t* buf, int width) const { + IM_ASSERT(width <= 64); + size_t out_n = 0; + static char out_buf[64 + 8 + 1]; + int n = width / 8; + for (int j = n - 1; j >= 0; --j) { + for (int i = 0; i < 8; ++i) + out_buf[out_n++] = (buf[j] & (1 << (7 - i))) ? '1' : '0'; + out_buf[out_n++] = ' '; + } + IM_ASSERT(out_n < IM_ARRAYSIZE(out_buf)); + out_buf[out_n] = 0; + return out_buf; + } + + // [Internal] + void DrawPreviewData(size_t addr, const ImU8* mem_data, size_t mem_size, + ImGuiDataType data_type, DataFormat data_format, char* out_buf, + size_t out_buf_size) const { + uint8_t buf[8]; + size_t elem_size = DataTypeGetSize(data_type); + size_t size = addr + elem_size > mem_size ? mem_size - addr : elem_size; + if (ReadFn) + for (int i = 0, n = (int)size; i < n; ++i) + buf[i] = ReadFn(mem_data, addr + i, UserData); + else + memcpy(buf, mem_data + addr, size); + + if (data_format == DataFormat_Bin) { + uint8_t binbuf[8]; + EndiannessCopy(binbuf, buf, size); + ImSnprintf(out_buf, out_buf_size, "%s", FormatBinary(binbuf, (int)size * 8)); + return; + } + + out_buf[0] = 0; + switch (data_type) { + case ImGuiDataType_S8: { + int8_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%hhd", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%02x", data & 0xFF); + return; + } + break; + } + case ImGuiDataType_U8: { + uint8_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%hhu", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%02x", data & 0XFF); + return; + } + break; + } + case ImGuiDataType_S16: { + int16_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%hd", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%04x", data & 0xFFFF); + return; + } + break; + } + case ImGuiDataType_U16: { + uint16_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%hu", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%04x", data & 0xFFFF); + return; + } + break; + } + case ImGuiDataType_S32: { + int32_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%d", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%08x", data); + return; + } + break; + } + case ImGuiDataType_U32: { + uint32_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%u", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%08x", data); + return; + } + break; + } + case ImGuiDataType_S64: { + int64_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%lld", (long long)data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)data); + return; + } + break; + } + case ImGuiDataType_U64: { + uint64_t data = 0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%llu", (long long)data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)data); + return; + } + break; + } + case ImGuiDataType_Float: { + float data = 0.0f; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%f", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "%a", data); + return; + } + break; + } + case ImGuiDataType_Double: { + double data = 0.0; + EndiannessCopy(&data, buf, size); + if (data_format == DataFormat_Dec) { + ImSnprintf(out_buf, out_buf_size, "%f", data); + return; + } + if (data_format == DataFormat_Hex) { + ImSnprintf(out_buf, out_buf_size, "%a", data); + return; + } + break; + } + default: + case ImGuiDataType_COUNT: + break; + } // Switch + IM_ASSERT(0); // Shouldn't reach + } +}; + +#undef _PRISizeT +#undef ImSnprintf + +#ifdef _MSC_VER +#pragma warning(pop) +#endif \ No newline at end of file diff --git a/src/core/devtools/widget/reg_popup.cpp b/src/core/devtools/widget/reg_popup.cpp new file mode 100644 index 000000000..0633e76e6 --- /dev/null +++ b/src/core/devtools/widget/reg_popup.cpp @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "reg_popup.h" + +#include +#include +#include + +#include "cmd_list.h" +#include "common.h" +#include "imgui/imgui_std.h" + +using namespace ImGui; +using magic_enum::enum_name; + +namespace Core::Devtools::Widget { + +void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) { + if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + // clang-format off + + DrawValueRowList( + "BASE_ADDR", buffer.base_address, + "PITCH.TILE_MAX", buffer.pitch.tile_max, + "PITCH.FMASK_TILE_MAX", buffer.pitch.fmask_tile_max, + "SLICE.TILE_MAX", buffer.slice.tile_max, + "VIEW.SLICE_START", buffer.view.slice_start, + "VIEW.SLICE_MAX", buffer.view.slice_max + ); + + TableNextRow(); + TableNextColumn(); + if (TreeNode("Color0Info")) { + TableNextRow(); + TableNextColumn(); + ParseColor0Info(buffer.info.u32all, false); + TreePop(); + } + + TableNextRow(); + TableNextColumn(); + if (TreeNode("Color0Attrib")) { + TableNextRow(); + TableNextColumn(); + ParseColor0Attrib(buffer.attrib.u32all, false); + TreePop(); + } + + TableNextRow(); + DrawValueRowList( + "CMASK_BASE_EXT", buffer.cmask_base_address, + "FMASK_BASE_EXT", buffer.fmask_base_address, + "FMASK_SLICE.TILE_MAX", buffer.fmask_slice.tile_max, + "CLEAR_WORD0", buffer.clear_word0, + "CLEAR_WORD1", buffer.clear_word1, + "Pitch()", buffer.Pitch(), + "Height()", buffer.Height(), + "Address()", buffer.Address(), + "CmaskAddress", buffer.CmaskAddress(), + "FmaskAddress", buffer.FmaskAddress(), + "NumSamples()", buffer.NumSamples(), + "NumSlices()", buffer.NumSlices(), + "GetColorSliceSize()", buffer.GetColorSliceSize(), + "GetTilingMode()", buffer.GetTilingMode(), + "IsTiled()", buffer.IsTiled(), + "NumFormat()", buffer.NumFormat() + ); + + // clang-format on + + EndTable(); + } +} + +void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) { + const auto& [depth_buffer, depth_control] = depth_data; + + SeparatorText("Depth buffer"); + + if (BeginTable("DEPTH_BUFFER", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + // clang-format off + DrawValueRowList( + "Z_INFO.FORMAT", depth_buffer.z_info.format, + "Z_INFO.NUM_SAMPLES", depth_buffer.z_info.num_samples, + "Z_INFO.TILE_SPLIT", depth_buffer.z_info.tile_split, + "Z_INFO.TILE_MODE_INDEX", depth_buffer.z_info.tile_mode_index, + "Z_INFO.DECOMPRESS_ON_N_ZPLANES", depth_buffer.z_info.decompress_on_n_zplanes, + "Z_INFO.ALLOW_EXPCLEAR", depth_buffer.z_info.allow_expclear, + "Z_INFO.READ_SIZE", depth_buffer.z_info.read_size, + "Z_INFO.TILE_SURFACE_EN", depth_buffer.z_info.tile_surface_en, + "Z_INFO.CLEAR_DISALLOWED", depth_buffer.z_info.clear_disallowed, + "Z_INFO.ZRANGE_PRECISION", depth_buffer.z_info.zrange_precision, + "STENCIL_INFO.FORMAT", depth_buffer.stencil_info.format, + "Z_READ_BASE", depth_buffer.z_read_base, + "STENCIL_READ_BASE", depth_buffer.stencil_read_base, + "Z_WRITE_BASE", depth_buffer.z_write_base, + "STENCIL_WRITE_BASE", depth_buffer.stencil_write_base, + "DEPTH_SIZE.PITCH_TILE_MAX", depth_buffer.depth_size.pitch_tile_max, + "DEPTH_SIZE.HEIGHT_TILE_MAX", depth_buffer.depth_size.height_tile_max, + "DEPTH_SLICE.TILE_MAX", depth_buffer.depth_slice.tile_max, + "Pitch()", depth_buffer.Pitch(), + "Height()", depth_buffer.Height(), + "Address()", depth_buffer.Address(), + "NumSamples()", depth_buffer.NumSamples(), + "NumBits()", depth_buffer.NumBits(), + "GetDepthSliceSize()", depth_buffer.GetDepthSliceSize() + ); + // clang-format on + + EndTable(); + } + SeparatorText("Depth control"); + if (BeginTable("DEPTH_CONTROL", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + // clang-format off + DrawValueRowList( + "STENCIL_ENABLE", depth_control.stencil_enable, + "DEPTH_ENABLE", depth_control.depth_enable, + "DEPTH_WRITE_ENABLE", depth_control.depth_write_enable, + "DEPTH_BOUNDS_ENABLE", depth_control.depth_bounds_enable, + "DEPTH_FUNC", depth_control.depth_func, + "BACKFACE_ENABLE", depth_control.backface_enable, + "STENCIL_FUNC", depth_control.stencil_ref_func, + "STENCIL_FUNC_BF", depth_control.stencil_bf_func, + "ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", depth_control.enable_color_writes_on_depth_fail, + "DISABLE_COLOR_WRITES_ON_DEPTH_PASS", depth_control.disable_color_writes_on_depth_pass + ); + // clang-format on + + EndTable(); + } +} + +RegPopup::RegPopup() { + static int unique_id = 0; + id = unique_id++; +} + +void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer, + u32 cb_id) { + this->data = color_buffer; + this->title = fmt::format("{}/CB #{}", base_title, cb_id); +} + +void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer, + AmdGpu::Liverpool::DepthControl depth_control) { + this->data = std::make_tuple(depth_buffer, depth_control); + this->title = fmt::format("{}/Depth", base_title); +} + +void RegPopup::SetPos(ImVec2 pos, bool auto_resize) { + char name[128]; + snprintf(name, sizeof(name), "%s###reg_popup_%d", title.c_str(), id); + Begin(name, &open, flags); + SetWindowPos(pos); + if (auto_resize) { + if (std::holds_alternative(data)) { + SetWindowSize({365.0f, 520.0f}); + KeepWindowInside(); + } else if (std::holds_alternative(data)) { + SetWindowSize({404.0f, 543.0f}); + KeepWindowInside(); + } + } + last_pos = GetWindowPos(); + moved = false; + End(); +} + +void RegPopup::Draw() { + char name[128]; + snprintf(name, sizeof(name), "%s###reg_popup_%d", title.c_str(), id); + if (Begin(name, &open, flags)) { + if (GetWindowPos() != last_pos) { + moved = true; + } + + if (const auto* buffer = std::get_if(&data)) { + DrawColorBuffer(*buffer); + } else if (const auto* depth_data = std::get_if(&data)) { + DrawDepthBuffer(*depth_data); + } + } + End(); +} +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/reg_popup.h b/src/core/devtools/widget/reg_popup.h new file mode 100644 index 000000000..9ccd60ac0 --- /dev/null +++ b/src/core/devtools/widget/reg_popup.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include + +#include "common/types.h" +#include "video_core/renderer_vulkan/liverpool_to_vk.h" + +namespace Core::Devtools::Widget { + +class RegPopup { + int id; + ImGuiWindowFlags flags{ImGuiWindowFlags_NoSavedSettings}; + + using DepthBuffer = std::tuple; + + ImVec2 last_pos; + std::variant data; + std::string title{}; + + static void DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer); + + static void DrawDepthBuffer(const DepthBuffer& depth_data); + +public: + bool open = false; + bool moved = false; + + RegPopup(); + + void SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer, + u32 cb_id); + + void SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer, + AmdGpu::Liverpool::DepthControl depth_control); + + void SetPos(ImVec2 pos, bool auto_resize = false); + + void Draw(); +}; + +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/reg_view.cpp b/src/core/devtools/widget/reg_view.cpp new file mode 100644 index 000000000..10cc88085 --- /dev/null +++ b/src/core/devtools/widget/reg_view.cpp @@ -0,0 +1,423 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "common/io_file.h" +#include "core/devtools/options.h" +#include "imgui/imgui_std.h" +#include "imgui_internal.h" +#include "reg_view.h" + +#if defined(_WIN32) +#define popen _popen +#define pclose _pclose +#endif + +using namespace ImGui; +using magic_enum::enum_name; + +constexpr auto depth_id = 0xF3; + +static std::optional exec_cli(const char* cli) { + std::array buffer{}; + std::string output; + const auto f = popen(cli, "r"); + if (!f) { + pclose(f); + return {}; + } + while (fgets(buffer.data(), buffer.size(), f)) { + output += buffer.data(); + } + pclose(f); + return output; +} + +namespace Core::Devtools::Widget { + +void RegView::ProcessShader(int shader_id) { + std::vector shader_code; + Vulkan::Liverpool::UserData user_data; + if (data.is_compute) { + shader_code = data.cs_data.code; + user_data = data.cs_data.cs_program.user_data; + } else { + const auto& s = data.stages[shader_id]; + shader_code = s.code; + user_data = s.user_data.user_data; + } + + std::string shader_dis; + + if (Options.disassembly_cli.empty()) { + shader_dis = "No disassembler set"; + } else { + auto bin_path = std::filesystem::temp_directory_path() / "shadps4_tmp_shader.bin"; + + constexpr std::string_view src_arg = "{src}"; + std::string cli = Options.disassembly_cli; + const auto pos = cli.find(src_arg); + if (pos == std::string::npos) { + DebugState.ShowDebugMessage("Disassembler CLI does not contain {src} argument"); + } else { + cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\""); + Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write); + file.Write(shader_code); + file.Close(); + + auto result = exec_cli(cli.c_str()); + shader_dis = result.value_or("Could not disassemble shader"); + if (shader_dis.empty()) { + shader_dis = "Disassembly empty or failed"; + } + + std::filesystem::remove(bin_path); + } + } + + MemoryEditor hex_view; + hex_view.Open = true; + hex_view.ReadOnly = true; + hex_view.Cols = 8; + hex_view.OptShowAscii = false; + hex_view.OptShowOptions = false; + + TextEditor dis_view; + dis_view.SetPalette(TextEditor::GetDarkPalette()); + dis_view.SetReadOnly(true); + dis_view.SetText(shader_dis); + + ShaderCache cache{ + .hex_view = hex_view, + .dis_view = dis_view, + .user_data = user_data, + }; + shader_decomp.emplace(shader_id, std::move(cache)); +} +void RegView::SelectShader(int id) { + selected_shader = id; + if (!shader_decomp.contains(id)) { + ProcessShader(id); + } +} + +void RegView::DrawComputeRegs() { + const auto& cs = data.cs_data.cs_program; + + if (BeginTable("CREGS", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + // clang-format off + DrawValueRowList( + "DISPATCH_INITIATOR", cs.dispatch_initiator, + "DIM_X", cs.dim_x, + "DIM_Y", cs.dim_y, + "DIM_Z", cs.dim_z, + "START_X", cs.start_x, + "START_Y", cs.start_y, + "START_Z", cs.start_z, + "NUM_THREAD_X.FULL", cs.num_thread_x.full, + "NUM_THREAD_X.PARTIAL", cs.num_thread_x.partial, + "NUM_THREAD_Y.FULL", cs.num_thread_y.full, + "NUM_THREAD_Y.PARTIAL", cs.num_thread_y.partial, + "NUM_THREAD_Z.FULL", cs.num_thread_z.full, + "NUM_THREAD_Z.PARTIAL", cs.num_thread_z.partial, + "MAX_WAVE_ID", cs.max_wave_id, + "SETTINGS.NUM_VGPRS", cs.settings.num_vgprs, + "SETTINGS.NUM_SGPRS", cs.settings.num_sgprs, + "SETTINGS.NUM_USER_REGS", cs.settings.num_user_regs, + "SETTINGS.TGID_ENABLE", cs.settings.tgid_enable, + "SETTINGS.LDS_DWORDS", cs.settings.lds_dwords, + "RESOURCE_LIMITS", cs.resource_limits + ); + // clang-format on + + EndTable(); + } +} + +void RegView::DrawGraphicsRegs() { + const auto& regs = data.regs; + + if (BeginTable("REGS", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + DrawValueRow("Primitive type", regs.primitive_type); + + const auto open_new_popup = [&](int cb, auto... args) { + const auto pos = GetItemRectMax() + ImVec2(5.0f, 0.0f); + if (GetIO().KeyShift) { + auto& pop = extra_reg_popup.emplace_back(); + pop.SetData(title, args...); + pop.open = true; + pop.SetPos(pos, true); + } else if (last_selected_cb == cb && default_reg_popup.open) { + default_reg_popup.open = false; + } else { + last_selected_cb = cb; + default_reg_popup.SetData(title, args...); + if (!default_reg_popup.open || !default_reg_popup.moved) { + default_reg_popup.open = true; + default_reg_popup.SetPos(pos, true); + } + } + }; + + for (int cb = 0; cb < AmdGpu::Liverpool::NumColorBuffers; ++cb) { + PushID(cb); + + TableNextRow(); + TableNextColumn(); + + const auto& buffer = regs.color_buffers[cb]; + + Text("Color buffer %d", cb); + TableNextColumn(); + if (!buffer || !regs.color_target_mask.GetMask(cb)) { + TextUnformatted("N/A"); + } else { + const char* text = last_selected_cb == cb && default_reg_popup.open ? "x" : "->"; + if (SmallButton(text)) { + open_new_popup(cb, buffer, cb); + } + } + + PopID(); + } + + TableNextRow(); + TableNextColumn(); + TextUnformatted("Depth buffer"); + TableNextColumn(); + if (regs.depth_buffer.Address() == 0 || !regs.depth_control.depth_enable) { + TextUnformatted("N/A"); + } else { + const char* text = last_selected_cb == depth_id && default_reg_popup.open ? "x" : "->"; + if (SmallButton(text)) { + open_new_popup(depth_id, regs.depth_buffer, regs.depth_control); + } + } + + auto& s = regs.screen_scissor; + DrawRow("Scissor", "(%d, %d, %d, %d)", s.top_left_x, s.top_left_y, s.bottom_right_x, + s.bottom_right_y); + + DrawValueRow("Color control", regs.color_control.mode); + + DrawRow("Primitive restart", "%X (IDX: %X)", regs.enable_primitive_restart & 1, + regs.primitive_restart_index); + // clang-format off + DrawValueRowList( + "Polygon mode", regs.polygon_control.PolyMode(), + "Cull mode", regs.polygon_control.CullingMode(), + "Clip Space", regs.clipper_control.clip_space, + "Front face", regs.polygon_control.front_face, + "Num Samples", regs.aa_config.NumSamples() + ); + // clang-format on + + EndTable(); + } +} + +RegView::RegView() { + static int unique_id = 0; + id = unique_id++; + + char name[128]; + snprintf(name, sizeof(name), "###reg_dump_%d", id); + SetNextWindowPos({400.0f, 200.0f}); + SetNextWindowSize({290.0f, 435.0f}); + ImGuiID root_dock_id; + Begin(name); + { + char dock_name[64]; + snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id); + root_dock_id = ImHashStr(dock_name); + DockSpace(root_dock_id); + } + End(); + + ImGuiID up1, down1; + + DockBuilderRemoveNodeChildNodes(root_dock_id); + DockBuilderSplitNode(root_dock_id, ImGuiDir_Up, 0.19f, &up1, &down1); + + snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id); + DockBuilderDockWindow(name, up1); + + snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id); + DockBuilderDockWindow(name, down1); + + snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id); + DockBuilderDockWindow(name, down1); + + DockBuilderFinish(root_dock_id); +} + +void RegView::SetData(DebugStateType::RegDump _data, const std::string& base_title, u32 batch_id) { + this->data = std::move(_data); + this->batch_id = batch_id; + this->title = fmt::format("{}/Batch {}", base_title, batch_id); + // clear cache + shader_decomp.clear(); + if (data.is_compute) { + selected_shader = -2; + last_selected_cb = -1; + default_reg_popup.open = false; + ProcessShader(-2); + } else { + const auto& regs = data.regs; + if (selected_shader >= 0 && !regs.stage_enable.IsStageEnabled(selected_shader)) { + selected_shader = -1; + } + if (default_reg_popup.open) { + default_reg_popup.open = false; + if (last_selected_cb == depth_id) { + const auto& has_depth = + regs.depth_buffer.Address() != 0 && regs.depth_control.depth_enable; + if (has_depth) { + default_reg_popup.SetData(title, regs.depth_buffer, regs.depth_control); + default_reg_popup.open = true; + } + } else if (last_selected_cb >= 0 && + last_selected_cb < AmdGpu::Liverpool::NumColorBuffers) { + const auto& buffer = regs.color_buffers[last_selected_cb]; + const bool has_cb = buffer && regs.color_target_mask.GetMask(last_selected_cb); + if (has_cb) { + default_reg_popup.SetData(title, buffer, last_selected_cb); + default_reg_popup.open = true; + } + } + } + } + extra_reg_popup.clear(); +} + +void RegView::SetPos(ImVec2 pos) { + char name[128]; + snprintf(name, sizeof(name), "%s###reg_dump_%d", title.c_str(), id); + Begin(name, &open, ImGuiWindowFlags_MenuBar); + SetWindowPos(pos); + KeepWindowInside(); + last_pos = GetWindowPos(); + moved = false; + End(); +} + +void RegView::Draw() { + char name[128]; + snprintf(name, sizeof(name), "%s###reg_dump_%d", title.c_str(), id); + + if (Begin(name, &open, ImGuiWindowFlags_MenuBar)) { + if (GetWindowPos() != last_pos) { + moved = true; + } + + const char* names[] = {"vs", "ps", "gs", "es", "hs", "ls"}; + + if (BeginMenuBar()) { + if (BeginMenu("Windows")) { + Checkbox("Registers", &show_registers); + Checkbox("User data", &show_user_data); + Checkbox("Disassembly", &show_disassembly); + ImGui::EndMenu(); + } + EndMenuBar(); + } + + if (!data.is_compute && + BeginChild("STAGES", {}, + ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY)) { + for (int i = 0; i < DebugStateType::RegDump::MaxShaderStages; i++) { + if (data.regs.stage_enable.IsStageEnabled(i)) { + const bool selected = selected_shader == i; + if (selected) { + PushStyleColor(ImGuiCol_Button, ImVec4{1.0f, 0.7f, 0.7f, 1.0f}); + } + if (Button(names[i], {40.0f, 40.0f})) { + SelectShader(i); + } + if (selected) { + PopStyleColor(); + } + } + SameLine(); + } + EndChild(); + } + } + char dock_name[64]; + snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id); + auto root_dock_id = ImHashStr(dock_name); + DockSpace(root_dock_id); + End(); + + auto get_shader = [&]() -> ShaderCache* { + auto shader_cache = shader_decomp.find(selected_shader); + if (shader_cache == shader_decomp.end()) { + return nullptr; + } + return &shader_cache->second; + }; + + if (show_user_data) { + snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id); + + if (Begin(name, &show_user_data, ImGuiWindowFlags_NoScrollbar)) { + auto shader = get_shader(); + if (!shader) { + Text("Stage not selected"); + } else { + shader->hex_view.DrawContents(shader->user_data.data(), shader->user_data.size()); + } + } + End(); + } + + if (show_disassembly) { + snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id); + if (Begin(name, &show_disassembly)) { + auto shader = get_shader(); + if (!shader) { + Text("Stage not selected"); + } else { + shader->dis_view.Render("Disassembly", GetContentRegionAvail()); + } + } + End(); + } + + if (show_registers) { + snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id); + if (Begin(name, &show_registers)) { + if (data.is_compute) { + DrawComputeRegs(); + } else { + DrawGraphicsRegs(); + } + } + End(); + } + + if (default_reg_popup.open) { + default_reg_popup.Draw(); + } + for (auto it = extra_reg_popup.begin(); it != extra_reg_popup.end();) { + if (!it->open) { + it = extra_reg_popup.erase(it); + continue; + } + it->Draw(); + ++it; + } +} + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/reg_view.h b/src/core/devtools/widget/reg_view.h new file mode 100644 index 000000000..3ac8ec077 --- /dev/null +++ b/src/core/devtools/widget/reg_view.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include "core/debug_state.h" +#include "imgui_memory_editor.h" +#include "reg_popup.h" +#include "text_editor.h" + +namespace Core::Devtools::Widget { + +struct ShaderCache { + MemoryEditor hex_view; + TextEditor dis_view; + Vulkan::Liverpool::UserData user_data; +}; + +class RegView { + int id; + + std::string title; + DebugStateType::RegDump data; + u32 batch_id{~0u}; + ImVec2 last_pos; + + std::unordered_map shader_decomp; + int selected_shader{-1}; + RegPopup default_reg_popup; + int last_selected_cb{-1}; + std::vector extra_reg_popup; + + bool show_registers{true}; + bool show_user_data{true}; + bool show_disassembly{true}; + + void ProcessShader(int shader_id); + + void SelectShader(int shader_id); + + void DrawComputeRegs(); + + void DrawGraphicsRegs(); + +public: + bool open = false; + bool moved = false; + + RegView(); + + void SetData(DebugStateType::RegDump data, const std::string& base_title, u32 batch_id); + + void SetPos(ImVec2 pos); + + void Draw(); +}; + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/text_editor.cpp b/src/core/devtools/widget/text_editor.cpp new file mode 100644 index 000000000..f447e45a2 --- /dev/null +++ b/src/core/devtools/widget/text_editor.cpp @@ -0,0 +1,2334 @@ +// SPDX-FileCopyrightText: Copyright (c) 2017 BalazsJako +// SPDX-License-Identifier: MIT + +// source: https://github.com/BalazsJako/ImGuiColorTextEdit + +#include +#include +#include +#include +#include + +#include "text_editor.h" + +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" // for imGui::GetCurrentWindow() + +// TODO +// - multiline comments vs single-line: latter is blocking start of a ML + +namespace Core::Devtools::Widget { + +template +bool equals(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p) { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) { + if (!p(*first1, *first2)) + return false; + } + return first1 == last1 && first2 == last2; +} + +TextEditor::TextEditor() + : mLineSpacing(1.0f), mUndoIndex(0), mTabSize(4), mOverwrite(false), mReadOnly(false), + mWithinRender(false), mScrollToCursor(false), mScrollToTop(false), mTextChanged(false), + mColorizerEnabled(true), mTextStart(20.0f), mLeftMargin(10), mCursorPositionChanged(false), + mColorRangeMin(0), mColorRangeMax(0), mSelectionMode(SelectionMode::Normal), + mCheckComments(true), mLastClick(-1.0f), mHandleKeyboardInputs(true), + mHandleMouseInputs(true), mIgnoreImGuiChild(false), mShowWhitespaces(true), + mStartTime(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count()) { + SetPalette(GetDarkPalette()); + mLines.push_back(Line()); +} + +TextEditor::~TextEditor() {} + +void TextEditor::SetLanguageDefinition(const LanguageDefinition& aLanguageDef) { + mLanguageDefinition = aLanguageDef; + mRegexList.clear(); + + for (auto& r : mLanguageDefinition.mTokenRegexStrings) + mRegexList.push_back( + std::make_pair(std::regex(r.first, std::regex_constants::optimize), r.second)); + + Colorize(); +} + +void TextEditor::SetPalette(const Palette& aValue) { + mPaletteBase = aValue; +} + +std::string TextEditor::GetText(const Coordinates& aStart, const Coordinates& aEnd) const { + std::string result; + + auto lstart = aStart.mLine; + auto lend = aEnd.mLine; + auto istart = GetCharacterIndex(aStart); + auto iend = GetCharacterIndex(aEnd); + size_t s = 0; + + for (size_t i = lstart; i < lend; i++) + s += mLines[i].size(); + + result.reserve(s + s / 8); + + while (istart < iend || lstart < lend) { + if (lstart >= (int)mLines.size()) + break; + + auto& line = mLines[lstart]; + if (istart < (int)line.size()) { + result += line[istart].mChar; + istart++; + } else { + istart = 0; + ++lstart; + result += '\n'; + } + } + + return result; +} + +TextEditor::Coordinates TextEditor::GetActualCursorCoordinates() const { + return SanitizeCoordinates(mState.mCursorPosition); +} + +TextEditor::Coordinates TextEditor::SanitizeCoordinates(const Coordinates& aValue) const { + auto line = aValue.mLine; + auto column = aValue.mColumn; + if (line >= (int)mLines.size()) { + if (mLines.empty()) { + line = 0; + column = 0; + } else { + line = (int)mLines.size() - 1; + column = GetLineMaxColumn(line); + } + return Coordinates(line, column); + } else { + column = mLines.empty() ? 0 : std::min(column, GetLineMaxColumn(line)); + return Coordinates(line, column); + } +} + +// https://en.wikipedia.org/wiki/UTF-8 +// We assume that the char is a standalone character (<128) or a leading byte of an UTF-8 code +// sequence (non-10xxxxxx code) +static int UTF8CharLength(TextEditor::Char c) { + if ((c & 0xFE) == 0xFC) + return 6; + if ((c & 0xFC) == 0xF8) + return 5; + if ((c & 0xF8) == 0xF0) + return 4; + else if ((c & 0xF0) == 0xE0) + return 3; + else if ((c & 0xE0) == 0xC0) + return 2; + return 1; +} + +// "Borrowed" from ImGui source +static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) { + if (c < 0x80) { + buf[0] = (char)c; + return 1; + } + if (c < 0x800) { + if (buf_size < 2) + return 0; + buf[0] = (char)(0xc0 + (c >> 6)); + buf[1] = (char)(0x80 + (c & 0x3f)); + return 2; + } + if (c >= 0xdc00 && c < 0xe000) { + return 0; + } + if (c >= 0xd800 && c < 0xdc00) { + if (buf_size < 4) + return 0; + buf[0] = (char)(0xf0 + (c >> 18)); + buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); + buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); + buf[3] = (char)(0x80 + ((c) & 0x3f)); + return 4; + } + // else if (c < 0x10000) + { + if (buf_size < 3) + return 0; + buf[0] = (char)(0xe0 + (c >> 12)); + buf[1] = (char)(0x80 + ((c >> 6) & 0x3f)); + buf[2] = (char)(0x80 + ((c) & 0x3f)); + return 3; + } +} + +void TextEditor::Advance(Coordinates& aCoordinates) const { + if (aCoordinates.mLine < (int)mLines.size()) { + auto& line = mLines[aCoordinates.mLine]; + auto cindex = GetCharacterIndex(aCoordinates); + + if (cindex + 1 < (int)line.size()) { + auto delta = UTF8CharLength(line[cindex].mChar); + cindex = std::min(cindex + delta, (int)line.size() - 1); + } else { + ++aCoordinates.mLine; + cindex = 0; + } + aCoordinates.mColumn = GetCharacterColumn(aCoordinates.mLine, cindex); + } +} + +void TextEditor::DeleteRange(const Coordinates& aStart, const Coordinates& aEnd) { + ASSERT(aEnd >= aStart); + ASSERT(!mReadOnly); + + // printf("D(%d.%d)-(%d.%d)\n", aStart.mLine, aStart.mColumn, aEnd.mLine, aEnd.mColumn); + + if (aEnd == aStart) + return; + + auto start = GetCharacterIndex(aStart); + auto end = GetCharacterIndex(aEnd); + + if (aStart.mLine == aEnd.mLine) { + auto& line = mLines[aStart.mLine]; + auto n = GetLineMaxColumn(aStart.mLine); + if (aEnd.mColumn >= n) + line.erase(line.begin() + start, line.end()); + else + line.erase(line.begin() + start, line.begin() + end); + } else { + auto& firstLine = mLines[aStart.mLine]; + auto& lastLine = mLines[aEnd.mLine]; + + firstLine.erase(firstLine.begin() + start, firstLine.end()); + lastLine.erase(lastLine.begin(), lastLine.begin() + end); + + if (aStart.mLine < aEnd.mLine) + firstLine.insert(firstLine.end(), lastLine.begin(), lastLine.end()); + + if (aStart.mLine < aEnd.mLine) + RemoveLine(aStart.mLine + 1, aEnd.mLine + 1); + } + + mTextChanged = true; +} + +int TextEditor::InsertTextAt(Coordinates& /* inout */ aWhere, const char* aValue) { + ASSERT(!mReadOnly); + + int cindex = GetCharacterIndex(aWhere); + int totalLines = 0; + while (*aValue != '\0') { + ASSERT(!mLines.empty()); + + if (*aValue == '\r') { + // skip + ++aValue; + } else if (*aValue == '\n') { + if (cindex < (int)mLines[aWhere.mLine].size()) { + auto& newLine = InsertLine(aWhere.mLine + 1); + auto& line = mLines[aWhere.mLine]; + newLine.insert(newLine.begin(), line.begin() + cindex, line.end()); + line.erase(line.begin() + cindex, line.end()); + } else { + InsertLine(aWhere.mLine + 1); + } + ++aWhere.mLine; + aWhere.mColumn = 0; + cindex = 0; + ++totalLines; + ++aValue; + } else { + auto& line = mLines[aWhere.mLine]; + auto d = UTF8CharLength(*aValue); + while (d-- > 0 && *aValue != '\0') + line.insert(line.begin() + cindex++, Glyph(*aValue++, PaletteIndex::Default)); + ++aWhere.mColumn; + } + + mTextChanged = true; + } + + return totalLines; +} + +void TextEditor::AddUndo(UndoRecord& aValue) { + ASSERT(!mReadOnly); + // printf("AddUndo: (@%d.%d) +\'%s' [%d.%d .. %d.%d], -\'%s', [%d.%d .. %d.%d] (@%d.%d)\n", + // aValue.mBefore.mCursorPosition.mLine, aValue.mBefore.mCursorPosition.mColumn, + // aValue.mAdded.c_str(), aValue.mAddedStart.mLine, aValue.mAddedStart.mColumn, + // aValue.mAddedEnd.mLine, aValue.mAddedEnd.mColumn, aValue.mRemoved.c_str(), + // aValue.mRemovedStart.mLine, aValue.mRemovedStart.mColumn, aValue.mRemovedEnd.mLine, + // aValue.mRemovedEnd.mColumn, aValue.mAfter.mCursorPosition.mLine, + // aValue.mAfter.mCursorPosition.mColumn + // ); + + mUndoBuffer.resize((size_t)(mUndoIndex + 1)); + mUndoBuffer.back() = aValue; + ++mUndoIndex; +} + +TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2& aPosition) const { + ImVec2 origin = ImGui::GetCursorScreenPos(); + ImVec2 local(aPosition.x - origin.x, aPosition.y - origin.y); + + int lineNo = std::max(0, (int)floor(local.y / mCharAdvance.y)); + + int columnCoord = 0; + + if (lineNo >= 0 && lineNo < (int)mLines.size()) { + auto& line = mLines.at(lineNo); + + int columnIndex = 0; + float columnX = 0.0f; + + while ((size_t)columnIndex < line.size()) { + float columnWidth = 0.0f; + + if (line[columnIndex].mChar == '\t') { + float spaceSize = + ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ").x; + float oldX = columnX; + float newColumnX = + (1.0f + std::floor((1.0f + columnX) / (float(mTabSize) * spaceSize))) * + (float(mTabSize) * spaceSize); + columnWidth = newColumnX - oldX; + if (mTextStart + columnX + columnWidth * 0.5f > local.x) + break; + columnX = newColumnX; + columnCoord = (columnCoord / mTabSize) * mTabSize + mTabSize; + columnIndex++; + } else { + char buf[7]; + auto d = UTF8CharLength(line[columnIndex].mChar); + int i = 0; + while (i < 6 && d-- > 0) + buf[i++] = line[columnIndex++].mChar; + buf[i] = '\0'; + columnWidth = + ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf).x; + if (mTextStart + columnX + columnWidth * 0.5f > local.x) + break; + columnX += columnWidth; + columnCoord++; + } + } + } + + return SanitizeCoordinates(Coordinates(lineNo, columnCoord)); +} + +TextEditor::Coordinates TextEditor::FindWordStart(const Coordinates& aFrom) const { + Coordinates at = aFrom; + if (at.mLine >= (int)mLines.size()) + return at; + + auto& line = mLines[at.mLine]; + auto cindex = GetCharacterIndex(at); + + if (cindex >= (int)line.size()) + return at; + + while (cindex > 0 && isspace(line[cindex].mChar)) + --cindex; + + auto cstart = (PaletteIndex)line[cindex].mColorIndex; + while (cindex > 0) { + auto c = line[cindex].mChar; + if ((c & 0xC0) != 0x80) // not UTF code sequence 10xxxxxx + { + if (c <= 32 && isspace(c)) { + cindex++; + break; + } + if (cstart != (PaletteIndex)line[size_t(cindex - 1)].mColorIndex) + break; + } + --cindex; + } + return Coordinates(at.mLine, GetCharacterColumn(at.mLine, cindex)); +} + +TextEditor::Coordinates TextEditor::FindWordEnd(const Coordinates& aFrom) const { + Coordinates at = aFrom; + if (at.mLine >= (int)mLines.size()) + return at; + + auto& line = mLines[at.mLine]; + auto cindex = GetCharacterIndex(at); + + if (cindex >= (int)line.size()) + return at; + + bool prevspace = (bool)isspace(line[cindex].mChar); + auto cstart = (PaletteIndex)line[cindex].mColorIndex; + while (cindex < (int)line.size()) { + auto c = line[cindex].mChar; + auto d = UTF8CharLength(c); + if (cstart != (PaletteIndex)line[cindex].mColorIndex) + break; + + if (prevspace != !!isspace(c)) { + if (isspace(c)) + while (cindex < (int)line.size() && isspace(line[cindex].mChar)) + ++cindex; + break; + } + cindex += d; + } + return Coordinates(aFrom.mLine, GetCharacterColumn(aFrom.mLine, cindex)); +} + +TextEditor::Coordinates TextEditor::FindNextWord(const Coordinates& aFrom) const { + Coordinates at = aFrom; + if (at.mLine >= (int)mLines.size()) + return at; + + // skip to the next non-word character + auto cindex = GetCharacterIndex(aFrom); + bool isword = false; + bool skip = false; + if (cindex < (int)mLines[at.mLine].size()) { + auto& line = mLines[at.mLine]; + isword = isalnum(line[cindex].mChar); + skip = isword; + } + + while (!isword || skip) { + if (at.mLine >= mLines.size()) { + auto l = std::max(0, (int)mLines.size() - 1); + return Coordinates(l, GetLineMaxColumn(l)); + } + + auto& line = mLines[at.mLine]; + if (cindex < (int)line.size()) { + isword = isalnum(line[cindex].mChar); + + if (isword && !skip) + return Coordinates(at.mLine, GetCharacterColumn(at.mLine, cindex)); + + if (!isword) + skip = false; + + cindex++; + } else { + cindex = 0; + ++at.mLine; + skip = false; + isword = false; + } + } + + return at; +} + +int TextEditor::GetCharacterIndex(const Coordinates& aCoordinates) const { + if (aCoordinates.mLine >= mLines.size()) + return -1; + auto& line = mLines[aCoordinates.mLine]; + int c = 0; + int i = 0; + for (; i < line.size() && c < aCoordinates.mColumn;) { + if (line[i].mChar == '\t') + c = (c / mTabSize) * mTabSize + mTabSize; + else + ++c; + i += UTF8CharLength(line[i].mChar); + } + return i; +} + +int TextEditor::GetCharacterColumn(int aLine, int aIndex) const { + if (aLine >= mLines.size()) + return 0; + auto& line = mLines[aLine]; + int col = 0; + int i = 0; + while (i < aIndex && i < (int)line.size()) { + auto c = line[i].mChar; + i += UTF8CharLength(c); + if (c == '\t') + col = (col / mTabSize) * mTabSize + mTabSize; + else + col++; + } + return col; +} + +int TextEditor::GetLineCharacterCount(int aLine) const { + if (aLine >= mLines.size()) + return 0; + auto& line = mLines[aLine]; + int c = 0; + for (unsigned i = 0; i < line.size(); c++) + i += UTF8CharLength(line[i].mChar); + return c; +} + +int TextEditor::GetLineMaxColumn(int aLine) const { + if (aLine >= mLines.size()) + return 0; + auto& line = mLines[aLine]; + int col = 0; + for (unsigned i = 0; i < line.size();) { + auto c = line[i].mChar; + if (c == '\t') + col = (col / mTabSize) * mTabSize + mTabSize; + else + col++; + i += UTF8CharLength(c); + } + return col; +} + +bool TextEditor::IsOnWordBoundary(const Coordinates& aAt) const { + if (aAt.mLine >= (int)mLines.size() || aAt.mColumn == 0) + return true; + + auto& line = mLines[aAt.mLine]; + auto cindex = GetCharacterIndex(aAt); + if (cindex >= (int)line.size()) + return true; + + if (mColorizerEnabled) + return line[cindex].mColorIndex != line[size_t(cindex - 1)].mColorIndex; + + return isspace(line[cindex].mChar) != isspace(line[cindex - 1].mChar); +} + +void TextEditor::RemoveLine(int aStart, int aEnd) { + ASSERT(!mReadOnly); + ASSERT(aEnd >= aStart); + ASSERT(mLines.size() > (size_t)(aEnd - aStart)); + + ErrorMarkers etmp; + for (auto& i : mErrorMarkers) { + ErrorMarkers::value_type e(i.first >= aStart ? i.first - 1 : i.first, i.second); + if (e.first >= aStart && e.first <= aEnd) + continue; + etmp.insert(e); + } + mErrorMarkers = std::move(etmp); + + Breakpoints btmp; + for (auto i : mBreakpoints) { + if (i >= aStart && i <= aEnd) + continue; + btmp.insert(i >= aStart ? i - 1 : i); + } + mBreakpoints = std::move(btmp); + + mLines.erase(mLines.begin() + aStart, mLines.begin() + aEnd); + ASSERT(!mLines.empty()); + + mTextChanged = true; +} + +void TextEditor::RemoveLine(int aIndex) { + ASSERT(!mReadOnly); + ASSERT(mLines.size() > 1); + + ErrorMarkers etmp; + for (auto& i : mErrorMarkers) { + ErrorMarkers::value_type e(i.first > aIndex ? i.first - 1 : i.first, i.second); + if (e.first - 1 == aIndex) + continue; + etmp.insert(e); + } + mErrorMarkers = std::move(etmp); + + Breakpoints btmp; + for (auto i : mBreakpoints) { + if (i == aIndex) + continue; + btmp.insert(i >= aIndex ? i - 1 : i); + } + mBreakpoints = std::move(btmp); + + mLines.erase(mLines.begin() + aIndex); + ASSERT(!mLines.empty()); + + mTextChanged = true; +} + +TextEditor::Line& TextEditor::InsertLine(int aIndex) { + ASSERT(!mReadOnly); + + auto& result = *mLines.insert(mLines.begin() + aIndex, Line()); + + ErrorMarkers etmp; + for (auto& i : mErrorMarkers) + etmp.insert(ErrorMarkers::value_type(i.first >= aIndex ? i.first + 1 : i.first, i.second)); + mErrorMarkers = std::move(etmp); + + Breakpoints btmp; + for (auto i : mBreakpoints) + btmp.insert(i >= aIndex ? i + 1 : i); + mBreakpoints = std::move(btmp); + + return result; +} + +std::string TextEditor::GetWordUnderCursor() const { + auto c = GetCursorPosition(); + return GetWordAt(c); +} + +std::string TextEditor::GetWordAt(const Coordinates& aCoords) const { + auto start = FindWordStart(aCoords); + auto end = FindWordEnd(aCoords); + + std::string r; + + auto istart = GetCharacterIndex(start); + auto iend = GetCharacterIndex(end); + + for (auto it = istart; it < iend; ++it) + r.push_back(mLines[aCoords.mLine][it].mChar); + + return r; +} + +ImU32 TextEditor::GetGlyphColor(const Glyph& aGlyph) const { + if (!mColorizerEnabled) + return mPalette[(int)PaletteIndex::Default]; + if (aGlyph.mComment) + return mPalette[(int)PaletteIndex::Comment]; + if (aGlyph.mMultiLineComment) + return mPalette[(int)PaletteIndex::MultiLineComment]; + auto const color = mPalette[(int)aGlyph.mColorIndex]; + if (aGlyph.mPreprocessor) { + const auto ppcolor = mPalette[(int)PaletteIndex::Preprocessor]; + const int c0 = ((ppcolor & 0xff) + (color & 0xff)) / 2; + const int c1 = (((ppcolor >> 8) & 0xff) + ((color >> 8) & 0xff)) / 2; + const int c2 = (((ppcolor >> 16) & 0xff) + ((color >> 16) & 0xff)) / 2; + const int c3 = (((ppcolor >> 24) & 0xff) + ((color >> 24) & 0xff)) / 2; + return ImU32(c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)); + } + return color; +} + +void TextEditor::HandleKeyboardInputs() { + ImGuiIO& io = ImGui::GetIO(); + auto shift = io.KeyShift; + auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl; + auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt; + + if (ImGui::IsWindowFocused()) { + if (ImGui::IsWindowHovered()) + ImGui::SetMouseCursor(ImGuiMouseCursor_TextInput); + // ImGui::CaptureKeyboardFromApp(true); + + io.WantCaptureKeyboard = true; + io.WantTextInput = true; + + if (!IsReadOnly() && ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z))) + Undo(); + else if (!IsReadOnly() && !ctrl && !shift && alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace))) + Undo(); + else if (!IsReadOnly() && ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y))) + Redo(); + else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow))) + MoveUp(1, shift); + else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow))) + MoveDown(1, shift); + else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow))) + MoveLeft(1, shift, ctrl); + else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow))) + MoveRight(1, shift, ctrl); + else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp))) + MoveUp(GetPageSize() - 4, shift); + else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown))) + MoveDown(GetPageSize() - 4, shift); + else if (!alt && ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home))) + MoveTop(shift); + else if (ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End))) + MoveBottom(shift); + else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home))) + MoveHome(shift); + else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End))) + MoveEnd(shift); + else if (!IsReadOnly() && !ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete))) + Delete(); + else if (!IsReadOnly() && !ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace))) + Backspace(); + else if (!ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert))) + mOverwrite ^= true; + else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert))) + Copy(); + else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C))) + Copy(); + else if (!IsReadOnly() && !ctrl && shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert))) + Paste(); + else if (!IsReadOnly() && ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_V))) + Paste(); + else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_X))) + Cut(); + else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete))) + Cut(); + else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_A))) + SelectAll(); + else if (!IsReadOnly() && !ctrl && !shift && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter))) + EnterCharacter('\n', false); + else if (!IsReadOnly() && !ctrl && !alt && + ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab))) + EnterCharacter('\t', shift); + + if (!IsReadOnly() && !io.InputQueueCharacters.empty()) { + for (int i = 0; i < io.InputQueueCharacters.Size; i++) { + auto c = io.InputQueueCharacters[i]; + if (c != 0 && (c == '\n' || c >= 32)) + EnterCharacter(c, shift); + } + io.InputQueueCharacters.resize(0); + } + } +} + +void TextEditor::HandleMouseInputs() { + ImGuiIO& io = ImGui::GetIO(); + auto shift = io.KeyShift; + auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl; + auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt; + + if (ImGui::IsWindowHovered()) { + if (!shift && !alt) { + auto click = ImGui::IsMouseClicked(0); + auto doubleClick = ImGui::IsMouseDoubleClicked(0); + auto t = ImGui::GetTime(); + auto tripleClick = click && !doubleClick && + (mLastClick != -1.0f && (t - mLastClick) < io.MouseDoubleClickTime); + + /* + Left mouse button triple click + */ + + if (tripleClick) { + if (!ctrl) { + mState.mCursorPosition = mInteractiveStart = mInteractiveEnd = + ScreenPosToCoordinates(ImGui::GetMousePos()); + mSelectionMode = SelectionMode::Line; + SetSelection(mInteractiveStart, mInteractiveEnd, mSelectionMode); + } + + mLastClick = -1.0f; + } + + /* + Left mouse button double click + */ + + else if (doubleClick) { + if (!ctrl) { + mState.mCursorPosition = mInteractiveStart = mInteractiveEnd = + ScreenPosToCoordinates(ImGui::GetMousePos()); + if (mSelectionMode == SelectionMode::Line) + mSelectionMode = SelectionMode::Normal; + else + mSelectionMode = SelectionMode::Word; + SetSelection(mInteractiveStart, mInteractiveEnd, mSelectionMode); + } + + mLastClick = (float)ImGui::GetTime(); + } + + /* + Left mouse button click + */ + else if (click) { + mState.mCursorPosition = mInteractiveStart = mInteractiveEnd = + ScreenPosToCoordinates(ImGui::GetMousePos()); + if (ctrl) + mSelectionMode = SelectionMode::Word; + else + mSelectionMode = SelectionMode::Normal; + SetSelection(mInteractiveStart, mInteractiveEnd, mSelectionMode); + + mLastClick = (float)ImGui::GetTime(); + } + // Mouse left button dragging (=> update selection) + else if (ImGui::IsMouseDragging(0) && ImGui::IsMouseDown(0)) { + io.WantCaptureMouse = true; + mState.mCursorPosition = mInteractiveEnd = + ScreenPosToCoordinates(ImGui::GetMousePos()); + SetSelection(mInteractiveStart, mInteractiveEnd, mSelectionMode); + } + } + } +} + +void TextEditor::Render() { + /* Compute mCharAdvance regarding to scaled font size (Ctrl + mouse wheel)*/ + const float fontSize = + ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, "#", nullptr, nullptr) + .x; + mCharAdvance = ImVec2(fontSize, ImGui::GetTextLineHeightWithSpacing() * mLineSpacing); + + /* Update palette with the current alpha from style */ + for (int i = 0; i < (int)PaletteIndex::Max; ++i) { + auto color = ImGui::ColorConvertU32ToFloat4(mPaletteBase[i]); + color.w *= ImGui::GetStyle().Alpha; + mPalette[i] = ImGui::ColorConvertFloat4ToU32(color); + } + + ASSERT(mLineBuffer.empty()); + + auto contentSize = ImGui::GetWindowContentRegionMax(); + auto drawList = ImGui::GetWindowDrawList(); + float longest(mTextStart); + + if (mScrollToTop) { + mScrollToTop = false; + ImGui::SetScrollY(0.f); + } + + ImVec2 cursorScreenPos = ImGui::GetCursorScreenPos(); + auto scrollX = ImGui::GetScrollX(); + auto scrollY = ImGui::GetScrollY(); + + auto lineNo = (int)floor(scrollY / mCharAdvance.y); + auto globalLineMax = (int)mLines.size(); + auto lineMax = + std::max(0, std::min((int)mLines.size() - 1, + lineNo + (int)floor((scrollY + contentSize.y) / mCharAdvance.y))); + + // Deduce mTextStart by evaluating mLines size (global lineMax) plus two spaces as text width + char buf[16]; + snprintf(buf, 16, " %d ", globalLineMax); + mTextStart = ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr) + .x + + mLeftMargin; + + if (!mLines.empty()) { + float spaceSize = + ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr) + .x; + + while (lineNo <= lineMax) { + ImVec2 lineStartScreenPos = + ImVec2(cursorScreenPos.x, cursorScreenPos.y + lineNo * mCharAdvance.y); + ImVec2 textScreenPos = ImVec2(lineStartScreenPos.x + mTextStart, lineStartScreenPos.y); + + auto& line = mLines[lineNo]; + longest = std::max( + mTextStart + TextDistanceToLineStart(Coordinates(lineNo, GetLineMaxColumn(lineNo))), + longest); + auto columnNo = 0; + Coordinates lineStartCoord(lineNo, 0); + Coordinates lineEndCoord(lineNo, GetLineMaxColumn(lineNo)); + + // Draw selection for the current line + float sstart = -1.0f; + float ssend = -1.0f; + + ASSERT(mState.mSelectionStart <= mState.mSelectionEnd); + if (mState.mSelectionStart <= lineEndCoord) + sstart = mState.mSelectionStart > lineStartCoord + ? TextDistanceToLineStart(mState.mSelectionStart) + : 0.0f; + if (mState.mSelectionEnd > lineStartCoord) + ssend = TextDistanceToLineStart( + mState.mSelectionEnd < lineEndCoord ? mState.mSelectionEnd : lineEndCoord); + + if (mState.mSelectionEnd.mLine > lineNo) + ssend += mCharAdvance.x; + + if (sstart != -1 && ssend != -1 && sstart < ssend) { + ImVec2 vstart(lineStartScreenPos.x + mTextStart + sstart, lineStartScreenPos.y); + ImVec2 vend(lineStartScreenPos.x + mTextStart + ssend, + lineStartScreenPos.y + mCharAdvance.y); + drawList->AddRectFilled(vstart, vend, mPalette[(int)PaletteIndex::Selection]); + } + + // Draw breakpoints + auto start = ImVec2(lineStartScreenPos.x + scrollX, lineStartScreenPos.y); + + if (mBreakpoints.count(lineNo + 1) != 0) { + auto end = ImVec2(lineStartScreenPos.x + contentSize.x + 2.0f * scrollX, + lineStartScreenPos.y + mCharAdvance.y); + drawList->AddRectFilled(start, end, mPalette[(int)PaletteIndex::Breakpoint]); + } + + // Draw error markers + auto errorIt = mErrorMarkers.find(lineNo + 1); + if (errorIt != mErrorMarkers.end()) { + auto end = ImVec2(lineStartScreenPos.x + contentSize.x + 2.0f * scrollX, + lineStartScreenPos.y + mCharAdvance.y); + drawList->AddRectFilled(start, end, mPalette[(int)PaletteIndex::ErrorMarker]); + + if (ImGui::IsMouseHoveringRect(lineStartScreenPos, end)) { + ImGui::BeginTooltip(); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.2f, 0.2f, 1.0f)); + ImGui::Text("Error at line %d:", errorIt->first); + ImGui::PopStyleColor(); + ImGui::Separator(); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.2f, 1.0f)); + ImGui::Text("%s", errorIt->second.c_str()); + ImGui::PopStyleColor(); + ImGui::EndTooltip(); + } + } + + // Draw line number (right aligned) + snprintf(buf, 16, "%d ", lineNo + 1); + + auto lineNoWidth = + ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr) + .x; + drawList->AddText( + ImVec2(lineStartScreenPos.x + mTextStart - lineNoWidth, lineStartScreenPos.y), + mPalette[(int)PaletteIndex::LineNumber], buf); + + if (mState.mCursorPosition.mLine == lineNo) { + auto focused = ImGui::IsWindowFocused(); + + // Highlight the current line (where the cursor is) + if (!HasSelection()) { + auto end = ImVec2(start.x + contentSize.x + scrollX, start.y + mCharAdvance.y); + drawList->AddRectFilled( + start, end, + mPalette[(int)(focused ? PaletteIndex::CurrentLineFill + : PaletteIndex::CurrentLineFillInactive)]); + drawList->AddRect(start, end, mPalette[(int)PaletteIndex::CurrentLineEdge], + 1.0f); + } + + // Render the cursor + if (focused) { + auto timeEnd = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + auto elapsed = timeEnd - mStartTime; + if (elapsed > 400) { + float width = 1.0f; + auto cindex = GetCharacterIndex(mState.mCursorPosition); + float cx = TextDistanceToLineStart(mState.mCursorPosition); + + if (mOverwrite && cindex < (int)line.size()) { + auto c = line[cindex].mChar; + if (c == '\t') { + auto x = (1.0f + + std::floor((1.0f + cx) / (float(mTabSize) * spaceSize))) * + (float(mTabSize) * spaceSize); + width = x - cx; + } else { + char buf2[2]; + buf2[0] = line[cindex].mChar; + buf2[1] = '\0'; + width = + ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf2) + .x; + } + } + ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y); + ImVec2 cend(textScreenPos.x + cx + width, + lineStartScreenPos.y + mCharAdvance.y); + drawList->AddRectFilled(cstart, cend, mPalette[(int)PaletteIndex::Cursor]); + if (elapsed > 800) + mStartTime = timeEnd; + } + } + } + + // Render colorized text + auto prevColor = + line.empty() ? mPalette[(int)PaletteIndex::Default] : GetGlyphColor(line[0]); + ImVec2 bufferOffset; + + for (int i = 0; i < line.size();) { + auto& glyph = line[i]; + auto color = GetGlyphColor(glyph); + + if ((color != prevColor || glyph.mChar == '\t' || glyph.mChar == ' ') && + !mLineBuffer.empty()) { + const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, + textScreenPos.y + bufferOffset.y); + drawList->AddText(newOffset, prevColor, mLineBuffer.c_str()); + auto textSize = + ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, + mLineBuffer.c_str(), nullptr, nullptr); + bufferOffset.x += textSize.x; + mLineBuffer.clear(); + } + prevColor = color; + + if (glyph.mChar == '\t') { + auto oldX = bufferOffset.x; + bufferOffset.x = (1.0f + std::floor((1.0f + bufferOffset.x) / + (float(mTabSize) * spaceSize))) * + (float(mTabSize) * spaceSize); + ++i; + + if (mShowWhitespaces) { + const auto s = ImGui::GetFontSize(); + const auto x1 = textScreenPos.x + oldX + 1.0f; + const auto x2 = textScreenPos.x + bufferOffset.x - 1.0f; + const auto y = textScreenPos.y + bufferOffset.y + s * 0.5f; + const ImVec2 p1(x1, y); + const ImVec2 p2(x2, y); + const ImVec2 p3(x2 - s * 0.2f, y - s * 0.2f); + const ImVec2 p4(x2 - s * 0.2f, y + s * 0.2f); + drawList->AddLine(p1, p2, 0x90909090); + drawList->AddLine(p2, p3, 0x90909090); + drawList->AddLine(p2, p4, 0x90909090); + } + } else if (glyph.mChar == ' ') { + if (mShowWhitespaces) { + const auto s = ImGui::GetFontSize(); + const auto x = textScreenPos.x + bufferOffset.x + spaceSize * 0.5f; + const auto y = textScreenPos.y + bufferOffset.y + s * 0.5f; + drawList->AddCircleFilled(ImVec2(x, y), 1.5f, 0x80808080, 4); + } + bufferOffset.x += spaceSize; + i++; + } else { + auto l = UTF8CharLength(glyph.mChar); + while (l-- > 0) + mLineBuffer.push_back(line[i++].mChar); + } + ++columnNo; + } + + if (!mLineBuffer.empty()) { + const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, + textScreenPos.y + bufferOffset.y); + drawList->AddText(newOffset, prevColor, mLineBuffer.c_str()); + mLineBuffer.clear(); + } + + ++lineNo; + } + + // Draw a tooltip on known identifiers/preprocessor symbols + if (ImGui::IsMousePosValid()) { + auto id = GetWordAt(ScreenPosToCoordinates(ImGui::GetMousePos())); + if (!id.empty()) { + auto it = mLanguageDefinition.mIdentifiers.find(id); + if (it != mLanguageDefinition.mIdentifiers.end()) { + ImGui::BeginTooltip(); + ImGui::TextUnformatted(it->second.mDeclaration.c_str()); + ImGui::EndTooltip(); + } else { + auto pi = mLanguageDefinition.mPreprocIdentifiers.find(id); + if (pi != mLanguageDefinition.mPreprocIdentifiers.end()) { + ImGui::BeginTooltip(); + ImGui::TextUnformatted(pi->second.mDeclaration.c_str()); + ImGui::EndTooltip(); + } + } + } + } + } + + ImGui::Dummy(ImVec2((longest + 2), mLines.size() * mCharAdvance.y)); + + if (mScrollToCursor) { + EnsureCursorVisible(); + ImGui::SetWindowFocus(); + mScrollToCursor = false; + } +} + +void TextEditor::Render(const char* aTitle, const ImVec2& aSize, bool aBorder) { + mWithinRender = true; + mTextChanged = false; + mCursorPositionChanged = false; + + ImGui::PushStyleColor(ImGuiCol_ChildBg, + ImGui::ColorConvertU32ToFloat4(mPalette[(int)PaletteIndex::Background])); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + if (!mIgnoreImGuiChild) + ImGui::BeginChild(aTitle, aSize, aBorder, + ImGuiWindowFlags_HorizontalScrollbar | + ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NoMove); + + if (mHandleKeyboardInputs) { + HandleKeyboardInputs(); + ImGui::PushAllowKeyboardFocus(true); + } + + if (mHandleMouseInputs) + HandleMouseInputs(); + + ColorizeInternal(); + Render(); + + if (mHandleKeyboardInputs) + ImGui::PopAllowKeyboardFocus(); + + if (!mIgnoreImGuiChild) + ImGui::EndChild(); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + + mWithinRender = false; +} + +void TextEditor::SetText(const std::string& aText) { + mLines.clear(); + mLines.emplace_back(Line()); + for (auto chr : aText) { + if (chr == '\r') { + // ignore the carriage return character + } else if (chr == '\n') + mLines.emplace_back(Line()); + else { + mLines.back().emplace_back(Glyph(chr, PaletteIndex::Default)); + } + } + + mTextChanged = true; + mScrollToTop = true; + + mUndoBuffer.clear(); + mUndoIndex = 0; + + Colorize(); +} + +void TextEditor::SetTextLines(const std::vector& aLines) { + mLines.clear(); + + if (aLines.empty()) { + mLines.emplace_back(Line()); + } else { + mLines.resize(aLines.size()); + + for (size_t i = 0; i < aLines.size(); ++i) { + const std::string& aLine = aLines[i]; + + mLines[i].reserve(aLine.size()); + for (size_t j = 0; j < aLine.size(); ++j) + mLines[i].emplace_back(Glyph(aLine[j], PaletteIndex::Default)); + } + } + + mTextChanged = true; + mScrollToTop = true; + + mUndoBuffer.clear(); + mUndoIndex = 0; + + Colorize(); +} + +void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) { + ASSERT(!mReadOnly); + + UndoRecord u; + + u.mBefore = mState; + + if (HasSelection()) { + if (aChar == '\t' && mState.mSelectionStart.mLine != mState.mSelectionEnd.mLine) { + + auto start = mState.mSelectionStart; + auto end = mState.mSelectionEnd; + auto originalEnd = end; + + if (start > end) + std::swap(start, end); + start.mColumn = 0; + // end.mColumn = end.mLine < mLines.size() ? mLines[end.mLine].size() : 0; + if (end.mColumn == 0 && end.mLine > 0) + --end.mLine; + if (end.mLine >= (int)mLines.size()) + end.mLine = mLines.empty() ? 0 : (int)mLines.size() - 1; + end.mColumn = GetLineMaxColumn(end.mLine); + + // if (end.mColumn >= GetLineMaxColumn(end.mLine)) + // end.mColumn = GetLineMaxColumn(end.mLine) - 1; + + u.mRemovedStart = start; + u.mRemovedEnd = end; + u.mRemoved = GetText(start, end); + + bool modified = false; + + for (int i = start.mLine; i <= end.mLine; i++) { + auto& line = mLines[i]; + if (aShift) { + if (!line.empty()) { + if (line.front().mChar == '\t') { + line.erase(line.begin()); + modified = true; + } else { + for (int j = 0; + j < mTabSize && !line.empty() && line.front().mChar == ' '; j++) { + line.erase(line.begin()); + modified = true; + } + } + } + } else { + line.insert(line.begin(), Glyph('\t', TextEditor::PaletteIndex::Background)); + modified = true; + } + } + + if (modified) { + start = Coordinates(start.mLine, GetCharacterColumn(start.mLine, 0)); + Coordinates rangeEnd; + if (originalEnd.mColumn != 0) { + end = Coordinates(end.mLine, GetLineMaxColumn(end.mLine)); + rangeEnd = end; + u.mAdded = GetText(start, end); + } else { + end = Coordinates(originalEnd.mLine, 0); + rangeEnd = Coordinates(end.mLine - 1, GetLineMaxColumn(end.mLine - 1)); + u.mAdded = GetText(start, rangeEnd); + } + + u.mAddedStart = start; + u.mAddedEnd = rangeEnd; + u.mAfter = mState; + + mState.mSelectionStart = start; + mState.mSelectionEnd = end; + AddUndo(u); + + mTextChanged = true; + + EnsureCursorVisible(); + } + + return; + } // c == '\t' + else { + u.mRemoved = GetSelectedText(); + u.mRemovedStart = mState.mSelectionStart; + u.mRemovedEnd = mState.mSelectionEnd; + DeleteSelection(); + } + } // HasSelection + + auto coord = GetActualCursorCoordinates(); + u.mAddedStart = coord; + + ASSERT(!mLines.empty()); + + if (aChar == '\n') { + InsertLine(coord.mLine + 1); + auto& line = mLines[coord.mLine]; + auto& newLine = mLines[coord.mLine + 1]; + + if (mLanguageDefinition.mAutoIndentation) + for (size_t it = 0; + it < line.size() && isascii(line[it].mChar) && isblank(line[it].mChar); ++it) + newLine.push_back(line[it]); + + const size_t whitespaceSize = newLine.size(); + auto cindex = GetCharacterIndex(coord); + newLine.insert(newLine.end(), line.begin() + cindex, line.end()); + line.erase(line.begin() + cindex, line.begin() + line.size()); + SetCursorPosition( + Coordinates(coord.mLine + 1, GetCharacterColumn(coord.mLine + 1, (int)whitespaceSize))); + u.mAdded = (char)aChar; + } else { + char buf[7]; + int e = ImTextCharToUtf8(buf, 7, aChar); + if (e > 0) { + buf[e] = '\0'; + auto& line = mLines[coord.mLine]; + auto cindex = GetCharacterIndex(coord); + + if (mOverwrite && cindex < (int)line.size()) { + auto d = UTF8CharLength(line[cindex].mChar); + + u.mRemovedStart = mState.mCursorPosition; + u.mRemovedEnd = + Coordinates(coord.mLine, GetCharacterColumn(coord.mLine, cindex + d)); + + while (d-- > 0 && cindex < (int)line.size()) { + u.mRemoved += line[cindex].mChar; + line.erase(line.begin() + cindex); + } + } + + for (auto p = buf; *p != '\0'; p++, ++cindex) + line.insert(line.begin() + cindex, Glyph(*p, PaletteIndex::Default)); + u.mAdded = buf; + + SetCursorPosition(Coordinates(coord.mLine, GetCharacterColumn(coord.mLine, cindex))); + } else + return; + } + + mTextChanged = true; + + u.mAddedEnd = GetActualCursorCoordinates(); + u.mAfter = mState; + + AddUndo(u); + + Colorize(coord.mLine - 1, 3); + EnsureCursorVisible(); +} + +void TextEditor::SetReadOnly(bool aValue) { + mReadOnly = aValue; +} + +void TextEditor::SetColorizerEnable(bool aValue) { + mColorizerEnabled = aValue; +} + +void TextEditor::SetCursorPosition(const Coordinates& aPosition) { + if (mState.mCursorPosition != aPosition) { + mState.mCursorPosition = aPosition; + mCursorPositionChanged = true; + EnsureCursorVisible(); + } +} + +void TextEditor::SetSelectionStart(const Coordinates& aPosition) { + mState.mSelectionStart = SanitizeCoordinates(aPosition); + if (mState.mSelectionStart > mState.mSelectionEnd) + std::swap(mState.mSelectionStart, mState.mSelectionEnd); +} + +void TextEditor::SetSelectionEnd(const Coordinates& aPosition) { + mState.mSelectionEnd = SanitizeCoordinates(aPosition); + if (mState.mSelectionStart > mState.mSelectionEnd) + std::swap(mState.mSelectionStart, mState.mSelectionEnd); +} + +void TextEditor::SetSelection(const Coordinates& aStart, const Coordinates& aEnd, + SelectionMode aMode) { + auto oldSelStart = mState.mSelectionStart; + auto oldSelEnd = mState.mSelectionEnd; + + mState.mSelectionStart = SanitizeCoordinates(aStart); + mState.mSelectionEnd = SanitizeCoordinates(aEnd); + if (mState.mSelectionStart > mState.mSelectionEnd) + std::swap(mState.mSelectionStart, mState.mSelectionEnd); + + switch (aMode) { + case TextEditor::SelectionMode::Normal: + break; + case TextEditor::SelectionMode::Word: { + mState.mSelectionStart = FindWordStart(mState.mSelectionStart); + if (!IsOnWordBoundary(mState.mSelectionEnd)) + mState.mSelectionEnd = FindWordEnd(FindWordStart(mState.mSelectionEnd)); + break; + } + case TextEditor::SelectionMode::Line: { + const auto lineNo = mState.mSelectionEnd.mLine; + const auto lineSize = (size_t)lineNo < mLines.size() ? mLines[lineNo].size() : 0; + mState.mSelectionStart = Coordinates(mState.mSelectionStart.mLine, 0); + mState.mSelectionEnd = Coordinates(lineNo, GetLineMaxColumn(lineNo)); + break; + } + default: + break; + } + + if (mState.mSelectionStart != oldSelStart || mState.mSelectionEnd != oldSelEnd) + mCursorPositionChanged = true; +} + +void TextEditor::SetTabSize(int aValue) { + mTabSize = std::max(0, std::min(32, aValue)); +} + +void TextEditor::InsertText(const std::string& aValue) { + InsertText(aValue.c_str()); +} + +void TextEditor::InsertText(const char* aValue) { + if (aValue == nullptr) + return; + + auto pos = GetActualCursorCoordinates(); + auto start = std::min(pos, mState.mSelectionStart); + int totalLines = pos.mLine - start.mLine; + + totalLines += InsertTextAt(pos, aValue); + + SetSelection(pos, pos); + SetCursorPosition(pos); + Colorize(start.mLine - 1, totalLines + 2); +} + +void TextEditor::DeleteSelection() { + ASSERT(mState.mSelectionEnd >= mState.mSelectionStart); + + if (mState.mSelectionEnd == mState.mSelectionStart) + return; + + DeleteRange(mState.mSelectionStart, mState.mSelectionEnd); + + SetSelection(mState.mSelectionStart, mState.mSelectionStart); + SetCursorPosition(mState.mSelectionStart); + Colorize(mState.mSelectionStart.mLine, 1); +} + +void TextEditor::MoveUp(int aAmount, bool aSelect) { + auto oldPos = mState.mCursorPosition; + mState.mCursorPosition.mLine = std::max(0, mState.mCursorPosition.mLine - aAmount); + if (oldPos != mState.mCursorPosition) { + if (aSelect) { + if (oldPos == mInteractiveStart) + mInteractiveStart = mState.mCursorPosition; + else if (oldPos == mInteractiveEnd) + mInteractiveEnd = mState.mCursorPosition; + else { + mInteractiveStart = mState.mCursorPosition; + mInteractiveEnd = oldPos; + } + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd); + + EnsureCursorVisible(); + } +} + +void TextEditor::MoveDown(int aAmount, bool aSelect) { + ASSERT(mState.mCursorPosition.mColumn >= 0); + auto oldPos = mState.mCursorPosition; + mState.mCursorPosition.mLine = + std::max(0, std::min((int)mLines.size() - 1, mState.mCursorPosition.mLine + aAmount)); + + if (mState.mCursorPosition != oldPos) { + if (aSelect) { + if (oldPos == mInteractiveEnd) + mInteractiveEnd = mState.mCursorPosition; + else if (oldPos == mInteractiveStart) + mInteractiveStart = mState.mCursorPosition; + else { + mInteractiveStart = oldPos; + mInteractiveEnd = mState.mCursorPosition; + } + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd); + + EnsureCursorVisible(); + } +} + +static bool IsUTFSequence(char c) { + return (c & 0xC0) == 0x80; +} + +void TextEditor::MoveLeft(int aAmount, bool aSelect, bool aWordMode) { + if (mLines.empty()) + return; + + auto oldPos = mState.mCursorPosition; + mState.mCursorPosition = GetActualCursorCoordinates(); + auto line = mState.mCursorPosition.mLine; + auto cindex = GetCharacterIndex(mState.mCursorPosition); + + while (aAmount-- > 0) { + if (cindex == 0) { + if (line > 0) { + --line; + if ((int)mLines.size() > line) + cindex = (int)mLines[line].size(); + else + cindex = 0; + } + } else { + --cindex; + if (cindex > 0) { + if ((int)mLines.size() > line) { + while (cindex > 0 && IsUTFSequence(mLines[line][cindex].mChar)) + --cindex; + } + } + } + + mState.mCursorPosition = Coordinates(line, GetCharacterColumn(line, cindex)); + if (aWordMode) { + mState.mCursorPosition = FindWordStart(mState.mCursorPosition); + cindex = GetCharacterIndex(mState.mCursorPosition); + } + } + + mState.mCursorPosition = Coordinates(line, GetCharacterColumn(line, cindex)); + + ASSERT(mState.mCursorPosition.mColumn >= 0); + if (aSelect) { + if (oldPos == mInteractiveStart) + mInteractiveStart = mState.mCursorPosition; + else if (oldPos == mInteractiveEnd) + mInteractiveEnd = mState.mCursorPosition; + else { + mInteractiveStart = mState.mCursorPosition; + mInteractiveEnd = oldPos; + } + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd, + aSelect && aWordMode ? SelectionMode::Word : SelectionMode::Normal); + + EnsureCursorVisible(); +} + +void TextEditor::MoveRight(int aAmount, bool aSelect, bool aWordMode) { + auto oldPos = mState.mCursorPosition; + + if (mLines.empty() || oldPos.mLine >= mLines.size()) + return; + + auto cindex = GetCharacterIndex(mState.mCursorPosition); + while (aAmount-- > 0) { + auto lindex = mState.mCursorPosition.mLine; + auto& line = mLines[lindex]; + + if (cindex >= line.size()) { + if (mState.mCursorPosition.mLine < mLines.size() - 1) { + mState.mCursorPosition.mLine = + std::max(0, std::min((int)mLines.size() - 1, mState.mCursorPosition.mLine + 1)); + mState.mCursorPosition.mColumn = 0; + } else + return; + } else { + cindex += UTF8CharLength(line[cindex].mChar); + mState.mCursorPosition = Coordinates(lindex, GetCharacterColumn(lindex, cindex)); + if (aWordMode) + mState.mCursorPosition = FindNextWord(mState.mCursorPosition); + } + } + + if (aSelect) { + if (oldPos == mInteractiveEnd) + mInteractiveEnd = SanitizeCoordinates(mState.mCursorPosition); + else if (oldPos == mInteractiveStart) + mInteractiveStart = mState.mCursorPosition; + else { + mInteractiveStart = oldPos; + mInteractiveEnd = mState.mCursorPosition; + } + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd, + aSelect && aWordMode ? SelectionMode::Word : SelectionMode::Normal); + + EnsureCursorVisible(); +} + +void TextEditor::MoveTop(bool aSelect) { + auto oldPos = mState.mCursorPosition; + SetCursorPosition(Coordinates(0, 0)); + + if (mState.mCursorPosition != oldPos) { + if (aSelect) { + mInteractiveEnd = oldPos; + mInteractiveStart = mState.mCursorPosition; + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd); + } +} + +void TextEditor::TextEditor::MoveBottom(bool aSelect) { + auto oldPos = GetCursorPosition(); + auto newPos = Coordinates((int)mLines.size() - 1, 0); + SetCursorPosition(newPos); + if (aSelect) { + mInteractiveStart = oldPos; + mInteractiveEnd = newPos; + } else + mInteractiveStart = mInteractiveEnd = newPos; + SetSelection(mInteractiveStart, mInteractiveEnd); +} + +void TextEditor::MoveHome(bool aSelect) { + auto oldPos = mState.mCursorPosition; + SetCursorPosition(Coordinates(mState.mCursorPosition.mLine, 0)); + + if (mState.mCursorPosition != oldPos) { + if (aSelect) { + if (oldPos == mInteractiveStart) + mInteractiveStart = mState.mCursorPosition; + else if (oldPos == mInteractiveEnd) + mInteractiveEnd = mState.mCursorPosition; + else { + mInteractiveStart = mState.mCursorPosition; + mInteractiveEnd = oldPos; + } + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd); + } +} + +void TextEditor::MoveEnd(bool aSelect) { + auto oldPos = mState.mCursorPosition; + SetCursorPosition(Coordinates(mState.mCursorPosition.mLine, GetLineMaxColumn(oldPos.mLine))); + + if (mState.mCursorPosition != oldPos) { + if (aSelect) { + if (oldPos == mInteractiveEnd) + mInteractiveEnd = mState.mCursorPosition; + else if (oldPos == mInteractiveStart) + mInteractiveStart = mState.mCursorPosition; + else { + mInteractiveStart = oldPos; + mInteractiveEnd = mState.mCursorPosition; + } + } else + mInteractiveStart = mInteractiveEnd = mState.mCursorPosition; + SetSelection(mInteractiveStart, mInteractiveEnd); + } +} + +void TextEditor::Delete() { + ASSERT(!mReadOnly); + + if (mLines.empty()) + return; + + UndoRecord u; + u.mBefore = mState; + + if (HasSelection()) { + u.mRemoved = GetSelectedText(); + u.mRemovedStart = mState.mSelectionStart; + u.mRemovedEnd = mState.mSelectionEnd; + + DeleteSelection(); + } else { + auto pos = GetActualCursorCoordinates(); + SetCursorPosition(pos); + auto& line = mLines[pos.mLine]; + + if (pos.mColumn == GetLineMaxColumn(pos.mLine)) { + if (pos.mLine == (int)mLines.size() - 1) + return; + + u.mRemoved = '\n'; + u.mRemovedStart = u.mRemovedEnd = GetActualCursorCoordinates(); + Advance(u.mRemovedEnd); + + auto& nextLine = mLines[pos.mLine + 1]; + line.insert(line.end(), nextLine.begin(), nextLine.end()); + RemoveLine(pos.mLine + 1); + } else { + auto cindex = GetCharacterIndex(pos); + u.mRemovedStart = u.mRemovedEnd = GetActualCursorCoordinates(); + u.mRemovedEnd.mColumn++; + u.mRemoved = GetText(u.mRemovedStart, u.mRemovedEnd); + + auto d = UTF8CharLength(line[cindex].mChar); + while (d-- > 0 && cindex < (int)line.size()) + line.erase(line.begin() + cindex); + } + + mTextChanged = true; + + Colorize(pos.mLine, 1); + } + + u.mAfter = mState; + AddUndo(u); +} + +void TextEditor::Backspace() { + ASSERT(!mReadOnly); + + if (mLines.empty()) + return; + + UndoRecord u; + u.mBefore = mState; + + if (HasSelection()) { + u.mRemoved = GetSelectedText(); + u.mRemovedStart = mState.mSelectionStart; + u.mRemovedEnd = mState.mSelectionEnd; + + DeleteSelection(); + } else { + auto pos = GetActualCursorCoordinates(); + SetCursorPosition(pos); + + if (mState.mCursorPosition.mColumn == 0) { + if (mState.mCursorPosition.mLine == 0) + return; + + u.mRemoved = '\n'; + u.mRemovedStart = u.mRemovedEnd = + Coordinates(pos.mLine - 1, GetLineMaxColumn(pos.mLine - 1)); + Advance(u.mRemovedEnd); + + auto& line = mLines[mState.mCursorPosition.mLine]; + auto& prevLine = mLines[mState.mCursorPosition.mLine - 1]; + auto prevSize = GetLineMaxColumn(mState.mCursorPosition.mLine - 1); + prevLine.insert(prevLine.end(), line.begin(), line.end()); + + ErrorMarkers etmp; + for (auto& i : mErrorMarkers) + etmp.insert(ErrorMarkers::value_type( + i.first - 1 == mState.mCursorPosition.mLine ? i.first - 1 : i.first, i.second)); + mErrorMarkers = std::move(etmp); + + RemoveLine(mState.mCursorPosition.mLine); + --mState.mCursorPosition.mLine; + mState.mCursorPosition.mColumn = prevSize; + } else { + auto& line = mLines[mState.mCursorPosition.mLine]; + auto cindex = GetCharacterIndex(pos) - 1; + auto cend = cindex + 1; + while (cindex > 0 && IsUTFSequence(line[cindex].mChar)) + --cindex; + + // if (cindex > 0 && UTF8CharLength(line[cindex].mChar) > 1) + // --cindex; + + u.mRemovedStart = u.mRemovedEnd = GetActualCursorCoordinates(); + --u.mRemovedStart.mColumn; + --mState.mCursorPosition.mColumn; + + while (cindex < line.size() && cend-- > cindex) { + u.mRemoved += line[cindex].mChar; + line.erase(line.begin() + cindex); + } + } + + mTextChanged = true; + + EnsureCursorVisible(); + Colorize(mState.mCursorPosition.mLine, 1); + } + + u.mAfter = mState; + AddUndo(u); +} + +void TextEditor::SelectWordUnderCursor() { + auto c = GetCursorPosition(); + SetSelection(FindWordStart(c), FindWordEnd(c)); +} + +void TextEditor::SelectAll() { + SetSelection(Coordinates(0, 0), Coordinates((int)mLines.size(), 0)); +} + +bool TextEditor::HasSelection() const { + return mState.mSelectionEnd > mState.mSelectionStart; +} + +void TextEditor::Copy() { + if (HasSelection()) { + ImGui::SetClipboardText(GetSelectedText().c_str()); + } else { + if (!mLines.empty()) { + std::string str; + auto& line = mLines[GetActualCursorCoordinates().mLine]; + for (auto& g : line) + str.push_back(g.mChar); + ImGui::SetClipboardText(str.c_str()); + } + } +} + +void TextEditor::Cut() { + if (IsReadOnly()) { + Copy(); + } else { + if (HasSelection()) { + UndoRecord u; + u.mBefore = mState; + u.mRemoved = GetSelectedText(); + u.mRemovedStart = mState.mSelectionStart; + u.mRemovedEnd = mState.mSelectionEnd; + + Copy(); + DeleteSelection(); + + u.mAfter = mState; + AddUndo(u); + } + } +} + +void TextEditor::Paste() { + if (IsReadOnly()) + return; + + auto clipText = ImGui::GetClipboardText(); + if (clipText != nullptr && strlen(clipText) > 0) { + UndoRecord u; + u.mBefore = mState; + + if (HasSelection()) { + u.mRemoved = GetSelectedText(); + u.mRemovedStart = mState.mSelectionStart; + u.mRemovedEnd = mState.mSelectionEnd; + DeleteSelection(); + } + + u.mAdded = clipText; + u.mAddedStart = GetActualCursorCoordinates(); + + InsertText(clipText); + + u.mAddedEnd = GetActualCursorCoordinates(); + u.mAfter = mState; + AddUndo(u); + } +} + +bool TextEditor::CanUndo() const { + return !mReadOnly && mUndoIndex > 0; +} + +bool TextEditor::CanRedo() const { + return !mReadOnly && mUndoIndex < (int)mUndoBuffer.size(); +} + +void TextEditor::Undo(int aSteps) { + while (CanUndo() && aSteps-- > 0) + mUndoBuffer[--mUndoIndex].Undo(this); +} + +void TextEditor::Redo(int aSteps) { + while (CanRedo() && aSteps-- > 0) + mUndoBuffer[mUndoIndex++].Redo(this); +} + +const TextEditor::Palette& TextEditor::GetDarkPalette() { + const static Palette p = {{ + 0xff7f7f7f, // Default + 0xffd69c56, // Keyword + 0xff00ff00, // Number + 0xff7070e0, // String + 0xff70a0e0, // Char literal + 0xffffffff, // Punctuation + 0xff408080, // Preprocessor + 0xffaaaaaa, // Identifier + 0xff9bc64d, // Known identifier + 0xffc040a0, // Preproc identifier + 0xff206020, // Comment (single line) + 0xff406020, // Comment (multi line) + 0xff101010, // Background + 0xffe0e0e0, // Cursor + 0x80a06020, // Selection + 0x800020ff, // ErrorMarker + 0x40f08000, // Breakpoint + 0xff707000, // Line number + 0x40000000, // Current line fill + 0x40808080, // Current line fill (inactive) + 0x40a0a0a0, // Current line edge + }}; + return p; +} + +const TextEditor::Palette& TextEditor::GetLightPalette() { + const static Palette p = {{ + 0xff7f7f7f, // None + 0xffff0c06, // Keyword + 0xff008000, // Number + 0xff2020a0, // String + 0xff304070, // Char literal + 0xff000000, // Punctuation + 0xff406060, // Preprocessor + 0xff404040, // Identifier + 0xff606010, // Known identifier + 0xffc040a0, // Preproc identifier + 0xff205020, // Comment (single line) + 0xff405020, // Comment (multi line) + 0xffffffff, // Background + 0xff000000, // Cursor + 0x80600000, // Selection + 0xa00010ff, // ErrorMarker + 0x80f08000, // Breakpoint + 0xff505000, // Line number + 0x40000000, // Current line fill + 0x40808080, // Current line fill (inactive) + 0x40000000, // Current line edge + }}; + return p; +} + +const TextEditor::Palette& TextEditor::GetRetroBluePalette() { + const static Palette p = {{ + 0xff00ffff, // None + 0xffffff00, // Keyword + 0xff00ff00, // Number + 0xff808000, // String + 0xff808000, // Char literal + 0xffffffff, // Punctuation + 0xff008000, // Preprocessor + 0xff00ffff, // Identifier + 0xffffffff, // Known identifier + 0xffff00ff, // Preproc identifier + 0xff808080, // Comment (single line) + 0xff404040, // Comment (multi line) + 0xff800000, // Background + 0xff0080ff, // Cursor + 0x80ffff00, // Selection + 0xa00000ff, // ErrorMarker + 0x80ff8000, // Breakpoint + 0xff808000, // Line number + 0x40000000, // Current line fill + 0x40808080, // Current line fill (inactive) + 0x40000000, // Current line edge + }}; + return p; +} + +std::string TextEditor::GetText() const { + return GetText(Coordinates(), Coordinates((int)mLines.size(), 0)); +} + +std::vector TextEditor::GetTextLines() const { + std::vector result; + + result.reserve(mLines.size()); + + for (auto& line : mLines) { + std::string text; + + text.resize(line.size()); + + for (size_t i = 0; i < line.size(); ++i) + text[i] = line[i].mChar; + + result.emplace_back(std::move(text)); + } + + return result; +} + +std::string TextEditor::GetSelectedText() const { + return GetText(mState.mSelectionStart, mState.mSelectionEnd); +} + +std::string TextEditor::GetCurrentLineText() const { + auto lineLength = GetLineMaxColumn(mState.mCursorPosition.mLine); + return GetText(Coordinates(mState.mCursorPosition.mLine, 0), + Coordinates(mState.mCursorPosition.mLine, lineLength)); +} + +void TextEditor::ProcessInputs() {} + +void TextEditor::Colorize(int aFromLine, int aLines) { + int toLine = + aLines == -1 ? (int)mLines.size() : std::min((int)mLines.size(), aFromLine + aLines); + mColorRangeMin = std::min(mColorRangeMin, aFromLine); + mColorRangeMax = std::max(mColorRangeMax, toLine); + mColorRangeMin = std::max(0, mColorRangeMin); + mColorRangeMax = std::max(mColorRangeMin, mColorRangeMax); + mCheckComments = true; +} + +void TextEditor::ColorizeRange(int aFromLine, int aToLine) { + if (mLines.empty() || aFromLine >= aToLine) + return; + + std::string buffer; + std::cmatch results; + std::string id; + + int endLine = std::max(0, std::min((int)mLines.size(), aToLine)); + for (int i = aFromLine; i < endLine; ++i) { + auto& line = mLines[i]; + + if (line.empty()) + continue; + + buffer.resize(line.size()); + for (size_t j = 0; j < line.size(); ++j) { + auto& col = line[j]; + buffer[j] = col.mChar; + col.mColorIndex = PaletteIndex::Default; + } + + const char* bufferBegin = &buffer.front(); + const char* bufferEnd = bufferBegin + buffer.size(); + + auto last = bufferEnd; + + for (auto first = bufferBegin; first != last;) { + const char* token_begin = nullptr; + const char* token_end = nullptr; + PaletteIndex token_color = PaletteIndex::Default; + + bool hasTokenizeResult = false; + + if (mLanguageDefinition.mTokenize != nullptr) { + if (mLanguageDefinition.mTokenize(first, last, token_begin, token_end, token_color)) + hasTokenizeResult = true; + } + + if (hasTokenizeResult == false) { + // todo : remove + // printf("using regex for %.*s\n", first + 10 < last ? 10 : int(last - first), + // first); + + for (auto& p : mRegexList) { + if (std::regex_search(first, last, results, p.first, + std::regex_constants::match_continuous)) { + hasTokenizeResult = true; + + auto& v = *results.begin(); + token_begin = v.first; + token_end = v.second; + token_color = p.second; + break; + } + } + } + + if (hasTokenizeResult == false) { + first++; + } else { + const size_t token_length = token_end - token_begin; + + if (token_color == PaletteIndex::Identifier) { + id.assign(token_begin, token_end); + + // todo : allmost all language definitions use lower case to specify keywords, + // so shouldn't this use ::tolower ? + if (!mLanguageDefinition.mCaseSensitive) + std::transform(id.begin(), id.end(), id.begin(), ::toupper); + + if (!line[first - bufferBegin].mPreprocessor) { + if (mLanguageDefinition.mKeywords.count(id) != 0) + token_color = PaletteIndex::Keyword; + else if (mLanguageDefinition.mIdentifiers.count(id) != 0) + token_color = PaletteIndex::KnownIdentifier; + else if (mLanguageDefinition.mPreprocIdentifiers.count(id) != 0) + token_color = PaletteIndex::PreprocIdentifier; + } else { + if (mLanguageDefinition.mPreprocIdentifiers.count(id) != 0) + token_color = PaletteIndex::PreprocIdentifier; + } + } + + for (size_t j = 0; j < token_length; ++j) + line[(token_begin - bufferBegin) + j].mColorIndex = token_color; + + first = token_end; + } + } + } +} + +void TextEditor::ColorizeInternal() { + if (mLines.empty() || !mColorizerEnabled) + return; + + if (mCheckComments) { + auto endLine = mLines.size(); + auto endIndex = 0; + auto commentStartLine = endLine; + auto commentStartIndex = endIndex; + auto withinString = false; + auto withinSingleLineComment = false; + auto withinPreproc = false; + auto firstChar = true; // there is no other non-whitespace characters in the line before + auto concatenate = false; // '\' on the very end of the line + auto currentLine = 0; + auto currentIndex = 0; + while (currentLine < endLine || currentIndex < endIndex) { + auto& line = mLines[currentLine]; + + if (currentIndex == 0 && !concatenate) { + withinSingleLineComment = false; + withinPreproc = false; + firstChar = true; + } + + concatenate = false; + + if (!line.empty()) { + auto& g = line[currentIndex]; + auto c = g.mChar; + + if (c != mLanguageDefinition.mPreprocChar && !isspace(c)) + firstChar = false; + + if (currentIndex == (int)line.size() - 1 && line[line.size() - 1].mChar == '\\') + concatenate = true; + + bool inComment = + (commentStartLine < currentLine || + (commentStartLine == currentLine && commentStartIndex <= currentIndex)); + + if (withinString) { + line[currentIndex].mMultiLineComment = inComment; + + if (c == '\"') { + if (currentIndex + 1 < (int)line.size() && + line[currentIndex + 1].mChar == '\"') { + currentIndex += 1; + if (currentIndex < (int)line.size()) + line[currentIndex].mMultiLineComment = inComment; + } else + withinString = false; + } else if (c == '\\') { + currentIndex += 1; + if (currentIndex < (int)line.size()) + line[currentIndex].mMultiLineComment = inComment; + } + } else { + if (firstChar && c == mLanguageDefinition.mPreprocChar) + withinPreproc = true; + + if (c == '\"') { + withinString = true; + line[currentIndex].mMultiLineComment = inComment; + } else { + auto pred = [](const char& a, const Glyph& b) { return a == b.mChar; }; + auto from = line.begin() + currentIndex; + auto& startStr = mLanguageDefinition.mCommentStart; + auto& singleStartStr = mLanguageDefinition.mSingleLineComment; + + if (singleStartStr.size() > 0 && + currentIndex + singleStartStr.size() <= line.size() && + equals(singleStartStr.begin(), singleStartStr.end(), from, + from + singleStartStr.size(), pred)) { + withinSingleLineComment = true; + } else if (!withinSingleLineComment && + currentIndex + startStr.size() <= line.size() && + equals(startStr.begin(), startStr.end(), from, + from + startStr.size(), pred)) { + commentStartLine = currentLine; + commentStartIndex = currentIndex; + } + + inComment = inComment = + (commentStartLine < currentLine || (commentStartLine == currentLine && + commentStartIndex <= currentIndex)); + + line[currentIndex].mMultiLineComment = inComment; + line[currentIndex].mComment = withinSingleLineComment; + + auto& endStr = mLanguageDefinition.mCommentEnd; + if (currentIndex + 1 >= (int)endStr.size() && + equals(endStr.begin(), endStr.end(), from + 1 - endStr.size(), from + 1, + pred)) { + commentStartIndex = endIndex; + commentStartLine = endLine; + } + } + } + line[currentIndex].mPreprocessor = withinPreproc; + currentIndex += UTF8CharLength(c); + if (currentIndex >= (int)line.size()) { + currentIndex = 0; + ++currentLine; + } + } else { + currentIndex = 0; + ++currentLine; + } + } + mCheckComments = false; + } + + if (mColorRangeMin < mColorRangeMax) { + const int increment = (mLanguageDefinition.mTokenize == nullptr) ? 10 : 10000; + const int to = std::min(mColorRangeMin + increment, mColorRangeMax); + ColorizeRange(mColorRangeMin, to); + mColorRangeMin = to; + + if (mColorRangeMax == mColorRangeMin) { + mColorRangeMin = std::numeric_limits::max(); + mColorRangeMax = 0; + } + return; + } +} + +float TextEditor::TextDistanceToLineStart(const Coordinates& aFrom) const { + auto& line = mLines[aFrom.mLine]; + float distance = 0.0f; + float spaceSize = + ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr) + .x; + int colIndex = GetCharacterIndex(aFrom); + for (size_t it = 0u; it < line.size() && it < colIndex;) { + if (line[it].mChar == '\t') { + distance = (1.0f + std::floor((1.0f + distance) / (float(mTabSize) * spaceSize))) * + (float(mTabSize) * spaceSize); + ++it; + } else { + auto d = UTF8CharLength(line[it].mChar); + char tempCString[7]; + int i = 0; + for (; i < 6 && d-- > 0 && it < (int)line.size(); i++, it++) + tempCString[i] = line[it].mChar; + + tempCString[i] = '\0'; + distance += ImGui::GetFont() + ->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, tempCString, + nullptr, nullptr) + .x; + } + } + + return distance; +} + +void TextEditor::EnsureCursorVisible() { + if (!mWithinRender) { + mScrollToCursor = true; + return; + } + + float scrollX = ImGui::GetScrollX(); + float scrollY = ImGui::GetScrollY(); + + auto height = ImGui::GetWindowHeight(); + auto width = ImGui::GetWindowWidth(); + + auto top = 1 + (int)ceil(scrollY / mCharAdvance.y); + auto bottom = (int)ceil((scrollY + height) / mCharAdvance.y); + + auto left = (int)ceil(scrollX / mCharAdvance.x); + auto right = (int)ceil((scrollX + width) / mCharAdvance.x); + + auto pos = GetActualCursorCoordinates(); + auto len = TextDistanceToLineStart(pos); + + if (pos.mLine < top) + ImGui::SetScrollY(std::max(0.0f, (pos.mLine - 1) * mCharAdvance.y)); + if (pos.mLine > bottom - 4) + ImGui::SetScrollY(std::max(0.0f, (pos.mLine + 4) * mCharAdvance.y - height)); + if (len + mTextStart < left + 4) + ImGui::SetScrollX(std::max(0.0f, len + mTextStart - 4)); + if (len + mTextStart > right - 4) + ImGui::SetScrollX(std::max(0.0f, len + mTextStart + 4 - width)); +} + +int TextEditor::GetPageSize() const { + auto height = ImGui::GetWindowHeight() - 20.0f; + return (int)floor(height / mCharAdvance.y); +} + +TextEditor::UndoRecord::UndoRecord( + const std::string& aAdded, const TextEditor::Coordinates aAddedStart, + const TextEditor::Coordinates aAddedEnd, const std::string& aRemoved, + const TextEditor::Coordinates aRemovedStart, const TextEditor::Coordinates aRemovedEnd, + TextEditor::EditorState& aBefore, TextEditor::EditorState& aAfter) + : mAdded(aAdded), mAddedStart(aAddedStart), mAddedEnd(aAddedEnd), mRemoved(aRemoved), + mRemovedStart(aRemovedStart), mRemovedEnd(aRemovedEnd), mBefore(aBefore), mAfter(aAfter) { + ASSERT(mAddedStart <= mAddedEnd); + ASSERT(mRemovedStart <= mRemovedEnd); +} + +void TextEditor::UndoRecord::Undo(TextEditor* aEditor) { + if (!mAdded.empty()) { + aEditor->DeleteRange(mAddedStart, mAddedEnd); + aEditor->Colorize(mAddedStart.mLine - 1, mAddedEnd.mLine - mAddedStart.mLine + 2); + } + + if (!mRemoved.empty()) { + auto start = mRemovedStart; + aEditor->InsertTextAt(start, mRemoved.c_str()); + aEditor->Colorize(mRemovedStart.mLine - 1, mRemovedEnd.mLine - mRemovedStart.mLine + 2); + } + + aEditor->mState = mBefore; + aEditor->EnsureCursorVisible(); +} + +void TextEditor::UndoRecord::Redo(TextEditor* aEditor) { + if (!mRemoved.empty()) { + aEditor->DeleteRange(mRemovedStart, mRemovedEnd); + aEditor->Colorize(mRemovedStart.mLine - 1, mRemovedEnd.mLine - mRemovedStart.mLine + 1); + } + + if (!mAdded.empty()) { + auto start = mAddedStart; + aEditor->InsertTextAt(start, mAdded.c_str()); + aEditor->Colorize(mAddedStart.mLine - 1, mAddedEnd.mLine - mAddedStart.mLine + 1); + } + + aEditor->mState = mAfter; + aEditor->EnsureCursorVisible(); +} + +const TextEditor::LanguageDefinition& TextEditor::LanguageDefinition::GLSL() { + static bool inited = false; + static LanguageDefinition langDef; + if (!inited) { + static const char* const keywords[] = { + "auto", "break", "case", "char", "const", "continue", + "default", "do", "double", "else", "enum", "extern", + "float", "for", "goto", "if", "inline", "int", + "long", "register", "restrict", "return", "short", "signed", + "sizeof", "static", "struct", "switch", "typedef", "union", + "unsigned", "void", "volatile", "while", "_Alignas", "_Alignof", + "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn", + "_Static_assert", "_Thread_local"}; + for (auto& k : keywords) + langDef.mKeywords.insert(k); + + static const char* const identifiers[] = { + "abort", "abs", "acos", "asin", "atan", "atexit", "atof", + "atoi", "atol", "ceil", "clock", "cosh", "ctime", "div", + "exit", "fabs", "floor", "fmod", "getchar", "getenv", "isalnum", + "isalpha", "isdigit", "isgraph", "ispunct", "isspace", "isupper", "kbhit", + "log10", "log2", "log", "memcmp", "modf", "pow", "putchar", + "putenv", "puts", "rand", "remove", "rename", "sinh", "sqrt", + "srand", "strcat", "strcmp", "strerror", "time", "tolower", "toupper"}; + for (auto& k : identifiers) { + Identifier id; + id.mDeclaration = "Built-in function"; + langDef.mIdentifiers.insert(std::make_pair(std::string(k), id)); + } + + langDef.mTokenRegexStrings.push_back(std::make_pair( + "[ \\t]*#[ \\t]*[a-zA-Z_]+", PaletteIndex::Preprocessor)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "L?\\\"(\\\\.|[^\\\"])*\\\"", PaletteIndex::String)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "\\'\\\\?[^\\']\\'", PaletteIndex::CharLiteral)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?", PaletteIndex::Number)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "[+-]?[0-9]+[Uu]?[lL]?[lL]?", PaletteIndex::Number)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "0[0-7]+[Uu]?[lL]?[lL]?", PaletteIndex::Number)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?", PaletteIndex::Number)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "[a-zA-Z_][a-zA-Z0-9_]*", PaletteIndex::Identifier)); + langDef.mTokenRegexStrings.push_back(std::make_pair( + "[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/\\;\\,\\.]", + PaletteIndex::Punctuation)); + + langDef.mCommentStart = "/*"; + langDef.mCommentEnd = "*/"; + langDef.mSingleLineComment = "//"; + + langDef.mCaseSensitive = true; + langDef.mAutoIndentation = true; + + langDef.mName = "GLSL"; + + inited = true; + } + return langDef; +} + +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/text_editor.h b/src/core/devtools/widget/text_editor.h new file mode 100644 index 000000000..5c3f29f11 --- /dev/null +++ b/src/core/devtools/widget/text_editor.h @@ -0,0 +1,408 @@ +// SPDX-FileCopyrightText: Copyright (c) 2017 BalazsJako +// SPDX-License-Identifier: MIT + +// source: https://github.com/BalazsJako/ImGuiColorTextEdit + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/assert.h" +#include "imgui.h" + +namespace Core::Devtools::Widget { + +class TextEditor { +public: + enum class PaletteIndex { + Default, + Keyword, + Number, + String, + CharLiteral, + Punctuation, + Preprocessor, + Identifier, + KnownIdentifier, + PreprocIdentifier, + Comment, + MultiLineComment, + Background, + Cursor, + Selection, + ErrorMarker, + Breakpoint, + LineNumber, + CurrentLineFill, + CurrentLineFillInactive, + CurrentLineEdge, + Max + }; + + enum class SelectionMode { Normal, Word, Line }; + + struct Breakpoint { + int mLine; + bool mEnabled; + std::string mCondition; + + Breakpoint() : mLine(-1), mEnabled(false) {} + }; + + // Represents a character coordinate from the user's point of view, + // i. e. consider an uniform grid (assuming fixed-width font) on the + // screen as it is rendered, and each cell has its own coordinate, starting from 0. + // Tabs are counted as [1..mTabSize] count empty spaces, depending on + // how many space is necessary to reach the next tab stop. + // For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize + // = 4, because it is rendered as " ABC" on the screen. + struct Coordinates { + int mLine, mColumn; + Coordinates() : mLine(0), mColumn(0) {} + Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn) { + ASSERT(aLine >= 0); + ASSERT(aColumn >= 0); + } + static Coordinates Invalid() { + static Coordinates invalid(-1, -1); + return invalid; + } + + bool operator==(const Coordinates& o) const { + return mLine == o.mLine && mColumn == o.mColumn; + } + + bool operator!=(const Coordinates& o) const { + return mLine != o.mLine || mColumn != o.mColumn; + } + + bool operator<(const Coordinates& o) const { + if (mLine != o.mLine) + return mLine < o.mLine; + return mColumn < o.mColumn; + } + + bool operator>(const Coordinates& o) const { + if (mLine != o.mLine) + return mLine > o.mLine; + return mColumn > o.mColumn; + } + + bool operator<=(const Coordinates& o) const { + if (mLine != o.mLine) + return mLine < o.mLine; + return mColumn <= o.mColumn; + } + + bool operator>=(const Coordinates& o) const { + if (mLine != o.mLine) + return mLine > o.mLine; + return mColumn >= o.mColumn; + } + }; + + struct Identifier { + Coordinates mLocation; + std::string mDeclaration; + }; + + typedef std::string String; + typedef std::unordered_map Identifiers; + typedef std::unordered_set Keywords; + typedef std::map ErrorMarkers; + typedef std::unordered_set Breakpoints; + typedef std::array Palette; + typedef uint8_t Char; + + struct Glyph { + Char mChar; + PaletteIndex mColorIndex = PaletteIndex::Default; + bool mComment : 1; + bool mMultiLineComment : 1; + bool mPreprocessor : 1; + + Glyph(Char aChar, PaletteIndex aColorIndex) + : mChar(aChar), mColorIndex(aColorIndex), mComment(false), mMultiLineComment(false), + mPreprocessor(false) {} + }; + + typedef std::vector Line; + typedef std::vector Lines; + + struct LanguageDefinition { + typedef std::pair TokenRegexString; + typedef std::vector TokenRegexStrings; + typedef bool (*TokenizeCallback)(const char* in_begin, const char* in_end, + const char*& out_begin, const char*& out_end, + PaletteIndex& paletteIndex); + + std::string mName; + Keywords mKeywords; + Identifiers mIdentifiers; + Identifiers mPreprocIdentifiers; + std::string mCommentStart, mCommentEnd, mSingleLineComment; + char mPreprocChar; + bool mAutoIndentation; + + TokenizeCallback mTokenize; + + TokenRegexStrings mTokenRegexStrings; + + bool mCaseSensitive; + + LanguageDefinition() + : mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true) {} + + static const LanguageDefinition& GLSL(); + }; + + TextEditor(); + ~TextEditor(); + + void SetLanguageDefinition(const LanguageDefinition& aLanguageDef); + const LanguageDefinition& GetLanguageDefinition() const { + return mLanguageDefinition; + } + + const Palette& GetPalette() const { + return mPaletteBase; + } + void SetPalette(const Palette& aValue); + + void SetErrorMarkers(const ErrorMarkers& aMarkers) { + mErrorMarkers = aMarkers; + } + void SetBreakpoints(const Breakpoints& aMarkers) { + mBreakpoints = aMarkers; + } + + void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false); + void SetText(const std::string& aText); + std::string GetText() const; + + void SetTextLines(const std::vector& aLines); + std::vector GetTextLines() const; + + std::string GetSelectedText() const; + std::string GetCurrentLineText() const; + + int GetTotalLines() const { + return (int)mLines.size(); + } + bool IsOverwrite() const { + return mOverwrite; + } + + void SetReadOnly(bool aValue); + bool IsReadOnly() const { + return mReadOnly; + } + bool IsTextChanged() const { + return mTextChanged; + } + bool IsCursorPositionChanged() const { + return mCursorPositionChanged; + } + + bool IsColorizerEnabled() const { + return mColorizerEnabled; + } + void SetColorizerEnable(bool aValue); + + Coordinates GetCursorPosition() const { + return GetActualCursorCoordinates(); + } + void SetCursorPosition(const Coordinates& aPosition); + + inline void SetHandleMouseInputs(bool aValue) { + mHandleMouseInputs = aValue; + } + inline bool IsHandleMouseInputsEnabled() const { + return mHandleKeyboardInputs; + } + + inline void SetHandleKeyboardInputs(bool aValue) { + mHandleKeyboardInputs = aValue; + } + inline bool IsHandleKeyboardInputsEnabled() const { + return mHandleKeyboardInputs; + } + + inline void SetImGuiChildIgnored(bool aValue) { + mIgnoreImGuiChild = aValue; + } + inline bool IsImGuiChildIgnored() const { + return mIgnoreImGuiChild; + } + + inline void SetShowWhitespaces(bool aValue) { + mShowWhitespaces = aValue; + } + inline bool IsShowingWhitespaces() const { + return mShowWhitespaces; + } + + void SetTabSize(int aValue); + inline int GetTabSize() const { + return mTabSize; + } + + void InsertText(const std::string& aValue); + void InsertText(const char* aValue); + + void MoveUp(int aAmount = 1, bool aSelect = false); + void MoveDown(int aAmount = 1, bool aSelect = false); + void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false); + void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false); + void MoveTop(bool aSelect = false); + void MoveBottom(bool aSelect = false); + void MoveHome(bool aSelect = false); + void MoveEnd(bool aSelect = false); + + void SetSelectionStart(const Coordinates& aPosition); + void SetSelectionEnd(const Coordinates& aPosition); + void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, + SelectionMode aMode = SelectionMode::Normal); + void SelectWordUnderCursor(); + void SelectAll(); + bool HasSelection() const; + + void Copy(); + void Cut(); + void Paste(); + void Delete(); + + bool CanUndo() const; + bool CanRedo() const; + void Undo(int aSteps = 1); + void Redo(int aSteps = 1); + + static const Palette& GetDarkPalette(); + static const Palette& GetLightPalette(); + static const Palette& GetRetroBluePalette(); + +private: + typedef std::vector> RegexList; + + struct EditorState { + Coordinates mSelectionStart; + Coordinates mSelectionEnd; + Coordinates mCursorPosition; + }; + + class UndoRecord { + public: + UndoRecord() {} + ~UndoRecord() {} + + UndoRecord(const std::string& aAdded, const TextEditor::Coordinates aAddedStart, + const TextEditor::Coordinates aAddedEnd, + + const std::string& aRemoved, const TextEditor::Coordinates aRemovedStart, + const TextEditor::Coordinates aRemovedEnd, + + TextEditor::EditorState& aBefore, TextEditor::EditorState& aAfter); + + void Undo(TextEditor* aEditor); + void Redo(TextEditor* aEditor); + + std::string mAdded; + Coordinates mAddedStart; + Coordinates mAddedEnd; + + std::string mRemoved; + Coordinates mRemovedStart; + Coordinates mRemovedEnd; + + EditorState mBefore; + EditorState mAfter; + }; + + typedef std::vector UndoBuffer; + + void ProcessInputs(); + void Colorize(int aFromLine = 0, int aCount = -1); + void ColorizeRange(int aFromLine = 0, int aToLine = 0); + void ColorizeInternal(); + float TextDistanceToLineStart(const Coordinates& aFrom) const; + void EnsureCursorVisible(); + int GetPageSize() const; + std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const; + Coordinates GetActualCursorCoordinates() const; + Coordinates SanitizeCoordinates(const Coordinates& aValue) const; + void Advance(Coordinates& aCoordinates) const; + void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd); + int InsertTextAt(Coordinates& aWhere, const char* aValue); + void AddUndo(UndoRecord& aValue); + Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const; + Coordinates FindWordStart(const Coordinates& aFrom) const; + Coordinates FindWordEnd(const Coordinates& aFrom) const; + Coordinates FindNextWord(const Coordinates& aFrom) const; + int GetCharacterIndex(const Coordinates& aCoordinates) const; + int GetCharacterColumn(int aLine, int aIndex) const; + int GetLineCharacterCount(int aLine) const; + int GetLineMaxColumn(int aLine) const; + bool IsOnWordBoundary(const Coordinates& aAt) const; + void RemoveLine(int aStart, int aEnd); + void RemoveLine(int aIndex); + Line& InsertLine(int aIndex); + void EnterCharacter(ImWchar aChar, bool aShift); + void Backspace(); + void DeleteSelection(); + std::string GetWordUnderCursor() const; + std::string GetWordAt(const Coordinates& aCoords) const; + ImU32 GetGlyphColor(const Glyph& aGlyph) const; + + void HandleKeyboardInputs(); + void HandleMouseInputs(); + void Render(); + + float mLineSpacing; + Lines mLines; + EditorState mState; + UndoBuffer mUndoBuffer; + int mUndoIndex; + + int mTabSize; + bool mOverwrite; + bool mReadOnly; + bool mWithinRender; + bool mScrollToCursor; + bool mScrollToTop; + bool mTextChanged; + bool mColorizerEnabled; + float mTextStart; // position (in pixels) where a code line starts relative to the left of the + // TextEditor. + int mLeftMargin; + bool mCursorPositionChanged; + int mColorRangeMin, mColorRangeMax; + SelectionMode mSelectionMode; + bool mHandleKeyboardInputs; + bool mHandleMouseInputs; + bool mIgnoreImGuiChild; + bool mShowWhitespaces; + + Palette mPaletteBase; + Palette mPalette; + LanguageDefinition mLanguageDefinition; + RegexList mRegexList; + + bool mCheckComments; + Breakpoints mBreakpoints; + ErrorMarkers mErrorMarkers; + ImVec2 mCharAdvance; + Coordinates mInteractiveStart, mInteractiveEnd; + std::string mLineBuffer; + uint64_t mStartTime; + + float mLastClick; +}; + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp index 336d81019..0ae9f57eb 100644 --- a/src/core/file_format/pkg.cpp +++ b/src/core/file_format/pkg.cpp @@ -3,6 +3,7 @@ #include #include "common/io_file.h" +#include "common/logging/formatter.h" #include "core/file_format/pkg.h" #include "core/file_format/pkg_type.h" @@ -44,7 +45,7 @@ PKG::PKG() = default; PKG::~PKG() = default; -bool PKG::Open(const std::filesystem::path& filepath) { +bool PKG::Open(const std::filesystem::path& filepath, std::string& failreason) { Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); if (!file.IsOpen()) { return false; @@ -67,21 +68,32 @@ bool PKG::Open(const std::filesystem::path& filepath) { file.Seek(0x47); // skip first 7 characters of content_id file.Read(pkgTitleID); - file.Seek(0); - pkg.resize(pkgheader.pkg_promote_size); - file.Read(pkg); - u32 offset = pkgheader.pkg_table_entry_offset; u32 n_files = pkgheader.pkg_table_entry_count; + + if (!file.Seek(offset)) { + failreason = "Failed to seek to PKG table entry offset"; + return false; + } + for (int i = 0; i < n_files; i++) { - PKGEntry entry; - std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry)); + PKGEntry entry{}; + file.Read(entry.id); + file.Read(entry.filename_offset); + file.Read(entry.flags1); + file.Read(entry.flags2); + file.Read(entry.offset); + file.Read(entry.size); + file.Seek(8, Common::FS::SeekOrigin::CurrentPosition); // Try to figure out the name const auto name = GetEntryNameByType(entry.id); if (name == "param.sfo") { sfo.clear(); - file.Seek(entry.offset); + if (!file.Seek(entry.offset)) { + failreason = "Failed to seek to param.sfo offset"; + return false; + } sfo.resize(entry.size); file.ReadRaw(sfo.data(), entry.size); } @@ -113,9 +125,6 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: failreason = "Content size is bigger than pkg size"; return false; } - file.Seek(0); - pkg.resize(pkgheader.pkg_promote_size); - file.Read(pkg); u32 offset = pkgheader.pkg_table_entry_offset; u32 n_files = pkgheader.pkg_table_entry_count; @@ -126,9 +135,22 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: std::array, 7> key1; std::array imgkeydata; + if (!file.Seek(offset)) { + failreason = "Failed to seek to PKG table entry offset"; + return false; + } + for (int i = 0; i < n_files; i++) { - PKGEntry entry; - std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry)); + PKGEntry entry{}; + file.Read(entry.id); + file.Read(entry.filename_offset); + file.Read(entry.flags1); + file.Read(entry.flags2); + file.Read(entry.offset); + file.Read(entry.size); + file.Seek(8, Common::FS::SeekOrigin::CurrentPosition); + + auto currentPos = file.Tell(); // Try to figure out the name const auto name = GetEntryNameByType(entry.id); @@ -139,8 +161,18 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: // Just print with id Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id), Common::FS::FileAccessMode::Write); - out.WriteRaw(pkg.data() + entry.offset, entry.size); + if (!file.Seek(entry.offset)) { + failreason = "Failed to seek to PKG entry offset"; + return false; + } + + std::vector data; + data.resize(entry.size); + file.ReadRaw(data.data(), entry.size); + out.WriteRaw(data.data(), entry.size); out.Close(); + + file.Seek(currentPos); continue; } @@ -178,14 +210,31 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: } Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write); - out.WriteRaw(pkg.data() + entry.offset, entry.size); + if (!file.Seek(entry.offset)) { + failreason = "Failed to seek to PKG entry offset"; + return false; + } + + std::vector data; + data.resize(entry.size); + file.ReadRaw(data.data(), entry.size); + out.WriteRaw(data.data(), entry.size); out.Close(); // Decrypt Np stuff and overwrite. if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 || entry.id == 0x403) { // somehow 0x401 is not decrypting decNp.resize(entry.size); - std::span cipherNp(pkg.data() + entry.offset, entry.size); + if (!file.Seek(entry.offset)) { + failreason = "Failed to seek to PKG entry offset"; + return false; + } + + std::vector data; + data.resize(entry.size); + file.ReadRaw(data.data(), entry.size); + + std::span cipherNp(data.data(), entry.size); std::array concatenated_ivkey_dk3_; std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry)); std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_)); @@ -197,45 +246,47 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: out.Write(decNp); out.Close(); } - } - // Extract trophy files - if (!trp.Extract(extract_path)) { - // Do nothing some pkg come with no trp file. - // return false; + file.Seek(currentPos); } // Read the seed std::array seed; - file.Seek(pkgheader.pfs_image_offset + 0x370); + if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) { + failreason = "Failed to seek to PFS image offset"; + return false; + } file.Read(seed); // Get data and tweak keys. PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey); const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok. - // Read encrypted pfs_image - std::vector pfs_encrypted(length); - file.Seek(pkgheader.pfs_image_offset); - file.Read(pfs_encrypted); - file.Close(); - // Decrypt the pfs_image. - std::vector pfs_decrypted(length); - PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0); - - // Retrieve PFSC from decrypted pfs_image. - pfsc_offset = GetPFSCOffset(pfs_decrypted); + int num_blocks = 0; std::vector pfsc(length); - std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset); + if (length != 0) { + // Read encrypted pfs_image + std::vector pfs_encrypted(length); + file.Seek(pkgheader.pfs_image_offset); + file.Read(pfs_encrypted); + file.Close(); + // Decrypt the pfs_image. + std::vector pfs_decrypted(length); + PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0); - PFSCHdr pfsChdr; - std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr)); + // Retrieve PFSC from decrypted pfs_image. + pfsc_offset = GetPFSCOffset(pfs_decrypted); + std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset); - const int num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2); - sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset. + PFSCHdr pfsChdr; + std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr)); - for (int i = 0; i < num_blocks + 1; i++) { - std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8); + num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2); + sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset. + + for (int i = 0; i < num_blocks + 1; i++) { + std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8); + } } u32 ent_size = 0; @@ -279,8 +330,8 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: } } - // let's deal with the root/uroot enteries here. - // Sometimes it's more than 2 enteries (Tomb Raider Remastered) + // let's deal with the root/uroot entries here. + // Sometimes it's more than 2 entries (Tomb Raider Remastered) const std::string_view flat_path_table(&decompressedData[0x10], 15); if (flat_path_table == "flat_path_table") { uroot_reached = true; @@ -296,7 +347,16 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: } else { // Set the the folder according to the current inode. // Can be 2 or more (rarely) - extractPaths[ndinode_counter] = extract_path.parent_path() / GetTitleID(); + auto parent_path = extract_path.parent_path(); + auto title_id = GetTitleID(); + + if (parent_path.filename() != title_id && + !fmt::UTF(extract_path.u8string()).data.ends_with("-UPDATE")) { + extractPaths[ndinode_counter] = parent_path / title_id; + } else { + // DLCs path has different structure + extractPaths[ndinode_counter] = extract_path; + } uroot_reached = false; break; } @@ -330,8 +390,7 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem:: if (table.type == PFS_CURRENT_DIR) { current_dir = extractPaths[table.inode]; } - extractPaths[table.inode] = - current_dir.string() / std::filesystem::path(table.name); + extractPaths[table.inode] = current_dir / std::filesystem::path(table.name); if (table.type == PFS_FILE || table.type == PFS_DIR) { if (table.type == PFS_DIR) { // Create dirs. @@ -361,7 +420,7 @@ void PKG::ExtractFiles(const int index) { int bsize = iNodeBuf[inode_number].Size; Common::FS::IOFile inflated; - inflated.Open(extractPaths[inode_number].string(), Common::FS::FileAccessMode::Write); + inflated.Open(extractPaths[inode_number], Common::FS::FileAccessMode::Write); Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict. pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read); diff --git a/src/core/file_format/pkg.h b/src/core/file_format/pkg.h index b6b09a191..a488a2df8 100644 --- a/src/core/file_format/pkg.h +++ b/src/core/file_format/pkg.h @@ -103,7 +103,7 @@ public: PKG(); ~PKG(); - bool Open(const std::filesystem::path& filepath); + bool Open(const std::filesystem::path& filepath, std::string& failreason); void ExtractFiles(const int index); bool Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract, std::string& failreason); @@ -149,7 +149,6 @@ public: private: Crypto crypto; TRP trp; - std::vector pkg; u64 pkgSize = 0; char pkgTitleID[9]; PKGHeader pkgheader; diff --git a/src/core/file_format/psf.cpp b/src/core/file_format/psf.cpp index 3d076acdc..0502f29d2 100644 --- a/src/core/file_format/psf.cpp +++ b/src/core/file_format/psf.cpp @@ -2,61 +2,286 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + +#include "common/assert.h" #include "common/io_file.h" +#include "common/logging/log.h" #include "core/file_format/psf.h" -PSF::PSF() = default; +static const std::unordered_map psf_known_max_sizes = { + {"ACCOUNT_ID", 8}, {"CATEGORY", 4}, {"DETAIL", 1024}, {"FORMAT", 4}, + {"MAINTITLE", 128}, {"PARAMS", 1024}, {"SAVEDATA_BLOCKS", 8}, {"SAVEDATA_DIRECTORY", 32}, + {"SUBTITLE", 128}, {"TITLE_ID", 12}, +}; +static inline u32 get_max_size(std::string_view key, u32 default_value) { + if (const auto& v = psf_known_max_sizes.find(key); v != psf_known_max_sizes.end()) { + return v->second; + } + return default_value; +} -PSF::~PSF() = default; - -bool PSF::open(const std::string& filepath, const std::vector& psfBuffer) { - if (!psfBuffer.empty()) { - psf.resize(psfBuffer.size()); - psf = psfBuffer; - } else { - Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); - if (!file.IsOpen()) { - return false; - } - - const u64 psfSize = file.GetSize(); - psf.resize(psfSize); - file.Seek(0); - file.Read(psf); - file.Close(); +bool PSF::Open(const std::filesystem::path& filepath) { + if (std::filesystem::exists(filepath)) { + last_write = std::filesystem::last_write_time(filepath); } - // Parse file contents - PSFHeader header; - std::memcpy(&header, psf.data(), sizeof(header)); - for (u32 i = 0; i < header.index_table_entries; i++) { - PSFEntry entry; - std::memcpy(&entry, &psf[sizeof(PSFHeader) + i * sizeof(PSFEntry)], sizeof(entry)); + Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); + if (!file.IsOpen()) { + return false; + } - const std::string key = (char*)&psf[header.key_table_offset + entry.key_offset]; - if (entry.param_fmt == PSFEntry::Fmt::TextRaw || - entry.param_fmt == PSFEntry::Fmt::TextNormal) { - map_strings[key] = (char*)&psf[header.data_table_offset + entry.data_offset]; - } - if (entry.param_fmt == PSFEntry::Fmt::Integer) { - u32 value; - std::memcpy(&value, &psf[header.data_table_offset + entry.data_offset], sizeof(value)); - map_integers[key] = value; + const u64 psfSize = file.GetSize(); + std::vector psf(psfSize); + file.Seek(0); + file.Read(psf); + file.Close(); + return Open(psf); +} + +bool PSF::Open(const std::vector& psf_buffer) { + const u8* psf_data = psf_buffer.data(); + + entry_list.clear(); + map_binaries.clear(); + map_strings.clear(); + map_integers.clear(); + + // Parse file contents + PSFHeader header{}; + std::memcpy(&header, psf_data, sizeof(header)); + + if (header.magic != PSF_MAGIC) { + LOG_ERROR(Core, "Invalid PSF magic number"); + return false; + } + if (header.version != PSF_VERSION_1_1 && header.version != PSF_VERSION_1_0) { + LOG_ERROR(Core, "Unsupported PSF version: 0x{:08x}", header.version); + return false; + } + + for (u32 i = 0; i < header.index_table_entries; i++) { + PSFRawEntry raw_entry{}; + std::memcpy(&raw_entry, psf_data + sizeof(PSFHeader) + i * sizeof(PSFRawEntry), + sizeof(raw_entry)); + + Entry& entry = entry_list.emplace_back(); + entry.key = std::string{(char*)(psf_data + header.key_table_offset + raw_entry.key_offset)}; + entry.param_fmt = static_cast(raw_entry.param_fmt.Raw()); + entry.max_len = raw_entry.param_max_len; + + const u8* data = psf_data + header.data_table_offset + raw_entry.data_offset; + + switch (entry.param_fmt) { + case PSFEntryFmt::Binary: { + std::vector value(raw_entry.param_len); + std::memcpy(value.data(), data, raw_entry.param_len); + map_binaries.emplace(i, std::move(value)); + } break; + case PSFEntryFmt::Text: { + std::string c_str{reinterpret_cast(data)}; + map_strings.emplace(i, std::move(c_str)); + } break; + case PSFEntryFmt::Integer: { + ASSERT_MSG(raw_entry.param_len == sizeof(s32), "PSF integer entry size mismatch"); + s32 integer = *(s32*)data; + map_integers.emplace(i, integer); + } break; + default: + UNREACHABLE_MSG("Unknown PSF entry format"); } } return true; } -std::string PSF::GetString(const std::string& key) { - if (map_strings.find(key) != map_strings.end()) { - return map_strings.at(key); +bool PSF::Encode(const std::filesystem::path& filepath) const { + Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Write); + if (!file.IsOpen()) { + return false; } - return ""; + + last_write = std::filesystem::file_time_type::clock::now(); + + const auto psf_buffer = Encode(); + const size_t written = file.Write(psf_buffer); + if (written != psf_buffer.size()) { + LOG_ERROR(Core, "Failed to write PSF file. Written {} Expected {}", written, + psf_buffer.size()); + } + return written == psf_buffer.size(); } -u32 PSF::GetInteger(const std::string& key) { - if (map_integers.find(key) != map_integers.end()) { - return map_integers.at(key); - } - return -1; +std::vector PSF::Encode() const { + std::vector psf_buffer; + Encode(psf_buffer); + return psf_buffer; +} + +void PSF::Encode(std::vector& psf_buffer) const { + psf_buffer.resize(sizeof(PSFHeader) + sizeof(PSFRawEntry) * entry_list.size()); + + { + auto& header = *(PSFHeader*)psf_buffer.data(); + header.magic = PSF_MAGIC; + header.version = PSF_VERSION_1_1; + header.index_table_entries = entry_list.size(); + } + + const size_t key_table_offset = psf_buffer.size(); + ((PSFHeader*)psf_buffer.data())->key_table_offset = key_table_offset; + for (size_t i = 0; i < entry_list.size(); i++) { + auto& raw_entry = ((PSFRawEntry*)(psf_buffer.data() + sizeof(PSFHeader)))[i]; + const Entry& entry = entry_list[i]; + raw_entry.key_offset = psf_buffer.size() - key_table_offset; + raw_entry.param_fmt.FromRaw(static_cast(entry.param_fmt)); + raw_entry.param_max_len = entry.max_len; + std::ranges::copy(entry.key, std::back_inserter(psf_buffer)); + psf_buffer.push_back(0); // NULL terminator + } + + const size_t data_table_offset = psf_buffer.size(); + ((PSFHeader*)psf_buffer.data())->data_table_offset = data_table_offset; + for (size_t i = 0; i < entry_list.size(); i++) { + if (psf_buffer.size() % 4 != 0) { + std::ranges::fill_n(std::back_inserter(psf_buffer), 4 - psf_buffer.size() % 4, 0); + } + auto& raw_entry = ((PSFRawEntry*)(psf_buffer.data() + sizeof(PSFHeader)))[i]; + const Entry& entry = entry_list[i]; + raw_entry.data_offset = psf_buffer.size() - data_table_offset; + + s32 additional_padding = s32(raw_entry.param_max_len); + + switch (entry.param_fmt) { + case PSFEntryFmt::Binary: { + const auto& value = map_binaries.at(i); + raw_entry.param_len = value.size(); + additional_padding -= s32(raw_entry.param_len); + std::ranges::copy(value, std::back_inserter(psf_buffer)); + } break; + case PSFEntryFmt::Text: { + const auto& value = map_strings.at(i); + raw_entry.param_len = value.size() + 1; + additional_padding -= s32(raw_entry.param_len); + std::ranges::copy(value, std::back_inserter(psf_buffer)); + psf_buffer.push_back(0); // NULL terminator + } break; + case PSFEntryFmt::Integer: { + const auto& value = map_integers.at(i); + raw_entry.param_len = sizeof(s32); + additional_padding -= s32(raw_entry.param_len); + const auto value_bytes = reinterpret_cast(&value); + std::ranges::copy(value_bytes, value_bytes + sizeof(s32), + std::back_inserter(psf_buffer)); + } break; + default: + UNREACHABLE_MSG("Unknown PSF entry format"); + } + ASSERT_MSG(additional_padding >= 0, "PSF entry max size mismatch"); + std::ranges::fill_n(std::back_inserter(psf_buffer), additional_padding, 0); + } +} + +std::optional> PSF::GetBinary(std::string_view key) const { + const auto& [it, index] = FindEntry(key); + if (it == entry_list.end()) { + return {}; + } + ASSERT(it->param_fmt == PSFEntryFmt::Binary); + return std::span{map_binaries.at(index)}; +} + +std::optional PSF::GetString(std::string_view key) const { + const auto& [it, index] = FindEntry(key); + if (it == entry_list.end()) { + return {}; + } + ASSERT(it->param_fmt == PSFEntryFmt::Text); + return std::string_view{map_strings.at(index)}; +} + +std::optional PSF::GetInteger(std::string_view key) const { + const auto& [it, index] = FindEntry(key); + if (it == entry_list.end()) { + return {}; + } + ASSERT(it->param_fmt == PSFEntryFmt::Integer); + return map_integers.at(index); +} + +void PSF::AddBinary(std::string key, std::vector value, bool update) { + auto [it, index] = FindEntry(key); + bool exist = it != entry_list.end(); + if (exist && !update) { + LOG_ERROR(Core, "PSF: Tried to add binary key that already exists: {}", key); + return; + } + if (exist) { + ASSERT_MSG(it->param_fmt == PSFEntryFmt::Binary, "PSF: Change format is not supported"); + it->max_len = get_max_size(key, value.size()); + map_binaries.at(index) = std::move(value); + return; + } + Entry& entry = entry_list.emplace_back(); + entry.max_len = get_max_size(key, value.size()); + entry.key = std::move(key); + entry.param_fmt = PSFEntryFmt::Binary; + map_binaries.emplace(entry_list.size() - 1, std::move(value)); +} + +void PSF::AddBinary(std::string key, uint64_t value, bool update) { + std::vector data(8); + std::memcpy(data.data(), &value, 8); + return AddBinary(std::move(key), std::move(data), update); +} + +void PSF::AddString(std::string key, std::string value, bool update) { + auto [it, index] = FindEntry(key); + bool exist = it != entry_list.end(); + if (exist && !update) { + LOG_ERROR(Core, "PSF: Tried to add string key that already exists: {}", key); + return; + } + if (exist) { + ASSERT_MSG(it->param_fmt == PSFEntryFmt::Text, "PSF: Change format is not supported"); + it->max_len = get_max_size(key, value.size() + 1); + map_strings.at(index) = std::move(value); + return; + } + Entry& entry = entry_list.emplace_back(); + entry.max_len = get_max_size(key, value.size() + 1); + entry.key = std::move(key); + entry.param_fmt = PSFEntryFmt::Text; + map_strings.emplace(entry_list.size() - 1, std::move(value)); +} + +void PSF::AddInteger(std::string key, s32 value, bool update) { + auto [it, index] = FindEntry(key); + bool exist = it != entry_list.end(); + if (exist && !update) { + LOG_ERROR(Core, "PSF: Tried to add integer key that already exists: {}", key); + return; + } + if (exist) { + ASSERT_MSG(it->param_fmt == PSFEntryFmt::Integer, "PSF: Change format is not supported"); + it->max_len = sizeof(s32); + map_integers.at(index) = value; + return; + } + Entry& entry = entry_list.emplace_back(); + entry.key = std::move(key); + entry.param_fmt = PSFEntryFmt::Integer; + entry.max_len = sizeof(s32); + map_integers.emplace(entry_list.size() - 1, value); +} + +std::pair::iterator, size_t> PSF::FindEntry(std::string_view key) { + auto entry = + std::ranges::find_if(entry_list, [&](const auto& entry) { return entry.key == key; }); + return {entry, std::distance(entry_list.begin(), entry)}; +} + +std::pair::const_iterator, size_t> PSF::FindEntry( + std::string_view key) const { + auto entry = + std::ranges::find_if(entry_list, [&](const auto& entry) { return entry.key == key; }); + return {entry, std::distance(entry_list.begin(), entry)}; } diff --git a/src/core/file_format/psf.h b/src/core/file_format/psf.h index 9a162b1d5..6f35fa69a 100644 --- a/src/core/file_format/psf.h +++ b/src/core/file_format/psf.h @@ -3,11 +3,18 @@ #pragma once +#include +#include #include +#include #include #include #include "common/endian.h" +constexpr u32 PSF_MAGIC = 0x00505346; +constexpr u32 PSF_VERSION_1_1 = 0x00000101; +constexpr u32 PSF_VERSION_1_0 = 0x00000100; + struct PSFHeader { u32_be magic; u32_le version; @@ -15,34 +22,73 @@ struct PSFHeader { u32_le data_table_offset; u32_le index_table_entries; }; +static_assert(sizeof(PSFHeader) == 0x14); -struct PSFEntry { - enum Fmt : u16 { - TextRaw = 0x0400, // String in UTF-8 format and not NULL terminated - TextNormal = 0x0402, // String in UTF-8 format and NULL terminated - Integer = 0x0404, // Unsigned 32-bit integer - }; - +struct PSFRawEntry { u16_le key_offset; u16_be param_fmt; u32_le param_len; u32_le param_max_len; u32_le data_offset; }; +static_assert(sizeof(PSFRawEntry) == 0x10); + +enum class PSFEntryFmt : u16 { + Binary = 0x0004, // Binary data + Text = 0x0204, // String in UTF-8 format and NULL terminated + Integer = 0x0404, // Signed 32-bit integer +}; class PSF { + struct Entry { + std::string key; + PSFEntryFmt param_fmt; + u32 max_len; + }; + public: - PSF(); - ~PSF(); + PSF() = default; + ~PSF() = default; - bool open(const std::string& filepath, const std::vector& psfBuffer); + PSF(const PSF& other) = default; + PSF(PSF&& other) noexcept = default; + PSF& operator=(const PSF& other) = default; + PSF& operator=(PSF&& other) noexcept = default; - std::string GetString(const std::string& key); - u32 GetInteger(const std::string& key); + bool Open(const std::filesystem::path& filepath); + bool Open(const std::vector& psf_buffer); - std::unordered_map map_strings; - std::unordered_map map_integers; + [[nodiscard]] std::vector Encode() const; + void Encode(std::vector& buf) const; + bool Encode(const std::filesystem::path& filepath) const; + + std::optional> GetBinary(std::string_view key) const; + std::optional GetString(std::string_view key) const; + std::optional GetInteger(std::string_view key) const; + + void AddBinary(std::string key, std::vector value, bool update = false); + void AddBinary(std::string key, uint64_t value, bool update = false); // rsv4 format + void AddString(std::string key, std::string value, bool update = false); + void AddInteger(std::string key, s32 value, bool update = false); + + [[nodiscard]] std::filesystem::file_time_type GetLastWrite() const { + return last_write; + } + + [[nodiscard]] const std::vector& GetEntries() const { + return entry_list; + } private: - std::vector psf; + mutable std::filesystem::file_time_type last_write; + + std::vector entry_list; + + std::unordered_map> map_binaries; + std::unordered_map map_strings; + std::unordered_map map_integers; + + [[nodiscard]] std::pair::iterator, size_t> FindEntry(std::string_view key); + [[nodiscard]] std::pair::const_iterator, size_t> FindEntry( + std::string_view key) const; }; diff --git a/src/core/file_format/splash.cpp b/src/core/file_format/splash.cpp index f41789a85..5e06c912d 100644 --- a/src/core/file_format/splash.cpp +++ b/src/core/file_format/splash.cpp @@ -12,8 +12,8 @@ #define STBI_NO_STDIO #include "externals/stb_image.h" -bool Splash::Open(const std::string& filepath) { - ASSERT_MSG(filepath.ends_with(".png"), "Unexpected file format passed"); +bool Splash::Open(const std::filesystem::path& filepath) { + ASSERT_MSG(filepath.stem().string() != "png", "Unexpected file format passed"); Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); if (!file.IsOpen()) { diff --git a/src/core/file_format/splash.h b/src/core/file_format/splash.h index 68cc33c47..7c563f317 100644 --- a/src/core/file_format/splash.h +++ b/src/core/file_format/splash.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include "common/types.h" @@ -22,7 +23,7 @@ public: Splash() = default; ~Splash() = default; - bool Open(const std::string& filepath); + bool Open(const std::filesystem::path& filepath); [[nodiscard]] bool IsLoaded() const { return img_data.size(); } diff --git a/src/core/file_format/trp.cpp b/src/core/file_format/trp.cpp index f122709e4..2ca88c778 100644 --- a/src/core/file_format/trp.cpp +++ b/src/core/file_format/trp.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/logging/log.h" +#include "common/path_util.h" #include "trp.h" TRP::TRP() = default; @@ -10,9 +12,13 @@ void TRP::GetNPcommID(const std::filesystem::path& trophyPath, int index) { std::filesystem::path trpPath = trophyPath / "sce_sys/npbind.dat"; Common::FS::IOFile npbindFile(trpPath, Common::FS::FileAccessMode::Read); if (!npbindFile.IsOpen()) { + LOG_CRITICAL(Common_Filesystem, "Failed to open npbind.dat file"); + return; + } + if (!npbindFile.Seek(0x84 + (index * 0x180))) { + LOG_CRITICAL(Common_Filesystem, "Failed to seek to NPbind offset"); return; } - npbindFile.Seek(0x84 + (index * 0x180)); npbindFile.ReadRaw(np_comm_id.data(), 12); std::fill(np_comm_id.begin() + 12, np_comm_id.end(), 0); // fill with 0, we need 16 bytes. } @@ -27,10 +33,10 @@ static void removePadding(std::vector& vec) { } } -bool TRP::Extract(const std::filesystem::path& trophyPath) { - std::string title = trophyPath.filename().string(); +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; } for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) { @@ -39,41 +45,57 @@ bool TRP::Extract(const std::filesystem::path& trophyPath) { Common::FS::IOFile file(it.path(), Common::FS::FileAccessMode::Read); if (!file.IsOpen()) { + LOG_CRITICAL(Common_Filesystem, "Unable to open trophy file for read"); return false; } TrpHeader header; file.Read(header); - if (header.magic != 0xDCA24D00) + if (header.magic != 0xDCA24D00) { + LOG_CRITICAL(Common_Filesystem, "Wrong trophy magic number"); return false; + } s64 seekPos = sizeof(TrpHeader); - std::filesystem::path trpFilesPath(std::filesystem::current_path() / "user/game_data" / - title / "TrophyFiles" / it.path().stem()); + std::filesystem::path trpFilesPath( + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / titleId / + "TrophyFiles" / it.path().stem()); std::filesystem::create_directories(trpFilesPath / "Icons"); std::filesystem::create_directory(trpFilesPath / "Xml"); for (int i = 0; i < header.entry_num; i++) { - file.Seek(seekPos); + if (!file.Seek(seekPos)) { + LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset"); + return false; + } seekPos += (s64)header.entry_size; TrpEntry entry; file.Read(entry); std::string_view name(entry.entry_name); if (entry.flag == 0 && name.find("TROP") != std::string::npos) { // PNG - file.Seek(entry.entry_pos); + if (!file.Seek(entry.entry_pos)) { + LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset"); + return false; + } std::vector icon(entry.entry_len); file.Read(icon); Common::FS::IOFile::WriteBytes(trpFilesPath / "Icons" / name, icon); } if (entry.flag == 3 && np_comm_id[0] == 'N' && np_comm_id[1] == 'P') { // ESFM, encrypted. - file.Seek(entry.entry_pos); + if (!file.Seek(entry.entry_pos)) { + LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset"); + return false; + } file.Read(esfmIv); // get iv key. // Skip the first 16 bytes which are the iv key on every entry as we want a // clean xml file. std::vector ESFM(entry.entry_len - iv_len); std::vector XML(entry.entry_len - iv_len); - file.Seek(entry.entry_pos + iv_len); + if (!file.Seek(entry.entry_pos + iv_len)) { + LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry + iv offset"); + return false; + } file.Read(ESFM); crypto.decryptEFSM(np_comm_id, esfmIv, ESFM, XML); // decrypt removePadding(XML); @@ -81,7 +103,14 @@ bool TRP::Extract(const std::filesystem::path& trophyPath) { size_t pos = xml_name.find("ESFM"); if (pos != std::string::npos) xml_name.replace(pos, xml_name.length(), "XML"); - Common::FS::IOFile::WriteBytes(trpFilesPath / "Xml" / xml_name, XML); + std::filesystem::path path = trpFilesPath / "Xml" / xml_name; + size_t written = Common::FS::IOFile::WriteBytes(path, XML); + if (written != XML.size()) { + LOG_CRITICAL( + Common_Filesystem, + "Trophy XML {} write failed, wanted to write {} bytes, wrote {}", + fmt::UTF(path.u8string()), XML.size(), written); + } } } } diff --git a/src/core/file_format/trp.h b/src/core/file_format/trp.h index 56f490026..aec129f0e 100644 --- a/src/core/file_format/trp.h +++ b/src/core/file_format/trp.h @@ -33,7 +33,7 @@ class TRP { public: TRP(); ~TRP(); - bool Extract(const std::filesystem::path& trophyPath); + bool Extract(const std::filesystem::path& trophyPath, const std::string titleId); void GetNPcommID(const std::filesystem::path& trophyPath, int index); private: diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index 40d8212bb..b5f1711db 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/config.h" #include "common/string_util.h" #include "core/file_sys/fs.h" @@ -9,12 +10,14 @@ namespace Core::FileSys { constexpr int RESERVED_HANDLES = 3; // First 3 handles are stdin,stdout,stderr -void MntPoints::Mount(const std::filesystem::path& host_folder, const std::string& guest_folder) { +void MntPoints::Mount(const std::filesystem::path& host_folder, const std::string& guest_folder, + bool read_only) { std::scoped_lock lock{m_mutex}; - m_mnt_pairs.emplace_back(host_folder, guest_folder); + m_mnt_pairs.emplace_back(host_folder, guest_folder, read_only); } void MntPoints::Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder) { + std::scoped_lock lock{m_mutex}; auto it = std::remove_if(m_mnt_pairs.begin(), m_mnt_pairs.end(), [&](const MntPair& pair) { return pair.mount == guest_folder; }); m_mnt_pairs.erase(it, m_mnt_pairs.end()); @@ -25,88 +28,102 @@ void MntPoints::UnmountAll() { m_mnt_pairs.clear(); } -std::filesystem::path MntPoints::GetHostPath(std::string_view guest_directory) { +std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_read_only) { // Evil games like Turok2 pass double slashes e.g /app0//game.kpf - std::string corrected_path(guest_directory); - size_t pos = corrected_path.find("//"); - while (pos != std::string::npos) { - corrected_path.replace(pos, 2, "/"); - pos = corrected_path.find("//", pos + 1); - } + const auto normalized_path = std::filesystem::path(path).lexically_normal().string(); - const MntPair* mount = GetMount(corrected_path); + const MntPair* mount = GetMount(normalized_path); if (!mount) { return ""; } + if (is_read_only) { + *is_read_only = mount->read_only; + } + // Nothing to do if getting the mount itself. - if (corrected_path == mount->mount) { + if (normalized_path == mount->mount) { return mount->host_path; } // Remove device (e.g /app0) from path to retrieve relative path. - pos = mount->mount.size() + 1; - const auto rel_path = std::string_view(corrected_path).substr(pos); - const auto host_path = mount->host_path / rel_path; - if (!NeedsCaseInsensiveSearch) { + const auto rel_path = std::string_view{normalized_path}.substr(mount->mount.size() + 1); + std::filesystem::path host_path = mount->host_path / rel_path; + std::filesystem::path patch_path = mount->host_path; + patch_path += "-UPDATE"; + patch_path /= rel_path; + + if ((normalized_path.starts_with("/app0") || normalized_path.starts_with("/hostapp")) && + std::filesystem::exists(patch_path)) { + return patch_path; + } + + if (!NeedsCaseInsensitiveSearch) { return host_path; } - // If the path does not exist attempt to verify this. - // Retrieve parent path until we find one that exists. - std::scoped_lock lk{m_mutex}; - path_parts.clear(); - auto current_path = host_path; - while (!std::filesystem::exists(current_path)) { - // We have probably cached this if it's a folder. - if (auto it = path_cache.find(current_path); it != path_cache.end()) { - current_path = it->second; - break; + const auto search = [&](const auto host_path) { + // If the path does not exist attempt to verify this. + // Retrieve parent path until we find one that exists. + std::scoped_lock lk{m_mutex}; + path_parts.clear(); + auto current_path = host_path; + while (!std::filesystem::exists(current_path)) { + // We have probably cached this if it's a folder. + if (auto it = path_cache.find(current_path); it != path_cache.end()) { + current_path = it->second; + break; + } + path_parts.emplace_back(current_path.filename()); + current_path = current_path.parent_path(); } - path_parts.emplace_back(current_path.filename()); - current_path = current_path.parent_path(); - } - - // We have found an anchor. Traverse parts we recoded and see if they - // exist in filesystem but in different case. - auto guest_path = current_path; - while (!path_parts.empty()) { - const auto part = path_parts.back(); - const auto add_match = [&](const auto& host_part) { - current_path /= host_part; - guest_path /= part; - path_cache[guest_path] = current_path; - path_parts.pop_back(); - }; - - // Can happen when the mismatch is in upper folder. - if (std::filesystem::exists(current_path / part)) { - add_match(part); - continue; - } - const auto part_low = Common::ToLower(part.string()); - bool found_match = false; - for (const auto& path : std::filesystem::directory_iterator(current_path)) { - const auto candidate = path.path().filename(); - const auto filename = Common::ToLower(candidate.string()); - // Check if a filename matches in case insensitive manner. - if (filename != part_low) { + // We have found an anchor. Traverse parts we recoded and see if they + // exist in filesystem but in different case. + auto guest_path = current_path; + while (!path_parts.empty()) { + const auto part = path_parts.back(); + const auto add_match = [&](const auto& host_part) { + current_path /= host_part; + guest_path /= part; + path_cache[guest_path] = current_path; + path_parts.pop_back(); + }; + // Can happen when the mismatch is in upper folder. + if (std::filesystem::exists(current_path / part)) { + add_match(part); continue; } - // We found a match, record the actual path in the cache. - add_match(candidate); - found_match = true; - break; - } - if (!found_match) { - // Opening the guest path will surely fail but at least gives - // a better error message than the empty path. - return host_path; + const auto part_low = Common::ToLower(part.string()); + bool found_match = false; + for (const auto& path : std::filesystem::directory_iterator(current_path)) { + const auto candidate = path.path().filename(); + const auto filename = Common::ToLower(candidate.string()); + // Check if a filename matches in case insensitive manner. + if (filename != part_low) { + continue; + } + // We found a match, record the actual path in the cache. + add_match(candidate); + found_match = true; + break; + } + if (!found_match) { + return std::optional({}); + } } + return std::optional(current_path); + }; + + if (const auto path = search(patch_path)) { + return *path; + } + if (const auto path = search(host_path)) { + return *path; } - // The path was found. - return current_path; + // Opening the guest path will surely fail but at least gives + // a better error message than the empty path. + return host_path; } int HandleTable::CreateHandle() { diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index b0fb63242..eeaeaf781 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -14,26 +14,30 @@ namespace Core::FileSys { class MntPoints { #ifdef _WIN64 - static constexpr bool NeedsCaseInsensiveSearch = false; + static constexpr bool NeedsCaseInsensitiveSearch = false; #else - static constexpr bool NeedsCaseInsensiveSearch = true; + static constexpr bool NeedsCaseInsensitiveSearch = true; #endif public: struct MntPair { std::filesystem::path host_path; std::string mount; // e.g /app0/ + bool read_only; }; explicit MntPoints() = default; ~MntPoints() = default; - void Mount(const std::filesystem::path& host_folder, const std::string& guest_folder); + void Mount(const std::filesystem::path& host_folder, const std::string& guest_folder, + bool read_only = false); void Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder); void UnmountAll(); - std::filesystem::path GetHostPath(std::string_view guest_directory); + std::filesystem::path GetHostPath(std::string_view guest_directory, + bool* is_read_only = nullptr); const MntPair* GetMount(const std::string& guest_path) { + std::scoped_lock lock{m_mutex}; const auto it = std::ranges::find_if( m_mnt_pairs, [&](const auto& mount) { return guest_path.starts_with(mount.mount); }); return it == m_mnt_pairs.end() ? nullptr : &*it; diff --git a/src/core/libraries/ajm/ajm.cpp b/src/core/libraries/ajm/ajm.cpp index d8d8304ab..441a07f63 100644 --- a/src/core/libraries/ajm/ajm.cpp +++ b/src/core/libraries/ajm/ajm.cpp @@ -1,9 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator +#include "ajm.h" +#include "ajm_error.h" + #include "common/logging/log.h" -#include "core/libraries/ajm/ajm.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/ajm/ajm_error.h b/src/core/libraries/ajm/ajm_error.h new file mode 100644 index 000000000..64129554f --- /dev/null +++ b/src/core/libraries/ajm/ajm_error.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_AJM_ERROR_UNKNOWN = 0x80930001; +constexpr int ORBIS_AJM_ERROR_INVALID_CONTEXT = 0x80930002; +constexpr int ORBIS_AJM_ERROR_INVALID_INSTANCE = 0x80930003; +constexpr int ORBIS_AJM_ERROR_INVALID_BATCH = 0x80930004; +constexpr int ORBIS_AJM_ERROR_INVALID_PARAMETER = 0x80930005; +constexpr int ORBIS_AJM_ERROR_OUT_OF_MEMORY = 0x80930006; +constexpr int ORBIS_AJM_ERROR_OUT_OF_RESOURCES = 0x80930007; +constexpr int ORBIS_AJM_ERROR_CODEC_NOT_SUPPORTED = 0x80930008; +constexpr int ORBIS_AJM_ERROR_CODEC_ALREADY_REGISTERED = 0x80930009; +constexpr int ORBIS_AJM_ERROR_CODEC_NOT_REGISTERED = 0x8093000A; +constexpr int ORBIS_AJM_ERROR_WRONG_REVISION_FLAG = 0x8093000B; +constexpr int ORBIS_AJM_ERROR_FLAG_NOT_SUPPORTED = 0x8093000C; +constexpr int ORBIS_AJM_ERROR_BUSY = 0x8093000D; +constexpr int ORBIS_AJM_ERROR_BAD_PRIORITY = 0x8093000E; +constexpr int ORBIS_AJM_ERROR_IN_PROGRESS = 0x8093000F; +constexpr int ORBIS_AJM_ERROR_RETRY = 0x80930010; +constexpr int ORBIS_AJM_ERROR_MALFORMED_BATCH = 0x80930011; +constexpr int ORBIS_AJM_ERROR_JOB_CREATION = 0x80930012; +constexpr int ORBIS_AJM_ERROR_INVALID_OPCODE = 0x80930013; +constexpr int ORBIS_AJM_ERROR_PRIORITY_VIOLATION = 0x80930014; +constexpr int ORBIS_AJM_ERROR_BUFFER_TOO_BIG = 0x80930015; +constexpr int ORBIS_AJM_ERROR_INVALID_ADDRESS = 0x80930016; +constexpr int ORBIS_AJM_ERROR_CANCELLED = 0x80930017; diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index 882f99e49..f912639eb 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -1,20 +1,40 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include -#include -#include -#include -#include + #include "app_content.h" +#include "common/assert.h" +#include "common/config.h" #include "common/io_file.h" #include "common/logging/log.h" +#include "common/path_util.h" +#include "common/singleton.h" +#include "common/string_util.h" +#include "core/file_format/psf.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" namespace Libraries::AppContent { +int32_t addcont_count = 0; + +struct AddContInfo { + char entitlementLabel[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE]; + OrbisAppContentAddcontDownloadStatus status; + OrbisAppContentGetEntitlementKey key; +}; + +std::array addcont_info = {{ + {"0000000000000000", + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}}, +}}; + +std::string title_id; + int PS4_SYSV_ABI _Z5dummyv() { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); return ORBIS_OK; @@ -35,9 +55,30 @@ int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAddcontMount() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentMountPoint* mount_point) { + LOG_INFO(Lib_AppContent, "called"); + + const auto& mount_dir = Config::getAddonInstallDir() / title_id / entitlement_label->data; + auto* mnt = Common::Singleton::Instance(); + + for (int i = 0; i < addcont_count; i++) { + if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) { + continue; + } + + if (addcont_info[i].status != ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED) { + return ORBIS_APP_CONTENT_ERROR_NOT_FOUND; + } + + snprintf(mount_point->data, ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE, "/addcont%d", i); + mnt->Mount(mount_dir, mount_point->data); + return ORBIS_OK; + } + + return ORBIS_APP_CONTENT_ERROR_NOT_FOUND; } int PS4_SYSV_ABI sceAppContentAddcontShrink() { @@ -50,37 +91,32 @@ int PS4_SYSV_ABI sceAppContentAddcontUnmount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value) { - if (value == nullptr) +int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* out_value) { + if (out_value == nullptr) return ORBIS_APP_CONTENT_ERROR_PARAMETER; auto* param_sfo = Common::Singleton::Instance(); + std::optional value; switch (paramId) { case ORBIS_APP_CONTENT_APPPARAM_ID_SKU_FLAG: - *value = ORBIS_APP_CONTENT_APPPARAM_SKU_FLAG_FULL; + value = ORBIS_APP_CONTENT_APPPARAM_SKU_FLAG_FULL; break; case ORBIS_APP_CONTENT_APPPARAM_ID_USER_DEFINED_PARAM_1: - *value = param_sfo->GetInteger("USER_DEFINED_PARAM_1"); + value = param_sfo->GetInteger("USER_DEFINED_PARAM_1"); break; case ORBIS_APP_CONTENT_APPPARAM_ID_USER_DEFINED_PARAM_2: - *value = param_sfo->GetInteger("USER_DEFINED_PARAM_2"); + value = param_sfo->GetInteger("USER_DEFINED_PARAM_2"); break; case ORBIS_APP_CONTENT_APPPARAM_ID_USER_DEFINED_PARAM_3: - *value = param_sfo->GetInteger("USER_DEFINED_PARAM_3"); + value = param_sfo->GetInteger("USER_DEFINED_PARAM_3"); break; case ORBIS_APP_CONTENT_APPPARAM_ID_USER_DEFINED_PARAM_4: - *value = param_sfo->GetInteger("USER_DEFINED_PARAM_4"); + value = param_sfo->GetInteger("USER_DEFINED_PARAM_4"); break; default: - LOG_ERROR(Lib_AppContent, " paramId = {}, value = {} paramId is not valid", paramId, - *value); - return ORBIS_APP_CONTENT_ERROR_PARAMETER; - } - if (*value == -1) { - LOG_ERROR(Lib_AppContent, - " paramId = {}, value = {} value is not valid can't read param.sfo?", paramId, - *value); + LOG_ERROR(Lib_AppContent, " paramId = {} paramId is not valid", paramId); return ORBIS_APP_CONTENT_ERROR_PARAMETER; } + *out_value = value.value_or(0); return ORBIS_OK; } @@ -124,22 +160,80 @@ int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentGetAddcontInfo() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlementLabel, + OrbisAppContentAddcontInfo* info) { + LOG_INFO(Lib_AppContent, "called"); + + if (entitlementLabel == nullptr || info == nullptr) { + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + + for (auto i = 0; i < addcont_count; i++) { + if (strncmp(entitlementLabel->data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) { + continue; + } + + LOG_INFO(Lib_AppContent, "found DLC {}", entitlementLabel->data); + + strncpy(info->entitlement_label.data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE); + info->status = addcont_info[i].status; + return ORBIS_OK; + } + + return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT; } int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, OrbisAppContentAddcontInfo* list, u32 list_num, u32* hit_num) { - *hit_num = 0; - LOG_ERROR(Lib_AppContent, "(DUMMY) called"); + LOG_INFO(Lib_AppContent, "called"); + + if (list_num == 0 || list == nullptr) { + if (hit_num == nullptr) { + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + + *hit_num = addcont_count; + return ORBIS_OK; + } + + int dlcs_to_list = addcont_count < list_num ? addcont_count : list_num; + for (int i = 0; i < dlcs_to_list; i++) { + strncpy(list[i].entitlement_label.data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE); + list[i].status = addcont_info[i].status; + } + + if (hit_num != nullptr) { + *hit_num = dlcs_to_list; + } + return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentGetEntitlementKey() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAppContentGetEntitlementKey( + u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentGetEntitlementKey* key) { + LOG_ERROR(Lib_AppContent, "called"); + + if (entitlement_label == nullptr || key == nullptr) { + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + + for (int i = 0; i < addcont_count; i++) { + if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel, + ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) { + continue; + } + + memcpy(key->data, addcont_info[i].key.data, ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE); + return ORBIS_OK; + } + + return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT; } int PS4_SYSV_ABI sceAppContentGetRegion() { @@ -150,7 +244,29 @@ int PS4_SYSV_ABI sceAppContentGetRegion() { int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, OrbisAppContentBootParam* bootParam) { LOG_ERROR(Lib_AppContent, "(DUMMY) called"); - bootParam->attr = 0; // always 0 + auto* param_sfo = Common::Singleton::Instance(); + + const auto addons_dir = Config::getAddonInstallDir(); + if (const auto value = param_sfo->GetString("TITLE_ID"); value.has_value()) { + title_id = *value; + } else { + UNREACHABLE_MSG("Failed to get TITLE_ID"); + } + auto addon_path = addons_dir / title_id; + if (std::filesystem::exists(addon_path)) { + for (const auto& entry : std::filesystem::directory_iterator(addon_path)) { + if (entry.is_directory()) { + auto entitlement_label = entry.path().filename().string(); + + AddContInfo info{}; + info.status = ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED; + strcpy(info.entitlementLabel, entitlement_label.c_str()); + + addcont_info[addcont_count++] = info; + } + } + } + return ORBIS_OK; } @@ -221,12 +337,12 @@ int PS4_SYSV_ABI Func_C59A36FF8D7C59DA() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlemetId() { +int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlementId() { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlemetId() { +int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlementId() { LOG_ERROR(Lib_AppContent, "(STUBBED) called"); return ORBIS_OK; } @@ -313,9 +429,9 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("xZo2-418Wdo", "libSceAppContentBundle", 1, "libSceAppContent", 1, 1, Func_C59A36FF8D7C59DA); LIB_FUNCTION("kJmjt81mXKQ", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, - sceAppContentAddcontEnqueueDownloadByEntitlemetId); + sceAppContentAddcontEnqueueDownloadByEntitlementId); LIB_FUNCTION("efX3lrPwdKA", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, - sceAppContentAddcontMountByEntitlemetId); + sceAppContentAddcontMountByEntitlementId); LIB_FUNCTION("z9hgjLd1SGA", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, sceAppContentGetAddcontInfoByEntitlementId); LIB_FUNCTION("3wUaDTGmjcQ", "libSceAppContentIro", 1, "libSceAppContent", 1, 1, @@ -324,4 +440,4 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) { sceAppContentGetDownloadedStoreCountry); }; -} // namespace Libraries::AppContent \ No newline at end of file +} // namespace Libraries::AppContent diff --git a/src/core/libraries/app_content/app_content.h b/src/core/libraries/app_content/app_content.h index ecf69199e..a16da5b40 100644 --- a/src/core/libraries/app_content/app_content.h +++ b/src/core/libraries/app_content/app_content.h @@ -41,6 +41,16 @@ struct OrbisAppContentMountPoint { constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_NONE = 0; constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_FORMAT = (1 << 0); constexpr int ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE = 17; +constexpr int ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE = 16; +constexpr int ORBIS_APP_CONTENT_INFO_LIST_MAX_SIZE = 2500; + +enum OrbisAppContentAddcontDownloadStatus : u32 { + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_EXTRA_DATA = 0, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_IN_QUEUE = 1, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOADING = 2, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOAD_SUSPENDED = 3, + ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED = 4 +}; struct OrbisNpUnifiedEntitlementLabel { char data[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE]; @@ -54,11 +64,17 @@ struct OrbisAppContentAddcontInfo { u32 status; }; +struct OrbisAppContentGetEntitlementKey { + char data[ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE]; +}; + int PS4_SYSV_ABI _Z5dummyv(); int PS4_SYSV_ABI sceAppContentAddcontDelete(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownload(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp(); -int PS4_SYSV_ABI sceAppContentAddcontMount(); +int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentMountPoint* mount_point); int PS4_SYSV_ABI sceAppContentAddcontShrink(); int PS4_SYSV_ABI sceAppContentAddcontUnmount(); int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value); @@ -70,11 +86,15 @@ int PS4_SYSV_ABI sceAppContentDownload1Shrink(); int PS4_SYSV_ABI sceAppContentDownloadDataFormat(); int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(); int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress(); -int PS4_SYSV_ABI sceAppContentGetAddcontInfo(); +int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label, + const OrbisNpUnifiedEntitlementLabel* entitlementLabel, + OrbisAppContentAddcontInfo* info); int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, OrbisAppContentAddcontInfo* list, u32 list_num, u32* hit_num); -int PS4_SYSV_ABI sceAppContentGetEntitlementKey(); +int PS4_SYSV_ABI sceAppContentGetEntitlementKey( + u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label, + OrbisAppContentGetEntitlementKey* key); int PS4_SYSV_ABI sceAppContentGetRegion(); int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, OrbisAppContentBootParam* bootParam); @@ -92,8 +112,8 @@ int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOp int PS4_SYSV_ABI sceAppContentTemporaryDataUnmount(); int PS4_SYSV_ABI sceAppContentGetPftFlag(); int PS4_SYSV_ABI Func_C59A36FF8D7C59DA(); -int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlemetId(); -int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlemetId(); +int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlementId(); +int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlementId(); int PS4_SYSV_ABI sceAppContentGetAddcontInfoByEntitlementId(); int PS4_SYSV_ABI sceAppContentGetAddcontInfoListByIroTag(); int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry(); diff --git a/src/core/libraries/audio/audioout.cpp b/src/core/libraries/audio/audioout.cpp index cb676afc1..778d777c2 100644 --- a/src/core/libraries/audio/audioout.cpp +++ b/src/core/libraries/audio/audioout.cpp @@ -2,9 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include #include + #include "audio_core/sdl_audio.h" +#include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/audio/audioout.h" #include "core/libraries/error_codes.h" @@ -175,11 +176,15 @@ int PS4_SYSV_ABI sceAudioOutGetLastOutputTime() { } int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* state) { + if (handle < 1 || handle > SCE_AUDIO_OUT_NUM_PORTS) { + return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + } + int type = 0; int channels_num = 0; - if (!audio->AudioOutGetStatus(handle, &type, &channels_num)) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + if (const auto err = audio->AudioOutGetStatus(handle, &type, &channels_num); err != ORBIS_OK) { + return err; } state->rerouteCounter = 0; @@ -309,12 +314,7 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, LOG_ERROR(Lib_AudioOut, "Invalid format attribute"); return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT; } - int result = audio->AudioOutOpen(port_type, length, sample_rate, format); - if (result == -1) { - LOG_ERROR(Lib_AudioOut, "Audio ports are full"); - return ORBIS_AUDIO_OUT_ERROR_PORT_FULL; - } - return result; + return audio->AudioOutOpen(port_type, length, sample_rate, format); } int PS4_SYSV_ABI sceAudioOutOpenEx() { @@ -323,12 +323,19 @@ int PS4_SYSV_ABI sceAudioOutOpenEx() { } s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const 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; + } return audio->AudioOutOutput(handle, ptr); } int PS4_SYSV_ABI sceAudioOutOutputs(OrbisAudioOutOutputParam* param, u32 num) { for (u32 i = 0; i < num; i++) { - if (auto err = audio->AudioOutOutput(param[i].handle, param[i].ptr); err != 0) + if (const auto err = sceAudioOutOutput(param[i].handle, param[i].ptr); err != 0) return err; } return ORBIS_OK; @@ -425,10 +432,10 @@ int PS4_SYSV_ABI sceAudioOutSetUsbVolume() { } s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) { - if (!audio->AudioOutSetVolume(handle, flag, vol)) { + if (handle < 1 || handle > SCE_AUDIO_OUT_NUM_PORTS) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - return ORBIS_OK; + return audio->AudioOutSetVolume(handle, flag, vol); } int PS4_SYSV_ABI sceAudioOutSetVolumeDown() { diff --git a/src/core/libraries/audio/audioout.h b/src/core/libraries/audio/audioout.h index d29eea7c3..95cfc1707 100644 --- a/src/core/libraries/audio/audioout.h +++ b/src/core/libraries/audio/audioout.h @@ -11,6 +11,10 @@ namespace Libraries::AudioOut { constexpr int SCE_AUDIO_OUT_VOLUME_0DB = 32768; // max volume value +// 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; + enum OrbisAudioOutPort { ORBIS_AUDIO_OUT_PORT_TYPE_MAIN = 0, ORBIS_AUDIO_OUT_PORT_TYPE_BGM = 1, diff --git a/src/core/libraries/audio3d/audio3d.cpp b/src/core/libraries/audio3d/audio3d.cpp new file mode 100644 index 000000000..63815a068 --- /dev/null +++ b/src/core/libraries/audio3d/audio3d.cpp @@ -0,0 +1,344 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "audio3d.h" +#include "audio3d_error.h" +#include "audio3d_impl.h" + +#include "common/logging/log.h" +#include "core/libraries/audio/audioout.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" + +namespace Libraries::Audio3d { + +// Audio3d + +int PS4_SYSV_ABI sceAudio3dInitialize(s64 iReserved) { + LOG_INFO(Lib_Audio3d, "iReserved = {}", iReserved); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dTerminate() { + // TODO: When not initialized or some ports still open, return ORBIS_AUDIO3D_ERROR_NOT_READY + LOG_INFO(Lib_Audio3d, "called"); + return ORBIS_OK; +} + +void PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* sParameters) { + if (sParameters != NULL) { + sParameters->szSizeThis = sizeof(OrbisAudio3dOpenParameters); + sParameters->uiGranularity = 256; + sParameters->eRate = ORBIS_AUDIO3D_RATE_48000; + sParameters->uiMaxObjects = 512; + sParameters->uiQueueDepth = 2; + sParameters->eBufferMode = ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH; + sParameters->uiNumBeds = 2; + } else { + LOG_ERROR(Lib_Audio3d, "Invalid OpenParameters ptr"); + } +} + +int PS4_SYSV_ABI sceAudio3dPortOpen(OrbisUserServiceUserId iUserId, + const OrbisAudio3dOpenParameters* pParameters, + OrbisAudio3dPortId* pId) { + LOG_INFO(Lib_Audio3d, "iUserId = {}", iUserId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortClose(OrbisAudio3dPortId uiPortId) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortSetAttribute(OrbisAudio3dPortId uiPortId, + OrbisAudio3dAttributeId uiAttributeId, + const void* pAttribute, size_t szAttribute) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiAttributeId = {}, szAttribute = {}", uiPortId, + uiAttributeId, szAttribute); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortFlush(OrbisAudio3dPortId uiPortId) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortAdvance(OrbisAudio3dPortId uiPortId) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortPush(OrbisAudio3dPortId uiPortId, OrbisAudio3dBlocking eBlocking) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported(OrbisAudio3dPortId uiPortId, + OrbisAudio3dAttributeId* pCapabilities, + unsigned int* pNumCapabilities) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId uiPortId, unsigned int* pQueueLevel, + unsigned int* pQueueAvailable) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dObjectReserve(OrbisAudio3dPortId uiPortId, OrbisAudio3dObjectId* pId) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dObjectUnreserve(OrbisAudio3dPortId uiPortId, + OrbisAudio3dObjectId uiObjectId) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiObjectId = {}", uiPortId, uiObjectId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dObjectSetAttributes(OrbisAudio3dPortId uiPortId, + OrbisAudio3dObjectId uiObjectId, + size_t szNumAttributes, + const OrbisAudio3dAttribute* pAttributeArray) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiObjectId = {}, szNumAttributes = {}", uiPortId, + uiObjectId, szNumAttributes); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dBedWrite(OrbisAudio3dPortId uiPortId, unsigned int uiNumChannels, + OrbisAudio3dFormat eFormat, const void* pBuffer, + unsigned int uiNumSamples) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiNumChannels = {}, uiNumSamples = {}", uiPortId, + uiNumChannels, uiNumSamples); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dBedWrite2(OrbisAudio3dPortId uiPortId, unsigned int uiNumChannels, + OrbisAudio3dFormat eFormat, const void* pBuffer, + unsigned int uiNumSamples, + OrbisAudio3dOutputRoute eOutputRoute, bool bRestricted) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiNumChannels = {}, uiNumSamples = {}, bRestricted = {}", + uiPortId, uiNumChannels, uiNumSamples, bRestricted); + return ORBIS_OK; +} + +size_t PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize(unsigned int uiNumSpeakers, bool bIs3d) { + LOG_INFO(Lib_Audio3d, "uiNumSpeakers = {}, bIs3d = {}", uiNumSpeakers, bIs3d); + return ORBIS_OK; +} + +int PS4_SYSV_ABI +sceAudio3dCreateSpeakerArray(OrbisAudio3dSpeakerArrayHandle* pHandle, + const OrbisAudio3dSpeakerArrayParameters* pParameters) { + if (pHandle == nullptr || pParameters == nullptr) { + LOG_ERROR(Lib_Audio3d, "invalid SpeakerArray parameters"); + return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER; + } + LOG_INFO(Lib_Audio3d, "called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray(OrbisAudio3dSpeakerArrayHandle handle) { + if (handle == nullptr) { + LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle"); + return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER; + } + LOG_INFO(Lib_Audio3d, "called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients(OrbisAudio3dSpeakerArrayHandle handle, + OrbisAudio3dPosition pos, float fSpread, + float* pCoefficients, + unsigned int uiNumCoefficients) { + LOG_INFO(Lib_Audio3d, "fSpread = {}, uiNumCoefficients = {}", fSpread, uiNumCoefficients); + if (handle == nullptr) { + LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle"); + return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER; + } + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2(OrbisAudio3dSpeakerArrayHandle handle, + OrbisAudio3dPosition pos, float fSpread, + float* pCoefficients, + unsigned int uiNumCoefficients, + bool bHeightAware, + float fDownmixSpreadRadius) { + LOG_INFO(Lib_Audio3d, + "fSpread = {}, uiNumCoefficients = {}, bHeightAware = {}, fDownmixSpreadRadius = {}", + fSpread, uiNumCoefficients, bHeightAware, fDownmixSpreadRadius); + if (handle == nullptr) { + LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle"); + return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER; + } + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceAudio3dAudioOutOpen(OrbisAudio3dPortId uiPortId, OrbisUserServiceUserId userId, + s32 type, s32 index, u32 len, u32 freq, u32 param) { + LOG_INFO(Lib_Audio3d, + "uiPortId = {}, userId = {}, type = {}, index = {}, len = {}, freq = {}, param = {}", + uiPortId, userId, type, index, len, freq, param); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(s32 handle) { + LOG_INFO(Lib_Audio3d, "handle = {}", handle); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(s32 handle, const void* ptr) { + LOG_INFO(Lib_Audio3d, "handle = {}", handle); + if (ptr == nullptr) { + LOG_ERROR(Lib_Audio3d, "invalid Output ptr"); + return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER; + } + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(::Libraries::AudioOut::OrbisAudioOutOutputParam* param, + s32 num) { + LOG_INFO(Lib_Audio3d, "num = {}", num); + if (param == nullptr) { + LOG_ERROR(Lib_Audio3d, "invalid OutputParam ptr"); + return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER; + } + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortCreate(unsigned int uiGranularity, OrbisAudio3dRate eRate, + s64 iReserved, OrbisAudio3dPortId* pId) { + LOG_INFO(Lib_Audio3d, "uiGranularity = {}, iReserved = {}", uiGranularity, iReserved); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortDestroy(OrbisAudio3dPortId uiPortId) { + LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId); + return ORBIS_OK; +} + +// Audio3dPrivate + +const char* PS4_SYSV_ABI sceAudio3dStrError(int iErrorCode) { + LOG_ERROR(Lib_Audio3d, "(PRIVATE) called, iErrorCode = {}", iErrorCode); + return "NOT_IMPLEMENTED"; +} + +// Audio3dDebug + +int PS4_SYSV_ABI sceAudio3dPortQueryDebug() { + LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortQueryDebug called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortGetList() { + LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetList called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortGetParameters() { + LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetParameters called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortGetState() { + LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetState called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortFreeState() { + LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortFreeState called"); + return ORBIS_OK; +} + +// Unknown + +int PS4_SYSV_ABI sceAudio3dPortGetBufferLevel() { + LOG_ERROR(Lib_Audio3d, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dPortGetStatus() { + LOG_ERROR(Lib_Audio3d, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dReportRegisterHandler() { + LOG_ERROR(Lib_Audio3d, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dReportUnregisterHandler() { + LOG_ERROR(Lib_Audio3d, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceAudio3dSetGpuRenderer() { + LOG_ERROR(Lib_Audio3d, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("-R1DukFq7Dk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dGetSpeakerArrayMixCoefficients); + LIB_FUNCTION("-Re+pCWvwjQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dGetSpeakerArrayMixCoefficients2); + LIB_FUNCTION("-pzYDZozm+M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dPortQueryDebug); + LIB_FUNCTION("1HXxo-+1qCw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dObjectUnreserve); + LIB_FUNCTION("4uyHN9q4ZeU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dObjectSetAttributes); + LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dAudioOutOutput); + LIB_FUNCTION("8hm6YdoQgwg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dDeleteSpeakerArray); + LIB_FUNCTION("9ZA23Ia46Po", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dPortGetAttributesSupported); + LIB_FUNCTION("9tEwE0GV0qo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite); + LIB_FUNCTION("Aacl5qkRU6U", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dStrError); + LIB_FUNCTION("CKHlRW2E9dA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetState); + LIB_FUNCTION("HbxYY27lK6E", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dAudioOutOutputs); + LIB_FUNCTION("Im+jOoa5WAI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dGetDefaultOpenParameters); + LIB_FUNCTION("Mw9mRQtWepY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortDestroy); + LIB_FUNCTION("OyVqOeVNtSk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortClose); + LIB_FUNCTION("QfNXBrKZeI0", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dReportRegisterHandler); + LIB_FUNCTION("QqgTQQdzEMY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dPortGetBufferLevel); + LIB_FUNCTION("SEggctIeTcI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetList); + LIB_FUNCTION("UHFOgVNz0kk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortCreate); + LIB_FUNCTION("UmCvjSmuZIw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dInitialize); + LIB_FUNCTION("VEVhZ9qd4ZY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortPush); + LIB_FUNCTION("WW1TS2iz5yc", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dTerminate); + LIB_FUNCTION("XeDDK0xJWQA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortOpen); + LIB_FUNCTION("YaaDbDwKpFM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dPortGetQueueLevel); + LIB_FUNCTION("Yq9bfUQ0uJg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dPortSetAttribute); + LIB_FUNCTION("ZOGrxWLgQzE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFlush); + LIB_FUNCTION("flPcUaXVXcw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dPortGetParameters); + LIB_FUNCTION("iRX6GJs9tvE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetStatus); + LIB_FUNCTION("jO2tec4dJ2M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dObjectReserve); + LIB_FUNCTION("kEqqyDkmgdI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dGetSpeakerArrayMemorySize); + LIB_FUNCTION("lvWMW6vEqFU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dCreateSpeakerArray); + LIB_FUNCTION("lw0qrdSjZt8", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortAdvance); + LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutClose); + LIB_FUNCTION("psv2gbihC1A", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dReportUnregisterHandler); + LIB_FUNCTION("uJ0VhGcxCTQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFreeState); + LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutOpen); + LIB_FUNCTION("xH4Q9UILL3o", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite2); + LIB_FUNCTION("yEYXcbAGK14", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, + sceAudio3dSetGpuRenderer); +}; + +} // namespace Libraries::Audio3d \ No newline at end of file diff --git a/src/core/libraries/audio3d/audio3d.h b/src/core/libraries/audio3d/audio3d.h new file mode 100644 index 000000000..6cbe2d02f --- /dev/null +++ b/src/core/libraries/audio3d/audio3d.h @@ -0,0 +1,134 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +#include + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Audio3d { + +class Audio3d; + +typedef int OrbisUserServiceUserId; +typedef unsigned int OrbisAudio3dPortId; +typedef unsigned int OrbisAudio3dObjectId; +typedef unsigned int OrbisAudio3dAttributeId; + +enum OrbisAudio3dFormat { + ORBIS_AUDIO3D_FORMAT_S16 = 0, // s16 + ORBIS_AUDIO3D_FORMAT_FLOAT = 1 // f32 +}; + +enum OrbisAudio3dRate { ORBIS_AUDIO3D_RATE_48000 = 0 }; + +enum OrbisAudio3dBufferMode { + ORBIS_AUDIO3D_BUFFER_NO_ADVANCE = 0, + ORBIS_AUDIO3D_BUFFER_ADVANCE_NO_PUSH = 1, + ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH = 2 +}; + +enum OrbisAudio3dBlocking { ORBIS_AUDIO3D_BLOCKING_ASYNC = 0, ORBIS_AUDIO3D_BLOCKING_SYNC = 1 }; + +enum OrbisAudio3dPassthrough { + ORBIS_AUDIO3D_PASSTHROUGH_NONE = 0, + ORBIS_AUDIO3D_PASSTHROUGH_LEFT = 1, + ORBIS_AUDIO3D_PASSTHROUGH_RIGHT = 2 +}; + +enum OrbisAudio3dOutputRoute { + ORBIS_AUDIO3D_OUTPUT_BOTH = 0, + ORBIS_AUDIO3D_OUTPUT_HMU_ONLY = 1, + ORBIS_AUDIO3D_OUTPUT_TV_ONLY = 2 +}; + +enum OrbisAudio3dAmbisonics { + ORBIS_AUDIO3D_AMBISONICS_NONE = ~0, + ORBIS_AUDIO3D_AMBISONICS_W = 0, + ORBIS_AUDIO3D_AMBISONICS_X = 1, + ORBIS_AUDIO3D_AMBISONICS_Y = 2, + ORBIS_AUDIO3D_AMBISONICS_Z = 3, + ORBIS_AUDIO3D_AMBISONICS_R = 4, + ORBIS_AUDIO3D_AMBISONICS_S = 5, + ORBIS_AUDIO3D_AMBISONICS_T = 6, + ORBIS_AUDIO3D_AMBISONICS_U = 7, + ORBIS_AUDIO3D_AMBISONICS_V = 8, + ORBIS_AUDIO3D_AMBISONICS_K = 9, + ORBIS_AUDIO3D_AMBISONICS_L = 10, + ORBIS_AUDIO3D_AMBISONICS_M = 11, + ORBIS_AUDIO3D_AMBISONICS_N = 12, + ORBIS_AUDIO3D_AMBISONICS_O = 13, + ORBIS_AUDIO3D_AMBISONICS_P = 14, + ORBIS_AUDIO3D_AMBISONICS_Q = 15 +}; + +static const OrbisAudio3dAttributeId s_sceAudio3dAttributePcm = 0x00000001; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributePriority = 0x00000002; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributePosition = 0x00000003; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeSpread = 0x00000004; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeGain = 0x00000005; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributePassthrough = 0x00000006; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeResetState = 0x00000007; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeApplicationSpecific = 0x00000008; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeAmbisonics = 0x00000009; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeRestricted = 0x0000000A; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeOutputRoute = 0x0000000B; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeLateReverbLevel = 0x00010001; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeDownmixSpreadRadius = 0x00010002; +static const OrbisAudio3dAttributeId s_sceAudio3dAttributeDownmixSpreadHeightAware = 0x00010003; + +struct OrbisAudio3dSpeakerArray; +using OrbisAudio3dSpeakerArrayHandle = OrbisAudio3dSpeakerArray*; // head + +struct OrbisAudio3dOpenParameters { + size_t szSizeThis; + unsigned int uiGranularity; + OrbisAudio3dRate eRate; + unsigned int uiMaxObjects; + unsigned int uiQueueDepth; + OrbisAudio3dBufferMode eBufferMode; + char padding[32]; + unsigned int uiNumBeds; +}; + +struct OrbisAudio3dAttribute { + OrbisAudio3dAttributeId uiAttributeId; + char padding[32]; + const void* pValue; + size_t szValue; +}; + +struct OrbisAudio3dPosition { + float fX; + float fY; + float fZ; +}; + +struct OrbisAudio3dPcm { + OrbisAudio3dFormat eFormat; + const void* pSampleBuffer; + unsigned int uiNumSamples; +}; + +struct OrbisAudio3dSpeakerArrayParameters { + OrbisAudio3dPosition* pSpeakerPosition; + unsigned int uiNumSpeakers; + bool bIs3d; + void* pBuffer; + size_t szSize; +}; + +struct OrbisAudio3dApplicationSpecific { + size_t szSizeThis; + u8 cApplicationSpecific[32]; +}; + +void PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* sParameters); + +void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Audio3d \ No newline at end of file diff --git a/src/core/libraries/audio3d/audio3d_error.h b/src/core/libraries/audio3d/audio3d_error.h new file mode 100644 index 000000000..ff9d9749c --- /dev/null +++ b/src/core/libraries/audio3d/audio3d_error.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_AUDIO3D_ERROR_UNKNOWN = 0x80EA0001; +constexpr int ORBIS_AUDIO3D_ERROR_INVALID_PORT = 0x80EA0002; +constexpr int ORBIS_AUDIO3D_ERROR_INVALID_OBJECT = 0x80EA0003; +constexpr int ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER = 0x80EA0004; +constexpr int ORBIS_AUDIO3D_ERROR_OUT_OF_MEMORY = 0x80EA0005; +constexpr int ORBIS_AUDIO3D_ERROR_OUT_OF_RESOURCES = 0x80EA0006; +constexpr int ORBIS_AUDIO3D_ERROR_NOT_READY = 0x80EA0007; +constexpr int ORBIS_AUDIO3D_ERROR_NOT_SUPPORTED = 0x80EA0008; diff --git a/src/core/libraries/audio3d/audio3d_impl.cpp b/src/core/libraries/audio3d/audio3d_impl.cpp new file mode 100644 index 000000000..c267c096f --- /dev/null +++ b/src/core/libraries/audio3d/audio3d_impl.cpp @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "audio3d_error.h" +#include "audio3d_impl.h" + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/kernel/libkernel.h" + +using namespace Libraries::Kernel; + +namespace Libraries::Audio3d {} // namespace Libraries::Audio3d diff --git a/src/core/libraries/audio3d/audio3d_impl.h b/src/core/libraries/audio3d/audio3d_impl.h new file mode 100644 index 000000000..4e6342b1b --- /dev/null +++ b/src/core/libraries/audio3d/audio3d_impl.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "audio3d.h" + +namespace Libraries::Audio3d { + +class Audio3d { +public: +private: + typedef unsigned int OrbisAudio3dPluginId; +}; + +} // namespace Libraries::Audio3d diff --git a/src/core/libraries/avplayer/avplayer.cpp b/src/core/libraries/avplayer/avplayer.cpp index bd1f6b503..60d68c4f7 100644 --- a/src/core/libraries/avplayer/avplayer.cpp +++ b/src/core/libraries/avplayer/avplayer.cpp @@ -40,9 +40,11 @@ int PS4_SYSV_ABI sceAvPlayerChangeStream() { s32 PS4_SYSV_ABI sceAvPlayerClose(SceAvPlayerHandle handle) { LOG_TRACE(Lib_AvPlayer, "called"); if (handle == nullptr) { + LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS"); return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } delete handle; + LOG_TRACE(Lib_AvPlayer, "returning ORBIS_OK"); return ORBIS_OK; } @@ -164,8 +166,8 @@ s32 PS4_SYSV_ABI sceAvPlayerInitEx(const SceAvPlayerInitDataEx* p_data, bool PS4_SYSV_ABI sceAvPlayerIsActive(SceAvPlayerHandle handle) { LOG_TRACE(Lib_AvPlayer, "called"); if (handle == nullptr) { - LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS"); - return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; + LOG_TRACE(Lib_AvPlayer, "returning false"); + return false; } const auto res = handle->IsActive(); LOG_TRACE(Lib_AvPlayer, "returning {}", res); @@ -257,6 +259,7 @@ s32 PS4_SYSV_ABI sceAvPlayerStart(SceAvPlayerHandle handle) { s32 PS4_SYSV_ABI sceAvPlayerStop(SceAvPlayerHandle handle) { LOG_TRACE(Lib_AvPlayer, "called"); if (handle == nullptr) { + LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS"); return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } const auto res = handle->Stop(); @@ -322,4 +325,4 @@ void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("yN7Jhuv8g24", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerVprintf); }; -} // namespace Libraries::AvPlayer \ No newline at end of file +} // namespace Libraries::AvPlayer diff --git a/src/core/libraries/avplayer/avplayer.h b/src/core/libraries/avplayer/avplayer.h index 360f06b65..98e932070 100644 --- a/src/core/libraries/avplayer/avplayer.h +++ b/src/core/libraries/avplayer/avplayer.h @@ -161,7 +161,20 @@ struct SceAvPlayerFileReplacement { SceAvPlayerSizeFile size; }; -typedef void PS4_SYSV_ABI (*SceAvPlayerEventCallback)(void* p, s32 event, s32 src_id, void* data); +enum SceAvPlayerEvents { + SCE_AVPLAYER_STATE_STOP = 0x01, + SCE_AVPLAYER_STATE_READY = 0x02, + SCE_AVPLAYER_STATE_PLAY = 0x03, + SCE_AVPLAYER_STATE_PAUSE = 0x04, + SCE_AVPLAYER_STATE_BUFFERING = 0x05, + SCE_AVPLAYER_TIMED_TEXT_DELIVERY = 0x10, + SCE_AVPLAYER_WARNING_ID = 0x20, + SCE_AVPLAYER_ENCRYPTION = 0x30, + SCE_AVPLAYER_DRM_ERROR = 0x40 +}; + +typedef void PS4_SYSV_ABI (*SceAvPlayerEventCallback)(void* p, SceAvPlayerEvents event, s32 src_id, + void* data); struct SceAvPlayerEventReplacement { void* object_ptr; @@ -275,18 +288,6 @@ enum SceAvPlayerAvSyncMode { typedef int PS4_SYSV_ABI (*SceAvPlayerLogCallback)(void* p, const char* format, va_list args); -enum SceAvPlayerEvents { - SCE_AVPLAYER_STATE_STOP = 0x01, - SCE_AVPLAYER_STATE_READY = 0x02, - SCE_AVPLAYER_STATE_PLAY = 0x03, - SCE_AVPLAYER_STATE_PAUSE = 0x04, - SCE_AVPLAYER_STATE_BUFFERING = 0x05, - SCE_AVPLAYER_TIMED_TEXT_DELIVERY = 0x10, - SCE_AVPLAYER_WARNING_ID = 0x20, - SCE_AVPLAYER_ENCRYPTION = 0x30, - SCE_AVPLAYER_DRM_ERROR = 0x40 -}; - void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::AvPlayer diff --git a/src/core/libraries/avplayer/avplayer_data_streamer.h b/src/core/libraries/avplayer/avplayer_data_streamer.h index 04097bb4d..319c88a91 100644 --- a/src/core/libraries/avplayer/avplayer_data_streamer.h +++ b/src/core/libraries/avplayer/avplayer_data_streamer.h @@ -7,6 +7,8 @@ #include "common/types.h" +#include + struct AVIOContext; namespace Libraries::AvPlayer { @@ -14,6 +16,7 @@ namespace Libraries::AvPlayer { class IDataStreamer { public: virtual ~IDataStreamer() = default; + virtual bool Init(std::string_view path) = 0; virtual AVIOContext* GetContext() = 0; }; diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.cpp b/src/core/libraries/avplayer/avplayer_file_streamer.cpp index dc1386a47..c7bd5b5de 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.cpp +++ b/src/core/libraries/avplayer/avplayer_file_streamer.cpp @@ -18,19 +18,8 @@ extern "C" { namespace Libraries::AvPlayer { -AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement, - std::string_view path) - : m_file_replacement(file_replacement) { - const auto ptr = m_file_replacement.object_ptr; - m_fd = m_file_replacement.open(ptr, path.data()); - ASSERT(m_fd >= 0); - m_file_size = m_file_replacement.size(ptr); - // avio_buffer is deallocated in `avio_context_free` - const auto avio_buffer = reinterpret_cast(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE)); - m_avio_context = - avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this, - &AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek); -} +AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement) + : m_file_replacement(file_replacement) {} AvPlayerFileStreamer::~AvPlayerFileStreamer() { if (m_avio_context != nullptr) { @@ -43,6 +32,21 @@ AvPlayerFileStreamer::~AvPlayerFileStreamer() { } } +bool AvPlayerFileStreamer::Init(std::string_view path) { + const auto ptr = m_file_replacement.object_ptr; + m_fd = m_file_replacement.open(ptr, path.data()); + if (m_fd < 0) { + return false; + } + m_file_size = m_file_replacement.size(ptr); + // avio_buffer is deallocated in `avio_context_free` + const auto avio_buffer = reinterpret_cast(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE)); + m_avio_context = + avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this, + &AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek); + return true; +} + s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) { const auto self = reinterpret_cast(opaque); if (self->m_position >= self->m_file_size) { diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.h b/src/core/libraries/avplayer/avplayer_file_streamer.h index 658ce8c1e..034e40dd4 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.h +++ b/src/core/libraries/avplayer/avplayer_file_streamer.h @@ -15,9 +15,11 @@ namespace Libraries::AvPlayer { class AvPlayerFileStreamer : public IDataStreamer { public: - AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement, std::string_view path); + AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement); ~AvPlayerFileStreamer(); + bool Init(std::string_view path) override; + AVIOContext* GetContext() override { return m_avio_context; } diff --git a/src/core/libraries/avplayer/avplayer_impl.cpp b/src/core/libraries/avplayer/avplayer_impl.cpp index cdfff8277..1c414c961 100644 --- a/src/core/libraries/avplayer/avplayer_impl.cpp +++ b/src/core/libraries/avplayer/avplayer_impl.cpp @@ -6,8 +6,10 @@ #include "avplayer_impl.h" #include "common/logging/log.h" +#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/libkernel.h" +#include "core/linker.h" using namespace Libraries::Kernel; @@ -17,28 +19,32 @@ void* PS4_SYSV_ABI AvPlayer::Allocate(void* handle, u32 alignment, u32 size) { const auto* const self = reinterpret_cast(handle); const auto allocate = self->m_init_data_original.memory_replacement.allocate; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return allocate(ptr, alignment, size); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(allocate, ptr, alignment, size); } void PS4_SYSV_ABI AvPlayer::Deallocate(void* handle, void* memory) { const auto* const self = reinterpret_cast(handle); const auto deallocate = self->m_init_data_original.memory_replacement.deallocate; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return deallocate(ptr, memory); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(deallocate, ptr, memory); } void* PS4_SYSV_ABI AvPlayer::AllocateTexture(void* handle, u32 alignment, u32 size) { const auto* const self = reinterpret_cast(handle); const auto allocate = self->m_init_data_original.memory_replacement.allocate_texture; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return allocate(ptr, alignment, size); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(allocate, ptr, alignment, size); } void PS4_SYSV_ABI AvPlayer::DeallocateTexture(void* handle, void* memory) { const auto* const self = reinterpret_cast(handle); const auto deallocate = self->m_init_data_original.memory_replacement.deallocate_texture; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return deallocate(ptr, memory); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(deallocate, ptr, memory); } int PS4_SYSV_ABI AvPlayer::OpenFile(void* handle, const char* filename) { @@ -47,7 +53,8 @@ int PS4_SYSV_ABI AvPlayer::OpenFile(void* handle, const char* filename) { const auto open = self->m_init_data_original.file_replacement.open; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return open(ptr, filename); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(open, ptr, filename); } int PS4_SYSV_ABI AvPlayer::CloseFile(void* handle) { @@ -56,7 +63,8 @@ int PS4_SYSV_ABI AvPlayer::CloseFile(void* handle) { const auto close = self->m_init_data_original.file_replacement.close; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return close(ptr); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(close, ptr); } int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position, u32 length) { @@ -65,7 +73,8 @@ int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position const auto read_offset = self->m_init_data_original.file_replacement.readOffset; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return read_offset(ptr, buffer, position, length); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(read_offset, ptr, buffer, position, length); } u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) { @@ -74,7 +83,8 @@ u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) { const auto size = self->m_init_data_original.file_replacement.size; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return size(ptr); + const auto* linker = Common::Singleton::Instance(); + return linker->ExecuteGuest(size, ptr); } SceAvPlayerInitData AvPlayer::StubInitData(const SceAvPlayerInitData& data) { @@ -102,7 +112,7 @@ AvPlayer::AvPlayer(const SceAvPlayerInitData& data) m_state(std::make_unique(m_init_data)) {} s32 AvPlayer::PostInit(const SceAvPlayerPostInitData& data) { - m_post_init_data = data; + m_state->PostInit(data); return ORBIS_OK; } @@ -110,7 +120,7 @@ s32 AvPlayer::AddSource(std::string_view path) { if (path.empty()) { return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } - if (AVPLAYER_IS_ERROR(m_state->AddSource(path, GetSourceType(path)))) { + if (!m_state->AddSource(path, GetSourceType(path))) { return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; } return ORBIS_OK; @@ -128,7 +138,7 @@ s32 AvPlayer::GetStreamCount() { } s32 AvPlayer::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { - if (AVPLAYER_IS_ERROR(m_state->GetStreamInfo(stream_index, info))) { + if (!m_state->GetStreamInfo(stream_index, info)) { return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; } return ORBIS_OK; @@ -145,7 +155,10 @@ s32 AvPlayer::EnableStream(u32 stream_index) { } s32 AvPlayer::Start() { - return m_state->Start(); + if (!m_state->Start()) { + return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; + } + return ORBIS_OK; } bool AvPlayer::GetVideoData(SceAvPlayerFrameInfo& video_info) { diff --git a/src/core/libraries/avplayer/avplayer_impl.h b/src/core/libraries/avplayer/avplayer_impl.h index 09989d399..d7f28094e 100644 --- a/src/core/libraries/avplayer/avplayer_impl.h +++ b/src/core/libraries/avplayer/avplayer_impl.h @@ -40,8 +40,6 @@ public: bool SetLooping(bool is_looping); private: - using ScePthreadMutex = Kernel::ScePthreadMutex; - // Memory Replacement static void* PS4_SYSV_ABI Allocate(void* handle, u32 alignment, u32 size); static void PS4_SYSV_ABI Deallocate(void* handle, void* memory); @@ -58,7 +56,6 @@ private: SceAvPlayerInitData m_init_data{}; SceAvPlayerInitData m_init_data_original{}; - SceAvPlayerPostInitData m_post_init_data{}; std::mutex m_file_io_mutex{}; std::atomic_bool m_has_source{}; diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index 2fc360a0e..19925ba0c 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -5,7 +5,10 @@ #include "avplayer_file_streamer.h" +#include "common/alignment.h" #include "common/singleton.h" +#include "common/thread.h" + #include "core/file_sys/fs.h" #include "core/libraries/kernel/time_management.h" @@ -19,35 +22,55 @@ extern "C" { #include } +// The av_err2str macro in libavutil/error.h does not play nice with C++ +#ifdef av_err2str +#undef av_err2str +#include +av_always_inline std::string av_err2string(int errnum) { + char errbuf[AV_ERROR_MAX_STRING_SIZE]; + return av_make_error_string(errbuf, AV_ERROR_MAX_STRING_SIZE, errnum); +} +#define av_err2str(err) av_err2string(err).c_str() +#endif // av_err2str + namespace Libraries::AvPlayer { using namespace Kernel; -AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, std::string_view path, - const SceAvPlayerInitData& init_data, - SceAvPlayerSourceType source_type) - : m_state(state), m_memory_replacement(init_data.memory_replacement), - m_num_output_video_framebuffers( - std::min(std::max(2, init_data.num_output_video_framebuffers), 16)) { - AVFormatContext* context = avformat_alloc_context(); - if (init_data.file_replacement.open != nullptr) { - m_up_data_streamer = - std::make_unique(init_data.file_replacement, path); - context->pb = m_up_data_streamer->GetContext(); - ASSERT(!AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr))); - } else { - const auto mnt = Common::Singleton::Instance(); - const auto filepath = mnt->GetHostPath(path); - ASSERT(!AVPLAYER_IS_ERROR( - avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr))); - } - m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext); -} +AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, bool use_vdec2) + : m_state(state), m_use_vdec2(use_vdec2) {} AvPlayerSource::~AvPlayerSource() { Stop(); } +bool AvPlayerSource::Init(const SceAvPlayerInitData& init_data, std::string_view path) { + m_memory_replacement = init_data.memory_replacement, + m_num_output_video_framebuffers = + std::min(std::max(2, init_data.num_output_video_framebuffers), 16); + + AVFormatContext* context = avformat_alloc_context(); + if (init_data.file_replacement.open != nullptr) { + m_up_data_streamer = std::make_unique(init_data.file_replacement); + if (!m_up_data_streamer->Init(path)) { + return false; + } + context->pb = m_up_data_streamer->GetContext(); + if (AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr))) { + return false; + } + } else { + const auto mnt = Common::Singleton::Instance(); + const auto filepath = mnt->GetHostPath(path); + if (AVPLAYER_IS_ERROR( + avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr))) { + return false; + } + } + m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext); + return true; +} + bool AvPlayerSource::FindStreamInfo() { if (m_avformat_context == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not find stream info. NULL context."); @@ -86,16 +109,16 @@ static f32 AVRationalToF32(const AVRational rational) { return f32(rational.num) / rational.den; } -s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { +bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { info = {}; if (m_avformat_context == nullptr || stream_index >= m_avformat_context->nb_streams) { LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info.", stream_index); - return -1; + return false; } const auto p_stream = m_avformat_context->streams[stream_index]; if (p_stream == nullptr || p_stream->codecpar == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. NULL stream.", stream_index); - return -1; + return false; } info.type = CodecTypeToStreamType(p_stream->codecpar->codec_type); info.start_time = p_stream->start_time; @@ -107,18 +130,25 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) LOG_WARNING(Lib_AvPlayer, "Stream {} language is unknown", stream_index); } switch (info.type) { - case SCE_AVPLAYER_VIDEO: + case SCE_AVPLAYER_VIDEO: { LOG_INFO(Lib_AvPlayer, "Stream {} is a video stream.", stream_index); info.details.video.aspect_ratio = f32(p_stream->codecpar->width) / p_stream->codecpar->height; - info.details.video.width = p_stream->codecpar->width; - info.details.video.height = p_stream->codecpar->height; + auto width = u32(p_stream->codecpar->width); + auto height = u32(p_stream->codecpar->height); + if (!m_use_vdec2) { + width = Common::AlignUp(width, 16); + height = Common::AlignUp(height, 16); + } + info.details.video.width = width; + info.details.video.height = height; if (p_lang_node != nullptr) { std::memcpy(info.details.video.language_code, p_lang_node->value, std::min(strlen(p_lang_node->value), size_t(3))); } break; - case SCE_AVPLAYER_AUDIO: + } + case SCE_AVPLAYER_AUDIO: { LOG_INFO(Lib_AvPlayer, "Stream {} is an audio stream.", stream_index); info.details.audio.channel_count = p_stream->codecpar->ch_layout.nb_channels; info.details.audio.sample_rate = p_stream->codecpar->sample_rate; @@ -128,7 +158,8 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) std::min(strlen(p_lang_node->value), size_t(3))); } break; - case SCE_AVPLAYER_TIMEDTEXT: + } + case SCE_AVPLAYER_TIMEDTEXT: { LOG_WARNING(Lib_AvPlayer, "Stream {} is a timedtext stream.", stream_index); info.details.subs.font_size = 12; info.details.subs.text_size = 12; @@ -137,11 +168,13 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) std::min(strlen(p_lang_node->value), size_t(3))); } break; - default: - LOG_ERROR(Lib_AvPlayer, "Stream {} type is unknown: {}.", stream_index, info.type); - return -1; } - return 0; + default: { + LOG_ERROR(Lib_AvPlayer, "Stream {} type is unknown: {}.", stream_index, info.type); + return false; + } + } + return true; } bool AvPlayerSource::EnableStream(u32 stream_index) { @@ -167,8 +200,13 @@ bool AvPlayerSource::EnableStream(u32 stream_index) { LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", stream_index); return false; } - const auto width = m_video_codec_context->width; - const auto size = (width * m_video_codec_context->height * 3) / 2; + auto width = u32(m_video_codec_context->width); + auto height = u32(m_video_codec_context->height); + if (!m_use_vdec2) { + width = Common::AlignUp(width, 16); + height = Common::AlignUp(height, 16); + } + const auto size = (width * height * 3) / 2; for (u64 index = 0; index < m_num_output_video_framebuffers; ++index) { m_video_buffers.Push(FrameBuffer(m_memory_replacement, 0x100, size)); } @@ -213,12 +251,12 @@ std::optional AvPlayerSource::HasFrames(u32 num_frames) { return m_video_packets.Size() > num_frames || m_is_eof; } -s32 AvPlayerSource::Start() { +bool AvPlayerSource::Start() { std::unique_lock lock(m_state_mutex); if (m_audio_codec_context == nullptr && m_video_codec_context == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not start playback. NULL context."); - return -1; + return false; } m_demuxer_thread = std::jthread([this](std::stop_token stop) { this->DemuxerThread(stop); }); m_video_decoder_thread = @@ -226,7 +264,7 @@ s32 AvPlayerSource::Start() { m_audio_decoder_thread = std::jthread([this](std::stop_token stop) { this->AudioDecoderThread(stop); }); m_start_time = std::chrono::high_resolution_clock::now(); - return 0; + return true; } bool AvPlayerSource::Stop() { @@ -284,11 +322,6 @@ bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfo& video_info) { return true; } -static void CopyNV12Data(u8* dst, const AVFrame& src) { - std::memcpy(dst, src.data[0], src.width * src.height); - std::memcpy(dst + src.width * src.height, src.data[1], (src.width * src.height) / 2); -} - bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfoEx& video_info) { if (!IsActive()) { return false; @@ -298,7 +331,7 @@ bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfoEx& video_info) { auto frame = m_video_frames.Pop(); if (!frame.has_value()) { - LOG_WARNING(Lib_AvPlayer, "Could get video frame. EOF reached."); + LOG_TRACE(Lib_AvPlayer, "Could get video frame. EOF reached."); return false; } @@ -333,7 +366,7 @@ bool AvPlayerSource::GetAudioData(SceAvPlayerFrameInfo& audio_info) { auto frame = m_audio_frames.Pop(); if (!frame.has_value()) { - LOG_WARNING(Lib_AvPlayer, "Could get audio frame. EOF reached."); + LOG_TRACE(Lib_AvPlayer, "Could get audio frame. EOF reached."); return false; } @@ -416,6 +449,8 @@ void AvPlayerSource::ReleaseAVFormatContext(AVFormatContext* context) { void AvPlayerSource::DemuxerThread(std::stop_token stop) { using namespace std::chrono; + Common::SetCurrentThreadName("shadPS4:AvDemuxer"); + if (!m_audio_stream_index.has_value() && !m_video_stream_index.has_value()) { LOG_WARNING(Lib_AvPlayer, "Could not start DEMUXER thread. No streams enabled."); return; @@ -423,7 +458,8 @@ void AvPlayerSource::DemuxerThread(std::stop_token stop) { LOG_INFO(Lib_AvPlayer, "Demuxer Thread started"); while (!stop.stop_requested()) { - if (m_video_packets.Size() > 30 && m_audio_packets.Size() > 8) { + if (m_video_packets.Size() > 30 && + (!m_audio_stream_index.has_value() || m_audio_packets.Size() > 8)) { std::this_thread::sleep_for(milliseconds(5)); continue; } @@ -482,7 +518,7 @@ void AvPlayerSource::DemuxerThread(std::stop_token stop) { } m_state.OnEOF(); - LOG_INFO(Lib_AvPlayer, "Demuxer Thread exited normaly"); + LOG_INFO(Lib_AvPlayer, "Demuxer Thread exited normally"); } AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& frame) { @@ -493,13 +529,17 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram nv12_frame->width = frame.width; nv12_frame->height = frame.height; nv12_frame->sample_aspect_ratio = frame.sample_aspect_ratio; + nv12_frame->crop_top = frame.crop_top; + nv12_frame->crop_bottom = frame.crop_bottom; + nv12_frame->crop_left = frame.crop_left; + nv12_frame->crop_right = frame.crop_right; av_frame_get_buffer(nv12_frame.get(), 0); if (m_sws_context == nullptr) { m_sws_context = SWSContextPtr(sws_getContext(frame.width, frame.height, AVPixelFormat(frame.format), - frame.width, frame.height, AV_PIX_FMT_NV12, + nv12_frame->width, nv12_frame->height, AV_PIX_FMT_NV12, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr), &ReleaseSWSContext); } @@ -512,11 +552,35 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram return nv12_frame; } +static void CopyNV12Data(u8* dst, const AVFrame& src, bool use_vdec2) { + auto width = u32(src.width); + auto height = u32(src.height); + if (!use_vdec2) { + width = Common::AlignUp(width, 16); + height = Common::AlignUp(height, 16); + } + + if (src.width == width) { + std::memcpy(dst, src.data[0], src.width * src.height); + std::memcpy(dst + src.width * height, src.data[1], (src.width * src.height) / 2); + } else { + const auto luma_dst = dst; + for (u32 y = 0; y < src.height; ++y) { + std::memcpy(luma_dst + y * width, src.data[0] + y * src.width, src.width); + } + const auto chroma_dst = dst + width * height; + for (u32 y = 0; y < src.height / 2; ++y) { + std::memcpy(chroma_dst + y * (width / 2), src.data[0] + y * (src.width / 2), + src.width / 2); + } + } +} + Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame) { ASSERT(frame.format == AV_PIX_FMT_NV12); auto p_buffer = buffer.GetBuffer(); - CopyNV12Data(p_buffer, frame); + CopyNV12Data(p_buffer, frame, m_use_vdec2); const auto pkt_dts = u64(frame.pkt_dts) * 1000; const auto stream = m_avformat_context->streams[m_video_stream_index.value()]; @@ -525,6 +589,13 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame const auto num = time_base.num; const auto timestamp = (num != 0 && den > 1) ? (pkt_dts * num) / den : pkt_dts; + auto width = u32(frame.width); + auto height = u32(frame.height); + if (!m_use_vdec2) { + width = Common::AlignUp(width, 16); + height = Common::AlignUp(height, 16); + } + return Frame{ .buffer = std::move(buffer), .info = @@ -535,9 +606,14 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame { .video = { - .width = u32(frame.width), - .height = u32(frame.height), + .width = width, + .height = height, .aspect_ratio = AVRationalToF32(frame.sample_aspect_ratio), + .crop_left_offset = u32(frame.crop_left), + .crop_right_offset = u32(frame.crop_right + (width - frame.width)), + .crop_top_offset = u32(frame.crop_top), + .crop_bottom_offset = + u32(frame.crop_bottom + (height - frame.height)), .pitch = u32(frame.linesize[0]), .luma_bit_depth = 8, .chroma_bit_depth = 8, @@ -549,6 +625,8 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame void AvPlayerSource::VideoDecoderThread(std::stop_token stop) { using namespace std::chrono; + Common::SetCurrentThreadName("shadPS4:AvVideoDecoder"); + LOG_INFO(Lib_AvPlayer, "Video Decoder Thread started"); while ((!m_is_eof || m_video_packets.Size() != 0) && !stop.stop_requested()) { if (!m_video_packets_cv.Wait(stop, @@ -604,7 +682,7 @@ void AvPlayerSource::VideoDecoderThread(std::stop_token stop) { } } - LOG_INFO(Lib_AvPlayer, "Video Decoder Thread exited normaly"); + LOG_INFO(Lib_AvPlayer, "Video Decoder Thread exited normally"); } AvPlayerSource::AVFramePtr AvPlayerSource::ConvertAudioFrame(const AVFrame& frame) { @@ -669,6 +747,8 @@ Frame AvPlayerSource::PrepareAudioFrame(FrameBuffer buffer, const AVFrame& frame void AvPlayerSource::AudioDecoderThread(std::stop_token stop) { using namespace std::chrono; + Common::SetCurrentThreadName("shadPS4:AvAudioDecoder"); + LOG_INFO(Lib_AvPlayer, "Audio Decoder Thread started"); while ((!m_is_eof || m_audio_packets.Size() != 0) && !stop.stop_requested()) { if (!m_audio_packets_cv.Wait(stop, @@ -724,7 +804,7 @@ void AvPlayerSource::AudioDecoderThread(std::stop_token stop) { } } - LOG_INFO(Lib_AvPlayer, "Audio Decoder Thread exited normaly"); + LOG_INFO(Lib_AvPlayer, "Audio Decoder Thread exited normally"); } bool AvPlayerSource::HasRunningThreads() const { diff --git a/src/core/libraries/avplayer/avplayer_source.h b/src/core/libraries/avplayer/avplayer_source.h index 7144e7ee4..505d74465 100644 --- a/src/core/libraries/avplayer/avplayer_source.h +++ b/src/core/libraries/avplayer/avplayer_source.h @@ -120,17 +120,17 @@ private: class AvPlayerSource { public: - AvPlayerSource(AvPlayerStateCallback& state, std::string_view path, - const SceAvPlayerInitData& init_data, SceAvPlayerSourceType source_type); + AvPlayerSource(AvPlayerStateCallback& state, bool use_vdec2); ~AvPlayerSource(); + bool Init(const SceAvPlayerInitData& init_data, std::string_view path); bool FindStreamInfo(); s32 GetStreamCount(); - s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); + bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); bool EnableStream(u32 stream_index); void SetLooping(bool is_looping); std::optional HasFrames(u32 num_frames); - s32 Start(); + bool Start(); bool Stop(); bool GetAudioData(SceAvPlayerFrameInfo& audio_info); bool GetVideoData(SceAvPlayerFrameInfo& video_info); @@ -168,6 +168,7 @@ private: Frame PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame); AvPlayerStateCallback& m_state; + bool m_use_vdec2 = false; SceAvPlayerMemAllocator m_memory_replacement{}; u32 m_num_output_video_framebuffers{}; diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index 884cd9408..e66100679 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -5,8 +5,11 @@ #include "avplayer_source.h" #include "avplayer_state.h" +#include "common/singleton.h" +#include "common/thread.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/time_management.h" +#include "core/linker.h" #include @@ -14,8 +17,8 @@ namespace Libraries::AvPlayer { using namespace Kernel; -void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_id, s32 source_id, - void* event_data) { +void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, SceAvPlayerEvents event_id, + s32 source_id, void* event_data) { auto const self = reinterpret_cast(opaque); if (event_id == SCE_AVPLAYER_STATE_READY) { @@ -24,6 +27,7 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i s32 timedtext_stream_index = -1; const s32 stream_count = self->GetStreamCount(); if (AVPLAYER_IS_ERROR(stream_count)) { + self->Stop(); return; } if (stream_count == 0) { @@ -32,7 +36,10 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i } for (u32 stream_index = 0; stream_index < stream_count; ++stream_index) { SceAvPlayerStreamInfo info{}; - self->GetStreamInfo(stream_index, info); + if (!self->GetStreamInfo(stream_index, info)) { + self->Stop(); + return; + } const std::string_view default_language( reinterpret_cast(self->m_default_language)); @@ -80,11 +87,17 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i return; } - // Pass other events to the game + DefaultEventCallback(opaque, event_id, 0, event_data); +} + +void AvPlayerState::DefaultEventCallback(void* opaque, SceAvPlayerEvents event_id, s32 source_id, + void* event_data) { + auto const self = reinterpret_cast(opaque); const auto callback = self->m_event_replacement.event_callback; const auto ptr = self->m_event_replacement.object_ptr; if (callback != nullptr) { - callback(ptr, event_id, 0, event_data); + const auto* linker = Common::Singleton::Instance(); + linker->ExecuteGuest(callback, ptr, event_id, 0, event_data); } } @@ -94,8 +107,10 @@ AvPlayerState::AvPlayerState(const SceAvPlayerInitData& init_data) if (m_event_replacement.event_callback == nullptr || init_data.auto_start) { m_auto_start = true; m_init_data.event_replacement.event_callback = &AvPlayerState::AutoPlayEventCallback; - m_init_data.event_replacement.object_ptr = this; + } else { + m_init_data.event_replacement.event_callback = &AvPlayerState::DefaultEventCallback; } + m_init_data.event_replacement.object_ptr = this; if (init_data.default_language != nullptr) { std::memcpy(m_default_language, init_data.default_language, sizeof(m_default_language)); } @@ -115,24 +130,35 @@ AvPlayerState::~AvPlayerState() { m_event_queue.Clear(); } +void AvPlayerState::PostInit(const SceAvPlayerPostInitData& post_init_data) { + m_post_init_data = post_init_data; +} + // Called inside GAME thread -s32 AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) { +bool AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) { if (path.empty()) { LOG_ERROR(Lib_AvPlayer, "File path is empty."); - return -1; + return false; } { std::unique_lock lock(m_source_mutex); if (m_up_source != nullptr) { LOG_ERROR(Lib_AvPlayer, "Only one source is supported."); - return -1; + return false; } - m_up_source = std::make_unique(*this, path, m_init_data, source_type); + m_up_source = std::make_unique( + *this, m_post_init_data.video_decoder_init.decoderType.video_type == + SCE_AVPLAYER_VIDEO_DECODER_TYPE_SOFTWARE2); + if (!m_up_source->Init(m_init_data, path)) { + SetState(AvState::Error); + m_up_source.reset(); + return false; + } } AddSourceEvent(); - return 0; + return true; } // Called inside GAME thread @@ -146,29 +172,30 @@ s32 AvPlayerState::GetStreamCount() { } // Called inside GAME thread -s32 AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { +bool AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) { std::shared_lock lock(m_source_mutex); if (m_up_source == nullptr) { LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. No source.", stream_index); - return -1; + return false; } return m_up_source->GetStreamInfo(stream_index, info); } // Called inside GAME thread -s32 AvPlayerState::Start() { +bool AvPlayerState::Start() { std::shared_lock lock(m_source_mutex); - if (m_up_source == nullptr || m_up_source->Start() < 0) { + if (m_up_source == nullptr || !m_up_source->Start()) { LOG_ERROR(Lib_AvPlayer, "Could not start playback."); - return -1; + return false; } SetState(AvState::Play); OnPlaybackStateChanged(AvState::Play); - return 0; + return true; } void AvPlayerState::AvControllerThread(std::stop_token stop) { using std::chrono::milliseconds; + Common::SetCurrentThreadName("shadPS4:AvController"); while (!stop.stop_requested()) { if (m_event_queue.Size() != 0) { @@ -219,11 +246,14 @@ bool AvPlayerState::Stop() { if (m_up_source == nullptr || m_current_state == AvState::Stop) { return false; } + if (!m_up_source->Stop()) { + return false; + } if (!SetState(AvState::Stop)) { return false; } OnPlaybackStateChanged(AvState::Stop); - return m_up_source->Stop(); + return true; } bool AvPlayerState::GetVideoData(SceAvPlayerFrameInfo& video_info) { diff --git a/src/core/libraries/avplayer/avplayer_state.h b/src/core/libraries/avplayer/avplayer_state.h index ff80b6cea..d106127e4 100644 --- a/src/core/libraries/avplayer/avplayer_state.h +++ b/src/core/libraries/avplayer/avplayer_state.h @@ -24,11 +24,12 @@ public: AvPlayerState(const SceAvPlayerInitData& init_data); ~AvPlayerState(); - s32 AddSource(std::string_view filename, SceAvPlayerSourceType source_type); + void PostInit(const SceAvPlayerPostInitData& post_init_data); + bool AddSource(std::string_view filename, SceAvPlayerSourceType source_type); s32 GetStreamCount(); - s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); + bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info); bool EnableStream(u32 stream_index); - s32 Start(); + bool Start(); bool Stop(); bool GetAudioData(SceAvPlayerFrameInfo& audio_info); bool GetVideoData(SceAvPlayerFrameInfo& video_info); @@ -38,12 +39,12 @@ public: bool SetLooping(bool is_looping); private: - using ScePthreadMutex = Kernel::ScePthreadMutex; - using ScePthread = Kernel::ScePthread; - // Event Replacement - static void PS4_SYSV_ABI AutoPlayEventCallback(void* handle, s32 event_id, s32 source_id, - void* event_data); + static void PS4_SYSV_ABI AutoPlayEventCallback(void* handle, SceAvPlayerEvents event_id, + s32 source_id, void* event_data); + + static void PS4_SYSV_ABI DefaultEventCallback(void* handle, SceAvPlayerEvents event_id, + s32 source_id, void* event_data); void OnWarning(u32 id) override; void OnError() override; @@ -68,6 +69,7 @@ private: std::unique_ptr m_up_source; SceAvPlayerInitData m_init_data{}; + SceAvPlayerPostInitData m_post_init_data{}; SceAvPlayerEventReplacement m_event_replacement{}; bool m_auto_start{}; u8 m_default_language[4]{}; diff --git a/src/core/libraries/dialogs/error_dialog.cpp b/src/core/libraries/dialogs/error_dialog.cpp index 02f82c096..811f2cb99 100644 --- a/src/core/libraries/dialogs/error_dialog.cpp +++ b/src/core/libraries/dialogs/error_dialog.cpp @@ -1,41 +1,166 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator +#include +#include +#include + +#include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" -#include "error_codes.h" +#include "core/libraries/system/commondialog.h" #include "error_dialog.h" +#include "imgui/imgui_layer.h" +#include "imgui/imgui_std.h" + +static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; namespace Libraries::ErrorDialog { -static OrbisErrorDialogStatus g_error_dlg_status = - OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_NONE; +using CommonDialog::Error; +using CommonDialog::Result; +using CommonDialog::Status; -int PS4_SYSV_ABI sceErrorDialogClose() { - g_error_dlg_status = OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_FINISHED; - return ORBIS_OK; -} +class ErrorDialogUi final : public ImGui::Layer { + bool first_render{false}; -OrbisErrorDialogStatus PS4_SYSV_ABI sceErrorDialogGetStatus() { - return g_error_dlg_status; -} + Status* status{nullptr}; + std::string err_message{}; -int PS4_SYSV_ABI sceErrorDialogInitialize(OrbisErrorDialogParam* param) { - if (g_error_dlg_status == OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_INITIALIZED) { - LOG_ERROR(Lib_ErrorDialog, "Error dialog is already at init mode"); - return ORBIS_ERROR_DIALOG_ERROR_ALREADY_INITIALIZED; +public: + explicit ErrorDialogUi(Status* status = nullptr, std::string err_message = "") + : status(status), err_message(std::move(err_message)) { + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } } - g_error_dlg_status = OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_INITIALIZED; - return ORBIS_OK; + ~ErrorDialogUi() override { + Finish(); + } + ErrorDialogUi(const ErrorDialogUi& other) = delete; + ErrorDialogUi(ErrorDialogUi&& other) noexcept + : Layer(other), status(other.status), err_message(std::move(other.err_message)) { + other.status = nullptr; + } + ErrorDialogUi& operator=(ErrorDialogUi other) { + using std::swap; + swap(status, other.status); + swap(err_message, other.err_message); + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } + return *this; + } + + void Finish() { + if (status) { + *status = Status::FINISHED; + } + status = nullptr; + RemoveLayer(this); + } + + void Draw() override { + using namespace ImGui; + if (status == nullptr || *status != Status::RUNNING) { + return; + } + const auto& io = GetIO(); + + const ImVec2 window_size{ + std::min(io.DisplaySize.x, 500.0f), + std::min(io.DisplaySize.y, 300.0f), + }; + + CentralizeNextWindow(); + SetNextWindowSize(window_size); + SetNextWindowCollapsed(false); + if (first_render || !io.NavActive) { + SetNextWindowFocus(); + } + KeepNavHighlight(); + if (Begin("Error Dialog##ErrorDialog", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { + const auto ws = GetWindowSize(); + + DrawPrettyBackground(); + const char* begin = &err_message.front(); + const char* end = &err_message.back() + 1; + SetWindowFontScale(1.3f); + DrawCenteredText(begin, end, + GetContentRegionAvail() - ImVec2{0.0f, 15.0f + BUTTON_SIZE.y}); + SetWindowFontScale(1.0f); + + SetCursorPos({ + ws.x / 2.0f - BUTTON_SIZE.x / 2.0f, + ws.y - 10.0f - BUTTON_SIZE.y, + }); + if (Button("OK", BUTTON_SIZE)) { + Finish(); + } + if (first_render) { + SetItemCurrentNavFocus(); + } + } + End(); + + first_render = false; + } +}; + +static auto g_status = Status::NONE; +static ErrorDialogUi g_dialog_ui; + +struct Param { + s32 size; + s32 errorCode; + OrbisUserServiceUserId userId; + s32 _reserved; +}; + +Error PS4_SYSV_ABI sceErrorDialogClose() { + LOG_DEBUG(Lib_ErrorDialog, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + g_dialog_ui.Finish(); + return Error::OK; } -int PS4_SYSV_ABI sceErrorDialogOpen(OrbisErrorDialogParam* param) { - LOG_ERROR(Lib_ErrorDialog, "size = {} errorcode = {:#x} userid = {}", param->size, - param->errorCode, param->userId); - g_error_dlg_status = OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_RUNNING; - return ORBIS_OK; +Status PS4_SYSV_ABI sceErrorDialogGetStatus() { + LOG_TRACE(Lib_ErrorDialog, "called status={}", magic_enum::enum_name(g_status)); + return g_status; +} + +Error PS4_SYSV_ABI sceErrorDialogInitialize() { + LOG_DEBUG(Lib_ErrorDialog, "called"); + if (g_status != Status::NONE) { + return Error::ALREADY_INITIALIZED; + } + g_status = Status::INITIALIZED; + return Error::OK; +} + +Error PS4_SYSV_ABI sceErrorDialogOpen(const Param* param) { + if (g_status != Status::INITIALIZED && g_status != Status::FINISHED) { + LOG_INFO(Lib_ErrorDialog, "called without initialize"); + return Error::INVALID_STATE; + } + if (param == nullptr) { + LOG_DEBUG(Lib_ErrorDialog, "called param:(NULL)"); + return Error::ARG_NULL; + } + const auto err = static_cast(param->errorCode); + LOG_DEBUG(Lib_ErrorDialog, "called param->errorCode = {:#x}", err); + ASSERT(param->size == sizeof(Param)); + + const std::string err_message = fmt::format("An error has occurred. \nCode: {:#X}", err); + g_status = Status::RUNNING; + g_dialog_ui = ErrorDialogUi{&g_status, err_message}; + return Error::OK; } int PS4_SYSV_ABI sceErrorDialogOpenDetail() { @@ -48,20 +173,21 @@ int PS4_SYSV_ABI sceErrorDialogOpenWithReport() { return ORBIS_OK; } -int PS4_SYSV_ABI sceErrorDialogTerminate() { - if (g_error_dlg_status == OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_NONE) { - LOG_ERROR(Lib_ErrorDialog, "Error dialog hasn't initialized"); - return ORBIS_ERROR_DIALOG_ERROR_NOT_INITIALIZED; +Error PS4_SYSV_ABI sceErrorDialogTerminate() { + LOG_DEBUG(Lib_ErrorDialog, "called"); + if (g_status == Status::RUNNING) { + sceErrorDialogClose(); } - g_error_dlg_status = OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_NONE; - return ORBIS_OK; + if (g_status == Status::NONE) { + return Error::NOT_INITIALIZED; + } + g_status = Status::NONE; + return Error::OK; } -OrbisErrorDialogStatus PS4_SYSV_ABI sceErrorDialogUpdateStatus() { - // TODO when imgui dialog is done this will loop until ORBIS_ERROR_DIALOG_STATUS_FINISHED - // This should be done calling sceErrorDialogClose but since we don't have a dialog we finish it - // here - return OrbisErrorDialogStatus::ORBIS_ERROR_DIALOG_STATUS_FINISHED; +Status PS4_SYSV_ABI sceErrorDialogUpdateStatus() { + LOG_TRACE(Lib_ErrorDialog, "called status={}", magic_enum::enum_name(g_status)); + return g_status; } void RegisterlibSceErrorDialog(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/dialogs/error_dialog.h b/src/core/libraries/dialogs/error_dialog.h index e491b2eee..3e6651d4a 100644 --- a/src/core/libraries/dialogs/error_dialog.h +++ b/src/core/libraries/dialogs/error_dialog.h @@ -4,34 +4,25 @@ #pragma once #include "common/types.h" +#include "core/libraries/system/commondialog.h" namespace Core::Loader { class SymbolsResolver; } namespace Libraries::ErrorDialog { -enum OrbisErrorDialogStatus { - ORBIS_ERROR_DIALOG_STATUS_NONE = 0, - ORBIS_ERROR_DIALOG_STATUS_INITIALIZED = 1, - ORBIS_ERROR_DIALOG_STATUS_RUNNING = 2, - ORBIS_ERROR_DIALOG_STATUS_FINISHED = 3 -}; +using OrbisUserServiceUserId = s32; -struct OrbisErrorDialogParam { - s32 size; - u32 errorCode; - s32 userId; - s32 reserved; -}; +struct Param; -int PS4_SYSV_ABI sceErrorDialogClose(); -OrbisErrorDialogStatus PS4_SYSV_ABI sceErrorDialogGetStatus(); -int PS4_SYSV_ABI sceErrorDialogInitialize(OrbisErrorDialogParam* param); -int PS4_SYSV_ABI sceErrorDialogOpen(OrbisErrorDialogParam* param); +CommonDialog::Error PS4_SYSV_ABI sceErrorDialogClose(); +CommonDialog::Status PS4_SYSV_ABI sceErrorDialogGetStatus(); +CommonDialog::Error PS4_SYSV_ABI sceErrorDialogInitialize(); +CommonDialog::Error PS4_SYSV_ABI sceErrorDialogOpen(const Param* param); int PS4_SYSV_ABI sceErrorDialogOpenDetail(); int PS4_SYSV_ABI sceErrorDialogOpenWithReport(); -int PS4_SYSV_ABI sceErrorDialogTerminate(); -OrbisErrorDialogStatus PS4_SYSV_ABI sceErrorDialogUpdateStatus(); +CommonDialog::Error PS4_SYSV_ABI sceErrorDialogTerminate(); +CommonDialog::Status PS4_SYSV_ABI sceErrorDialogUpdateStatus(); void RegisterlibSceErrorDialog(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::ErrorDialog \ No newline at end of file diff --git a/src/core/libraries/dialogs/ime_dialog.cpp b/src/core/libraries/dialogs/ime_dialog.cpp index e73c1881b..63b52706a 100644 --- a/src/core/libraries/dialogs/ime_dialog.cpp +++ b/src/core/libraries/dialogs/ime_dialog.cpp @@ -1,29 +1,75 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator +#include +#include #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "ime_dialog.h" +#include "ime_dialog_ui.h" + +static constexpr std::array MAX_X_POSITIONS = {3840.0f, 1920.0f}; +static constexpr std::array MAX_Y_POSITIONS = {2160.0f, 1080.0f}; namespace Libraries::ImeDialog { -static OrbisImeDialogStatus g_ime_dlg_status = OrbisImeDialogStatus::ORBIS_IME_DIALOG_STATUS_NONE; +static OrbisImeDialogStatus g_ime_dlg_status = OrbisImeDialogStatus::NONE; +static OrbisImeDialogResult g_ime_dlg_result{}; +static ImeDialogState g_ime_dlg_state{}; +static ImeDialogUi g_ime_dlg_ui; -int PS4_SYSV_ABI sceImeDialogAbort() { - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - return ORBIS_OK; +static bool IsValidOption(OrbisImeDialogOption option, OrbisImeType type) { + if (False(~option & + (OrbisImeDialogOption::MULTILINE | OrbisImeDialogOption::NO_AUTO_COMPLETION))) { + return false; + } + + if (True(option & OrbisImeDialogOption::MULTILINE) && type != OrbisImeType::DEFAULT && + type != OrbisImeType::BASIC_LATIN) { + return false; + } + + if (True(option & OrbisImeDialogOption::NO_AUTO_COMPLETION) && type != OrbisImeType::NUMBER && + type != OrbisImeType::BASIC_LATIN) { + return false; + } + + return true; } -int PS4_SYSV_ABI sceImeDialogForceClose() { - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceImeDialogAbort() { + if (g_ime_dlg_status == OrbisImeDialogStatus::NONE) { + LOG_INFO(Lib_ImeDialog, "IME dialog not in use"); + return Error::DIALOG_NOT_IN_USE; + } + + if (g_ime_dlg_status != OrbisImeDialogStatus::RUNNING) { + LOG_INFO(Lib_ImeDialog, "IME dialog not running"); + return Error::DIALOG_NOT_RUNNING; + } + + g_ime_dlg_status = OrbisImeDialogStatus::FINISHED; + g_ime_dlg_result.endstatus = OrbisImeDialogEndStatus::ABORTED; + + return Error::OK; } -int PS4_SYSV_ABI sceImeDialogForTestFunction() { - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceImeDialogForceClose() { + if (g_ime_dlg_status == OrbisImeDialogStatus::NONE) { + LOG_INFO(Lib_ImeDialog, "IME dialog not in use"); + return Error::DIALOG_NOT_IN_USE; + } + + g_ime_dlg_status = OrbisImeDialogStatus::NONE; + g_ime_dlg_ui = ImeDialogUi(); + g_ime_dlg_state = ImeDialogState(); + + return Error::OK; +} + +Error PS4_SYSV_ABI sceImeDialogForTestFunction() { + return Error::INTERNAL; } int PS4_SYSV_ABI sceImeDialogGetCurrentStarState() { @@ -46,26 +92,118 @@ int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended() { return ORBIS_OK; } -int PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result) { - result->endstatus = OrbisImeDialogEndStatus::ORBIS_IME_DIALOG_END_STATUS_OK; - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result) { + if (g_ime_dlg_status == OrbisImeDialogStatus::NONE) { + LOG_INFO(Lib_ImeDialog, "IME dialog is not running"); + return Error::DIALOG_NOT_IN_USE; + } + + if (result == nullptr) { + LOG_INFO(Lib_ImeDialog, "called with result (NULL)"); + return Error::INVALID_ADDRESS; + } + + result->endstatus = g_ime_dlg_result.endstatus; + + if (g_ime_dlg_status == OrbisImeDialogStatus::RUNNING) { + return Error::DIALOG_NOT_FINISHED; + } + + g_ime_dlg_state.CopyTextToOrbisBuffer(); + return Error::OK; } -int PS4_SYSV_ABI sceImeDialogGetStatus() { - if (g_ime_dlg_status == OrbisImeDialogStatus::ORBIS_IME_DIALOG_STATUS_RUNNING) { - return OrbisImeDialogStatus::ORBIS_IME_DIALOG_STATUS_FINISHED; +OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus() { + if (g_ime_dlg_status == OrbisImeDialogStatus::RUNNING) { + g_ime_dlg_state.CallTextFilter(); } + return g_ime_dlg_status; } -int PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) { - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - const std::wstring_view text = L"shadPS4"; - param->maxTextLength = text.size(); - std::memcpy(param->inputTextBuffer, text.data(), text.size() * sizeof(wchar_t)); - g_ime_dlg_status = OrbisImeDialogStatus::ORBIS_IME_DIALOG_STATUS_RUNNING; - return ORBIS_OK; +Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) { + if (g_ime_dlg_status != OrbisImeDialogStatus::NONE) { + LOG_INFO(Lib_ImeDialog, "IME dialog is already running"); + return Error::BUSY; + } + + if (param == nullptr) { + LOG_INFO(Lib_ImeDialog, "called with param (NULL)"); + return Error::INVALID_ADDRESS; + } + + if (!magic_enum::enum_contains(param->type)) { + LOG_INFO(Lib_ImeDialog, "Invalid param->type"); + return Error::INVALID_ADDRESS; + } + + // TODO: do correct param->option validation + // TODO: do correct param->supportedLanguages validation + + if (param->posx < 0.0f || + param->posx >= + MAX_X_POSITIONS[False(param->option & OrbisImeDialogOption::LARGE_RESOLUTION)]) { + LOG_INFO(Lib_ImeDialog, "Invalid param->posx"); + return Error::INVALID_POSX; + } + + if (param->posy < 0.0f || + param->posy >= + MAX_Y_POSITIONS[False(param->option & OrbisImeDialogOption::LARGE_RESOLUTION)]) { + LOG_INFO(Lib_ImeDialog, "Invalid param->posy"); + return Error::INVALID_POSY; + } + + if (!magic_enum::enum_contains(param->horizontalAlignment)) { + LOG_INFO(Lib_ImeDialog, "Invalid param->horizontalAlignment"); + return Error::INVALID_HORIZONTALIGNMENT; + } + + if (!magic_enum::enum_contains(param->verticalAlignment)) { + LOG_INFO(Lib_ImeDialog, "Invalid param->verticalAlignment"); + return Error::INVALID_VERTICALALIGNMENT; + } + + if (!IsValidOption(param->option, param->type)) { + LOG_INFO(Lib_ImeDialog, "Invalid param->option"); + return Error::INVALID_PARAM; + } + + if (param->inputTextBuffer == nullptr) { + LOG_INFO(Lib_ImeDialog, "Invalid param->inputTextBuffer"); + return Error::INVALID_INPUT_TEXT_BUFFER; + } + + if (extended) { + if (!magic_enum::enum_contains(extended->priority)) { + LOG_INFO(Lib_ImeDialog, "Invalid extended->priority"); + return Error::INVALID_EXTENDED; + } + + // TODO: do correct extended->option validation + + if ((extended->extKeyboardMode & 0xe3fffffc) != 0) { + LOG_INFO(Lib_ImeDialog, "Invalid extended->extKeyboardMode"); + return Error::INVALID_EXTENDED; + } + + if (extended->disableDevice > 7) { + LOG_INFO(Lib_ImeDialog, "Invalid extended->disableDevice"); + return Error::INVALID_EXTENDED; + } + } + + if (param->maxTextLength > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) { + LOG_INFO(Lib_ImeDialog, "Invalid param->maxTextLength"); + return Error::INVALID_MAX_TEXT_LENGTH; + } + + g_ime_dlg_result = {}; + g_ime_dlg_state = ImeDialogState(param, extended); + g_ime_dlg_status = OrbisImeDialogStatus::RUNNING; + g_ime_dlg_ui = ImeDialogUi(&g_ime_dlg_state, &g_ime_dlg_status, &g_ime_dlg_result); + + return Error::OK; } int PS4_SYSV_ABI sceImeDialogInitInternal() { @@ -88,10 +226,22 @@ int PS4_SYSV_ABI sceImeDialogSetPanelPosition() { return ORBIS_OK; } -int PS4_SYSV_ABI sceImeDialogTerm() { - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - g_ime_dlg_status = OrbisImeDialogStatus::ORBIS_IME_DIALOG_STATUS_NONE; - return ORBIS_OK; +Error PS4_SYSV_ABI sceImeDialogTerm() { + if (g_ime_dlg_status == OrbisImeDialogStatus::NONE) { + LOG_INFO(Lib_ImeDialog, "IME dialog not in use"); + return Error::DIALOG_NOT_IN_USE; + } + + if (g_ime_dlg_status == OrbisImeDialogStatus::RUNNING) { + LOG_INFO(Lib_ImeDialog, "IME dialog is still running"); + return Error::DIALOG_NOT_FINISHED; + } + + g_ime_dlg_status = OrbisImeDialogStatus::NONE; + g_ime_dlg_ui = ImeDialogUi(); + g_ime_dlg_state = ImeDialogState(); + + return Error::OK; } void RegisterlibSceImeDialog(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/dialogs/ime_dialog.h b/src/core/libraries/dialogs/ime_dialog.h index ffe42b31a..66cf9fb93 100644 --- a/src/core/libraries/dialogs/ime_dialog.h +++ b/src/core/libraries/dialogs/ime_dialog.h @@ -3,6 +3,7 @@ #pragma once +#include "common/enum.h" #include "common/types.h" namespace Core::Loader { @@ -11,71 +12,150 @@ class SymbolsResolver; namespace Libraries::ImeDialog { -enum OrbisImeDialogStatus { - ORBIS_IME_DIALOG_STATUS_NONE = 0, - ORBIS_IME_DIALOG_STATUS_RUNNING = 1, - ORBIS_IME_DIALOG_STATUS_FINISHED = 2 +constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 0x78; + +enum class Error : u32 { + OK = 0x0, + BUSY = 0x80bc0001, + NOT_OPENED = 0x80bc0002, + NO_MEMORY = 0x80bc0003, + CONNECTION_FAILED = 0x80bc0004, + TOO_MANY_REQUESTS = 0x80bc0005, + INVALID_TEXT = 0x80bc0006, + EVENT_OVERFLOW = 0x80bc0007, + NOT_ACTIVE = 0x80bc0008, + IME_SUSPENDING = 0x80bc0009, + DEVICE_IN_USE = 0x80bc000a, + INVALID_USER_ID = 0x80bc0010, + INVALID_TYPE = 0x80bc0011, + INVALID_SUPPORTED_LANGUAGES = 0x80bc0012, + INVALID_ENTER_LABEL = 0x80bc0013, + INVALID_INPUT_METHOD = 0x80bc0014, + INVALID_OPTION = 0x80bc0015, + INVALID_MAX_TEXT_LENGTH = 0x80bc0016, + INVALID_INPUT_TEXT_BUFFER = 0x80bc0017, + INVALID_POSX = 0x80bc0018, + INVALID_POSY = 0x80bc0019, + INVALID_HORIZONTALIGNMENT = 0x80bc001a, + INVALID_VERTICALALIGNMENT = 0x80bc001b, + INVALID_EXTENDED = 0x80bc001c, + INVALID_KEYBOARD_TYPE = 0x80bc001d, + INVALID_WORK = 0x80bc0020, + INVALID_ARG = 0x80bc0021, + INVALID_HANDLER = 0x80bc0022, + NO_RESOURCE_ID = 0x80bc0023, + INVALID_MODE = 0x80bc0024, + INVALID_PARAM = 0x80bc0030, + INVALID_ADDRESS = 0x80bc0031, + INVALID_RESERVED = 0x80bc0032, + INVALID_TIMING = 0x80bc0033, + INTERNAL = 0x80bc00ff, + DIALOG_INVALID_TITLE = 0x80bc0101, + DIALOG_NOT_RUNNING = 0x80bc0105, + DIALOG_NOT_FINISHED = 0x80bc0106, + DIALOG_NOT_IN_USE = 0x80bc0107, }; -enum OrbisImeDialogEndStatus { - ORBIS_IME_DIALOG_END_STATUS_OK = 0, - ORBIS_IME_DIALOG_END_STATUS_USER_CANCELED = 1, - ORBIS_IME_DIALOG_END_STATUS_ABORTED = 2 +enum class OrbisImeDialogStatus : u32 { + NONE = 0, + RUNNING = 1, + FINISHED = 2, }; -struct OrbisImeDialogResult { - OrbisImeDialogEndStatus endstatus; - s32 reserved[12]; +enum class OrbisImeDialogEndStatus : u32 { + OK = 0, + USER_CANCELED = 1, + ABORTED = 2, }; -enum OrbisImeType { - ORBIS_IME_TYPE_DEFAULT = 0, - ORBIS_IME_TYPE_BASIC_LATIN = 1, - ORBIS_IME_TYPE_URL = 2, - ORBIS_IME_TYPE_MAIL = 3, - ORBIS_IME_TYPE_NUMBER = 4 +enum class OrbisImeType : u32 { + DEFAULT = 0, + BASIC_LATIN = 1, + URL = 2, + MAIL = 3, + NUMBER = 4, }; -enum OrbisImeEnterLabel { - ORBIS_IME_ENTER_LABEL_DEFAULT = 0, - ORBIS_IME_ENTER_LABEL_SEND = 1, - ORBIS_IME_ENTER_LABEL_SEARCH = 2, - ORBIS_IME_ENTER_LABEL_GO = 3 -}; -enum OrbiImeInputMethod { ORBIS_IME_INPUT_METHOD_DEFAULT = 0 }; - -typedef int (*OrbisImeTextFilter)(wchar_t* outText, u32* outTextLength, const wchar_t* srcText, - u32 srcTextLength); - -enum OrbisImeHorizontalAlignment { - ORBIS_IME_HALIGN_LEFT = 0, - ORBIS_IME_HALIGN_CENTER = 1, - ORBIS_IME_HALIGN_RIGHT = 2 +enum class OrbisImeEnterLabel : u32 { + DEFAULT = 0, + SEND = 1, + SEARCH = 2, + GO = 3, }; -enum OrbisImeVerticalAlignment { - ORBIS_IME_VALIGN_TOP = 0, - ORBIS_IME_VALIGN_CENTER = 1, - ORBIS_IME_VALIGN_BOTTOM = 2 +enum class OrbisImeDialogOption : u32 { + DEFAULT = 0, + MULTILINE = 1, + NO_AUTO_CORRECTION = 2, + NO_AUTO_COMPLETION = 4, + // TODO: Document missing options + LARGE_RESOLUTION = 1024, }; -struct OrbisImeDialogParam { - s32 userId; - OrbisImeType type; - u64 supportedLanguages; - OrbisImeEnterLabel enterLabel; - OrbiImeInputMethod inputMethod; - OrbisImeTextFilter filter; - u32 option; - u32 maxTextLength; - wchar_t* inputTextBuffer; - float posx; - float posy; - OrbisImeHorizontalAlignment horizontalAlignment; - OrbisImeVerticalAlignment verticalAlignment; - const wchar_t* placeholder; - const wchar_t* title; - s8 reserved[16]; +DECLARE_ENUM_FLAG_OPERATORS(OrbisImeDialogOption) + +enum class OrbisImeInputMethod : u32 { + DEFAULT = 0, +}; + +enum class OrbisImeHorizontalAlignment : u32 { + LEFT = 0, + CENTER = 1, + RIGHT = 2, +}; + +enum class OrbisImeVerticalAlignment : u32 { + TOP = 0, + CENTER = 1, + BOTTOM = 2, +}; + +enum class OrbisImePanelPriority : u32 { + DEFAULT = 0, + ALPHABET = 1, + SYMBOL = 2, + ACCENT = 3, +}; + +enum class OrbisImeKeyboardType : u32 { + NONE = 0, + DANISH = 1, + GERMAN = 2, + GERMAN_SW = 3, + ENGLISH_US = 4, + ENGLISH_GB = 5, + SPANISH = 6, + SPANISH_LA = 7, + FINNISH = 8, + FRENCH = 9, + FRENCH_BR = 10, + FRENCH_CA = 11, + FRENCH_SW = 12, + ITALIAN = 13, + DUTCH = 14, + NORWEGIAN = 15, + POLISH = 16, + PORTUGUESE_BR = 17, + PORTUGUESE_PT = 18, + RUSSIAN = 19, + SWEDISH = 20, + TURKISH = 21, + JAPANESE_ROMAN = 22, + JAPANESE_KANA = 23, + KOREAN = 24, + SM_CHINESE = 25, + TR_CHINESE_ZY = 26, + TR_CHINESE_PY_HK = 27, + TR_CHINESE_PY_TW = 28, + TR_CHINESE_CG = 29, + ARABIC_AR = 30, + THAI = 31, + CZECH = 32, + GREEK = 33, + INDONESIAN = 34, + VIETNAMESE = 35, + ROMANIAN = 36, + HUNGARIAN = 37, }; struct OrbisImeColor { @@ -85,57 +165,14 @@ struct OrbisImeColor { u8 a; }; -enum OrbisImePanelPriority { - ORBIS_IME_PANEL_PRIORITY_DEFAULT = 0, - ORBIS_IME_PANEL_PRIORITY_ALPHABET = 1, - ORBIS_IME_PANEL_PRIORITY_SYMBOL = 2, - ORBIS_IME_PANEL_PRIORITY_ACCENT = 3 -}; - -enum OrbisImeKeyboardType { - ORBIS_IME_KEYBOARD_TYPE_NONE = 0, - ORBIS_IME_KEYBOARD_TYPE_DANISH = 1, - ORBIS_IME_KEYBOARD_TYPE_GERMAN = 2, - ORBIS_IME_KEYBOARD_TYPE_GERMAN_SW = 3, - ORBIS_IME_KEYBOARD_TYPE_ENGLISH_US = 4, - ORBIS_IME_KEYBOARD_TYPE_ENGLISH_GB = 5, - ORBIS_IME_KEYBOARD_TYPE_SPANISH = 6, - ORBIS_IME_KEYBOARD_TYPE_SPANISH_LA = 7, - ORBIS_IME_KEYBOARD_TYPE_FINNISH = 8, - ORBIS_IME_KEYBOARD_TYPE_FRENCH = 9, - ORBIS_IME_KEYBOARD_TYPE_FRENCH_BR = 10, - ORBIS_IME_KEYBOARD_TYPE_FRENCH_CA = 11, - ORBIS_IME_KEYBOARD_TYPE_FRENCH_SW = 12, - ORBIS_IME_KEYBOARD_TYPE_ITALIAN = 13, - ORBIS_IME_KEYBOARD_TYPE_DUTCH = 14, - ORBIS_IME_KEYBOARD_TYPE_NORWEGIAN = 15, - ORBIS_IME_KEYBOARD_TYPE_POLISH = 16, - ORBIS_IME_KEYBOARD_TYPE_PORTUGUESE_BR = 17, - ORBIS_IME_KEYBOARD_TYPE_PORTUGUESE_PT = 18, - ORBIS_IME_KEYBOARD_TYPE_RUSSIAN = 19, - ORBIS_IME_KEYBOARD_TYPE_SWEDISH = 20, - ORBIS_IME_KEYBOARD_TYPE_TURKISH = 21, - ORBIS_IME_KEYBOARD_TYPE_JAPANESE_ROMAN = 22, - ORBIS_IME_KEYBOARD_TYPE_JAPANESE_KANA = 23, - ORBIS_IME_KEYBOARD_TYPE_KOREAN = 24, - ORBIS_IME_KEYBOARD_TYPE_SM_CHINESE = 25, - ORBIS_IME_KEYBOARD_TYPE_TR_CHINESE_ZY = 26, - ORBIS_IME_KEYBOARD_TYPE_TR_CHINESE_PY_HK = 27, - ORBIS_IME_KEYBOARD_TYPE_TR_CHINESE_PY_TW = 28, - ORBIS_IME_KEYBOARD_TYPE_TR_CHINESE_CG = 29, - ORBIS_IME_KEYBOARD_TYPE_ARABIC_AR = 30, - ORBIS_IME_KEYBOARD_TYPE_THAI = 31, - ORBIS_IME_KEYBOARD_TYPE_CZECH = 32, - ORBIS_IME_KEYBOARD_TYPE_GREEK = 33, - ORBIS_IME_KEYBOARD_TYPE_INDONESIAN = 34, - ORBIS_IME_KEYBOARD_TYPE_VIETNAMESE = 35, - ORBIS_IME_KEYBOARD_TYPE_ROMANIAN = 36, - ORBIS_IME_KEYBOARD_TYPE_HUNGARIAN = 37 +struct OrbisImeDialogResult { + OrbisImeDialogEndStatus endstatus; + s32 reserved[12]; }; struct OrbisImeKeycode { u16 keycode; - wchar_t character; + char16_t character; u32 status; OrbisImeKeyboardType type; s32 userId; @@ -143,11 +180,34 @@ struct OrbisImeKeycode { u64 timestamp; }; -typedef int (*OrbisImeExtKeyboardFilter)(const OrbisImeKeycode* srcKeycode, u16* outKeycode, - u32* outStatus, void* reserved); +typedef PS4_SYSV_ABI int (*OrbisImeTextFilter)(char16_t* outText, u32* outTextLength, + const char16_t* srcText, u32 srcTextLength); + +typedef PS4_SYSV_ABI int (*OrbisImeExtKeyboardFilter)(const OrbisImeKeycode* srcKeycode, + u16* outKeycode, u32* outStatus, + void* reserved); + +struct OrbisImeDialogParam { + s32 userId; + OrbisImeType type; + u64 supportedLanguages; + OrbisImeEnterLabel enterLabel; + OrbisImeInputMethod inputMethod; + OrbisImeTextFilter filter; + OrbisImeDialogOption option; + u32 maxTextLength; + char16_t* inputTextBuffer; + float posx; + float posy; + OrbisImeHorizontalAlignment horizontalAlignment; + OrbisImeVerticalAlignment verticalAlignment; + const char16_t* placeholder; + const char16_t* title; + s8 reserved[16]; +}; struct OrbisImeParamExtended { - u32 option; + u32 option; // OrbisImeDialogOptionExtended OrbisImeColor colorBase; OrbisImeColor colorLine; OrbisImeColor colorTextField; @@ -165,21 +225,21 @@ struct OrbisImeParamExtended { int8_t reserved[60]; }; -int PS4_SYSV_ABI sceImeDialogAbort(); -int PS4_SYSV_ABI sceImeDialogForceClose(); -int PS4_SYSV_ABI sceImeDialogForTestFunction(); +Error PS4_SYSV_ABI sceImeDialogAbort(); +Error PS4_SYSV_ABI sceImeDialogForceClose(); +Error PS4_SYSV_ABI sceImeDialogForTestFunction(); int PS4_SYSV_ABI sceImeDialogGetCurrentStarState(); int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm(); int PS4_SYSV_ABI sceImeDialogGetPanelSize(); int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended(); -int PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result); -/*OrbisImeDialogStatus*/ int PS4_SYSV_ABI sceImeDialogGetStatus(); -int PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended); +Error PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result); +OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus(); +Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended); int PS4_SYSV_ABI sceImeDialogInitInternal(); int PS4_SYSV_ABI sceImeDialogInitInternal2(); int PS4_SYSV_ABI sceImeDialogInitInternal3(); int PS4_SYSV_ABI sceImeDialogSetPanelPosition(); -int PS4_SYSV_ABI sceImeDialogTerm(); +Error PS4_SYSV_ABI sceImeDialogTerm(); void RegisterlibSceImeDialog(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::ImeDialog \ No newline at end of file diff --git a/src/core/libraries/dialogs/ime_dialog_ui.cpp b/src/core/libraries/dialogs/ime_dialog_ui.cpp new file mode 100644 index 000000000..9d50d2fbb --- /dev/null +++ b/src/core/libraries/dialogs/ime_dialog_ui.cpp @@ -0,0 +1,390 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include + +#include "common/assert.h" +#include "common/logging/log.h" +#include "common/singleton.h" +#include "core/libraries/dialogs/ime_dialog.h" +#include "core/libraries/dialogs/ime_dialog_ui.h" +#include "core/linker.h" +#include "imgui/imgui_std.h" + +using namespace ImGui; + +static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; + +namespace Libraries::ImeDialog { + +ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, + const OrbisImeParamExtended* extended) { + if (!param) + return; + + userId = param->userId; + is_multiLine = True(param->option & OrbisImeDialogOption::MULTILINE); + is_numeric = param->type == OrbisImeType::NUMBER; + type = param->type; + enter_label = param->enterLabel; + text_filter = param->filter; + keyboard_filter = extended ? extended->extKeyboardFilter : nullptr; + max_text_length = param->maxTextLength; + text_buffer = param->inputTextBuffer; + + if (param->title) { + std::size_t title_len = std::char_traits::length(param->title); + title.resize(title_len * 4 + 1); + title[title_len * 4] = '\0'; + + if (!ConvertOrbisToUTF8(param->title, title_len, &title[0], title_len * 4)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert title to utf8 encoding"); + } + } + + if (param->placeholder) { + std::size_t placeholder_len = std::char_traits::length(param->placeholder); + placeholder.resize(placeholder_len * 4 + 1); + placeholder[placeholder_len * 4] = '\0'; + + if (!ConvertOrbisToUTF8(param->placeholder, placeholder_len, &placeholder[0], + placeholder_len * 4)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert placeholder to utf8 encoding"); + } + } + + std::size_t text_len = std::char_traits::length(text_buffer); + if (!ConvertOrbisToUTF8(text_buffer, text_len, current_text.begin(), + ORBIS_IME_DIALOG_MAX_TEXT_LENGTH * 4)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert text to utf8 encoding"); + } +} + +ImeDialogState::ImeDialogState(ImeDialogState&& other) noexcept + : input_changed(other.input_changed), userId(other.userId), is_multiLine(other.is_multiLine), + is_numeric(other.is_numeric), type(other.type), enter_label(other.enter_label), + text_filter(other.text_filter), keyboard_filter(other.keyboard_filter), + max_text_length(other.max_text_length), text_buffer(other.text_buffer), + title(std::move(other.title)), placeholder(std::move(other.placeholder)), + current_text(other.current_text) { + + other.text_buffer = nullptr; +} + +ImeDialogState& ImeDialogState::operator=(ImeDialogState&& other) { + if (this != &other) { + input_changed = other.input_changed; + userId = other.userId; + is_multiLine = other.is_multiLine; + is_numeric = other.is_numeric; + type = other.type; + enter_label = other.enter_label; + text_filter = other.text_filter; + keyboard_filter = other.keyboard_filter; + max_text_length = other.max_text_length; + text_buffer = other.text_buffer; + title = std::move(other.title); + placeholder = std::move(other.placeholder); + current_text = other.current_text; + + other.text_buffer = nullptr; + } + + return *this; +} + +bool ImeDialogState::CopyTextToOrbisBuffer() { + if (!text_buffer) { + return false; + } + + return ConvertUTF8ToOrbis(current_text.begin(), current_text.capacity(), text_buffer, + max_text_length); +} + +bool ImeDialogState::CallTextFilter() { + if (!text_filter || !input_changed) { + return true; + } + + input_changed = false; + + char16_t src_text[ORBIS_IME_DIALOG_MAX_TEXT_LENGTH + 1] = {0}; + u32 src_text_length = current_text.size(); + char16_t out_text[ORBIS_IME_DIALOG_MAX_TEXT_LENGTH + 1] = {0}; + u32 out_text_length = ORBIS_IME_DIALOG_MAX_TEXT_LENGTH; + + if (!ConvertUTF8ToOrbis(current_text.begin(), src_text_length, src_text, + ORBIS_IME_DIALOG_MAX_TEXT_LENGTH)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert text to orbis encoding"); + return false; + } + + auto* linker = Common::Singleton::Instance(); + int ret = + linker->ExecuteGuest(text_filter, out_text, &out_text_length, src_text, src_text_length); + + if (ret != 0) { + return false; + } + + if (!ConvertOrbisToUTF8(out_text, out_text_length, current_text.begin(), + ORBIS_IME_DIALOG_MAX_TEXT_LENGTH * 4)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert text to utf8 encoding"); + return false; + } + + return true; +} + +bool ImeDialogState::CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, + u32* out_status) { + if (!keyboard_filter) { + return true; + } + + auto* linker = Common::Singleton::Instance(); + int ret = linker->ExecuteGuest(keyboard_filter, src_keycode, out_keycode, out_status, nullptr); + + return ret == 0; +} + +bool ImeDialogState::ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, + char* utf8_text, std::size_t utf8_text_len) { + + std::fill(utf8_text, utf8_text + utf8_text_len, '\0'); + const ImWchar* orbis_text_ptr = reinterpret_cast(orbis_text); + ImTextStrToUtf8(utf8_text, utf8_text_len, orbis_text_ptr, orbis_text_ptr + orbis_text_len); + + return true; +} + +bool ImeDialogState::ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_text_len, + char16_t* orbis_text, std::size_t orbis_text_len) { + + std::fill(orbis_text, orbis_text + orbis_text_len, u'\0'); + ImTextStrFromUtf8(reinterpret_cast(orbis_text), orbis_text_len, utf8_text, nullptr); + + return true; +} + +ImeDialogUi::ImeDialogUi(ImeDialogState* state, OrbisImeDialogStatus* status, + OrbisImeDialogResult* result) + : state(state), status(status), result(result) { + + if (state && *status == OrbisImeDialogStatus::RUNNING) { + AddLayer(this); + } +} + +ImeDialogUi::~ImeDialogUi() { + std::scoped_lock lock(draw_mutex); + + Free(); +} + +ImeDialogUi::ImeDialogUi(ImeDialogUi&& other) noexcept + : state(other.state), status(other.status), result(other.result), + first_render(other.first_render) { + + std::scoped_lock lock(draw_mutex, other.draw_mutex); + other.state = nullptr; + other.status = nullptr; + other.result = nullptr; + + if (state && *status == OrbisImeDialogStatus::RUNNING) { + AddLayer(this); + } +} + +ImeDialogUi& ImeDialogUi::operator=(ImeDialogUi&& other) { + std::scoped_lock lock(draw_mutex, other.draw_mutex); + Free(); + + state = other.state; + status = other.status; + result = other.result; + first_render = other.first_render; + other.state = nullptr; + other.status = nullptr; + other.result = nullptr; + + if (state && *status == OrbisImeDialogStatus::RUNNING) { + AddLayer(this); + } + + return *this; +} + +void ImeDialogUi::Free() { + RemoveLayer(this); +} + +void ImeDialogUi::Draw() { + std::unique_lock lock{draw_mutex}; + + if (!state) { + return; + } + + if (!status || *status != OrbisImeDialogStatus::RUNNING) { + return; + } + + const auto& ctx = *GetCurrentContext(); + const auto& io = ctx.IO; + + ImVec2 window_size; + + if (state->is_multiLine) { + window_size = {500.0f, 300.0f}; + } else { + window_size = {500.0f, 150.0f}; + } + + CentralizeNextWindow(); + SetNextWindowSize(window_size); + SetNextWindowCollapsed(false); + + if (first_render || !io.NavActive) { + SetNextWindowFocus(); + } + + if (Begin("IME Dialog##ImeDialog", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { + DrawPrettyBackground(); + + if (!state->title.empty()) { + SetWindowFontScale(1.7f); + TextUnformatted(state->title.data()); + SetWindowFontScale(1.0f); + } + + if (state->is_multiLine) { + DrawMultiLineInputText(); + } else { + DrawInputText(); + } + + SetCursorPosY(GetCursorPosY() + 10.0f); + + const char* button_text; + + switch (state->enter_label) { + case OrbisImeEnterLabel::GO: + button_text = "Go##ImeDialogOK"; + break; + case OrbisImeEnterLabel::SEARCH: + button_text = "Search##ImeDialogOK"; + break; + case OrbisImeEnterLabel::SEND: + button_text = "Send##ImeDialogOK"; + break; + case OrbisImeEnterLabel::DEFAULT: + default: + button_text = "OK##ImeDialogOK"; + break; + } + + float button_spacing = 10.0f; + float total_button_width = BUTTON_SIZE.x * 2 + button_spacing; + float button_start_pos = (window_size.x - total_button_width) / 2.0f; + + SetCursorPosX(button_start_pos); + + if (Button(button_text, BUTTON_SIZE) || + (!state->is_multiLine && IsKeyPressed(ImGuiKey_Enter))) { + *status = OrbisImeDialogStatus::FINISHED; + result->endstatus = OrbisImeDialogEndStatus::OK; + } + + SameLine(0.0f, button_spacing); + + if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { + *status = OrbisImeDialogStatus::FINISHED; + result->endstatus = OrbisImeDialogEndStatus::USER_CANCELED; + } + } + End(); + + first_render = false; +} + +void ImeDialogUi::DrawInputText() { + ImVec2 input_size = {GetWindowWidth() - 40.0f, 0.0f}; + SetCursorPosX(20.0f); + if (first_render) { + SetKeyboardFocusHere(); + } + const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), + state->max_text_length, input_size, ImGuiInputTextFlags_CallbackCharFilter, + InputTextCallback, this)) { + state->input_changed = true; + } +} + +void ImeDialogUi::DrawMultiLineInputText() { + ImVec2 input_size = {GetWindowWidth() - 40.0f, 200.0f}; + SetCursorPosX(20.0f); + ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackCharFilter | + static_cast(ImGuiInputTextFlags_Multiline); + if (first_render) { + SetKeyboardFocusHere(); + } + const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), + state->max_text_length, input_size, flags, InputTextCallback, this)) { + state->input_changed = true; + } +} + +int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { + ImeDialogUi* ui = static_cast(data->UserData); + + ASSERT(ui); + + // Should we filter punctuation? + if (ui->state->is_numeric && (data->EventChar < '0' || data->EventChar > '9') && + data->EventChar != '\b' && data->EventChar != ',' && data->EventChar != '.') { + return 1; + } + + if (!ui->state->keyboard_filter) { + return 0; + } + + // ImGui encodes ImWchar32 as multi-byte UTF-8 characters + char* event_char = reinterpret_cast(&data->EventChar); + + // Call the keyboard filter + OrbisImeKeycode src_keycode = { + .keycode = 0, + .character = 0, + .status = 1, // ??? 1 = key pressed, 0 = key released + .type = OrbisImeKeyboardType::ENGLISH_US, // TODO set this to the correct value (maybe use + // the current language?) + .userId = ui->state->userId, + .resourceId = 0, + .timestamp = 0}; + + if (!ui->state->ConvertUTF8ToOrbis(event_char, 4, &src_keycode.character, 1)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert orbis char to utf8"); + return 0; + } + src_keycode.keycode = src_keycode.character; // TODO set this to the correct value + + u16 out_keycode; + u32 out_status; + + ui->state->CallKeyboardFilter(&src_keycode, &out_keycode, &out_status); + + // TODO. set the keycode + + return 0; +} + +} // namespace Libraries::ImeDialog \ No newline at end of file diff --git a/src/core/libraries/dialogs/ime_dialog_ui.h b/src/core/libraries/dialogs/ime_dialog_ui.h new file mode 100644 index 000000000..96c83954a --- /dev/null +++ b/src/core/libraries/dialogs/ime_dialog_ui.h @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include "common/cstring.h" +#include "common/types.h" +#include "core/libraries/dialogs/ime_dialog.h" +#include "imgui/imgui_layer.h" + +namespace Libraries::ImeDialog { + +class ImeDialogUi; + +class ImeDialogState final { + friend ImeDialogUi; + + bool input_changed = false; + + s32 userId{}; + bool is_multiLine{}; + bool is_numeric{}; + OrbisImeType type{}; + OrbisImeEnterLabel enter_label{}; + OrbisImeTextFilter text_filter{}; + OrbisImeExtKeyboardFilter keyboard_filter{}; + u32 max_text_length{}; + char16_t* text_buffer{}; + std::vector title; + std::vector placeholder; + + // A character can hold up to 4 bytes in UTF-8 + Common::CString current_text; + +public: + ImeDialogState(const OrbisImeDialogParam* param = nullptr, + const OrbisImeParamExtended* extended = nullptr); + ImeDialogState(const ImeDialogState& other) = delete; + ImeDialogState(ImeDialogState&& other) noexcept; + ImeDialogState& operator=(ImeDialogState&& other); + + bool CopyTextToOrbisBuffer(); + bool CallTextFilter(); + +private: + bool CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, u32* out_status); + + bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, + std::size_t native_text_len); + bool ConvertUTF8ToOrbis(const char* native_text, std::size_t utf8_text_len, + char16_t* orbis_text, std::size_t orbis_text_len); +}; + +class ImeDialogUi final : public ImGui::Layer { + ImeDialogState* state{}; + OrbisImeDialogStatus* status{}; + OrbisImeDialogResult* result{}; + + bool first_render = true; + std::mutex draw_mutex; + +public: + explicit ImeDialogUi(ImeDialogState* state = nullptr, OrbisImeDialogStatus* status = nullptr, + OrbisImeDialogResult* result = nullptr); + ~ImeDialogUi() override; + ImeDialogUi(const ImeDialogUi& other) = delete; + ImeDialogUi(ImeDialogUi&& other) noexcept; + ImeDialogUi& operator=(ImeDialogUi&& other); + + void Draw() override; + +private: + void Free(); + + void DrawInputText(); + void DrawMultiLineInputText(); + + static int InputTextCallback(ImGuiInputTextCallbackData* data); +}; + +} // namespace Libraries::ImeDialog diff --git a/src/core/libraries/disc_map/disc_map.cpp b/src/core/libraries/disc_map/disc_map.cpp index 79f4acb34..bb566a149 100644 --- a/src/core/libraries/disc_map/disc_map.cpp +++ b/src/core/libraries/disc_map/disc_map.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index 123edcee8..dae285664 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -233,9 +233,6 @@ constexpr int SCE_KERNEL_ERROR_ESDKVERSION = 0x80020063; constexpr int SCE_KERNEL_ERROR_ESTART = 0x80020064; constexpr int SCE_KERNEL_ERROR_ESTOP = 0x80020065; -// libSceRandom error codes -constexpr int SCE_RANDOM_ERROR_INVALID = 0x817C0016; - // videoOut constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument constexpr int SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS = 0x80290002; // invalid addresses @@ -249,14 +246,6 @@ constexpr int SCE_VIDEO_OUT_ERROR_SLOT_OCCUPIED = 0x80290010; // slot alr constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full constexpr int SCE_VIDEO_OUT_ERROR_INVALID_OPTION = 0x8029001A; // Invalid buffer attribute option -// GnmDriver -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID = 0x80D17000; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID = 0x80D17001; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR = 0x80D17003; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE = 0x80D17002; -constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR = 0x80D17004; -constexpr int ORBIS_GNM_ERROR_FAILURE = 0x8EEE00FF; - // Generic constexpr int ORBIS_OK = 0x00000000; constexpr int ORBIS_FAIL = 0xFFFFFFFF; @@ -449,13 +438,50 @@ constexpr int ORBIS_USER_SERVICE_ERROR_BUFFER_TOO_SHORT = 0x8096000A; // SystemService library constexpr int ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER = 0x80A10003; +constexpr int ORBIS_SYSTEM_SERVICE_ERROR_NO_EVENT = 0x80A10004; // NpTrophy library +constexpr int ORBIS_NP_TROPHY_ERROR_UNKNOWN = 0x80551600; +constexpr int ORBIS_NP_TROPHY_ERROR_NOT_INITIALIZED = 0x80551601; +constexpr int ORBIS_NP_TROPHY_ERROR_ALREADY_INITIALIZED = 0x80551602; +constexpr int ORBIS_NP_TROPHY_ERROR_OUT_OF_MEMORY = 0x80551603; constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT = 0x80551604; +constexpr int ORBIS_NP_TROPHY_ERROR_INSUFFICIENT_BUFFER = 0x80551605; +constexpr int ORBIS_NP_TROPHY_ERROR_EXCEEDS_MAX = 0x80551606; +constexpr int ORBIS_NP_TROPHY_ERROR_ABORT = 0x80551607; constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE = 0x80551608; -constexpr int ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX = 0x80551624; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT = 0x80551609; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_TROPHY_ID = 0x8055160A; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_GROUP_ID = 0x8055160B; +constexpr int ORBIS_NP_TROPHY_ERROR_TROPHY_ALREADY_UNLOCKED = 0x8055160C; +constexpr int ORBIS_NP_TROPHY_ERROR_PLATINUM_CANNOT_UNLOCK = 0x8055160D; +constexpr int ORBIS_NP_TROPHY_ERROR_ACCOUNTID_NOT_MATCH = 0x8055160E; +constexpr int ORBIS_NP_TROPHY_ERROR_NOT_REGISTERED = 0x8055160F; +constexpr int ORBIS_NP_TROPHY_ERROR_ALREADY_REGISTERED = 0x80551610; +constexpr int ORBIS_NP_TROPHY_ERROR_BROKEN_DATA = 0x80551611; +constexpr int ORBIS_NP_TROPHY_ERROR_INSUFFICIENT_SPACE = 0x80551612; constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_ALREADY_EXISTS = 0x80551613; -constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX = 0x80551622; +constexpr int ORBIS_NP_TROPHY_ERROR_ICON_FILE_NOT_FOUND = 0x80551614; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_TRP_FILE_FORMAT = 0x80551616; +constexpr int ORBIS_NP_TROPHY_ERROR_UNSUPPORTED_TRP_FILE = 0x80551617; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_TROPHY_CONF_FORMAT = 0x80551618; +constexpr int ORBIS_NP_TROPHY_ERROR_UNSUPPORTED_TROPHY_CONF = 0x80551619; +constexpr int ORBIS_NP_TROPHY_ERROR_TROPHY_NOT_UNLOCKED = 0x8055161A; +constexpr int ORBIS_NP_TROPHY_ERROR_USER_NOT_FOUND = 0x8055161C; +constexpr int ORBIS_NP_TROPHY_ERROR_USER_NOT_LOGGED_IN = 0x8055161D; +constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_USER_LOGOUT = 0x8055161E; +constexpr int ORBIS_NP_TROPHY_ERROR_USE_TRP_FOR_DEVELOPMENT = 0x8055161F; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_NP_SERVICE_LABEL = 0x80551621; +constexpr int ORBIS_NP_TROPHY_ERROR_NOT_SUPPORTED = 0x80551622; +constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX = 0x80551623; +constexpr int ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX = 0x80551624; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_USER_ID = 0x80551625; +constexpr int ORBIS_NP_TROPHY_ERROR_TITLE_CONF_NOT_INSTALLED = 0x80551626; +constexpr int ORBIS_NP_TROPHY_ERROR_BROKEN_TITLE_CONF = 0x80551627; +constexpr int ORBIS_NP_TROPHY_ERROR_INCONSISTENT_TITLE_CONF = 0x80551628; +constexpr int ORBIS_NP_TROPHY_ERROR_TITLE_BACKGROUND = 0x80551629; +constexpr int ORBIS_NP_TROPHY_ERROR_SCREENSHOT_DISABLED = 0x8055162B; +constexpr int ORBIS_NP_TROPHY_ERROR_SCREENSHOT_DISPLAY_BUFFER_NOT_IN_USE = 0x8055162D; // AvPlayer library constexpr int ORBIS_AVPLAYER_ERROR_INVALID_PARAMS = 0x806A0001; @@ -471,4 +497,14 @@ constexpr int ORBIS_AVPLAYER_ERROR_INFO_AES_ENCRY = 0x806A00B5; constexpr int ORBIS_AVPLAYER_ERROR_INFO_OTHER_ENCRY = 0x806A00BF; // AppContent library -constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; \ No newline at end of file +constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; +constexpr int ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = 0x80D90007; +constexpr int ORBIS_APP_CONTENT_ERROR_NOT_FOUND = 0x80D90005; + +// Fiber library +constexpr int ORBIS_FIBER_ERROR_NULL = 0x80590001; +constexpr int ORBIS_FIBER_ERROR_ALIGNMENT = 0x80590002; +constexpr int ORBIS_FIBER_ERROR_RANGE = 0x80590003; +constexpr int ORBIS_FIBER_ERROR_INVALID = 0x80590004; +constexpr int ORBIS_FIBER_ERROR_PERMISSION = 0x80590005; +constexpr int ORBIS_FIBER_ERROR_STATE = 0x80590006; \ No newline at end of file diff --git a/src/core/libraries/fiber/fiber.cpp b/src/core/libraries/fiber/fiber.cpp new file mode 100644 index 000000000..bd1575dda --- /dev/null +++ b/src/core/libraries/fiber/fiber.cpp @@ -0,0 +1,284 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "fiber.h" + +#include "common/logging/log.h" +#include "common/singleton.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "core/linker.h" + +#ifdef _WIN64 +#include +#endif + +namespace Libraries::Fiber { + +constexpr static u64 kFiberSignature = 0x054ad954; + +thread_local SceFiber* gCurrentFiber = nullptr; +thread_local void* gFiberThread = nullptr; + +void FiberEntry(void* param) { + SceFiber* fiber = static_cast(param); + u64 argRun = 0; + u64 argRet = 0; + + gCurrentFiber = fiber; + + if (fiber->pArgRun != nullptr) { + argRun = *fiber->pArgRun; + } + + const auto* linker = Common::Singleton::Instance(); + linker->ExecuteGuest(fiber->entry, fiber->argOnInitialize, argRun); + + UNREACHABLE(); +} + +s32 PS4_SYSV_ABI sceFiberInitialize(SceFiber* fiber, const char* name, SceFiberEntry entry, + u64 argOnInitialize, void* addrContext, u64 sizeContext, + const SceFiberOptParam* optParam) { + LOG_INFO(Lib_Fiber, "called: name = {}", name); + + if (!fiber || !name || !entry) { + return ORBIS_FIBER_ERROR_NULL; + } + + fiber->signature = kFiberSignature; + + fiber->entry = entry; + fiber->argOnInitialize = argOnInitialize; + + fiber->argRun = 0; + fiber->pArgRun = &fiber->argRun; + fiber->argReturn = 0; + fiber->pArgReturn = &fiber->argReturn; + + fiber->sizeContext = sizeContext; + + fiber->state = FiberState::Init; +#ifdef _WIN64 + fiber->handle = CreateFiber(sizeContext, FiberEntry, fiber); +#else + UNREACHABLE_MSG("Missing implementation"); +#endif + strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH); + + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberOptParamInitialize(SceFiberOptParam* optParam) { + LOG_ERROR(Lib_Fiber, "called"); + + if (!optParam) { + return ORBIS_FIBER_ERROR_NULL; + } + + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberFinalize(SceFiber* fiber) { + LOG_TRACE(Lib_Fiber, "called"); + + if (!fiber) { + return ORBIS_FIBER_ERROR_NULL; + } + if ((u64)fiber % 8 != 0) { + return ORBIS_FIBER_ERROR_ALIGNMENT; + } + if (fiber->signature != kFiberSignature) { + return ORBIS_FIBER_ERROR_INVALID; + } + if (fiber->state != FiberState::Run) { + return ORBIS_FIBER_ERROR_STATE; + } + + fiber->signature = 0; + fiber->state = FiberState::None; + +#ifdef _WIN64 + DeleteFiber(fiber->handle); +#else + UNREACHABLE_MSG("Missing implementation"); +#endif + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberRun(SceFiber* fiber, u64 argOnRunTo, u64* argOnReturn) { + LOG_TRACE(Lib_Fiber, "called"); + + if (!fiber) { + return ORBIS_FIBER_ERROR_NULL; + } + if ((u64)fiber % 8 != 0) { + return ORBIS_FIBER_ERROR_ALIGNMENT; + } + if (fiber->signature != kFiberSignature) { + return ORBIS_FIBER_ERROR_INVALID; + } + if (fiber->state == FiberState::Run) { + return ORBIS_FIBER_ERROR_STATE; + } + + if (gFiberThread == nullptr) { +#ifdef _WIN64 + gFiberThread = ConvertThreadToFiber(nullptr); +#else + UNREACHABLE_MSG("Missing implementation"); +#endif + } + + gCurrentFiber = fiber; + + if (fiber->pArgRun != nullptr) { + *fiber->pArgRun = argOnRunTo; + } + + fiber->pArgReturn = argOnReturn; + fiber->state = FiberState::Run; +#ifdef _WIN64 + SwitchToFiber(fiber->handle); +#else + UNREACHABLE_MSG("Missing implementation"); +#endif + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberSwitch(SceFiber* fiber, u64 argOnRunTo, u64* argOnRun) { + LOG_TRACE(Lib_Fiber, "called"); + + if (!fiber) { + return ORBIS_FIBER_ERROR_NULL; + } + if ((u64)fiber % 8 != 0) { + return ORBIS_FIBER_ERROR_ALIGNMENT; + } + if (fiber->signature != kFiberSignature) { + return ORBIS_FIBER_ERROR_INVALID; + } + if (gCurrentFiber == nullptr) { + return ORBIS_FIBER_ERROR_PERMISSION; + } + if (fiber->state == FiberState::Run) { + return ORBIS_FIBER_ERROR_STATE; + } + + gCurrentFiber->state = FiberState::Suspend; + + // TODO: argOnRun + + *fiber->pArgRun = argOnRunTo; + fiber->state = FiberState::Run; + + gCurrentFiber = fiber; +#ifdef _WIN64 + SwitchToFiber(fiber->handle); +#else + UNREACHABLE_MSG("Missing implementation"); +#endif + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberGetSelf(SceFiber** fiber) { + LOG_TRACE(Lib_Fiber, "called"); + + if (!fiber || !gCurrentFiber) { + return ORBIS_FIBER_ERROR_NULL; + } + if (gCurrentFiber->signature != kFiberSignature) { + return ORBIS_FIBER_ERROR_PERMISSION; + } + + *fiber = gCurrentFiber; + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberReturnToThread(u64 argOnReturn, u64* argOnRun) { + LOG_TRACE(Lib_Fiber, "called"); + + if (gCurrentFiber->signature != kFiberSignature) { + return ORBIS_FIBER_ERROR_PERMISSION; + } + + if (gCurrentFiber->pArgReturn != nullptr) { + *gCurrentFiber->pArgReturn = argOnReturn; + } + + // TODO: argOnRun + gCurrentFiber->state = FiberState::Suspend; + gCurrentFiber = nullptr; +#ifdef _WIN64 + SwitchToFiber(gFiberThread); +#else + UNREACHABLE_MSG("Missing implementation"); +#endif + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberGetInfo(SceFiber* fiber, SceFiberInfo* fiberInfo) { + LOG_INFO(Lib_Fiber, "called"); + + if (!fiber || !fiberInfo) { + return ORBIS_FIBER_ERROR_NULL; + } + + fiberInfo->entry = fiber->entry; + fiberInfo->argOnInitialize = fiber->argOnInitialize; + fiberInfo->addrContext = nullptr; + fiberInfo->sizeContext = fiber->sizeContext; + fiberInfo->sizeContextMargin = 0; + + strncpy(fiberInfo->name, fiber->name, ORBIS_FIBER_MAX_NAME_LENGTH); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberStartContextSizeCheck(u32 flags) { + LOG_ERROR(Lib_Fiber, "called"); + + if (flags != 0) { + return ORBIS_FIBER_ERROR_INVALID; + } + + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberStopContextSizeCheck() { + LOG_ERROR(Lib_Fiber, "called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceFiberRename(SceFiber* fiber, const char* name) { + LOG_INFO(Lib_Fiber, "called, name = {}", name); + + if (!fiber || !name) { + return ORBIS_FIBER_ERROR_NULL; + } + if ((u64)fiber % 8 != 0) { + return ORBIS_FIBER_ERROR_ALIGNMENT; + } + + strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH); + return ORBIS_OK; +} + +void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("hVYD7Ou2pCQ", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberInitialize); + LIB_FUNCTION("asjUJJ+aa8s", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberOptParamInitialize); + LIB_FUNCTION("JeNX5F-NzQU", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberFinalize); + + LIB_FUNCTION("a0LLrZWac0M", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberRun); + LIB_FUNCTION("PFT2S-tJ7Uk", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberSwitch); + LIB_FUNCTION("p+zLIOg27zU", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberGetSelf); + LIB_FUNCTION("B0ZX2hx9DMw", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberReturnToThread); + + 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); +} + +} // namespace Libraries::Fiber \ No newline at end of file diff --git a/src/core/libraries/fiber/fiber.h b/src/core/libraries/fiber/fiber.h new file mode 100644 index 000000000..930409caa --- /dev/null +++ b/src/core/libraries/fiber/fiber.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/assert.h" +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} +namespace Libraries::Fiber { + +#define ORBIS_FIBER_MAX_NAME_LENGTH (31) + +typedef void PS4_SYSV_ABI (*SceFiberEntry)(u64 argOnInitialize, u64 argOnRun); + +enum FiberState : u32 { + None = 0u, + Init = 1u, + Run = 2u, + Suspend = 3u, +}; + +struct SceFiber { + u64 signature; + FiberState state; + SceFiberEntry entry; + + u64 argOnInitialize; + + u64 argRun; + u64* pArgRun; + + u64 argReturn; + u64* pArgReturn; + + u64 sizeContext; + + char name[ORBIS_FIBER_MAX_NAME_LENGTH]; + void* handle; +}; +static_assert(sizeof(SceFiber) <= 256); + +struct SceFiberInfo { + u64 size; + SceFiberEntry entry; + u64 argOnInitialize; + void* addrContext; + u64 sizeContext; + char name[ORBIS_FIBER_MAX_NAME_LENGTH + 1]; + u64 sizeContextMargin; +}; +static_assert(sizeof(SceFiberInfo) <= 128); + +typedef void* SceFiberOptParam; + +s32 PS4_SYSV_ABI sceFiberInitialize(SceFiber* fiber, const char* name, SceFiberEntry entry, + u64 argOnInitialize, void* addrContext, u64 sizeContext, + const SceFiberOptParam* optParam); + +s32 PS4_SYSV_ABI sceFiberOptParamInitialize(SceFiberOptParam* optParam); + +s32 PS4_SYSV_ABI sceFiberFinalize(SceFiber* fiber); + +s32 PS4_SYSV_ABI sceFiberRun(SceFiber* fiber, u64 argOnRunTo, u64* argOnReturn); + +s32 PS4_SYSV_ABI sceFiberSwitch(SceFiber* fiber, u64 argOnRunTo, u64* argOnRun); + +s32 PS4_SYSV_ABI sceFiberGetSelf(SceFiber** fiber); + +s32 PS4_SYSV_ABI sceFiberReturnToThread(u64 argOnReturn, u64* argOnRun); + +s32 PS4_SYSV_ABI sceFiberGetInfo(SceFiber* fiber, SceFiberInfo* fiberInfo); + +s32 PS4_SYSV_ABI sceFiberStartContextSizeCheck(u32 flags); + +s32 PS4_SYSV_ABI sceFiberStopContextSizeCheck(void); + +s32 PS4_SYSV_ABI sceFiberRename(SceFiber* fiber, const char* name); + +void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Fiber \ No newline at end of file diff --git a/src/core/libraries/game_live_streaming/gamelivestreaming.cpp b/src/core/libraries/game_live_streaming/gamelivestreaming.cpp new file mode 100644 index 000000000..a1ebddfbf --- /dev/null +++ b/src/core/libraries/game_live_streaming/gamelivestreaming.cpp @@ -0,0 +1,354 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "gamelivestreaming.h" + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" + +namespace Libraries::GameLiveStreaming { + +int PS4_SYSV_ABI sceGameLiveStreamingStartDebugBroadcast() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingStopDebugBroadcast() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingApplySocialFeedbackMessageFilter() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingCheckCallback() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingClearPresetSocialFeedbackCommands() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingClearSocialFeedbackMessages() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingClearSpoilerTag() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingEnableLiveStreaming() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingEnableSocialFeedback() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingGetCurrentBroadcastScreenLayout() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingGetCurrentStatus(OrbisGameLiveStreamingStatus* status) { + memset(status, 0, sizeof(*status)); + status->isOnAir = false; + LOG_DEBUG(Lib_GameLiveStreaming, "(STUBBED) called userid = {}", status->userId); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingGetCurrentStatus2() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingGetProgramInfo() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingGetSocialFeedbackMessages() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingGetSocialFeedbackMessagesCount() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingInitialize() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingLaunchLiveViewer() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingLaunchLiveViewerA() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingPermitLiveStreaming() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingPermitServerSideRecording() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingPostSocialMessage() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingRegisterCallback() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenCloseSeparateMode() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenConfigureSeparateMode() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenInitialize() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenInitializeSeparateModeParameter() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenOpenSeparateMode() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenSetMode() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingScreenTerminate() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetCameraFrameSetting() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetDefaultServiceProviderPermission() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetGuardAreas() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetInvitationSessionId() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetLinkCommentPreset() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetMaxBitrate() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetMetadata() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetPresetSocialFeedbackCommands() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetServiceProviderPermission() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetSpoilerTag() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingSetStandbyScreenResource() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingStartGenerateStandbyScreenResource() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingStartSocialFeedbackMessageFiltering() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingStopGenerateStandbyScreenResource() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingStopSocialFeedbackMessageFiltering() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingTerminate() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceGameLiveStreamingUnregisterCallback() { + LOG_ERROR(Lib_GameLiveStreaming, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceGameLiveStreaming(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("caqgDl+V9qA", "libSceGameLiveStreaming_debug", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingStartDebugBroadcast); + LIB_FUNCTION("0i8Lrllxwow", "libSceGameLiveStreaming_debug", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingStopDebugBroadcast); + LIB_FUNCTION("NqkTzemliC0", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingApplySocialFeedbackMessageFilter); + LIB_FUNCTION("PC4jq87+YQI", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingCheckCallback); + LIB_FUNCTION("FcHBfHjFXkA", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingClearPresetSocialFeedbackCommands); + LIB_FUNCTION("lZ2Sd0uEvpo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingClearSocialFeedbackMessages); + LIB_FUNCTION("6c2zGtThFww", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingClearSpoilerTag); + LIB_FUNCTION("dWM80AX39o4", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingEnableLiveStreaming); + LIB_FUNCTION("wBOQWjbWMfU", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingEnableSocialFeedback); + LIB_FUNCTION("aRSQNqbats4", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetCurrentBroadcastScreenLayout); + LIB_FUNCTION("CoPMx369EqM", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetCurrentStatus); + LIB_FUNCTION("lK8dLBNp9OE", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetCurrentStatus2); + LIB_FUNCTION("OIIm19xu+NM", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetProgramInfo); + LIB_FUNCTION("PMx7N4WqNdo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetSocialFeedbackMessages); + LIB_FUNCTION("yeQKjHETi40", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetSocialFeedbackMessagesCount); + LIB_FUNCTION("kvYEw2lBndk", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingInitialize); + LIB_FUNCTION("ysWfX5PPbfc", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingLaunchLiveViewer); + LIB_FUNCTION("cvRCb7DTAig", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingLaunchLiveViewerA); + LIB_FUNCTION("K0QxEbD7q+c", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingPermitLiveStreaming); + LIB_FUNCTION("-EHnU68gExU", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingPermitServerSideRecording); + LIB_FUNCTION("hggKhPySVgI", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingPostSocialMessage); + LIB_FUNCTION("nFP8qT9YXbo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingRegisterCallback); + LIB_FUNCTION("b5RaMD2J0So", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenCloseSeparateMode); + LIB_FUNCTION("hBdd8n6kuvE", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenConfigureSeparateMode); + LIB_FUNCTION("uhCmn81s-mU", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenInitialize); + LIB_FUNCTION("fo5B8RUaBxQ", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenInitializeSeparateModeParameter); + LIB_FUNCTION("iorzW0pKOiA", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenOpenSeparateMode); + LIB_FUNCTION("gDSvt78H3Oo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenSetMode); + LIB_FUNCTION("HE93dr-5rx4", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingScreenTerminate); + LIB_FUNCTION("3PSiwAzFISE", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetCameraFrameSetting); + LIB_FUNCTION("TwuUzTKKeek", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetDefaultServiceProviderPermission); + LIB_FUNCTION("Gw6S4oqlY7E", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetGuardAreas); + LIB_FUNCTION("QmQYwQ7OTJI", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetInvitationSessionId); + LIB_FUNCTION("Sb5bAXyUt5c", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetLinkCommentPreset); + LIB_FUNCTION("q-kxuaF7URU", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetMaxBitrate); + LIB_FUNCTION("hUY-mSOyGL0", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetMetadata); + LIB_FUNCTION("ycodiP2I0xo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetPresetSocialFeedbackCommands); + LIB_FUNCTION("x6deXUpQbBo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription); + LIB_FUNCTION("mCoz3k3zPmA", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetServiceProviderPermission); + LIB_FUNCTION("ZuX+zzz2DkA", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetSpoilerTag); + LIB_FUNCTION("MLvYI86FFAo", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingSetStandbyScreenResource); + LIB_FUNCTION("y0KkAydy9xE", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingStartGenerateStandbyScreenResource); + LIB_FUNCTION("Y1WxX7dPMCw", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingStartSocialFeedbackMessageFiltering); + LIB_FUNCTION("D7dg5QJ4FlE", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingStopGenerateStandbyScreenResource); + LIB_FUNCTION("bYuGUBuIsaY", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingStopSocialFeedbackMessageFiltering); + LIB_FUNCTION("9yK6Fk8mKOQ", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingTerminate); + LIB_FUNCTION("5XHaH3kL+bA", "libSceGameLiveStreaming", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingUnregisterCallback); + LIB_FUNCTION("caqgDl+V9qA", "libSceGameLiveStreaming_direct_streaming", 1, + "libSceGameLiveStreaming", 1, 1, sceGameLiveStreamingStartDebugBroadcast); + LIB_FUNCTION("0i8Lrllxwow", "libSceGameLiveStreaming_direct_streaming", 1, + "libSceGameLiveStreaming", 1, 1, sceGameLiveStreamingStopDebugBroadcast); + LIB_FUNCTION("CoPMx369EqM", "libSceGameLiveStreamingCompat", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingGetCurrentStatus); + LIB_FUNCTION("ysWfX5PPbfc", "libSceGameLiveStreamingCompat", 1, "libSceGameLiveStreaming", 1, 1, + sceGameLiveStreamingLaunchLiveViewer); +}; + +} // namespace Libraries::GameLiveStreaming \ No newline at end of file diff --git a/src/core/libraries/game_live_streaming/gamelivestreaming.h b/src/core/libraries/game_live_streaming/gamelivestreaming.h new file mode 100644 index 000000000..468750fd1 --- /dev/null +++ b/src/core/libraries/game_live_streaming/gamelivestreaming.h @@ -0,0 +1,81 @@ +// 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::GameLiveStreaming { + +struct OrbisGameLiveStreamingStatus { + bool isOnAir; + u8 align[3]; + u32 spectatorCounts; + s32 userId; + u8 reserved[60]; +}; +struct OrbisGameLiveStreamingStatus2 { + s32 userId; + bool isOnAir; + u8 align[3]; + u32 spectatorCounts; + u32 textMessageCounts; + u32 commandMessageCounts; + u32 broadcastVideoResolution; + u8 reserved[48]; +}; + +int PS4_SYSV_ABI sceGameLiveStreamingStartDebugBroadcast(); +int PS4_SYSV_ABI sceGameLiveStreamingStopDebugBroadcast(); +int PS4_SYSV_ABI sceGameLiveStreamingApplySocialFeedbackMessageFilter(); +int PS4_SYSV_ABI sceGameLiveStreamingCheckCallback(); +int PS4_SYSV_ABI sceGameLiveStreamingClearPresetSocialFeedbackCommands(); +int PS4_SYSV_ABI sceGameLiveStreamingClearSocialFeedbackMessages(); +int PS4_SYSV_ABI sceGameLiveStreamingClearSpoilerTag(); +int PS4_SYSV_ABI sceGameLiveStreamingEnableLiveStreaming(); +int PS4_SYSV_ABI sceGameLiveStreamingEnableSocialFeedback(); +int PS4_SYSV_ABI sceGameLiveStreamingGetCurrentBroadcastScreenLayout(); +int PS4_SYSV_ABI sceGameLiveStreamingGetCurrentStatus(OrbisGameLiveStreamingStatus* status); +int PS4_SYSV_ABI sceGameLiveStreamingGetCurrentStatus2(); +int PS4_SYSV_ABI sceGameLiveStreamingGetProgramInfo(); +int PS4_SYSV_ABI sceGameLiveStreamingGetSocialFeedbackMessages(); +int PS4_SYSV_ABI sceGameLiveStreamingGetSocialFeedbackMessagesCount(); +int PS4_SYSV_ABI sceGameLiveStreamingInitialize(); +int PS4_SYSV_ABI sceGameLiveStreamingLaunchLiveViewer(); +int PS4_SYSV_ABI sceGameLiveStreamingLaunchLiveViewerA(); +int PS4_SYSV_ABI sceGameLiveStreamingPermitLiveStreaming(); +int PS4_SYSV_ABI sceGameLiveStreamingPermitServerSideRecording(); +int PS4_SYSV_ABI sceGameLiveStreamingPostSocialMessage(); +int PS4_SYSV_ABI sceGameLiveStreamingRegisterCallback(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenCloseSeparateMode(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenConfigureSeparateMode(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenInitialize(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenInitializeSeparateModeParameter(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenOpenSeparateMode(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenSetMode(); +int PS4_SYSV_ABI sceGameLiveStreamingScreenTerminate(); +int PS4_SYSV_ABI sceGameLiveStreamingSetCameraFrameSetting(); +int PS4_SYSV_ABI sceGameLiveStreamingSetDefaultServiceProviderPermission(); +int PS4_SYSV_ABI sceGameLiveStreamingSetGuardAreas(); +int PS4_SYSV_ABI sceGameLiveStreamingSetInvitationSessionId(); +int PS4_SYSV_ABI sceGameLiveStreamingSetLinkCommentPreset(); +int PS4_SYSV_ABI sceGameLiveStreamingSetMaxBitrate(); +int PS4_SYSV_ABI sceGameLiveStreamingSetMetadata(); +int PS4_SYSV_ABI sceGameLiveStreamingSetPresetSocialFeedbackCommands(); +int PS4_SYSV_ABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(); +int PS4_SYSV_ABI sceGameLiveStreamingSetServiceProviderPermission(); +int PS4_SYSV_ABI sceGameLiveStreamingSetSpoilerTag(); +int PS4_SYSV_ABI sceGameLiveStreamingSetStandbyScreenResource(); +int PS4_SYSV_ABI sceGameLiveStreamingStartGenerateStandbyScreenResource(); +int PS4_SYSV_ABI sceGameLiveStreamingStartSocialFeedbackMessageFiltering(); +int PS4_SYSV_ABI sceGameLiveStreamingStopGenerateStandbyScreenResource(); +int PS4_SYSV_ABI sceGameLiveStreamingStopSocialFeedbackMessageFiltering(); +int PS4_SYSV_ABI sceGameLiveStreamingTerminate(); +int PS4_SYSV_ABI sceGameLiveStreamingUnregisterCallback(); + +void RegisterlibSceGameLiveStreaming(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::GameLiveStreaming \ No newline at end of file diff --git a/src/core/libraries/gnmdriver/gnm_error.h b/src/core/libraries/gnmdriver/gnm_error.h new file mode 100644 index 000000000..eab684a24 --- /dev/null +++ b/src/core/libraries/gnmdriver/gnm_error.h @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_GNM_ERROR_SUBMISSION_FAILED_INVALID_ARGUMENT = 0x80D11000; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_NOT_ENOUGH_RESOURCES = 0x80D11001; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_INVALID_COMMAND_BUFFER = 0x80D11080; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_INVALID_QUEUE_FULL = 0x80D11081; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_REQUEST_FAILED = 0x80D11082; +constexpr int ORBIS_GNM_ERROR_SUBMISSION_FAILED_INTERNAL_ERROR = 0x80D110FF; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING = 0x80D12000; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_RWBUFFER_ROTYPE = 0x80D12001; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_BLENDING = 0x80D12002; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_DRAW_CU_MASK = 0x80D12003; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_MRT_SETUP = 0x80D12004; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_DEPTH_RT_SETUP = 0x80D12005; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_PS_AND_MRT_FORMAT = 0x80D1200F; +constexpr int ORBIS_GNM_ERROR_VALIDATION_ERROR = 0x80D13000; +constexpr int ORBIS_GNM_ERROR_VALIDATION_VSHARP = 0x80D13001; +constexpr int ORBIS_GNM_ERROR_VALIDATION_TSHARP = 0x80D13002; +constexpr int ORBIS_GNM_ERROR_VALIDATION_RESOURCE = 0x80D13003; +constexpr int ORBIS_GNM_ERROR_VALIDATION_TABLE_MEMORY = 0x80D13004; +constexpr int ORBIS_GNM_ERROR_VALIDATION_WRITE_EVENT_OP = 0x80D13005; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INDEX_BUFFER = 0x80D13006; +constexpr int ORBIS_GNM_ERROR_VALIDATION_TESS_FACTOR_BUFFER = 0x80D13007; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SCRATCH_RING = 0x80D13008; +constexpr int ORBIS_GNM_ERROR_VALIDATION_PRIMITIVE_TYPE = 0x80D13009; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INDEX_SIZE = 0x80D1300A; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INLINE_DRAW_SIZE = 0x80D1300B; +constexpr int ORBIS_GNM_ERROR_VALIDATION_NUM_INPUT_PATCHES = 0x80D1300C; +constexpr int ORBIS_GNM_ERROR_VALIDATION_GS_MODE = 0x80D1300D; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SHADER_ADDRESS = 0x80D1300E; +constexpr int ORBIS_GNM_ERROR_VALIDATION_BORDER_COLOR_TABLE = 0x80D1300F; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SSHARP = 0x80D13010; +constexpr int ORBIS_GNM_ERROR_VALIDATION_DISPATCH_DRAW = 0x80D13011; +constexpr int ORBIS_GNM_ERROR_VALIDATION_ACTIVE_SHADER_STAGE = 0x80D13012; +constexpr int ORBIS_GNM_ERROR_VALIDATION_DCB = 0x80D13013; +constexpr int ORBIS_GNM_ERROR_VALIDATION_MISMATCH_SHADER_STAGE = 0x80D13014; +constexpr int ORBIS_GNM_ERROR_VALIDATION_MRT_SETUP = 0x80D13015; +constexpr int ORBIS_GNM_ERROR_VALIDATION_BAD_OP_CODE = 0x80D13016; +constexpr int ORBIS_GNM_ERROR_VALIDATION_DEPTH_RT_SETUP = 0x80D13017; +constexpr int ORBIS_GNM_ERROR_VALIDATION_NUM_INSTANCES = 0x80D13018; +constexpr int ORBIS_GNM_ERROR_VALIDATION_SRT = 0x80D13019; +constexpr int ORBIS_GNM_ERROR_VALIDATION_INVALID_ARGUMENT = 0x80D13FFD; +constexpr int ORBIS_GNM_ERROR_VALIDATION_FAILED_INTERNAL_ERROR = 0x80D13FFE; +constexpr int ORBIS_GNM_ERROR_VALIDATION_NOT_ENABLED = 0x80D13FFF; +constexpr int ORBIS_GNM_ERROR_CAPTURE_FILE_IO = 0x80D15000; +constexpr int ORBIS_GNM_ERROR_CAPTURE_RAZOR_NOT_LOADED = 0x80D15001; +constexpr int ORBIS_GNM_ERROR_CAPTURE_NOTHING_TO_CAPTURE = 0x80D15002; +constexpr int ORBIS_GNM_ERROR_CAPTURE_FAILED_INTERNAL = 0x80D1500F; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID = 0x80D17000; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID = 0x80D17001; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE = 0x80D17002; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR = 0x80D17003; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR = 0x80D17004; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_PRIORITY = 0x80D17005; +constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INTERNAL = 0x80D170FF; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_ARGUMENT = 0x80D19000; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_SHADER = 0x80D19001; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_STALE_HANDLE = 0x80D19002; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_FULL = 0x80D19003; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_NOT_PERMITTED = 0x80D19004; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OUTPUT_ARGUMENT_IS_NULL = 0x80D19005; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OWNER_HANDLE_INVALID = 0x80D19006; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_HANDLE_INVALID = 0x80D19007; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_TYPE_INVALID = 0x80D19008; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_GDS_RESOURCE_TYPE_INVALID = 0x80D19009; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_SIZE_INVALID = 0x80D1900A; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_ADDRESS_IS_NULL = 0x80D1900B; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_GDS_OFFSET_INVALID = 0x80D1900C; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_NAME_IS_NULL = 0x80D1900D; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OWNER_NAME_IS_NULL = 0x80D1900E; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_FIND_CALLBACK_IS_NULL = 0x80D1900F; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_IS_NOT_SHADER = 0x80D19010; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_USER_MEMORY_PARAM_IS_NULL = 0x80D19011; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_USER_MEMORY_PARAM_NOT_ALIGNED = 0x80D19012; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_NAME_LENGTH_PARAM = 0x80D19013; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_SIZE_PARAM = 0x80D19014; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_NUM_RESOURCES_PARAM = 0x80D19015; +constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INTERNAL = 0x80D19FFF; +constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_PARAMETER_NULL = 0x80D1B000; +constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_FAILED = 0x80D1B001; +constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_PARAMETER_INVALID = 0x80D1B002; +constexpr int ORBIS_GNM_ERROR_FAILURE = 0x8EEE00FF; diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index c2ee6d592..4d8aa8817 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "gnm_error.h" +#include "gnmdriver.h" + #include "common/assert.h" #include "common/config.h" #include "common/debug.h" @@ -8,8 +11,8 @@ #include "common/path_util.h" #include "common/slot_vector.h" #include "core/address_space.h" +#include "core/debug_state.h" #include "core/libraries/error_codes.h" -#include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/libs.h" #include "core/libraries/videoout/video_out.h" @@ -55,6 +58,10 @@ static constexpr auto HwInitPacketSize = 0x100u; // clang-format off static constexpr std::array InitSequence{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -94,9 +101,13 @@ static constexpr std::array InitSequence{ 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, 0xc0017900u, 0x200u, 0xe0000000u, }; -static_assert(InitSequence.size() == 0x73); +static_assert(InitSequence.size() == 0x73 + 2); static constexpr std::array InitSequence175{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -136,9 +147,13 @@ static constexpr std::array InitSequence175{ 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, 0xc0017900u, 0x200u, 0xe0000000u, }; -static_assert(InitSequence175.size() == 0x73); +static_assert(InitSequence175.size() == 0x73 + 2); static constexpr std::array InitSequence200{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -179,9 +194,13 @@ static constexpr std::array InitSequence200{ 0xc0036900u, 0x295u, 0x100u, 0x100u, 4u, 0xc0017900u, 0x200u, 0xe0000000u, }; -static_assert(InitSequence200.size() == 0x76); +static_assert(InitSequence200.size() == 0x76 + 2); static constexpr std::array InitSequence350{ + // A fake preamble to mimic context reset sent by FW + 0xc0001200u, 0u, // IT_CLEAR_STATE + + // Actual init state sequence 0xc0017600u, 0x216u, 0xffffffffu, 0xc0017600u, 0x217u, 0xffffffffu, 0xc0017600u, 0x215u, 0u, @@ -224,7 +243,7 @@ static constexpr std::array InitSequence350{ 0xc0017900u, 0x200u, 0xe0000000u, 0xc0016900u, 0x2aau, 0xffu, }; -static_assert(InitSequence350.size() == 0x7c); +static_assert(InitSequence350.size() == 0x7c + 2); static constexpr std::array CtxInitSequence{ 0xc0012800u, 0x80000000u, 0x80000000u, @@ -302,20 +321,6 @@ static void WaitGpuIdle() { cv_lock.wait(lock, [] { return submission_lock == 0; }); } -static void DumpCommandList(std::span cmd_list, const std::string& postfix) { - using namespace Common::FS; - const auto dump_dir = GetUserPath(PathType::PM4Dir); - if (!std::filesystem::exists(dump_dir)) { - std::filesystem::create_directories(dump_dir); - } - if (cmd_list.empty()) { - return; - } - const auto filename = fmt::format("{:08}_{}", frames_submitted, postfix); - const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; - file.WriteSpan(cmd_list); -} - // Write a special ending NOP packet with N DWs data block template static inline u32* WriteTrailingNop(u32* cmdbuf) { @@ -481,7 +486,7 @@ int PS4_SYSV_ABI sceGnmDestroyWorkloadStream() { } void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) { - LOG_INFO(Lib_GnmDriver, "vqid {}, offset_dw {}", gnm_vqid, next_offs_dw); + LOG_DEBUG(Lib_GnmDriver, "vqid {}, offset_dw {}", gnm_vqid, next_offs_dw); if (gnm_vqid == 0) { return; @@ -489,16 +494,18 @@ void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) { WaitGpuIdle(); - /* Suspend logic goes here */ + if (DebugState.ShouldPauseInSubmit()) { + DebugState.PauseGuestThreads(); + } auto vqid = gnm_vqid - 1; auto& asc_queue = asc_queues[{vqid}]; const auto* acb_ptr = reinterpret_cast(asc_queue.map_addr + *asc_queue.read_addr); const auto acb_size = next_offs_dw ? (next_offs_dw << 2u) - *asc_queue.read_addr : (asc_queue.ring_size_dw << 2u) - *asc_queue.read_addr; - const std::span acb_span{acb_ptr, acb_size >> 2u}; + const std::span acb_span{acb_ptr, acb_size >> 2u}; - if (Config::dumpPM4()) { + if (DebugState.DumpingCurrentFrame()) { static auto last_frame_num = -1LL; static u32 seq_num{}; if (last_frame_num == frames_submitted) { @@ -512,16 +519,24 @@ void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) { // Dumping them using the current ring pointer would result in files containing only the // `IndirectBuffer` command. To access the actual command stream, we need to unwrap the IB. auto acb = acb_span; + auto base_addr = reinterpret_cast(acb_ptr); const auto* indirect_buffer = reinterpret_cast(acb_span.data()); if (indirect_buffer->header.opcode == PM4ItOpcode::IndirectBuffer) { - acb = {indirect_buffer->Address(), indirect_buffer->ib_size}; + base_addr = reinterpret_cast(indirect_buffer->Address()); + acb = {reinterpret_cast(base_addr), indirect_buffer->ib_size}; } - // File name format is: __ - DumpCommandList(acb, fmt::format("acb_{}_{}", gnm_vqid, seq_num)); - } + using namespace DebugStateType; + DebugState.PushQueueDump({ + .type = QueueType::acb, + .submit_num = seq_num, + .num2 = gnm_vqid, + .data = {acb.begin(), acb.end()}, + .base_addr = base_addr, + }); + } liverpool->SubmitAsc(vqid, acb_span); *asc_queue.read_addr += acb_size; @@ -632,12 +647,12 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 } s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags) { LOG_TRACE(Lib_GnmDriver, "called"); if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) && - (vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) { + (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) { const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; cmdbuf = WriteHeader( @@ -647,7 +662,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, cmdbuf[0] = data_offset; cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset; - cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset; + cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[3] = 0; cmdbuf += 4; @@ -689,11 +704,11 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, } s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags) { + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags) { LOG_TRACE(Lib_GnmDriver, "called"); if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) && - (vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) { + (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) { const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable; cmdbuf = WriteHeader(cmdbuf, 4, PM4ShaderType::ShaderGraphics, @@ -703,7 +718,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 cmdbuf[0] = data_offset; cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset; - cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset; + cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset; cmdbuf[3] = 2; // auto index cmdbuf += 4; @@ -735,11 +750,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, InitSequence.data(), InitSequence.size() * 4); - cmdbuf += InitSequence.size(); + std::memcpy(cmdbuf, &InitSequence[2], (InitSequence.size() - 2) * 4); + cmdbuf += InitSequence.size() - 2; const auto cmdbuf_left = - HwInitPacketSize - InitSequence.size() - (clear_state ? 0xc : 0) - 1; + HwInitPacketSize - (InitSequence.size() - 2) - (clear_state ? 0xc : 0) - 1; cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); cmdbuf = WriteBody(cmdbuf, 0u); @@ -757,10 +772,10 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState175(u32* cmdbuf, u32 size) { } cmdbuf = ClearContextState(cmdbuf); - std::memcpy(cmdbuf, InitSequence175.data(), InitSequence175.size() * 4); - cmdbuf += InitSequence175.size(); + std::memcpy(cmdbuf, &InitSequence175[2], (InitSequence175.size() - 2) * 4); + cmdbuf += InitSequence175.size() - 2; - constexpr auto cmdbuf_left = HwInitPacketSize - InitSequence175.size() - 0xc - 1; + constexpr auto cmdbuf_left = HwInitPacketSize - (InitSequence175.size() - 2) - 0xc - 1; WriteTrailingNop(cmdbuf); return HwInitPacketSize; @@ -778,11 +793,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState200(u32* cmdbuf, u32 size) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, InitSequence200.data(), InitSequence200.size() * 4); - cmdbuf += InitSequence200.size(); + std::memcpy(cmdbuf, &InitSequence200[2], (InitSequence200.size() - 2) * 4); + cmdbuf += InitSequence200.size() - 2; const auto cmdbuf_left = - HwInitPacketSize - InitSequence200.size() - (clear_state ? 0xc : 0) - 1; + HwInitPacketSize - (InitSequence200.size() - 2) - (clear_state ? 0xc : 0) - 1; cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); cmdbuf = WriteBody(cmdbuf, 0u); @@ -804,11 +819,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState350(u32* cmdbuf, u32 size) { cmdbuf = ClearContextState(cmdbuf); } - std::memcpy(cmdbuf, InitSequence350.data(), InitSequence350.size() * 4); - cmdbuf += InitSequence350.size(); + std::memcpy(cmdbuf, &InitSequence350[2], (InitSequence350.size() - 2) * 4); + cmdbuf += InitSequence350.size() - 2; const auto cmdbuf_left = - HwInitPacketSize - InitSequence350.size() - (clear_state ? 0xc : 0) - 1; + HwInitPacketSize - (InitSequence350.size() - 2) - (clear_state ? 0xc : 0) - 1; cmdbuf = WriteHeader(cmdbuf, cmdbuf_left); cmdbuf = WriteBody(cmdbuf, 0u); @@ -1063,9 +1078,27 @@ s32 PS4_SYSV_ABI sceGnmInsertPopMarker(u32* cmdbuf, u32 size) { return -1; } -int PS4_SYSV_ABI sceGnmInsertPushColorMarker() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceGnmInsertPushColorMarker(u32* cmdbuf, u32 size, const char* marker, u32 color) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (cmdbuf && marker) { + const auto len = std::strlen(marker); + const u32 packet_size = ((len + 0xc) >> 2) + ((len + 0x10) >> 3) * 2; + if (packet_size + 2 == size) { + auto* nop = reinterpret_cast(cmdbuf); + nop->header = + PM4Type3Header{PM4ItOpcode::Nop, packet_size, PM4ShaderType::ShaderGraphics}; + nop->data_block[0] = PM4CmdNop::PayloadType::DebugColorMarkerPush; + const auto marker_len = len + 1; + std::memcpy(&nop->data_block[1], marker, marker_len); + *reinterpret_cast(reinterpret_cast(&nop->data_block[1]) + marker_len + 8) = + color; + std::memset(reinterpret_cast(&nop->data_block[1]) + marker_len + 8 + sizeof(u32), + 0, packet_size * 4 - marker_len - 8 - sizeof(u32)); + return ORBIS_OK; + } + } + return -1; } s32 PS4_SYSV_ABI sceGnmInsertPushMarker(u32* cmdbuf, u32 size, const char* marker) { @@ -1094,9 +1127,25 @@ int PS4_SYSV_ABI sceGnmInsertSetColorMarker() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmInsertSetMarker() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceGnmInsertSetMarker(u32* cmdbuf, u32 size, const char* marker) { + LOG_TRACE(Lib_GnmDriver, "called"); + + if (cmdbuf && marker) { + const auto len = std::strlen(marker); + const u32 packet_size = ((len + 8) >> 2) + ((len + 0xc) >> 3) * 2; + if (packet_size + 2 == size) { + auto* nop = reinterpret_cast(cmdbuf); + nop->header = + PM4Type3Header{PM4ItOpcode::Nop, packet_size, PM4ShaderType::ShaderGraphics}; + nop->data_block[0] = PM4CmdNop::PayloadType::DebugSetMarker; + const auto marker_len = len + 1; + std::memcpy(&nop->data_block[1], marker, marker_len); + std::memset(reinterpret_cast(&nop->data_block[1]) + marker_len, 0, + packet_size * 4 - marker_len); + return ORBIS_OK; + } + } + return -1; } int PS4_SYSV_ABI sceGnmInsertThreadTraceMarker() { @@ -1254,8 +1303,12 @@ int PS4_SYSV_ABI sceGnmRequestMipStatsReportAndReset() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmResetVgtControl() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceGnmResetVgtControl(u32* cmdbuf, u32 size) { + LOG_TRACE(Lib_GnmDriver, "called"); + if (cmdbuf == nullptr || size != 3) { + return -1; + } + PM4CmdSetData::SetContextReg(cmdbuf, 0x2aau, 0xffu); // IA_MULTI_VGT_PARAM return ORBIS_OK; } @@ -1743,7 +1796,7 @@ s32 PS4_SYSV_ABI sceGnmSetVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u3 return -1; } - const u32 var = shader_modifier == 0 ? vs_regs[2] : (vs_regs[2] & 0xfcfffc3f | shader_modifier); + const u32 var = shader_modifier == 0 ? vs_regs[2] : (vs_regs[2] & 0xfcfffc3f) | shader_modifier; cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], 0u); // SPI_SHADER_PGM_LO_VS cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x4au, var, vs_regs[3]); // SPI_SHADER_PGM_RSRC1_VS cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x207u, vs_regs[6]); // PA_CL_VS_OUT_CNTL @@ -2036,7 +2089,7 @@ s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers(u32 count, u32* dcb_gpu_addrs u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[], u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, u32 flip_arg) { - LOG_INFO(Lib_GnmDriver, "called [buf = {}]", buf_idx); + LOG_DEBUG(Lib_GnmDriver, "called [buf = {}]", buf_idx); auto* cmdbuf = dcb_gpu_addrs[count - 1]; const auto size_dw = dcb_sizes_in_bytes[count - 1] / 4; @@ -2060,7 +2113,7 @@ int PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffersForWorkload() { s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes, const u32* ccb_gpu_addrs[], u32* ccb_sizes_in_bytes) { - LOG_INFO(Lib_GnmDriver, "called"); + LOG_DEBUG(Lib_GnmDriver, "called"); if (!dcb_gpu_addrs || !dcb_sizes_in_bytes) { LOG_ERROR(Lib_GnmDriver, "dcbGpuAddrs and dcbSizesInBytes must not be NULL"); @@ -2086,7 +2139,9 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[ WaitGpuIdle(); - /* Suspend logic goes here */ + if (DebugState.ShouldPauseInSubmit()) { + DebugState.PauseGuestThreads(); + } if (send_init_packet) { if (sdk_version <= 0x1ffffffu) { @@ -2106,10 +2161,10 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[ const auto dcb_size_dw = dcb_sizes_in_bytes[cbpair] >> 2; const auto ccb_size_dw = ccb_size_in_bytes >> 2; - const auto& dcb_span = std::span{dcb_gpu_addrs[cbpair], dcb_size_dw}; - const auto& ccb_span = std::span{ccb, ccb_size_dw}; + const auto& dcb_span = std::span{dcb_gpu_addrs[cbpair], dcb_size_dw}; + const auto& ccb_span = std::span{ccb, ccb_size_dw}; - if (Config::dumpPM4()) { + if (DebugState.DumpingCurrentFrame()) { static auto last_frame_num = -1LL; static u32 seq_num{}; if (last_frame_num == frames_submitted && cbpair == 0) { @@ -2119,11 +2174,23 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[ seq_num = 0u; } - // File name format is: __ - DumpCommandList(dcb_span, fmt::format("dcb_{}_{}", seq_num, cbpair)); - DumpCommandList(ccb_span, fmt::format("ccb_{}_{}", seq_num, cbpair)); - } + using DebugStateType::QueueType; + DebugState.PushQueueDump({ + .type = QueueType::dcb, + .submit_num = seq_num, + .num2 = cbpair, + .data = {dcb_span.begin(), dcb_span.end()}, + .base_addr = reinterpret_cast(dcb_gpu_addrs[cbpair]), + }); + DebugState.PushQueueDump({ + .type = QueueType::ccb, + .submit_num = seq_num, + .num2 = cbpair, + .data = {ccb_span.begin(), ccb_span.end()}, + .base_addr = reinterpret_cast(ccb), + }); + } liverpool->SubmitGfx(dcb_span, ccb_span); } @@ -2136,13 +2203,15 @@ int PS4_SYSV_ABI sceGnmSubmitCommandBuffersForWorkload() { } int PS4_SYSV_ABI sceGnmSubmitDone() { - LOG_INFO(Lib_GnmDriver, "called"); + LOG_DEBUG(Lib_GnmDriver, "called"); + WaitGpuIdle(); if (!liverpool->IsGpuIdle()) { submission_lock = true; } liverpool->SubmitDone(); send_init_packet = true; ++frames_submitted; + DebugState.IncGnmFrameNum(); return ORBIS_OK; } @@ -2328,9 +2397,9 @@ s32 PS4_SYSV_ABI sceGnmUpdateVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmValidateCommandBuffers() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceGnmValidateCommandBuffers() { + LOG_TRACE(Lib_GnmDriver, "called"); + return ORBIS_GNM_ERROR_VALIDATION_NOT_ENABLED; // not available in retail FW; } int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics() { @@ -2648,6 +2717,10 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sdk_version = 0; } + if (Config::copyGPUCmdBuffers()) { + liverpool->reserveCopyBufferSpace(); + } + Platform::IrqC::Instance()->Register(Platform::InterruptId::GpuIdle, ResetSubmissionLock, nullptr); diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 84872297e..a95daa90d 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -45,7 +45,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr u32 flags, u32 type); s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags); s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags); int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti(); @@ -53,7 +53,7 @@ int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced(); s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count, u32 flags); s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage, - u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags); + u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags); int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndirectMulti(); u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size); @@ -105,10 +105,10 @@ int PS4_SYSV_ABI sceGnmGpuPaDebugEnter(); int PS4_SYSV_ABI sceGnmGpuPaDebugLeave(); int PS4_SYSV_ABI sceGnmInsertDingDongMarker(); s32 PS4_SYSV_ABI sceGnmInsertPopMarker(u32* cmdbuf, u32 size); -int PS4_SYSV_ABI sceGnmInsertPushColorMarker(); +s32 PS4_SYSV_ABI sceGnmInsertPushColorMarker(u32* cmdbuf, u32 size, const char* marker, u32 color); s32 PS4_SYSV_ABI sceGnmInsertPushMarker(u32* cmdbuf, u32 size, const char* marker); int PS4_SYSV_ABI sceGnmInsertSetColorMarker(); -int PS4_SYSV_ABI sceGnmInsertSetMarker(); +s32 PS4_SYSV_ABI sceGnmInsertSetMarker(u32* cmdbuf, u32 size, const char* marker); int PS4_SYSV_ABI sceGnmInsertThreadTraceMarker(); s32 PS4_SYSV_ABI sceGnmInsertWaitFlipDone(u32* cmdbuf, u32 size, s32 vo_handle, u32 buf_idx); int PS4_SYSV_ABI sceGnmIsCoredumpValid(); @@ -134,7 +134,7 @@ s32 PS4_SYSV_ABI sceGnmRegisterResource(void* res_handle, void* owner_handle, co int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDone(); int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDoneForWorkload(); int PS4_SYSV_ABI sceGnmRequestMipStatsReportAndReset(); -int PS4_SYSV_ABI sceGnmResetVgtControl(); +s32 PS4_SYSV_ABI sceGnmResetVgtControl(u32* cmdbuf, u32 size); int PS4_SYSV_ABI sceGnmSdmaClose(); int PS4_SYSV_ABI sceGnmSdmaConstFill(); int PS4_SYSV_ABI sceGnmSdmaCopyLinear(); @@ -223,7 +223,7 @@ s32 PS4_SYSV_ABI sceGnmUpdatePsShader(u32* cmdbuf, u32 size, const u32* ps_regs) s32 PS4_SYSV_ABI sceGnmUpdatePsShader350(u32* cmdbuf, u32 size, const u32* ps_regs); s32 PS4_SYSV_ABI sceGnmUpdateVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u32 shader_modifier); -int PS4_SYSV_ABI sceGnmValidateCommandBuffers(); +s32 PS4_SYSV_ABI sceGnmValidateCommandBuffers(); int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics(); int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics2(); int PS4_SYSV_ABI sceGnmValidateDispatchCommandBuffers(); diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp new file mode 100644 index 000000000..13a70acf7 --- /dev/null +++ b/src/core/libraries/ime/ime.cpp @@ -0,0 +1,340 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ime.h" + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" + +namespace Libraries::Ime { + +int PS4_SYSV_ABI FinalizeImeModule() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI InitializeImeModule() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeCheckFilterText() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeCheckRemoteEventParam() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeCheckUpdateTextInfo() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeClose() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeConfigGet() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeConfigSet() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeConfirmCandidate() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDicAddWord() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDicDeleteLearnDics() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDicDeleteUserDics() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDicDeleteWord() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDicGetWords() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDicReplaceWord() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeDisableController() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeFilterText() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeForTestFunction() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeGetPanelPositionAndForm() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeGetPanelSize() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardClose() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardGetInfo() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardGetResourceId() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardOpen() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardOpenInternal() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardSetMode() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeKeyboardUpdate() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeOpen() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeOpenInternal() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeParamInit() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeSetCandidateIndex() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeSetCaret() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeSetText() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeSetTextGeometry() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeUpdate() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshClearPreedit() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshClose() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshConfirmPreedit() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshDisableController() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshGetPanelPositionAndForm() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshInformConfirmdString() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshInformConfirmdString2() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshOpen() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSendTextInfo() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetCaretGeometry() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetCaretIndexInPreedit() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetPanelPosition() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetParam() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetPreeditGeometry() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetSelectGeometry() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshSetSelectionText() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshUpdate() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshUpdateContext() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceImeVshUpdateContext2() { + LOG_ERROR(Lib_Ime, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceIme(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("mN+ZoSN-8hQ", "libSceIme", 1, "libSceIme", 1, 1, FinalizeImeModule); + LIB_FUNCTION("uTW+63goeJs", "libSceIme", 1, "libSceIme", 1, 1, InitializeImeModule); + LIB_FUNCTION("Lf3DeGWC6xg", "libSceIme", 1, "libSceIme", 1, 1, sceImeCheckFilterText); + LIB_FUNCTION("zHuMUGb-AQI", "libSceIme", 1, "libSceIme", 1, 1, sceImeCheckRemoteEventParam); + LIB_FUNCTION("OTb0Mg+1i1k", "libSceIme", 1, "libSceIme", 1, 1, sceImeCheckUpdateTextInfo); + LIB_FUNCTION("TmVP8LzcFcY", "libSceIme", 1, "libSceIme", 1, 1, sceImeClose); + LIB_FUNCTION("Ho5NVQzpKHo", "libSceIme", 1, "libSceIme", 1, 1, sceImeConfigGet); + LIB_FUNCTION("P5dPeiLwm-M", "libSceIme", 1, "libSceIme", 1, 1, sceImeConfigSet); + LIB_FUNCTION("tKLmVIUkpyM", "libSceIme", 1, "libSceIme", 1, 1, sceImeConfirmCandidate); + LIB_FUNCTION("NYDsL9a0oEo", "libSceIme", 1, "libSceIme", 1, 1, sceImeDicAddWord); + LIB_FUNCTION("l01GKoyiQrY", "libSceIme", 1, "libSceIme", 1, 1, sceImeDicDeleteLearnDics); + LIB_FUNCTION("E2OcGgi-FPY", "libSceIme", 1, "libSceIme", 1, 1, sceImeDicDeleteUserDics); + LIB_FUNCTION("JAiMBkOTYKI", "libSceIme", 1, "libSceIme", 1, 1, sceImeDicDeleteWord); + LIB_FUNCTION("JoPdCUXOzMU", "libSceIme", 1, "libSceIme", 1, 1, sceImeDicGetWords); + LIB_FUNCTION("FuEl46uHDyo", "libSceIme", 1, "libSceIme", 1, 1, sceImeDicReplaceWord); + LIB_FUNCTION("E+f1n8e8DAw", "libSceIme", 1, "libSceIme", 1, 1, sceImeDisableController); + LIB_FUNCTION("evjOsE18yuI", "libSceIme", 1, "libSceIme", 1, 1, sceImeFilterText); + LIB_FUNCTION("wVkehxutK-U", "libSceIme", 1, "libSceIme", 1, 1, sceImeForTestFunction); + LIB_FUNCTION("T6FYjZXG93o", "libSceIme", 1, "libSceIme", 1, 1, sceImeGetPanelPositionAndForm); + LIB_FUNCTION("ziPDcIjO0Vk", "libSceIme", 1, "libSceIme", 1, 1, sceImeGetPanelSize); + LIB_FUNCTION("PMVehSlfZ94", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardClose); + LIB_FUNCTION("VkqLPArfFdc", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardGetInfo); + LIB_FUNCTION("dKadqZFgKKQ", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardGetResourceId); + LIB_FUNCTION("eaFXjfJv3xs", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardOpen); + LIB_FUNCTION("oYkJlMK51SA", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardOpenInternal); + LIB_FUNCTION("ua+13Hk9kKs", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardSetMode); + LIB_FUNCTION("3Hx2Uw9xnv8", "libSceIme", 1, "libSceIme", 1, 1, sceImeKeyboardUpdate); + LIB_FUNCTION("RPydv-Jr1bc", "libSceIme", 1, "libSceIme", 1, 1, sceImeOpen); + LIB_FUNCTION("16UI54cWRQk", "libSceIme", 1, "libSceIme", 1, 1, sceImeOpenInternal); + LIB_FUNCTION("WmYDzdC4EHI", "libSceIme", 1, "libSceIme", 1, 1, sceImeParamInit); + LIB_FUNCTION("TQaogSaqkEk", "libSceIme", 1, "libSceIme", 1, 1, sceImeSetCandidateIndex); + LIB_FUNCTION("WLxUN2WMim8", "libSceIme", 1, "libSceIme", 1, 1, sceImeSetCaret); + LIB_FUNCTION("ieCNrVrzKd4", "libSceIme", 1, "libSceIme", 1, 1, sceImeSetText); + LIB_FUNCTION("TXYHFRuL8UY", "libSceIme", 1, "libSceIme", 1, 1, sceImeSetTextGeometry); + LIB_FUNCTION("-4GCfYdNF1s", "libSceIme", 1, "libSceIme", 1, 1, sceImeUpdate); + LIB_FUNCTION("oOwl47ouxoM", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshClearPreedit); + LIB_FUNCTION("gtoTsGM9vEY", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshClose); + LIB_FUNCTION("wTKF4mUlSew", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshConfirmPreedit); + LIB_FUNCTION("rM-1hkuOhh0", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshDisableController); + LIB_FUNCTION("42xMaQ+GLeQ", "libSceIme", 1, "libSceIme", 1, 1, + sceImeVshGetPanelPositionAndForm); + LIB_FUNCTION("ZmmV6iukhyo", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshInformConfirmdString); + LIB_FUNCTION("EQBusz6Uhp8", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshInformConfirmdString2); + LIB_FUNCTION("LBicRa-hj3A", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshOpen); + LIB_FUNCTION("-IAOwd2nO7g", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSendTextInfo); + LIB_FUNCTION("qDagOjvJdNk", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetCaretGeometry); + LIB_FUNCTION("tNOlmxee-Nk", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetCaretIndexInPreedit); + LIB_FUNCTION("rASXozKkQ9g", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetPanelPosition); + LIB_FUNCTION("idvMaIu5H+k", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetParam); + LIB_FUNCTION("ga5GOgThbjo", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetPreeditGeometry); + LIB_FUNCTION("RuSca8rS6yA", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetSelectGeometry); + LIB_FUNCTION("J7COZrgSFRA", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshSetSelectionText); + LIB_FUNCTION("WqAayyok5p0", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshUpdate); + LIB_FUNCTION("O7Fdd+Oc-qQ", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshUpdateContext); + LIB_FUNCTION("fwcPR7+7Rks", "libSceIme", 1, "libSceIme", 1, 1, sceImeVshUpdateContext2); +}; + +} // namespace Libraries::Ime \ No newline at end of file diff --git a/src/core/libraries/ime/ime.h b/src/core/libraries/ime/ime.h new file mode 100644 index 000000000..807616f14 --- /dev/null +++ b/src/core/libraries/ime/ime.h @@ -0,0 +1,70 @@ +// 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::Ime { + +int PS4_SYSV_ABI FinalizeImeModule(); +int PS4_SYSV_ABI InitializeImeModule(); +int PS4_SYSV_ABI sceImeCheckFilterText(); +int PS4_SYSV_ABI sceImeCheckRemoteEventParam(); +int PS4_SYSV_ABI sceImeCheckUpdateTextInfo(); +int PS4_SYSV_ABI sceImeClose(); +int PS4_SYSV_ABI sceImeConfigGet(); +int PS4_SYSV_ABI sceImeConfigSet(); +int PS4_SYSV_ABI sceImeConfirmCandidate(); +int PS4_SYSV_ABI sceImeDicAddWord(); +int PS4_SYSV_ABI sceImeDicDeleteLearnDics(); +int PS4_SYSV_ABI sceImeDicDeleteUserDics(); +int PS4_SYSV_ABI sceImeDicDeleteWord(); +int PS4_SYSV_ABI sceImeDicGetWords(); +int PS4_SYSV_ABI sceImeDicReplaceWord(); +int PS4_SYSV_ABI sceImeDisableController(); +int PS4_SYSV_ABI sceImeFilterText(); +int PS4_SYSV_ABI sceImeForTestFunction(); +int PS4_SYSV_ABI sceImeGetPanelPositionAndForm(); +int PS4_SYSV_ABI sceImeGetPanelSize(); +int PS4_SYSV_ABI sceImeKeyboardClose(); +int PS4_SYSV_ABI sceImeKeyboardGetInfo(); +int PS4_SYSV_ABI sceImeKeyboardGetResourceId(); +int PS4_SYSV_ABI sceImeKeyboardOpen(); +int PS4_SYSV_ABI sceImeKeyboardOpenInternal(); +int PS4_SYSV_ABI sceImeKeyboardSetMode(); +int PS4_SYSV_ABI sceImeKeyboardUpdate(); +int PS4_SYSV_ABI sceImeOpen(); +int PS4_SYSV_ABI sceImeOpenInternal(); +int PS4_SYSV_ABI sceImeParamInit(); +int PS4_SYSV_ABI sceImeSetCandidateIndex(); +int PS4_SYSV_ABI sceImeSetCaret(); +int PS4_SYSV_ABI sceImeSetText(); +int PS4_SYSV_ABI sceImeSetTextGeometry(); +int PS4_SYSV_ABI sceImeUpdate(); +int PS4_SYSV_ABI sceImeVshClearPreedit(); +int PS4_SYSV_ABI sceImeVshClose(); +int PS4_SYSV_ABI sceImeVshConfirmPreedit(); +int PS4_SYSV_ABI sceImeVshDisableController(); +int PS4_SYSV_ABI sceImeVshGetPanelPositionAndForm(); +int PS4_SYSV_ABI sceImeVshInformConfirmdString(); +int PS4_SYSV_ABI sceImeVshInformConfirmdString2(); +int PS4_SYSV_ABI sceImeVshOpen(); +int PS4_SYSV_ABI sceImeVshSendTextInfo(); +int PS4_SYSV_ABI sceImeVshSetCaretGeometry(); +int PS4_SYSV_ABI sceImeVshSetCaretIndexInPreedit(); +int PS4_SYSV_ABI sceImeVshSetPanelPosition(); +int PS4_SYSV_ABI sceImeVshSetParam(); +int PS4_SYSV_ABI sceImeVshSetPreeditGeometry(); +int PS4_SYSV_ABI sceImeVshSetSelectGeometry(); +int PS4_SYSV_ABI sceImeVshSetSelectionText(); +int PS4_SYSV_ABI sceImeVshUpdate(); +int PS4_SYSV_ABI sceImeVshUpdateContext(); +int PS4_SYSV_ABI sceImeVshUpdateContext2(); + +void RegisterlibSceIme(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Ime \ No newline at end of file diff --git a/src/core/libraries/kernel/cpu_management.cpp b/src/core/libraries/kernel/cpu_management.cpp index 93dc60bd0..3bf609dfe 100644 --- a/src/core/libraries/kernel/cpu_management.cpp +++ b/src/core/libraries/kernel/cpu_management.cpp @@ -8,7 +8,7 @@ namespace Libraries::Kernel { int PS4_SYSV_ABI sceKernelIsNeoMode() { - LOG_INFO(Kernel_Sce, "called"); + LOG_DEBUG(Kernel_Sce, "called"); return Config::isNeoMode(); } diff --git a/src/core/libraries/kernel/event_flag/event_flag.cpp b/src/core/libraries/kernel/event_flag/event_flag.cpp index 8afd139c0..f83ae0a7f 100644 --- a/src/core/libraries/kernel/event_flag/event_flag.cpp +++ b/src/core/libraries/kernel/event_flag/event_flag.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include +#include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" @@ -78,7 +78,7 @@ int PS4_SYSV_ABI sceKernelCloseEventFlag() { return ORBIS_OK; } int PS4_SYSV_ABI sceKernelClearEventFlag(OrbisKernelEventFlag ef, u64 bitPattern) { - LOG_INFO(Kernel_Event, "called"); + LOG_DEBUG(Kernel_Event, "called"); ef->Clear(bitPattern); return ORBIS_OK; } @@ -97,7 +97,7 @@ int PS4_SYSV_ABI sceKernelSetEventFlag(OrbisKernelEventFlag ef, u64 bitPattern) } int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode, u64* pResultPat) { - LOG_INFO(Kernel_Event, "called bitPattern = {:#x} waitMode = {:#x}", bitPattern, waitMode); + LOG_DEBUG(Kernel_Event, "called bitPattern = {:#x} waitMode = {:#x}", bitPattern, waitMode); if (ef == nullptr) { return ORBIS_KERNEL_ERROR_ESRCH; @@ -137,7 +137,7 @@ int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, auto result = ef->Poll(bitPattern, wait, clear, pResultPat); - if (result != ORBIS_OK) { + if (result != ORBIS_OK && result != ORBIS_KERNEL_ERROR_EBUSY) { LOG_ERROR(Kernel_Event, "returned {}", result); } @@ -145,7 +145,7 @@ int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, } int PS4_SYSV_ABI sceKernelWaitEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode, u64* pResultPat, OrbisKernelUseconds* pTimeout) { - LOG_INFO(Kernel_Event, "called bitPattern = {:#x} waitMode = {:#x}", bitPattern, waitMode); + LOG_DEBUG(Kernel_Event, "called bitPattern = {:#x} waitMode = {:#x}", bitPattern, waitMode); if (ef == nullptr) { return ORBIS_KERNEL_ERROR_ESRCH; } @@ -184,7 +184,7 @@ int PS4_SYSV_ABI sceKernelWaitEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 result = ef->Wait(bitPattern, wait, clear, pResultPat, pTimeout); - if (result != ORBIS_OK) { + if (result != ORBIS_OK && result != ORBIS_KERNEL_ERROR_ETIMEDOUT) { LOG_ERROR(Kernel_Event, "returned {:#x}", result); } diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp index ed01d7cc0..6d6dcf7a9 100644 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp +++ b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "core/libraries/error_codes.h" #include "event_flag_obj.h" diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h index fe50be697..8d1624e2b 100644 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.h +++ b/src/core/libraries/kernel/event_flag/event_flag_obj.h @@ -2,8 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include #include + #include "common/types.h" namespace Libraries::Kernel { diff --git a/src/core/libraries/kernel/event_queue.cpp b/src/core/libraries/kernel/event_queue.cpp index 3555fddc9..88918bf54 100644 --- a/src/core/libraries/kernel/event_queue.cpp +++ b/src/core/libraries/kernel/event_queue.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/assert.h" #include "core/libraries/kernel/event_queue.h" diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 990b11d69..7f86ee540 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -89,6 +89,8 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { } // RW, then scekernelWrite is called and savedata is written just fine now. e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite); + } else if (write) { + e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write); } else { UNREACHABLE(); } @@ -150,7 +152,6 @@ int PS4_SYSV_ABI posix_close(int d) { return -1; } return result; - return ORBIS_OK; } size_t PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes) { @@ -180,11 +181,16 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) { auto* h = Common::Singleton::Instance(); auto* mnt = Common::Singleton::Instance(); - const auto host_path = mnt->GetHostPath(path); + bool ro = false; + const auto host_path = mnt->GetHostPath(path, &ro); if (host_path.empty()) { return SCE_KERNEL_ERROR_EACCES; } + if (ro) { + return SCE_KERNEL_ERROR_EROFS; + } + if (std::filesystem::is_directory(host_path)) { return SCE_KERNEL_ERROR_EPERM; } @@ -223,7 +229,10 @@ s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) { } std::scoped_lock lk{file->m_mutex}; - file->f.Seek(offset, origin); + if (!file->f.Seek(offset, origin)) { + LOG_CRITICAL(Kernel_Fs, "sceKernelLseek: failed to seek"); + return SCE_KERNEL_ERROR_EINVAL; + } return file->f.Tell(); } @@ -271,13 +280,21 @@ int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) { return SCE_KERNEL_ERROR_EINVAL; } auto* mnt = Common::Singleton::Instance(); - const auto dir_name = mnt->GetHostPath(path); + + bool ro = false; + const auto dir_name = mnt->GetHostPath(path, &ro); + if (std::filesystem::exists(dir_name)) { return SCE_KERNEL_ERROR_EEXIST; } + if (ro) { + return SCE_KERNEL_ERROR_EROFS; + } + // CUSA02456: path = /aotl after sceSaveDataMount(mode = 1) - if (dir_name.empty() || !std::filesystem::create_directory(dir_name)) { + std::error_code ec; + if (dir_name.empty() || !std::filesystem::create_directory(dir_name, ec)) { return SCE_KERNEL_ERROR_EIO; } @@ -297,10 +314,63 @@ int PS4_SYSV_ABI posix_mkdir(const char* path, u16 mode) { return result; } +int PS4_SYSV_ABI sceKernelRmdir(const char* path) { + auto* mnt = Common::Singleton::Instance(); + bool ro = false; + + const std::filesystem::path dir_name = mnt->GetHostPath(path, &ro); + + if (dir_name.empty()) { + LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, permission denied", + fmt::UTF(dir_name.u8string())); + return SCE_KERNEL_ERROR_EACCES; + } + + if (ro) { + LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, directory is read only", + fmt::UTF(dir_name.u8string())); + return SCE_KERNEL_ERROR_EROFS; + } + + if (!std::filesystem::is_directory(dir_name)) { + LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, path is not a directory", + fmt::UTF(dir_name.u8string())); + return ORBIS_KERNEL_ERROR_ENOTDIR; + } + + if (!std::filesystem::exists(dir_name)) { + LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, no such file or directory", + fmt::UTF(dir_name.u8string())); + return ORBIS_KERNEL_ERROR_ENOENT; + } + + std::error_code ec; + int result = std::filesystem::remove_all(dir_name, ec); + + if (!ec) { + LOG_INFO(Kernel_Fs, "Removed directory: {}", fmt::UTF(dir_name.u8string())); + return ORBIS_OK; + } + LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, error_code={}", + fmt::UTF(dir_name.u8string()), ec.message()); + return ErrnoToSceKernelError(ec.value()); +} + +int PS4_SYSV_ABI posix_rmdir(const char* path) { + int result = sceKernelRmdir(path); + if (result < 0) { + LOG_ERROR(Kernel_Pthread, "posix_rmdir: error = {}", result); + ErrSceToPosix(result); + return -1; + } + return result; +} + int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) { LOG_INFO(Kernel_Fs, "(PARTIAL) path = {}", path); auto* mnt = Common::Singleton::Instance(); - const auto path_name = mnt->GetHostPath(path); + bool ro = false; + const auto path_name = mnt->GetHostPath(path, &ro); std::memset(sb, 0, sizeof(OrbisKernelStat)); const bool is_dir = std::filesystem::is_directory(path_name); const bool is_file = std::filesystem::is_regular_file(path_name); @@ -320,6 +390,10 @@ int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) { sb->st_blocks = (sb->st_size + 511) / 512; // TODO incomplete } + if (ro) { + sb->st_mode &= ~0000555u; + } + return ORBIS_OK; } @@ -361,14 +435,26 @@ s64 PS4_SYSV_ABI sceKernelPread(int d, void* buf, size_t nbytes, s64 offset) { SCOPE_EXIT { file->f.Seek(pos); }; - file->f.Seek(offset); + if (!file->f.Seek(offset)) { + LOG_CRITICAL(Kernel_Fs, "sceKernelPread: failed to seek"); + return ORBIS_KERNEL_ERROR_EINVAL; + } return file->f.ReadRaw(buf, nbytes); } int PS4_SYSV_ABI sceKernelFStat(int fd, OrbisKernelStat* sb) { LOG_INFO(Kernel_Fs, "(PARTIAL) fd = {}", fd); + if (fd < 3) { + return ORBIS_KERNEL_ERROR_EPERM; + } + if (sb == nullptr) { + return ORBIS_KERNEL_ERROR_EFAULT; + } auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(fd); + if (file == nullptr) { + return ORBIS_KERNEL_ERROR_EBADF; + } std::memset(sb, 0, sizeof(OrbisKernelStat)); if (file->is_directory) { @@ -421,15 +507,24 @@ int PS4_SYSV_ABI sceKernelFtruncate(int fd, s64 length) { } static int GetDents(int fd, char* buf, int nbytes, s64* basep) { - // TODO error codes - ASSERT(buf != nullptr); + if (fd < 3) { + return ORBIS_KERNEL_ERROR_EBADF; + } + + if (buf == nullptr) { + return ORBIS_KERNEL_ERROR_EFAULT; + } auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(fd); - + if (file == nullptr) { + return ORBIS_KERNEL_ERROR_EBADF; + } if (file->dirents_index == file->dirents.size()) { return ORBIS_OK; } - + if (!file->is_directory || nbytes < 512 || file->dirents_index > file->dirents.size()) { + return ORBIS_KERNEL_ERROR_EINVAL; + } const auto& entry = file->dirents.at(file->dirents_index++); auto str = entry.name; auto str_size = str.size() - 1; @@ -477,17 +572,27 @@ s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset) { SCOPE_EXIT { file->f.Seek(pos); }; - file->f.Seek(offset); + if (!file->f.Seek(offset)) { + LOG_CRITICAL(Kernel_Fs, "sceKernelPwrite: failed to seek"); + return ORBIS_KERNEL_ERROR_EINVAL; + } return file->f.WriteRaw(buf, nbytes); } s32 PS4_SYSV_ABI sceKernelRename(const char* from, const char* to) { auto* mnt = Common::Singleton::Instance(); - const auto src_path = mnt->GetHostPath(from); + bool ro = false; + const auto src_path = mnt->GetHostPath(from, &ro); if (!std::filesystem::exists(src_path)) { return ORBIS_KERNEL_ERROR_ENOENT; } - const auto dst_path = mnt->GetHostPath(to); + if (ro) { + return SCE_KERNEL_ERROR_EROFS; + } + const auto dst_path = mnt->GetHostPath(to, &ro); + if (ro) { + return SCE_KERNEL_ERROR_EROFS; + } const bool src_is_dir = std::filesystem::is_directory(src_path); const bool dst_is_dir = std::filesystem::is_directory(dst_path); if (src_is_dir && !dst_is_dir) { @@ -521,13 +626,19 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("AqBioC2vF3I", "libScePosix", 1, "libkernel", 1, 1, posix_read); LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir); LIB_FUNCTION("JGMio+21L4c", "libScePosix", 1, "libkernel", 1, 1, posix_mkdir); + LIB_FUNCTION("JGMio+21L4c", "libkernel", 1, "libkernel", 1, 1, posix_mkdir); + LIB_FUNCTION("naInUjYt3so", "libkernel", 1, "libkernel", 1, 1, sceKernelRmdir); + LIB_FUNCTION("c7ZnT7V1B98", "libScePosix", 1, "libkernel", 1, 1, posix_rmdir); + LIB_FUNCTION("c7ZnT7V1B98", "libkernel", 1, "libkernel", 1, 1, posix_rmdir); LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat); LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFStat); LIB_FUNCTION("mqQMh1zPPT8", "libScePosix", 1, "libkernel", 1, 1, posix_fstat); + LIB_FUNCTION("mqQMh1zPPT8", "libkernel", 1, "libkernel", 1, 1, posix_fstat); LIB_FUNCTION("VW3TVZiM4-E", "libkernel", 1, "libkernel", 1, 1, sceKernelFtruncate); LIB_FUNCTION("52NcYU9+lEo", "libkernel", 1, "libkernel", 1, 1, sceKernelRename); LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat); + LIB_FUNCTION("E6ao34wPw+U", "libkernel", 1, "libkernel", 1, 1, posix_stat); LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread); LIB_FUNCTION("uWyW3v98sU4", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckReachability); LIB_FUNCTION("fTx66l5iWIA", "libkernel", 1, "libkernel", 1, 1, sceKernelFsync); @@ -538,7 +649,7 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { // openOrbis (to check if it is valid out of OpenOrbis LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1, - posix_open); // _open shoudld be equal to open function + posix_open); // _open should be equal to open function } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index 2634e25c8..b013f29bf 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -8,6 +8,7 @@ #include "common/assert.h" #include "common/debug.h" +#include "common/elf_info.h" #include "common/logging/log.h" #include "common/polyfill_thread.h" #include "common/singleton.h" @@ -55,7 +56,7 @@ void KernelSignalRequest() { } static void KernelServiceThread(std::stop_token stoken) { - Common::SetCurrentThreadName("Kernel_ServiceThread"); + Common::SetCurrentThreadName("shadPS4:Kernel_ServiceThread"); while (!stoken.stop_requested()) { HLE_TRACE; @@ -156,6 +157,7 @@ void SetPosixErrno(int e) { g_posix_errno = e; } } + int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, void** res) { LOG_INFO(Kernel_Vmm, "called addr = {}, len = {}, prot = {}, flags = {}, fd = {}, offset = {}", @@ -185,6 +187,16 @@ void* PS4_SYSV_ABI posix_mmap(void* addr, u64 len, int prot, int flags, int fd, return ptr; } +s32 PS4_SYSV_ABI sceKernelConfiguredFlexibleMemorySize(u64* sizeOut) { + if (sizeOut == nullptr) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + auto* memory = Core::Memory::Instance(); + *sizeOut = memory->GetTotalFlexibleSize(); + return ORBIS_OK; +} + static uint64_t g_mspace_atomic_id_mask = 0; static uint64_t g_mstate_table[64] = {0}; @@ -243,8 +255,7 @@ int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, } int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver) { - auto* param_sfo = Common::Singleton::Instance(); - int version = param_sfo->GetInteger("SYSTEM_VER"); + int version = Common::ElfInfo::Instance().RawFirmwareVer(); LOG_INFO(Kernel, "returned system version = {:#x}", version); *ver = version; return (version > 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL; @@ -403,10 +414,12 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { // obj LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); + // misc LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord); LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect); LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask); + // memory LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException); LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1, sceKernelAllocateDirectMemory); @@ -425,6 +438,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("WFcfL2lzido", "libkernel", 1, "libkernel", 1, 1, sceKernelQueryMemoryProtection); LIB_FUNCTION("BHouLQzh0X0", "libkernel", 1, "libkernel", 1, 1, sceKernelDirectMemoryQuery); LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory); + LIB_FUNCTION("PGhQHd-dzv8", "libkernel", 1, "libkernel", 1, 1, sceKernelMmap); LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap); LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory); LIB_FUNCTION("aNz11fnnzi4", "libkernel", 1, "libkernel", 1, 1, @@ -442,6 +456,14 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("2SKEx6bSq-4", "libkernel", 1, "libkernel", 1, 1, sceKernelBatchMap); LIB_FUNCTION("kBJzF8x4SyE", "libkernel", 1, "libkernel", 1, 1, sceKernelBatchMap2); LIB_FUNCTION("DGMG3JshrZU", "libkernel", 1, "libkernel", 1, 1, sceKernelSetVirtualRangeName); + LIB_FUNCTION("n1-v6FgU7MQ", "libkernel", 1, "libkernel", 1, 1, + sceKernelConfiguredFlexibleMemorySize); + + // Memory pool + LIB_FUNCTION("qCSfqDILlns", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolExpand); + LIB_FUNCTION("pU-QydtGcGY", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolReserve); + LIB_FUNCTION("Vzl66WmfLvk", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolCommit); + LIB_FUNCTION("LXo1tpFqJGs", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolDecommit); // equeue LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue); @@ -454,6 +476,8 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { 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("9bfdLIyuwCY", "libkernel", 1, "libkernel", 1, 1, sceKernelMTypeProtect); + LIB_FUNCTION("vSMAm3cxYTY", "libkernel", 1, "libkernel", 1, 1, sceKernelMProtect); LIB_FUNCTION("23CPPI1tyBY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventFilter); // misc diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/libkernel.h index 5b7f1e722..73705cdc2 100644 --- a/src/core/libraries/kernel/libkernel.h +++ b/src/core/libraries/kernel/libkernel.h @@ -4,6 +4,7 @@ #pragma once #include + #include "common/types.h" namespace Core::Loader { @@ -32,6 +33,8 @@ typedef struct { } OrbisKernelUuid; int* PS4_SYSV_ABI __Error(); +int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, + struct OrbisTimesec* st, unsigned long* dst_sec); int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver); void LibKernel_Register(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index 826d47973..5331f47f2 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -2,10 +2,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/alignment.h" #include "common/assert.h" #include "common/logging/log.h" #include "common/singleton.h" +#include "core/address_space.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/memory_management.h" #include "core/linker.h" @@ -15,7 +17,8 @@ namespace Libraries::Kernel { u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() { LOG_WARNING(Kernel_Vmm, "called"); - return SCE_KERNEL_MAIN_DMEM_SIZE; + const auto* memory = Core::Memory::Instance(); + return memory->GetTotalDirectSize(); } int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, @@ -52,8 +55,8 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, s64* physAddrOut) { - return sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, len, alignment, memoryType, - physAddrOut); + const auto searchEnd = static_cast(sceKernelGetDirectMemorySize()); + return sceKernelAllocateDirectMemory(0, searchEnd, len, alignment, memoryType, physAddrOut); } s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) { @@ -75,19 +78,28 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE LOG_WARNING(Kernel_Vmm, "called searchStart = {:#x}, searchEnd = {:#x}, alignment = {:#x}", searchStart, searchEnd, alignment); - if (searchEnd <= searchStart) { + if (physAddrOut == nullptr || sizeOut == nullptr) { return ORBIS_KERNEL_ERROR_EINVAL; } - if (searchEnd > SCE_KERNEL_MAIN_DMEM_SIZE) { + if (searchEnd > sceKernelGetDirectMemorySize()) { return ORBIS_KERNEL_ERROR_EINVAL; } + if (searchEnd <= searchStart) { + return ORBIS_KERNEL_ERROR_ENOMEM; + } auto* memory = Core::Memory::Instance(); - PAddr physAddr; - s32 result = - memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, sizeOut); + PAddr physAddr{}; + size_t size{}; + s32 result = memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, &size); + + if (size == 0) { + return ORBIS_KERNEL_ERROR_ENOMEM; + } + *physAddrOut = static_cast(physAddr); + *sizeOut = size; return result; } @@ -207,6 +219,18 @@ int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** return memory->QueryProtection(std::bit_cast(addr), start, end, prot); } +int PS4_SYSV_ABI sceKernelMProtect(const void* addr, size_t size, int prot) { + Core::MemoryManager* memory_manager = Core::Memory::Instance(); + Core::MemoryProt protection_flags = static_cast(prot); + return memory_manager->Protect(std::bit_cast(addr), size, protection_flags); +} + +int PS4_SYSV_ABI sceKernelMTypeProtect(const void* addr, size_t size, int mtype, int prot) { + Core::MemoryManager* memory_manager = Core::Memory::Instance(); + Core::MemoryProt protection_flags = static_cast(prot); + return memory_manager->Protect(std::bit_cast(addr), size, protection_flags); +} + int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info, size_t infoSize) { LOG_WARNING(Kernel_Vmm, "called offset = {:#x}, flags = {:#x}", offset, flags); @@ -245,46 +269,61 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries, int* numEntriesOut, int flags) { + int result = ORBIS_OK; int processed = 0; - int result = 0; - for (int i = 0; i < numEntries; i++) { + for (int i = 0; i < numEntries; i++, processed++) { if (entries == nullptr || entries[i].length == 0 || entries[i].operation > 4) { result = ORBIS_KERNEL_ERROR_EINVAL; break; // break and assign a value to numEntriesOut. } - if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT) { + switch (entries[i].operation) { + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT: { result = sceKernelMapNamedDirectMemory(&entries[i].start, entries[i].length, entries[i].protection, flags, static_cast(entries[i].offset), 0, ""); - LOG_INFO( - Kernel_Vmm, - "BatchMap: entry = {}, operation = {}, len = {:#x}, offset = {:#x}, type = {}, " - "result = {}", - i, entries[i].operation, entries[i].length, entries[i].offset, (u8)entries[i].type, - result); - - if (result == 0) - processed++; - } else if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP) { + LOG_INFO(Kernel_Vmm, + "entry = {}, operation = {}, len = {:#x}, offset = {:#x}, type = {}, " + "result = {}", + i, entries[i].operation, entries[i].length, entries[i].offset, + (u8)entries[i].type, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP: { result = sceKernelMunmap(entries[i].start, entries[i].length); - LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}", - i, entries[i].operation, entries[i].length, result); - - if (result == 0) - processed++; - } else if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_FLEXIBLE) { + LOG_INFO(Kernel_Vmm, "entry = {}, operation = {}, len = {:#x}, result = {}", i, + entries[i].operation, entries[i].length, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_PROTECT: { + result = sceKernelMProtect(entries[i].start, entries[i].length, entries[i].protection); + LOG_INFO(Kernel_Vmm, "entry = {}, operation = {}, len = {:#x}, result = {}", i, + entries[i].operation, entries[i].length, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_FLEXIBLE: { result = sceKernelMapNamedFlexibleMemory(&entries[i].start, entries[i].length, entries[i].protection, flags, ""); LOG_INFO(Kernel_Vmm, - "BatchMap: entry = {}, operation = {}, len = {:#x}, type = {}, " + "entry = {}, operation = {}, len = {:#x}, type = {}, " "result = {}", i, entries[i].operation, entries[i].length, (u8)entries[i].type, result); + break; + } + case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_TYPE_PROTECT: { + result = sceKernelMTypeProtect(entries[i].start, entries[i].length, entries[i].type, + entries[i].protection); + LOG_INFO(Kernel_Vmm, "entry = {}, operation = {}, len = {:#x}, result = {}", i, + entries[i].operation, entries[i].length, result); + break; + } + default: { + UNREACHABLE(); + } + } - if (result == 0) - processed++; - } else { - UNREACHABLE_MSG("called: Unimplemented Operation = {}", entries[i].operation); + if (result != ORBIS_OK) { + break; } } if (numEntriesOut != NULL) { // can be zero. do not return an error code. @@ -308,4 +347,102 @@ s32 PS4_SYSV_ABI sceKernelSetVirtualRangeName(const void* addr, size_t len, cons memory->NameVirtualRange(std::bit_cast(addr), len, name); return ORBIS_OK; } + +s32 PS4_SYSV_ABI sceKernelMemoryPoolExpand(u64 searchStart, u64 searchEnd, size_t len, + size_t alignment, u64* physAddrOut) { + if (searchStart < 0 || searchEnd <= searchStart) { + LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + const bool is_in_range = searchEnd - searchStart >= len; + if (len <= 0 || !Common::Is64KBAligned(len) || !is_in_range) { + LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (alignment != 0 && !Common::Is64KBAligned(alignment)) { + LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (physAddrOut == nullptr) { + LOG_ERROR(Kernel_Vmm, "Result physical address pointer is null!"); + return SCE_KERNEL_ERROR_EINVAL; + } + + auto* memory = Core::Memory::Instance(); + PAddr phys_addr = memory->PoolExpand(searchStart, searchEnd, len, alignment); + *physAddrOut = static_cast(phys_addr); + + LOG_INFO(Kernel_Vmm, + "searchStart = {:#x}, searchEnd = {:#x}, len = {:#x}, alignment = {:#x}, physAddrOut " + "= {:#x}", + searchStart, searchEnd, len, alignment, phys_addr); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t alignment, int flags, + void** addrOut) { + LOG_INFO(Kernel_Vmm, "addrIn = {}, len = {:#x}, alignment = {:#x}, flags = {:#x}", + fmt::ptr(addrIn), len, alignment, flags); + + if (addrIn == nullptr) { + LOG_ERROR(Kernel_Vmm, "Address is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (len == 0 || !Common::Is2MBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 2MB aligned!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (alignment != 0) { + if ((!std::has_single_bit(alignment) && !Common::Is2MBAligned(alignment))) { + LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + } + + auto* memory = Core::Memory::Instance(); + const VAddr in_addr = reinterpret_cast(addrIn); + const auto map_flags = static_cast(flags); + memory->PoolReserve(addrOut, in_addr, len, map_flags, alignment); + + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags) { + if (addr == nullptr) { + LOG_ERROR(Kernel_Vmm, "Address is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (len == 0 || !Common::Is64KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 64KB aligned!"); + return SCE_KERNEL_ERROR_EINVAL; + } + + LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, type = {:#x}, prot = {:#x}, flags = {:#x}", + fmt::ptr(addr), len, type, prot, flags); + + const VAddr in_addr = reinterpret_cast(addr); + const auto mem_prot = static_cast(prot); + auto* memory = Core::Memory::Instance(); + return memory->PoolCommit(in_addr, len, mem_prot); +} + +s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags) { + if (addr == nullptr) { + LOG_ERROR(Kernel_Vmm, "Address is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (len == 0 || !Common::Is64KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 64KB aligned!"); + return SCE_KERNEL_ERROR_EINVAL; + } + + LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, flags = {:#x}", fmt::ptr(addr), len, flags); + + const VAddr pool_addr = reinterpret_cast(addr); + auto* memory = Core::Memory::Instance(); + memory->PoolDecommit(pool_addr, len); + + return ORBIS_OK; +} + } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index 378449cc5..6e90204cf 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -6,7 +6,9 @@ #include "common/bit_field.h" #include "common/types.h" -constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 6_GB; // ~ 6GB +constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB +// TODO: Confirm this value on hardware. +constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE_PRO = 5568_MB; // ~ 5.5GB namespace Libraries::Kernel { @@ -56,7 +58,7 @@ struct OrbisVirtualQueryInfo { BitField<1, 1, u32> is_direct; BitField<2, 1, u32> is_stack; BitField<3, 1, u32> is_pooled; - BitField<4, 1, u32> is_commited; + BitField<4, 1, u32> is_committed; }; std::array name; }; @@ -95,6 +97,10 @@ s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int flags); int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot); +int PS4_SYSV_ABI sceKernelMProtect(const void* addr, size_t size, int prot); + +int PS4_SYSV_ABI sceKernelMTypeProtect(const void* addr, size_t size, int mtype, int prot); + int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info, size_t infoSize); s32 PS4_SYSV_ABI sceKernelAvailableFlexibleMemorySize(size_t* sizeOut); @@ -110,4 +116,11 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn s32 PS4_SYSV_ABI sceKernelSetVirtualRangeName(const void* addr, size_t len, const char* name); +s32 PS4_SYSV_ABI sceKernelMemoryPoolExpand(u64 searchStart, u64 searchEnd, size_t len, + size_t alignment, u64* physAddrOut); +s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t alignment, int flags, + void** addrOut); +s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags); +s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags); + } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 689532693..39c0eaf80 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -2,20 +2,23 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include -#include + #include "common/alignment.h" #include "common/assert.h" #include "common/error.h" #include "common/logging/log.h" #include "common/singleton.h" #include "common/thread.h" +#include "core/debug_state.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/kernel/thread_management.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" #include "core/linker.h" +#include "core/tls.h" #ifdef _WIN64 #include #else @@ -33,6 +36,10 @@ void init_pthreads() { ScePthreadMutexattr default_mutexattr = nullptr; scePthreadMutexattrInit(&default_mutexattr); g_pthread_cxt->setDefaultMutexattr(default_mutexattr); + ScePthreadMutexattr adaptive_mutexattr = nullptr; + scePthreadMutexattrInit(&adaptive_mutexattr); + scePthreadMutexattrSettype(&adaptive_mutexattr, ORBIS_PTHREAD_MUTEX_ADAPTIVE); + g_pthread_cxt->setAdaptiveMutexattr(adaptive_mutexattr); // default cond init ScePthreadCondattr default_condattr = nullptr; scePthreadCondattrInit(&default_condattr); @@ -50,11 +57,12 @@ void init_pthreads() { } void pthreadInitSelfMainThread() { + const char* name = "Main_Thread"; auto* pthread_pool = g_pthread_cxt->GetPthreadPool(); - g_pthread_self = pthread_pool->Create(); + g_pthread_self = pthread_pool->Create(name); scePthreadAttrInit(&g_pthread_self->attr); g_pthread_self->pth = pthread_self(); - g_pthread_self->name = "Main_Thread"; + g_pthread_self->name = name; } int PS4_SYSV_ABI scePthreadAttrInit(ScePthreadAttr* attr) { @@ -292,7 +300,7 @@ ScePthread PS4_SYSV_ABI scePthreadSelf() { int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr, const /*SceKernelCpumask*/ u64 mask) { - LOG_INFO(Kernel_Pthread, "called"); + LOG_DEBUG(Kernel_Pthread, "called"); if (pattr == nullptr || *pattr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -384,7 +392,7 @@ int PS4_SYSV_ABI posix_pthread_attr_setstacksize(ScePthreadAttr* attr, size_t st } int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpumask*/ u64 mask) { - LOG_INFO(Kernel_Pthread, "called"); + LOG_DEBUG(Kernel_Pthread, "called"); if (thread == nullptr) { return SCE_KERNEL_ERROR_ESRCH; @@ -408,14 +416,11 @@ int PS4_SYSV_ABI scePthreadGetaffinity(ScePthread thread, /*SceKernelCpumask*/ u } ScePthreadMutex* createMutex(ScePthreadMutex* addr) { - if (addr == nullptr || *addr != nullptr) { - return addr; - } - static std::mutex mutex; - std::scoped_lock lk{mutex}; - if (*addr != nullptr) { + if (addr == nullptr || + (*addr != nullptr && *addr != ORBIS_PTHREAD_MUTEX_ADAPTIVE_INITIALIZER)) { return addr; } + const VAddr vaddr = reinterpret_cast(addr); std::string name = fmt::format("mutex{:#x}", vaddr); scePthreadMutexInit(addr, nullptr, name.c_str()); @@ -429,14 +434,14 @@ int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMut if (mutex == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } - if (mutex_attr == nullptr) { - attr = g_pthread_cxt->getDefaultMutexattr(); - } else { - if (*mutex_attr == nullptr) { - attr = g_pthread_cxt->getDefaultMutexattr(); + if (mutex_attr == nullptr || *mutex_attr == nullptr) { + if (*mutex == ORBIS_PTHREAD_MUTEX_ADAPTIVE_INITIALIZER) { + attr = g_pthread_cxt->getAdaptiveMutexattr(); } else { - attr = mutex_attr; + attr = g_pthread_cxt->getDefaultMutexattr(); } + } else { + attr = mutex_attr; } *mutex = new PthreadMutexInternal{}; @@ -510,23 +515,27 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) { int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) { int ptype = PTHREAD_MUTEX_DEFAULT; switch (type) { - case 1: + case ORBIS_PTHREAD_MUTEX_ERRORCHECK: ptype = PTHREAD_MUTEX_ERRORCHECK; break; - case 2: + case ORBIS_PTHREAD_MUTEX_RECURSIVE: ptype = PTHREAD_MUTEX_RECURSIVE; break; - case 3: - case 4: + case ORBIS_PTHREAD_MUTEX_NORMAL: ptype = PTHREAD_MUTEX_NORMAL; break; + case ORBIS_PTHREAD_MUTEX_ADAPTIVE: + LOG_ERROR(Kernel_Pthread, "Unimplemented adaptive mutex"); + ptype = PTHREAD_MUTEX_ERRORCHECK; + break; default: - UNREACHABLE_MSG("Invalid type: {}", type); + return SCE_KERNEL_ERROR_EINVAL; } int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype); + ASSERT(result == 0); - return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; + return SCE_OK; } int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol) { @@ -580,8 +589,7 @@ int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) { } int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) { - mutex = createMutex(mutex); - if (mutex == nullptr) { + if (mutex == nullptr || *mutex == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -654,7 +662,7 @@ int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondat int result = pthread_cond_init(&(*cond)->cond, &(*attr)->cond_attr); if (name != nullptr) { - LOG_INFO(Kernel_Pthread, "name={}, result={}", (*cond)->name, result); + LOG_TRACE(Kernel_Pthread, "name={}, result={}", (*cond)->name, result); } switch (result) { @@ -984,19 +992,21 @@ static void cleanup_thread(void* arg) { destructor(value); } } + Core::SetTcbBase(nullptr); thread->is_almost_done = true; + DebugState.RemoveCurrentThreadFromGuestList(); } static void* run_thread(void* arg) { auto* thread = static_cast(arg); Common::SetCurrentThreadName(thread->name.c_str()); - auto* linker = Common::Singleton::Instance(); - linker->InitTlsForThread(false); + const auto* linker = Common::Singleton::Instance(); void* ret = nullptr; g_pthread_self = thread; pthread_cleanup_push(cleanup_thread, thread); thread->is_started = true; - ret = thread->entry(thread->arg); + DebugState.AddCurrentThreadToGuestList(); + ret = linker->ExecuteGuest(thread->entry, thread->arg); pthread_cleanup_pop(1); return ret; } @@ -1013,7 +1023,7 @@ int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr attr = g_pthread_cxt->GetDefaultAttr(); } - *thread = pthread_pool->Create(); + *thread = pthread_pool->Create(name); if ((*thread)->attr != nullptr) { scePthreadAttrDestroy(&(*thread)->attr); @@ -1055,11 +1065,11 @@ int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr } } -ScePthread PThreadPool::Create() { +ScePthread PThreadPool::Create(const char* name) { std::scoped_lock lock{m_mutex}; for (auto* p : m_threads) { - if (p->is_free) { + if (p->is_free && name != nullptr && p->name == name) { p->is_free = false; return p; } @@ -1123,7 +1133,6 @@ int PS4_SYSV_ABI posix_pthread_join(ScePthread thread, void** res) { } int PS4_SYSV_ABI scePthreadDetach(ScePthread thread) { - LOG_INFO(Kernel_Pthread, "thread create name = {}", thread->name); thread->is_detached = true; return ORBIS_OK; } @@ -1183,6 +1192,7 @@ int PS4_SYSV_ABI scePthreadCondattrDestroy(ScePthreadCondattr* attr) { int result = pthread_condattr_destroy(&(*attr)->cond_attr); LOG_DEBUG(Kernel_Pthread, "scePthreadCondattrDestroy: result = {} ", result); + delete *attr; switch (result) { case 0: @@ -1374,90 +1384,97 @@ int PS4_SYSV_ABI posix_pthread_detach(ScePthread thread) { return pthread_detach(thread->pth); } -int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) { - int result = sem_init(sem, pshared, value); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_init(PthreadSemInternal** sem, int pshared, unsigned int value) { + if (value > ORBIS_KERNEL_SEM_VALUE_MAX) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if (sem != nullptr) { + *sem = new PthreadSemInternal{ + .semaphore = std::counting_semaphore{value}, + .value = {static_cast(value)}, + }; + } + return 0; } -int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) { - int result = sem_wait(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_wait(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + (*sem)->semaphore.acquire(); + --(*sem)->value; + return 0; } -int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) { - int result = sem_trywait(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_trywait(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if (!(*sem)->semaphore.try_acquire()) { + SetPosixErrno(EAGAIN); + return -1; + } + --(*sem)->value; + return 0; } -#ifndef HAVE_SEM_TIMEDWAIT -int sem_timedwait(sem_t* sem, const struct timespec* abstime) { - int rc; - while ((rc = sem_trywait(sem)) == EAGAIN) { - struct timespec curr_time; - clock_gettime(CLOCK_REALTIME, &curr_time); - - s64 remaining_ns = 0; - remaining_ns += - (static_cast(abstime->tv_sec) - static_cast(curr_time.tv_sec)) * 1000000000L; - remaining_ns += static_cast(abstime->tv_nsec) - static_cast(curr_time.tv_nsec); - - if (remaining_ns <= 0) { - return ETIMEDOUT; - } - - struct timespec sleep_time; - sleep_time.tv_sec = 0; - if (remaining_ns < 5000000L) { - sleep_time.tv_nsec = remaining_ns; - } else { - sleep_time.tv_nsec = 5000000; - } - - nanosleep(&sleep_time, nullptr); +int PS4_SYSV_ABI posix_sem_timedwait(PthreadSemInternal** sem, const timespec* t) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return rc; -} -#endif -int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) { - int result = sem_timedwait(sem, t); - if (result == -1) { - SetPosixErrno(errno); + using std::chrono::duration_cast; + using std::chrono::nanoseconds; + using std::chrono::seconds; + using std::chrono::system_clock; + + const system_clock::time_point time{ + duration_cast(seconds{t->tv_sec} + nanoseconds{t->tv_nsec})}; + if (!(*sem)->semaphore.try_acquire_until(time)) { + SetPosixErrno(ETIMEDOUT); + return -1; } - return result; + --(*sem)->value; + return 0; } -int PS4_SYSV_ABI posix_sem_post(sem_t* sem) { - int result = sem_post(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_post(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if ((*sem)->value == ORBIS_KERNEL_SEM_VALUE_MAX) { + SetPosixErrno(EOVERFLOW); + return -1; + } + ++(*sem)->value; + (*sem)->semaphore.release(); + return 0; } -int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) { - int result = sem_destroy(sem); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_destroy(PthreadSemInternal** sem) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + delete *sem; + *sem = nullptr; + return 0; } -int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) { - int result = sem_getvalue(sem, sval); - if (result == -1) { - SetPosixErrno(errno); +int PS4_SYSV_ABI posix_sem_getvalue(PthreadSemInternal** sem, int* sval) { + if (sem == nullptr || *sem == nullptr) { + SetPosixErrno(EINVAL); + return -1; } - return result; + if (sval) { + *sval = (*sem)->value; + } + return 0; } int PS4_SYSV_ABI posix_pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* size) { @@ -1481,6 +1498,8 @@ int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) { } [[noreturn]] void PS4_SYSV_ABI scePthreadExit(void* value_ptr) { + g_pthread_self->is_free = true; + pthread_exit(value_ptr); UNREACHABLE(); } @@ -1499,6 +1518,10 @@ int PS4_SYSV_ABI scePthreadGetprio(ScePthread thread, int* prio) { return ORBIS_OK; } int PS4_SYSV_ABI scePthreadSetprio(ScePthread thread, int prio) { + if (thread == nullptr) { + LOG_ERROR(Kernel_Pthread, "scePthreadSetprio: thread is nullptr"); + return ORBIS_KERNEL_ERROR_EINVAL; + } thread->prio = prio; return ORBIS_OK; } @@ -1609,6 +1632,10 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("upoVrzMHFeE", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexTrylock); LIB_FUNCTION("IafI2PxcPnQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexTimedlock); + // scePthreadMutexInitForInternalLibc, scePthreadMutexattrInitForInternalLibc + LIB_FUNCTION("qH1gXoq71RY", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit); + LIB_FUNCTION("n2MMpvU8igI", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrInit); + // cond calls LIB_FUNCTION("2Tb92quprl0", "libkernel", 1, "libkernel", 1, 1, scePthreadCondInit); LIB_FUNCTION("m5-2bsNfv7s", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrInit); diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index c5935275f..3cdb300f7 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -5,12 +5,16 @@ #include #include +#include #include #include #include #include + #include "common/types.h" +#define ORBIS_PTHREAD_MUTEX_ADAPTIVE_INITIALIZER (reinterpret_cast(1)) + namespace Core::Loader { class SymbolsResolver; } @@ -19,6 +23,12 @@ namespace Libraries::Kernel { constexpr int ORBIS_KERNEL_PRIO_FIFO_DEFAULT = 700; constexpr int ORBIS_KERNEL_PRIO_FIFO_HIGHEST = 256; constexpr int ORBIS_KERNEL_PRIO_FIFO_LOWEST = 767; +constexpr int ORBIS_KERNEL_SEM_VALUE_MAX = 0x7FFFFFFF; + +constexpr int ORBIS_PTHREAD_MUTEX_ERRORCHECK = 1; +constexpr int ORBIS_PTHREAD_MUTEX_RECURSIVE = 2; +constexpr int ORBIS_PTHREAD_MUTEX_NORMAL = 3; +constexpr int ORBIS_PTHREAD_MUTEX_ADAPTIVE = 4; struct PthreadInternal; struct PthreadAttrInternal; @@ -104,9 +114,14 @@ struct PthreadRwInternal { std::string name; }; +struct PthreadSemInternal { + std::counting_semaphore semaphore; + std::atomic value; +}; + class PThreadPool { public: - ScePthread Create(); + ScePthread Create(const char* name); private: std::vector m_threads; @@ -121,6 +136,12 @@ public: void setDefaultMutexattr(ScePthreadMutexattr attr) { m_default_mutexattr = attr; } + ScePthreadMutexattr* getAdaptiveMutexattr() { + return &m_adaptive_mutexattr; + } + void setAdaptiveMutexattr(ScePthreadMutexattr attr) { + m_adaptive_mutexattr = attr; + } ScePthreadCondattr* getDefaultCondattr() { return &m_default_condattr; } @@ -148,6 +169,7 @@ public: private: ScePthreadMutexattr m_default_mutexattr = nullptr; + ScePthreadMutexattr m_adaptive_mutexattr = nullptr; ScePthreadCondattr m_default_condattr = nullptr; ScePthreadAttr m_default_attr = nullptr; PThreadPool* m_pthread_pool = nullptr; diff --git a/src/core/libraries/kernel/threads/semaphore.cpp b/src/core/libraries/kernel/threads/semaphore.cpp index 3bd9ccbc0..59099c1b8 100644 --- a/src/core/libraries/kernel/threads/semaphore.cpp +++ b/src/core/libraries/kernel/threads/semaphore.cpp @@ -2,10 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include -#include -#include #include + #include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" @@ -13,9 +13,6 @@ namespace Libraries::Kernel { -using ListBaseHook = - boost::intrusive::list_base_hook>; - class Semaphore { public: Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo) @@ -35,12 +32,20 @@ public: return ORBIS_KERNEL_ERROR_EBUSY; } + if (timeout && *timeout == 0) { + return SCE_KERNEL_ERROR_ETIMEDOUT; + } + // Create waiting thread object and add it into the list of waiters. WaitingThread waiter{need_count, is_fifo}; - AddWaiter(waiter); + const auto it = AddWaiter(&waiter); // Perform the wait. - return waiter.Wait(lk, timeout); + const s32 result = waiter.Wait(lk, timeout); + if (result == SCE_KERNEL_ERROR_ETIMEDOUT) { + wait_list.erase(it); + } + return result; } bool Signal(s32 signal_count) { @@ -52,14 +57,14 @@ public: // Wake up threads in order of priority. for (auto it = wait_list.begin(); it != wait_list.end();) { - auto& waiter = *it; - if (waiter.need_count > token_count) { + auto* waiter = *it; + if (waiter->need_count > token_count) { ++it; continue; } it = wait_list.erase(it); - token_count -= waiter.need_count; - waiter.cv.notify_one(); + token_count -= waiter->need_count; + waiter->cv.notify_one(); } return true; @@ -70,9 +75,9 @@ public: if (num_waiters) { *num_waiters = wait_list.size(); } - for (auto& waiter : wait_list) { - waiter.was_cancled = true; - waiter.cv.notify_one(); + for (auto* waiter : wait_list) { + waiter->was_cancled = true; + waiter->cv.notify_one(); } wait_list.clear(); token_count = set_count < 0 ? init_count : set_count; @@ -80,7 +85,7 @@ public: } public: - struct WaitingThread : public ListBaseHook { + struct WaitingThread { std::condition_variable cv; u32 priority; s32 need_count; @@ -132,24 +137,24 @@ public: } }; - void AddWaiter(WaitingThread& waiter) { + using WaitList = std::list; + + WaitList::iterator AddWaiter(WaitingThread* waiter) { // Insert at the end of the list for FIFO order. if (is_fifo) { wait_list.push_back(waiter); - return; + return --wait_list.end(); } // Find the first with priority less then us and insert right before it. auto it = wait_list.begin(); - while (it != wait_list.end() && it->priority > waiter.priority) { + while (it != wait_list.end() && (*it)->priority > waiter->priority) { ++it; } wait_list.insert(it, waiter); + return it; } - using WaitingThreads = - boost::intrusive::list, - boost::intrusive::constant_time_size>; - WaitingThreads wait_list; + WaitList wait_list; std::string name; std::atomic token_count; std::mutex mutex; diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index 214f039b4..853f8d54c 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/assert.h" +#include "common/debug.h" #include "common/native_clock.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/time_management.h" @@ -30,7 +32,8 @@ u64 PS4_SYSV_ABI sceKernelGetTscFrequency() { } u64 PS4_SYSV_ABI sceKernelGetProcessTime() { - return clock->GetProcessTimeUS(); + // TODO: this timer should support suspends, so initial ptc needs to be updated on wake up + return clock->GetTimeUS(initial_ptc); } u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter() { @@ -144,13 +147,20 @@ int PS4_SYSV_ABI sceKernelGettimeofday(OrbisKernelTimeval* tp) { } #ifdef _WIN64 - auto now = std::chrono::system_clock::now(); - auto duration = now.time_since_epoch(); - auto seconds = std::chrono::duration_cast(duration); - auto microsecs = std::chrono::duration_cast(duration - seconds); + FILETIME filetime; + GetSystemTimePreciseAsFileTime(&filetime); - tp->tv_sec = seconds.count(); - tp->tv_usec = microsecs.count(); + constexpr u64 UNIX_TIME_START = 0x295E9648864000; + constexpr u64 TICKS_PER_SECOND = 1000000; + + u64 ticks = filetime.dwHighDateTime; + ticks <<= 32; + ticks |= filetime.dwLowDateTime; + ticks /= 10; + ticks -= UNIX_TIME_START; + + tp->tv_sec = ticks / TICKS_PER_SECOND; + tp->tv_usec = ticks % TICKS_PER_SECOND; #else timeval tv; gettimeofday(&tv, nullptr); @@ -237,6 +247,17 @@ int PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2, return SCE_OK; } +namespace Dev { +u64& GetInitialPtc() { + return initial_ptc; +} + +Common::NativeClock* GetClock() { + return clock.get(); +} + +} // namespace Dev + void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) { clock = std::make_unique(); initial_ptc = clock->GetUptime(); diff --git a/src/core/libraries/kernel/time_management.h b/src/core/libraries/kernel/time_management.h index a28f8c133..f2216f3d3 100644 --- a/src/core/libraries/kernel/time_management.h +++ b/src/core/libraries/kernel/time_management.h @@ -3,8 +3,14 @@ #pragma once +#include + #include "common/types.h" +namespace Common { +class NativeClock; +} + namespace Core::Loader { class SymbolsResolver; } @@ -45,12 +51,21 @@ constexpr int ORBIS_CLOCK_EXT_DEBUG_NETWORK = 17; constexpr int ORBIS_CLOCK_EXT_AD_NETWORK = 18; constexpr int ORBIS_CLOCK_EXT_RAW_NETWORK = 19; +namespace Dev { +u64& GetInitialPtc(); + +Common::NativeClock* GetClock(); +} // namespace Dev + u64 PS4_SYSV_ABI sceKernelGetTscFrequency(); u64 PS4_SYSV_ABI sceKernelGetProcessTime(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency(); u64 PS4_SYSV_ABI sceKernelReadTsc(); - +int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp); +s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz); +int PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2, time_t* seconds, + OrbisKernelTimezone* timezone, int* dst_seconds); void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/libc_internal/libc_internal.cpp b/src/core/libraries/libc_internal/libc_internal.cpp index 0607e93b7..8eea41eb3 100644 --- a/src/core/libraries/libc_internal/libc_internal.cpp +++ b/src/core/libraries/libc_internal/libc_internal.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index f0171199b..caa254fd8 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -2,13 +2,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/config.h" +#include "core/libraries/ajm/ajm.h" #include "core/libraries/app_content/app_content.h" #include "core/libraries/audio/audioin.h" #include "core/libraries/audio/audioout.h" +#include "core/libraries/audio3d/audio3d.h" +#include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/dialogs/error_dialog.h" +#include "core/libraries/dialogs/ime_dialog.h" #include "core/libraries/disc_map/disc_map.h" +#include "core/libraries/game_live_streaming/gamelivestreaming.h" #include "core/libraries/gnmdriver/gnmdriver.h" +#include "core/libraries/ime/ime.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/libc_internal/libc_internal.h" +#include "core/libraries/libpng/pngdec.h" #include "core/libraries/libs.h" #include "core/libraries/network/http.h" #include "core/libraries/network/net.h" @@ -20,23 +28,20 @@ #include "core/libraries/pad/pad.h" #include "core/libraries/playgo/playgo.h" #include "core/libraries/random/random.h" +#include "core/libraries/remote_play/remoteplay.h" #include "core/libraries/rtc/rtc.h" +#include "core/libraries/save_data/dialog/savedatadialog.h" #include "core/libraries/save_data/savedata.h" #include "core/libraries/screenshot/screenshot.h" +#include "core/libraries/share_play/shareplay.h" #include "core/libraries/system/commondialog.h" #include "core/libraries/system/msgdialog.h" #include "core/libraries/system/posix.h" -#include "core/libraries/system/savedatadialog.h" #include "core/libraries/system/sysmodule.h" #include "core/libraries/system/systemservice.h" #include "core/libraries/system/userservice.h" #include "core/libraries/usbd/usbd.h" #include "core/libraries/videoout/video_out.h" -#include "src/core/libraries/ajm/ajm.h" -#include "src/core/libraries/avplayer/avplayer.h" -#include "src/core/libraries/dialogs/error_dialog.h" -#include "src/core/libraries/dialogs/ime_dialog.h" -#include "src/core/libraries/libpng/pngdec.h" namespace Libraries { @@ -56,11 +61,11 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::Net::RegisterlibSceNet(sym); Libraries::NetCtl::RegisterlibSceNetCtl(sym); Libraries::SaveData::RegisterlibSceSaveData(sym); + Libraries::SaveData::Dialog::RegisterlibSceSaveDataDialog(sym); Libraries::Ssl::RegisterlibSceSsl(sym); Libraries::SysModule::RegisterlibSceSysmodule(sym); Libraries::Posix::Registerlibsceposix(sym); Libraries::AudioIn::RegisterlibSceAudioIn(sym); - Libraries::SaveDataDialog::RegisterlibSceSaveDataDialog(sym); Libraries::NpManager::RegisterlibSceNpManager(sym); Libraries::NpScore::RegisterlibSceNpScore(sym); Libraries::NpTrophy::RegisterlibSceNpTrophy(sym); @@ -75,6 +80,11 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::ErrorDialog::RegisterlibSceErrorDialog(sym); Libraries::ImeDialog::RegisterlibSceImeDialog(sym); Libraries::AvPlayer::RegisterlibSceAvPlayer(sym); + Libraries::Audio3d::RegisterlibSceAudio3d(sym); + Libraries::Ime::RegisterlibSceIme(sym); + Libraries::GameLiveStreaming::RegisterlibSceGameLiveStreaming(sym); + Libraries::SharePlay::RegisterlibSceSharePlay(sym); + Libraries::Remoteplay::RegisterlibSceRemoteplay(sym); } } // namespace Libraries diff --git a/src/core/libraries/libs.h b/src/core/libraries/libs.h index 7cad7f8ba..ea928101e 100644 --- a/src/core/libraries/libs.h +++ b/src/core/libraries/libs.h @@ -4,6 +4,7 @@ #pragma once #include + #include "common/logging/log.h" #include "core/loader/elf.h" #include "core/loader/symbols_resolver.h" diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 2c03dde3e..161fc5214 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -18,6 +18,8 @@ namespace Libraries::Net { +static thread_local int32_t net_errno = 0; + int PS4_SYSV_ABI in6addr_any() { LOG_ERROR(Lib_Net, "(STUBBED) called"); return ORBIS_OK; @@ -563,9 +565,9 @@ int PS4_SYSV_ABI sceNetEpollWait() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetErrnoLoc() { +int* PS4_SYSV_ABI sceNetErrnoLoc() { LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + return &net_errno; } int PS4_SYSV_ABI sceNetEtherNtostr() { @@ -732,9 +734,16 @@ int PS4_SYSV_ABI sceNetInetNtopWithScopeId() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetInetPton() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst) { +#ifdef WIN32 + int res = InetPtonA(af, src, dst); +#else + int res = inet_pton(af, src, dst); +#endif + if (res < 0) { + UNREACHABLE(); + } + return res; } int PS4_SYSV_ABI sceNetInetPtonEx() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 965b76809..beef38b56 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -10,8 +10,12 @@ class SymbolsResolver; } // Define our own htonll and ntohll because its not available in some systems/platforms +#ifndef HTONLL #define HTONLL(x) (((uint64_t)htonl((x) & 0xFFFFFFFFUL)) << 32) | htonl((uint32_t)((x) >> 32)) +#endif +#ifndef NTOHLL #define NTOHLL(x) (((uint64_t)ntohl((x) & 0xFFFFFFFFUL)) << 32) | ntohl((uint32_t)((x) >> 32)) +#endif namespace Libraries::Net { @@ -132,7 +136,7 @@ int PS4_SYSV_ABI sceNetEpollControl(); int PS4_SYSV_ABI sceNetEpollCreate(); int PS4_SYSV_ABI sceNetEpollDestroy(); int PS4_SYSV_ABI sceNetEpollWait(); -int PS4_SYSV_ABI sceNetErrnoLoc(); +int* PS4_SYSV_ABI sceNetErrnoLoc(); int PS4_SYSV_ABI sceNetEtherNtostr(); int PS4_SYSV_ABI sceNetEtherStrton(); int PS4_SYSV_ABI sceNetEventCallbackCreate(); @@ -165,7 +169,7 @@ u64 PS4_SYSV_ABI sceNetHtonll(u64 host64); u16 PS4_SYSV_ABI sceNetHtons(u16 host16); const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 size); int PS4_SYSV_ABI sceNetInetNtopWithScopeId(); -int PS4_SYSV_ABI sceNetInetPton(); +int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst); int PS4_SYSV_ABI sceNetInetPtonEx(); int PS4_SYSV_ABI sceNetInetPtonWithScopeId(); int PS4_SYSV_ABI sceNetInfoDumpStart(); diff --git a/src/core/libraries/network/net_ctl_codes.h b/src/core/libraries/network/net_ctl_codes.h new file mode 100644 index 000000000..0dac4201e --- /dev/null +++ b/src/core/libraries/network/net_ctl_codes.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +// error codes +constexpr int ORBIS_NET_CTL_ERROR_CALLBACK_MAX = 0x80412103; +constexpr int ORBIS_NET_CTL_ERROR_ID_NOT_FOUND = 0x80412104; +constexpr int ORBIS_NET_CTL_ERROR_INVALID_ID = 0x80412105; +constexpr int ORBIS_NET_CTL_ERROR_INVALID_ADDR = 0x80412107; +constexpr int ORBIS_NET_CTL_ERROR_NOT_CONNECTED = 0x80412108; +constexpr int ORBIS_NET_CTL_ERROR_NOT_AVAIL = 0x80412109; +constexpr int ORBIS_NET_CTL_ERROR_NETWORK_DISABLED = 0x8041210D; +constexpr int ORBIS_NET_CTL_ERROR_DISCONNECT_REQ = 0x8041210E; +constexpr int ORBIS_NET_CTL_ERROR_ETHERNET_PLUGOUT = 0x80412115; +constexpr int ORBIS_NET_CTL_ERROR_WIFI_DEAUTHED = 0x80412116; +constexpr int ORBIS_NET_CTL_ERROR_WIFI_BEACON_LOST = 0x80412117; + +// state codes +constexpr int ORBIS_NET_CTL_STATE_DISCONNECTED = 0; +constexpr int ORBIS_NET_CTL_STATE_CONNECTING = 1; +constexpr int ORBIS_NET_CTL_STATE_IPOBTAINING = 2; +constexpr int ORBIS_NET_CTL_STATE_IPOBTAINED = 3; + +// event type +constexpr int ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED = 1; +constexpr int ORBIS_SCE_NET_CTL_EVENT_TYPE_DISCONNECT_REQ_FINISHED = 2; +constexpr int ORBIS_NET_CTL_EVENT_TYPE_IPOBTAINED = 3; + +// get info codes +// device +constexpr int ORBIS_NET_CTL_DEVICE_WIRED = 0; +constexpr int ORBIS_NET_CTL_DEVICE_WIRELESS = 1; +// link +constexpr int ORBIS_NET_CTL_LINK_DISCONNECTED = 0; +constexpr int ORBIS_NET_CTL_LINK_CONNECTED = 1; diff --git a/src/core/libraries/network/net_ctl_obj.cpp b/src/core/libraries/network/net_ctl_obj.cpp new file mode 100644 index 000000000..07381d676 --- /dev/null +++ b/src/core/libraries/network/net_ctl_obj.cpp @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/singleton.h" +#include "core/linker.h" +#include "net_ctl_codes.h" +#include "net_ctl_obj.h" + +Libraries::NetCtl::NetCtlInternal::NetCtlInternal() { + callbacks.fill({nullptr, nullptr}); + nptoolCallbacks.fill({nullptr, nullptr}); +} + +Libraries::NetCtl::NetCtlInternal::~NetCtlInternal() {} + +s32 Libraries::NetCtl::NetCtlInternal::registerCallback(OrbisNetCtlCallback func, void* arg) { + std::unique_lock lock{m_mutex}; + + // Find the next available slot + int next_id = 0; + for (const auto& callback : callbacks) { + if (callback.func == nullptr) { + break; + } + next_id++; + } + + if (next_id == 8) { + return ORBIS_NET_CTL_ERROR_CALLBACK_MAX; + } + + callbacks[next_id].func = func; + callbacks[next_id].arg = arg; + return next_id; +} + +s32 Libraries::NetCtl::NetCtlInternal::registerNpToolkitCallback( + OrbisNetCtlCallbackForNpToolkit func, void* arg) { + + std::unique_lock lock{m_mutex}; + + // Find the next available slot + int next_id = 0; + for (const auto& callback : nptoolCallbacks) { + if (callback.func == nullptr) { + break; + } + next_id++; + } + + if (next_id == 8) { + return ORBIS_NET_CTL_ERROR_CALLBACK_MAX; + } + + nptoolCallbacks[next_id].func = func; + nptoolCallbacks[next_id].arg = arg; + return next_id; +} + +void Libraries::NetCtl::NetCtlInternal::checkCallback() { + std::unique_lock lock{m_mutex}; + const auto* linker = Common::Singleton::Instance(); + for (auto& callback : callbacks) { + if (callback.func != nullptr) { + linker->ExecuteGuest(callback.func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, + callback.arg); + } + } +} + +void Libraries::NetCtl::NetCtlInternal::checkNpToolkitCallback() { + std::unique_lock lock{m_mutex}; + const auto* linker = Common::Singleton::Instance(); + for (auto& callback : nptoolCallbacks) { + if (callback.func != nullptr) { + linker->ExecuteGuest(callback.func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, + callback.arg); + } + } +} diff --git a/src/core/libraries/network/net_ctl_obj.h b/src/core/libraries/network/net_ctl_obj.h new file mode 100644 index 000000000..3178677f4 --- /dev/null +++ b/src/core/libraries/network/net_ctl_obj.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/types.h" + +namespace Libraries::NetCtl { + +using OrbisNetCtlCallback = PS4_SYSV_ABI void (*)(int eventType, void* arg); +using OrbisNetCtlCallbackForNpToolkit = PS4_SYSV_ABI void (*)(int eventType, void* arg); + +struct NetCtlCallback { + OrbisNetCtlCallback func; + void* arg; +}; + +struct NetCtlCallbackForNpToolkit { + OrbisNetCtlCallbackForNpToolkit func; + void* arg; +}; + +class NetCtlInternal { +public: + NetCtlInternal(); + ~NetCtlInternal(); + s32 registerCallback(OrbisNetCtlCallback func, void* arg); + s32 registerNpToolkitCallback(OrbisNetCtlCallbackForNpToolkit func, void* arg); + void checkCallback(); + void checkNpToolkitCallback(); + +public: + std::array nptoolCallbacks; + std::array callbacks; + std::mutex m_mutex; +}; +} // namespace Libraries::NetCtl diff --git a/src/core/libraries/network/net_obj.cpp b/src/core/libraries/network/net_obj.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/libraries/network/net_obj.h b/src/core/libraries/network/net_obj.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index a1c8e81c0..e7a69611e 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -1,9 +1,22 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#ifdef WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +#include +#include +#else +#include +#include +#include +#endif + #include "common/logging/log.h" +#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" +#include "core/libraries/network/net_ctl_codes.h" #include "core/libraries/network/netctl.h" namespace Libraries::NetCtl { @@ -79,7 +92,8 @@ int PS4_SYSV_ABI sceNetCtlUnregisterCallbackV6() { } int PS4_SYSV_ABI sceNetCtlCheckCallback() { - LOG_TRACE(Lib_NetCtl, "(STUBBED) called"); + auto* netctl = Common::Singleton::Instance(); + netctl->checkCallback(); return ORBIS_OK; } @@ -143,8 +157,35 @@ int PS4_SYSV_ABI sceNetCtlGetIfStat() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetCtlGetInfo() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { + switch (code) { + case ORBIS_NET_CTL_INFO_DEVICE: + info->device = ORBIS_NET_CTL_DEVICE_WIRED; + break; + case ORBIS_NET_CTL_INFO_LINK: + info->link = ORBIS_NET_CTL_LINK_DISCONNECTED; + break; + case ORBIS_NET_CTL_INFO_IP_ADDRESS: { + strcpy(info->ip_address, + "127.0.0.1"); // placeholder in case gethostbyname can't find another ip + char devname[80]; + gethostname(devname, 80); + struct hostent* resolved = gethostbyname(devname); + for (int i = 0; resolved->h_addr_list[i] != nullptr; ++i) { + struct in_addr addrIn; + memcpy(&addrIn, resolved->h_addr_list[i], sizeof(u32)); + char* addr = inet_ntoa(addrIn); + if (strcmp(addr, "127.0.0.1") != 0) { + strcpy(info->ip_address, addr); + break; + } + } + break; + } + default: + LOG_ERROR(Lib_NetCtl, "{} unsupported code", code); + } + LOG_DEBUG(Lib_NetCtl, "(STUBBED) called"); return ORBIS_OK; } @@ -173,8 +214,12 @@ int PS4_SYSV_ABI sceNetCtlGetNetEvConfigInfoIpcInt() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetCtlGetResult() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetCtlGetResult(int eventType, int* errorCode) { + if (!errorCode) { + return ORBIS_NET_CTL_ERROR_INVALID_ADDR; + } + LOG_DEBUG(Lib_NetCtl, "(STUBBED) called eventType = {} ", eventType); + *errorCode = 0; return ORBIS_OK; } @@ -213,8 +258,8 @@ int PS4_SYSV_ABI sceNetCtlGetScanInfoForSsidScanIpcInt() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetCtlGetState() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetCtlGetState(int* state) { + *state = ORBIS_NET_CTL_STATE_DISCONNECTED; return ORBIS_OK; } @@ -248,8 +293,17 @@ int PS4_SYSV_ABI sceNetCtlIsBandwidthManagementEnabledIpcInt() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetCtlRegisterCallback() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetCtlRegisterCallback(OrbisNetCtlCallback func, void* arg, int* cid) { + if (!func || !cid) { + return ORBIS_NET_CTL_ERROR_INVALID_ADDR; + } + auto* netctl = Common::Singleton::Instance(); + s32 result = netctl->registerCallback(func, arg); + if (result < 0) { + return result; + } else { + *cid = result; + } return ORBIS_OK; } @@ -319,7 +373,8 @@ int PS4_SYSV_ABI Func_D8DCB6973537A3DC() { } int PS4_SYSV_ABI sceNetCtlCheckCallbackForNpToolkit() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); + auto* netctl = Common::Singleton::Instance(); + netctl->checkNpToolkitCallback(); return ORBIS_OK; } @@ -328,8 +383,18 @@ int PS4_SYSV_ABI sceNetCtlClearEventForNpToolkit() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetCtlRegisterCallbackForNpToolkit() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetCtlRegisterCallbackForNpToolkit(OrbisNetCtlCallbackForNpToolkit func, + void* arg, int* cid) { + if (!func || !cid) { + return ORBIS_NET_CTL_ERROR_INVALID_ADDR; + } + auto* netctl = Common::Singleton::Instance(); + s32 result = netctl->registerNpToolkitCallback(func, arg); + if (result < 0) { + return result; + } else { + *cid = result; + } return ORBIS_OK; } diff --git a/src/core/libraries/network/netctl.h b/src/core/libraries/network/netctl.h index 0d6adf9c1..89ba34c31 100644 --- a/src/core/libraries/network/netctl.h +++ b/src/core/libraries/network/netctl.h @@ -4,6 +4,7 @@ #pragma once #include "common/types.h" +#include "net_ctl_obj.h" namespace Core::Loader { class SymbolsResolver; @@ -11,6 +12,46 @@ class SymbolsResolver; namespace Libraries::NetCtl { +constexpr int ORBIS_NET_ETHER_ADDR_LEN = 6; + +struct OrbisNetEtherAddr { + u8 data[ORBIS_NET_ETHER_ADDR_LEN]; +}; + +constexpr int ORBIS_NET_CTL_SSID_LEN = 32 + 1; +constexpr int ORBIS_NET_CTL_HOSTNAME_LEN = 255 + 1; +constexpr int ORBIS_NET_CTL_AUTH_NAME_LEN = 127 + 1; +constexpr int ORBIS_NET_CTL_IPV4_ADDR_STR_LEN = 16; + +typedef union OrbisNetCtlInfo { + u32 device; + OrbisNetEtherAddr ether_addr; + u32 mtu; + u32 link; + OrbisNetEtherAddr bssid; + char ssid[ORBIS_NET_CTL_SSID_LEN]; + u32 wifi_security; + u8 rssi_dbm; + uint8_t rssi_percentage; + u8 channel; + u32 ip_config; + char dhcp_hostname[ORBIS_NET_CTL_HOSTNAME_LEN]; + char pppoe_auth_name[ORBIS_NET_CTL_AUTH_NAME_LEN]; + char ip_address[ORBIS_NET_CTL_IPV4_ADDR_STR_LEN]; + char netmask[ORBIS_NET_CTL_IPV4_ADDR_STR_LEN]; + char default_route[ORBIS_NET_CTL_IPV4_ADDR_STR_LEN]; + char primary_dns[ORBIS_NET_CTL_IPV4_ADDR_STR_LEN]; + char secondary_dns[ORBIS_NET_CTL_IPV4_ADDR_STR_LEN]; + u32 http_proxy_config; + char http_proxy_server[ORBIS_NET_CTL_HOSTNAME_LEN]; + u16 http_proxy_port; +} SceNetCtlInfo; + +// GetInfo codes +constexpr int ORBIS_NET_CTL_INFO_DEVICE = 1; +constexpr int ORBIS_NET_CTL_INFO_LINK = 4; +constexpr int ORBIS_NET_CTL_INFO_IP_ADDRESS = 14; + int PS4_SYSV_ABI sceNetBweCheckCallbackIpcInt(); int PS4_SYSV_ABI sceNetBweClearEventIpcInt(); int PS4_SYSV_ABI sceNetBweFinishInternetConnectionTestIpcInt(); @@ -38,13 +79,13 @@ int PS4_SYSV_ABI sceNetCtlEnableBandwidthManagementIpcInt(); int PS4_SYSV_ABI sceNetCtlGetBandwidthInfoIpcInt(); int PS4_SYSV_ABI sceNetCtlGetEtherLinkMode(); int PS4_SYSV_ABI sceNetCtlGetIfStat(); -int PS4_SYSV_ABI sceNetCtlGetInfo(); +int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info); int PS4_SYSV_ABI sceNetCtlGetInfoIpcInt(); int PS4_SYSV_ABI sceNetCtlGetInfoV6IpcInt(); int PS4_SYSV_ABI sceNetCtlGetNatInfo(); int PS4_SYSV_ABI sceNetCtlGetNatInfoIpcInt(); int PS4_SYSV_ABI sceNetCtlGetNetEvConfigInfoIpcInt(); -int PS4_SYSV_ABI sceNetCtlGetResult(); +int PS4_SYSV_ABI sceNetCtlGetResult(int eventType, int* errorCode); int PS4_SYSV_ABI sceNetCtlGetResultIpcInt(); int PS4_SYSV_ABI sceNetCtlGetResultV6IpcInt(); int PS4_SYSV_ABI sceNetCtlGetScanInfoBssidForSsidListScanIpcInt(); @@ -52,14 +93,14 @@ int PS4_SYSV_ABI sceNetCtlGetScanInfoBssidIpcInt(); int PS4_SYSV_ABI sceNetCtlGetScanInfoByBssidIpcInt(); int PS4_SYSV_ABI sceNetCtlGetScanInfoForSsidListScanIpcInt(); int PS4_SYSV_ABI sceNetCtlGetScanInfoForSsidScanIpcInt(); -int PS4_SYSV_ABI sceNetCtlGetState(); +int PS4_SYSV_ABI sceNetCtlGetState(int* state); int PS4_SYSV_ABI sceNetCtlGetState2IpcInt(); int PS4_SYSV_ABI sceNetCtlGetStateIpcInt(); int PS4_SYSV_ABI sceNetCtlGetStateV6IpcInt(); int PS4_SYSV_ABI sceNetCtlGetWifiType(); int PS4_SYSV_ABI sceNetCtlInit(); int PS4_SYSV_ABI sceNetCtlIsBandwidthManagementEnabledIpcInt(); -int PS4_SYSV_ABI sceNetCtlRegisterCallback(); +int PS4_SYSV_ABI sceNetCtlRegisterCallback(OrbisNetCtlCallback func, void* arg, int* cid); int PS4_SYSV_ABI sceNetCtlRegisterCallbackForLibIpcInt(); int PS4_SYSV_ABI sceNetCtlRegisterCallbackIpcInt(); int PS4_SYSV_ABI sceNetCtlRegisterCallbackV6IpcInt(); @@ -75,7 +116,8 @@ int PS4_SYSV_ABI sceNetCtlUnsetStunWithPaddingFlagIpcInt(); int PS4_SYSV_ABI Func_D8DCB6973537A3DC(); int PS4_SYSV_ABI sceNetCtlCheckCallbackForNpToolkit(); int PS4_SYSV_ABI sceNetCtlClearEventForNpToolkit(); -int PS4_SYSV_ABI sceNetCtlRegisterCallbackForNpToolkit(); +int PS4_SYSV_ABI sceNetCtlRegisterCallbackForNpToolkit(OrbisNetCtlCallbackForNpToolkit func, + void* arg, int* cid); int PS4_SYSV_ABI sceNetCtlUnregisterCallbackForNpToolkit(); int PS4_SYSV_ABI sceNetCtlApCheckCallback(); int PS4_SYSV_ABI sceNetCtlApClearEvent(); diff --git a/src/core/libraries/ngs2/ngs2_error.h b/src/core/libraries/ngs2/ngs2_error.h index 254ae26e6..2773168e2 100644 --- a/src/core/libraries/ngs2/ngs2_error.h +++ b/src/core/libraries/ngs2/ngs2_error.h @@ -3,54 +3,116 @@ #pragma once -constexpr int ORBIS_NGS2_ERROR_INVALID_PARAMETERS = 0x804A0001; -constexpr int ORBIS_NGS2_ERROR_INVALID_MAXIMUM_GRAIN_SAMPLES = 0x804A0050; -constexpr int ORBIS_NGS2_ERROR_INVALID_GRAIN_SAMPLES = 0x804A0051; -constexpr int ORBIS_NGS2_ERROR_INVALID_CHANNELS = 0x804A0052; -constexpr int ORBIS_NGS2_ERROR_INVALD_ADDRESS = 0x804A0053; -constexpr int ORBIS_NGS2_ERROR_INVALD_SIZE = 0x804A0054; +constexpr int ORBIS_NGS2_ERROR_FAIL = 0x804A0001; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES = 0x804A0050; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES = 0x804A0051; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_CHANNELS = 0x804A0052; +constexpr int ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS = 0x804A0053; +constexpr int ORBIS_NGS2_ERROR_INVALID_OUT_SIZE = 0x804A0054; +constexpr int ORBIS_NGS2_ERROR_INVALID_OPTION_ADDRESS = 0x804A0080; constexpr int ORBIS_NGS2_ERROR_INVALID_OPTION_SIZE = 0x804A0081; -constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_OPTION_MAX_MATRICES = 0x804A0100; -constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_OPTION_MAX_PORTS = 0x804A0101; -constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_OPTION_MAX_INPUT_DELAY_BLOCKS = 0x804A0102; -constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_LEVELS = 0x804A0150; -constexpr int ORBIS_NGS2_ERROR_SAMPLER_WAVEFORM_TERMINATED = 0x804A0151; -constexpr int ORBIS_NGS2_ERROR_INVALID_ENVELOPE_POINTS = 0x804A0152; +constexpr int ORBIS_NGS2_ERROR_INVALID_OPTION_FLAG = 0x804A0082; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_MATRICES = 0x804A0100; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_PORTS = 0x804A0101; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_INPUT_DELAY_BLOCKS = 0x804A0102; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_VOICES = 0x804A0103; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CHANNELS = 0x804A0104; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CHANNEL_WORKS = 0x804A0105; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_WAVEFORM_BLOCKS = 0x804A0106; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_ENVELOPE_POINTS = 0x804A0107; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_FILTERS = 0x804A0108; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CODEC_CACHES = 0x804A0109; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_ATRAC9_DECODERS = 0x804A010A; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_ATRAC9_CHANNEL_WORKS = 0x804A010B; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_INPUTS = 0x804A010C; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_MATRIX_LEVELS = 0x804A0150; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_WAVEFORM_BLOCKS = 0x804A0151; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_ENVELOPE_POINTS = 0x804A0152; constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_LEVEL_ADDRESS = 0x804A0153; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_BLOCK_ADDRESS = 0x804A0154; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_BLOCK_ADDRESS = 0x804A0154; constexpr int ORBIS_NGS2_ERROR_INVALID_ENVELOPE_POINT_ADDRESS = 0x804A0155; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_PEAKMETER_BLOCKS = 0x804A0156; constexpr int ORBIS_NGS2_ERROR_INVALID_HANDLE = 0x804A0200; constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLE_RATE = 0x804A0201; +constexpr int ORBIS_NGS2_ERROR_INVALID_REPORT_TYPE = 0x804A0202; +constexpr int ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLER = 0x804A0203; constexpr int ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE = 0x804A0204; +constexpr int ORBIS_NGS2_ERROR_EMPTY_REPORT_HANDLE = 0x804A0205; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_INFO = 0x804A0206; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ADDRESS = 0x804A0207; -constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ALIGNMENT = 0x804A0208; +constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ALIGN = 0x804A0208; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE = 0x804A0209; constexpr int ORBIS_NGS2_ERROR_INVALID_BUFFER_ALLOCATOR = 0x804A020A; -constexpr int ORBIS_NGS2_ERROR_BUFFER_VERIFY_FAILED = 0x804A020B; -constexpr int ORBIS_NGS2_ERROR_MODULE_PLAYER_DATA_EMPTY = 0x804A020C; +constexpr int ORBIS_NGS2_ERROR_BUFFER_BROKEN = 0x804A020B; +constexpr int ORBIS_NGS2_ERROR_EMPTY_BUFFER = 0x804A020C; constexpr int ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE = 0x804A0230; constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_ID = 0x804A0260; constexpr int ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE = 0x804A0261; constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE = 0x804A0300; +constexpr int ORBIS_NGS2_ERROR_UNINIT_VOICE = 0x804A0301; constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_INDEX = 0x804A0302; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_EVENT = 0x804A0303; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_PORT_INDEX = 0x804A0304; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_INPUT_OR_RACK_OCCUPIED = 0x804A0305; -constexpr int ORBIS_NGS2_ERROR_INVALID_CONTROL_ID = 0x804A0308; -constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_PARAMETER = 0x804A0309; -constexpr int ORBIS_NGS2_ERROR_INVALID_PARAMETER_SIZE = 0x804A030A; +constexpr int ORBIS_NGS2_ERROR_INVALID_EVENT_TYPE = 0x804A0303; +constexpr int ORBIS_NGS2_ERROR_INVALID_PORT_INDEX = 0x804A0304; +constexpr int ORBIS_NGS2_ERROR_INVALID_PATCH = 0x804A0305; +constexpr int ORBIS_NGS2_ERROR_EMPTY_CHANNEL_WORK = 0x804A0306; +constexpr int ORBIS_NGS2_ERROR_EMPTY_CODEC_DECODER = 0x804A0307; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_ID = 0x804A0308; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_ADDRESS = 0x804A0309; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_CONTROL_SIZE = 0x804A030A; constexpr int ORBIS_NGS2_ERROR_DETECTED_CIRCULAR_VOICE_CONTROL = 0x804A030B; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_DATA = 0x804A0400; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_FORMAT = 0x804A0401; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_TYPE_NO_ATRAC9_DECODERS = 0x804A0402; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_ATRAC9_CONFIG_DATA = 0x804A0403; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_SAMPLE_RATE = 0x804A0404; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_FRAME = 0x804A0405; -constexpr int ORBIS_NGS2_ERROR_INVALID_SAMPLER_WAVEFORM_ADDRESS = 0x804A0406; +constexpr int ORBIS_NGS2_ERROR_UNABLE_CALLBACK = 0x804A030C; +constexpr int ORBIS_NGS2_ERROR_INVALID_CALLBACK_FLAG = 0x804A030D; +constexpr int ORBIS_NGS2_ERROR_INVALID_CALLBACK_HANDLER = 0x804A030E; +constexpr int ORBIS_NGS2_ERROR_INVALID_OPERATION = 0x804A030F; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_FORMAT = 0x804A0400; +constexpr int ORBIS_NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT = 0x804A0401; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_TYPE = 0x804A0402; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_CONFIG = 0x804A0403; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_SAMPLE_RATE = 0x804A0404; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_FRAME = 0x804A0405; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_ADDRESS = 0x804A0406; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_SIZE = 0x804A0407; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_DATA = 0x804A0408; +constexpr int ORBIS_NGS2_ERROR_INVALID_WAVEFORM_BLOCK_NUM_REPEATS = 0x804A0409; constexpr int ORBIS_NGS2_ERROR_INVALID_ENVELOPE_CURVE = 0x804A0500; +constexpr int ORBIS_NGS2_ERROR_INVALID_PEAKMETER_FLAG = 0x804A0510; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_CHORUS_PHASES = 0x804A0520; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_CHORUS_PHASES = 0x804A0521; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_DELAY_LENGTH = 0x804A0530; +constexpr int ORBIS_NGS2_ERROR_INVALID_MAX_DELAY_TAPS = 0x804A0531; +constexpr int ORBIS_NGS2_ERROR_INVALID_DELAY_TYPE = 0x804A0532; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_DELAY_TAPS = 0x804A0533; +constexpr int ORBIS_NGS2_ERROR_INVALID_DELAY_TAP_INFO = 0x804A0534; +constexpr int ORBIS_NGS2_ERROR_INVALID_PITCH_SHIFT_QUALITY = 0x804A0540; constexpr int ORBIS_NGS2_ERROR_INVALID_FILTER_INDEX = 0x804A0600; constexpr int ORBIS_NGS2_ERROR_INVALID_FILTER_TYPE = 0x804A0601; constexpr int ORBIS_NGS2_ERROR_INVALID_FILTER_LOCATION = 0x804A0602; -constexpr int ORBIS_NGS2_ERROR_INVALID_LFE_CUT_OFF_FREQUENCY = 0x804A0603; -constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_INDEX_OR_TYPE = 0x804A0700; \ No newline at end of file +constexpr int ORBIS_NGS2_ERROR_INVALID_LFE_FC = 0x804A0603; +constexpr int ORBIS_NGS2_ERROR_INVALID_USER_FX_PARAM_SIZE = 0x804A0650; +constexpr int ORBIS_NGS2_ERROR_INVALID_MATRIX_INDEX = 0x804A0700; +constexpr int ORBIS_NGS2_ERROR_CODEC_UNKNOWN_WAVEFORM = 0x804A0800; +constexpr int ORBIS_NGS2_ERROR_CODEC_EMPTY_INSTANCE = 0x804A0801; +constexpr int ORBIS_NGS2_ERROR_CODEC_EMPTY_CHANNEL = 0x804A0802; +constexpr int ORBIS_NGS2_ERROR_CODEC_SETUP_FAIL = 0x804A0803; +constexpr int ORBIS_NGS2_ERROR_CODEC_RESET_FAIL = 0x804A0804; +constexpr int ORBIS_NGS2_ERROR_CODEC_DECODE_FAIL = 0x804A0805; +constexpr int ORBIS_NGS2_ERROR_INVALID_REVERB_SIZE = 0x804A0900; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_UNIT_ANGLE = 0x804A0910; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_SPEAKER = 0x804A0911; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_MATRIX_FORMAT = 0x804A0912; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_WORK = 0x804A0913; +constexpr int ORBIS_NGS2_ERROR_INVALID_PAN_PARAM = 0x804A0914; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_DISTANCE = 0x804A0920; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_LISTENER_ADDRESS = 0x804A0921; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_SOURCE_ADDRESS = 0x804A0922; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_FLAG = 0x804A0923; +constexpr int ORBIS_NGS2_ERROR_INVALID_GEOM_CONE = 0x804A0924; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_ID = 0x804A0A00; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_MODULES = 0x804A0A01; +constexpr int ORBIS_NGS2_ERROR_INVALID_NUM_MODULE_BUFFERS = 0x804A0A02; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_BUFFER_ID = 0x804A0A03; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_STATE_OFFSET = 0x804A0A04; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_STATE_SIZE = 0x804A0A05; +constexpr int ORBIS_NGS2_ERROR_INVALID_VOICE_STATE_SIZE = 0x804A0A06; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_INDEX = 0x804A0B00; +constexpr int ORBIS_NGS2_ERROR_INVALID_MODULE_INFO_SIZE = 0x804A0B01; \ No newline at end of file diff --git a/src/core/libraries/ngs2/ngs2_impl.cpp b/src/core/libraries/ngs2/ngs2_impl.cpp index 50c62f5e4..793435d83 100644 --- a/src/core/libraries/ngs2/ngs2_impl.cpp +++ b/src/core/libraries/ngs2/ngs2_impl.cpp @@ -138,13 +138,13 @@ s32 Ngs2::SystemSetupCore(StackBuffer* buf, SystemOptions* options, Ngs2Handle** // Validate maxGrainSamples if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 0x3F) != 0) { LOG_ERROR(Lib_Ngs2, "Invalid system option (maxGrainSamples={},x64)", maxGrainSamples); - return ORBIS_NGS2_ERROR_INVALID_MAXIMUM_GRAIN_SAMPLES; + return ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES; } // Validate numGrainSamples if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 0x3F) != 0) { LOG_ERROR(Lib_Ngs2, "Invalid system option (numGrainSamples={},x64)", numGrainSamples); - return ORBIS_NGS2_ERROR_INVALID_GRAIN_SAMPLES; + return ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES; } // Validate sampleRate diff --git a/src/core/libraries/np_manager/np_manager.cpp b/src/core/libraries/np_manager/np_manager.cpp index c657fbf60..4fff59003 100644 --- a/src/core/libraries/np_manager/np_manager.cpp +++ b/src/core/libraries/np_manager/np_manager.cpp @@ -1,7 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator +#include +#include #include "common/config.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" @@ -875,11 +876,6 @@ int PS4_SYSV_ABI sceNpCheckCallback() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpCheckCallbackForLib() { - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); - return ORBIS_OK; -} - int PS4_SYSV_ABI sceNpCheckNpAvailability() { LOG_ERROR(Lib_NpManager, "(STUBBED) called"); return ORBIS_OK; @@ -906,12 +902,13 @@ int PS4_SYSV_ABI sceNpCreateAsyncRequest() { } int PS4_SYSV_ABI sceNpCreateRequest() { - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); - return ORBIS_OK; + LOG_ERROR(Lib_NpManager, "(DUMMY) called"); + static int id = 0; + return ++id; } -int PS4_SYSV_ABI sceNpDeleteRequest() { - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); +int PS4_SYSV_ABI sceNpDeleteRequest(int reqId) { + LOG_ERROR(Lib_NpManager, "(DUMMY) called reqId = {}", reqId); return ORBIS_OK; } @@ -976,9 +973,10 @@ int PS4_SYSV_ABI sceNpGetGamePresenceStatusA() { } int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId userId, OrbisNpId* npId) { - LOG_ERROR(Lib_NpManager, "(DUMMY) called"); - + LOG_INFO(Lib_NpManager, "userId {}", userId); std::string name = Config::getUserName(); + // Fill the unused stuffs to 0 + memset(npId, 0, sizeof(*npId)); strcpy(npId->handle.data, name.c_str()); return ORBIS_OK; } @@ -988,8 +986,12 @@ int PS4_SYSV_ABI sceNpGetNpReachabilityState() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpGetOnlineId() { - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); +int PS4_SYSV_ABI sceNpGetOnlineId(s32 userId, OrbisNpOnlineId* onlineId) { + LOG_DEBUG(Lib_NpManager, "userId {}", userId); + std::string name = Config::getUserName(); + // Fill the unused stuffs to 0 + memset(onlineId, 0, sizeof(*onlineId)); + strcpy(onlineId->data, name.c_str()); return ORBIS_OK; } @@ -1003,8 +1005,9 @@ int PS4_SYSV_ABI sceNpGetParentalControlInfoA() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpGetState() { - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); +int PS4_SYSV_ABI sceNpGetState(s32 userId, OrbisNpState* state) { + *state = ORBIS_NP_STATE_SIGNED_OUT; + LOG_DEBUG(Lib_NpManager, "Signed out"); return ORBIS_OK; } @@ -2508,11 +2511,30 @@ int PS4_SYSV_ABI Func_FF966E4351E564D6() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpRegisterStateCallbackForToolkit() { - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); +struct NpStateCallbackForNpToolkit { + OrbisNpStateCallbackForNpToolkit func; + void* userdata; +}; + +NpStateCallbackForNpToolkit NpStateCbForNp; + +int PS4_SYSV_ABI sceNpCheckCallbackForLib() { + // LOG_ERROR(Lib_NpManager, "(STUBBED) called"); + const auto* linker = Common::Singleton::Instance(); + linker->ExecuteGuest(NpStateCbForNp.func, 1, ORBIS_NP_STATE_SIGNED_OUT, + NpStateCbForNp.userdata); return ORBIS_OK; } +int PS4_SYSV_ABI sceNpRegisterStateCallbackForToolkit(OrbisNpStateCallbackForNpToolkit callback, + void* userdata) { + static int id = 0; + LOG_ERROR(Lib_NpManager, "(STUBBED) called"); + NpStateCbForNp.func = callback; + NpStateCbForNp.userdata = userdata; + return id; +} + int PS4_SYSV_ABI sceNpUnregisterStateCallbackForToolkit() { LOG_ERROR(Lib_NpManager, "(STUBBED) called"); return ORBIS_OK; diff --git a/src/core/libraries/np_manager/np_manager.h b/src/core/libraries/np_manager/np_manager.h index 5955a40b4..7e906cdc8 100644 --- a/src/core/libraries/np_manager/np_manager.h +++ b/src/core/libraries/np_manager/np_manager.h @@ -11,6 +11,17 @@ class SymbolsResolver; namespace Libraries::NpManager { +constexpr int ORBIS_NP_ERROR_SIGNED_OUT = 0x80550006; + +enum OrbisNpState { + ORBIS_NP_STATE_UNKNOWN = 0, + ORBIS_NP_STATE_SIGNED_OUT, + ORBIS_NP_STATE_SIGNED_IN +}; + +using OrbisNpStateCallbackForNpToolkit = PS4_SYSV_ABI void (*)(s32 userId, OrbisNpState state, + void* userdata); + constexpr int ORBIS_NP_ONLINEID_MAX_LENGTH = 16; typedef int OrbisUserServiceUserId; @@ -207,7 +218,7 @@ int PS4_SYSV_ABI sceNpCheckNpReachability(); int PS4_SYSV_ABI sceNpCheckPlus(); int PS4_SYSV_ABI sceNpCreateAsyncRequest(); int PS4_SYSV_ABI sceNpCreateRequest(); -int PS4_SYSV_ABI sceNpDeleteRequest(); +int PS4_SYSV_ABI sceNpDeleteRequest(int reqId); int PS4_SYSV_ABI sceNpGetAccountAge(); int PS4_SYSV_ABI sceNpGetAccountCountry(); int PS4_SYSV_ABI sceNpGetAccountCountryA(); @@ -222,10 +233,10 @@ int PS4_SYSV_ABI sceNpGetGamePresenceStatus(); int PS4_SYSV_ABI sceNpGetGamePresenceStatusA(); int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId userId, OrbisNpId* npId); int PS4_SYSV_ABI sceNpGetNpReachabilityState(); -int PS4_SYSV_ABI sceNpGetOnlineId(); +int PS4_SYSV_ABI sceNpGetOnlineId(s32 userId, OrbisNpOnlineId* onlineId); int PS4_SYSV_ABI sceNpGetParentalControlInfo(); int PS4_SYSV_ABI sceNpGetParentalControlInfoA(); -int PS4_SYSV_ABI sceNpGetState(); +int PS4_SYSV_ABI sceNpGetState(s32 userId, OrbisNpState* state); int PS4_SYSV_ABI sceNpGetUserIdByAccountId(); int PS4_SYSV_ABI sceNpGetUserIdByOnlineId(); int PS4_SYSV_ABI sceNpHasSignedUp(); @@ -526,7 +537,8 @@ int PS4_SYSV_ABI Func_F91B5B25CC9B30D9(); int PS4_SYSV_ABI Func_FC335B7102A585B3(); int PS4_SYSV_ABI Func_FCEAC354CA8B206E(); int PS4_SYSV_ABI Func_FF966E4351E564D6(); -int PS4_SYSV_ABI sceNpRegisterStateCallbackForToolkit(); +int PS4_SYSV_ABI sceNpRegisterStateCallbackForToolkit(OrbisNpStateCallbackForNpToolkit callback, + void* userdata); int PS4_SYSV_ABI sceNpUnregisterStateCallbackForToolkit(); void RegisterlibSceNpManager(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/libraries/np_score/np_score.cpp b/src/core/libraries/np_score/np_score.cpp index d6e4631ce..dc16e12d2 100644 --- a/src/core/libraries/np_score/np_score.cpp +++ b/src/core/libraries/np_score/np_score.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/np_trophy/np_trophy.cpp b/src/core/libraries/np_trophy/np_trophy.cpp index 4b1f43694..e8fd57ef1 100644 --- a/src/core/libraries/np_trophy/np_trophy.cpp +++ b/src/core/libraries/np_trophy/np_trophy.cpp @@ -1,17 +1,21 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include +#include #include "common/logging/log.h" +#include "common/path_util.h" #include "common/slot_vector.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "np_trophy.h" +#include "trophy_ui.h" namespace Libraries::NpTrophy { +std::string game_serial; + static constexpr auto MaxTrophyHandles = 4u; static constexpr auto MaxTrophyContexts = 8u; @@ -25,11 +29,70 @@ struct ContextKeyHash { struct TrophyContext { u32 context_id; }; -static Common::SlotVector trophy_handles{}; +static Common::SlotVector trophy_handles{}; static Common::SlotVector trophy_contexts{}; static std::unordered_map contexts_internal{}; -int PS4_SYSV_ABI sceNpTrophyAbortHandle() { +void ORBIS_NP_TROPHY_FLAG_ZERO(OrbisNpTrophyFlagArray* p) { + for (int i = 0; i < ORBIS_NP_TROPHY_NUM_MAX; i++) { + uint32_t array_index = i / 32; + uint32_t bit_position = i % 32; + + p->flag_bits[array_index] &= ~(1U << bit_position); + } +} + +void ORBIS_NP_TROPHY_FLAG_SET(int32_t trophyId, OrbisNpTrophyFlagArray* p) { + uint32_t array_index = trophyId / 32; + uint32_t bit_position = trophyId % 32; + + p->flag_bits[array_index] |= (1U << bit_position); +} + +void ORBIS_NP_TROPHY_FLAG_SET_ALL(OrbisNpTrophyFlagArray* p) { + for (int i = 0; i < ORBIS_NP_TROPHY_NUM_MAX; i++) { + uint32_t array_index = i / 32; + uint32_t bit_position = i % 32; + + p->flag_bits[array_index] |= (1U << bit_position); + } +} + +void ORBIS_NP_TROPHY_FLAG_CLR(int32_t trophyId, OrbisNpTrophyFlagArray* p) { + uint32_t array_index = trophyId / 32; + uint32_t bit_position = trophyId % 32; + + p->flag_bits[array_index] &= ~(1U << bit_position); +} + +bool ORBIS_NP_TROPHY_FLAG_ISSET(int32_t trophyId, OrbisNpTrophyFlagArray* p) { + uint32_t array_index = trophyId / 32; + uint32_t bit_position = trophyId % 32; + + return (p->flag_bits[array_index] & (1U << bit_position)) ? 1 : 0; +} + +OrbisNpTrophyGrade GetTrophyGradeFromChar(char trophyType) { + switch (trophyType) { + default: + return ORBIS_NP_TROPHY_GRADE_UNKNOWN; + break; + case 'B': + return ORBIS_NP_TROPHY_GRADE_BRONZE; + break; + case 'S': + return ORBIS_NP_TROPHY_GRADE_SILVER; + break; + case 'G': + return ORBIS_NP_TROPHY_GRADE_GOLD; + break; + case 'P': + return ORBIS_NP_TROPHY_GRADE_PLATINUM; + break; + } +} + +int PS4_SYSV_ABI sceNpTrophyAbortHandle(OrbisNpTrophyHandle handle) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } @@ -84,8 +147,8 @@ int PS4_SYSV_ABI sceNpTrophyConfigHasGroupFeature() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceNpTrophyCreateContext(u32* context, u32 user_id, u32 service_label, - u64 options) { +s32 PS4_SYSV_ABI sceNpTrophyCreateContext(OrbisNpTrophyContext* context, int32_t user_id, + uint32_t service_label, uint64_t options) { ASSERT(options == 0ull); if (!context) { return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; @@ -108,7 +171,7 @@ s32 PS4_SYSV_ABI sceNpTrophyCreateContext(u32* context, u32 user_id, u32 service return ORBIS_OK; } -s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(u32* handle) { +s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(OrbisNpTrophyHandle* handle) { if (!handle) { return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; } @@ -123,55 +186,361 @@ s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(u32* handle) { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyDestroyContext() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); +int PS4_SYSV_ABI sceNpTrophyDestroyContext(OrbisNpTrophyContext context) { + LOG_INFO(Lib_NpTrophy, "Destroyed Context {}", context); + + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + + Common::SlotId contextId; + contextId.index = context; + + ContextKey contextkey = trophy_contexts[contextId]; + trophy_contexts.erase(contextId); + contexts_internal.erase(contextkey); + return ORBIS_OK; } -s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(u32 handle) { - if (!trophy_handles.is_allocated({handle})) { +s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(OrbisNpTrophyHandle handle) { + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + + if (!trophy_handles.is_allocated({static_cast(handle)})) { return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; } - trophy_handles.erase({handle}); + trophy_handles.erase({static_cast(handle)}); LOG_INFO(Lib_NpTrophy, "Handle {} destroyed", handle); return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyGetGameIcon() { +int PS4_SYSV_ABI sceNpTrophyGetGameIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + void* buffer, size_t* size) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyGetGameInfo() { +struct GameTrophyInfo { + uint32_t num_groups; + uint32_t num_trophies; + uint32_t num_trophies_by_rarity[5]; + uint32_t unlocked_trophies; + uint32_t unlocked_trophies_by_rarity[5]; +}; + +int PS4_SYSV_ABI sceNpTrophyGetGameInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyGameDetails* details, + OrbisNpTrophyGameData* data) { + LOG_INFO(Lib_NpTrophy, "Getting Game Trophy"); + + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + + if (details == nullptr || data == nullptr) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + if (details->size != 0x4A0 || data->size != 0x20) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + const auto trophy_dir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; + auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); + + if (!result) { + LOG_ERROR(Lib_NpTrophy, "Failed to parse trophy xml : {}", result.description()); + return ORBIS_OK; + } + + GameTrophyInfo game_info{}; + + auto trophyconf = doc.child("trophyconf"); + for (const pugi::xml_node& node : trophyconf.children()) { + std::string_view node_name = node.name(); + + if (node_name == "title-name") { + strncpy(details->title, node.text().as_string(), ORBIS_NP_TROPHY_GAME_TITLE_MAX_SIZE); + } + + if (node_name == "title-detail") { + strncpy(details->description, node.text().as_string(), + ORBIS_NP_TROPHY_GAME_DESCR_MAX_SIZE); + } + + if (node_name == "group") + game_info.num_groups++; + + if (node_name == "trophy") { + bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); + std::string_view current_trophy_grade = node.attribute("ttype").value(); + + if (current_trophy_grade.empty()) { + continue; + } + + game_info.num_trophies++; + int trophy_grade = GetTrophyGradeFromChar(current_trophy_grade.at(0)); + game_info.num_trophies_by_rarity[trophy_grade]++; + + if (current_trophy_unlockstate) { + game_info.unlocked_trophies++; + game_info.unlocked_trophies_by_rarity[trophy_grade]++; + } + } + } + + details->num_groups = game_info.num_groups; + details->num_trophies = game_info.num_trophies; + details->num_platinum = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; + details->num_gold = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; + details->num_silver = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; + details->num_bronze = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; + data->unlocked_trophies = game_info.unlocked_trophies; + data->unlocked_platinum = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; + data->unlocked_gold = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; + data->unlocked_silver = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; + data->unlocked_bronze = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; + + // maybe this should be 1 instead of 100? + data->progress_percentage = 100; + + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceNpTrophyGetGroupIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyGroupId groupId, void* buffer, size_t* size) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyGetGroupIcon() { +struct GroupTrophyInfo { + uint32_t num_trophies; + uint32_t num_trophies_by_rarity[5]; + uint32_t unlocked_trophies; + uint32_t unlocked_trophies_by_rarity[5]; +}; + +int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyGroupId groupId, + OrbisNpTrophyGroupDetails* details, + OrbisNpTrophyGroupData* data) { + LOG_INFO(Lib_NpTrophy, "Getting Trophy Group Info for id {}", groupId); + + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + + if (details == nullptr || data == nullptr) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + if (details->size != 0x4A0 || data->size != 0x28) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + const auto trophy_dir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; + auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + + pugi::xml_document doc; + 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 ORBIS_OK; + } + + GroupTrophyInfo group_info{}; + + auto trophyconf = doc.child("trophyconf"); + for (const pugi::xml_node& node : trophyconf.children()) { + std::string_view node_name = node.name(); + + if (node_name == "group") { + int current_group_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_GROUP_ID); + if (current_group_id != ORBIS_NP_TROPHY_INVALID_GROUP_ID) { + if (current_group_id == groupId) { + std::string_view current_group_name = node.child("name").text().as_string(); + std::string_view current_group_description = + node.child("detail").text().as_string(); + + strncpy(details->title, current_group_name.data(), + ORBIS_NP_TROPHY_GROUP_TITLE_MAX_SIZE); + strncpy(details->description, current_group_description.data(), + ORBIS_NP_TROPHY_GAME_DESCR_MAX_SIZE); + } + } + } + + details->group_id = groupId; + data->group_id = groupId; + + if (node_name == "trophy") { + bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); + std::string_view current_trophy_grade = node.attribute("ttype").value(); + int current_trophy_group_id = node.attribute("gid").as_int(-1); + + if (current_trophy_grade.empty()) { + continue; + } + + if (current_trophy_group_id == groupId) { + group_info.num_trophies++; + int trophyGrade = GetTrophyGradeFromChar(current_trophy_grade.at(0)); + group_info.num_trophies_by_rarity[trophyGrade]++; + if (current_trophy_unlockstate) { + group_info.unlocked_trophies++; + group_info.unlocked_trophies_by_rarity[trophyGrade]++; + } + } + } + } + + details->num_trophies = group_info.num_trophies; + details->num_platinum = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; + details->num_gold = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; + details->num_silver = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; + details->num_bronze = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; + data->unlocked_trophies = group_info.unlocked_trophies; + data->unlocked_platinum = + group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; + data->unlocked_gold = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; + data->unlocked_silver = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; + data->unlocked_bronze = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; + + // maybe this should be 1 instead of 100? + data->progress_percentage = 100; + + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceNpTrophyGetTrophyIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyId trophyId, void* buffer, size_t* size) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyGetGroupInfo() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); +int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyId trophyId, OrbisNpTrophyDetails* details, + OrbisNpTrophyData* data) { + LOG_INFO(Lib_NpTrophy, "Getting trophy info for id {}", trophyId); + + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + + if (trophyId >= 127) + return ORBIS_NP_TROPHY_ERROR_INVALID_TROPHY_ID; + + if (details == nullptr || data == nullptr) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + if (details->size != 0x498 || data->size != 0x18) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + const auto trophy_dir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; + auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + + pugi::xml_document doc; + 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 ORBIS_OK; + } + + auto trophyconf = doc.child("trophyconf"); + + for (const pugi::xml_node& node : trophyconf.children()) { + std::string_view node_name = node.name(); + + if (node_name == "trophy") { + int current_trophy_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); + if (current_trophy_id == trophyId) { + bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); + std::string_view current_trophy_grade = node.attribute("ttype").value(); + std::string_view current_trophy_name = node.child("name").text().as_string(); + std::string_view current_trophy_description = + node.child("detail").text().as_string(); + + uint64_t current_trophy_timestamp = node.attribute("timestamp").as_ullong(); + int current_trophy_groupid = node.attribute("gid").as_int(-1); + bool current_trophy_hidden = node.attribute("hidden").as_bool(); + + details->trophy_id = trophyId; + details->trophy_grade = GetTrophyGradeFromChar(current_trophy_grade.at(0)); + details->group_id = current_trophy_groupid; + details->hidden = current_trophy_hidden; + + strncpy(details->name, current_trophy_name.data(), ORBIS_NP_TROPHY_NAME_MAX_SIZE); + strncpy(details->description, current_trophy_description.data(), + ORBIS_NP_TROPHY_DESCR_MAX_SIZE); + + data->trophy_id = trophyId; + data->unlocked = current_trophy_unlockstate; + data->timestamp.tick = current_trophy_timestamp; + } + } + } + return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyGetTrophyIcon() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); - return ORBIS_OK; -} +s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context, + OrbisNpTrophyHandle handle, + OrbisNpTrophyFlagArray* flags, u32* count) { + LOG_INFO(Lib_NpTrophy, "GetTrophyUnlockState called"); -int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); - return ORBIS_OK; -} + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; -s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, u32* flags, u32* count) { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); - *flags = 0u; - *count = 0; + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + + if (flags == nullptr || count == nullptr) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + ORBIS_NP_TROPHY_FLAG_ZERO(flags); + + const auto trophy_dir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; + auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + + pugi::xml_document doc; + 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; + } + + int num_trophies = 0; + auto trophyconf = doc.child("trophyconf"); + + for (const pugi::xml_node& node : trophyconf.children()) { + std::string_view node_name = node.name(); + int current_trophy_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); + bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); + + if (node_name == "trophy") { + num_trophies++; + } + + if (current_trophy_unlockstate) { + ORBIS_NP_TROPHY_FLAG_SET(current_trophy_id, flags); + } + } + + *count = num_trophies; return ORBIS_OK; } @@ -240,8 +609,16 @@ int PS4_SYSV_ABI sceNpTrophyNumInfoGetTotal() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyRegisterContext() { +int PS4_SYSV_ABI sceNpTrophyRegisterContext(OrbisNpTrophyContext context, + OrbisNpTrophyHandle handle, uint64_t options) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); + + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + return ORBIS_OK; } @@ -255,7 +632,8 @@ int PS4_SYSV_ABI sceNpTrophySetInfoGetTrophyNum() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyShowTrophyList() { +int PS4_SYSV_ABI sceNpTrophyShowTrophyList(OrbisNpTrophyContext context, + OrbisNpTrophyHandle handle) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } @@ -475,8 +853,136 @@ int PS4_SYSV_ABI sceNpTrophySystemSetDbgParamInt() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyUnlockTrophy() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); +int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyId trophyId, OrbisNpTrophyId* platinumId) { + LOG_INFO(Lib_NpTrophy, "Unlocking trophy id {}", trophyId); + + if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + + if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + + if (trophyId >= 127) + return ORBIS_NP_TROPHY_ERROR_INVALID_TROPHY_ID; + + if (platinumId == nullptr) + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + + const auto trophy_dir = + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; + auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); + + if (!result) { + LOG_ERROR(Lib_NpTrophy, "Failed to parse trophy xml : {}", result.description()); + return ORBIS_OK; + } + + *platinumId = ORBIS_NP_TROPHY_INVALID_TROPHY_ID; + + int num_trophies = 0; + int num_trophies_unlocked = 0; + pugi::xml_node platinum_node; + + auto trophyconf = doc.child("trophyconf"); + + for (pugi::xml_node& node : trophyconf.children()) { + int current_trophy_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); + bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); + const char* current_trophy_name = node.child("name").text().as_string(); + std::string_view current_trophy_description = node.child("detail").text().as_string(); + std::string_view current_trophy_type = node.attribute("ttype").value(); + + if (current_trophy_type == "P") { + platinum_node = node; + if (trophyId == current_trophy_id) { + return ORBIS_NP_TROPHY_ERROR_PLATINUM_CANNOT_UNLOCK; + } + } + + if (std::string_view(node.name()) == "trophy") { + if (node.attribute("pid").as_int(-1) != ORBIS_NP_TROPHY_INVALID_TROPHY_ID) { + num_trophies++; + if (current_trophy_unlockstate) { + num_trophies_unlocked++; + } + } + + if (current_trophy_id == trophyId) { + if (current_trophy_unlockstate) { + LOG_INFO(Lib_NpTrophy, "Trophy already unlocked"); + return ORBIS_NP_TROPHY_ERROR_TROPHY_ALREADY_UNLOCKED; + } else { + if (node.attribute("unlockstate").empty()) { + node.append_attribute("unlockstate") = "true"; + } else { + node.attribute("unlockstate").set_value("true"); + } + + Rtc::OrbisRtcTick trophyTimestamp; + Rtc::sceRtcGetCurrentTick(&trophyTimestamp); + + if (node.attribute("timestamp").empty()) { + node.append_attribute("timestamp") = + std::to_string(trophyTimestamp.tick).c_str(); + } else { + node.attribute("timestamp") + .set_value(std::to_string(trophyTimestamp.tick).c_str()); + } + + std::string trophy_icon_file = "TROP"; + trophy_icon_file.append(node.attribute("id").value()); + trophy_icon_file.append(".PNG"); + + std::filesystem::path current_icon_path = + trophy_dir / "trophy00" / "Icons" / trophy_icon_file; + + AddTrophyToQueue(current_icon_path, current_trophy_name); + } + } + } + } + + if (!platinum_node.attribute("unlockstate").as_bool()) { + if ((num_trophies - 1) == num_trophies_unlocked) { + if (platinum_node.attribute("unlockstate").empty()) { + platinum_node.append_attribute("unlockstate") = "true"; + } else { + platinum_node.attribute("unlockstate").set_value("true"); + } + + Rtc::OrbisRtcTick trophyTimestamp; + Rtc::sceRtcGetCurrentTick(&trophyTimestamp); + + if (platinum_node.attribute("timestamp").empty()) { + platinum_node.append_attribute("timestamp") = + std::to_string(trophyTimestamp.tick).c_str(); + } else { + platinum_node.attribute("timestamp") + .set_value(std::to_string(trophyTimestamp.tick).c_str()); + } + + int platinum_trophy_id = + platinum_node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); + const char* platinum_trophy_name = platinum_node.child("name").text().as_string(); + + std::string platinum_icon_file = "TROP"; + platinum_icon_file.append(platinum_node.attribute("id").value()); + platinum_icon_file.append(".PNG"); + + std::filesystem::path platinum_icon_path = + trophy_dir / "trophy00" / "Icons" / platinum_icon_file; + + *platinumId = platinum_trophy_id; + AddTrophyToQueue(platinum_icon_path, platinum_trophy_name); + } + } + + doc.save_file((trophy_dir / "trophy00" / "Xml" / "TROP.XML").native().c_str()); + return ORBIS_OK; } diff --git a/src/core/libraries/np_trophy/np_trophy.h b/src/core/libraries/np_trophy/np_trophy.h index d05d353f1..ac13a9ab7 100644 --- a/src/core/libraries/np_trophy/np_trophy.h +++ b/src/core/libraries/np_trophy/np_trophy.h @@ -4,6 +4,7 @@ #pragma once #include "common/types.h" +#include "core/libraries/rtc/rtc.h" namespace Core::Loader { class SymbolsResolver; @@ -11,7 +12,116 @@ class SymbolsResolver; namespace Libraries::NpTrophy { -int PS4_SYSV_ABI sceNpTrophyAbortHandle(); +extern std::string game_serial; + +constexpr int ORBIS_NP_TROPHY_FLAG_SETSIZE = 128; +constexpr int ORBIS_NP_TROPHY_FLAG_BITS_SHIFT = 5; + +constexpr int ORBIS_NP_TROPHY_GAME_TITLE_MAX_SIZE = 128; +constexpr int ORBIS_NP_TROPHY_GAME_DESCR_MAX_SIZE = 1024; +constexpr int ORBIS_NP_TROPHY_GROUP_TITLE_MAX_SIZE = 128; +constexpr int ORBIS_NP_TROPHY_GROUP_DESCR_MAX_SIZE = 1024; +constexpr int ORBIS_NP_TROPHY_NAME_MAX_SIZE = 128; +constexpr int ORBIS_NP_TROPHY_DESCR_MAX_SIZE = 1024; +constexpr int ORBIS_NP_TROPHY_NUM_MAX = 128; + +constexpr int ORBIS_NP_TROPHY_INVALID_HANDLE = -1; +constexpr int ORBIS_NP_TROPHY_INVALID_CONTEXT = -1; +constexpr int ORBIS_NP_TROPHY_INVALID_TROPHY_ID = -1; + +typedef int32_t OrbisNpTrophyHandle; +typedef int32_t OrbisNpTrophyContext; +typedef int32_t OrbisNpTrophyId; +typedef uint32_t OrbisNpTrophyFlagMask; + +struct OrbisNpTrophyFlagArray { + OrbisNpTrophyFlagMask + flag_bits[ORBIS_NP_TROPHY_FLAG_SETSIZE >> ORBIS_NP_TROPHY_FLAG_BITS_SHIFT]; +}; + +void ORBIS_NP_TROPHY_FLAG_ZERO(OrbisNpTrophyFlagArray* p); +void ORBIS_NP_TROPHY_FLAG_SET(int32_t trophyId, OrbisNpTrophyFlagArray* p); +void ORBIS_NP_TROPHY_FLAG_SET_ALL(OrbisNpTrophyFlagArray* p); +void ORBIS_NP_TROPHY_FLAG_CLR(int32_t trophyId, OrbisNpTrophyFlagArray* p); +bool ORBIS_NP_TROPHY_FLAG_ISSET(int32_t trophyId, OrbisNpTrophyFlagArray* p); + +struct OrbisNpTrophyData { + size_t size; + OrbisNpTrophyId trophy_id; + bool unlocked; + uint8_t reserved[3]; + Rtc::OrbisRtcTick timestamp; +}; + +typedef int32_t OrbisNpTrophyGrade; +constexpr int ORBIS_NP_TROPHY_GRADE_UNKNOWN = 0; +constexpr int ORBIS_NP_TROPHY_GRADE_PLATINUM = 1; +constexpr int ORBIS_NP_TROPHY_GRADE_GOLD = 2; +constexpr int ORBIS_NP_TROPHY_GRADE_SILVER = 3; +constexpr int ORBIS_NP_TROPHY_GRADE_BRONZE = 4; + +typedef int32_t OrbisNpTrophyGroupId; +constexpr int ORBIS_NP_TROPHY_BASE_GAME_GROUP_ID = -1; +constexpr int ORBIS_NP_TROPHY_INVALID_GROUP_ID = -2; + +struct OrbisNpTrophyDetails { + size_t size; + OrbisNpTrophyId trophy_id; + OrbisNpTrophyGrade trophy_grade; + OrbisNpTrophyGroupId group_id; + bool hidden; + uint8_t reserved[3]; + char name[ORBIS_NP_TROPHY_NAME_MAX_SIZE]; + char description[ORBIS_NP_TROPHY_DESCR_MAX_SIZE]; +}; + +struct OrbisNpTrophyGameData { + size_t size; + uint32_t unlocked_trophies; + uint32_t unlocked_platinum; + uint32_t unlocked_gold; + uint32_t unlocked_silver; + uint32_t unlocked_bronze; + uint32_t progress_percentage; +}; + +struct OrbisNpTrophyGameDetails { + size_t size; + uint32_t num_groups; + uint32_t num_trophies; + uint32_t num_platinum; + uint32_t num_gold; + uint32_t num_silver; + uint32_t num_bronze; + char title[ORBIS_NP_TROPHY_GAME_TITLE_MAX_SIZE]; + char description[ORBIS_NP_TROPHY_GAME_DESCR_MAX_SIZE]; +}; + +struct OrbisNpTrophyGroupData { + size_t size; + OrbisNpTrophyGroupId group_id; + uint32_t unlocked_trophies; + uint32_t unlocked_platinum; + uint32_t unlocked_gold; + uint32_t unlocked_silver; + uint32_t unlocked_bronze; + uint32_t progress_percentage; + uint8_t reserved[4]; +}; + +struct OrbisNpTrophyGroupDetails { + size_t size; + OrbisNpTrophyGroupId group_id; + uint32_t num_trophies; + uint32_t num_platinum; + uint32_t num_gold; + uint32_t num_silver; + uint32_t num_bronze; + char title[ORBIS_NP_TROPHY_GROUP_TITLE_MAX_SIZE]; + char description[ORBIS_NP_TROPHY_GROUP_DESCR_MAX_SIZE]; +}; + +int PS4_SYSV_ABI sceNpTrophyAbortHandle(OrbisNpTrophyHandle handle); int PS4_SYSV_ABI sceNpTrophyCaptureScreenshot(); int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyDetails(); int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyFlagArray(); @@ -22,18 +132,30 @@ int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetInfoInGroup(); int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetVersion(); int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyTitleDetails(); int PS4_SYSV_ABI sceNpTrophyConfigHasGroupFeature(); -s32 PS4_SYSV_ABI sceNpTrophyCreateContext(u32* context, u32 user_id, u32 service_label, - u64 options); -s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(u32* handle); -int PS4_SYSV_ABI sceNpTrophyDestroyContext(); -s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(u32 handle); -int PS4_SYSV_ABI sceNpTrophyGetGameIcon(); -int PS4_SYSV_ABI sceNpTrophyGetGameInfo(); -int PS4_SYSV_ABI sceNpTrophyGetGroupIcon(); -int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(); -int PS4_SYSV_ABI sceNpTrophyGetTrophyIcon(); -int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(); -s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, u32* flags, u32* count); +s32 PS4_SYSV_ABI sceNpTrophyCreateContext(OrbisNpTrophyContext* context, int32_t user_id, + uint32_t service_label, uint64_t options); +s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(OrbisNpTrophyHandle* handle); +int PS4_SYSV_ABI sceNpTrophyDestroyContext(OrbisNpTrophyContext context); +s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(OrbisNpTrophyHandle handle); +int PS4_SYSV_ABI sceNpTrophyGetGameIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + void* buffer, size_t* size); +int PS4_SYSV_ABI sceNpTrophyGetGameInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyGameDetails* details, + OrbisNpTrophyGameData* data); +int PS4_SYSV_ABI sceNpTrophyGetGroupIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyGroupId groupId, void* buffer, size_t* size); +int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyGroupId groupId, + OrbisNpTrophyGroupDetails* details, + OrbisNpTrophyGroupData* data); +int PS4_SYSV_ABI sceNpTrophyGetTrophyIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyId trophyId, void* buffer, size_t* size); +int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyId trophyId, OrbisNpTrophyDetails* details, + OrbisNpTrophyData* data); +s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context, + OrbisNpTrophyHandle handle, + OrbisNpTrophyFlagArray* flags, u32* count); int PS4_SYSV_ABI sceNpTrophyGroupArrayGetNum(); int PS4_SYSV_ABI sceNpTrophyIntAbortHandle(); int PS4_SYSV_ABI sceNpTrophyIntCheckNetSyncTitles(); @@ -47,10 +169,12 @@ int PS4_SYSV_ABI sceNpTrophyIntGetTrpIconByUri(); int PS4_SYSV_ABI sceNpTrophyIntNetSyncTitle(); int PS4_SYSV_ABI sceNpTrophyIntNetSyncTitles(); int PS4_SYSV_ABI sceNpTrophyNumInfoGetTotal(); -int PS4_SYSV_ABI sceNpTrophyRegisterContext(); +int PS4_SYSV_ABI sceNpTrophyRegisterContext(OrbisNpTrophyContext context, + OrbisNpTrophyHandle handle, uint64_t options); int PS4_SYSV_ABI sceNpTrophySetInfoGetTrophyFlagArray(); int PS4_SYSV_ABI sceNpTrophySetInfoGetTrophyNum(); -int PS4_SYSV_ABI sceNpTrophyShowTrophyList(); +int PS4_SYSV_ABI sceNpTrophyShowTrophyList(OrbisNpTrophyContext context, + OrbisNpTrophyHandle handle); int PS4_SYSV_ABI sceNpTrophySystemAbortHandle(); int PS4_SYSV_ABI sceNpTrophySystemBuildGroupIconUri(); int PS4_SYSV_ABI sceNpTrophySystemBuildNetTrophyIconUri(); @@ -94,7 +218,8 @@ int PS4_SYSV_ABI sceNpTrophySystemRemoveTitleData(); int PS4_SYSV_ABI sceNpTrophySystemRemoveUserData(); int PS4_SYSV_ABI sceNpTrophySystemSetDbgParam(); int PS4_SYSV_ABI sceNpTrophySystemSetDbgParamInt(); -int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(); +int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, + OrbisNpTrophyId trophyId, OrbisNpTrophyId* platinumId); int PS4_SYSV_ABI Func_149656DA81D41C59(); int PS4_SYSV_ABI Func_9F80071876FFA5F6(); int PS4_SYSV_ABI Func_F8EF6F5350A91990(); diff --git a/src/core/libraries/np_trophy/trophy_ui.cpp b/src/core/libraries/np_trophy/trophy_ui.cpp new file mode 100644 index 000000000..618f8db46 --- /dev/null +++ b/src/core/libraries/np_trophy/trophy_ui.cpp @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include "common/assert.h" +#include "common/singleton.h" +#include "imgui/imgui_std.h" +#include "trophy_ui.h" + +using namespace ImGui; +namespace Libraries::NpTrophy { + +std::optional current_trophy_ui; +std::queue trophy_queue; +std::mutex queueMtx; + +TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName) + : trophy_name(trophyName) { + if (std::filesystem::exists(trophyIconPath)) { + trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath); + } else { + LOG_ERROR(Lib_NpTrophy, "Couldnt load trophy icon at {}", + fmt::UTF(trophyIconPath.u8string())); + } + AddLayer(this); +} + +TrophyUI::~TrophyUI() { + Finish(); +} + +void TrophyUI::Finish() { + RemoveLayer(this); +} + +void TrophyUI::Draw() { + const auto& io = GetIO(); + + const ImVec2 window_size{ + std::min(io.DisplaySize.x, 250.f), + std::min(io.DisplaySize.y, 70.f), + }; + + SetNextWindowSize(window_size); + SetNextWindowCollapsed(false); + SetNextWindowPos(ImVec2(io.DisplaySize.x - 250, 50)); + KeepNavHighlight(); + + if (Begin("Trophy Window", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoInputs)) { + if (trophy_icon) { + Image(trophy_icon.GetTexture().im_id, ImVec2(50, 50)); + ImGui::SameLine(); + } else { + // placeholder + const auto pos = GetCursorScreenPos(); + ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f}, + GetColorU32(ImVec4{0.7f})); + ImGui::Indent(60); + } + TextWrapped("Trophy earned!\n%s", trophy_name.c_str()); + } + End(); + + trophy_timer -= io.DeltaTime; + if (trophy_timer <= 0) { + std::lock_guard lock(queueMtx); + if (!trophy_queue.empty()) { + TrophyInfo next_trophy = trophy_queue.front(); + trophy_queue.pop(); + current_trophy_ui.emplace(next_trophy.trophy_icon_path, next_trophy.trophy_name); + } else { + current_trophy_ui.reset(); + } + } +} + +void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName) { + std::lock_guard lock(queueMtx); + if (current_trophy_ui.has_value()) { + TrophyInfo new_trophy; + new_trophy.trophy_icon_path = trophyIconPath; + new_trophy.trophy_name = trophyName; + trophy_queue.push(new_trophy); + } else { + current_trophy_ui.emplace(trophyIconPath, trophyName); + } +} + +} // namespace Libraries::NpTrophy \ No newline at end of file diff --git a/src/core/libraries/np_trophy/trophy_ui.h b/src/core/libraries/np_trophy/trophy_ui.h new file mode 100644 index 000000000..ce7a1c63a --- /dev/null +++ b/src/core/libraries/np_trophy/trophy_ui.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#include "common/fixed_value.h" +#include "common/types.h" +#include "core/libraries/np_trophy/np_trophy.h" +#include "imgui/imgui_layer.h" +#include "imgui/imgui_texture.h" + +namespace Libraries::NpTrophy { + +class TrophyUI final : public ImGui::Layer { +public: + TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName); + ~TrophyUI() override; + + void Finish(); + + void Draw() override; + +private: + std::string trophy_name; + float trophy_timer = 5.0f; + ImGui::RefCountedTexture trophy_icon; +}; + +struct TrophyInfo { + std::filesystem::path trophy_icon_path; + std::string trophy_name; +}; + +void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName); + +}; // namespace Libraries::NpTrophy \ No newline at end of file diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index 305b20bd6..d786647c2 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -1,10 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator -#include -#include +#include "common/assert.h" +#include "common/config.h" #include "common/logging/log.h" +#include "common/singleton.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "input/controller.h" @@ -25,6 +25,9 @@ int PS4_SYSV_ABI scePadConnectPort() { int PS4_SYSV_ABI scePadDeviceClassGetExtendedInformation( s32 handle, OrbisPadDeviceClassExtendedInformation* pExtInfo) { LOG_ERROR(Lib_Pad, "(STUBBED) called"); + if (Config::getUseSpecialPad()) { + pExtInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass(); + } return ORBIS_OK; } @@ -85,7 +88,7 @@ int PS4_SYSV_ABI scePadGetCapability() { } int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerInformation* pInfo) { - LOG_INFO(Lib_Pad, "called handle = {}", handle); + LOG_DEBUG(Lib_Pad, "called handle = {}", handle); if (handle < 0) { pInfo->touchPadInfo.pixelDensity = 1; pInfo->touchPadInfo.resolution.x = 1920; @@ -107,6 +110,10 @@ int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerIn pInfo->connectedCount = 1; pInfo->connected = true; pInfo->deviceClass = ORBIS_PAD_DEVICE_CLASS_STANDARD; + if (Config::getUseSpecialPad()) { + pInfo->connectionType = ORBIS_PAD_PORT_TYPE_SPECIAL; + pInfo->deviceClass = (OrbisPadDeviceClass)Config::getSpecialPadClass(); + } return SCE_OK; } @@ -239,11 +246,26 @@ int PS4_SYSV_ABI scePadMbusTerm() { int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam) { LOG_INFO(Lib_Pad, "(DUMMY) called user_id = {} type = {} index = {}", userId, type, index); + if (Config::getUseSpecialPad()) { + if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; + } else { + if (type != ORBIS_PAD_PORT_TYPE_STANDARD && type != ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL) + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; + } return 1; // dummy } -int PS4_SYSV_ABI scePadOpenExt() { +int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, + const OrbisPadOpenExtParam* pParam) { LOG_ERROR(Lib_Pad, "(STUBBED) called"); + if (Config::getUseSpecialPad()) { + if (type != ORBIS_PAD_PORT_TYPE_SPECIAL) + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; + } else { + if (type != ORBIS_PAD_PORT_TYPE_STANDARD && type != ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL) + return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED; + } return 1; // dummy } @@ -286,12 +308,13 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { pData[i].angularVelocity.x = 0.0f; pData[i].angularVelocity.y = 0.0f; pData[i].angularVelocity.z = 0.0f; - pData[i].touchData.touchNum = 0; - pData[i].touchData.touch[0].x = 0; - pData[i].touchData.touch[0].y = 0; + pData[i].touchData.touchNum = + (states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0); + pData[i].touchData.touch[0].x = states[i].touchpad[0].x; + pData[i].touchData.touch[0].y = states[i].touchpad[0].y; pData[i].touchData.touch[0].id = 1; - pData[i].touchData.touch[1].x = 0; - pData[i].touchData.touch[1].y = 0; + pData[i].touchData.touch[1].x = states[i].touchpad[1].x; + pData[i].touchData.touch[1].y = states[i].touchpad[1].y; pData[i].touchData.touch[1].id = 2; pData[i].connected = connected; pData[i].timestamp = states[i].time; @@ -345,12 +368,13 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) { pData->angularVelocity.x = 0.0f; pData->angularVelocity.y = 0.0f; pData->angularVelocity.z = 0.0f; - pData->touchData.touchNum = 0; - pData->touchData.touch[0].x = 0; - pData->touchData.touch[0].y = 0; + pData->touchData.touchNum = + (state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0); + pData->touchData.touch[0].x = state.touchpad[0].x; + pData->touchData.touch[0].y = state.touchpad[0].y; pData->touchData.touch[0].id = 1; - pData->touchData.touch[1].x = 0; - pData->touchData.touch[1].y = 0; + pData->touchData.touch[1].x = state.touchpad[1].x; + pData->touchData.touch[1].y = state.touchpad[1].y; pData->touchData.touch[1].id = 2; pData->timestamp = state.time; pData->connected = true; // isConnected; //TODO fix me proper @@ -499,8 +523,8 @@ int PS4_SYSV_ABI scePadSetUserColor() { int PS4_SYSV_ABI scePadSetVibration(s32 handle, const OrbisPadVibrationParam* pParam) { if (pParam != nullptr) { - LOG_INFO(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle, - pParam->smallMotor, pParam->largeMotor); + LOG_DEBUG(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle, + pParam->smallMotor, pParam->largeMotor); auto* controller = Common::Singleton::Instance(); controller->SetVibration(pParam->smallMotor, pParam->largeMotor); return ORBIS_OK; diff --git a/src/core/libraries/pad/pad.h b/src/core/libraries/pad/pad.h index 3e9c14a17..f94a642cf 100644 --- a/src/core/libraries/pad/pad.h +++ b/src/core/libraries/pad/pad.h @@ -16,6 +16,7 @@ constexpr int ORBIS_PAD_MAX_DEVICE_UNIQUE_DATA_SIZE = 12; constexpr int ORBIS_PAD_PORT_TYPE_STANDARD = 0; constexpr int ORBIS_PAD_PORT_TYPE_SPECIAL = 2; +constexpr int ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL = 16; enum OrbisPadDeviceClass { ORBIS_PAD_DEVICE_CLASS_INVALID = -1, @@ -229,6 +230,13 @@ struct OrbisPadOpenParam { u8 reserve[8]; }; +struct OrbisPadOpenExtParam { + u16 vendorId; + u16 productId; + u16 productId_2; + u8 reserve[10]; +}; + struct OrbisPadLightBarParam { u8 r; u8 g; @@ -284,7 +292,7 @@ int PS4_SYSV_ABI scePadIsValidHandle(); int PS4_SYSV_ABI scePadMbusInit(); int PS4_SYSV_ABI scePadMbusTerm(); int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam); -int PS4_SYSV_ABI scePadOpenExt(); +int PS4_SYSV_ABI scePadOpenExt(s32 userId, s32 type, s32 index, const OrbisPadOpenExtParam* pParam); int PS4_SYSV_ABI scePadOpenExt2(); int PS4_SYSV_ABI scePadOutputReport(); int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num); diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp index 66422dc28..d4f5c6b7c 100644 --- a/src/core/libraries/playgo/playgo.cpp +++ b/src/core/libraries/playgo/playgo.cpp @@ -1,9 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "common/logging/log.h" #include "common/singleton.h" +#include "core/file_format/playgo_chunk.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/system/systemservice.h" diff --git a/src/core/libraries/playgo/playgo.h b/src/core/libraries/playgo/playgo.h index f5ae1baa6..2338c9ebf 100644 --- a/src/core/libraries/playgo/playgo.h +++ b/src/core/libraries/playgo/playgo.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include "common/types.h" #include "playgo_types.h" diff --git a/src/core/libraries/random/random.cpp b/src/core/libraries/random/random.cpp index 8147c5183..f7cc3fd2c 100644 --- a/src/core/libraries/random/random.cpp +++ b/src/core/libraries/random/random.cpp @@ -1,14 +1,16 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "random.h" +#include "random_error.h" + #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" -#include "random.h" namespace Libraries::Random { -s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, size_t size) { +s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, std::size_t size) { LOG_TRACE(Lib_Random, "called"); if (size > SCE_RANDOM_MAX_SIZE) { return SCE_RANDOM_ERROR_INVALID; diff --git a/src/core/libraries/random/random.h b/src/core/libraries/random/random.h index b5f87f877..b483cf6ed 100644 --- a/src/core/libraries/random/random.h +++ b/src/core/libraries/random/random.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include "common/types.h" namespace Core::Loader { @@ -11,7 +12,7 @@ class SymbolsResolver; namespace Libraries::Random { constexpr int32_t SCE_RANDOM_MAX_SIZE = 64; -s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, size_t size); +s32 PS4_SYSV_ABI sceRandomGetRandomNumber(u8* buf, std::size_t size); void RegisterlibSceRandom(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Random \ No newline at end of file diff --git a/src/core/libraries/random/random_error.h b/src/core/libraries/random/random_error.h new file mode 100644 index 000000000..772316ae5 --- /dev/null +++ b/src/core/libraries/random/random_error.h @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int SCE_RANDOM_ERROR_INVALID = 0x817C0016; +constexpr int SCE_RANDOM_ERROR_OUT_OF_RESOURCES = 0x817C001C; +constexpr int SCE_RANDOM_ERROR_FATAL = 0x817C00FF; \ No newline at end of file diff --git a/src/core/libraries/remote_play/remoteplay.cpp b/src/core/libraries/remote_play/remoteplay.cpp new file mode 100644 index 000000000..b7402173e --- /dev/null +++ b/src/core/libraries/remote_play/remoteplay.cpp @@ -0,0 +1,309 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "remoteplay.h" + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" + +namespace Libraries::Remoteplay { + +int PS4_SYSV_ABI sceRemoteplayApprove() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayChangeEnterKey() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayClearAllRegistData() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayClearConnectHistory() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayConfirmDeviceRegist() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayDisconnect() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGeneratePinCode() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetApMode() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetConnectHistory() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetConnectionStatus(s32 userId, int* pStatus) { + *pStatus = ORBIS_REMOTEPLAY_CONNECTION_STATUS_DISCONNECT; + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetConnectUserId() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetMbusDeviceInfo() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetOperationStatus() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetRemoteplayStatus() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayGetRpMode() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeClose() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeFilterResult() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeGetEvent() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeNotify() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeNotifyEventResult() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeOpen() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeSetCaret() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayImeSetText() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayInitialize() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayIsRemoteOskReady() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayIsRemotePlaying() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayNotifyMbusDeviceRegistComplete() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayNotifyNpPushWakeup() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayNotifyPinCodeError() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayNotifyUserDelete() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayPrintAllRegistData() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayProhibit() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayProhibitStreaming() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayServerLock() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayServerUnLock() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplaySetApMode() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplaySetLogLevel() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplaySetProhibition() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplaySetProhibitionForVsh() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplaySetRpMode() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceRemoteplayTerminate() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI Func_1D5EE365ED5FADB3() { + LOG_ERROR(Lib_Remoteplay, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceRemoteplay(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("xQeIryTX7dY", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayApprove); + LIB_FUNCTION("IYZ+Mu+8tPo", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayChangeEnterKey); + LIB_FUNCTION("ZYUsJtcAnqA", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayClearAllRegistData); + LIB_FUNCTION("cCheyCbF7qw", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayClearConnectHistory); + LIB_FUNCTION("tPYT-kGbZh8", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayConfirmDeviceRegist); + LIB_FUNCTION("6Lg4BNleJWc", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayDisconnect); + LIB_FUNCTION("j98LdSGy4eY", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGeneratePinCode); + LIB_FUNCTION("L+cL-M-DP3w", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetApMode); + LIB_FUNCTION("g4K51cY+PEw", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetConnectHistory); + LIB_FUNCTION("g3PNjYKWqnQ", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetConnectionStatus); + LIB_FUNCTION("3eBNV9A0BUM", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetConnectUserId); + LIB_FUNCTION("ufesWMVX6iU", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetMbusDeviceInfo); + LIB_FUNCTION("DxU4JGh4S2k", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetOperationStatus); + LIB_FUNCTION("n5OxFJEvPlc", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetRemoteplayStatus); + LIB_FUNCTION("Cekhs6LSHC0", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayGetRpMode); + LIB_FUNCTION("ig1ocbR7Ptw", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeClose); + LIB_FUNCTION("gV9-8cJPM3I", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeFilterResult); + LIB_FUNCTION("cMk57DZXe6c", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeGetEvent); + LIB_FUNCTION("-gwkQpOCl68", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeNotify); + LIB_FUNCTION("58v9tSlRxc8", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeNotifyEventResult); + LIB_FUNCTION("C3r2zT5ebMg", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeOpen); + LIB_FUNCTION("oB730zwoz0s", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeSetCaret); + LIB_FUNCTION("rOTg1Nljp8w", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayImeSetText); + LIB_FUNCTION("k1SwgkMSOM8", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayInitialize); + LIB_FUNCTION("R8RZC1ZIkzU", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayIsRemoteOskReady); + LIB_FUNCTION("uYhiELUtLgA", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayIsRemotePlaying); + LIB_FUNCTION("d-BBSEq1nfc", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayNotifyMbusDeviceRegistComplete); + LIB_FUNCTION("Yytq7NE38R8", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayNotifyNpPushWakeup); + LIB_FUNCTION("Wg-w8xjMZA4", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayNotifyPinCodeError); + LIB_FUNCTION("yheulqylKwI", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayNotifyUserDelete); + LIB_FUNCTION("t5ZvUiZ1hpE", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayPrintAllRegistData); + LIB_FUNCTION("mrNh78tBpmg", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayProhibit); + LIB_FUNCTION("7QLrixwVHcU", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayProhibitStreaming); + LIB_FUNCTION("-ThIlThsN80", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayServerLock); + LIB_FUNCTION("0Z-Pm5rZJOI", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayServerUnLock); + LIB_FUNCTION("xSrhtSLIjOc", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplaySetApMode); + LIB_FUNCTION("5-2agAeaE+c", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplaySetLogLevel); + LIB_FUNCTION("Rf0XMVR7xPw", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplaySetProhibition); + LIB_FUNCTION("n4l3FTZtNQM", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplaySetProhibitionForVsh); + LIB_FUNCTION("-BPcEQ1w8xc", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplaySetRpMode); + LIB_FUNCTION("BOwybKVa3Do", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + sceRemoteplayTerminate); + LIB_FUNCTION("HV7jZe1frbM", "libSceRemoteplay", 1, "libSceRemoteplay", 0, 0, + Func_1D5EE365ED5FADB3); +}; + +} // namespace Libraries::Remoteplay \ No newline at end of file diff --git a/src/core/libraries/remote_play/remoteplay.h b/src/core/libraries/remote_play/remoteplay.h new file mode 100644 index 000000000..979f73a9e --- /dev/null +++ b/src/core/libraries/remote_play/remoteplay.h @@ -0,0 +1,62 @@ +// 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; +} + +// returning codes in sceRemoteplayGetConnectionStatus pstatus +constexpr int ORBIS_REMOTEPLAY_CONNECTION_STATUS_DISCONNECT = 0; +constexpr int ORBIS_REMOTEPLAY_CONNECTION_STATUS_CONNECT = 1; + +namespace Libraries::Remoteplay { + +int PS4_SYSV_ABI sceRemoteplayApprove(); +int PS4_SYSV_ABI sceRemoteplayChangeEnterKey(); +int PS4_SYSV_ABI sceRemoteplayClearAllRegistData(); +int PS4_SYSV_ABI sceRemoteplayClearConnectHistory(); +int PS4_SYSV_ABI sceRemoteplayConfirmDeviceRegist(); +int PS4_SYSV_ABI sceRemoteplayDisconnect(); +int PS4_SYSV_ABI sceRemoteplayGeneratePinCode(); +int PS4_SYSV_ABI sceRemoteplayGetApMode(); +int PS4_SYSV_ABI sceRemoteplayGetConnectHistory(); +int PS4_SYSV_ABI sceRemoteplayGetConnectionStatus(s32 userId, int* pStatus); +int PS4_SYSV_ABI sceRemoteplayGetConnectUserId(); +int PS4_SYSV_ABI sceRemoteplayGetMbusDeviceInfo(); +int PS4_SYSV_ABI sceRemoteplayGetOperationStatus(); +int PS4_SYSV_ABI sceRemoteplayGetRemoteplayStatus(); +int PS4_SYSV_ABI sceRemoteplayGetRpMode(); +int PS4_SYSV_ABI sceRemoteplayImeClose(); +int PS4_SYSV_ABI sceRemoteplayImeFilterResult(); +int PS4_SYSV_ABI sceRemoteplayImeGetEvent(); +int PS4_SYSV_ABI sceRemoteplayImeNotify(); +int PS4_SYSV_ABI sceRemoteplayImeNotifyEventResult(); +int PS4_SYSV_ABI sceRemoteplayImeOpen(); +int PS4_SYSV_ABI sceRemoteplayImeSetCaret(); +int PS4_SYSV_ABI sceRemoteplayImeSetText(); +int PS4_SYSV_ABI sceRemoteplayInitialize(); +int PS4_SYSV_ABI sceRemoteplayIsRemoteOskReady(); +int PS4_SYSV_ABI sceRemoteplayIsRemotePlaying(); +int PS4_SYSV_ABI sceRemoteplayNotifyMbusDeviceRegistComplete(); +int PS4_SYSV_ABI sceRemoteplayNotifyNpPushWakeup(); +int PS4_SYSV_ABI sceRemoteplayNotifyPinCodeError(); +int PS4_SYSV_ABI sceRemoteplayNotifyUserDelete(); +int PS4_SYSV_ABI sceRemoteplayPrintAllRegistData(); +int PS4_SYSV_ABI sceRemoteplayProhibit(); +int PS4_SYSV_ABI sceRemoteplayProhibitStreaming(); +int PS4_SYSV_ABI sceRemoteplayServerLock(); +int PS4_SYSV_ABI sceRemoteplayServerUnLock(); +int PS4_SYSV_ABI sceRemoteplaySetApMode(); +int PS4_SYSV_ABI sceRemoteplaySetLogLevel(); +int PS4_SYSV_ABI sceRemoteplaySetProhibition(); +int PS4_SYSV_ABI sceRemoteplaySetProhibitionForVsh(); +int PS4_SYSV_ABI sceRemoteplaySetRpMode(); +int PS4_SYSV_ABI sceRemoteplayTerminate(); +int PS4_SYSV_ABI Func_1D5EE365ED5FADB3(); + +void RegisterlibSceRemoteplay(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Remoteplay \ No newline at end of file diff --git a/src/core/libraries/rtc/rtc.cpp b/src/core/libraries/rtc/rtc.cpp index f6faa5382..7a46a1e31 100644 --- a/src/core/libraries/rtc/rtc.cpp +++ b/src/core/libraries/rtc/rtc.cpp @@ -1,160 +1,831 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include + #include "common/logging/log.h" #include "core/libraries/error_codes.h" +#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/time_management.h" #include "core/libraries/libs.h" #include "rtc.h" #include "rtc_error.h" namespace Libraries::Rtc { -int PS4_SYSV_ABI sceRtcCheckValid() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcCheckValid(OrbisRtcDateTime* pTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + if (pTime->year == 0 || pTime->year > 9999) + return ORBIS_RTC_ERROR_INVALID_YEAR; + + if (pTime->month == 0 || pTime->month > 12) + return ORBIS_RTC_ERROR_INVALID_MONTH; + + if (pTime->day == 0) + return ORBIS_RTC_ERROR_INVALID_DAY; + + using namespace std::chrono; + year chronoYear = year(pTime->year); + month chronoMonth = month(pTime->month); + int lastDay = + static_cast(unsigned(year_month_day_last{chronoYear / chronoMonth / last}.day())); + + if (pTime->day > lastDay) + return ORBIS_RTC_ERROR_INVALID_DAY; + + if (pTime->hour >= 24) + return ORBIS_RTC_ERROR_INVALID_HOUR; + + if (pTime->minute >= 60) + return ORBIS_RTC_ERROR_INVALID_MINUTE; + + if (pTime->second >= 60) + return ORBIS_RTC_ERROR_INVALID_SECOND; + + if (pTime->microsecond >= 1000000) + return ORBIS_RTC_ERROR_INVALID_MICROSECOND; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcCompareTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcCompareTick(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + if (pTick1->tick <= pTick2->tick) + return 1; + else + return 0; + + return ORBIS_FAIL; } -int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc(OrbisRtcTick* pTickLocal, OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickLocal == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + time_t seconds; + Kernel::OrbisKernelTimezone timezone; + + int convertValue = Kernel::sceKernelConvertLocaltimeToUtc( + (pTickLocal->tick - UNIX_EPOCH_TICKS) / 1000000, 0xffffffff, &seconds, &timezone, 0); + + if (convertValue >= 0) { + convertValue = sceRtcTickAddMinutes( + pTickUtc, pTickLocal, -(((timezone.tz_dsttime * 60) - timezone.tz_minuteswest))); + } + + return convertValue; } -int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime(OrbisRtcTick* pTickUtc, OrbisRtcTick* pTickLocal) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickUtc == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimezone timeZone; + int returnValue = Kernel::sceKernelGettimezone(&timeZone); + + sceRtcTickAddMinutes(pTickLocal, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); + + return 0; } int PS4_SYSV_ABI sceRtcEnd() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; + return SCE_OK; } -int PS4_SYSV_ABI sceRtcFormatRFC2822() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC2822(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int iTimeZoneMinutes) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + OrbisRtcTick formatTick; + + if (pTickUtc == nullptr) { + sceRtcGetCurrentTick(&formatTick); + } else { + formatTick.tick = pTickUtc->tick; + } + + sceRtcTickAddMinutes(&formatTick, &formatTick, iTimeZoneMinutes); + + OrbisRtcDateTime formatTime; + sceRtcSetTick(&formatTime, &formatTick); + + int validTime = sceRtcCheckValid(&formatTime); + + std::string formattedString; + + if (validTime >= 0) { + int weekDay = sceRtcGetDayOfWeek(formatTime.year, formatTime.month, formatTime.day); + switch (weekDay) { + case 0: + formattedString = "Sun, "; + break; + case 1: + formattedString = "Mon, "; + break; + case 2: + formattedString = "Tue, "; + break; + case 3: + formattedString = "Wed, "; + break; + case 4: + formattedString = "Thu, "; + break; + case 5: + formattedString = "Fri, "; + break; + case 6: + formattedString = "Sat, "; + break; + } + + if (formatTime.day < 10) { + formattedString += "0" + std::to_string(formatTime.day) + " "; + } else { + formattedString += std::to_string(formatTime.day) + " "; + } + + switch (formatTime.month) { + case 1: + formattedString += "Jan "; + break; + case 2: + formattedString += "Feb "; + break; + case 3: + formattedString += "Mar "; + break; + case 4: + formattedString += "Apr "; + break; + case 5: + formattedString += "May "; + break; + case 6: + formattedString += "Jun "; + break; + case 7: + formattedString += "Jul "; + break; + case 8: + formattedString += "Aug "; + break; + case 9: + formattedString += "Sep "; + break; + case 10: + formattedString += "Oct "; + break; + case 11: + formattedString += "Nov "; + break; + case 12: + formattedString += "Dec "; + break; + } + + formattedString += std::to_string(formatTime.year) + " "; + + if (formatTime.hour < 10) { + formattedString += "0" + std::to_string(formatTime.hour) + ":"; + } else { + formattedString += std::to_string(formatTime.hour) + ":"; + } + + if (formatTime.minute < 10) { + formattedString += "0" + std::to_string(formatTime.minute) + ":"; + } else { + formattedString += std::to_string(formatTime.minute) + ":"; + } + + if (formatTime.second < 10) { + formattedString += "0" + std::to_string(formatTime.second) + " "; + } else { + formattedString += std::to_string(formatTime.second) + " "; + } + + if (iTimeZoneMinutes == 0) { + formattedString += "+0000"; + } else { + int timeZoneHours = iTimeZoneMinutes / 60; + int timeZoneRemainder = iTimeZoneMinutes % 60; + + if (timeZoneHours < 0) { + formattedString += "-"; + timeZoneHours *= -1; + } else { + formattedString += "+"; + } + + if (timeZoneHours < 10) { + formattedString += "0" + std::to_string(timeZoneHours); + } else { + formattedString += std::to_string(timeZoneHours); + } + + if (timeZoneRemainder == 0) { + formattedString += "00"; + } else { + if (timeZoneRemainder < 0) + timeZoneRemainder *= -1; + formattedString += std::to_string(timeZoneRemainder); + } + } + + for (int i = 0; i < formattedString.size() + 1; ++i) { + pszDateTime[i] = formattedString.c_str()[i]; + } + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + Kernel::OrbisKernelTimezone timeZone; + Kernel::sceKernelGettimezone(&timeZone); + + return sceRtcFormatRFC2822(pszDateTime, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); } -int PS4_SYSV_ABI sceRtcFormatRFC3339() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int iTimeZoneMinutes) { + LOG_TRACE(Lib_Rtc, "called"); + return sceRtcFormatRFC3339Precise(pszDateTime, pTickUtc, iTimeZoneMinutes); } -int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + Kernel::OrbisKernelTimezone timeZone; + Kernel::sceKernelGettimezone(&timeZone); + + return sceRtcFormatRFC3339(pszDateTime, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); } -int PS4_SYSV_ABI sceRtcFormatRFC3339Precise() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339Precise(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int iTimeZoneMinutes) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + OrbisRtcTick formatTick; + + if (pTickUtc == nullptr) { + sceRtcGetCurrentTick(&formatTick); + } else { + formatTick.tick = pTickUtc->tick; + } + + sceRtcTickAddMinutes(&formatTick, &formatTick, iTimeZoneMinutes); + + OrbisRtcDateTime formatTime; + + sceRtcSetTick(&formatTime, &formatTick); + + std::string formattedString; + formattedString = std::to_string(formatTime.year) + "-"; + + if (formatTime.month < 10) { + formattedString += "0" + std::to_string(formatTime.month) + "-"; + } else { + formattedString += std::to_string(formatTime.month) + "-"; + } + + if (formatTime.day < 10) { + formattedString += "0" + std::to_string(formatTime.day) + "T"; + } else { + formattedString += std::to_string(formatTime.day) + "T"; + } + + if (formatTime.hour < 10) { + formattedString += "0" + std::to_string(formatTime.hour) + ":"; + } else { + formattedString += std::to_string(formatTime.hour) + ":"; + } + + if (formatTime.minute < 10) { + formattedString += "0" + std::to_string(formatTime.minute) + ":"; + } else { + formattedString += std::to_string(formatTime.minute) + ":"; + } + + if (formatTime.second < 10) { + formattedString += "0" + std::to_string(formatTime.second); + } else { + formattedString += std::to_string(formatTime.second); + } + + if (formatTime.microsecond != 0) { + formattedString += "." + std::to_string(formatTime.microsecond / 1000).substr(0, 2); + } else { + formattedString += ".00"; + } + + if (iTimeZoneMinutes == 0) { + formattedString += "Z"; + } else { + int timeZoneHours = iTimeZoneMinutes / 60; + int timeZoneRemainder = iTimeZoneMinutes % 60; + + if (timeZoneHours < 0) { + formattedString += "-"; + timeZoneHours *= -1; + } else { + formattedString += "+"; + } + + if (timeZoneHours < 10) { + formattedString += "0" + std::to_string(timeZoneHours); + } else { + formattedString += std::to_string(timeZoneHours); + } + + if (timeZoneRemainder == 0) { + formattedString += ":00"; + } else { + if (timeZoneRemainder < 0) + timeZoneRemainder *= -1; + formattedString += ":" + std::to_string(timeZoneRemainder); + } + } + + for (int i = 0; i < formattedString.size() + 1; ++i) { + pszDateTime[i] = formattedString.c_str()[i]; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime(char* pszDateTime, + const OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + Kernel::OrbisKernelTimezone timeZone; + Kernel::sceKernelGettimezone(&timeZone); + + return sceRtcFormatRFC3339Precise(pszDateTime, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); } -int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetCurrentClock() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentClock(OrbisRtcDateTime* pTime, int timeZone) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + OrbisRtcTick clockTick; + clockTick.tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + + sceRtcTickAddMinutes(&clockTick, &clockTick, timeZone); + sceRtcSetTick(pTime, &clockTick); + } + + return returnValue; } -int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime(OrbisRtcDateTime* pTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED; + + Kernel::OrbisKernelTimezone timeZone; + int returnValue = Kernel::sceKernelGettimezone(&timeZone); + + if (returnValue >= 0) { + Kernel::OrbisKernelTimespec clocktime; + + // calculate total timezone offset for converting UTC to local time + uint64_t tzOffset = -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60)); + + if (returnValue >= 0) { + OrbisRtcTick newTick; + sceRtcGetCurrentTick(&newTick); + sceRtcTickAddMinutes(&newTick, &newTick, tzOffset); + sceRtcSetTick(pTime, &newTick); + } + } + + return returnValue; } -int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } int PS4_SYSV_ABI sceRtcGetCurrentTick(OrbisRtcTick* pTick) { - pTick->tick = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(); - return ORBIS_OK; + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue >= 0) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetDayOfWeek() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetDayOfWeek(int year, int month, int day) { + LOG_TRACE(Lib_Rtc, "called"); + + int sdk_version = 0; + int sdkResult = Kernel::sceKernelGetCompiledSdkVersion(&sdk_version); + if (sdkResult != ORBIS_OK) { + sdk_version = 0; + } + + if (sdk_version < 0x3000000) { + if (year < 1) { + return ORBIS_RTC_ERROR_INVALID_YEAR; + } + if (month > 12 || month <= 0) { + return ORBIS_RTC_ERROR_INVALID_MONTH; + } + } else { + if (year > 9999 || year < 1) { + return ORBIS_RTC_ERROR_INVALID_YEAR; + } + if (month > 12 || month <= 0) { + return ORBIS_RTC_ERROR_INVALID_MONTH; + } + } + + int daysInMonth = sceRtcGetDaysInMonth(year, month); + + if (day <= 0 || day > daysInMonth) + return ORBIS_RTC_ERROR_INVALID_DAY; + + std::chrono::sys_days chrono_time{std::chrono::year(year) / std::chrono::month(month) / + std::chrono::day(day)}; + std::chrono::weekday chrono_weekday{chrono_time}; + + return chrono_weekday.c_encoding(); } -int PS4_SYSV_ABI sceRtcGetDaysInMonth() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetDaysInMonth(int year, int month) { + LOG_TRACE(Lib_Rtc, "called"); + + if (year <= 0) + return ORBIS_RTC_ERROR_INVALID_YEAR; + + if (month <= 0 || month > 12) + return ORBIS_RTC_ERROR_INVALID_MONTH; + + std::chrono::year chronoYear = std::chrono::year(year); + std::chrono::month chronoMonth = std::chrono::month(month); + int lastDay = static_cast(unsigned( + std::chrono::year_month_day_last{chronoYear / chronoMonth / std::chrono::last}.day())); + + return lastDay; } -int PS4_SYSV_ABI sceRtcGetDosTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetDosTime(OrbisRtcDateTime* pTime, unsigned int* dosTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || dosTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isValid = sceRtcCheckValid(pTime); + if (isValid != SCE_OK) { + return isValid; + } + + *dosTime |= (pTime->second / 2) & 0x1F; + *dosTime |= (pTime->minute & 0x3F) << 5; + *dosTime |= (pTime->hour & 0x1F) << 11; + *dosTime |= (pTime->day & 0x1F) << 16; + *dosTime |= (pTime->month & 0x0F) << 21; + *dosTime |= ((pTime->year - 1980) & 0x7F) << 25; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isTimeValid = sceRtcCheckValid(pTime); + if (isTimeValid != 0) + return isTimeValid; + + if (pTime->month > 2) { + pTime->month -= 3; + } else { + pTime->month += 9; + pTime->year -= 1; + } + + int c = pTime->year / 100; + int ya = pTime->year - 100 * c; + + u64 days; + u64 msec; + + days = ((146097 * c) >> 2) + ((1461 * ya) >> 2) + (153 * pTime->month + 2) / 5 + pTime->day; + days -= 307; + days *= 86400000000; + + msec = pTime->hour * 3600000000 + pTime->minute * 60000000 + pTime->second * 1000000 + + pTime->microsecond; + + pTick->tick = days + msec; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetTickResolution() { +unsigned int PS4_SYSV_ABI sceRtcGetTickResolution() { + LOG_TRACE(Lib_Rtc, "called"); + return 1000000; } -int PS4_SYSV_ABI sceRtcGetTime_t() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetTime_t(OrbisRtcDateTime* pTime, time_t* llTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || llTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isValid = sceRtcCheckValid(pTime); + if (isValid != SCE_OK) { + return isValid; + } + + OrbisRtcTick timeTick; + sceRtcGetTick(pTime, &timeTick); + + if (timeTick.tick < UNIX_EPOCH_TICKS) { + *llTime = 0; + } else { + *llTime = (timeTick.tick - UNIX_EPOCH_TICKS) / 1000000; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetWin32FileTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetWin32FileTime(OrbisRtcDateTime* pTime, uint64_t* ulWin32Time) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || ulWin32Time == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isValid = sceRtcCheckValid(pTime); + if (isValid != SCE_OK) { + return isValid; + } + + OrbisRtcTick timeTick; + sceRtcGetTick(pTime, &timeTick); + + if (timeTick.tick < WIN32_FILETIME_EPOCH_TICKS) { + *ulWin32Time = 0; + } else { + *ulWin32Time = (timeTick.tick - WIN32_FILETIME_EPOCH_TICKS) * 10; + } + + return SCE_OK; } int PS4_SYSV_ABI sceRtcInit() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; + return SCE_OK; } -int PS4_SYSV_ABI sceRtcIsLeapYear() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcIsLeapYear(int yearInt) { + LOG_TRACE(Lib_Rtc, "called"); + + if (yearInt < 1) + return ORBIS_RTC_ERROR_INVALID_YEAR; + + using namespace std::chrono; + + year_month_day_last ymdl{year(yearInt) / February / last}; + return (ymdl.day() == 29d); } -int PS4_SYSV_ABI sceRtcParseDateTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int GetMonthFromString(std::string monthStr) { + if (monthStr == "Jan") + return 1; + + if (monthStr == "Feb") + return 2; + + if (monthStr == "Mar") + return 3; + + if (monthStr == "Apr") + return 4; + + if (monthStr == "May") + return 5; + + if (monthStr == "Jun") + return 6; + + if (monthStr == "Jul") + return 7; + + if (monthStr == "Aug") + return 8; + + if (monthStr == "Sep") + return 9; + + if (monthStr == "Oct") + return 10; + + if (monthStr == "Nov") + return 11; + + if (monthStr == "Dec") + return 12; + + return 1; } -int PS4_SYSV_ABI sceRtcParseRFC3339() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcParseDateTime(OrbisRtcTick* pTickUtc, const char* pszDateTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickUtc == nullptr || pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + std::string dateTimeString = std::string(pszDateTime); + + char formatKey = dateTimeString[22]; + OrbisRtcDateTime dateTime; + + if (formatKey == 'Z' || formatKey == '-' || formatKey == '+') { + // RFC3339 + sceRtcParseRFC3339(pTickUtc, pszDateTime); + } else if (formatKey == ':') { + // RFC2822 + dateTime.day = std::stoi(dateTimeString.substr(5, 2)); + dateTime.month = GetMonthFromString(dateTimeString.substr(8, 3)); + dateTime.year = std::stoi(dateTimeString.substr(12, 4)); + dateTime.hour = std::stoi(dateTimeString.substr(17, 2)); + dateTime.minute = std::stoi(dateTimeString.substr(20, 2)); + dateTime.second = std::stoi(dateTimeString.substr(23, 2)); + dateTime.microsecond = 0; + + sceRtcGetTick(&dateTime, pTickUtc); + + if (dateTimeString[26] == '+') { + int timeZoneOffset = std::stoi(dateTimeString.substr(27, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(29, 2)); + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } else if (dateTimeString[26] == '-') { + int timeZoneOffset = std::stoi(dateTimeString.substr(27, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(29, 2)); + timeZoneOffset *= -1; + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } + + } else { + // asctime + dateTime.month = GetMonthFromString(dateTimeString.substr(4, 3)); + dateTime.day = std::stoi(dateTimeString.substr(8, 2)); + dateTime.hour = std::stoi(dateTimeString.substr(11, 2)); + dateTime.minute = std::stoi(dateTimeString.substr(14, 2)); + dateTime.second = std::stoi(dateTimeString.substr(17, 2)); + dateTime.year = std::stoi(dateTimeString.substr(20, 4)); + dateTime.microsecond = 0; + + sceRtcGetTick(&dateTime, pTickUtc); + } + + return SCE_OK; +} + +int PS4_SYSV_ABI sceRtcParseRFC3339(OrbisRtcTick* pTickUtc, const char* pszDateTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickUtc == nullptr || pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + std::string dateTimeString = std::string(pszDateTime); + + OrbisRtcDateTime dateTime; + dateTime.year = std::stoi(dateTimeString.substr(0, 4)); + dateTime.month = std::stoi(dateTimeString.substr(5, 2)); + dateTime.day = std::stoi(dateTimeString.substr(8, 2)); + dateTime.hour = std::stoi(dateTimeString.substr(11, 2)); + dateTime.minute = std::stoi(dateTimeString.substr(14, 2)); + dateTime.second = std::stoi(dateTimeString.substr(17, 2)); + dateTime.microsecond = std::stoi(dateTimeString.substr(20, 2)); + + sceRtcGetTick(&dateTime, pTickUtc); + + if (dateTimeString[22] != 'Z') { + if (dateTimeString[22] == '-') { + int timeZoneOffset = std::stoi(dateTimeString.substr(23, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(26, 2)); + timeZoneOffset *= -1; + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } else if (dateTimeString[22] == '+') { + int timeZoneOffset = std::stoi(dateTimeString.substr(23, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(26, 2)); + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } + } + + return SCE_OK; } int PS4_SYSV_ABI sceRtcSetConf() { @@ -162,89 +833,294 @@ int PS4_SYSV_ABI sceRtcSetConf() { return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick() { +int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick() { +int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick() { +int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentTick() { +int PS4_SYSV_ABI sceRtcSetCurrentTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetDosTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetDosTime(OrbisRtcDateTime* pTime, u32 dosTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTime->microsecond = 0; + pTime->second = (dosTime << 1) & 0x3e; + pTime->minute = (dosTime >> 5) & 0x3f; + pTime->hour = (dosTime & 0xf800) >> 0xb; + + int16_t days = dosTime >> 0x10; + + pTime->day = days & 0x1f; + pTime->month = (days >> 5) & 0x0f; + pTime->year = (days >> 9) + 1980; + return SCE_OK; } -int PS4_SYSV_ABI sceRtcSetTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + u32 ly, ld, lm, j; + u64 days, msec; + + days = pTick->tick / 86400000000; + msec = pTick->tick % 86400000000; + + days += 307; + + j = (days << 2) - 1; + ly = j / 146097; + + j -= (146097 * ly); + ld = j >> 2; + + j = ((ld << 2) + 3) / 1461; + ld = (((ld << 2) + 7) - 1461 * j) >> 2; + + lm = (5 * ld - 3) / 153; + ld = (5 * ld + 2 - 153 * lm) / 5; + ly = 100 * ly + j; + + if (lm < 10) { + lm += 3; + } else { + lm -= 9; + ly++; + } + + pTime->year = ly; + pTime->month = lm; + pTime->day = ld; + + pTime->hour = msec / 3600000000; + msec %= 3600000000; + pTime->minute = msec / 60000000; + msec %= 60000000; + pTime->second = msec / 1000000; + msec %= 1000000; + pTime->microsecond = msec; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcSetTime_t() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetTime_t(OrbisRtcDateTime* pTime, time_t llTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int sdk_version; + int sdkResult = Kernel::sceKernelGetCompiledSdkVersion(&sdk_version); + if (sdkResult != ORBIS_OK) { + sdk_version = 0; + } + + OrbisRtcTick newTick; + if (sdk_version < 0x3000000) { + newTick.tick = (llTime & 0xffffffff) * 1000000; + } else { + if (llTime < 0) { + return ORBIS_RTC_ERROR_INVALID_VALUE; + } + newTick.tick = llTime * 1000000; + } + + newTick.tick += UNIX_EPOCH_TICKS; + sceRtcSetTick(pTime, &newTick); + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcSetWin32FileTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetWin32FileTime(OrbisRtcDateTime* pTime, int64_t ulWin32Time) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + u64 convertedTime = (ulWin32Time / 10) + WIN32_FILETIME_EPOCH_TICKS; + + OrbisRtcTick convertedTick; + convertedTick.tick = convertedTime; + + sceRtcSetTick(pTime, &convertedTick); + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddDays() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddDays(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 86400000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddHours() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddHours(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 3600000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddMicroseconds() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddMicroseconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, + int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = lAdd + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddMinutes() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddMinutes(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 60000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddMonths() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddMonths(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + if (lAdd == 0) { + pTick1->tick = pTick2->tick; + return SCE_OK; + } + + OrbisRtcDateTime time; + s64 s; + s64 tempMonth; + + sceRtcSetTick(&time, pTick1); + + if (lAdd >= 0) { + s = 1; + } else { + s = -1; + } + + time.year += (lAdd / 12); + tempMonth = time.month + (lAdd % 12) - 1; + + if (tempMonth > 11 || tempMonth < 0) { + tempMonth -= s * 12; + time.year += s; + } + + time.month = tempMonth + 1; + + using namespace std::chrono; + year chronoYear = year(time.year); + month chronoMonth = month(time.month); + int lastDay = + static_cast(unsigned(year_month_day_last{chronoYear / chronoMonth / last}.day())); + + if (time.day > lastDay) { + time.day = lastDay; + } + + int timeIsValid = sceRtcCheckValid(&time); + if (timeIsValid == SCE_OK) { + sceRtcGetTick(&time, pTick1); + } else { + return timeIsValid; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddSeconds() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddSeconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 1000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddTicks() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddTicks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = lAdd + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddWeeks() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddWeeks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 604800000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddYears() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddYears(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + OrbisRtcDateTime time; + + if (lAdd == 0) { + pTick1->tick = pTick2->tick; + return SCE_OK; + } + + sceRtcSetTick(&time, pTick1); + + time.year += lAdd; + + int timeIsValid = sceRtcCheckValid(&time); + if (timeIsValid == SCE_OK) { + sceRtcGetTick(&time, pTick1); + } else { + return timeIsValid; + } + + return SCE_OK; } void RegisterlibSceRtc(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/rtc/rtc.h b/src/core/libraries/rtc/rtc.h index ee6afa70e..c41040863 100644 --- a/src/core/libraries/rtc/rtc.h +++ b/src/core/libraries/rtc/rtc.h @@ -11,57 +11,81 @@ class SymbolsResolver; namespace Libraries::Rtc { +constexpr int ORBIS_RTC_DAYOFWEEK_SUNDAY = 0; +constexpr int ORBIS_RTC_DAYOFWEEK_MONDAY = 1; +constexpr int ORBIS_RTC_DAYOFWEEK_TUESDAY = 2; +constexpr int ORBIS_RTC_DAYOFWEEK_WEDNESDAY = 3; +constexpr int ORBIS_RTC_DAYOFWEEK_THURSDAY = 4; +constexpr int ORBIS_RTC_DAYOFWEEK_FRIDAY = 5; +constexpr int ORBIS_RTC_DAYOFWEEK_SATURDAY = 6; + +constexpr int64_t UNIX_EPOCH_TICKS = 0xdcbffeff2bc000; +constexpr int64_t WIN32_FILETIME_EPOCH_TICKS = 0xb36168b6a58000; + struct OrbisRtcTick { - u64 tick; + uint64_t tick; }; -int PS4_SYSV_ABI sceRtcCheckValid(); -int PS4_SYSV_ABI sceRtcCompareTick(); -int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc(); -int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime(); +struct OrbisRtcDateTime { + uint16_t year; + uint16_t month; + uint16_t day; + uint16_t hour; + uint16_t minute; + uint16_t second; + uint32_t microsecond; +}; + +int PS4_SYSV_ABI sceRtcCheckValid(OrbisRtcDateTime* pTime); +int PS4_SYSV_ABI sceRtcCompareTick(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2); +int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc(OrbisRtcTick* pTickLocal, OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime(OrbisRtcTick* pTickUtc, OrbisRtcTick* pTickLocal); int PS4_SYSV_ABI sceRtcEnd(); -int PS4_SYSV_ABI sceRtcFormatRFC2822(); -int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime(); -int PS4_SYSV_ABI sceRtcFormatRFC3339(); -int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime(); -int PS4_SYSV_ABI sceRtcFormatRFC3339Precise(); -int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime(); -int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick(); -int PS4_SYSV_ABI sceRtcGetCurrentClock(); -int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime(); -int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick(); -int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick(); -int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick(); +int PS4_SYSV_ABI sceRtcFormatRFC2822(char* pszDateTime, const OrbisRtcTick* pTickUtc, int minutes); +int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcFormatRFC3339(char* pszDateTime, const OrbisRtcTick* pTickUtc, int minutes); +int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcFormatRFC3339Precise(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int minutes); +int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime(char* pszDateTime, + const OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcGetCurrentClock(OrbisRtcDateTime* pTime, int timeZone); +int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime(OrbisRtcDateTime* pTime); +int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick(OrbisRtcTick* pTick); int PS4_SYSV_ABI sceRtcGetCurrentTick(OrbisRtcTick* pTick); -int PS4_SYSV_ABI sceRtcGetDayOfWeek(); -int PS4_SYSV_ABI sceRtcGetDaysInMonth(); -int PS4_SYSV_ABI sceRtcGetDosTime(); -int PS4_SYSV_ABI sceRtcGetTick(); -int PS4_SYSV_ABI sceRtcGetTickResolution(); -int PS4_SYSV_ABI sceRtcGetTime_t(); -int PS4_SYSV_ABI sceRtcGetWin32FileTime(); +int PS4_SYSV_ABI sceRtcGetDayOfWeek(int year, int month, int day); +int PS4_SYSV_ABI sceRtcGetDaysInMonth(int year, int month); +int PS4_SYSV_ABI sceRtcGetDosTime(OrbisRtcDateTime* pTime, unsigned int* dosTime); +int PS4_SYSV_ABI sceRtcGetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick); +unsigned int PS4_SYSV_ABI sceRtcGetTickResolution(); +int PS4_SYSV_ABI sceRtcGetTime_t(OrbisRtcDateTime* pTime, time_t* llTime); +int PS4_SYSV_ABI sceRtcGetWin32FileTime(OrbisRtcDateTime* pTime, uint64_t* ulWin32Time); int PS4_SYSV_ABI sceRtcInit(); -int PS4_SYSV_ABI sceRtcIsLeapYear(); -int PS4_SYSV_ABI sceRtcParseDateTime(); -int PS4_SYSV_ABI sceRtcParseRFC3339(); +int PS4_SYSV_ABI sceRtcIsLeapYear(int yearInt); +int PS4_SYSV_ABI sceRtcParseDateTime(OrbisRtcTick* pTickUtc, const char* pszDateTime); +int PS4_SYSV_ABI sceRtcParseRFC3339(OrbisRtcTick* pTickUtc, const char* pszDateTime); int PS4_SYSV_ABI sceRtcSetConf(); -int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick(); -int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick(); -int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick(); -int PS4_SYSV_ABI sceRtcSetCurrentTick(); -int PS4_SYSV_ABI sceRtcSetDosTime(); -int PS4_SYSV_ABI sceRtcSetTick(); -int PS4_SYSV_ABI sceRtcSetTime_t(); -int PS4_SYSV_ABI sceRtcSetWin32FileTime(); -int PS4_SYSV_ABI sceRtcTickAddDays(); -int PS4_SYSV_ABI sceRtcTickAddHours(); -int PS4_SYSV_ABI sceRtcTickAddMicroseconds(); -int PS4_SYSV_ABI sceRtcTickAddMinutes(); -int PS4_SYSV_ABI sceRtcTickAddMonths(); -int PS4_SYSV_ABI sceRtcTickAddSeconds(); -int PS4_SYSV_ABI sceRtcTickAddTicks(); -int PS4_SYSV_ABI sceRtcTickAddWeeks(); -int PS4_SYSV_ABI sceRtcTickAddYears(); +int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetCurrentTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetDosTime(OrbisRtcDateTime* pTime, u32 dosTime); +int PS4_SYSV_ABI sceRtcSetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetTime_t(OrbisRtcDateTime* pTime, time_t llTime); +int PS4_SYSV_ABI sceRtcSetWin32FileTime(OrbisRtcDateTime* pTime, int64_t ulWin32Time); +int PS4_SYSV_ABI sceRtcTickAddDays(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddHours(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddMicroseconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, + int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddMinutes(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddMonths(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddSeconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddTicks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddWeeks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddYears(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); void RegisterlibSceRtc(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Rtc \ No newline at end of file diff --git a/src/core/libraries/rtc/rtc_error.h b/src/core/libraries/rtc/rtc_error.h index 04eecbbdf..3af5a68fd 100644 --- a/src/core/libraries/rtc/rtc_error.h +++ b/src/core/libraries/rtc/rtc_error.h @@ -3,6 +3,7 @@ #pragma once +constexpr int ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED = 0x7FFEF9FE; constexpr int ORBIS_RTC_ERROR_INVALID_PARAMETER = 0x80010602; constexpr int ORBIS_RTC_ERROR_INVALID_TICK_PARAMETER = 0x80010603; constexpr int ORBIS_RTC_ERROR_INVALID_DATE_PARAMETER = 0x80010604; @@ -14,4 +15,18 @@ constexpr int ORBIS_RTC_ERROR_INVALID_DAYS_PARAMETER = 0x80010623; constexpr int ORBIS_RTC_ERROR_INVALID_HOURS_PARAMETER = 0x80010624; constexpr int ORBIS_RTC_ERROR_INVALID_MINUTES_PARAMETER = 0x80010625; constexpr int ORBIS_RTC_ERROR_INVALID_SECONDS_PARAMETER = 0x80010626; -constexpr int ORBIS_RTC_ERROR_INVALID_MILLISECONDS_PARAMETER = 0x80010627; \ No newline at end of file +constexpr int ORBIS_RTC_ERROR_INVALID_MILLISECONDS_PARAMETER = 0x80010627; +constexpr int ORBIS_RTC_ERROR_NOT_INITIALIZED = 0x80B50001; +constexpr int ORBIS_RTC_ERROR_INVALID_POINTER = 0x80B50002; +constexpr int ORBIS_RTC_ERROR_INVALID_VALUE = 0x80B50003; +constexpr int ORBIS_RTC_ERROR_INVALID_ARG = 0x80B50004; +constexpr int ORBIS_RTC_ERROR_NOT_SUPPORTED = 0x80B50005; +constexpr int ORBIS_RTC_ERROR_NO_CLOCK = 0x80B50006; +constexpr int ORBIS_RTC_ERROR_BAD_PARSE = 0x80B50007; +constexpr int ORBIS_RTC_ERROR_INVALID_YEAR = 0x80B50008; +constexpr int ORBIS_RTC_ERROR_INVALID_MONTH = 0x80B50009; +constexpr int ORBIS_RTC_ERROR_INVALID_DAY = 0x80B5000A; +constexpr int ORBIS_RTC_ERROR_INVALID_HOUR = 0x80B5000B; +constexpr int ORBIS_RTC_ERROR_INVALID_MINUTE = 0x80B5000C; +constexpr int ORBIS_RTC_ERROR_INVALID_SECOND = 0x80B5000D; +constexpr int ORBIS_RTC_ERROR_INVALID_MICROSECOND = 0x80B5000E; \ No newline at end of file diff --git a/src/core/libraries/save_data/dialog/savedatadialog.cpp b/src/core/libraries/save_data/dialog/savedatadialog.cpp new file mode 100644 index 000000000..0ad7d7dc0 --- /dev/null +++ b/src/core/libraries/save_data/dialog/savedatadialog.cpp @@ -0,0 +1,164 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/elf_info.h" +#include "common/logging/log.h" +#include "core/libraries/libs.h" +#include "core/libraries/system/commondialog.h" +#include "magic_enum.hpp" +#include "savedatadialog.h" +#include "savedatadialog_ui.h" + +namespace Libraries::SaveData::Dialog { + +using CommonDialog::Error; +using CommonDialog::Result; +using CommonDialog::Status; + +static auto g_status = Status::NONE; +static SaveDialogState g_state{}; +static SaveDialogResult g_result{}; +static SaveDialogUi g_save_dialog_ui; + +Error PS4_SYSV_ABI sceSaveDataDialogClose() { + LOG_DEBUG(Lib_SaveDataDialog, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + g_save_dialog_ui.Finish(ButtonId::INVALID); + g_save_dialog_ui = SaveDialogUi{}; + return Error::OK; +} + +Error PS4_SYSV_ABI sceSaveDataDialogGetResult(OrbisSaveDataDialogResult* result) { + LOG_DEBUG(Lib_SaveDataDialog, "called"); + if (g_status != Status::FINISHED) { + return Error::NOT_FINISHED; + } + if (result == nullptr) { + return Error::ARG_NULL; + } + g_result.CopyTo(*result); + return Error::OK; +} + +Status PS4_SYSV_ABI sceSaveDataDialogGetStatus() { + LOG_TRACE(Lib_SaveDataDialog, "called status={}", magic_enum::enum_name(g_status)); + return g_status; +} + +Error PS4_SYSV_ABI sceSaveDataDialogInitialize() { + LOG_DEBUG(Lib_SaveDataDialog, "called"); + if (!CommonDialog::g_isInitialized) { + return Error::NOT_SYSTEM_INITIALIZED; + } + if (g_status != Status::NONE) { + return Error::ALREADY_INITIALIZED; + } + if (CommonDialog::g_isUsed) { + return Error::BUSY; + } + g_status = Status::INITIALIZED; + CommonDialog::g_isUsed = true; + + return Error::OK; +} + +s32 PS4_SYSV_ABI sceSaveDataDialogIsReadyToDisplay() { + return 1; +} + +Error PS4_SYSV_ABI sceSaveDataDialogOpen(const OrbisSaveDataDialogParam* param) { + if (g_status != Status::INITIALIZED && g_status != Status::FINISHED) { + LOG_INFO(Lib_SaveDataDialog, "called without initialize"); + return Error::INVALID_STATE; + } + if (param == nullptr) { + LOG_DEBUG(Lib_SaveDataDialog, "called param:(NULL)"); + return Error::ARG_NULL; + } + LOG_DEBUG(Lib_SaveDataDialog, "called param->mode: {}", magic_enum::enum_name(param->mode)); + ASSERT(param->size == sizeof(OrbisSaveDataDialogParam)); + ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam)); + g_result = {}; + g_state = SaveDialogState{*param}; + g_status = Status::RUNNING; + g_save_dialog_ui = SaveDialogUi(&g_state, &g_status, &g_result); + return Error::OK; +} + +Error PS4_SYSV_ABI sceSaveDataDialogProgressBarInc(OrbisSaveDataDialogProgressBarTarget target, + u32 delta) { + LOG_DEBUG(Lib_SaveDataDialog, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + if (g_state.GetMode() != SaveDataDialogMode::PROGRESS_BAR) { + return Error::NOT_SUPPORTED; + } + if (target != OrbisSaveDataDialogProgressBarTarget::DEFAULT) { + return Error::PARAM_INVALID; + } + g_state.GetState().progress += delta; + return Error::OK; +} + +Error PS4_SYSV_ABI sceSaveDataDialogProgressBarSetValue(OrbisSaveDataDialogProgressBarTarget target, + u32 rate) { + LOG_DEBUG(Lib_SaveDataDialog, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + if (g_state.GetMode() != SaveDataDialogMode::PROGRESS_BAR) { + return Error::NOT_SUPPORTED; + } + if (target != OrbisSaveDataDialogProgressBarTarget::DEFAULT) { + return Error::PARAM_INVALID; + } + g_state.GetState().progress = rate; + return Error::OK; +} + +Error PS4_SYSV_ABI sceSaveDataDialogTerminate() { + LOG_DEBUG(Lib_SaveDataDialog, "called"); + if (g_status == Status::RUNNING) { + sceSaveDataDialogClose(); + } + if (g_status == Status::NONE) { + return Error::NOT_INITIALIZED; + } + g_save_dialog_ui = SaveDialogUi{}; + g_status = Status::NONE; + CommonDialog::g_isUsed = false; + return Error::OK; +} + +Status PS4_SYSV_ABI sceSaveDataDialogUpdateStatus() { + LOG_TRACE(Lib_SaveDataDialog, "called status={}", magic_enum::enum_name(g_status)); + return g_status; +} + +void RegisterlibSceSaveDataDialog(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("fH46Lag88XY", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogClose); + LIB_FUNCTION("yEiJ-qqr6Cg", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogGetResult); + LIB_FUNCTION("ERKzksauAJA", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogGetStatus); + LIB_FUNCTION("s9e3+YpRnzw", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogInitialize); + LIB_FUNCTION("en7gNVnh878", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogIsReadyToDisplay); + LIB_FUNCTION("4tPhsP6FpDI", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogOpen); + LIB_FUNCTION("V-uEeFKARJU", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogProgressBarInc); + LIB_FUNCTION("hay1CfTmLyA", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogProgressBarSetValue); + LIB_FUNCTION("YuH2FA7azqQ", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogTerminate); + LIB_FUNCTION("KK3Bdg1RWK0", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, + sceSaveDataDialogUpdateStatus); +}; + +} // namespace Libraries::SaveData::Dialog diff --git a/src/core/libraries/save_data/dialog/savedatadialog.h b/src/core/libraries/save_data/dialog/savedatadialog.h new file mode 100644 index 000000000..34afe98a7 --- /dev/null +++ b/src/core/libraries/save_data/dialog/savedatadialog.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" +#include "core/libraries/system/commondialog.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::SaveData::Dialog { + +struct OrbisSaveDataDialogParam; +struct OrbisSaveDataDialogResult; +enum class OrbisSaveDataDialogProgressBarTarget : u32; + +CommonDialog::Error PS4_SYSV_ABI sceSaveDataDialogClose(); +CommonDialog::Error PS4_SYSV_ABI sceSaveDataDialogGetResult(OrbisSaveDataDialogResult* result); +CommonDialog::Status PS4_SYSV_ABI sceSaveDataDialogGetStatus(); +CommonDialog::Error PS4_SYSV_ABI sceSaveDataDialogInitialize(); +s32 PS4_SYSV_ABI sceSaveDataDialogIsReadyToDisplay(); +CommonDialog::Error PS4_SYSV_ABI sceSaveDataDialogOpen(const OrbisSaveDataDialogParam* param); +CommonDialog::Error PS4_SYSV_ABI +sceSaveDataDialogProgressBarInc(OrbisSaveDataDialogProgressBarTarget target, u32 delta); +CommonDialog::Error PS4_SYSV_ABI +sceSaveDataDialogProgressBarSetValue(OrbisSaveDataDialogProgressBarTarget target, u32 rate); +CommonDialog::Error PS4_SYSV_ABI sceSaveDataDialogTerminate(); +CommonDialog::Status PS4_SYSV_ABI sceSaveDataDialogUpdateStatus(); + +void RegisterlibSceSaveDataDialog(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::SaveData::Dialog diff --git a/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp b/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp new file mode 100644 index 000000000..01e56f8b8 --- /dev/null +++ b/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp @@ -0,0 +1,852 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include + +#include "common/elf_info.h" +#include "common/singleton.h" +#include "common/string_util.h" +#include "core/file_sys/fs.h" +#include "core/libraries/save_data/save_instance.h" +#include "imgui/imgui_std.h" +#include "savedatadialog_ui.h" + +using namespace ImGui; +using namespace Libraries::CommonDialog; +using Common::ElfInfo; + +constexpr u32 OrbisSaveDataBlockSize = 32768; // 32 KiB + +constexpr auto SAVE_ICON_SIZE = ImVec2{152.0f, 85.0f}; +constexpr auto SAVE_ICON_PADDING = ImVec2{8.0f, 2.0f}; + +static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; +constexpr auto FOOTER_HEIGHT = BUTTON_SIZE.y + 15.0f; +static constexpr float PROGRESS_BAR_WIDTH{0.8f}; + +static ::Core::FileSys::MntPoints* g_mnt = + Common::Singleton<::Core::FileSys::MntPoints>::Instance(); + +static std::string SpaceSizeToString(size_t size) { + std::string size_str; + if (size > 1024 * 1024 * 1024) { // > 1GB + size_str = fmt::format("{:.2f} GB", double(size / 1024 / 1024) / 1024.0f); + } else if (size > 1024 * 1024) { // > 1MB + size_str = fmt::format("{:.2f} MB", double(size / 1024) / 1024.0f); + } else if (size > 1024) { // > 1KB + size_str = fmt::format("{:.2f} KB", double(size) / 1024.0f); + } else { + size_str = fmt::format("{} B", size); + } + return size_str; +} + +namespace Libraries::SaveData::Dialog { + +void SaveDialogResult::CopyTo(OrbisSaveDataDialogResult& result) const { + result.mode = this->mode; + result.result = this->result; + result.buttonId = this->button_id; + if (mode == SaveDataDialogMode::LIST || ElfInfo::Instance().FirmwareVer() >= ElfInfo::FW_45) { + if (result.dirName != nullptr) { + result.dirName->data.FromString(this->dir_name); + } + if (result.param != nullptr && this->param.GetString(SaveParams::MAINTITLE).has_value()) { + result.param->FromSFO(this->param); + } + } + result.userData = this->user_data; +} + +SaveDialogState::SaveDialogState(const OrbisSaveDataDialogParam& param) { + this->mode = param.mode; + this->type = param.dispType; + this->user_data = param.userData; + if (param.optionParam != nullptr) { + this->enable_back = {param.optionParam->back == OptionBack::ENABLE}; + } + + const auto& game_serial = Common::ElfInfo::Instance().GameSerial(); + + const auto item = param.items; + this->user_id = item->userId; + + if (item->titleId == nullptr) { + this->title_id = game_serial; + } else { + this->title_id = item->titleId->data.to_string(); + } + + if (item->dirName != nullptr) { + for (u32 i = 0; i < item->dirNameNum; i++) { + const auto dir_name = item->dirName[i].data.to_view(); + + if (dir_name.empty()) { + continue; + } + + auto dir_path = SaveInstance::MakeDirSavePath(user_id, title_id, dir_name); + + auto param_sfo_path = dir_path / "sce_sys" / "param.sfo"; + if (!std::filesystem::exists(param_sfo_path)) { + continue; + } + + PSF param_sfo; + param_sfo.Open(param_sfo_path); + + auto last_write = param_sfo.GetLastWrite(); +#if defined(_WIN32) && !defined(__GNUC__) && !defined(__MINGW32__) && !defined(__MINGW64__) + auto utc_time = std::chrono::file_clock::to_utc(last_write); +#else + auto utc_time = std::chrono::file_clock::to_sys(last_write); +#endif + std::string date_str = fmt::format("{:%d %b, %Y %R}", utc_time); + + size_t size = Common::FS::GetDirectorySize(dir_path); + std::string size_str = SpaceSizeToString(size); + + auto icon_path = dir_path / "sce_sys" / "icon0.png"; + RefCountedTexture icon; + if (std::filesystem::exists(icon_path)) { + icon = RefCountedTexture::DecodePngFile(icon_path); + } + + bool is_corrupted = std::filesystem::exists(dir_path / "sce_sys" / "corrupted"); + + this->save_list.emplace_back(Item{ + .dir_name = std::string{dir_name}, + .icon = icon, + + .title = + std::string{param_sfo.GetString(SaveParams::MAINTITLE).value_or("Unknown")}, + .subtitle = std::string{param_sfo.GetString(SaveParams::SUBTITLE).value_or("")}, + .details = std::string{param_sfo.GetString(SaveParams::DETAIL).value_or("")}, + .date = date_str, + .size = size_str, + .last_write = param_sfo.GetLastWrite(), + .pfo = param_sfo, + .is_corrupted = is_corrupted, + }); + } + } + + if (type == DialogType::SAVE && item->newItem != nullptr) { + RefCountedTexture icon; + std::string title{"New Save"}; + + const auto new_item = item->newItem; + if (new_item->iconBuf && new_item->iconSize) { + auto buf = (u8*)new_item->iconBuf; + icon = RefCountedTexture::DecodePngTexture({buf, buf + new_item->iconSize}); + } else { + const auto& src_icon = g_mnt->GetHostPath("/app0/sce_sys/save_data.png"); + if (std::filesystem::exists(src_icon)) { + icon = RefCountedTexture::DecodePngFile(src_icon); + } + } + if (new_item->title != nullptr) { + title = std::string{new_item->title}; + } + + this->new_item = Item{ + .dir_name = "", + .icon = icon, + .title = title, + }; + } + + if (item->focusPos != FocusPos::DIRNAME) { + this->focus_pos = item->focusPos; + } else { + this->focus_pos = item->focusPosDirName->data.to_string(); + } + this->style = item->itemStyle; + + switch (mode) { + case SaveDataDialogMode::USER_MSG: { + this->state = UserState{param}; + } break; + case SaveDataDialogMode::SYSTEM_MSG: + this->state = SystemState{*this, param}; + break; + case SaveDataDialogMode::ERROR_CODE: { + this->state = ErrorCodeState{param}; + } break; + case SaveDataDialogMode::PROGRESS_BAR: { + this->state = ProgressBarState{*this, param}; + } break; + default: + break; + } +} + +SaveDialogState::UserState::UserState(const OrbisSaveDataDialogParam& param) { + auto& user = *param.userMsgParam; + this->type = user.buttonType; + this->msg_type = user.msgType; + this->msg = user.msg != nullptr ? std::string{user.msg} : std::string{}; +} + +SaveDialogState::SystemState::SystemState(const SaveDialogState& state, + const OrbisSaveDataDialogParam& param) { +#define M(save, load, del) \ + if (type == DialogType::SAVE) \ + this->msg = save; \ + else if (type == DialogType::LOAD) \ + this->msg = load; \ + else if (type == DialogType::DELETE) \ + this->msg = del; \ + else \ + UNREACHABLE() + + auto type = param.dispType; + auto& sys = *param.sysMsgParam; + switch (sys.msgType) { + case SystemMessageType::NODATA: { + return_cancel = true; + this->msg = "There is no saved data"; + } break; + case SystemMessageType::CONFIRM: + show_no = true; + M("Do you want to save?", "Do you want to load this saved data?", + "Do you want to delete this saved data?"); + break; + case SystemMessageType::OVERWRITE: + show_no = true; + M("Do you want to overwrite the existing saved data?", "##UNKNOWN##", "##UNKNOWN##"); + break; + case SystemMessageType::NOSPACE: + return_cancel = true; + M(fmt::format( + "There is not enough space to save the data. To continue {} free space is required.", + SpaceSizeToString(sys.value * OrbisSaveDataBlockSize)), + "##UNKNOWN##", "##UNKNOWN##"); + break; + case SystemMessageType::PROGRESS: + hide_ok = true; + show_cancel = state.enable_back.value_or(false); + M("Saving...", "Loading...", "Deleting..."); + break; + case SystemMessageType::FILE_CORRUPTED: + return_cancel = true; + this->msg = "The saved data is corrupted."; + break; + case SystemMessageType::FINISHED: + return_cancel = true; + M("Saved successfully.", "Loading complete.", "Deletion complete."); + break; + case SystemMessageType::NOSPACE_CONTINUABLE: + return_cancel = true; + M(fmt::format("There is not enough space to save the data. {} free space is required.", + SpaceSizeToString(sys.value * OrbisSaveDataBlockSize)), + "##UNKNOWN##", "##UNKNOWN##"); + break; + case SystemMessageType::CORRUPTED_AND_DELETED: { + show_cancel = state.enable_back.value_or(true); + const char* msg1 = "The saved data is corrupted and will be deleted."; + M(msg1, msg1, "##UNKNOWN##"); + } break; + case SystemMessageType::CORRUPTED_AND_CREATED: { + show_cancel = state.enable_back.value_or(true); + const char* msg2 = "The saved data is corrupted. This saved data will be deleted and a new " + "one will be created."; + M(msg2, msg2, "##UNKNOWN##"); + } break; + case SystemMessageType::CORRUPTED_AND_RESTORE: { + show_cancel = state.enable_back.value_or(true); + const char* msg3 = + "The saved data is corrupted. The data that was backed up by the system will be " + "restored."; + M(msg3, msg3, "##UNKNOWN##"); + } break; + case SystemMessageType::TOTAL_SIZE_EXCEEDED: + M("Cannot create more saved data", "##UNKNOWN##", "##UNKNOWN##"); + break; + default: + msg = fmt::format("Unknown message type: {}", magic_enum::enum_name(sys.msgType)); + break; + } + +#undef M +} + +SaveDialogState::ErrorCodeState::ErrorCodeState(const OrbisSaveDataDialogParam& param) { + auto& err = *param.errorCodeParam; + constexpr auto NOT_FOUND = 0x809F0008; + constexpr auto BROKEN = 0x809F000F; + switch (err.errorCode) { + case NOT_FOUND: + this->error_msg = "There is not saved data."; + break; + case BROKEN: + this->error_msg = "The data is corrupted."; + break; + default: + this->error_msg = fmt::format("An error has occurred. ({:X})", err.errorCode); + break; + } +} +SaveDialogState::ProgressBarState::ProgressBarState(const SaveDialogState& state, + const OrbisSaveDataDialogParam& param) { + static auto fw_ver = ElfInfo::Instance().FirmwareVer(); + + this->progress = 0; + + auto& bar = *param.progressBarParam; + + if (bar.msg != nullptr) { + this->msg = std::string{bar.msg}; + } else { + switch (bar.sysMsgType) { + case ProgressSystemMessageType::INVALID: + this->msg = ""; + break; + case ProgressSystemMessageType::PROGRESS: + switch (state.type) { + case DialogType::SAVE: + this->msg = "Saving..."; + break; + case DialogType::LOAD: + this->msg = "Loading..."; + break; + case DialogType::DELETE: + this->msg = "Deleting..."; + break; + } + break; + case ProgressSystemMessageType::RESTORE: + this->msg = "Restoring saved data..."; + break; + } + } +} + +SaveDialogUi::SaveDialogUi(SaveDialogState* state, Status* status, SaveDialogResult* result) + : state(state), status(status), result(result) { + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } +} + +SaveDialogUi::~SaveDialogUi() { + Finish(ButtonId::INVALID); +} + +SaveDialogUi::SaveDialogUi(SaveDialogUi&& other) noexcept + : Layer(other), state(other.state), status(other.status), result(other.result) { + std::scoped_lock lock(draw_mutex, other.draw_mutex); + other.state = nullptr; + other.status = nullptr; + other.result = nullptr; + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } +} + +SaveDialogUi& SaveDialogUi::operator=(SaveDialogUi other) { + std::scoped_lock lock(draw_mutex, other.draw_mutex); + using std::swap; + swap(state, other.state); + swap(status, other.status); + swap(result, other.result); + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } + return *this; +} + +void SaveDialogUi::Finish(ButtonId buttonId, Result r) { + std::unique_lock lock(draw_mutex); + if (result) { + result->mode = this->state->mode; + result->result = r; + result->button_id = buttonId; + result->user_data = this->state->user_data; + if (state && state->mode != SaveDataDialogMode::LIST && !state->save_list.empty()) { + result->dir_name = state->save_list.front().dir_name; + } + } + if (status) { + *status = Status::FINISHED; + } + RemoveLayer(this); +} + +void SaveDialogUi::Draw() { + std::unique_lock lock{draw_mutex}; + + if (status == nullptr || *status != Status::RUNNING || state == nullptr) { + return; + } + + const auto& ctx = *GetCurrentContext(); + const auto& io = ctx.IO; + + ImVec2 window_size; + + if (state->GetMode() == SaveDataDialogMode::LIST) { + window_size = ImVec2{ + std::min(io.DisplaySize.x - 200.0f, 1100.0f), + std::min(io.DisplaySize.y - 100.0f, 700.0f), + }; + } else { + window_size = ImVec2{ + std::min(io.DisplaySize.x, 600.0f), + std::min(io.DisplaySize.y, 300.0f), + }; + } + + CentralizeNextWindow(); + SetNextWindowSize(window_size); + SetNextWindowCollapsed(false); + if (first_render || !io.NavActive) { + SetNextWindowFocus(); + } + if (Begin("Save Data Dialog##SaveDataDialog", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { + DrawPrettyBackground(); + + Separator(); + // Draw title bigger + SetWindowFontScale(1.7f); + switch (state->type) { + case DialogType::SAVE: + TextUnformatted("Save"); + break; + case DialogType::LOAD: + TextUnformatted("Load"); + break; + case DialogType::DELETE: + TextUnformatted("Delete"); + break; + } + SetWindowFontScale(1.0f); + Separator(); + + BeginGroup(); + switch (state->GetMode()) { + case SaveDataDialogMode::LIST: + DrawList(); + break; + case SaveDataDialogMode::USER_MSG: + DrawUser(); + break; + case SaveDataDialogMode::SYSTEM_MSG: + DrawSystemMessage(); + break; + case SaveDataDialogMode::ERROR_CODE: + DrawErrorCode(); + break; + case SaveDataDialogMode::PROGRESS_BAR: + DrawProgressBar(); + break; + default: + TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "!!!Unknown dialog mode!!!"); + } + EndGroup(); + } + End(); + + first_render = false; + if (*status == Status::FINISHED) { + if (state) { + *state = SaveDialogState{}; + } + state = nullptr; + status = nullptr; + result = nullptr; + } +} + +void SaveDialogUi::DrawItem(int _id, const SaveDialogState::Item& item, bool clickable) { + constexpr auto text_spacing = 0.95f; + + auto& ctx = *GetCurrentContext(); + auto& window = *ctx.CurrentWindow; + + auto content_region_avail = GetContentRegionAvail(); + const auto outer_pos = window.DC.CursorPos; + const auto pos = outer_pos + SAVE_ICON_PADDING; + + const ImVec2 size = {content_region_avail.x - SAVE_ICON_PADDING.x, + SAVE_ICON_SIZE.y + SAVE_ICON_PADDING.y}; + const ImRect bb{outer_pos, outer_pos + size + SAVE_ICON_PADDING}; + + const ImGuiID id = GetID(_id); + + ItemSize(size + ImVec2{0.0f, SAVE_ICON_PADDING.y * 2.0f}); + if (!ItemAdd(bb, id)) { + return; + } + + window.DrawList->AddRectFilled(bb.Min + SAVE_ICON_PADDING, bb.Max - SAVE_ICON_PADDING, + GetColorU32(ImVec4{0.3f})); + + bool hovered = false; + if (clickable) { + bool held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + if (pressed) { + result->dir_name = item.dir_name; + result->param = item.pfo; + Finish(ButtonId::INVALID); + } + RenderNavHighlight(bb, id); + } + + if (item.icon) { + auto texture = item.icon.GetTexture(); + window.DrawList->AddImage(texture.im_id, pos, pos + SAVE_ICON_SIZE); + } else { + // placeholder + window.DrawList->AddRectFilled(pos, pos + SAVE_ICON_SIZE, GetColorU32(ImVec4{0.7f})); + } + + auto pos_x = SAVE_ICON_SIZE.x + 5.0f; + auto pos_y = 2.0f; + + if (!item.title.empty()) { + const char* begin = &item.title.front(); + const char* end = &item.title.back() + 1; + SetWindowFontScale(1.5f); + RenderText(pos + ImVec2{pos_x, pos_y}, begin, end, false); + pos_y += ctx.FontSize * text_spacing; + } + SetWindowFontScale(1.1f); + + if (item.is_corrupted) { + pos_y -= ctx.FontSize * text_spacing * 0.3f; + const auto bright = (int)std::abs(std::sin(ctx.Time) * 0.15f * 255.0f); + PushStyleColor(ImGuiCol_Text, IM_COL32(bright + 216, bright, bright, 0xFF)); + RenderText(pos + ImVec2{pos_x, pos_y}, "Corrupted", nullptr, false); + PopStyleColor(); + pos_y += ctx.FontSize * text_spacing * 0.8f; + } + + if (state->style == ItemStyle::TITLE_SUBTITLE_DATESIZE) { + if (!item.subtitle.empty()) { + const char* begin = &item.subtitle.front(); + const char* end = &item.subtitle.back() + 1; + RenderText(pos + ImVec2{pos_x, pos_y}, begin, end, false); + } + pos_y += ctx.FontSize * text_spacing; + } + + { + float width = 0.0f; + if (!item.date.empty()) { + const char* d_begin = &item.date.front(); + const char* d_end = &item.date.back() + 1; + width = CalcTextSize(d_begin, d_end).x + 15.0f; + RenderText(pos + ImVec2{pos_x, pos_y}, d_begin, d_end, false); + } + if (!item.size.empty()) { + const char* s_begin = &item.size.front(); + const char* s_end = &item.size.back() + 1; + RenderText(pos + ImVec2{pos_x + width, pos_y}, s_begin, s_end, false); + } + pos_y += ctx.FontSize * text_spacing; + } + + if (state->style == ItemStyle::TITLE_DATASIZE_SUBTITLE && !item.subtitle.empty()) { + const char* begin = &item.subtitle.front(); + const char* end = &item.subtitle.back() + 1; + RenderText(pos + ImVec2{pos_x, pos_y}, begin, end, false); + } + + SetWindowFontScale(1.0f); + + if (hovered) { + window.DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, 0, 2.0f); + } +} + +void SaveDialogUi::DrawList() { + auto availableSize = GetContentRegionAvail(); + + constexpr auto footerHeight = 30.0f; + availableSize.y -= footerHeight + 1.0f; + + BeginChild("##ScrollingRegion", availableSize, ImGuiChildFlags_NavFlattened); + int i = 0; + if (state->new_item.has_value()) { + DrawItem(i++, state->new_item.value()); + } + for (const auto& item : state->save_list) { + DrawItem(i++, item); + } + if (first_render) { // Make the initial focus + if (std::holds_alternative(state->focus_pos)) { + auto pos = std::get(state->focus_pos); + if (pos == FocusPos::LISTHEAD || pos == FocusPos::DATAHEAD) { + SetItemCurrentNavFocus(GetID(0)); + } else if (pos == FocusPos::LISTTAIL || pos == FocusPos::DATATAIL) { + SetItemCurrentNavFocus(GetID(std::max(i - 1, 0))); + } else { // Date + int idx = 0; + int max_idx = 0; + bool is_min = pos == FocusPos::DATAOLDEST; + std::filesystem::file_time_type max_write{}; + if (state->new_item.has_value()) { + idx++; + } + for (const auto& item : state->save_list) { + if (item.last_write > max_write ^ is_min) { + max_write = item.last_write; + max_idx = idx; + } + idx++; + } + SetItemCurrentNavFocus(GetID(max_idx)); + } + } else if (std::holds_alternative(state->focus_pos)) { + auto dir_name = std::get(state->focus_pos); + if (dir_name.empty()) { + SetItemCurrentNavFocus(GetID(0)); + } else { + int idx = 0; + if (state->new_item.has_value()) { + if (dir_name == state->new_item->dir_name) { + SetItemCurrentNavFocus(GetID(idx)); + } + idx++; + } + for (const auto& item : state->save_list) { + if (item.dir_name == dir_name) { + SetItemCurrentNavFocus(GetID(idx)); + break; + } + idx++; + } + } + } + } + EndChild(); + + Separator(); + if (state->enable_back.value_or(true)) { + constexpr auto back = "Back"; + constexpr float pad = 7.0f; + const auto txt_size = CalcTextSize(back); + const auto button_size = ImVec2{ + std::max(txt_size.x, 100.0f) + pad * 2.0f, + footerHeight - pad, + }; + SetCursorPosX(GetContentRegionAvail().x - button_size.x); + if (Button(back, button_size)) { + result->dir_name.clear(); + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } + if (IsKeyPressed(ImGuiKey_GamepadFaceRight)) { + SetItemCurrentNavFocus(); + } + } +} + +void SaveDialogUi::DrawUser() { + const auto& user_state = state->GetState(); + const auto btn_type = user_state.type; + + const auto ws = GetWindowSize(); + + if (!state->save_list.empty()) { + DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); + } + + auto has_btn = btn_type != ButtonType::NONE; + ImVec2 btn_space; + if (has_btn) { + btn_space = ImVec2{0.0f, FOOTER_HEIGHT}; + } + + const auto& msg = user_state.msg; + if (!msg.empty()) { + const char* begin = &msg.front(); + const char* end = &msg.back() + 1; + if (user_state.msg_type == UserMessageType::ERROR) { + PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); + // Maybe make the text bold? + } + DrawCenteredText(begin, end, GetContentRegionAvail() - btn_space); + if (user_state.msg_type == UserMessageType::ERROR) { + PopStyleColor(); + } + } + + if (has_btn) { + int count = 1; + if (btn_type == ButtonType::YESNO || btn_type == ButtonType::OKCANCEL) { + ++count; + } + + SetCursorPos({ + ws.x / 2.0f - BUTTON_SIZE.x / 2.0f * static_cast(count), + ws.y - FOOTER_HEIGHT + 5.0f, + }); + + BeginGroup(); + if (btn_type == ButtonType::YESNO) { + if (Button("Yes", BUTTON_SIZE)) { + Finish(ButtonId::YES); + } + SameLine(); + if (Button("No", BUTTON_SIZE)) { + if (ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::NO); + } + } + if (first_render || IsKeyPressed(ImGuiKey_GamepadFaceRight)) { + SetItemCurrentNavFocus(); + } + } else { + if (Button("OK", BUTTON_SIZE)) { + if (btn_type == ButtonType::OK && + ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::OK); + } + } + if (first_render) { + SetItemCurrentNavFocus(); + } + if (btn_type == ButtonType::OKCANCEL) { + SameLine(); + if (Button("Cancel", BUTTON_SIZE)) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } + if (IsKeyPressed(ImGuiKey_GamepadFaceRight)) { + SetItemCurrentNavFocus(); + } + } + } + EndGroup(); + } +} + +void SaveDialogUi::DrawSystemMessage() { + const auto& sys_state = state->GetState(); + + if (!state->save_list.empty()) { + DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); + } + + const auto ws = GetWindowSize(); + const auto& msg = sys_state.msg; + if (!msg.empty()) { + const char* begin = &msg.front(); + const char* end = &msg.back() + 1; + DrawCenteredText(begin, end, GetContentRegionAvail() - ImVec2{0.0f, FOOTER_HEIGHT}); + } + int count = 1; + if (sys_state.hide_ok) { + --count; + } + if (sys_state.show_no || sys_state.show_cancel) { + ++count; + } + + SetCursorPos({ + ws.x / 2.0f - BUTTON_SIZE.x / 2.0f * static_cast(count), + ws.y - FOOTER_HEIGHT + 5.0f, + }); + BeginGroup(); + if (Button(sys_state.show_no ? "Yes" : "OK", BUTTON_SIZE)) { + if (sys_state.return_cancel && ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::YES); + } + } + SameLine(); + if (sys_state.show_no) { + if (Button("No", BUTTON_SIZE)) { + if (ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::NO); + } + } + } else if (sys_state.show_cancel) { + if (Button("Cancel", BUTTON_SIZE)) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } + } + if (first_render || IsKeyPressed(ImGuiKey_GamepadFaceRight)) { + SetItemCurrentNavFocus(); + } + EndGroup(); +} + +void SaveDialogUi::DrawErrorCode() { + const auto& err_state = state->GetState(); + + if (!state->save_list.empty()) { + DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); + } + + const auto ws = GetWindowSize(); + const auto& msg = err_state.error_msg; + if (!msg.empty()) { + const char* begin = &msg.front(); + const char* end = &msg.back() + 1; + DrawCenteredText(begin, end, GetContentRegionAvail() - ImVec2{0.0f, FOOTER_HEIGHT}); + } + + SetCursorPos({ + ws.x / 2.0f - BUTTON_SIZE.x / 2.0f, + ws.y - FOOTER_HEIGHT + 5.0f, + }); + if (Button("OK", BUTTON_SIZE)) { + if (ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::OK); + } + } + if (first_render) { + SetItemCurrentNavFocus(); + } +} + +void SaveDialogUi::DrawProgressBar() { + const auto& bar_state = state->GetState(); + + const auto ws = GetWindowSize(); + + if (!state->save_list.empty()) { + DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); + } + + const auto& msg = bar_state.msg; + if (!msg.empty()) { + const char* begin = &msg.front(); + const char* end = &msg.back() + 1; + DrawCenteredText(begin, end, GetContentRegionAvail() - ImVec2{0.0f, FOOTER_HEIGHT}); + } + + SetCursorPos({ + ws.x * ((1 - PROGRESS_BAR_WIDTH) / 2.0f), + ws.y - FOOTER_HEIGHT + 5.0f, + }); + + ProgressBar(static_cast(bar_state.progress) / 100.0f, + {PROGRESS_BAR_WIDTH * ws.x, BUTTON_SIZE.y}); +} +}; // namespace Libraries::SaveData::Dialog \ No newline at end of file diff --git a/src/core/libraries/save_data/dialog/savedatadialog_ui.h b/src/core/libraries/save_data/dialog/savedatadialog_ui.h new file mode 100644 index 000000000..3f414470f --- /dev/null +++ b/src/core/libraries/save_data/dialog/savedatadialog_ui.h @@ -0,0 +1,319 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#include "core/file_format/psf.h" +#include "core/libraries/save_data/savedata.h" +#include "core/libraries/system/commondialog.h" +#include "imgui/imgui_layer.h" +#include "imgui/imgui_texture.h" + +namespace Libraries::SaveData::Dialog { + +using OrbisUserServiceUserId = s32; + +enum class SaveDataDialogMode : u32 { + INVALID = 0, + LIST = 1, + USER_MSG = 2, + SYSTEM_MSG = 3, + ERROR_CODE = 4, + PROGRESS_BAR = 5, +}; + +enum class DialogType : u32 { + SAVE = 1, + LOAD = 2, + DELETE = 3, +}; + +enum class DialogAnimation : u32 { + ON = 0, + OFF = 1, +}; + +enum class ButtonId : u32 { + INVALID = 0, + OK = 1, + YES = 1, + NO = 2, +}; + +enum class ButtonType : u32 { + OK = 0, + YESNO = 1, + NONE = 2, + OKCANCEL = 3, +}; + +enum class UserMessageType : u32 { + NORMAL = 0, + ERROR = 1, +}; + +enum class FocusPos : u32 { + LISTHEAD = 0, + LISTTAIL = 1, + DATAHEAD = 2, + DATATAIL = 3, + DATALTATEST = 4, + DATAOLDEST = 5, + DIRNAME = 6, +}; + +enum class ItemStyle : u32 { + TITLE_DATASIZE_SUBTITLE = 0, + TITLE_SUBTITLE_DATESIZE = 1, + TITLE_DATESIZE = 2, +}; + +enum class SystemMessageType : u32 { + NODATA = 1, + CONFIRM = 2, + OVERWRITE = 3, + NOSPACE = 4, + PROGRESS = 5, + FILE_CORRUPTED = 6, + FINISHED = 7, + NOSPACE_CONTINUABLE = 8, + CORRUPTED_AND_DELETED = 10, + CORRUPTED_AND_CREATED = 11, + CORRUPTED_AND_RESTORE = 13, + TOTAL_SIZE_EXCEEDED = 14, +}; + +enum class ProgressBarType : u32 { + PERCENTAGE = 0, +}; + +enum class ProgressSystemMessageType : u32 { + INVALID = 0, + PROGRESS = 1, + RESTORE = 2, +}; + +enum class OptionBack : u32 { + ENABLE = 0, + DISABLE = 1, +}; + +enum class OrbisSaveDataDialogProgressBarTarget : u32 { + DEFAULT = 0, +}; + +struct AnimationParam { + DialogAnimation userOK; + DialogAnimation userCancel; + std::array _reserved; +}; + +struct SaveDialogNewItem { + const char* title; + void* iconBuf; + size_t iconSize; + std::array _reserved; +}; + +struct SaveDialogItems { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + u32 dirNameNum; + s32 : 32; + const SaveDialogNewItem* newItem; + FocusPos focusPos; + s32 : 32; + const OrbisSaveDataDirName* focusPosDirName; + ItemStyle itemStyle; + std::array _reserved; +}; + +struct UserMessageParam { + ButtonType buttonType; + UserMessageType msgType; + const char* msg; + std::array _reserved; +}; + +struct SystemMessageParam { + SystemMessageType msgType; + s32 : 32; + u64 value; + std::array _reserved; +}; + +struct ErrorCodeParam { + u32 errorCode; + std::array _reserved; +}; + +struct ProgressBarParam { + ProgressBarType barType; + s32 : 32; + const char* msg; + ProgressSystemMessageType sysMsgType; + std::array _reserved; +}; + +struct OptionParam { + OptionBack back; + std::array _reserved; +}; + +struct OrbisSaveDataDialogParam { + CommonDialog::BaseParam baseParam; + s32 size; + SaveDataDialogMode mode; + DialogType dispType; + s32 : 32; + AnimationParam* animParam; + SaveDialogItems* items; + UserMessageParam* userMsgParam; + SystemMessageParam* sysMsgParam; + ErrorCodeParam* errorCodeParam; + ProgressBarParam* progressBarParam; + void* userData; + OptionParam* optionParam; + std::array _reserved; +}; + +struct OrbisSaveDataDialogResult { + SaveDataDialogMode mode{}; + CommonDialog::Result result{}; + ButtonId buttonId{}; + s32 : 32; + OrbisSaveDataDirName* dirName; + OrbisSaveDataParam* param; + void* userData; + std::array _reserved; +}; + +struct SaveDialogResult { + SaveDataDialogMode mode{}; + CommonDialog::Result result{CommonDialog::Result::OK}; + ButtonId button_id{ButtonId::INVALID}; + std::string dir_name{}; + PSF param{}; + void* user_data{}; + + void CopyTo(OrbisSaveDataDialogResult& result) const; +}; + +class SaveDialogState { + friend class SaveDialogUi; + +public: + struct UserState { + ButtonType type{}; + UserMessageType msg_type{}; + std::string msg{}; + + UserState(const OrbisSaveDataDialogParam& param); + }; + struct SystemState { + std::string msg{}; + bool hide_ok{}; + bool show_no{}; // Yes instead of OK + bool show_cancel{}; + + bool return_cancel{}; + + SystemState(const SaveDialogState& state, const OrbisSaveDataDialogParam& param); + }; + struct ErrorCodeState { + std::string error_msg{}; + + ErrorCodeState(const OrbisSaveDataDialogParam& param); + }; + struct ProgressBarState { + std::string msg{}; + u32 progress{}; + + ProgressBarState(const SaveDialogState& state, const OrbisSaveDataDialogParam& param); + }; + + struct Item { + std::string dir_name{}; + ImGui::RefCountedTexture icon{}; + + std::string title{}; + std::string subtitle{}; + std::string details{}; + std::string date{}; + std::string size{}; + + std::filesystem::file_time_type last_write{}; + PSF pfo{}; + bool is_corrupted{}; + }; + +private: + SaveDataDialogMode mode{}; + DialogType type{}; + void* user_data{}; + std::optional enable_back{}; + + OrbisUserServiceUserId user_id{}; + std::string title_id{}; + std::vector save_list{}; + std::variant focus_pos{std::monostate{}}; + ItemStyle style{}; + + std::optional new_item{}; + + std::variant state{ + std::monostate{}}; + +public: + explicit SaveDialogState(const OrbisSaveDataDialogParam& param); + + SaveDialogState() = default; + + [[nodiscard]] SaveDataDialogMode GetMode() const { + return mode; + } + + template + [[nodiscard]] T& GetState() { + return std::get(state); + } +}; + +class SaveDialogUi final : public ImGui::Layer { + bool first_render{false}; + SaveDialogState* state{}; + CommonDialog::Status* status{}; + SaveDialogResult* result{}; + + std::recursive_mutex draw_mutex{}; + +public: + explicit SaveDialogUi(SaveDialogState* state = nullptr, CommonDialog::Status* status = nullptr, + SaveDialogResult* result = nullptr); + + ~SaveDialogUi() override; + SaveDialogUi(const SaveDialogUi& other) = delete; + SaveDialogUi(SaveDialogUi&& other) noexcept; + SaveDialogUi& operator=(SaveDialogUi other); + + void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK); + + void Draw() override; + +private: + void DrawItem(int id, const SaveDialogState::Item& item, bool clickable = true); + + void DrawList(); + void DrawUser(); + void DrawSystemMessage(); + void DrawErrorCode(); + void DrawProgressBar(); +}; + +}; // namespace Libraries::SaveData::Dialog \ No newline at end of file diff --git a/src/core/libraries/save_data/error_codes.h b/src/core/libraries/save_data/error_codes.h deleted file mode 100644 index a4a1b7a5a..000000000 --- a/src/core/libraries/save_data/error_codes.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -constexpr int ORBIS_SAVE_DATA_ERROR_PARAMETER = 0x809F0000; -constexpr int ORBIS_SAVE_DATA_ERROR_NOT_INITIALIZED = 0x809F0001; -constexpr int ORBIS_SAVE_DATA_ERROR_OUT_OF_MEMORY = 0x809F0002; -constexpr int ORBIS_SAVE_DATA_ERROR_BUSY = 0x809F0003; -constexpr int ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED = 0x809F0004; -constexpr int ORBIS_SAVE_DATA_ERROR_NO_PERMISSION = 0x809F0005; -constexpr int ORBIS_SAVE_DATA_ERROR_FINGERPRINT_MISMATCH = 0x809F0006; -constexpr int ORBIS_SAVE_DATA_ERROR_EXISTS = 0x809F0007; -constexpr int ORBIS_SAVE_DATA_ERROR_NOT_FOUND = 0x809F0008; -constexpr int ORBIS_SAVE_DATA_ERROR_NO_SPACE_FS = 0x809F000A; -constexpr int ORBIS_SAVE_DATA_ERROR_INTERNAL = 0x809F000B; -constexpr int ORBIS_SAVE_DATA_ERROR_MOUNT_FULL = 0x809F000C; -constexpr int ORBIS_SAVE_DATA_ERROR_BAD_MOUNTED = 0x809F000D; -constexpr int ORBIS_SAVE_DATA_ERROR_FILE_NOT_FOUND = 0x809F000E; -constexpr int ORBIS_SAVE_DATA_ERROR_BROKEN = 0x809F000F; -constexpr int ORBIS_SAVE_DATA_ERROR_INVALID_LOGIN_USER = 0x809F0011; -constexpr int ORBIS_SAVE_DATA_ERROR_MEMORY_NOT_READY = 0x809F0012; -constexpr int ORBIS_SAVE_DATA_ERROR_BACKUP_BUSY = 0x809F0013; -constexpr int ORBIS_SAVE_DATA_ERROR_NOT_REGIST_CALLBACK = 0x809F0015; -constexpr int ORBIS_SAVE_DATA_ERROR_BUSY_FOR_SAVING = 0x809F0016; -constexpr int ORBIS_SAVE_DATA_ERROR_LIMITATION_OVER = 0x809F0017; -constexpr int ORBIS_SAVE_DATA_ERROR_EVENT_BUSY = 0x809F0018; -constexpr int ORBIS_SAVE_DATA_ERROR_PARAMSFO_TRANSFER_TITLE_ID_NOT_FOUND = 0x809F0019; diff --git a/src/core/libraries/save_data/save_backup.cpp b/src/core/libraries/save_data/save_backup.cpp new file mode 100644 index 000000000..da5172b15 --- /dev/null +++ b/src/core/libraries/save_data/save_backup.cpp @@ -0,0 +1,250 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include + +#include + +#include "save_backup.h" +#include "save_instance.h" + +#include "common/logging/log.h" +#include "common/logging/log_entry.h" +#include "common/polyfill_thread.h" +#include "common/thread.h" + +constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save +constexpr std::string_view backup_dir = "sce_backup"; // backup folder +constexpr std::string_view backup_dir_tmp = "sce_backup_tmp"; // in-progress backup folder +constexpr std::string_view backup_dir_old = "sce_backup_old"; // previous backup folder + +namespace fs = std::filesystem; + +namespace Libraries::SaveData::Backup { + +static std::jthread g_backup_thread; +static std::counting_semaphore g_backup_thread_semaphore{0}; + +static std::mutex g_backup_running_mutex; + +static std::mutex g_backup_queue_mutex; +static std::deque g_backup_queue; +static std::deque g_result_queue; + +static std::atomic_int g_backup_progress = 0; +static std::atomic g_backup_status = WorkerStatus::NotStarted; + +static void backup(const std::filesystem::path& dir_name) { + std::unique_lock lk{g_backup_running_mutex}; + if (!fs::exists(dir_name)) { + return; + } + + const auto backup_dir = dir_name / ::backup_dir; + const auto backup_dir_tmp = dir_name / ::backup_dir_tmp; + const auto backup_dir_old = dir_name / ::backup_dir_old; + + fs::remove_all(backup_dir_tmp); + fs::remove_all(backup_dir_old); + + std::vector backup_files; + for (const auto& entry : fs::directory_iterator(dir_name)) { + const auto filename = entry.path().filename(); + if (filename != ::backup_dir) { + backup_files.push_back(entry.path()); + } + } + + g_backup_progress = 0; + + int total_count = static_cast(backup_files.size()); + int current_count = 0; + + fs::create_directory(backup_dir_tmp); + for (const auto& file : backup_files) { + fs::copy(file, backup_dir_tmp / file.filename(), fs::copy_options::recursive); + current_count++; + g_backup_progress = current_count * 100 / total_count; + } + bool has_existing_backup = fs::exists(backup_dir); + if (has_existing_backup) { + fs::rename(backup_dir, backup_dir_old); + } + fs::rename(backup_dir_tmp, backup_dir); + if (has_existing_backup) { + fs::remove_all(backup_dir_old); + } +} + +static void BackupThreadBody() { + Common::SetCurrentThreadName("shadPS4:SaveData_BackupThread"); + while (g_backup_status != WorkerStatus::Stopping) { + g_backup_status = WorkerStatus::Waiting; + + bool wait; + BackupRequest req; + { + std::scoped_lock lk{g_backup_queue_mutex}; + wait = g_backup_queue.empty(); + if (!wait) { + req = g_backup_queue.front(); + } + } + if (wait) { + g_backup_thread_semaphore.acquire(); + { + std::scoped_lock lk{g_backup_queue_mutex}; + if (g_backup_queue.empty()) { + continue; + } + req = g_backup_queue.front(); + } + } + if (req.save_path.empty()) { + break; + } + g_backup_status = WorkerStatus::Running; + + LOG_INFO(Lib_SaveData, "Backing up the following directory: {}", + fmt::UTF(req.save_path.u8string())); + try { + backup(req.save_path); + } catch (const std::filesystem::filesystem_error& err) { + LOG_ERROR(Lib_SaveData, "Failed to backup {}: {}", fmt::UTF(req.save_path.u8string()), + err.what()); + } + LOG_DEBUG(Lib_SaveData, "Backing up the following directory: {} finished", + fmt::UTF(req.save_path.u8string())); + { + std::scoped_lock lk{g_backup_queue_mutex}; + g_backup_queue.front().done = true; + } + std::this_thread::sleep_for(std::chrono::seconds(5)); // Don't backup too often + { + std::scoped_lock lk{g_backup_queue_mutex}; + g_backup_queue.pop_front(); + g_result_queue.push_back(std::move(req)); + if (g_result_queue.size() > 20) { + g_result_queue.pop_front(); + } + } + } + g_backup_status = WorkerStatus::NotStarted; +} + +void StartThread() { + if (g_backup_status != WorkerStatus::NotStarted) { + return; + } + LOG_DEBUG(Lib_SaveData, "Starting backup thread"); + g_backup_status = WorkerStatus::Waiting; + g_backup_thread = std::jthread{BackupThreadBody}; +} + +void StopThread() { + if (g_backup_status == WorkerStatus::NotStarted || g_backup_status == WorkerStatus::Stopping) { + return; + } + LOG_DEBUG(Lib_SaveData, "Stopping backup thread"); + { + std::scoped_lock lk{g_backup_queue_mutex}; + g_backup_queue.emplace_back(BackupRequest{}); + } + g_backup_thread_semaphore.release(); + g_backup_status = WorkerStatus::Stopping; +} + +bool NewRequest(OrbisUserServiceUserId user_id, std::string_view title_id, + std::string_view dir_name, OrbisSaveDataEventType origin) { + auto save_path = SaveInstance::MakeDirSavePath(user_id, title_id, dir_name); + + if (g_backup_status != WorkerStatus::Waiting && g_backup_status != WorkerStatus::Running) { + LOG_ERROR(Lib_SaveData, "Called backup while status is {}. Backup request to {} ignored", + magic_enum::enum_name(g_backup_status.load()), fmt::UTF(save_path.u8string())); + return false; + } + { + std::scoped_lock lk{g_backup_queue_mutex}; + for (const auto& it : g_backup_queue) { + if (it.dir_name == dir_name) { + LOG_TRACE(Lib_SaveData, "Backup request to {} ignored. Already queued", dir_name); + return false; + } + } + g_backup_queue.push_back(BackupRequest{ + .user_id = user_id, + .title_id = std::string{title_id}, + .dir_name = std::string{dir_name}, + .origin = origin, + .save_path = std::move(save_path), + }); + } + g_backup_thread_semaphore.release(); + return true; +} + +bool Restore(const std::filesystem::path& save_path) { + LOG_INFO(Lib_SaveData, "Restoring backup for {}", fmt::UTF(save_path.u8string())); + std::unique_lock lk{g_backup_running_mutex}; + if (!fs::exists(save_path) || !fs::exists(save_path / backup_dir)) { + return false; + } + for (const auto& entry : fs::directory_iterator(save_path)) { + const auto filename = entry.path().filename(); + if (filename != backup_dir) { + fs::remove_all(entry.path()); + } + } + + for (const auto& entry : fs::directory_iterator(save_path / backup_dir)) { + const auto filename = entry.path().filename(); + fs::copy(entry.path(), save_path / filename, fs::copy_options::recursive); + } + + return true; +} + +WorkerStatus GetWorkerStatus() { + return g_backup_status; +} + +bool IsBackupExecutingFor(const std::filesystem::path& save_path) { + std::scoped_lock lk{g_backup_queue_mutex}; + const auto& it = + std::ranges::find(g_backup_queue, save_path, [](const auto& v) { return v.save_path; }); + return it != g_backup_queue.end() && !it->done; +} + +std::filesystem::path MakeBackupPath(const std::filesystem::path& save_path) { + return save_path / backup_dir; +} + +std::optional PopLastEvent() { + std::scoped_lock lk{g_backup_queue_mutex}; + if (g_result_queue.empty()) { + return std::nullopt; + } + auto req = std::move(g_result_queue.front()); + g_result_queue.pop_front(); + return req; +} + +void PushBackupEvent(BackupRequest&& req) { + std::scoped_lock lk{g_backup_queue_mutex}; + g_result_queue.push_back(std::move(req)); + if (g_result_queue.size() > 20) { + g_result_queue.pop_front(); + } +} + +float GetProgress() { + return static_cast(g_backup_progress) / 100.0f; +} + +void ClearProgress() { + g_backup_progress = 0; +} + +} // namespace Libraries::SaveData::Backup \ No newline at end of file diff --git a/src/core/libraries/save_data/save_backup.h b/src/core/libraries/save_data/save_backup.h new file mode 100644 index 000000000..e49c69f60 --- /dev/null +++ b/src/core/libraries/save_data/save_backup.h @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/types.h" + +namespace Libraries::SaveData { + +using OrbisUserServiceUserId = s32; + +namespace Backup { + +enum class WorkerStatus { + NotStarted, + Waiting, + Running, + Stopping, +}; + +enum class OrbisSaveDataEventType : u32 { + UMOUNT_BACKUP = 1, + BACKUP = 2, + SAVE_DATA_MEMORY_SYNC = 3, +}; + +struct BackupRequest { + bool done{}; + + OrbisUserServiceUserId user_id{}; + std::string title_id{}; + std::string dir_name{}; + OrbisSaveDataEventType origin{}; + + std::filesystem::path save_path{}; +}; + +// No problem calling this function if the backup thread is already running +void StartThread(); + +void StopThread(); + +bool NewRequest(OrbisUserServiceUserId user_id, std::string_view title_id, + std::string_view dir_name, OrbisSaveDataEventType origin); + +bool Restore(const std::filesystem::path& save_path); + +WorkerStatus GetWorkerStatus(); + +bool IsBackupExecutingFor(const std::filesystem::path& save_path); + +std::filesystem::path MakeBackupPath(const std::filesystem::path& save_path); + +std::optional PopLastEvent(); + +void PushBackupEvent(BackupRequest&& req); + +float GetProgress(); + +void ClearProgress(); + +} // namespace Backup + +} // namespace Libraries::SaveData diff --git a/src/core/libraries/save_data/save_instance.cpp b/src/core/libraries/save_data/save_instance.cpp new file mode 100644 index 000000000..0d6c5173c --- /dev/null +++ b/src/core/libraries/save_data/save_instance.cpp @@ -0,0 +1,226 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include + +#include "common/assert.h" +#include "common/config.h" +#include "common/path_util.h" +#include "common/singleton.h" +#include "core/file_sys/fs.h" +#include "save_instance.h" + +constexpr auto OrbisSaveDataBlocksMin2 = 96; // 3MiB +constexpr auto OrbisSaveDataBlocksMax = 32768; // 1 GiB +constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save + +static Core::FileSys::MntPoints* g_mnt = Common::Singleton::Instance(); + +namespace fs = std::filesystem; + +// clang-format off +static const std::unordered_map default_title = { + {"ja_JP", "セーブデータ"}, + {"en", "Saved Data"}, + {"fr", "Données sauvegardées"}, + {"es_ES", "Datos guardados"}, + {"de", "Gespeicherte Daten"}, + {"it", "Dati salvati"}, + {"nl", "Opgeslagen data"}, + {"pt_PT", "Dados guardados"}, + {"ru", "Сохраненные данные"}, + {"ko_KR", "저장 데이터"}, + {"zh_CN", "保存数据"}, + {"fi", "Tallennetut tiedot"}, + {"sv_SE", "Sparade data"}, + {"da_DK", "Gemte data"}, + {"no_NO", "Lagrede data"}, + {"pl_PL", "Zapisane dane"}, + {"pt_BR", "Dados salvos"}, + {"tr_TR", "Kayıtlı Veriler"}, +}; +// clang-format on + +namespace Libraries::SaveData { + +std::filesystem::path SaveInstance::MakeTitleSavePath(OrbisUserServiceUserId user_id, + std::string_view game_serial) { + return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / + game_serial; +} + +std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_id, + std::string_view game_serial, + std::string_view dir_name) { + return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / + game_serial / dir_name; +} + +uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) { + const auto vec = psf.GetBinary(std::string{SaveParams::SAVEDATA_BLOCKS}); + if (!vec.has_value()) { + return OrbisSaveDataBlocksMax; + } + auto value = vec.value(); + return *(uint64_t*)value.data(); +} + +std::filesystem::path SaveInstance::GetParamSFOPath(const std::filesystem::path& dir_path) { + return dir_path / sce_sys / "param.sfo"; +} + +void SaveInstance::SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name, + std::string game_serial) { + std::string locale = Config::getEmulatorLanguage(); + if (!default_title.contains(locale)) { + locale = "en"; + } + +#define P(type, key, ...) param_sfo.Add##type(std::string{key}, __VA_ARGS__) + // TODO Link with user service + P(Binary, SaveParams::ACCOUNT_ID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + P(String, SaveParams::MAINTITLE, default_title.at(locale)); + P(String, SaveParams::SUBTITLE, ""); + P(String, SaveParams::DETAIL, ""); + P(String, SaveParams::SAVEDATA_DIRECTORY, std::move(dir_name)); + P(Integer, SaveParams::SAVEDATA_LIST_PARAM, 0); + P(String, SaveParams::TITLE_ID, std::move(game_serial)); + P(Binary, SaveParams::SAVEDATA_BLOCKS, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); +#undef P +} + +SaveInstance::SaveInstance(int slot_num, OrbisUserServiceUserId user_id, std::string _game_serial, + std::string_view _dir_name, int max_blocks) + : slot_num(slot_num), user_id(user_id), game_serial(std::move(_game_serial)), + dir_name(_dir_name), + max_blocks(std::clamp(max_blocks, OrbisSaveDataBlocksMin2, OrbisSaveDataBlocksMax)) { + ASSERT(slot_num >= 0 && slot_num < 16); + + save_path = MakeDirSavePath(user_id, game_serial, dir_name); + + const auto sce_sys_path = save_path / sce_sys; + param_sfo_path = sce_sys_path / "param.sfo"; + corrupt_file_path = sce_sys_path / "corrupted"; + + mount_point = "/savedata" + std::to_string(slot_num); + + this->exists = fs::exists(param_sfo_path); + this->mounted = g_mnt->GetMount(mount_point) != nullptr; +} + +SaveInstance::~SaveInstance() { + if (mounted) { + Umount(); + } +} +SaveInstance::SaveInstance(SaveInstance&& other) noexcept { + if (this == &other) + return; + *this = std::move(other); +} + +SaveInstance& SaveInstance::operator=(SaveInstance&& other) noexcept { + if (this == &other) + return *this; + slot_num = other.slot_num; + user_id = other.user_id; + game_serial = std::move(other.game_serial); + dir_name = std::move(other.dir_name); + save_path = std::move(other.save_path); + param_sfo_path = std::move(other.param_sfo_path); + corrupt_file_path = std::move(other.corrupt_file_path); + corrupt_file = std::move(other.corrupt_file); + param_sfo = std::move(other.param_sfo); + mount_point = std::move(other.mount_point); + max_blocks = other.max_blocks; + exists = other.exists; + mounted = other.mounted; + read_only = other.read_only; + + other.mounted = false; + + return *this; +} + +void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_corrupt) { + if (mounted) { + UNREACHABLE_MSG("Save instance is already mounted"); + } + this->exists = fs::exists(param_sfo_path); // check again just in case + if (!exists) { + CreateFiles(); + if (copy_icon) { + const auto& src_icon = g_mnt->GetHostPath("/app0/sce_sys/save_data.png"); + if (fs::exists(src_icon)) { + auto output_icon = GetIconPath(); + if (fs::exists(output_icon)) { + fs::remove(output_icon); + } + fs::copy_file(src_icon, output_icon); + } + } + exists = true; + } else { + if (!ignore_corrupt && fs::exists(corrupt_file_path)) { + throw std::filesystem::filesystem_error( + "Corrupted save data", corrupt_file_path, + std::make_error_code(std::errc::illegal_byte_sequence)); + } + if (!param_sfo.Open(param_sfo_path)) { + throw std::filesystem::filesystem_error( + "Failed to read param.sfo", param_sfo_path, + std::make_error_code(std::errc::illegal_byte_sequence)); + } + } + + if (!ignore_corrupt && !read_only) { + int err = corrupt_file.Open(corrupt_file_path, Common::FS::FileAccessMode::Write); + if (err != 0) { + throw std::filesystem::filesystem_error( + "Failed to open corrupted file", corrupt_file_path, + std::make_error_code(std::errc::illegal_byte_sequence)); + } + } + + max_blocks = static_cast(GetMaxBlockFromSFO(param_sfo)); + + g_mnt->Mount(save_path, mount_point, read_only); + mounted = true; + this->read_only = read_only; +} + +void SaveInstance::Umount() { + if (!mounted) { + UNREACHABLE_MSG("Save instance is not mounted"); + return; + } + mounted = false; + const bool ok = param_sfo.Encode(param_sfo_path); + if (!ok) { + throw std::filesystem::filesystem_error("Failed to write param.sfo", param_sfo_path, + std::make_error_code(std::errc::permission_denied)); + } + param_sfo = PSF(); + + corrupt_file.Close(); + fs::remove(corrupt_file_path); + g_mnt->Unmount(save_path, mount_point); +} + +void SaveInstance::CreateFiles() { + const auto sce_sys_dir = save_path / sce_sys; + fs::create_directories(sce_sys_dir); + + SetupDefaultParamSFO(param_sfo, dir_name, game_serial); + param_sfo.AddBinary(std::string{SaveParams::SAVEDATA_BLOCKS}, max_blocks, true); + + const bool ok = param_sfo.Encode(param_sfo_path); + if (!ok) { + throw std::filesystem::filesystem_error("Failed to write param.sfo", param_sfo_path, + std::make_error_code(std::errc::permission_denied)); + } +} + +} // namespace Libraries::SaveData \ No newline at end of file diff --git a/src/core/libraries/save_data/save_instance.h b/src/core/libraries/save_data/save_instance.h new file mode 100644 index 000000000..3be5c4595 --- /dev/null +++ b/src/core/libraries/save_data/save_instance.h @@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/io_file.h" +#include "core/file_format/psf.h" + +namespace Core::FileSys { +class MntPoints; +} + +namespace Libraries::SaveData { + +// Used constexpr to easily use as string +namespace SaveParams { +constexpr std::string_view ACCOUNT_ID = "ACCOUNT_ID"; +constexpr std::string_view ATTRIBUTE = "ATTRIBUTE"; +constexpr std::string_view CATEGORY = "CATEGORY"; +constexpr std::string_view DETAIL = "DETAIL"; +constexpr std::string_view FORMAT = "FORMAT"; +constexpr std::string_view MAINTITLE = "MAINTITLE"; +constexpr std::string_view PARAMS = "PARAMS"; +constexpr std::string_view SAVEDATA_BLOCKS = "SAVEDATA_BLOCKS"; +constexpr std::string_view SAVEDATA_DIRECTORY = "SAVEDATA_DIRECTORY"; +constexpr std::string_view SAVEDATA_LIST_PARAM = "SAVEDATA_LIST_PARAM"; +constexpr std::string_view SUBTITLE = "SUBTITLE"; +constexpr std::string_view TITLE_ID = "TITLE_ID"; +} // namespace SaveParams + +using OrbisUserServiceUserId = s32; + +class SaveInstance { + int slot_num{}; + int user_id{}; + std::string game_serial; + std::string dir_name; + + std::filesystem::path save_path; + std::filesystem::path param_sfo_path; + std::filesystem::path corrupt_file_path; + + Common::FS::IOFile corrupt_file; + + PSF param_sfo; + std::string mount_point; + + int max_blocks{}; + bool exists{}; + bool mounted{}; + bool read_only{}; + +public: + // Location of all save data for a title + static std::filesystem::path MakeTitleSavePath(OrbisUserServiceUserId user_id, + std::string_view game_serial); + + // Location of a specific save data directory + static std::filesystem::path MakeDirSavePath(OrbisUserServiceUserId user_id, + std::string_view game_serial, + std::string_view dir_name); + + static uint64_t GetMaxBlockFromSFO(const PSF& psf); + + // Get param.sfo path from a dir_path generated by MakeDirSavePath + static std::filesystem::path GetParamSFOPath(const std::filesystem::path& dir_path); + + static void SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name, std::string game_serial); + + explicit SaveInstance(int slot_num, OrbisUserServiceUserId user_id, std::string game_serial, + std::string_view dir_name, int max_blocks = 0); + + ~SaveInstance(); + + SaveInstance(const SaveInstance& other) = delete; + SaveInstance(SaveInstance&& other) noexcept; + + SaveInstance& operator=(const SaveInstance& other) = delete; + SaveInstance& operator=(SaveInstance&& other) noexcept; + + void SetupAndMount(bool read_only = false, bool copy_icon = false, bool ignore_corrupt = false); + + void Umount(); + + [[nodiscard]] std::filesystem::path GetIconPath() const noexcept { + return save_path / "sce_sys" / "icon0.png"; + } + + [[nodiscard]] bool Exists() const noexcept { + return exists; + } + + [[nodiscard]] OrbisUserServiceUserId GetUserId() const noexcept { + return user_id; + } + + [[nodiscard]] std::string_view GetTitleId() const noexcept { + return game_serial; + } + + [[nodiscard]] const std::string& GetDirName() const noexcept { + return dir_name; + } + + [[nodiscard]] const std::filesystem::path& GetSavePath() const noexcept { + return save_path; + } + + [[nodiscard]] const PSF& GetParamSFO() const noexcept { + return param_sfo; + } + + [[nodiscard]] PSF& GetParamSFO() noexcept { + return param_sfo; + } + + [[nodiscard]] const std::string& GetMountPoint() const noexcept { + return mount_point; + } + + [[nodiscard]] int GetMaxBlocks() const noexcept { + return max_blocks; + } + + [[nodiscard]] bool Mounted() const noexcept { + return mounted; + } + + [[nodiscard]] bool IsReadOnly() const noexcept { + return read_only; + } + + void CreateFiles(); +}; + +} // namespace Libraries::SaveData diff --git a/src/core/libraries/save_data/save_memory.cpp b/src/core/libraries/save_data/save_memory.cpp new file mode 100644 index 000000000..e9ef53761 --- /dev/null +++ b/src/core/libraries/save_data/save_memory.cpp @@ -0,0 +1,287 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "save_memory.h" + +#include +#include +#include +#include +#include + +#include + +#include "common/assert.h" +#include "common/logging/log.h" +#include "common/polyfill_thread.h" +#include "common/singleton.h" +#include "common/thread.h" +#include "core/file_sys/fs.h" +#include "save_instance.h" + +using Common::FS::IOFile; +namespace fs = std::filesystem; + +constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save +constexpr std::string_view DirnameSaveDataMemory = "sce_sdmemory"; +constexpr std::string_view FilenameSaveDataMemory = "memory.dat"; + +namespace Libraries::SaveData::SaveMemory { + +static Core::FileSys::MntPoints* g_mnt = Common::Singleton::Instance(); + +static OrbisUserServiceUserId g_user_id{}; +static std::string g_game_serial{}; +static std::filesystem::path g_save_path{}; +static std::filesystem::path g_param_sfo_path{}; +static PSF g_param_sfo; + +static bool g_save_memory_initialized = false; +static std::mutex g_saving_memory_mutex; +static std::vector g_save_memory; + +static std::filesystem::path g_icon_path; +static std::vector g_icon_memory; + +static std::condition_variable g_trigger_save_memory; +static std::atomic_bool g_saving_memory = false; +static std::atomic_bool g_save_event = false; +static std::jthread g_save_memory_thread; + +static std::atomic_bool g_memory_dirty = false; +static std::atomic_bool g_param_dirty = false; +static std::atomic_bool g_icon_dirty = false; + +static void SaveFileSafe(void* buf, size_t count, const std::filesystem::path& path) { + const auto& dir = path.parent_path(); + const auto& name = path.filename(); + const auto tmp_path = dir / (name.string() + ".tmp"); + + IOFile file(tmp_path, Common::FS::FileAccessMode::Write); + file.WriteRaw(buf, count); + file.Close(); + + fs::remove(path); + fs::rename(tmp_path, path); +} + +[[noreturn]] void SaveThreadLoop() { + Common::SetCurrentThreadName("shadPS4:SaveData_SaveDataMemoryThread"); + std::mutex mtx; + while (true) { + { + std::unique_lock lk{mtx}; + g_trigger_save_memory.wait(lk); + } + // Save the memory + g_saving_memory = true; + std::scoped_lock lk{g_saving_memory_mutex}; + try { + LOG_DEBUG(Lib_SaveData, "Saving save data memory {}", fmt::UTF(g_save_path.u8string())); + + if (g_memory_dirty) { + g_memory_dirty = false; + SaveFileSafe(g_save_memory.data(), g_save_memory.size(), + g_save_path / FilenameSaveDataMemory); + } + if (g_param_dirty) { + g_param_dirty = false; + static std::vector buf; + g_param_sfo.Encode(buf); + SaveFileSafe(buf.data(), buf.size(), g_param_sfo_path); + } + if (g_icon_dirty) { + g_icon_dirty = false; + SaveFileSafe(g_icon_memory.data(), g_icon_memory.size(), g_icon_path); + } + + if (g_save_event) { + Backup::PushBackupEvent(Backup::BackupRequest{ + .user_id = g_user_id, + .title_id = g_game_serial, + .dir_name = std::string{DirnameSaveDataMemory}, + .origin = Backup::OrbisSaveDataEventType::SAVE_DATA_MEMORY_SYNC, + .save_path = g_save_path, + }); + g_save_event = false; + } + } catch (const fs::filesystem_error& e) { + LOG_ERROR(Lib_SaveData, "Failed to save save data memory: {}", e.what()); + MsgDialog::ShowMsgDialog(MsgDialog::MsgDialogState{ + MsgDialog::MsgDialogState::UserState{ + .type = MsgDialog::ButtonType::OK, + .msg = fmt::format("Failed to save save data memory.\nCode: <{}>\n{}", + e.code().message(), e.what()), + }, + }); + } + g_saving_memory = false; + } +} + +void SetDirectories(OrbisUserServiceUserId user_id, std::string _game_serial) { + g_user_id = user_id; + g_game_serial = std::move(_game_serial); + g_save_path = SaveInstance::MakeDirSavePath(user_id, g_game_serial, DirnameSaveDataMemory); + g_param_sfo_path = SaveInstance::GetParamSFOPath(g_save_path); + g_param_sfo = PSF(); + g_icon_path = g_save_path / sce_sys / "icon0.png"; +} + +const std::filesystem::path& GetSavePath() { + return g_save_path; +} + +size_t CreateSaveMemory(size_t memory_size) { + size_t existed_size = 0; + + static std::once_flag init_save_thread_flag; + std::call_once(init_save_thread_flag, + [] { g_save_memory_thread = std::jthread{SaveThreadLoop}; }); + + g_save_memory.resize(memory_size); + SaveInstance::SetupDefaultParamSFO(g_param_sfo, std::string{DirnameSaveDataMemory}, + g_game_serial); + + g_save_memory_initialized = true; + + if (!fs::exists(g_param_sfo_path)) { + // Create save memory + fs::create_directories(g_save_path / sce_sys); + + IOFile memory_file{g_save_path / FilenameSaveDataMemory, Common::FS::FileAccessMode::Write}; + bool ok = memory_file.SetSize(memory_size); + if (!ok) { + LOG_ERROR(Lib_SaveData, "Failed to set memory size"); + throw std::filesystem::filesystem_error( + "Failed to set save memory size", g_save_path / FilenameSaveDataMemory, + std::make_error_code(std::errc::no_space_on_device)); + } + memory_file.Close(); + } else { + // Load save memory + + bool ok = g_param_sfo.Open(g_param_sfo_path); + if (!ok) { + LOG_ERROR(Lib_SaveData, "Failed to open SFO at {}", + fmt::UTF(g_param_sfo_path.u8string())); + throw std::filesystem::filesystem_error( + "failed to open SFO", g_param_sfo_path, + std::make_error_code(std::errc::illegal_byte_sequence)); + } + + IOFile memory_file{g_save_path / FilenameSaveDataMemory, Common::FS::FileAccessMode::Read}; + if (!memory_file.IsOpen()) { + LOG_ERROR(Lib_SaveData, "Failed to open save memory"); + throw std::filesystem::filesystem_error( + "failed to open save memory", g_save_path / FilenameSaveDataMemory, + std::make_error_code(std::errc::permission_denied)); + } + size_t save_size = memory_file.GetSize(); + existed_size = save_size; + memory_file.Seek(0); + memory_file.ReadRaw(g_save_memory.data(), std::min(save_size, memory_size)); + memory_file.Close(); + } + + return existed_size; +} + +void SetIcon(void* buf, size_t buf_size) { + if (buf == nullptr) { + const auto& src_icon = g_mnt->GetHostPath("/app0/sce_sys/save_data.png"); + if (fs::exists(src_icon)) { + if (fs::exists(g_icon_path)) { + fs::remove(g_icon_path); + } + fs::copy_file(src_icon, g_icon_path); + } + if (fs::exists(g_icon_path)) { + IOFile file(g_icon_path, Common::FS::FileAccessMode::Read); + size_t size = file.GetSize(); + file.Seek(0); + g_icon_memory.resize(size); + file.ReadRaw(g_icon_memory.data(), size); + file.Close(); + } + } else { + g_icon_memory.resize(buf_size); + std::memcpy(g_icon_memory.data(), buf, buf_size); + IOFile file(g_icon_path, Common::FS::FileAccessMode::Write); + file.Seek(0); + file.WriteRaw(g_icon_memory.data(), buf_size); + file.Close(); + } +} + +void WriteIcon(void* buf, size_t buf_size) { + if (buf_size != g_icon_memory.size()) { + g_icon_memory.resize(buf_size); + } + std::memcpy(g_icon_memory.data(), buf, buf_size); + g_icon_dirty = true; +} + +bool IsSaveMemoryInitialized() { + return g_save_memory_initialized; +} + +PSF& GetParamSFO() { + return g_param_sfo; +} + +std::span GetIcon() { + return {g_icon_memory}; +} + +void SaveSFO(bool sync) { + if (!sync) { + g_param_dirty = true; + return; + } + const bool ok = g_param_sfo.Encode(g_param_sfo_path); + if (!ok) { + LOG_ERROR(Lib_SaveData, "Failed to encode param.sfo"); + throw std::filesystem::filesystem_error("Failed to write param.sfo", g_param_sfo_path, + std::make_error_code(std::errc::permission_denied)); + } +} +bool IsSaving() { + return g_saving_memory; +} + +bool TriggerSaveWithoutEvent() { + if (g_saving_memory) { + return false; + } + g_trigger_save_memory.notify_one(); + return true; +} + +bool TriggerSave() { + if (g_saving_memory) { + return false; + } + g_save_event = true; + g_trigger_save_memory.notify_one(); + return true; +} + +void ReadMemory(void* buf, size_t buf_size, int64_t offset) { + std::scoped_lock lk{g_saving_memory_mutex}; + if (offset + buf_size > g_save_memory.size()) { + UNREACHABLE_MSG("ReadMemory out of bounds"); + } + std::memcpy(buf, g_save_memory.data() + offset, buf_size); +} + +void WriteMemory(void* buf, size_t buf_size, int64_t offset) { + std::scoped_lock lk{g_saving_memory_mutex}; + if (offset + buf_size > g_save_memory.size()) { + g_save_memory.resize(offset + buf_size); + } + std::memcpy(g_save_memory.data() + offset, buf, buf_size); + g_memory_dirty = true; +} + +} // namespace Libraries::SaveData::SaveMemory \ No newline at end of file diff --git a/src/core/libraries/save_data/save_memory.h b/src/core/libraries/save_data/save_memory.h new file mode 100644 index 000000000..04eeaa652 --- /dev/null +++ b/src/core/libraries/save_data/save_memory.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "save_backup.h" + +class PSF; + +namespace Libraries::SaveData { +using OrbisUserServiceUserId = s32; +} + +namespace Libraries::SaveData::SaveMemory { + +void SetDirectories(OrbisUserServiceUserId user_id, std::string game_serial); + +[[nodiscard]] const std::filesystem::path& GetSavePath(); + +// returns the size of the existed save memory +size_t CreateSaveMemory(size_t memory_size); + +// Initialize the icon. Set buf to null to read the standard icon. +void SetIcon(void* buf, size_t buf_size); + +// Update the icon +void WriteIcon(void* buf, size_t buf_size); + +[[nodiscard]] bool IsSaveMemoryInitialized(); + +[[nodiscard]] PSF& GetParamSFO(); + +[[nodiscard]] std::span GetIcon(); + +// Save now or wait for the background thread to save +void SaveSFO(bool sync = false); + +[[nodiscard]] bool IsSaving(); + +bool TriggerSaveWithoutEvent(); + +bool TriggerSave(); + +void ReadMemory(void* buf, size_t buf_size, int64_t offset); + +void WriteMemory(void* buf, size_t buf_size, int64_t offset); + +} // namespace Libraries::SaveData::SaveMemory \ No newline at end of file diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 6652ee571..93b3c20a9 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -3,30 +3,562 @@ #include #include -#include -#include -#include -#include + +#include +#include + #include "common/assert.h" +#include "common/cstring.h" +#include "common/elf_info.h" +#include "common/enum.h" #include "common/logging/log.h" +#include "common/path_util.h" +#include "common/string_util.h" +#include "core/file_format/psf.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/save_data/savedata.h" -#include "error_codes.h" +#include "core/libraries/system/msgdialog.h" +#include "save_backup.h" +#include "save_instance.h" +#include "save_memory.h" + +namespace fs = std::filesystem; +namespace chrono = std::chrono; + +using Common::CString; +using Common::ElfInfo; namespace Libraries::SaveData { -bool is_rw_mode = false; -static constexpr std::string_view g_mount_point = "/savedata0"; // temp mount point (todo) -std::string game_serial; + +enum class Error : u32 { + OK = 0, + USER_SERVICE_NOT_INITIALIZED = 0x80960002, + PARAMETER = 0x809F0000, + NOT_INITIALIZED = 0x809F0001, + OUT_OF_MEMORY = 0x809F0002, + BUSY = 0x809F0003, + NOT_MOUNTED = 0x809F0004, + EXISTS = 0x809F0007, + NOT_FOUND = 0x809F0008, + NO_SPACE_FS = 0x809F000A, + INTERNAL = 0x809F000B, + MOUNT_FULL = 0x809F000C, + BAD_MOUNTED = 0x809F000D, + BROKEN = 0x809F000F, + INVALID_LOGIN_USER = 0x809F0011, + MEMORY_NOT_READY = 0x809F0012, + BACKUP_BUSY = 0x809F0013, + BUSY_FOR_SAVING = 0x809F0016, +}; + +enum class OrbisSaveDataSaveDataMemoryOption : u32 { + NONE = 0, + SET_PARAM = 1 << 0, + DOUBLE_BUFFER = 1 << 1, + UNLOCK_LIMITATIONS = 1 << 2, +}; + +using OrbisUserServiceUserId = s32; +using OrbisSaveDataBlocks = u64; + +constexpr u32 OrbisSaveDataBlockSize = 32768; // 32 KiB +constexpr u32 OrbisSaveDataBlocksMin2 = 96; // 3MiB +constexpr u32 OrbisSaveDataBlocksMax = 32768; // 1 GiB + +// Maximum size for a mount point "/savedataN", where N is a number +constexpr size_t OrbisSaveDataMountPointDataMaxsize = 16; + +constexpr size_t OrbisSaveDataFingerprintDataSize = 65; // Maximum fingerprint size + +enum class OrbisSaveDataMountMode : u32 { + RDONLY = 1 << 0, + RDWR = 1 << 1, + CREATE = 1 << 2, + DESTRUCT_OFF = 1 << 3, + COPY_ICON = 1 << 4, + CREATE2 = 1 << 5, +}; +DECLARE_ENUM_FLAG_OPERATORS(OrbisSaveDataMountMode); + +enum class OrbisSaveDataMountStatus : u32 { + NOTHING = 0, + CREATED = 1, +}; + +enum class OrbisSaveDataParamType : u32 { + ALL = 0, + TITLE = 1, + SUB_TITLE = 2, + DETAIL = 3, + USER_PARAM = 4, + MTIME = 5, +}; + +enum class OrbisSaveDataSortKey : u32 { + DIRNAME = 0, + USER_PARAM = 1, + BLOCKS = 2, + MTIME = 3, + FREE_BLOCKS = 5, +}; + +enum class OrbisSaveDataSortOrder : u32 { + ASCENT = 0, + DESCENT = 1, +}; + +struct OrbisSaveDataFingerprint { + CString data; + std::array _pad; +}; + +struct OrbisSaveDataBackup { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + const OrbisSaveDataFingerprint* param; + std::array _reserved; +}; + +struct OrbisSaveDataCheckBackupData { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + OrbisSaveDataParam* param; + OrbisSaveDataIcon* icon; + std::array _reserved; +}; + +struct OrbisSaveDataDelete { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + u32 _unused; + std::array _reserved; + s32 : 32; +}; + +struct OrbisSaveDataIcon { + void* buf; + size_t bufSize; + size_t dataSize; + std::array _reserved; + + Error LoadIcon(const std::filesystem::path& icon_path) { + try { + const Common::FS::IOFile file(icon_path, Common::FS::FileAccessMode::Read); + dataSize = file.GetSize(); + file.Seek(0); + file.ReadRaw(buf, std::min(bufSize, dataSize)); + } catch (const fs::filesystem_error& e) { + LOG_ERROR(Lib_SaveData, "Failed to load icon: {}", e.what()); + return Error::INTERNAL; + } + return Error::OK; + } +}; + +struct OrbisSaveDataMemoryData { + void* buf; + size_t bufSize; + s64 offset; + u8 _reserved[40]; +}; + +struct OrbisSaveDataMemoryGet2 { + OrbisUserServiceUserId userId; + std::array _pad; + OrbisSaveDataMemoryData* data; + OrbisSaveDataParam* param; + OrbisSaveDataIcon* icon; + std::array _reserved; +}; + +struct OrbisSaveDataMemorySet2 { + OrbisUserServiceUserId userId; + std::array _pad; + const OrbisSaveDataMemoryData* data; + const OrbisSaveDataParam* param; + const OrbisSaveDataIcon* icon; + std::array _reserved; +}; + +struct OrbisSaveDataMemorySetup2 { + OrbisSaveDataSaveDataMemoryOption option; + OrbisUserServiceUserId userId; + size_t memorySize; + size_t iconMemorySize; + // +4.5 + const OrbisSaveDataParam* initParam; + // +4.5 + const OrbisSaveDataIcon* initIcon; + std::array _reserved; +}; + +struct OrbisSaveDataMemorySetupResult { + size_t existedMemorySize; + std::array _reserved; +}; + +struct OrbisSaveDataMemorySync { + OrbisUserServiceUserId userId; + std::array _reserved; +}; + +struct OrbisSaveDataMount2 { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataDirName* dirName; + OrbisSaveDataBlocks blocks; + OrbisSaveDataMountMode mountMode; + std::array _reserved; + s32 : 32; +}; + +struct OrbisSaveDataMount { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + const OrbisSaveDataFingerprint* fingerprint; + OrbisSaveDataBlocks blocks; + OrbisSaveDataMountMode mountMode; + std::array _reserved; +}; + +struct OrbisSaveDataMountInfo { + OrbisSaveDataBlocks blocks; + OrbisSaveDataBlocks freeBlocks; + std::array _reserved; +}; + +struct OrbisSaveDataMountPoint { + CString data; +}; + +struct OrbisSaveDataMountResult { + OrbisSaveDataMountPoint mount_point; + OrbisSaveDataBlocks required_blocks; + u32 _unused; + // +4.5 + OrbisSaveDataMountStatus mount_status; + std::array _reserved; + s32 : 32; +}; + +struct OrbisSaveDataRestoreBackupData { + OrbisUserServiceUserId userId; + s32 : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + const OrbisSaveDataFingerprint* fingerprint; + u32 _unused; + std::array _reserved; + s32 : 32; +}; + +struct OrbisSaveDataTransferringMount { + OrbisUserServiceUserId userId; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + const OrbisSaveDataFingerprint* fingerprint; + std::array _reserved; +}; + +struct OrbisSaveDataDirNameSearchCond { + OrbisUserServiceUserId userId; + int : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + OrbisSaveDataSortKey key; + OrbisSaveDataSortOrder order; + std::array _reserved; +}; + +struct OrbisSaveDataSearchInfo { + u64 blocks; + u64 freeBlocks; + std::array _reserved; +}; + +struct OrbisSaveDataDirNameSearchResult { + u32 hitNum; + int : 32; + OrbisSaveDataDirName* dirNames; + u32 dirNamesNum; + // +1.7 + u32 setNum; + // +1.7 + OrbisSaveDataParam* params; + // +2.5 + OrbisSaveDataSearchInfo* infos; + std::array _reserved; + int : 32; +}; + +struct OrbisSaveDataEventParam { // dummy structure + OrbisSaveDataEventParam() = delete; +}; + +using OrbisSaveDataEventType = Backup::OrbisSaveDataEventType; + +struct OrbisSaveDataEvent { + OrbisSaveDataEventType type; + s32 errorCode; + OrbisUserServiceUserId userId; + std::array _pad; + OrbisSaveDataTitleId titleId; + OrbisSaveDataDirName dirName; + std::array _reserved; +}; + +static bool g_initialized = false; +static std::string g_game_serial; +static u32 g_fw_ver; +static std::array, 16> g_mount_slots; + +static void initialize() { + g_initialized = true; + g_game_serial = ElfInfo::Instance().GameSerial(); + g_fw_ver = ElfInfo::Instance().FirmwareVer(); +} + +// game_00other | game*other + +static bool match(std::string_view str, std::string_view pattern) { + auto str_it = str.begin(); + auto pat_it = pattern.begin(); + while (str_it != str.end() && pat_it != pattern.end()) { + if (*pat_it == '%') { // 0 or more wildcard + for (auto str_wild_it = str_it; str_wild_it <= str.end(); ++str_wild_it) { + if (match({str_wild_it, str.end()}, {pat_it + 1, pattern.end()})) { + return true; + } + } + return false; + } + if (*pat_it == '_') { // 1 character wildcard + ++str_it; + ++pat_it; + } else if (*pat_it != *str_it) { + return false; + } + ++str_it; + ++pat_it; + } + return str_it == str.end() && pat_it == pattern.end(); +} + +static Error setNotInitializedError() { + if (g_fw_ver < ElfInfo::FW_20) { + return Error::INTERNAL; + } + if (g_fw_ver < ElfInfo::FW_25) { + return Error::USER_SERVICE_NOT_INITIALIZED; + } + return Error::NOT_INITIALIZED; +} + +static Error saveDataMount(const OrbisSaveDataMount2* mount_info, + OrbisSaveDataMountResult* mount_result, + std::string_view title_id = g_game_serial) { + + if (mount_info->userId < 0) { + return Error::INVALID_LOGIN_USER; + } + if (mount_info->dirName == nullptr) { + LOG_INFO(Lib_SaveData, "called without dirName"); + return Error::PARAMETER; + } + + // check backup status + { + const auto save_path = + SaveInstance::MakeDirSavePath(mount_info->userId, title_id, mount_info->dirName->data); + if (Backup::IsBackupExecutingFor(save_path) && g_fw_ver) { + return Error::BACKUP_BUSY; + } + } + + auto mount_mode = mount_info->mountMode; + const bool is_ro = True(mount_mode & OrbisSaveDataMountMode::RDONLY); + + const bool create = True(mount_mode & OrbisSaveDataMountMode::CREATE); + const bool create_if_not_exist = + True(mount_mode & OrbisSaveDataMountMode::CREATE2) && g_fw_ver >= ElfInfo::FW_45; + ASSERT(!create || !create_if_not_exist); // Can't have both + + const bool copy_icon = True(mount_mode & OrbisSaveDataMountMode::COPY_ICON); + + const bool ignore_corrupt = + True(mount_mode & OrbisSaveDataMountMode::DESTRUCT_OFF) || g_fw_ver < ElfInfo::FW_16; + + const std::string_view dir_name{mount_info->dirName->data}; + + // find available mount point + int slot_num = -1; + for (size_t i = 0; i < g_mount_slots.size(); i++) { + const auto& instance = g_mount_slots[i]; + if (instance.has_value()) { + const auto& slot_name = instance->GetDirName(); + if (slot_name == dir_name) { + return Error::BUSY; + } + } else { + slot_num = static_cast(i); + break; + } + } + if (slot_num == -1) { + return Error::MOUNT_FULL; + } + + SaveInstance save_instance{slot_num, mount_info->userId, std::string{title_id}, dir_name, + (int)mount_info->blocks}; + + if (save_instance.Mounted()) { + UNREACHABLE_MSG("Save instance should not be mounted"); + } + + if (!create && !create_if_not_exist && !save_instance.Exists()) { + return Error::NOT_FOUND; + } + if (create && save_instance.Exists()) { + return Error::EXISTS; + } + + bool to_be_created = !save_instance.Exists(); + + if (to_be_created) { // Check size + + if (mount_info->blocks < OrbisSaveDataBlocksMin2 || + mount_info->blocks > OrbisSaveDataBlocksMax) { + LOG_INFO(Lib_SaveData, "called with invalid block size"); + } + + const auto root_save = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir); + fs::create_directories(root_save); + const auto available = fs::space(root_save).available; + + auto requested_size = save_instance.GetMaxBlocks() * OrbisSaveDataBlockSize; + if (requested_size > available) { + mount_result->required_blocks = (requested_size - available) / OrbisSaveDataBlockSize; + return Error::NO_SPACE_FS; + } + } + + try { + save_instance.SetupAndMount(is_ro, copy_icon, ignore_corrupt); + } catch (const fs::filesystem_error& e) { + if (e.code() == std::errc::illegal_byte_sequence) { + LOG_ERROR(Lib_SaveData, "Corrupted save data"); + return Error::BROKEN; + } + if (e.code() == std::errc::no_space_on_device) { + return Error::NO_SPACE_FS; + } + LOG_ERROR(Lib_SaveData, "Failed to mount save data: {}", e.what()); + return Error::INTERNAL; + } + + mount_result->mount_point.data.FromString(save_instance.GetMountPoint()); + + if (g_fw_ver >= ElfInfo::FW_45) { + mount_result->mount_status = create_if_not_exist && to_be_created + ? OrbisSaveDataMountStatus::CREATED + : OrbisSaveDataMountStatus::NOTHING; + } + + g_mount_slots[slot_num].emplace(std::move(save_instance)); + + return Error::OK; +} + +static Error Umount(const OrbisSaveDataMountPoint* mountPoint, bool call_backup = false) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (mountPoint == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "Umount mountPoint:{}", mountPoint->data.to_view()); + const std::string_view mount_point_str{mountPoint->data}; + for (auto& instance : g_mount_slots) { + if (instance.has_value()) { + const auto& slot_name = instance->GetMountPoint(); + if (slot_name == mount_point_str) { + // TODO: check if is busy + instance->Umount(); + if (call_backup) { + Backup::StartThread(); + Backup::NewRequest(instance->GetUserId(), instance->GetTitleId(), + instance->GetDirName(), + OrbisSaveDataEventType::UMOUNT_BACKUP); + } + instance.reset(); + return Error::OK; + } + } + } + return Error::NOT_FOUND; +} + +void OrbisSaveDataParam::FromSFO(const PSF& sfo) { + memset(this, 0, sizeof(OrbisSaveDataParam)); + title.FromString(sfo.GetString(SaveParams::MAINTITLE).value_or("Unknown")); + subTitle.FromString(sfo.GetString(SaveParams::SUBTITLE).value_or("")); + detail.FromString(sfo.GetString(SaveParams::DETAIL).value_or("")); + userParam = sfo.GetInteger(SaveParams::SAVEDATA_LIST_PARAM).value_or(0); + const auto time_since_epoch = sfo.GetLastWrite().time_since_epoch(); + mtime = chrono::duration_cast(time_since_epoch).count(); +} + +void OrbisSaveDataParam::ToSFO(PSF& sfo) const { + sfo.AddString(std::string{SaveParams::MAINTITLE}, std::string{title}, true); + sfo.AddString(std::string{SaveParams::SUBTITLE}, std::string{subTitle}, true); + sfo.AddString(std::string{SaveParams::DETAIL}, std::string{detail}, true); + sfo.AddInteger(std::string{SaveParams::SAVEDATA_LIST_PARAM}, static_cast(userParam), true); +} int PS4_SYSV_ABI sceSaveDataAbort() { LOG_ERROR(Lib_SaveData, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataBackup() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataBackup(const OrbisSaveDataBackup* backup) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (backup == nullptr || backup->dirName == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + + const std::string_view dir_name{backup->dirName->data}; + LOG_DEBUG(Lib_SaveData, "called dirName: {}", dir_name); + + std::string_view title{backup->titleId != nullptr ? std::string_view{backup->titleId->data} + : std::string_view{g_game_serial}}; + + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetUserId() == backup->userId && + instance->GetTitleId() == title && instance->GetDirName() == dir_name) { + return Error::BUSY; + } + } + + Backup::StartThread(); + Backup::NewRequest(backup->userId, title, dir_name, OrbisSaveDataEventType::BACKUP); + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataBindPsnAccount() { @@ -49,15 +581,55 @@ int PS4_SYSV_ABI sceSaveDataChangeInternal() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check) { - auto* mnt = Common::Singleton::Instance(); - const auto mount_dir = mnt->GetHostPath(check->dirName->data); - if (!std::filesystem::exists(mount_dir)) { - return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; +Error PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (check == nullptr || check->dirName == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; } - LOG_INFO(Lib_SaveData, "called = {}", mount_dir.string()); - return ORBIS_OK; + const std::string_view title{check->titleId != nullptr ? std::string_view{check->titleId->data} + : std::string_view{g_game_serial}}; + LOG_DEBUG(Lib_SaveData, "called with titleId={}", title); + + const auto save_path = + SaveInstance::MakeDirSavePath(check->userId, title, check->dirName->data); + + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetSavePath() == save_path) { + return Error::BUSY; + } + } + + if (Backup::IsBackupExecutingFor(save_path)) { + return Error::BACKUP_BUSY; + } + + const auto backup_path = Backup::MakeBackupPath(save_path); + if (!fs::exists(backup_path)) { + return Error::NOT_FOUND; + } + + if (check->param != nullptr) { + PSF sfo; + if (!sfo.Open(backup_path / "sce_sys" / "param.sfo")) { + LOG_ERROR(Lib_SaveData, "Failed to read SFO at {}", fmt::UTF(backup_path.u8string())); + return Error::INTERNAL; + } + check->param->FromSFO(sfo); + } + + if (check->icon != nullptr) { + const auto icon_path = backup_path / "sce_sys" / "icon0.png"; + if (fs::exists(icon_path) && check->icon->LoadIcon(icon_path) != Error::OK) { + return Error::INTERNAL; + } + } + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataCheckBackupDataForCdlg() { @@ -95,9 +667,14 @@ int PS4_SYSV_ABI sceSaveDataCheckSaveDataVersionLatest() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataClearProgress() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataClearProgress() { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + LOG_DEBUG(Lib_SaveData, "called"); + Backup::ClearProgress(); + return Error::OK; } int PS4_SYSV_ABI sceSaveDataCopy5() { @@ -145,15 +722,35 @@ int PS4_SYSV_ABI sceSaveDataDebugTarget() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del) { - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(1) / game_serial / std::string(del->dirName->data); - LOG_INFO(Lib_SaveData, "called: dirname = {}, mount_dir = {}", (char*)del->dirName->data, - mount_dir.string()); - if (std::filesystem::exists(mount_dir) && std::filesystem::is_directory(mount_dir)) { - std::filesystem::remove_all(mount_dir); +Error PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); } - return ORBIS_OK; + if (del == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + const std::string_view dirName{del->dirName->data}; + LOG_DEBUG(Lib_SaveData, "called dirName: {}", dirName); + if (dirName.empty()) { + return Error::PARAMETER; + } + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetDirName() == dirName) { + return Error::BUSY; + } + } + const auto save_path = SaveInstance::MakeDirSavePath(del->userId, g_game_serial, dirName); + try { + if (fs::exists(save_path)) { + fs::remove_all(save_path); + } + } catch (const fs::filesystem_error& e) { + LOG_ERROR(Lib_SaveData, "Failed to delete save data: {}", e.what()); + return Error::INTERNAL; + } + return Error::OK; } int PS4_SYSV_ABI sceSaveDataDelete5() { @@ -176,46 +773,124 @@ int PS4_SYSV_ABI sceSaveDataDeleteUser() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond* cond, - OrbisSaveDataDirNameSearchResult* result) { - if (cond == nullptr) - return ORBIS_SAVE_DATA_ERROR_PARAMETER; - LOG_INFO(Lib_SaveData, "called"); - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(cond->userId) / game_serial; - if (!mount_dir.empty() && std::filesystem::exists(mount_dir)) { - if (cond->dirName == nullptr || std::string_view(cond->dirName->data) - .empty()) { // look for all dirs if no dir is provided. - for (int i = 0; const auto& entry : std::filesystem::directory_iterator(mount_dir)) { - if (std::filesystem::is_directory(entry.path()) && - entry.path().filename().string() != "sdmemory") { - // sceSaveDataDirNameSearch does not search for dataMemory1/2 dirs. - // copy dir name to be used by sceSaveDataMount in read mode. - strncpy(result->dirNames[i].data, entry.path().filename().string().c_str(), 32); - i++; - result->hitNum = i; - result->dirNamesNum = i; - result->setNum = i; - } - } - } else { // Need a game to test. - LOG_ERROR(Lib_SaveData, "Check Me. sceSaveDataDirNameSearch: dirName = {}", - cond->dirName->data); - strncpy(result->dirNames[0].data, cond->dirName->data, 32); - result->hitNum = 1; - result->dirNamesNum = 1; - result->setNum = 1; - } - } else { +Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond* cond, + OrbisSaveDataDirNameSearchResult* result) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (cond == nullptr || result == nullptr || cond->key > OrbisSaveDataSortKey::FREE_BLOCKS || + cond->order > OrbisSaveDataSortOrder::DESCENT) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called"); + const std::string_view title_id{cond->titleId == nullptr + ? std::string_view{g_game_serial} + : std::string_view{cond->titleId->data}}; + const auto save_path = SaveInstance::MakeTitleSavePath(cond->userId, title_id); + + if (!fs::exists(save_path)) { result->hitNum = 0; - result->dirNamesNum = 0; - result->setNum = 0; + if (g_fw_ver >= ElfInfo::FW_17) { + result->setNum = 0; + } + return Error::OK; } - if (result->infos != nullptr) { - result->infos->blocks = ORBIS_SAVE_DATA_BLOCK_SIZE; - result->infos->freeBlocks = ORBIS_SAVE_DATA_BLOCK_SIZE; + + std::vector dir_list; + + for (const auto& path : fs::directory_iterator{save_path}) { + auto dir_name = path.path().filename().string(); + // skip non-directories, sce_* and directories without param.sfo + if (fs::is_directory(path) && !dir_name.starts_with("sce_") && + fs::exists(SaveInstance::GetParamSFOPath(path))) { + dir_list.push_back(dir_name); + } } - return ORBIS_OK; + if (cond->dirName != nullptr) { + // Filter names + const auto pat = Common::ToLower(std::string_view{cond->dirName->data}); + if (!pat.empty()) { + std::erase_if(dir_list, [&](const std::string& dir_name) { + return !match(Common::ToLower(dir_name), pat); + }); + } + } + + std::unordered_map map_dir_sfo; + std::unordered_map map_max_blocks; + std::unordered_map map_free_size; + + for (const auto& dir_name : dir_list) { + const auto dir_path = SaveInstance::MakeDirSavePath(cond->userId, title_id, dir_name); + const auto sfo_path = SaveInstance::GetParamSFOPath(dir_path); + PSF sfo; + if (!sfo.Open(sfo_path)) { + LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", fmt::UTF(sfo_path.u8string())); + ASSERT_MSG(false, "Failed to read SFO"); + } + + size_t size = Common::FS::GetDirectorySize(dir_path); + size_t total = SaveInstance::GetMaxBlockFromSFO(sfo); + + map_dir_sfo.emplace(dir_name, std::move(sfo)); + map_free_size.emplace(dir_name, total - size / OrbisSaveDataBlockSize); + map_max_blocks.emplace(dir_name, total); + } + +#define PROJ(x) [&](const auto& v) { return x; } + switch (cond->key) { + case OrbisSaveDataSortKey::DIRNAME: + std::ranges::stable_sort(dir_list); + break; + case OrbisSaveDataSortKey::USER_PARAM: + std::ranges::stable_sort( + dir_list, {}, + PROJ(map_dir_sfo.at(v).GetInteger(SaveParams::SAVEDATA_LIST_PARAM).value_or(0))); + break; + case OrbisSaveDataSortKey::BLOCKS: + std::ranges::stable_sort(dir_list, {}, PROJ(map_max_blocks.at(v))); + break; + case OrbisSaveDataSortKey::FREE_BLOCKS: + std::ranges::stable_sort(dir_list, {}, PROJ(map_free_size.at(v))); + break; + case OrbisSaveDataSortKey::MTIME: + std::ranges::stable_sort(dir_list, {}, PROJ(map_dir_sfo.at(v).GetLastWrite())); + break; + } +#undef PROJ + + if (cond->order == OrbisSaveDataSortOrder::DESCENT) { + std::ranges::reverse(dir_list); + } + + size_t max_count = std::min(static_cast(result->dirNamesNum), dir_list.size()); + if (g_fw_ver >= ElfInfo::FW_17) { + result->hitNum = dir_list.size(); + result->setNum = max_count; + } else { + result->hitNum = max_count; + } + + for (size_t i = 0; i < max_count; i++) { + auto& name_data = result->dirNames[i].data; + name_data.FromString(dir_list[i]); + + if (g_fw_ver >= ElfInfo::FW_17 && result->params != nullptr) { + auto& sfo = map_dir_sfo.at(dir_list[i]); + auto& param_data = result->params[i]; + param_data.FromSFO(sfo); + } + + if (g_fw_ver >= ElfInfo::FW_25 && result->infos != nullptr) { + auto& info = result->infos[i]; + info.blocks = map_max_blocks.at(dir_list[i]); + info.freeBlocks = map_free_size.at(dir_list[i]); + } + } + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataDirNameSearchInternal() { @@ -278,15 +953,30 @@ int PS4_SYSV_ABI sceSaveDataGetEventInfo() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam* eventParam, - OrbisSaveDataEvent* event) { - // eventParam can be 0/null. - if (event == nullptr) - return ORBIS_SAVE_DATA_ERROR_NOT_INITIALIZED; +Error PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam*, + OrbisSaveDataEvent* event) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (event == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_TRACE(Lib_SaveData, "called"); - LOG_INFO(Lib_SaveData, "called: Todo."); - event->userId = 1; - return ORBIS_OK; + auto last_event = Backup::PopLastEvent(); + if (!last_event.has_value()) { + return Error::NOT_FOUND; + } + + event->type = last_event->origin; + event->errorCode = 0; + event->userId = last_event->user_id; + event->titleId.data.FromString(last_event->title_id); + event->dirName.data.FromString(last_event->dir_name); + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataGetFormat() { @@ -299,65 +989,119 @@ int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, - OrbisSaveDataMountInfo* info) { - LOG_INFO(Lib_SaveData, "called"); - info->blocks = ORBIS_SAVE_DATA_BLOCKS_MAX; - info->freeBlocks = ORBIS_SAVE_DATA_BLOCKS_MAX; - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataMountInfo* info) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (mountPoint == nullptr || info == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called"); + const std::string_view mount_point_str{mountPoint->data}; + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetMountPoint() == mount_point_str) { + const u32 blocks = instance->GetMaxBlocks(); + const u64 size = Common::FS::GetDirectorySize(instance->GetSavePath()); + info->blocks = blocks; + info->freeBlocks = blocks - size / OrbisSaveDataBlockSize; + return Error::OK; + } + } + return Error::NOT_MOUNTED; } -int PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint, - const OrbisSaveDataParamType paramType, void* paramBuf, - const size_t paramBufSize, size_t* gotSize) { +Error PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataParamType paramType, void* paramBuf, + size_t paramBufSize, size_t* gotSize) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (paramType > OrbisSaveDataParamType::MTIME || paramBuf == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called: paramType = {}", magic_enum::enum_name(paramType)); + const PSF* param_sfo = nullptr; - if (mountPoint == nullptr) - return ORBIS_SAVE_DATA_ERROR_PARAMETER; - - auto* mnt = Common::Singleton::Instance(); - const auto mount_dir = mnt->GetHostPath(mountPoint->data); - Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Read); - OrbisSaveDataParam params; - file.Read(params); - - LOG_INFO(Lib_SaveData, "called"); - - switch (paramType) { - case ORBIS_SAVE_DATA_PARAM_TYPE_ALL: { - memcpy(paramBuf, ¶ms, sizeof(OrbisSaveDataParam)); - *gotSize = sizeof(OrbisSaveDataParam); - } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_TITLE: { - std::memcpy(paramBuf, ¶ms.title, ORBIS_SAVE_DATA_TITLE_MAXSIZE); - *gotSize = ORBIS_SAVE_DATA_TITLE_MAXSIZE; - } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_SUB_TITLE: { - std::memcpy(paramBuf, ¶ms.subTitle, ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE); - *gotSize = ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE; - } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_DETAIL: { - std::memcpy(paramBuf, ¶ms.detail, ORBIS_SAVE_DATA_DETAIL_MAXSIZE); - *gotSize = ORBIS_SAVE_DATA_DETAIL_MAXSIZE; - } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_USER_PARAM: { - std::memcpy(paramBuf, ¶ms.userParam, sizeof(u32)); - *gotSize = sizeof(u32); - } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_MTIME: { - std::memcpy(paramBuf, ¶ms.mtime, sizeof(time_t)); - *gotSize = sizeof(time_t); - } break; - default: { - UNREACHABLE_MSG("Unknown Param = {}", paramType); - } break; + const std::string_view mount_point_str{mountPoint->data}; + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetMountPoint() == mount_point_str) { + param_sfo = &instance->GetParamSFO(); + break; + } + } + if (param_sfo == nullptr) { + return Error::NOT_MOUNTED; } - return ORBIS_OK; + switch (paramType) { + case OrbisSaveDataParamType::ALL: { + const auto param = static_cast(paramBuf); + ASSERT(paramBufSize == sizeof(OrbisSaveDataParam)); + param->FromSFO(*param_sfo); + if (gotSize != nullptr) { + *gotSize = sizeof(OrbisSaveDataParam); + } + break; + } + case OrbisSaveDataParamType::TITLE: + case OrbisSaveDataParamType::SUB_TITLE: + case OrbisSaveDataParamType::DETAIL: { + const auto param = static_cast(paramBuf); + std::string_view key; + if (paramType == OrbisSaveDataParamType::TITLE) { + key = SaveParams::MAINTITLE; + } else if (paramType == OrbisSaveDataParamType::SUB_TITLE) { + key = SaveParams::SUBTITLE; + } else if (paramType == OrbisSaveDataParamType::DETAIL) { + key = SaveParams::DETAIL; + } else { + UNREACHABLE(); + } + const size_t s = param_sfo->GetString(key).value_or("").copy(param, paramBufSize - 1); + param[s] = '\0'; // null terminate + if (gotSize != nullptr) { + *gotSize = s + 1; + } + } break; + case OrbisSaveDataParamType::USER_PARAM: { + const auto param = static_cast(paramBuf); + *param = param_sfo->GetInteger(SaveParams::SAVEDATA_LIST_PARAM).value_or(0); + if (gotSize != nullptr) { + *gotSize = sizeof(u32); + } + } break; + case OrbisSaveDataParamType::MTIME: { + const auto param = static_cast(paramBuf); + const auto last_write = param_sfo->GetLastWrite().time_since_epoch(); + *param = chrono::duration_cast(last_write).count(); + if (gotSize != nullptr) { + *gotSize = sizeof(time_t); + } + } break; + default: + UNREACHABLE(); + } + + return Error::OK; } -int PS4_SYSV_ABI sceSaveDataGetProgress() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataGetProgress(float* progress) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (progress == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called"); + *progress = Backup::GetProgress(); + return Error::OK; } int PS4_SYSV_ABI sceSaveDataGetSaveDataCount() { @@ -365,44 +1109,56 @@ int PS4_SYSV_ABI sceSaveDataGetSaveDataCount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize, - const int64_t offset) { - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(userId) / game_serial / "sdmemory/save_mem1.sav"; - - Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Read); - if (!file.IsOpen()) { - return false; - } - file.Seek(offset); - size_t nbytes = file.ReadRaw(buf, bufSize); - LOG_INFO(Lib_SaveData, "called: bufSize = {}, offset = {}", bufSize, offset, nbytes); - - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const OrbisUserServiceUserId userId, void* buf, + const size_t bufSize, const int64_t offset) { + LOG_DEBUG(Lib_SaveData, "Redirecting to sceSaveDataGetSaveDataMemory2"); + OrbisSaveDataMemoryData data{}; + data.buf = buf; + data.bufSize = bufSize; + data.offset = offset; + OrbisSaveDataMemoryGet2 param{}; + param.userId = userId; + param.data = &data; + param.param = nullptr; + param.icon = nullptr; + return sceSaveDataGetSaveDataMemory2(¶m); } -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam) { - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(getParam->userId) / game_serial / "sdmemory"; - if (getParam == nullptr) - return ORBIS_SAVE_DATA_ERROR_PARAMETER; - if (getParam->data != nullptr) { - Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Read); - if (!file.IsOpen()) { - return false; - } - file.Seek(getParam->data->offset); - file.ReadRaw(getParam->data->buf, getParam->data->bufSize); - LOG_INFO(Lib_SaveData, "called: bufSize = {}, offset = {}", getParam->data->bufSize, - getParam->data->offset); +Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (getParam == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + if (!SaveMemory::IsSaveMemoryInitialized()) { + 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) { + SaveMemory::ReadMemory(data->buf, data->bufSize, data->offset); + } + auto param = getParam->param; + if (param != nullptr) { + param->FromSFO(SaveMemory::GetParamSFO()); + } + auto icon = getParam->icon; + if (icon != nullptr) { + auto icon_mem = SaveMemory::GetIcon(); + size_t total = std::min(icon->bufSize, icon_mem.size()); + std::memcpy(icon->buf, icon_mem.data(), total); + icon->dataSize = total; } - if (getParam->param != nullptr) { - Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Read); - file.ReadRaw(getParam->param, sizeof(OrbisSaveDataParam)); - } - - return ORBIS_OK; + return Error::OK; } int PS4_SYSV_ABI sceSaveDataGetSaveDataRootDir() { @@ -430,25 +1186,22 @@ int PS4_SYSV_ABI sceSaveDataGetUpdatedDataCount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataInitialize() { - LOG_INFO(Lib_SaveData, "called"); - static auto* param_sfo = Common::Singleton::Instance(); - game_serial = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataInitialize(void*) { + LOG_DEBUG(Lib_SaveData, "called"); + initialize(); + return Error::OK; } -int PS4_SYSV_ABI sceSaveDataInitialize2() { - LOG_INFO(Lib_SaveData, "called"); - static auto* param_sfo = Common::Singleton::Instance(); - game_serial = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataInitialize2(void*) { + LOG_DEBUG(Lib_SaveData, "called"); + initialize(); + return Error::OK; } -int PS4_SYSV_ABI sceSaveDataInitialize3() { - LOG_INFO(Lib_SaveData, "called"); - static auto* param_sfo = Common::Singleton::Instance(); - game_serial = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataInitialize3(void*) { + LOG_DEBUG(Lib_SaveData, "called"); + initialize(); + return Error::OK; } int PS4_SYSV_ABI sceSaveDataInitializeForCdlg() { @@ -466,95 +1219,69 @@ int PS4_SYSV_ABI sceSaveDataIsMounted() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, - OrbisSaveDataIcon* icon) { - auto* mnt = Common::Singleton::Instance(); - const auto mount_dir = mnt->GetHostPath(mountPoint->data); - LOG_INFO(Lib_SaveData, "called: dir = {}", mount_dir.string()); - - if (icon != nullptr) { - Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Read); - icon->bufSize = file.GetSize(); - file.ReadRaw(icon->buf, icon->bufSize); +Error PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataIcon* icon) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); } - return ORBIS_OK; + if (mountPoint == nullptr || icon == nullptr || icon->buf == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called"); + std::filesystem::path path; + const std::string_view mount_point_str{mountPoint->data}; + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetMountPoint() == mount_point_str) { + path = instance->GetIconPath(); + break; + } + } + if (path.empty()) { + return Error::NOT_MOUNTED; + } + if (!fs::exists(path)) { + return Error::NOT_FOUND; + } + + return icon->LoadIcon(path); } -s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, - OrbisSaveDataMountResult* mount_result) { - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(user_id) / game_serial / dir_name; - auto* mnt = Common::Singleton::Instance(); - switch (mount_mode) { - case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: - case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: - case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: - case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: { - is_rw_mode = (mount_mode == ORBIS_SAVE_DATA_MOUNT_MODE_RDWR) ? true : false; - if (!std::filesystem::exists(mount_dir)) { - return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; - } - mount_result->mount_status = 0; - g_mount_point.copy(mount_result->mount_point.data, 16); - mnt->Mount(mount_dir, mount_result->mount_point.data); - } break; - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | - ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { - if (std::filesystem::exists(mount_dir)) { - return ORBIS_SAVE_DATA_ERROR_EXISTS; - } - if (std::filesystem::create_directories(mount_dir)) { - g_mount_point.copy(mount_result->mount_point.data, 16); - mnt->Mount(mount_dir, mount_result->mount_point.data); - mount_result->mount_status = 1; - } - } break; - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { - if (!std::filesystem::exists(mount_dir)) { - std::filesystem::create_directories(mount_dir); - } - g_mount_point.copy(mount_result->mount_point.data, 16); - mnt->Mount(mount_dir, mount_result->mount_point.data); - mount_result->mount_status = 1; - } break; - default: - UNREACHABLE_MSG("Unknown mount mode = {}", mount_mode); +Error PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, + OrbisSaveDataMountResult* mount_result) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); } - mount_result->required_blocks = 0; + if (mount == nullptr && mount->dirName != nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called dirName: {}, mode: {:0b}, blocks: {}", + mount->dirName->data.to_view(), (int)mount->mountMode, mount->blocks); - return ORBIS_OK; + OrbisSaveDataMount2 mount_info{}; + mount_info.userId = mount->userId; + mount_info.dirName = mount->dirName; + mount_info.mountMode = mount->mountMode; + mount_info.blocks = mount->blocks; + return saveDataMount(&mount_info, mount_result); } -s32 PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, - OrbisSaveDataMountResult* mount_result) { - if (mount == nullptr) { - return ORBIS_SAVE_DATA_ERROR_PARAMETER; +Error PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, + OrbisSaveDataMountResult* mount_result) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); } - LOG_INFO(Lib_SaveData, "called: dirName = {}, mode = {}, blocks = {}", mount->dir_name->data, - mount->mount_mode, mount->blocks); - return saveDataMount(mount->user_id, (char*)mount->dir_name->data, mount->mount_mode, - mount_result); -} - -s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, - OrbisSaveDataMountResult* mount_result) { - if (mount == nullptr) { - return ORBIS_SAVE_DATA_ERROR_PARAMETER; + if (mount == nullptr && mount->dirName != nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; } - LOG_INFO(Lib_SaveData, "called: dirName = {}, mode = {}, blocks = {}", mount->dir_name->data, - mount->mount_mode, mount->blocks); - return saveDataMount(mount->user_id, (char*)mount->dir_name->data, mount->mount_mode, - mount_result); + LOG_DEBUG(Lib_SaveData, "called dirName: {}, mode: {:0b}, blocks: {}", + mount->dirName->data.to_view(), (int)mount->mountMode, mount->blocks); + return saveDataMount(mount, mount_result); } int PS4_SYSV_ABI sceSaveDataMount5() { @@ -587,9 +1314,44 @@ int PS4_SYSV_ABI sceSaveDataRegisterEventCallback() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataRestoreBackupData() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataRestoreBackupData(const OrbisSaveDataRestoreBackupData* restore) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (restore == nullptr || restore->dirName == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + + const std::string_view dir_name{restore->dirName->data}; + LOG_DEBUG(Lib_SaveData, "called dirName: {}", dir_name); + + std::string_view title{restore->titleId != nullptr ? std::string_view{restore->titleId->data} + : std::string_view{g_game_serial}}; + + const auto save_path = SaveInstance::MakeDirSavePath(restore->userId, title, dir_name); + + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetSavePath() == save_path) { + return Error::BUSY; + } + } + if (Backup::IsBackupExecutingFor(save_path)) { + return Error::BACKUP_BUSY; + } + + const auto backup_path = Backup::MakeBackupPath(save_path); + if (!fs::exists(backup_path)) { + return Error::NOT_FOUND; + } + + const bool ok = Backup::Restore(save_path); + if (!ok) { + return Error::INTERNAL; + } + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataRestoreBackupDataForCdlg() { @@ -602,17 +1364,41 @@ int PS4_SYSV_ABI sceSaveDataRestoreLoadSaveDataMemory() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, - const OrbisSaveDataIcon* icon) { - auto* mnt = Common::Singleton::Instance(); - const auto mount_dir = mnt->GetHostPath(mountPoint->data); - LOG_INFO(Lib_SaveData, "called = {}", mount_dir.string()); - - if (icon != nullptr) { - Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Write); - file.WriteRaw(icon->buf, icon->bufSize); +Error PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, + const OrbisSaveDataIcon* icon) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); } - return ORBIS_OK; + if (mountPoint == nullptr || icon == nullptr || icon->buf == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called"); + std::filesystem::path path; + const std::string_view mount_point_str{mountPoint->data}; + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetMountPoint() == mount_point_str) { + if (instance->IsReadOnly()) { + return Error::BAD_MOUNTED; + } + path = instance->GetIconPath(); + break; + } + } + if (path.empty()) { + return Error::NOT_MOUNTED; + } + + try { + const Common::FS::IOFile file(path, Common::FS::FileAccessMode::Write); + file.WriteRaw(icon->buf, std::min(icon->bufSize, icon->dataSize)); + } catch (const fs::filesystem_error& e) { + LOG_ERROR(Lib_SaveData, "Failed to load icon: {}", e.what()); + return Error::INTERNAL; + } + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataSetAutoUploadSetting() { @@ -625,50 +1411,59 @@ int PS4_SYSV_ABI sceSaveDataSetEventInfo() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, - OrbisSaveDataParamType paramType, const void* paramBuf, - size_t paramBufSize) { - if (paramBuf == nullptr) - return ORBIS_SAVE_DATA_ERROR_PARAMETER; - - auto* mnt = Common::Singleton::Instance(); - const auto mount_dir = mnt->GetHostPath(mountPoint->data) / "param.txt"; - OrbisSaveDataParam params; - if (std::filesystem::exists(mount_dir)) { - Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Read); - file.ReadRaw(¶ms, sizeof(OrbisSaveDataParam)); +Error PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataParamType paramType, const void* paramBuf, + size_t paramBufSize) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (paramType > OrbisSaveDataParamType::USER_PARAM || mountPoint == nullptr || + paramBuf == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called: paramType = {}", magic_enum::enum_name(paramType)); + PSF* param_sfo = nullptr; + const std::string_view mount_point_str{mountPoint->data}; + for (auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetMountPoint() == mount_point_str) { + param_sfo = &instance->GetParamSFO(); + break; + } + } + if (param_sfo == nullptr) { + return Error::NOT_MOUNTED; } - - LOG_INFO(Lib_SaveData, "called"); switch (paramType) { - case ORBIS_SAVE_DATA_PARAM_TYPE_ALL: { - memcpy(¶ms, paramBuf, sizeof(OrbisSaveDataParam)); + case OrbisSaveDataParamType::ALL: { + const auto param = static_cast(paramBuf); + ASSERT(paramBufSize == sizeof(OrbisSaveDataParam)); + param->ToSFO(*param_sfo); + return Error::OK; } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_TITLE: { - strncpy(params.title, static_cast(paramBuf), paramBufSize); + case OrbisSaveDataParamType::TITLE: { + const auto value = static_cast(paramBuf); + param_sfo->AddString(std::string{SaveParams::MAINTITLE}, {value}, true); } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_SUB_TITLE: { - strncpy(params.subTitle, static_cast(paramBuf), paramBufSize); + case OrbisSaveDataParamType::SUB_TITLE: { + const auto value = static_cast(paramBuf); + param_sfo->AddString(std::string{SaveParams::SUBTITLE}, {value}, true); } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_DETAIL: { - strncpy(params.detail, static_cast(paramBuf), paramBufSize); + case OrbisSaveDataParamType::DETAIL: { + const auto value = static_cast(paramBuf); + param_sfo->AddString(std::string{SaveParams::DETAIL}, {value}, true); } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_USER_PARAM: { - params.userParam = *(static_cast(paramBuf)); + case OrbisSaveDataParamType::USER_PARAM: { + const auto value = static_cast(paramBuf); + param_sfo->AddInteger(std::string{SaveParams::SAVEDATA_LIST_PARAM}, *value, true); } break; - case ORBIS_SAVE_DATA_PARAM_TYPE_MTIME: { - params.mtime = *(static_cast(paramBuf)); - } break; - default: { - UNREACHABLE_MSG("Unknown Param = {}", paramType); - } + default: + UNREACHABLE(); } - Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write); - file.WriteRaw(¶ms, sizeof(OrbisSaveDataParam)); - - return ORBIS_OK; + return Error::OK; } int PS4_SYSV_ABI sceSaveDataSetSaveDataLibraryUser() { @@ -676,90 +1471,135 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataLibraryUser() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf, - const size_t bufSize, const int64_t offset) { - LOG_INFO(Lib_SaveData, "called"); - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(userId) / game_serial / "sdmemory/save_mem1.sav"; - - Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write); - file.Seek(offset); - file.WriteRaw(buf, bufSize); - - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(OrbisUserServiceUserId userId, void* buf, + size_t bufSize, int64_t offset) { + LOG_DEBUG(Lib_SaveData, "Redirecting to sceSaveDataSetSaveDataMemory2"); + OrbisSaveDataMemoryData data{}; + data.buf = buf; + data.bufSize = bufSize; + data.offset = offset; + OrbisSaveDataMemorySet2 setParam{}; + setParam.userId = userId; + setParam.data = &data; + setParam.param = nullptr; + setParam.icon = nullptr; + return sceSaveDataSetSaveDataMemory2(&setParam); } -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam) { - LOG_INFO(Lib_SaveData, "called: dataNum = {}, slotId= {}", setParam->dataNum, setParam->slotId); - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(setParam->userId) / game_serial / "sdmemory"; - if (setParam->data != nullptr) { - Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Write); - if (!file.IsOpen()) - return -1; - file.Seek(setParam->data->offset); - file.WriteRaw(setParam->data->buf, setParam->data->bufSize); +Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (setParam == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + if (!SaveMemory::IsSaveMemoryInitialized()) { + 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 = setParam->data; + if (data != nullptr) { + SaveMemory::WriteMemory(data->buf, data->bufSize, data->offset); + } + auto param = setParam->param; + if (param != nullptr) { + param->ToSFO(SaveMemory::GetParamSFO()); + SaveMemory::SaveSFO(); + } + auto icon = setParam->icon; + if (icon != nullptr) { + SaveMemory::WriteIcon(icon->buf, icon->bufSize); } - if (setParam->param != nullptr) { - Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Write); - file.WriteRaw((void*)setParam->param, sizeof(OrbisSaveDataParam)); - } - - if (setParam->icon != nullptr) { - Common::FS::IOFile file(mount_dir / "save_icon.png", Common::FS::FileAccessMode::Write); - file.WriteRaw(setParam->icon->buf, setParam->icon->bufSize); - } - - return ORBIS_OK; + SaveMemory::TriggerSaveWithoutEvent(); + return Error::OK; } -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(u32 userId, size_t memorySize, - OrbisSaveDataParam* param) { - - LOG_INFO(Lib_SaveData, "called:userId = {}, memorySize = {}", userId, memorySize); - - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(userId) / game_serial / "sdmemory"; - - if (std::filesystem::exists(mount_dir)) { - return ORBIS_SAVE_DATA_ERROR_EXISTS; +Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(OrbisUserServiceUserId userId, size_t memorySize, + OrbisSaveDataParam* param) { + LOG_DEBUG(Lib_SaveData, "called: userId = {}, memorySize = {}", userId, memorySize); + OrbisSaveDataMemorySetup2 setupParam{}; + setupParam.userId = userId; + setupParam.memorySize = memorySize; + setupParam.initParam = nullptr; + setupParam.initIcon = nullptr; + OrbisSaveDataMemorySetupResult result{}; + const auto res = sceSaveDataSetupSaveDataMemory2(&setupParam, &result); + if (res != Error::OK) { + return res; } - std::filesystem::create_directories(mount_dir); - std::vector buf(memorySize); - Common::FS::IOFile::WriteBytes(mount_dir / "save_mem1.sav", buf); - return ORBIS_OK; + if (param != nullptr) { + OrbisSaveDataMemorySet2 setParam{}; + setParam.userId = userId; + setParam.data = nullptr; + setParam.param = param; + setParam.icon = nullptr; + sceSaveDataSetSaveDataMemory2(&setParam); + } + return Error::OK; } -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, - OrbisSaveDataMemorySetupResult* result) { +Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, + OrbisSaveDataMemorySetupResult* result) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } if (setupParam == nullptr) { - return ORBIS_SAVE_DATA_ERROR_PARAMETER; + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; } - LOG_INFO(Lib_SaveData, "called"); - // if (setupParam->option == 1) { // check this later. - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(setupParam->userId) / game_serial / "sdmemory"; - if (std::filesystem::exists(mount_dir) && - std::filesystem::exists(mount_dir / "save_mem2.sav")) { - Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Read); - if (!file.IsOpen()) - return -1; - // Bunny - CUSA07988 has a null result, having null result is checked and valid. - if (result != nullptr) - result->existedMemorySize = file.GetSize(); // Assign the saved data size. - // do not return ORBIS_SAVE_DATA_ERROR_EXISTS, as it will not trigger - // sceSaveDataGetSaveDataMemory2. - } else { - std::filesystem::create_directories(mount_dir); - std::vector buf(setupParam->memorySize); // check if > 0x1000000 (16.77mb) or x2? - Common::FS::IOFile::WriteBytes(mount_dir / "save_mem2.sav", buf); - std::vector paramBuf(sizeof(OrbisSaveDataParam)); - Common::FS::IOFile::WriteBytes(mount_dir / "param.txt", paramBuf); - std::vector iconBuf(setupParam->iconMemorySize); - Common::FS::IOFile::WriteBytes(mount_dir / "save_icon.png", iconBuf); + LOG_DEBUG(Lib_SaveData, "called"); + + SaveMemory::SetDirectories(setupParam->userId, g_game_serial); + + const auto& save_path = SaveMemory::GetSavePath(); + for (const auto& instance : g_mount_slots) { + if (instance.has_value() && instance->GetSavePath() == save_path) { + return Error::BUSY; + } } - return ORBIS_OK; + + try { + size_t existed_size = SaveMemory::CreateSaveMemory(setupParam->memorySize); + if (existed_size == 0) { // Just created + if (g_fw_ver >= ElfInfo::FW_45 && setupParam->initParam != nullptr) { + auto& sfo = SaveMemory::GetParamSFO(); + setupParam->initParam->ToSFO(sfo); + } + SaveMemory::SaveSFO(); + + auto init_icon = setupParam->initIcon; + if (g_fw_ver >= ElfInfo::FW_45 && init_icon != nullptr) { + SaveMemory::SetIcon(init_icon->buf, init_icon->bufSize); + } else { + SaveMemory::SetIcon(nullptr, 0); + } + } + SaveMemory::TriggerSaveWithoutEvent(); + if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) { + result->existedMemorySize = existed_size; + } + } catch (const fs::filesystem_error& e) { + LOG_ERROR(Lib_SaveData, "Failed to create/load save memory: {}", e.what()); + + const MsgDialog::MsgDialogState dialog{MsgDialog::MsgDialogState::UserState{ + .type = MsgDialog::ButtonType::OK, + .msg = "Failed to create or load save memory:\n" + std::string{e.what()}, + }}; + MsgDialog::ShowMsgDialog(dialog); + + return Error::INTERNAL; + } + + return Error::OK; } int PS4_SYSV_ABI sceSaveDataShutdownStart() { @@ -777,34 +1617,69 @@ int PS4_SYSV_ABI sceSaveDataSyncCloudList() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam) { - LOG_ERROR(Lib_SaveData, "(STUBBED) called: option = {}", syncParam->option); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataTerminate() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataTransferringMount() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) { - LOG_INFO(Lib_SaveData, "mountPoint = {}", mountPoint->data); - if (std::string_view(mountPoint->data).empty()) { - return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED; +Error PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam) { + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); } - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / - std::to_string(1) / game_serial / mountPoint->data; - auto* mnt = Common::Singleton::Instance(); - const auto& guest_path = mnt->GetHostPath(mountPoint->data); - if (guest_path.empty()) - return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED; - mnt->Unmount(mount_dir, mountPoint->data); - return ORBIS_OK; + if (syncParam == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + if (!SaveMemory::IsSaveMemoryInitialized()) { + LOG_INFO(Lib_SaveData, "called without save memory initialized"); + return Error::MEMORY_NOT_READY; + } + LOG_DEBUG(Lib_SaveData, "called"); + bool ok = SaveMemory::TriggerSave(); + if (!ok) { + return Error::BUSY_FOR_SAVING; + } + return Error::OK; +} + +Error PS4_SYSV_ABI sceSaveDataTerminate() { + LOG_DEBUG(Lib_SaveData, "called"); + if (!g_initialized) { + return setNotInitializedError(); + } + for (auto& instance : g_mount_slots) { + if (instance.has_value()) { + if (g_fw_ver >= ElfInfo::FW_40) { + return Error::BUSY; + } + instance->Umount(); + instance.reset(); + } + } + g_initialized = false; + Backup::StopThread(); + return Error::OK; +} + +Error PS4_SYSV_ABI sceSaveDataTransferringMount(const OrbisSaveDataTransferringMount* mount, + OrbisSaveDataMountResult* mountResult) { + LOG_DEBUG(Lib_SaveData, "called"); + if (!g_initialized) { + LOG_INFO(Lib_SaveData, "called without initialize"); + return setNotInitializedError(); + } + if (mount == nullptr || mount->titleId == nullptr || mount->dirName == nullptr) { + LOG_INFO(Lib_SaveData, "called with invalid parameter"); + return Error::PARAMETER; + } + LOG_DEBUG(Lib_SaveData, "called titleId: {}, dirName: {}", mount->titleId->data.to_view(), + mount->dirName->data.to_view()); + OrbisSaveDataMount2 mount_info{}; + mount_info.userId = mount->userId; + mount_info.dirName = mount->dirName; + mount_info.mountMode = OrbisSaveDataMountMode::RDONLY; + return saveDataMount(&mount_info, mountResult, mount->titleId->data.to_string()); +} + +Error PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) { + LOG_DEBUG(Lib_SaveData, "called"); + return Umount(mountPoint); } int PS4_SYSV_ABI sceSaveDataUmountSys() { @@ -812,37 +1687,9 @@ int PS4_SYSV_ABI sceSaveDataUmountSys() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint) { - LOG_INFO(Lib_SaveData, "called mount = {}, is_rw_mode = {}", std::string(mountPoint->data), - is_rw_mode); - auto* mnt = Common::Singleton::Instance(); - const auto mount_dir = mnt->GetHostPath(mountPoint->data); - if (!std::filesystem::exists(mount_dir)) { - return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; - } - // leave disabled for now. and just unmount. - - /* if (is_rw_mode) { // backup is done only when mount mode is ReadWrite. - auto backup_path = mount_dir; - std::string save_data_dir = (mount_dir.string() + "_backup"); - backup_path.replace_filename(save_data_dir); - - std::filesystem::create_directories(backup_path); - - for (const auto& entry : std::filesystem::recursive_directory_iterator(mount_dir)) { - const auto& path = entry.path(); - if (std::filesystem::is_regular_file(path)) { - std::filesystem::copy(path, save_data_dir, - std::filesystem::copy_options::overwrite_existing); - } - } - }*/ - const auto& guest_path = mnt->GetHostPath(mountPoint->data); - if (guest_path.empty()) - return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED; - - mnt->Unmount(mount_dir, mountPoint->data); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint) { + LOG_DEBUG(Lib_SaveData, "called"); + return Umount(mountPoint, true); } int PS4_SYSV_ABI sceSaveDataUnregisterEventCallback() { diff --git a/src/core/libraries/save_data/savedata.h b/src/core/libraries/save_data/savedata.h index 9b3cf900f..5faf3f2d5 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -3,259 +3,82 @@ #pragma once +#include "common/cstring.h" #include "common/types.h" namespace Core::Loader { class SymbolsResolver; } +class PSF; + namespace Libraries::SaveData { -constexpr int ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE = - 32; // Maximum size for a save data directory name -constexpr int ORBIS_SAVE_DATA_MOUNT_POINT_DATA_MAXSIZE = 16; // Maximum size for a mount point name +constexpr size_t OrbisSaveDataTitleMaxsize = 128; // Maximum title name size +constexpr size_t OrbisSaveDataSubtitleMaxsize = 128; // Maximum subtitle name size +constexpr size_t OrbisSaveDataDetailMaxsize = 1024; // Maximum detail name size + +enum class Error : u32; +enum class OrbisSaveDataParamType : u32; + +using OrbisUserServiceUserId = s32; + +// Maximum size for a title ID (4 uppercase letters + 5 digits) +constexpr int OrbisSaveDataTitleIdDataSize = 10; +// Maximum save directory name size +constexpr int OrbisSaveDataDirnameDataMaxsize = 32; + +struct OrbisSaveDataTitleId { + Common::CString data; + std::array _pad; +}; struct OrbisSaveDataDirName { - char data[ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; + Common::CString data; }; -struct OrbisSaveDataMount2 { - s32 user_id; - s32 unk1; - const OrbisSaveDataDirName* dir_name; - u64 blocks; - u32 mount_mode; - u8 reserved[32]; - s32 unk2; -}; - -struct OrbisSaveDataMountPoint { - char data[ORBIS_SAVE_DATA_MOUNT_POINT_DATA_MAXSIZE]; -}; - -struct OrbisSaveDataMountResult { - OrbisSaveDataMountPoint mount_point; - u64 required_blocks; - u32 unused; - u32 mount_status; - u8 reserved[28]; - s32 unk1; -}; - -constexpr int ORBIS_SAVE_DATA_TITLE_ID_DATA_SIZE = 10; -struct OrbisSaveDataTitleId { - char data[ORBIS_SAVE_DATA_TITLE_ID_DATA_SIZE]; - char padding[6]; -}; - -constexpr int ORBIS_SAVE_DATA_FINGERPRINT_DATA_SIZE = 65; -struct OrbisSaveDataFingerprint { - char data[ORBIS_SAVE_DATA_FINGERPRINT_DATA_SIZE]; - char padding[15]; -}; - -struct OrbisSaveDataMount { - s32 user_id; - s32 pad; - const OrbisSaveDataTitleId* titleId; - const OrbisSaveDataDirName* dir_name; - const OrbisSaveDataFingerprint* fingerprint; - u64 blocks; - u32 mount_mode; - u8 reserved[32]; -}; - -typedef u32 OrbisSaveDataParamType; - -constexpr int ORBIS_SAVE_DATA_TITLE_MAXSIZE = 128; -constexpr int ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE = 128; -constexpr int ORBIS_SAVE_DATA_DETAIL_MAXSIZE = 1024; struct OrbisSaveDataParam { - char title[ORBIS_SAVE_DATA_TITLE_MAXSIZE]; - char subTitle[ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE]; - char detail[ORBIS_SAVE_DATA_DETAIL_MAXSIZE]; + Common::CString title; + Common::CString subTitle; + Common::CString detail; u32 userParam; int : 32; time_t mtime; - u8 reserved[32]; + std::array _reserved; + + void FromSFO(const PSF& sfo); + + void ToSFO(PSF& sfo) const; }; -struct OrbisSaveDataIcon { - void* buf; - size_t bufSize; - size_t dataSize; - u8 reserved[32]; -}; - -typedef u32 OrbisSaveDataSaveDataMemoryOption; -#define ORBIS_SAVE_DATA_MEMORY_OPTION_NONE (0x00000000) -#define ORBIS_SAVE_DATA_MEMORY_OPTION_SET_PARAM (0x00000001 << 0) -#define ORBIS_SAVE_DATA_MEMORY_OPTION_DOUBLE_BUFFER (0x00000001 << 1) - -struct OrbisSaveDataMemorySetup2 { - OrbisSaveDataSaveDataMemoryOption option; - s32 userId; - size_t memorySize; - size_t iconMemorySize; - const OrbisSaveDataParam* initParam; - const OrbisSaveDataIcon* initIcon; - u32 slotId; - u8 reserved[20]; -}; - -struct OrbisSaveDataMemorySetupResult { - size_t existedMemorySize; - u8 reserved[16]; -}; - -typedef u32 OrbisSaveDataEventType; -#define SCE_SAVE_DATA_EVENT_TYPE_INVALID (0) -#define SCE_SAVE_DATA_EVENT_TYPE_UMOUNT_BACKUP_END (1) -#define SCE_SAVE_DATA_EVENT_TYPE_BACKUP_END (2) -#define SCE_SAVE_DATA_EVENT_TYPE_SAVE_DATA_MEMORY_SYNC_END (3) - -struct OrbisSaveDataEvent { - OrbisSaveDataEventType type; - s32 errorCode; - s32 userId; - u8 padding[4]; - OrbisSaveDataTitleId titleId; - OrbisSaveDataDirName dirName; - u8 reserved[40]; -}; - -struct OrbisSaveDataMemoryData { - void* buf; - size_t bufSize; - off_t offset; - u8 reserved[40]; -}; - -struct OrbisSaveDataMemoryGet2 { - s32 userId; - u8 padding[4]; - OrbisSaveDataMemoryData* data; - OrbisSaveDataParam* param; - OrbisSaveDataIcon* icon; - u32 slotId; - u8 reserved[28]; -}; - -struct OrbisSaveDataMemorySet2 { - s32 userId; - u8 padding[4]; - const OrbisSaveDataMemoryData* data; - const OrbisSaveDataParam* param; - const OrbisSaveDataIcon* icon; - u32 dataNum; - u8 slotId; - u8 reserved[24]; -}; - -struct OrbisSaveDataCheckBackupData { - s32 userId; - int : 32; - const OrbisSaveDataTitleId* titleId; - const OrbisSaveDataDirName* dirName; - OrbisSaveDataParam* param; - OrbisSaveDataIcon* icon; - u8 reserved[32]; -}; - -struct OrbisSaveDataMountInfo { - u64 blocks; - u64 freeBlocks; - u8 reserved[32]; -}; - -#define ORBIS_SAVE_DATA_BLOCK_SIZE (32768) -#define ORBIS_SAVE_DATA_BLOCKS_MIN2 (96) -#define ORBIS_SAVE_DATA_BLOCKS_MAX (32768) - -// savedataMount2 mountModes (ORed values) -constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY = 1; -constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDWR = 2; -constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_CREATE = 4; -constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF = 8; -constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON = 16; -constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 = 32; -typedef struct _OrbisSaveDataEventParam OrbisSaveDataEventParam; - -typedef u32 OrbisSaveDataSortKey; -#define ORBIS_SAVE_DATA_SORT_KEY_DIRNAME (0) -#define ORBIS_SAVE_DATA_SORT_KEY_USER_PARAM (1) -#define ORBIS_SAVE_DATA_SORT_KEY_BLOCKS (2) -#define ORBIS_SAVE_DATA_SORT_KEY_MTIME (3) -#define ORBIS_SAVE_DATA_SORT_KEY_FREE_BLOCKS (5) - -typedef u32 OrbisSaveDataSortOrder; -#define ORBIS_SAVE_DATA_SORT_ORDER_ASCENT (0) -#define ORBIS_SAVE_DATA_SORT_ORDER_DESCENT (1) - -struct OrbisSaveDataDirNameSearchCond { - s32 userId; - int : 32; - const OrbisSaveDataTitleId* titleId; - const OrbisSaveDataDirName* dirName; - OrbisSaveDataSortKey key; - OrbisSaveDataSortOrder order; - u8 reserved[32]; -}; - -struct OrbisSaveDataSearchInfo { - u64 blocks; - u64 freeBlocks; - u8 reserved[32]; -}; - -struct OrbisSaveDataDirNameSearchResult { - u32 hitNum; - int : 32; - OrbisSaveDataDirName* dirNames; - u32 dirNamesNum; - u32 setNum; - OrbisSaveDataParam* params; - OrbisSaveDataSearchInfo* infos; - u8 reserved[12]; - int : 32; -}; - -struct OrbisSaveDataDelete { - s32 userId; - int : 32; - const OrbisSaveDataTitleId* titleId; - const OrbisSaveDataDirName* dirName; - u32 unused; - u8 reserved[32]; - int : 32; -}; - -typedef u32 OrbisSaveDataMemorySyncOption; - -#define SCE_SAVE_DATA_MEMORY_SYNC_OPTION_NONE (0x00000000) -#define SCE_SAVE_DATA_MEMORY_SYNC_OPTION_BLOCKING (0x00000001 << 0) - -struct OrbisSaveDataMemorySync { - s32 userId; - u32 slotId; - OrbisSaveDataMemorySyncOption option; - u8 reserved[28]; -}; - -constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_ALL = 0; -constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_TITLE = 1; -constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_SUB_TITLE = 2; -constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_DETAIL = 3; -constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_USER_PARAM = 4; -constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_MTIME = 5; +struct OrbisSaveDataBackup; +struct OrbisSaveDataCheckBackupData; +struct OrbisSaveDataDelete; +struct OrbisSaveDataDirNameSearchCond; +struct OrbisSaveDataDirNameSearchResult; +struct OrbisSaveDataEvent; +struct OrbisSaveDataEventParam; +struct OrbisSaveDataIcon; +struct OrbisSaveDataMemoryGet2; +struct OrbisSaveDataMemorySet2; +struct OrbisSaveDataMemorySetup2; +struct OrbisSaveDataMemorySetupResult; +struct OrbisSaveDataMemorySync; +struct OrbisSaveDataMount2; +struct OrbisSaveDataMount; +struct OrbisSaveDataMountInfo; +struct OrbisSaveDataMountPoint; +struct OrbisSaveDataMountResult; +struct OrbisSaveDataRestoreBackupData; +struct OrbisSaveDataTransferringMount; int PS4_SYSV_ABI sceSaveDataAbort(); -int PS4_SYSV_ABI sceSaveDataBackup(); +Error PS4_SYSV_ABI sceSaveDataBackup(const OrbisSaveDataBackup* backup); int PS4_SYSV_ABI sceSaveDataBindPsnAccount(); int PS4_SYSV_ABI sceSaveDataBindPsnAccountForSystemBackup(); int PS4_SYSV_ABI sceSaveDataChangeDatabase(); int PS4_SYSV_ABI sceSaveDataChangeInternal(); -int PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check); +Error PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check); int PS4_SYSV_ABI sceSaveDataCheckBackupDataForCdlg(); int PS4_SYSV_ABI sceSaveDataCheckBackupDataInternal(); int PS4_SYSV_ABI sceSaveDataCheckCloudData(); @@ -263,7 +86,7 @@ int PS4_SYSV_ABI sceSaveDataCheckIpmiIfSize(); int PS4_SYSV_ABI sceSaveDataCheckSaveDataBroken(); int PS4_SYSV_ABI sceSaveDataCheckSaveDataVersion(); int PS4_SYSV_ABI sceSaveDataCheckSaveDataVersionLatest(); -int PS4_SYSV_ABI sceSaveDataClearProgress(); +Error PS4_SYSV_ABI sceSaveDataClearProgress(); int PS4_SYSV_ABI sceSaveDataCopy5(); int PS4_SYSV_ABI sceSaveDataCreateUploadData(); int PS4_SYSV_ABI sceSaveDataDebug(); @@ -273,13 +96,13 @@ int PS4_SYSV_ABI sceSaveDataDebugCreateSaveDataRoot(); int PS4_SYSV_ABI sceSaveDataDebugGetThreadId(); int PS4_SYSV_ABI sceSaveDataDebugRemoveSaveDataRoot(); int PS4_SYSV_ABI sceSaveDataDebugTarget(); -int PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del); +Error PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del); int PS4_SYSV_ABI sceSaveDataDelete5(); int PS4_SYSV_ABI sceSaveDataDeleteAllUser(); int PS4_SYSV_ABI sceSaveDataDeleteCloudData(); int PS4_SYSV_ABI sceSaveDataDeleteUser(); -int PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond* cond, - OrbisSaveDataDirNameSearchResult* result); +Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond* cond, + OrbisSaveDataDirNameSearchResult* result); int PS4_SYSV_ABI sceSaveDataDirNameSearchInternal(); int PS4_SYSV_ABI sceSaveDataDownload(); int PS4_SYSV_ABI sceSaveDataGetAllSize(); @@ -292,70 +115,71 @@ int PS4_SYSV_ABI sceSaveDataGetClientThreadPriority(); int PS4_SYSV_ABI sceSaveDataGetCloudQuotaInfo(); int PS4_SYSV_ABI sceSaveDataGetDataBaseFilePath(); int PS4_SYSV_ABI sceSaveDataGetEventInfo(); -int PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam* eventParam, - OrbisSaveDataEvent* event); +Error PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam* eventParam, + OrbisSaveDataEvent* event); int PS4_SYSV_ABI sceSaveDataGetFormat(); int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount(); -int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, - OrbisSaveDataMountInfo* info); -int PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint, - const OrbisSaveDataParamType paramType, void* paramBuf, - const size_t paramBufSize, size_t* gotSize); -int PS4_SYSV_ABI sceSaveDataGetProgress(); +Error PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataMountInfo* info); +Error PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataParamType paramType, void* paramBuf, + size_t paramBufSize, size_t* gotSize); +Error PS4_SYSV_ABI sceSaveDataGetProgress(float* progress); int PS4_SYSV_ABI sceSaveDataGetSaveDataCount(); -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize, - const int64_t offset); -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam); +Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(OrbisUserServiceUserId userId, void* buf, + size_t bufSize, int64_t offset); +Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootDir(); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootPath(); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootUsbPath(); int PS4_SYSV_ABI sceSaveDataGetSavePoint(); int PS4_SYSV_ABI sceSaveDataGetUpdatedDataCount(); -int PS4_SYSV_ABI sceSaveDataInitialize(); -int PS4_SYSV_ABI sceSaveDataInitialize2(); -int PS4_SYSV_ABI sceSaveDataInitialize3(); +Error PS4_SYSV_ABI sceSaveDataInitialize(void*); +Error PS4_SYSV_ABI sceSaveDataInitialize2(void*); +Error PS4_SYSV_ABI sceSaveDataInitialize3(void*); int PS4_SYSV_ABI sceSaveDataInitializeForCdlg(); int PS4_SYSV_ABI sceSaveDataIsDeletingUsbDb(); int PS4_SYSV_ABI sceSaveDataIsMounted(); -int PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, - OrbisSaveDataIcon* icon); -int PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, - OrbisSaveDataMountResult* mount_result); -s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, - OrbisSaveDataMountResult* mount_result); +Error PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataIcon* icon); +Error PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, + OrbisSaveDataMountResult* mount_result); +Error PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, + OrbisSaveDataMountResult* mount_result); int PS4_SYSV_ABI sceSaveDataMount5(); int PS4_SYSV_ABI sceSaveDataMountInternal(); int PS4_SYSV_ABI sceSaveDataMountSys(); int PS4_SYSV_ABI sceSaveDataPromote5(); int PS4_SYSV_ABI sceSaveDataRebuildDatabase(); int PS4_SYSV_ABI sceSaveDataRegisterEventCallback(); -int PS4_SYSV_ABI sceSaveDataRestoreBackupData(); +Error PS4_SYSV_ABI sceSaveDataRestoreBackupData(const OrbisSaveDataRestoreBackupData* restore); int PS4_SYSV_ABI sceSaveDataRestoreBackupDataForCdlg(); int PS4_SYSV_ABI sceSaveDataRestoreLoadSaveDataMemory(); -int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, - const OrbisSaveDataIcon* icon); +Error PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, + const OrbisSaveDataIcon* icon); int PS4_SYSV_ABI sceSaveDataSetAutoUploadSetting(); int PS4_SYSV_ABI sceSaveDataSetEventInfo(); -int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, - OrbisSaveDataParamType paramType, const void* paramBuf, - size_t paramBufSize); +Error PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataParamType paramType, const void* paramBuf, + size_t paramBufSize); int PS4_SYSV_ABI sceSaveDataSetSaveDataLibraryUser(); -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf, - const size_t bufSize, const int64_t offset); -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam); -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(u32 userId, size_t memorySize, - OrbisSaveDataParam* param); -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, - OrbisSaveDataMemorySetupResult* result); +Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(OrbisUserServiceUserId userId, void* buf, + size_t bufSize, int64_t offset); +Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam); +Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(OrbisUserServiceUserId userId, size_t memorySize, + OrbisSaveDataParam* param); +Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, + OrbisSaveDataMemorySetupResult* result); int PS4_SYSV_ABI sceSaveDataShutdownStart(); int PS4_SYSV_ABI sceSaveDataSupportedFakeBrokenStatus(); int PS4_SYSV_ABI sceSaveDataSyncCloudList(); -int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam); -int PS4_SYSV_ABI sceSaveDataTerminate(); -int PS4_SYSV_ABI sceSaveDataTransferringMount(); -int PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint); +Error PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam); +Error PS4_SYSV_ABI sceSaveDataTerminate(); +Error PS4_SYSV_ABI sceSaveDataTransferringMount(const OrbisSaveDataTransferringMount* mount, + OrbisSaveDataMountResult* mountResult); +Error PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint); int PS4_SYSV_ABI sceSaveDataUmountSys(); -int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint); +Error PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint); int PS4_SYSV_ABI sceSaveDataUnregisterEventCallback(); int PS4_SYSV_ABI sceSaveDataUpload(); int PS4_SYSV_ABI Func_02E4C4D201716422(); diff --git a/src/core/libraries/screenshot/screenshot.cpp b/src/core/libraries/screenshot/screenshot.cpp index 1924ddf54..eaa535de7 100644 --- a/src/core/libraries/screenshot/screenshot.cpp +++ b/src/core/libraries/screenshot/screenshot.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/share_play/shareplay.cpp b/src/core/libraries/share_play/shareplay.cpp new file mode 100644 index 000000000..8370438b9 --- /dev/null +++ b/src/core/libraries/share_play/shareplay.cpp @@ -0,0 +1,186 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "shareplay.h" + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" + +namespace Libraries::SharePlay { + +int PS4_SYSV_ABI sceSharePlayCrashDaemon() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayGetCurrentConnectionInfo(OrbisSharePlayConnectionInfo* pInfo) { + memset(pInfo, 0, sizeof(*pInfo)); + pInfo->status = ORBIS_SHARE_PLAY_CONNECTION_STATUS_DORMANT; + LOG_DEBUG(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayGetCurrentConnectionInfoA() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayGetCurrentInfo() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayGetEvent() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayInitialize() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayNotifyDialogOpen() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayNotifyForceCloseForCdlg() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayNotifyOpenQuickMenu() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayResumeScreenForCdlg() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayServerLock() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayServerUnLock() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlaySetMode() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlaySetProhibition() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlaySetProhibitionModeWithAppId() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayStartStandby() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayStartStreaming() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayStopStandby() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayStopStreaming() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceSharePlayTerminate() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI Func_2E93C0EA6A6B67C4() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI Func_C1C236728D88E177() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI Func_E9E80C474781F115() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI Func_F3DD6199DA15ED44() { + LOG_ERROR(Lib_SharePlay, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceSharePlay(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("ggnCfalLU-8", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayCrashDaemon); + LIB_FUNCTION("OOrLKB0bSDs", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayGetCurrentConnectionInfo); + LIB_FUNCTION("+MCXJlWdi+s", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayGetCurrentConnectionInfoA); + LIB_FUNCTION("vUMkWXQff3w", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayGetCurrentInfo); + LIB_FUNCTION("Md7Mdkr8LBc", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayGetEvent); + LIB_FUNCTION("isruqthpYcw", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayInitialize); + LIB_FUNCTION("9zwJpai7jGc", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayNotifyDialogOpen); + LIB_FUNCTION("VUW2V9cUTP4", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayNotifyForceCloseForCdlg); + LIB_FUNCTION("XL0WwUJoQPg", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayNotifyOpenQuickMenu); + LIB_FUNCTION("6-1fKaa5HlY", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayResumeScreenForCdlg); + LIB_FUNCTION("U28jAuLHj6c", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayServerLock); + LIB_FUNCTION("3Oaux9ITEtY", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayServerUnLock); + LIB_FUNCTION("QZy+KmyqKPU", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, sceSharePlaySetMode); + LIB_FUNCTION("co2NCj--pnc", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlaySetProhibition); + LIB_FUNCTION("KADsbjNCgPo", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlaySetProhibitionModeWithAppId); + LIB_FUNCTION("-F6NddfUsa4", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayStartStandby); + LIB_FUNCTION("rWVNHNnEx6g", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayStartStreaming); + LIB_FUNCTION("zEDkUWLVwFI", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayStopStandby); + LIB_FUNCTION("aGlema+JxUU", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayStopStreaming); + LIB_FUNCTION("UaLjloJinow", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + sceSharePlayTerminate); + LIB_FUNCTION("LpPA6mprZ8Q", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + Func_2E93C0EA6A6B67C4); + LIB_FUNCTION("wcI2co2I4Xc", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + Func_C1C236728D88E177); + LIB_FUNCTION("6egMR0eB8RU", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + Func_E9E80C474781F115); + LIB_FUNCTION("891hmdoV7UQ", "libSceSharePlay", 1, "libSceSharePlay", 0, 0, + Func_F3DD6199DA15ED44); + LIB_FUNCTION("OOrLKB0bSDs", "libSceSharePlayCompat", 1, "libSceSharePlay", 0, 0, + sceSharePlayGetCurrentConnectionInfo); +}; + +} // namespace Libraries::SharePlay \ No newline at end of file diff --git a/src/core/libraries/share_play/shareplay.h b/src/core/libraries/share_play/shareplay.h new file mode 100644 index 000000000..8b1ad5f47 --- /dev/null +++ b/src/core/libraries/share_play/shareplay.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::SharePlay { + +constexpr int ORBIS_SHARE_PLAY_CONNECTION_STATUS_DORMANT = 0x00; +constexpr int ORBIS_SHARE_PLAY_CONNECTION_STATUS_READY = 0x01; +constexpr int ORBIS_SHARE_PLAY_CONNECTION_STATUS_CONNECTED = 0x02; + +struct OrbisSharePlayConnectionInfo { + int status; + int mode; + Libraries::NpManager::OrbisNpOnlineId hostOnlineId; + Libraries::NpManager::OrbisNpOnlineId visitorOnlineId; + s32 hostUserId; + s32 visitorUserId; +}; + +int PS4_SYSV_ABI sceSharePlayCrashDaemon(); +int PS4_SYSV_ABI sceSharePlayGetCurrentConnectionInfo(OrbisSharePlayConnectionInfo* pInfo); +int PS4_SYSV_ABI sceSharePlayGetCurrentConnectionInfoA(); +int PS4_SYSV_ABI sceSharePlayGetCurrentInfo(); +int PS4_SYSV_ABI sceSharePlayGetEvent(); +int PS4_SYSV_ABI sceSharePlayInitialize(); +int PS4_SYSV_ABI sceSharePlayNotifyDialogOpen(); +int PS4_SYSV_ABI sceSharePlayNotifyForceCloseForCdlg(); +int PS4_SYSV_ABI sceSharePlayNotifyOpenQuickMenu(); +int PS4_SYSV_ABI sceSharePlayResumeScreenForCdlg(); +int PS4_SYSV_ABI sceSharePlayServerLock(); +int PS4_SYSV_ABI sceSharePlayServerUnLock(); +int PS4_SYSV_ABI sceSharePlaySetMode(); +int PS4_SYSV_ABI sceSharePlaySetProhibition(); +int PS4_SYSV_ABI sceSharePlaySetProhibitionModeWithAppId(); +int PS4_SYSV_ABI sceSharePlayStartStandby(); +int PS4_SYSV_ABI sceSharePlayStartStreaming(); +int PS4_SYSV_ABI sceSharePlayStopStandby(); +int PS4_SYSV_ABI sceSharePlayStopStreaming(); +int PS4_SYSV_ABI sceSharePlayTerminate(); +int PS4_SYSV_ABI Func_2E93C0EA6A6B67C4(); +int PS4_SYSV_ABI Func_C1C236728D88E177(); +int PS4_SYSV_ABI Func_E9E80C474781F115(); +int PS4_SYSV_ABI Func_F3DD6199DA15ED44(); + +void RegisterlibSceSharePlay(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::SharePlay \ No newline at end of file diff --git a/src/core/libraries/system/commondialog.cpp b/src/core/libraries/system/commondialog.cpp index e32e3bb3f..cb9ce0442 100644 --- a/src/core/libraries/system/commondialog.cpp +++ b/src/core/libraries/system/commondialog.cpp @@ -8,6 +8,9 @@ namespace Libraries::CommonDialog { +bool g_isInitialized = false; +bool g_isUsed = false; + int PS4_SYSV_ABI _ZN3sce16CommonDialogUtil12getSelfAppIdEv() { LOG_ERROR(Lib_CommonDlg, "(STUBBED) called"); return ORBIS_OK; @@ -83,14 +86,19 @@ int PS4_SYSV_ABI _ZTVN3sce16CommonDialogUtil6ClientE() { return ORBIS_OK; } -int PS4_SYSV_ABI sceCommonDialogInitialize() { - LOG_ERROR(Lib_CommonDlg, "(DUMMY) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceCommonDialogInitialize() { + if (g_isInitialized) { + LOG_INFO(Lib_CommonDlg, "already initialized"); + return Error::ALREADY_SYSTEM_INITIALIZED; + } + LOG_DEBUG(Lib_CommonDlg, "initialized"); + g_isInitialized = true; + return Error::OK; } -int PS4_SYSV_ABI sceCommonDialogIsUsed() { - LOG_ERROR(Lib_CommonDlg, "(STUBBED) called"); - return ORBIS_OK; +bool PS4_SYSV_ABI sceCommonDialogIsUsed() { + LOG_TRACE(Lib_CommonDlg, "called"); + return g_isUsed; } int PS4_SYSV_ABI Func_0FF577E4E8457883() { diff --git a/src/core/libraries/system/commondialog.h b/src/core/libraries/system/commondialog.h index 110e9cc99..6b8ea3d95 100644 --- a/src/core/libraries/system/commondialog.h +++ b/src/core/libraries/system/commondialog.h @@ -11,9 +11,44 @@ class SymbolsResolver; namespace Libraries::CommonDialog { -struct OrbisCommonDialogBaseParam { +enum class Status : u32 { + NONE = 0, + INITIALIZED = 1, + RUNNING = 2, + FINISHED = 3, +}; + +enum class Result : u32 { + OK = 0, + USER_CANCELED = 1, +}; + +enum class Error : u32 { + OK = 0, + NOT_SYSTEM_INITIALIZED = 0x80B80001, + ALREADY_SYSTEM_INITIALIZED = 0x80B80002, + NOT_INITIALIZED = 0x80B80003, + ALREADY_INITIALIZED = 0x80B80004, + NOT_FINISHED = 0x80B80005, + INVALID_STATE = 0x80B80006, + RESULT_NONE = 0x80B80007, + BUSY = 0x80B80008, + OUT_OF_MEMORY = 0x80B80009, + PARAM_INVALID = 0x80B8000A, + NOT_RUNNING = 0x80B8000B, + ALREADY_CLOSE = 0x80B8000C, + ARG_NULL = 0x80B8000D, + UNEXPECTED_FATAL = 0x80B8000E, + NOT_SUPPORTED = 0x80B8000F, + INHIBIT_SHAREPLAY_CLIENT = 0x80B80010, +}; + +extern bool g_isInitialized; +extern bool g_isUsed; + +struct BaseParam { std::size_t size; - u8 reserved[36]; + std::array reserved; u32 magic; }; @@ -32,8 +67,8 @@ int PS4_SYSV_ABI _ZNK3sce16CommonDialogUtil6Client8getAppIdEv(); int PS4_SYSV_ABI _ZNK3sce16CommonDialogUtil6Client8isFinishEv(); int PS4_SYSV_ABI _ZNK3sce16CommonDialogUtil6Client9getResultEv(); int PS4_SYSV_ABI _ZTVN3sce16CommonDialogUtil6ClientE(); -int PS4_SYSV_ABI sceCommonDialogInitialize(); -int PS4_SYSV_ABI sceCommonDialogIsUsed(); +Error PS4_SYSV_ABI sceCommonDialogInitialize(); +bool PS4_SYSV_ABI sceCommonDialogIsUsed(); int PS4_SYSV_ABI Func_0FF577E4E8457883(); int PS4_SYSV_ABI Func_41716C2CE379416C(); int PS4_SYSV_ABI Func_483A427D8F6E0748(); diff --git a/src/core/libraries/system/msgdialog.cpp b/src/core/libraries/system/msgdialog.cpp index 452feec93..7d924e4ad 100644 --- a/src/core/libraries/system/msgdialog.cpp +++ b/src/core/libraries/system/msgdialog.cpp @@ -1,79 +1,152 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include + +#include "common/assert.h" #include "common/logging/log.h" -#include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/system/msgdialog.h" - -#include +#include "imgui_internal.h" +#include "msgdialog_ui.h" namespace Libraries::MsgDialog { -int PS4_SYSV_ABI sceMsgDialogClose() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; -} +using CommonDialog::Error; +using CommonDialog::Result; +using CommonDialog::Status; -int PS4_SYSV_ABI sceMsgDialogGetResult() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; -} +static auto g_status = Status::NONE; +static MsgDialogState g_state{}; +static DialogResult g_result{}; +static MsgDialogUi g_msg_dialog_ui; -int PS4_SYSV_ABI sceMsgDialogGetStatus() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceMsgDialogInitialize() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceMsgDialogOpen(const OrbisMsgDialogParam* param) { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - switch (param->mode) { - case ORBIS_MSG_DIALOG_MODE_USER_MSG: - LOG_INFO(Lib_MsgDlg, "sceMsgDialogOpen userMsg type = %s msg = %s", - magic_enum::enum_name(param->userMsgParam->buttonType), param->userMsgParam->msg); - break; - case ORBIS_MSG_DIALOG_MODE_PROGRESS_BAR: - LOG_INFO(Lib_MsgDlg, "sceMsgDialogOpen progressBar type = %s msg = %s", - magic_enum::enum_name(param->progBarParam->barType), param->progBarParam->msg); - break; - case ORBIS_MSG_DIALOG_MODE_SYSTEM_MSG: - LOG_INFO(Lib_MsgDlg, "sceMsgDialogOpen systemMsg type: %s", - magic_enum::enum_name(param->sysMsgParam->sysMsgType)); - break; - default: - break; +Error PS4_SYSV_ABI sceMsgDialogClose() { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; } - return ORBIS_OK; + g_msg_dialog_ui.Finish(ButtonId::INVALID); + return Error::OK; } -int PS4_SYSV_ABI sceMsgDialogProgressBarInc() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceMsgDialogGetResult(DialogResult* result) { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (g_status != Status::FINISHED) { + return Error::NOT_FINISHED; + } + if (result == nullptr) { + return Error::ARG_NULL; + } + *result = g_result; + return Error::OK; } -int PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; +Status PS4_SYSV_ABI sceMsgDialogGetStatus() { + LOG_TRACE(Lib_MsgDlg, "called status={}", magic_enum::enum_name(g_status)); + return g_status; } -int PS4_SYSV_ABI sceMsgDialogProgressBarSetValue() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceMsgDialogInitialize() { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (!CommonDialog::g_isInitialized) { + return Error::NOT_SYSTEM_INITIALIZED; + } + if (g_status != Status::NONE) { + return Error::ALREADY_INITIALIZED; + } + if (CommonDialog::g_isUsed) { + return Error::BUSY; + } + g_status = Status::INITIALIZED; + CommonDialog::g_isUsed = true; + + return Error::OK; } -int PS4_SYSV_ABI sceMsgDialogTerminate() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceMsgDialogOpen(const OrbisParam* param) { + if (g_status != Status::INITIALIZED && g_status != Status::FINISHED) { + LOG_INFO(Lib_MsgDlg, "called without initialize"); + return Error::INVALID_STATE; + } + if (param == nullptr) { + LOG_DEBUG(Lib_MsgDlg, "called param:(NULL)"); + return Error::ARG_NULL; + } + LOG_DEBUG(Lib_MsgDlg, "called param->mode: {}", magic_enum::enum_name(param->mode)); + ASSERT(param->size == sizeof(OrbisParam)); + ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam)); + g_result = {}; + g_state = MsgDialogState{*param}; + g_status = Status::RUNNING; + g_msg_dialog_ui = MsgDialogUi(&g_state, &g_status, &g_result); + return Error::OK; } -int PS4_SYSV_ABI sceMsgDialogUpdateStatus() { - LOG_ERROR(Lib_MsgDlg, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceMsgDialogProgressBarInc(OrbisMsgDialogProgressBarTarget target, u32 delta) { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) { + return Error::NOT_SUPPORTED; + } + if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) { + return Error::PARAM_INVALID; + } + g_state.GetState().progress += delta; + return Error::OK; +} + +Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget target, + const char* msg) { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) { + return Error::NOT_SUPPORTED; + } + if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) { + return Error::PARAM_INVALID; + } + g_state.GetState().msg = msg; + return Error::OK; +} + +Error PS4_SYSV_ABI sceMsgDialogProgressBarSetValue(OrbisMsgDialogProgressBarTarget target, + u32 value) { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (g_status != Status::RUNNING) { + return Error::NOT_RUNNING; + } + if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) { + return Error::NOT_SUPPORTED; + } + if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) { + return Error::PARAM_INVALID; + } + g_state.GetState().progress = value; + return Error::OK; +} + +Error PS4_SYSV_ABI sceMsgDialogTerminate() { + LOG_DEBUG(Lib_MsgDlg, "called"); + if (g_status == Status::RUNNING) { + sceMsgDialogClose(); + } + if (g_status == Status::NONE) { + return Error::NOT_INITIALIZED; + } + g_status = Status::NONE; + CommonDialog::g_isUsed = false; + return Error::OK; +} + +Status PS4_SYSV_ABI sceMsgDialogUpdateStatus() { + LOG_TRACE(Lib_MsgDlg, "called status={}", magic_enum::enum_name(g_status)); + return g_status; } void RegisterlibSceMsgDialog(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/system/msgdialog.h b/src/core/libraries/system/msgdialog.h index 28d379138..b8a1f3f07 100644 --- a/src/core/libraries/system/msgdialog.h +++ b/src/core/libraries/system/msgdialog.h @@ -3,7 +3,6 @@ #pragma once -#include "common/types.h" #include "core/libraries/system/commondialog.h" namespace Core::Loader { @@ -12,95 +11,23 @@ class SymbolsResolver; namespace Libraries::MsgDialog { -using OrbisUserServiceUserId = s32; +struct DialogResult; +struct OrbisParam; +enum class OrbisMsgDialogProgressBarTarget : u32; -enum OrbisCommonDialogStatus { - ORBIS_COMMON_DIALOG_STATUS_NONE = 0, - ORBIS_COMMON_DIALOG_STATUS_INITIALIZED = 1, - ORBIS_COMMON_DIALOG_STATUS_RUNNING = 2, - ORBIS_COMMON_DIALOG_STATUS_FINISHED = 3 -}; - -enum OrbisMsgDialogMode { - ORBIS_MSG_DIALOG_MODE_USER_MSG = 1, - ORBIS_MSG_DIALOG_MODE_PROGRESS_BAR = 2, - ORBIS_MSG_DIALOG_MODE_SYSTEM_MSG = 3, -}; - -enum OrbisMsgDialogButtonType { - ORBIS_MSG_DIALOG_BUTTON_TYPE_OK = 0, - ORBIS_MSG_DIALOG_BUTTON_TYPE_YESNO = 1, - ORBIS_MSG_DIALOG_BUTTON_TYPE_NONE = 2, - ORBIS_MSG_DIALOG_BUTTON_TYPE_OK_CANCEL = 3, - ORBIS_MSG_DIALOG_BUTTON_TYPE_WAIT = 5, - ORBIS_MSG_DIALOG_BUTTON_TYPE_WAIT_CANCEL = 6, - ORBIS_MSG_DIALOG_BUTTON_TYPE_YESNO_FOCUS_NO = 7, - ORBIS_MSG_DIALOG_BUTTON_TYPE_OK_CANCEL_FOCUS_CANCEL = 8, - ORBIS_MSG_DIALOG_BUTTON_TYPE_2BUTTONS = 9, -}; - -enum OrbisMsgDialogProgressBarType { - ORBIS_MSG_DIALOG_PROGRESSBAR_TYPE_PERCENTAGE = 0, - ORBIS_MSG_DIALOG_PROGRESSBAR_TYPE_PERCENTAGE_CANCEL = 1, -}; - -enum OrbisMsgDialogSystemMessageType { - ORBIS_MSG_DIALOG_SYSMSG_TYPE_TRC_EMPTY_STORE = 0, - ORBIS_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION = 1, - ORBIS_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_UGC_RESTRICTION = 2, - ORBIS_MSG_DIALOG_SYSMSG_TYPE_CAMERA_NOT_CONNECTED = 4, - ORBIS_MSG_DIALOG_SYSMSG_TYPE_WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED = 5, -}; - -struct OrbisMsgDialogButtonsParam { - const char* msg1; - const char* msg2; - char reserved[32]; -}; - -struct OrbisMsgDialogUserMessageParam { - OrbisMsgDialogButtonType buttonType; - s32 : 32; - const char* msg; - OrbisMsgDialogButtonsParam* buttonsParam; - char reserved[24]; -}; - -struct OrbisMsgDialogProgressBarParam { - OrbisMsgDialogProgressBarType barType; - int32_t : 32; - const char* msg; - char reserved[64]; -}; - -struct OrbisMsgDialogSystemMessageParam { - OrbisMsgDialogSystemMessageType sysMsgType; - char reserved[32]; -}; - -struct OrbisMsgDialogParam { - CommonDialog::OrbisCommonDialogBaseParam baseParam; - std::size_t size; - OrbisMsgDialogMode mode; - s32 : 32; - OrbisMsgDialogUserMessageParam* userMsgParam; - OrbisMsgDialogProgressBarParam* progBarParam; - OrbisMsgDialogSystemMessageParam* sysMsgParam; - OrbisUserServiceUserId userId; - char reserved[40]; - s32 : 32; -}; - -int PS4_SYSV_ABI sceMsgDialogClose(); -int PS4_SYSV_ABI sceMsgDialogGetResult(); -int PS4_SYSV_ABI sceMsgDialogGetStatus(); -int PS4_SYSV_ABI sceMsgDialogInitialize(); -s32 PS4_SYSV_ABI sceMsgDialogOpen(const OrbisMsgDialogParam* param); -int PS4_SYSV_ABI sceMsgDialogProgressBarInc(); -int PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(); -int PS4_SYSV_ABI sceMsgDialogProgressBarSetValue(); -int PS4_SYSV_ABI sceMsgDialogTerminate(); -int PS4_SYSV_ABI sceMsgDialogUpdateStatus(); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogClose(); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogGetResult(DialogResult* result); +CommonDialog::Status PS4_SYSV_ABI sceMsgDialogGetStatus(); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogInitialize(); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogOpen(const OrbisParam* param); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarInc(OrbisMsgDialogProgressBarTarget, + u32 delta); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget, + const char* msg); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarSetValue(OrbisMsgDialogProgressBarTarget, + u32 value); +CommonDialog::Error PS4_SYSV_ABI sceMsgDialogTerminate(); +CommonDialog::Status PS4_SYSV_ABI sceMsgDialogUpdateStatus(); void RegisterlibSceMsgDialog(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::MsgDialog diff --git a/src/core/libraries/system/msgdialog_ui.cpp b/src/core/libraries/system/msgdialog_ui.cpp new file mode 100644 index 000000000..862f5a569 --- /dev/null +++ b/src/core/libraries/system/msgdialog_ui.cpp @@ -0,0 +1,300 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#include +#include "common/assert.h" +#include "imgui/imgui_std.h" +#include "msgdialog_ui.h" + +using namespace ImGui; +using namespace Libraries::CommonDialog; +using namespace Libraries::MsgDialog; + +static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; +static constexpr float PROGRESS_BAR_WIDTH{0.8f}; + +struct { + int count = 0; + const char* text1; + const char* text2; +} static constexpr user_button_texts[] = { + {1, "OK"}, // 0 OK + {2, "Yes", "No"}, // 1 YESNO + {0}, // 2 NONE + {2, "OK", "Cancel"}, // 3 OK_CANCEL + {}, // 4 !!NOP + {1, "Wait"}, // 5 WAIT + {2, "Wait", "Cancel"}, // 6 WAIT_CANCEL + {2, "Yes", "No"}, // 7 YESNO_FOCUS_NO + {2, "OK", "Cancel"}, // 8 OK_CANCEL_FOCUS_CANCEL + {0xFF}, // 9 TWO_BUTTONS +}; +static_assert(std::size(user_button_texts) == static_cast(ButtonType::TWO_BUTTONS) + 1); + +MsgDialogState::MsgDialogState(const OrbisParam& param) { + this->mode = param.mode; + switch (mode) { + case MsgDialogMode::USER_MSG: { + ASSERT(param.userMsgParam); + const auto& v = *param.userMsgParam; + auto state = UserState{ + .type = v.buttonType, + .msg = std::string(v.msg), + }; + if (v.buttonType == ButtonType::TWO_BUTTONS) { + ASSERT(v.buttonsParam); + state.btn_param1 = std::string(v.buttonsParam->msg1); + state.btn_param2 = std::string(v.buttonsParam->msg2); + } + this->state = state; + } break; + case MsgDialogMode::PROGRESS_BAR: { + ASSERT(param.progBarParam); + const auto& v = *param.progBarParam; + this->state = ProgressState{ + .type = v.barType, + .msg = std::string(v.msg), + .progress = 0, + }; + } break; + case MsgDialogMode::SYSTEM_MSG: { + ASSERT(param.sysMsgParam); + const auto& v = *param.sysMsgParam; + this->state = SystemState{ + .type = v.sysMsgType, + }; + } break; + default: + UNREACHABLE_MSG("Unknown dialog mode"); + } +} + +MsgDialogState::MsgDialogState(UserState mode) { + this->mode = MsgDialogMode::USER_MSG; + this->state = mode; +} + +MsgDialogState::MsgDialogState(ProgressState mode) { + this->mode = MsgDialogMode::PROGRESS_BAR; + this->state = mode; +} + +MsgDialogState::MsgDialogState(SystemState mode) { + this->mode = MsgDialogMode::SYSTEM_MSG; + this->state = mode; +} + +void MsgDialogUi::DrawUser() { + const auto& [button_type, msg, btn_param1, btn_param2] = + state->GetState(); + const auto ws = GetWindowSize(); + if (!msg.empty()) { + DrawCenteredText(&msg.front(), &msg.back() + 1, + GetContentRegionAvail() - ImVec2{0.0f, 15.0f + BUTTON_SIZE.y}); + } + ASSERT(button_type <= ButtonType::TWO_BUTTONS); + auto [count, text1, text2] = user_button_texts[static_cast(button_type)]; + if (count == 0xFF) { // TWO_BUTTONS -> User defined message + count = 2; + text1 = btn_param1.c_str(); + text2 = btn_param2.c_str(); + } + const bool focus_first = button_type < ButtonType::YESNO_FOCUS_NO; + SetCursorPos({ + ws.x / 2.0f - BUTTON_SIZE.x / 2.0f * static_cast(count), + ws.y - 10.0f - BUTTON_SIZE.y, + }); + BeginGroup(); + if (count > 0) { + // First button at the right, so we render the second button first + if (count == 2) { + PushID(2); + if (Button(text2, BUTTON_SIZE)) { + switch (button_type) { + case ButtonType::OK_CANCEL: + case ButtonType::WAIT_CANCEL: + case ButtonType::OK_CANCEL_FOCUS_CANCEL: + Finish(ButtonId::INVALID, Result::USER_CANCELED); + break; + default: + Finish(ButtonId::BUTTON2); + break; + } + } + if ((first_render || IsKeyPressed(ImGuiKey_GamepadFaceRight)) && !focus_first) { + SetItemCurrentNavFocus(); + } + PopID(); + SameLine(); + } + PushID(1); + if (Button(text1, BUTTON_SIZE)) { + Finish(ButtonId::BUTTON1); + } + if ((first_render || IsKeyPressed(ImGuiKey_GamepadFaceRight)) && focus_first) { + SetItemCurrentNavFocus(); + } + PopID(); + SameLine(); + } + EndGroup(); +} + +void MsgDialogUi::DrawProgressBar() { + const auto& [bar_type, msg, progress_bar_value] = + state->GetState(); + DrawCenteredText(msg.c_str()); + const auto ws = GetWindowSize(); + SetCursorPos({ + ws.x * ((1 - PROGRESS_BAR_WIDTH) / 2.0f), + ws.y - 10.0f - BUTTON_SIZE.y, + }); + const bool has_cancel = bar_type == ProgressBarType::PERCENTAGE_CANCEL; + float bar_width = PROGRESS_BAR_WIDTH * ws.x; + if (has_cancel) { + bar_width -= BUTTON_SIZE.x - 10.0f; + } + BeginGroup(); + ProgressBar(static_cast(progress_bar_value) / 100.0f, {bar_width, BUTTON_SIZE.y}); + if (has_cancel) { + SameLine(); + if (Button("Cancel", BUTTON_SIZE)) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } + if (first_render) { + SetItemCurrentNavFocus(); + } + } + EndGroup(); +} + +struct { + const char* text; +} static constexpr system_message_texts[] = { + "No product available in the store.", // TRC_EMPTY_STORE + "PSN chat restriction.", // TRC_PSN_CHAT_RESTRICTION + "User-generated Media restriction", // TRC_PSN_UGC_RESTRICTION + nullptr, // !!NOP + "Camera not connected.", // CAMERA_NOT_CONNECTED + "Warning: profile picture and name are not set", // WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED +}; +static_assert(std::size(system_message_texts) == + static_cast(SystemMessageType::WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED) + 1); + +void MsgDialogUi::DrawSystemMessage() { + // TODO: Implement go to settings & user profile + const auto& [msg_type] = state->GetState(); + ASSERT(msg_type <= SystemMessageType::WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED); + auto [msg] = system_message_texts[static_cast(msg_type)]; + DrawCenteredText(msg); + const auto ws = GetWindowSize(); + SetCursorPos({ + ws.x / 2.0f - BUTTON_SIZE.x / 2.0f, + ws.y - 10.0f - BUTTON_SIZE.y, + }); + if (Button("OK", BUTTON_SIZE)) { + Finish(ButtonId::OK); + } + if (first_render) { + SetItemCurrentNavFocus(); + } +} + +MsgDialogUi::MsgDialogUi(MsgDialogState* state, Status* status, DialogResult* result) + : state(state), status(status), result(result) { + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } +} +MsgDialogUi::~MsgDialogUi() { + Finish(ButtonId::INVALID); +} +MsgDialogUi::MsgDialogUi(MsgDialogUi&& other) noexcept + : Layer(other), state(other.state), status(other.status), result(other.result) { + other.state = nullptr; + other.status = nullptr; + other.result = nullptr; +} +MsgDialogUi& MsgDialogUi::operator=(MsgDialogUi other) { + using std::swap; + swap(state, other.state); + swap(status, other.status); + swap(result, other.result); + if (status && *status == Status::RUNNING) { + first_render = true; + AddLayer(this); + } + return *this; +} + +void MsgDialogUi::Finish(ButtonId buttonId, Result r) { + if (result) { + result->result = r; + result->buttonId = buttonId; + } + if (status) { + *status = Status::FINISHED; + } + state = nullptr; + status = nullptr; + result = nullptr; + RemoveLayer(this); +} + +void MsgDialogUi::Draw() { + if (status == nullptr || *status != Status::RUNNING) { + return; + } + const auto& io = GetIO(); + + const ImVec2 window_size{ + std::min(io.DisplaySize.x, 500.0f), + std::min(io.DisplaySize.y, 300.0f), + }; + + CentralizeNextWindow(); + SetNextWindowSize(window_size); + SetNextWindowCollapsed(false); + if (first_render || !io.NavActive) { + SetNextWindowFocus(); + } + KeepNavHighlight(); + if (Begin("Message Dialog##MessageDialog", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { + switch (state->GetMode()) { + case MsgDialogMode::USER_MSG: + DrawUser(); + break; + case MsgDialogMode::PROGRESS_BAR: + DrawProgressBar(); + break; + case MsgDialogMode::SYSTEM_MSG: + DrawSystemMessage(); + break; + } + } + End(); + + first_render = false; +} + +DialogResult Libraries::MsgDialog::ShowMsgDialog(MsgDialogState p_state, bool block) { + static DialogResult result{}; + static Status status; + static MsgDialogUi dialog; + static MsgDialogState state; + dialog = MsgDialogUi{}; + status = Status::RUNNING; + state = std::move(p_state); + dialog = MsgDialogUi(&state, &status, &result); + if (block) { + while (status == Status::RUNNING) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + } + return result; +} diff --git a/src/core/libraries/system/msgdialog_ui.h b/src/core/libraries/system/msgdialog_ui.h new file mode 100644 index 000000000..d24ec067c --- /dev/null +++ b/src/core/libraries/system/msgdialog_ui.h @@ -0,0 +1,181 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/fixed_value.h" +#include "common/types.h" +#include "core/libraries/system/commondialog.h" +#include "imgui/imgui_layer.h" + +namespace Libraries::MsgDialog { + +using OrbisUserServiceUserId = s32; + +enum class MsgDialogMode : u32 { + USER_MSG = 1, + PROGRESS_BAR = 2, + SYSTEM_MSG = 3, +}; + +enum class ButtonId : u32 { + INVALID = 0, + OK = 1, + YES = 1, + NO = 2, + BUTTON1 = 1, + BUTTON2 = 2, +}; + +enum class ButtonType : u32 { + OK = 0, + YESNO = 1, + NONE = 2, + OK_CANCEL = 3, + WAIT = 5, + WAIT_CANCEL = 6, + YESNO_FOCUS_NO = 7, + OK_CANCEL_FOCUS_CANCEL = 8, + TWO_BUTTONS = 9, +}; + +enum class ProgressBarType : u32 { + PERCENTAGE = 0, + PERCENTAGE_CANCEL = 1, +}; + +enum class SystemMessageType : u32 { + TRC_EMPTY_STORE = 0, + TRC_PSN_CHAT_RESTRICTION = 1, + TRC_PSN_UGC_RESTRICTION = 2, + CAMERA_NOT_CONNECTED = 4, + WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED = 5, +}; + +enum class OrbisMsgDialogProgressBarTarget : u32 { + DEFAULT = 0, +}; + +struct ButtonsParam { + const char* msg1{}; + const char* msg2{}; + std::array reserved{}; +}; + +struct UserMessageParam { + ButtonType buttonType{}; + s32 : 32; + const char* msg{}; + ButtonsParam* buttonsParam{}; + std::array reserved{}; +}; + +struct ProgressBarParam { + ProgressBarType barType{}; + s32 : 32; + const char* msg{}; + std::array reserved{}; +}; + +struct SystemMessageParam { + SystemMessageType sysMsgType{}; + std::array reserved{}; +}; + +struct OrbisParam { + CommonDialog::BaseParam baseParam; + std::size_t size; + MsgDialogMode mode; + s32 : 32; + UserMessageParam* userMsgParam; + ProgressBarParam* progBarParam; + SystemMessageParam* sysMsgParam; + OrbisUserServiceUserId userId; + std::array reserved; + s32 : 32; +}; + +struct DialogResult { + FixedValue mode{}; + CommonDialog::Result result{CommonDialog::Result::OK}; + ButtonId buttonId{ButtonId::INVALID}; + std::array reserved{}; +}; + +// State is used to copy all the data from the param struct +class MsgDialogState { +public: + struct UserState { + ButtonType type{}; + std::string msg{}; + std::string btn_param1{}; + std::string btn_param2{}; + }; + struct ProgressState { + ProgressBarType type{}; + std::string msg{}; + u32 progress{}; + }; + struct SystemState { + SystemMessageType type{}; + }; + +private: + OrbisUserServiceUserId user_id{}; + MsgDialogMode mode{}; + std::variant state{std::monostate{}}; + +public: + explicit MsgDialogState(const OrbisParam& param); + + explicit MsgDialogState(UserState mode); + explicit MsgDialogState(ProgressState mode); + explicit MsgDialogState(SystemState mode); + + MsgDialogState() = default; + + [[nodiscard]] OrbisUserServiceUserId GetUserId() const { + return user_id; + } + + [[nodiscard]] MsgDialogMode GetMode() const { + return mode; + } + + template + [[nodiscard]] T& GetState() { + return std::get(state); + } +}; + +class MsgDialogUi final : public ImGui::Layer { + bool first_render{false}; + MsgDialogState* state{}; + CommonDialog::Status* status{}; + DialogResult* result{}; + + void DrawUser(); + void DrawProgressBar(); + void DrawSystemMessage(); + +public: + explicit MsgDialogUi(MsgDialogState* state = nullptr, CommonDialog::Status* status = nullptr, + DialogResult* result = nullptr); + ~MsgDialogUi() override; + MsgDialogUi(const MsgDialogUi& other) = delete; + MsgDialogUi(MsgDialogUi&& other) noexcept; + MsgDialogUi& operator=(MsgDialogUi other); + + void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK); + + void Draw() override; +}; + +// Utility function to show a message dialog +// !!! This function can block !!! +DialogResult ShowMsgDialog(MsgDialogState state, bool block = true); + +}; // namespace Libraries::MsgDialog \ No newline at end of file diff --git a/src/core/libraries/system/savedatadialog.cpp b/src/core/libraries/system/savedatadialog.cpp deleted file mode 100644 index d842fd11a..000000000 --- a/src/core/libraries/system/savedatadialog.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/libraries/error_codes.h" -#include "core/libraries/libs.h" -#include "core/libraries/system/savedatadialog.h" - -namespace Libraries::SaveDataDialog { - -int PS4_SYSV_ABI sceSaveDataDialogClose() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogGetResult() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogGetStatus() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogInitialize() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogIsReadyToDisplay() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogOpen() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogProgressBarInc() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogProgressBarSetValue() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogTerminate() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return ORBIS_OK; -} - -int PS4_SYSV_ABI sceSaveDataDialogUpdateStatus() { - LOG_ERROR(Lib_SaveDataDialog, "(STUBBED) called"); - return 3; // SCE_COMMON_DIALOG_STATUS_FINISHED -} - -void RegisterlibSceSaveDataDialog(Core::Loader::SymbolsResolver* sym) { - LIB_FUNCTION("fH46Lag88XY", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogClose); - LIB_FUNCTION("yEiJ-qqr6Cg", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogGetResult); - LIB_FUNCTION("ERKzksauAJA", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogGetStatus); - LIB_FUNCTION("s9e3+YpRnzw", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogInitialize); - LIB_FUNCTION("en7gNVnh878", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogIsReadyToDisplay); - LIB_FUNCTION("4tPhsP6FpDI", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogOpen); - LIB_FUNCTION("V-uEeFKARJU", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogProgressBarInc); - LIB_FUNCTION("hay1CfTmLyA", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogProgressBarSetValue); - LIB_FUNCTION("YuH2FA7azqQ", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogTerminate); - LIB_FUNCTION("KK3Bdg1RWK0", "libSceSaveDataDialog", 1, "libSceSaveDataDialog", 1, 1, - sceSaveDataDialogUpdateStatus); -}; - -} // namespace Libraries::SaveDataDialog diff --git a/src/core/libraries/system/savedatadialog.h b/src/core/libraries/system/savedatadialog.h deleted file mode 100644 index e8fe7c75f..000000000 --- a/src/core/libraries/system/savedatadialog.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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::SaveDataDialog { - -int PS4_SYSV_ABI sceSaveDataDialogClose(); -int PS4_SYSV_ABI sceSaveDataDialogGetResult(); -int PS4_SYSV_ABI sceSaveDataDialogGetStatus(); -int PS4_SYSV_ABI sceSaveDataDialogInitialize(); -int PS4_SYSV_ABI sceSaveDataDialogIsReadyToDisplay(); -int PS4_SYSV_ABI sceSaveDataDialogOpen(); -int PS4_SYSV_ABI sceSaveDataDialogProgressBarInc(); -int PS4_SYSV_ABI sceSaveDataDialogProgressBarSetValue(); -int PS4_SYSV_ABI sceSaveDataDialogTerminate(); -int PS4_SYSV_ABI sceSaveDataDialogUpdateStatus(); - -void RegisterlibSceSaveDataDialog(Core::Loader::SymbolsResolver* sym); -} // namespace Libraries::SaveDataDialog diff --git a/src/core/libraries/system/systemservice.cpp b/src/core/libraries/system/systemservice.cpp index d99ec7c7c..9c6fe8f2e 100644 --- a/src/core/libraries/system/systemservice.cpp +++ b/src/core/libraries/system/systemservice.cpp @@ -1717,7 +1717,7 @@ int PS4_SYSV_ABI sceSystemServiceGetAppType() { s32 PS4_SYSV_ABI sceSystemServiceGetDisplaySafeAreaInfo(OrbisSystemServiceDisplaySafeAreaInfo* info) { - LOG_INFO(Lib_SystemService, "called"); + LOG_DEBUG(Lib_SystemService, "called"); if (info == nullptr) { LOG_ERROR(Lib_SystemService, "OrbisSystemServiceDisplaySafeAreaInfo is null"); return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER; @@ -1942,9 +1942,12 @@ int PS4_SYSV_ABI sceSystemServiceRaiseExceptionLocalProcess() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSystemServiceReceiveEvent() { - LOG_ERROR(Lib_SystemService, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceSystemServiceReceiveEvent(OrbisSystemServiceEvent* event) { + LOG_ERROR(Lib_SystemService, "(STUBBED) called, event type = {:#x}", (int)event->eventType); + if (event == nullptr) { + return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER; + } + return ORBIS_SYSTEM_SERVICE_ERROR_NO_EVENT; } int PS4_SYSV_ABI sceSystemServiceReenableMusicPlayer() { diff --git a/src/core/libraries/system/systemservice.h b/src/core/libraries/system/systemservice.h index 1976606a8..56583c97e 100644 --- a/src/core/libraries/system/systemservice.h +++ b/src/core/libraries/system/systemservice.h @@ -87,6 +87,32 @@ enum OrbisSystemParamLanguage { ORBIS_SYSTEM_PARAM_LANG_INDONESIAN = 29 }; +enum OrbisSystemServiceEventType { + ORBIS_SYSTEM_SERVICE_EVENT_INVALID = -1, + ORBIS_SYSTEM_SERVICE_EVENT_ON_RESUME = 0x10000000, + ORBIS_SYSTEM_SERVICE_EVENT_GAME_LIVE_STREAMING_STATUS_UPDATE = 0x10000001, + ORBIS_SYSTEM_SERVICE_EVENT_SESSION_INVITATION = 0x10000002, + ORBIS_SYSTEM_SERVICE_EVENT_ENTITLEMENT_UPDATE = 0x10000003, + ORBIS_SYSTEM_SERVICE_EVENT_GAME_CUSTOM_DATA = 0x10000004, + ORBIS_SYSTEM_SERVICE_EVENT_DISPLAY_SAFE_AREA_UPDATE = 0x10000005, + ORBIS_SYSTEM_SERVICE_EVENT_URL_OPEN = 0x10000006, + ORBIS_SYSTEM_SERVICE_EVENT_LAUNCH_APP = 0x10000007, + ORBIS_SYSTEM_SERVICE_EVENT_APP_LAUNCH_LINK = 0x10000008, + ORBIS_SYSTEM_SERVICE_EVENT_ADDCONTENT_INSTALL = 0x10000009, + ORBIS_SYSTEM_SERVICE_EVENT_RESET_VR_POSITION = 0x1000000a, + ORBIS_SYSTEM_SERVICE_EVENT_JOIN_EVENT = 0x1000000b, + ORBIS_SYSTEM_SERVICE_EVENT_PLAYGO_LOCUS_UPDATE = 0x1000000c, + ORBIS_SYSTEM_SERVICE_EVENT_PLAY_TOGETHER_HOST = 0x1000000d, + ORBIS_SYSTEM_SERVICE_EVENT_SERVICE_ENTITLEMENT_UPDATE = 0x1000000e, + ORBIS_SYSTEM_SERVICE_EVENT_EYE_TO_EYE_DISTANCE_UPDATE = 0x1000000f, + ORBIS_SYSTEM_SERVICE_EVENT_JOIN_MATCH_EVENT = 0x10000010, + ORBIS_SYSTEM_SERVICE_EVENT_PLAY_TOGETHER_HOST_A = 0x10000011, + ORBIS_SYSTEM_SERVICE_EVENT_WEBBROWSER_CLOSED = 0x10000012, + ORBIS_SYSTEM_SERVICE_EVENT_CONTROLLER_SETTINGS_CLOSED = 0x10000013, + ORBIS_SYSTEM_SERVICE_EVENT_JOIN_TEAM_ON_TEAM_MATCH_EVENT = 0x10000014, + ORBIS_SYSTEM_SERVICE_EVENT_OPEN_SHARE_MENU = 0x30000000 +}; + struct OrbisSystemServiceStatus { s32 eventNum; bool isSystemUiOverlaid; @@ -102,6 +128,41 @@ struct OrbisSystemServiceDisplaySafeAreaInfo { uint8_t reserved[128]; }; +struct OrbisSystemServiceEvent { + OrbisSystemServiceEventType eventType; + union { + char param[8192]; + struct { + char source[1024]; + char url[4096]; + } urlOpen; + struct { + u32 size; + u8 arg[8188]; + } launchApp; + struct { + u32 size; + u8 arg[2020]; + } appLaunchLink; + struct { + s32 userId; + char eventId[37]; + char bootArgument[7169]; + } joinEvent; + struct { + s32 userId; + u32 npServiceLabel; + u8 reserved[8184]; + } serviceEntitlementUpdate; + struct { + s32 userId; + u32 npServiceLabel; + u8 reserved[8184]; + } unifiedEntitlementUpdate; + u8 reserved[8192]; + }; +}; + bool IsSplashVisible(); int PS4_SYSV_ABI sceAppMessagingClearEventFlag(); @@ -480,7 +541,7 @@ s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(int param_id, int* value); int PS4_SYSV_ABI sceSystemServiceParamGetString(); int PS4_SYSV_ABI sceSystemServicePowerTick(); int PS4_SYSV_ABI sceSystemServiceRaiseExceptionLocalProcess(); -int PS4_SYSV_ABI sceSystemServiceReceiveEvent(); +s32 PS4_SYSV_ABI sceSystemServiceReceiveEvent(OrbisSystemServiceEvent* event); int PS4_SYSV_ABI sceSystemServiceReenableMusicPlayer(); int PS4_SYSV_ABI sceSystemServiceRegisterDaemon(); int PS4_SYSV_ABI sceSystemServiceReleaseFb0(); diff --git a/src/core/libraries/system/userservice.cpp b/src/core/libraries/system/userservice.cpp index 8c48b3111..140ca8921 100644 --- a/src/core/libraries/system/userservice.cpp +++ b/src/core/libraries/system/userservice.cpp @@ -1,7 +1,9 @@ // 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 "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/system/userservice.h" @@ -489,7 +491,7 @@ int PS4_SYSV_ABI sceUserServiceGetImeRunCount() { } s32 PS4_SYSV_ABI sceUserServiceGetInitialUser(int* user_id) { - LOG_INFO(Lib_UserService, "called"); + LOG_DEBUG(Lib_UserService, "called"); if (user_id == nullptr) { LOG_ERROR(Lib_UserService, "user_id is null"); return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT; @@ -565,7 +567,7 @@ int PS4_SYSV_ABI sceUserServiceGetLoginFlag() { } s32 PS4_SYSV_ABI sceUserServiceGetLoginUserIdList(OrbisUserServiceLoginUserIdList* userIdList) { - LOG_INFO(Lib_UserService, "called"); + LOG_DEBUG(Lib_UserService, "called"); if (userIdList == nullptr) { LOG_ERROR(Lib_UserService, "user_id is null"); return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT; @@ -1071,7 +1073,7 @@ s32 PS4_SYSV_ABI sceUserServiceGetUserName(int user_id, char* user_name, std::si LOG_ERROR(Lib_UserService, "user_name is null"); return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT; } - std::string name = "shadps4"; // TODO onfigurable username + std::string name = Config::getUserName(); if (size < name.length()) { LOG_ERROR(Lib_UserService, "buffer is too short"); return ORBIS_USER_SERVICE_ERROR_BUFFER_TOO_SHORT; diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index 2a1f6028a..c0e1b7ea8 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// Generated By moduleGenerator #include "common/logging/log.h" #include "common/singleton.h" #include "core/libraries/error_codes.h" diff --git a/src/core/libraries/usbd/usbd.h b/src/core/libraries/usbd/usbd.h index 6aad31ebc..4ed153587 100644 --- a/src/core/libraries/usbd/usbd.h +++ b/src/core/libraries/usbd/usbd.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once + #include "common/types.h" namespace Core::Loader { diff --git a/src/core/libraries/videoout/buffer.h b/src/core/libraries/videoout/buffer.h index 8f49be591..08552bddb 100644 --- a/src/core/libraries/videoout/buffer.h +++ b/src/core/libraries/videoout/buffer.h @@ -4,6 +4,7 @@ #pragma once #include + #include "common/assert.h" #include "common/types.h" diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 25de48a4d..e2fd00028 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -1,11 +1,14 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include + #include "common/assert.h" #include "common/config.h" #include "common/debug.h" #include "common/thread.h" +#include "core/debug_state.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/time_management.h" #include "core/libraries/videoout/driver.h" @@ -96,7 +99,7 @@ int VideoOutDriver::RegisterBuffers(VideoOutPort* port, s32 startIndex, void* co } if (attribute->reserved0 != 0 || attribute->reserved1 != 0) { - LOG_ERROR(Lib_VideoOut, "Invalid reserved memebers"); + LOG_ERROR(Lib_VideoOut, "Invalid reserved members"); return ORBIS_VIDEO_OUT_ERROR_INVALID_VALUE; } if (attribute->aspect_ratio != 0) { @@ -159,13 +162,7 @@ int VideoOutDriver::UnregisterBuffers(VideoOutPort* port, s32 attributeIndex) { return ORBIS_OK; } -std::chrono::microseconds VideoOutDriver::Flip(const Request& req) { - if (!req) { - return std::chrono::microseconds{0}; - } - - const auto start = std::chrono::high_resolution_clock::now(); - +void VideoOutDriver::Flip(const Request& req) { // Whatever the game is rendering show splash if it is active if (!renderer->ShowSplash(req.frame)) { // Present the frame. @@ -201,9 +198,11 @@ std::chrono::microseconds VideoOutDriver::Flip(const Request& req) { port->buffer_labels[req.index] = 0; port->SignalVoLabel(); } +} - const auto end = std::chrono::high_resolution_clock::now(); - return std::chrono::duration_cast(end - start); +void VideoOutDriver::DrawBlankFrame() { + const auto empty_frame = renderer->PrepareBlankFrame(false); + renderer->Present(empty_frame); } bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, @@ -252,15 +251,20 @@ void VideoOutDriver::SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_ requests.push({ .frame = frame, .port = port, - .index = index, .flip_arg = flip_arg, + .index = index, .eop = is_eop, }); } void VideoOutDriver::PresentThread(std::stop_token token) { - static constexpr std::chrono::milliseconds VblankPeriod{16}; - Common::SetCurrentThreadName("PresentThread"); + static constexpr std::chrono::nanoseconds VblankPeriod{16666667}; + const auto vblank_period = VblankPeriod / Config::vblankDiv(); + + Common::SetCurrentThreadName("shadPS4:PresentThread"); + Common::SetCurrentThreadRealtime(vblank_period); + + Common::AccurateTimer timer{vblank_period}; const auto receive_request = [this] -> Request { std::scoped_lock lk{mutex}; @@ -272,18 +276,22 @@ void VideoOutDriver::PresentThread(std::stop_token token) { return {}; }; - auto vblank_period = VblankPeriod / Config::vblankDiv(); auto delay = std::chrono::microseconds{0}; while (!token.stop_requested()) { - // Sleep for most of the vblank duration. - std::this_thread::sleep_for(vblank_period - delay); + timer.Start(); // Check if it's time to take a request. auto& vblank_status = main_port.vblank_status; if (vblank_status.count % (main_port.flip_rate + 1) == 0) { const auto request = receive_request(); - delay = Flip(request); - FRAME_END; + if (!request) { + if (!main_port.is_open || DebugState.IsGuestThreadsPaused()) { + DrawBlankFrame(); + } + } else { + Flip(request); + FRAME_END; + } } { @@ -302,6 +310,8 @@ void VideoOutDriver::PresentThread(std::stop_token token) { Kernel::SceKernelEvent::Filter::VideoOut, nullptr); } } + + timer.End(); } } diff --git a/src/core/libraries/videoout/driver.h b/src/core/libraries/videoout/driver.h index bee800602..2e478b9ee 100644 --- a/src/core/libraries/videoout/driver.h +++ b/src/core/libraries/videoout/driver.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -92,8 +92,8 @@ private: struct Request { Vulkan::Frame* frame; VideoOutPort* port; - s32 index; s64 flip_arg; + s32 index; bool eop; operator bool() const noexcept { @@ -101,7 +101,8 @@ private: } }; - std::chrono::microseconds Flip(const Request& req); + void Flip(const Request& req); + void DrawBlankFrame(); // Used when there is no flip request to keep ImGui up to date void SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false); void PresentThread(std::stop_token token); diff --git a/src/core/libraries/videoout/video_out.cpp b/src/core/libraries/videoout/video_out.cpp index d13062cd4..631f77732 100644 --- a/src/core/libraries/videoout/video_out.cpp +++ b/src/core/libraries/videoout/video_out.cpp @@ -140,8 +140,8 @@ s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode return ORBIS_VIDEO_OUT_ERROR_INVALID_INDEX; } - LOG_INFO(Lib_VideoOut, "bufferIndex = {}, flipMode = {}, flipArg = {}", bufferIndex, flipMode, - flipArg); + LOG_DEBUG(Lib_VideoOut, "bufferIndex = {}, flipMode = {}, flipArg = {}", bufferIndex, flipMode, + flipArg); if (!driver->SubmitFlip(port, bufferIndex, flipArg)) { LOG_ERROR(Lib_VideoOut, "Flip queue is full"); @@ -185,14 +185,16 @@ s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status) { return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE; } - std::unique_lock lock{port->port_mutex}; - *status = port->flip_status; + { + std::unique_lock lock{port->port_mutex}; + *status = port->flip_status; + } - LOG_INFO(Lib_VideoOut, - "count = {}, processTime = {}, tsc = {}, submitTsc = {}, flipArg = {}, gcQueueNum = " - "{}, flipPendingNum = {}, currentBuffer = {}", - status->count, status->processTime, status->tsc, status->submitTsc, status->flipArg, - status->gcQueueNum, status->flipPendingNum, status->currentBuffer); + LOG_TRACE(Lib_VideoOut, + "count = {}, processTime = {}, tsc = {}, submitTsc = {}, flipArg = {}, gcQueueNum = " + "{}, flipPendingNum = {}, currentBuffer = {}", + status->count, status->processTime, status->tsc, status->submitTsc, status->flipArg, + status->gcQueueNum, status->flipPendingNum, status->currentBuffer); return ORBIS_OK; } diff --git a/src/core/linker.cpp b/src/core/linker.cpp index d4a15825b..2d7865c33 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/alignment.h" +#include "common/arch.h" #include "common/assert.h" #include "common/config.h" #include "common/logging/log.h" @@ -10,12 +11,14 @@ #include "common/thread.h" #include "core/aerolib/aerolib.h" #include "core/aerolib/stubs.h" +#include "core/cpu_patches.h" #include "core/libraries/kernel/memory_management.h" #include "core/libraries/kernel/thread_management.h" #include "core/linker.h" #include "core/memory.h" #include "core/tls.h" #include "core/virtual_memory.h" +#include "debug_state.h" namespace Core { @@ -25,7 +28,8 @@ static PS4_SYSV_ABI void ProgramExitFunc() { fmt::print("exit function called\n"); } -static void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc exit_func) { +#ifdef ARCH_X86_64 +static PS4_SYSV_ABI void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc exit_func) { // reinterpret_cast(addr)(params, exit_func); // can't be used, stack has to have // a specific layout asm volatile("andq $-16, %%rsp\n" // Align to 16 bytes @@ -46,6 +50,7 @@ static void RunMainEntry(VAddr addr, EntryParams* params, ExitFunc exit_func) { : "r"(addr), "r"(params), "r"(exit_func) : "rax", "rsi", "rdi"); } +#endif Linker::Linker() : memory{Memory::Instance()} {} @@ -68,16 +73,25 @@ void Linker::Execute() { } // Configure used flexible memory size. - // if (auto* mem_param = GetProcParam()->mem_param) { - // if (u64* flexible_size = mem_param->flexible_memory_size) { - // memory->SetTotalFlexibleSize(*flexible_size); - // } - // } + if (const auto* proc_param = GetProcParam()) { + if (proc_param->size >= + offsetof(OrbisProcParam, mem_param) + sizeof(OrbisKernelMemParam*)) { + if (const auto* mem_param = proc_param->mem_param) { + if (mem_param->size >= + offsetof(OrbisKernelMemParam, flexible_memory_size) + sizeof(u64*)) { + if (const auto* flexible_size = mem_param->flexible_memory_size) { + memory->SetupMemoryRegions(*flexible_size); + } + } + } + } + } // Init primary thread. Common::SetCurrentThreadName("GAME_MainThread"); + DebugState.AddCurrentThreadToGuestList(); Libraries::Kernel::pthreadInitSelfMainThread(); - InitTlsForThread(true); + EnsureThreadInitialized(true); // Start shared library modules for (auto& m : m_modules) { @@ -93,9 +107,16 @@ void Linker::Execute() { for (auto& m : m_modules) { if (!m->IsSharedLib()) { - RunMainEntry(m->GetEntryAddress(), &p, ProgramExitFunc); +#ifdef ARCH_X86_64 + ExecuteGuest(RunMainEntry, m->GetEntryAddress(), &p, ProgramExitFunc); +#else + UNIMPLEMENTED_MSG( + "Missing guest entrypoint implementation for target CPU architecture."); +#endif } } + + SetTcbBase(nullptr); } s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { @@ -168,7 +189,7 @@ void Linker::Relocate(Module* module) { auto sym_bind = sym.GetBind(); auto sym_type = sym.GetType(); auto sym_visibility = sym.GetVisibility(); - u64 symbol_vitrual_addr = 0; + u64 symbol_virtual_addr = 0; Loader::SymbolRecord symrec{}; switch (sym_type) { case STT_FUN: @@ -185,12 +206,12 @@ void Linker::Relocate(Module* module) { } if (sym_visibility != 0) { - LOG_INFO(Core_Linker, "symbol visilibity !=0"); + LOG_INFO(Core_Linker, "symbol visibility !=0"); } switch (sym_bind) { case STB_LOCAL: - symbol_vitrual_addr = rel_base_virtual_addr + sym.st_value; + symbol_virtual_addr = rel_base_virtual_addr + sym.st_value; module->SetRelaBit(bit_idx); break; case STB_GLOBAL: @@ -200,14 +221,14 @@ void Linker::Relocate(Module* module) { // Only set the rela bit if the symbol was actually resolved and not stubbed. module->SetRelaBit(bit_idx); } - symbol_vitrual_addr = symrec.virtual_address; + symbol_virtual_addr = symrec.virtual_address; break; } default: ASSERT_MSG(0, "unknown bind type {}", sym_bind); } - rel_is_resolved = (symbol_vitrual_addr != 0); - rel_value = (rel_is_resolved ? symbol_vitrual_addr + addend : 0); + rel_is_resolved = (symbol_virtual_addr != 0); + rel_value = (rel_is_resolved ? symbol_virtual_addr + addend : 0); rel_name = symrec.name; break; } @@ -306,7 +327,8 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) { Module* module = m_modules[module_index - 1].get(); const u32 init_image_size = module->tls.init_image_size; // TODO: Determine if Windows will crash from this - u8* dest = reinterpret_cast(heap_api->heap_malloc(module->tls.image_size)); + u8* dest = + reinterpret_cast(ExecuteGuest(heap_api->heap_malloc, module->tls.image_size)); const u8* src = reinterpret_cast(module->tls.image_virtual_addr); std::memcpy(dest, src, init_image_size); std::memset(dest + init_image_size, 0, module->tls.image_size - init_image_size); @@ -316,7 +338,18 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) { return addr + offset; } -void Linker::InitTlsForThread(bool is_primary) { +thread_local std::once_flag init_tls_flag; + +void Linker::EnsureThreadInitialized(bool is_primary) const { + std::call_once(init_tls_flag, [this, is_primary] { +#ifdef ARCH_X86_64 + InitializeThreadPatchStack(); +#endif + InitTlsForThread(is_primary); + }); +} + +void Linker::InitTlsForThread(bool is_primary) const { static constexpr size_t TcbSize = 0x40; static constexpr size_t TlsAllocAlign = 0x20; const size_t total_tls_size = Common::AlignUp(static_tls_size, TlsAllocAlign) + TcbSize; @@ -338,7 +371,7 @@ void Linker::InitTlsForThread(bool is_primary) { } else { if (heap_api) { #ifndef WIN32 - addr_out = heap_api->heap_malloc(total_tls_size); + addr_out = ExecuteGuestWithoutTls(heap_api->heap_malloc, total_tls_size); } else { addr_out = std::malloc(total_tls_size); #else diff --git a/src/core/linker.h b/src/core/linker.h index ed1fe400c..fe1278d00 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -98,7 +98,6 @@ public: } void* TlsGetAddr(u64 module_index, u64 offset); - void InitTlsForThread(bool is_primary = false); s32 LoadModule(const std::filesystem::path& elf_name, bool is_dynamic = false); Module* FindByAddress(VAddr address); @@ -109,8 +108,24 @@ public: void Execute(); void DebugDump(); + template + ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), + CallArgs&&... args) const { + // Make sure TLS is initialized for the thread before entering guest. + EnsureThreadInitialized(); + return ExecuteGuestWithoutTls(func, args...); + } + private: const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l); + void EnsureThreadInitialized(bool is_primary = false) const; + void InitTlsForThread(bool is_primary) const; + + template + ReturnType ExecuteGuestWithoutTls(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), + CallArgs&&... args) const { + return func(std::forward(args)...); + } MemoryManager* memory; std::mutex mutex; diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 6d7c8773a..4de20436f 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -204,7 +204,10 @@ void Elf::Open(const std::filesystem::path& file_name) { } out.resize(num); - m_f.Seek(offset, SeekOrigin::SetOrigin); + if (!m_f.Seek(offset, SeekOrigin::SetOrigin)) { + LOG_CRITICAL(Loader, "Failed to seek to header tables"); + return; + } m_f.Read(out); }; @@ -465,7 +468,10 @@ std::string Elf::ElfPHeaderStr(u16 no) { void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) { if (!is_self) { // It's elf file - m_f.Seek(file_offset, SeekOrigin::SetOrigin); + if (!m_f.Seek(file_offset, SeekOrigin::SetOrigin)) { + LOG_CRITICAL(Loader, "Failed to seek to ELF header"); + return; + } m_f.ReadRaw(reinterpret_cast(virtual_addr), size); return; } @@ -479,7 +485,10 @@ void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) { if (file_offset >= phdr.p_offset && file_offset < phdr.p_offset + phdr.p_filesz) { auto offset = file_offset - phdr.p_offset; - m_f.Seek(offset + seg.file_offset, SeekOrigin::SetOrigin); + if (!m_f.Seek(offset + seg.file_offset, SeekOrigin::SetOrigin)) { + LOG_CRITICAL(Loader, "Failed to seek to segment"); + return; + } m_f.ReadRaw(reinterpret_cast(virtual_addr), size); return; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index b7db15d13..471ba5856 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -3,17 +3,21 @@ #include "common/alignment.h" #include "common/assert.h" +#include "common/config.h" #include "common/debug.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/memory_management.h" #include "core/memory.h" +#include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" namespace Core { +constexpr u64 SCE_DEFAULT_FLEXIBLE_MEMORY_SIZE = 448_MB; + MemoryManager::MemoryManager() { - // Insert an area that covers direct memory physical block. - dmem_map.emplace(0, DirectMemoryArea{0, SCE_KERNEL_MAIN_DMEM_SIZE}); + // Set up the direct and flexible memory regions. + SetupMemoryRegions(SCE_DEFAULT_FLEXIBLE_MEMORY_SIZE); // Insert a virtual memory area that covers the entire area we manage. const VAddr system_managed_base = impl.SystemManagedVirtualBase(); @@ -35,6 +39,50 @@ 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; + total_direct_size = total_size - flexible_size; + + // Insert an area that covers direct memory physical block. + // Note that this should never be called after direct memory allocations have been made. + dmem_map.clear(); + dmem_map.emplace(0, DirectMemoryArea{0, total_direct_size}); + + LOG_INFO(Kernel_Vmm, "Configured memory regions: flexible size = {:#x}, direct size = {:#x}", + total_flexible_size, total_direct_size); +} + +PAddr MemoryManager::PoolExpand(PAddr search_start, PAddr search_end, size_t size, u64 alignment) { + std::scoped_lock lk{mutex}; + + auto dmem_area = FindDmemArea(search_start); + + const auto is_suitable = [&] { + const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) + : dmem_area->second.base; + const auto alignment_size = aligned_base - dmem_area->second.base; + const auto remaining_size = + dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; + return dmem_area->second.is_free && remaining_size >= size; + }; + while (!is_suitable() && dmem_area->second.GetEnd() <= search_end) { + dmem_area++; + } + ASSERT_MSG(is_suitable(), "Unable to find free direct memory area: size = {:#x}", size); + + // Align free position + PAddr free_addr = dmem_area->second.base; + free_addr = alignment > 0 ? Common::AlignUp(free_addr, alignment) : free_addr; + + // Add the allocated region to the list and commit its pages. + auto& area = CarveDmemArea(free_addr, size)->second; + area.is_free = false; + area.is_pooled = true; + return free_addr; +} + PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, int memory_type) { std::scoped_lock lk{mutex}; @@ -42,12 +90,17 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, auto dmem_area = FindDmemArea(search_start); const auto is_suitable = [&] { - return dmem_area->second.is_free && dmem_area->second.size >= size; + const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) + : dmem_area->second.base; + const auto alignment_size = aligned_base - dmem_area->second.base; + const auto remaining_size = + dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; + return dmem_area->second.is_free && remaining_size >= size; }; while (!is_suitable() && dmem_area->second.GetEnd() <= search_end) { ++dmem_area; } - ASSERT_MSG(is_suitable(), "Unable to find free direct memory area"); + ASSERT_MSG(is_suitable(), "Unable to find free direct memory area: size = {:#x}", size); // Align free position PAddr free_addr = dmem_area->second.base; @@ -81,7 +134,7 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) { } } for (const auto& [addr, size] : remove_list) { - UnmapMemory(addr, size); + UnmapMemoryImpl(addr, size); } // Mark region as free and attempt to coalesce it with neighbours. @@ -91,6 +144,43 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) { MergeAdjacent(dmem_map, dmem_area); } +int MemoryManager::PoolReserve(void** out_addr, VAddr virtual_addr, size_t size, + MemoryMapFlags flags, u64 alignment) { + std::scoped_lock lk{mutex}; + + virtual_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; + alignment = alignment > 0 ? alignment : 2_MB; + VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr; + + // Fixed mapping means the virtual address must exactly match the provided one. + if (True(flags & MemoryMapFlags::Fixed)) { + const auto& vma = FindVMA(mapped_addr)->second; + // If the VMA is mapped, unmap the region first. + if (vma.IsMapped()) { + UnmapMemoryImpl(mapped_addr, size); + } + const size_t remaining_size = vma.base + vma.size - mapped_addr; + ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size); + } + + // Find the first free area starting with provided virtual address. + if (False(flags & MemoryMapFlags::Fixed)) { + mapped_addr = SearchFree(mapped_addr, size, alignment); + } + + // Add virtual memory area + const auto new_vma_handle = CarveVMA(mapped_addr, size); + auto& new_vma = new_vma_handle->second; + new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce); + new_vma.prot = MemoryProt::NoAccess; + new_vma.name = ""; + new_vma.type = VMAType::PoolReserved; + MergeAdjacent(vma_map, new_vma_handle); + + *out_addr = std::bit_cast(mapped_addr); + return ORBIS_OK; +} + int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, MemoryMapFlags flags, u64 alignment) { std::scoped_lock lk{mutex}; @@ -104,7 +194,7 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem const auto& vma = FindVMA(mapped_addr)->second; // If the VMA is mapped, unmap the region first. if (vma.IsMapped()) { - UnmapMemory(mapped_addr, size); + UnmapMemoryImpl(mapped_addr, size); } const size_t remaining_size = vma.base + vma.size - mapped_addr; ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size); @@ -128,6 +218,37 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem return ORBIS_OK; } +int MemoryManager::PoolCommit(VAddr virtual_addr, size_t size, MemoryProt prot) { + std::scoped_lock lk{mutex}; + + const u64 alignment = 64_KB; + + // When virtual addr is zero, force it to virtual_base. The guest cannot pass Fixed + // flag so we will take the branch that searches for free (or reserved) mappings. + virtual_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; + VAddr mapped_addr = Common::AlignUp(virtual_addr, alignment); + + // This should return SCE_KERNEL_ERROR_ENOMEM but shouldn't normally happen. + const auto& vma = FindVMA(mapped_addr)->second; + const size_t remaining_size = vma.base + vma.size - mapped_addr; + ASSERT_MSG(!vma.IsMapped() && remaining_size >= size); + + // Perform the mapping. + void* out_addr = impl.Map(mapped_addr, size, alignment, -1, false); + TRACK_ALLOC(out_addr, size, "VMEM"); + + auto& new_vma = CarveVMA(mapped_addr, size)->second; + new_vma.disallow_merge = false; + new_vma.prot = prot; + new_vma.name = ""; + new_vma.type = Core::VMAType::Pooled; + new_vma.is_exec = false; + new_vma.phys_base = 0; + + rasterizer->MapMemory(mapped_addr, size); + return ORBIS_OK; +} + int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, VMAType type, std::string_view name, bool is_exec, PAddr phys_addr, u64 alignment) { @@ -211,9 +332,45 @@ int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, Mem return ORBIS_OK; } -void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { +void MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { std::scoped_lock lk{mutex}; + const auto it = FindVMA(virtual_addr); + const auto& vma_base = it->second; + ASSERT_MSG(vma_base.Contains(virtual_addr, size), + "Existing mapping does not contain requested unmap range"); + + 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; + + rasterizer->UnmapMemory(virtual_addr, size); + + // Mark region as free and attempt to coalesce it with neighbours. + const auto new_it = CarveVMA(virtual_addr, size); + auto& vma = new_it->second; + vma.type = VMAType::PoolReserved; + vma.prot = MemoryProt::NoAccess; + vma.phys_base = 0; + vma.disallow_merge = false; + vma.name = ""; + MergeAdjacent(vma_map, new_it); + + // Unmap the memory region. + impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base, is_exec, + false, false); + TRACK_FREE(virtual_addr, "VMEM"); +} + +void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { + std::scoped_lock lk{mutex}; + UnmapMemoryImpl(virtual_addr, size); +} + +void MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) { const auto it = FindVMA(virtual_addr); const auto& vma_base = it->second; ASSERT_MSG(vma_base.Contains(virtual_addr, size), @@ -269,6 +426,61 @@ int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr return ORBIS_OK; } +int MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) { + std::scoped_lock lk{mutex}; + + // Find the virtual memory area that contains the specified address range. + auto it = FindVMA(addr); + if (it == vma_map.end() || !it->second.Contains(addr, size)) { + LOG_ERROR(Core, "Address range not mapped"); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + VirtualMemoryArea& vma = it->second; + if (vma.type == VMAType::Free) { + LOG_ERROR(Core, "Cannot change protection on free memory region"); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + // Validate protection flags + constexpr static MemoryProt valid_flags = MemoryProt::NoAccess | MemoryProt::CpuRead | + MemoryProt::CpuReadWrite | MemoryProt::GpuRead | + MemoryProt::GpuWrite | MemoryProt::GpuReadWrite; + + MemoryProt invalid_flags = prot & ~valid_flags; + if (u32(invalid_flags) != 0 && u32(invalid_flags) != u32(MemoryProt::NoAccess)) { + LOG_ERROR(Core, "Invalid protection flags: prot = {:#x}, invalid flags = {:#x}", u32(prot), + u32(invalid_flags)); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + // Change protection + vma.prot = prot; + + // Set permissions + Core::MemoryPermission perms{}; + + if (True(prot & MemoryProt::CpuRead)) { + perms |= Core::MemoryPermission::Read; + } + if (True(prot & MemoryProt::CpuReadWrite)) { + perms |= Core::MemoryPermission::ReadWrite; + } + if (True(prot & MemoryProt::GpuRead)) { + perms |= Core::MemoryPermission::Read; + } + if (True(prot & MemoryProt::GpuWrite)) { + perms |= Core::MemoryPermission::Write; + } + if (True(prot & MemoryProt::GpuReadWrite)) { + perms |= Core::MemoryPermission::ReadWrite; + } + + impl.Protect(addr, size, perms); + + return ORBIS_OK; +} + int MemoryManager::VirtualQuery(VAddr addr, int flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info) { std::scoped_lock lk{mutex}; @@ -285,15 +497,20 @@ int MemoryManager::VirtualQuery(VAddr addr, int flags, const auto& vma = it->second; info->start = vma.base; info->end = vma.base + vma.size; + info->offset = vma.phys_base; + info->protection = static_cast(vma.prot); info->is_flexible.Assign(vma.type == VMAType::Flexible); info->is_direct.Assign(vma.type == VMAType::Direct); - info->is_commited.Assign(vma.type != VMAType::Free); + info->is_stack.Assign(vma.type == VMAType::Stack); + info->is_pooled.Assign(vma.type == VMAType::Pooled); + info->is_committed.Assign(vma.type != VMAType::Free && vma.type != VMAType::Reserved); vma.name.copy(info->name.data(), std::min(info->name.size(), vma.name.size())); if (vma.type == VMAType::Direct) { const auto dmem_it = FindDmemArea(vma.phys_base); ASSERT(dmem_it != dmem_map.end()); - info->offset = vma.phys_base; info->memory_type = dmem_it->second.memory_type; + } else { + info->memory_type = ::Libraries::Kernel::SCE_KERNEL_WB_ONION; } return ORBIS_OK; @@ -328,14 +545,24 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si PAddr paddr{}; size_t max_size{}; while (dmem_area != dmem_map.end() && dmem_area->second.GetEnd() <= search_end) { - if (dmem_area->second.size > max_size) { - paddr = dmem_area->second.base; - max_size = dmem_area->second.size; + if (!dmem_area->second.is_free) { + dmem_area++; + continue; + } + + const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) + : dmem_area->second.base; + const auto alignment_size = aligned_base - dmem_area->second.base; + const auto remaining_size = + dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; + if (remaining_size > max_size) { + paddr = aligned_base; + max_size = remaining_size; } dmem_area++; } - *phys_addr_out = alignment > 0 ? Common::AlignUp(paddr, alignment) : paddr; + *phys_addr_out = paddr; *size_out = max_size; return ORBIS_OK; } @@ -344,7 +571,7 @@ void MemoryManager::NameVirtualRange(VAddr virtual_addr, size_t size, std::strin auto it = FindVMA(virtual_addr); ASSERT_MSG(it->second.Contains(virtual_addr, size), - "Range provided is not fully containted in vma"); + "Range provided is not fully contained in vma"); it->second.name = name; } VAddr MemoryManager::SearchFree(VAddr virtual_addr, size_t size, u32 alignment) { @@ -413,7 +640,8 @@ MemoryManager::DMemHandle MemoryManager::CarveDmemArea(PAddr addr, size_t size) const PAddr start_in_area = addr - area.base; const PAddr end_in_vma = start_in_area + size; - ASSERT_MSG(end_in_vma <= area.size, "Mapping cannot fit inside free region"); + ASSERT_MSG(end_in_vma <= area.size, "Mapping cannot fit inside free region: size = {:#x}", + size); if (end_in_vma != area.size) { // Split VMA at the end of the allocated region diff --git a/src/core/memory.h b/src/core/memory.h index d58269678..320aa367a 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -28,8 +28,9 @@ enum class MemoryProt : u32 { CpuReadWrite = 2, GpuRead = 16, GpuWrite = 32, - GpuReadWrite = 38, + GpuReadWrite = 48, }; +DECLARE_ENUM_FLAG_OPERATORS(MemoryProt) enum class MemoryMapFlags : u32 { NoFlags = 0, @@ -49,15 +50,17 @@ enum class VMAType : u32 { Direct = 2, Flexible = 3, Pooled = 4, - Stack = 5, - Code = 6, - File = 7, + PoolReserved = 5, + Stack = 6, + Code = 7, + File = 8, }; struct DirectMemoryArea { PAddr base = 0; size_t size = 0; int memory_type = 0; + bool is_pooled = false; bool is_free = true; PAddr GetEnd() const { @@ -95,7 +98,7 @@ struct VirtualMemoryArea { } bool IsMapped() const noexcept { - return type != VMAType::Free && type != VMAType::Reserved; + return type != VMAType::Free && type != VMAType::Reserved && type != VMAType::PoolReserved; } bool CanMergeWith(const VirtualMemoryArea& next) const { @@ -130,8 +133,12 @@ public: rasterizer = rasterizer_; } - void SetTotalFlexibleSize(u64 size) { - total_flexible_size = size; + u64 GetTotalDirectSize() const { + return total_direct_size; + } + + u64 GetTotalFlexibleSize() const { + return total_flexible_size; } u64 GetAvailableFlexibleSize() const { @@ -142,14 +149,23 @@ public: return impl.SystemReservedVirtualBase(); } + void SetupMemoryRegions(u64 flexible_size); + + PAddr PoolExpand(PAddr search_start, PAddr search_end, size_t size, u64 alignment); + PAddr Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, int memory_type); void Free(PAddr phys_addr, size_t size); + int PoolReserve(void** out_addr, VAddr virtual_addr, size_t size, MemoryMapFlags flags, + u64 alignment = 0); + int Reserve(void** out_addr, VAddr virtual_addr, size_t size, MemoryMapFlags flags, u64 alignment = 0); + int PoolCommit(VAddr virtual_addr, size_t size, MemoryProt prot); + int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, VMAType type, std::string_view name = "", bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0); @@ -157,13 +173,18 @@ public: int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset); + void PoolDecommit(VAddr virtual_addr, size_t size); + void UnmapMemory(VAddr virtual_addr, size_t size); int QueryProtection(VAddr addr, void** start, void** end, u32* prot); - int VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info); + int Protect(VAddr addr, size_t size, MemoryProt prot); - int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info); + int VirtualQuery(VAddr addr, int flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info); + + int DirectMemoryQuery(PAddr addr, bool find_next, + ::Libraries::Kernel::OrbisQueryInfo* out_info); int DirectQueryAvailable(PAddr search_start, PAddr search_end, size_t alignment, PAddr* phys_addr_out, size_t* size_out); @@ -212,12 +233,15 @@ private: DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area); + void UnmapMemoryImpl(VAddr virtual_addr, size_t size); + private: AddressSpace impl; DMemMap dmem_map; VMAMap vma_map; - std::recursive_mutex mutex; - size_t total_flexible_size = 448_MB; + std::mutex mutex; + size_t total_direct_size{}; + size_t total_flexible_size{}; size_t flexible_usage{}; Vulkan::Rasterizer* rasterizer{}; }; diff --git a/src/core/module.cpp b/src/core/module.cpp index 775e1ef19..5d3b40577 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -1,13 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "common/alignment.h" +#include "common/arch.h" #include "common/assert.h" #include "common/logging/log.h" +#include "common/memory_patcher.h" #include "common/string_util.h" #include "core/aerolib/aerolib.h" #include "core/cpu_patches.h" +#include "core/linker.h" #include "core/loader/dwarf.h" #include "core/memory.h" #include "core/module.h" @@ -68,8 +70,9 @@ Module::~Module() = default; s32 Module::Start(size_t args, const void* argp, void* param) { LOG_INFO(Core_Linker, "Module started : {}", name); + const auto* linker = Common::Singleton::Instance(); const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress(); - return reinterpret_cast(addr)(args, argp, param); + return linker->ExecuteGuest(reinterpret_cast(addr), args, argp, param); } void Module::LoadModuleToMemory(u32& max_tls_index) { @@ -90,9 +93,11 @@ void Module::LoadModuleToMemory(u32& max_tls_index) { LoadOffset += CODE_BASE_INCR * (1 + aligned_base_size / CODE_BASE_INCR); LOG_INFO(Core_Linker, "Loading module {} to {}", name, fmt::ptr(*out_addr)); +#ifdef ARCH_X86_64 // Initialize trampoline generator. void* trampoline_addr = std::bit_cast(base_virtual_addr + aligned_base_size); - Xbyak::CodeGenerator c(TrampolineSize, trampoline_addr); + RegisterPatchModule(*out_addr, aligned_base_size, trampoline_addr, TrampolineSize); +#endif LOG_INFO(Core_Linker, "======== Load Module to Memory ========"); LOG_INFO(Core_Linker, "base_virtual_addr ......: {:#018x}", base_virtual_addr); @@ -131,9 +136,11 @@ void Module::LoadModuleToMemory(u32& max_tls_index) { LOG_INFO(Core_Linker, "segment_mode ..........: {}", segment_mode); add_segment(elf_pheader[i]); +#ifdef ARCH_X86_64 if (elf_pheader[i].p_flags & PF_EXEC) { - PatchInstructions(segment_addr, segment_file_size, c); + PrePatchInstructions(segment_addr, segment_file_size); } +#endif break; } case PT_DYNAMIC: @@ -192,6 +199,14 @@ void Module::LoadModuleToMemory(u32& max_tls_index) { const VAddr entry_addr = base_virtual_addr + elf.GetElfEntry(); LOG_INFO(Core_Linker, "program entry addr ..........: {:#018x}", entry_addr); + + if (MemoryPatcher::g_eboot_address == 0) { + if (name == "eboot") { + MemoryPatcher::g_eboot_address = base_virtual_addr; + MemoryPatcher::g_eboot_image_size = base_size; + MemoryPatcher::OnGameLoaded(); + } + } } void Module::LoadDynamicInfo() { diff --git a/src/core/signals.cpp b/src/core/signals.cpp new file mode 100644 index 000000000..8faf794ed --- /dev/null +++ b/src/core/signals.cpp @@ -0,0 +1,154 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/arch.h" +#include "common/assert.h" +#include "common/decoder.h" +#include "common/signal_context.h" +#include "core/signals.h" + +#ifdef _WIN32 +#include +#else +#include +#ifdef ARCH_X86_64 +#include +#endif +#endif + +namespace Core { + +#if defined(_WIN32) + +static LONG WINAPI SignalHandler(EXCEPTION_POINTERS* pExp) noexcept { + const auto* signals = Signals::Instance(); + + bool handled = false; + switch (pExp->ExceptionRecord->ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + handled = signals->DispatchAccessViolation( + pExp, reinterpret_cast(pExp->ExceptionRecord->ExceptionInformation[1])); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + handled = signals->DispatchIllegalInstruction(pExp); + break; + default: + break; + } + + return handled ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; +} + +#else + +static std::string DisassembleInstruction(void* code_address) { + char buffer[256] = ""; + +#ifdef ARCH_X86_64 + ZydisDecodedInstruction instruction; + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; + const auto status = + Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address); + if (ZYAN_SUCCESS(status)) { + ZydisFormatter formatter; + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); + ZydisFormatterFormatInstruction(&formatter, &instruction, operands, + instruction.operand_count_visible, buffer, sizeof(buffer), + reinterpret_cast(code_address), ZYAN_NULL); + } +#endif + + return buffer; +} + +static void SignalHandler(int sig, siginfo_t* info, void* raw_context) { + const auto* signals = Signals::Instance(); + + auto* code_address = Common::GetRip(raw_context); + + switch (sig) { + case SIGSEGV: + case SIGBUS: { + const bool is_write = Common::IsWriteError(raw_context); + if (!signals->DispatchAccessViolation(raw_context, info->si_addr)) { + UNREACHABLE_MSG("Unhandled access violation at code address {}: {} address {}", + fmt::ptr(code_address), is_write ? "Write to" : "Read from", + fmt::ptr(info->si_addr)); + } + break; + } + case SIGILL: + if (!signals->DispatchIllegalInstruction(raw_context)) { + UNREACHABLE_MSG("Unhandled illegal instruction at code address {}: {}", + fmt::ptr(code_address), DisassembleInstruction(code_address)); + } + break; + case SIGUSR1: { // Sleep thread until signal is received + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + sigwait(&sigset, &sig); + } break; + default: + break; + } +} + +#endif + +SignalDispatch::SignalDispatch() { +#if defined(_WIN32) + ASSERT_MSG(handle = AddVectoredExceptionHandler(0, SignalHandler), + "Failed to register exception handler."); +#else + struct sigaction action {}; + action.sa_sigaction = SignalHandler; + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + sigemptyset(&action.sa_mask); + + ASSERT_MSG(sigaction(SIGSEGV, &action, nullptr) == 0 && + sigaction(SIGBUS, &action, nullptr) == 0, + "Failed to register access violation signal handler."); + ASSERT_MSG(sigaction(SIGILL, &action, nullptr) == 0, + "Failed to register illegal instruction signal handler."); + ASSERT_MSG(sigaction(SIGUSR1, &action, nullptr) == 0, + "Failed to register sleep signal handler."); +#endif +} + +SignalDispatch::~SignalDispatch() { +#if defined(_WIN32) + ASSERT_MSG(RemoveVectoredExceptionHandler(handle), "Failed to remove exception handler."); +#else + struct sigaction action {}; + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + + ASSERT_MSG(sigaction(SIGSEGV, &action, nullptr) == 0 && + sigaction(SIGBUS, &action, nullptr) == 0, + "Failed to remove access violation signal handler."); + ASSERT_MSG(sigaction(SIGILL, &action, nullptr) == 0, + "Failed to remove illegal instruction signal handler."); +#endif +} + +bool SignalDispatch::DispatchAccessViolation(void* context, void* fault_address) const { + for (const auto& [handler, _] : access_violation_handlers) { + if (handler(context, fault_address)) { + return true; + } + } + return false; +} + +bool SignalDispatch::DispatchIllegalInstruction(void* context) const { + for (const auto& [handler, _] : illegal_instruction_handlers) { + if (handler(context)) { + return true; + } + } + return false; +} + +} // namespace Core \ No newline at end of file diff --git a/src/core/signals.h b/src/core/signals.h new file mode 100644 index 000000000..6ee525e10 --- /dev/null +++ b/src/core/signals.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/singleton.h" + +namespace Core { + +using AccessViolationHandler = bool (*)(void* context, void* fault_address); +using IllegalInstructionHandler = bool (*)(void* context); + +/// Receives OS signals and dispatches to the appropriate handlers. +class SignalDispatch { +public: + SignalDispatch(); + ~SignalDispatch(); + + /// Registers a handler for memory access violation signals. + void RegisterAccessViolationHandler(const AccessViolationHandler& handler, u32 priority) { + access_violation_handlers.emplace(handler, priority); + } + + /// Registers a handler for illegal instruction signals. + void RegisterIllegalInstructionHandler(const IllegalInstructionHandler& handler, u32 priority) { + illegal_instruction_handlers.emplace(handler, priority); + } + + /// Dispatches an access violation signal, returning whether it was successfully handled. + bool DispatchAccessViolation(void* context, void* fault_address) const; + + /// Dispatches an illegal instruction signal, returning whether it was successfully handled. + bool DispatchIllegalInstruction(void* context) const; + +private: + template + struct HandlerEntry { + T handler; + u32 priority; + + std::strong_ordering operator<=>(const HandlerEntry& right) const { + return priority <=> right.priority; + } + }; + std::set> access_violation_handlers; + std::set> illegal_instruction_handlers; + +#ifdef _WIN32 + void* handle{}; +#endif +}; + +using Signals = Common::Singleton; + +} // namespace Core \ No newline at end of file diff --git a/src/core/tls.cpp b/src/core/tls.cpp index 3216d0fe4..eb07e7a72 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -2,13 +2,19 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/arch.h" #include "common/assert.h" #include "common/types.h" #include "core/tls.h" #ifdef _WIN32 #include -#elif defined(__APPLE__) +#elif defined(__APPLE__) && defined(ARCH_X86_64) +#include +#include +#include +#include +#elif !defined(ARCH_X86_64) #include #endif @@ -16,12 +22,20 @@ namespace Core { #ifdef _WIN32 +// Windows + static DWORD slot = 0; +static std::once_flag slot_alloc_flag; static void AllocTcbKey() { slot = TlsAlloc(); } +u32 GetTcbKey() { + std::call_once(slot_alloc_flag, &AllocTcbKey); + return slot; +} + void SetTcbBase(void* image_address) { const BOOL result = TlsSetValue(GetTcbKey(), image_address); ASSERT(result != 0); @@ -31,28 +45,103 @@ Tcb* GetTcbBase() { return reinterpret_cast(TlsGetValue(GetTcbKey())); } -#elif defined(__APPLE__) +#elif defined(__APPLE__) && defined(ARCH_X86_64) -static pthread_key_t slot = 0; +// Apple x86_64 -static void AllocTcbKey() { - ASSERT(pthread_key_create(&slot, nullptr) == 0); +// Reserve space in the 32-bit address range for allocating TCB pages. +asm(".zerofill TCB_SPACE,TCB_SPACE,__guest_system,0x3FC000"); + +static constexpr u64 ldt_region_base = 0x4000; +static constexpr u64 ldt_region_size = 0x3FC000; +static constexpr u16 ldt_block_size = 0x1000; +static constexpr u16 ldt_index_base = 8; +static constexpr u16 ldt_index_total = (ldt_region_size - ldt_region_base) / ldt_block_size; + +static boost::icl::interval_set free_ldts{}; +static std::mutex free_ldts_lock; +static std::once_flag ldt_region_init_flag; + +static u16 GetLdtIndex() { + sel_t selector; + asm volatile("mov %%fs, %0" : "=r"(selector)); + return selector.index; +} + +static void InitLdtRegion() { + const void* result = + mmap(reinterpret_cast(ldt_region_base), ldt_region_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + ASSERT_MSG(result != MAP_FAILED, "Failed to map memory region for LDT entries."); + + free_ldts += + boost::icl::interval::right_open(ldt_index_base, ldt_index_base + ldt_index_total); +} + +static void** SetupThreadLdt() { + std::call_once(ldt_region_init_flag, InitLdtRegion); + + // Allocate a new LDT index for the current thread. + u16 ldt_index; + { + std::unique_lock lock{free_ldts_lock}; + ASSERT_MSG(!free_ldts.empty(), "Out of LDT space."); + ldt_index = first(*free_ldts.begin()); + free_ldts -= ldt_index; + } + const u64 addr = ldt_region_base + (ldt_index - ldt_index_base) * ldt_block_size; + + // Create an LDT entry for the TCB. + const ldt_entry ldt{.data{ + .base00 = static_cast(addr), + .base16 = static_cast(addr >> 16), + .base24 = static_cast(addr >> 24), + .limit00 = static_cast(ldt_block_size - 1), + .limit16 = 0, + .type = DESC_DATA_WRITE, + .dpl = 3, // User accessible + .present = 1, // Segment present + .stksz = DESC_DATA_32B, + .granular = DESC_GRAN_BYTE, + }}; + int ret = i386_set_ldt(ldt_index, &ldt, 1); + ASSERT_MSG(ret == ldt_index, + "Failed to set LDT for TLS area: expected {}, but syscall returned {}", ldt_index, + ret); + + // Set the FS segment to the created LDT. + const sel_t sel{ + .rpl = USER_PRIV, + .ti = SEL_LDT, + .index = ldt_index, + }; + asm volatile("mov %0, %%fs" ::"r"(sel)); + + return reinterpret_cast(addr); +} + +static void FreeThreadLdt() { + std::unique_lock lock{free_ldts_lock}; + free_ldts += GetLdtIndex(); } void SetTcbBase(void* image_address) { - ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0); + if (image_address != nullptr) { + *SetupThreadLdt() = image_address; + } else { + FreeThreadLdt(); + } } Tcb* GetTcbBase() { - return reinterpret_cast(pthread_getspecific(GetTcbKey())); + Tcb* tcb; + asm volatile("mov %%fs:0x0, %0" : "=r"(tcb)); + return tcb; } -#else +#elif defined(ARCH_X86_64) -// Placeholder for code compatibility. -static constexpr u32 slot = 0; - -static void AllocTcbKey() {} +// Other POSIX x86_64 void SetTcbBase(void* image_address) { asm volatile("wrgsbase %0" ::"r"(image_address) : "memory"); @@ -64,13 +153,32 @@ Tcb* GetTcbBase() { return tcb; } -#endif +#else +// POSIX non-x86_64 +// Just sets up a simple thread-local variable to store it, then instruction translation can point +// code to it. + +static pthread_key_t slot = 0; static std::once_flag slot_alloc_flag; -u32 GetTcbKey() { +static void AllocTcbKey() { + ASSERT(pthread_key_create(&slot, nullptr) == 0); +} + +pthread_key_t GetTcbKey() { std::call_once(slot_alloc_flag, &AllocTcbKey); return slot; } +void SetTcbBase(void* image_address) { + ASSERT(pthread_setspecific(GetTcbKey(), image_address) == 0); +} + +Tcb* GetTcbBase() { + return static_cast(pthread_getspecific(GetTcbKey())); +} + +#endif + } // namespace Core diff --git a/src/core/tls.h b/src/core/tls.h index 9829c8d9a..f5bf33184 100644 --- a/src/core/tls.h +++ b/src/core/tls.h @@ -22,8 +22,10 @@ struct Tcb { void* tcb_thread; }; +#ifdef _WIN32 /// Gets the thread local storage key for the TCB block. u32 GetTcbKey(); +#endif /// Sets the data pointer to the TCB block. void SetTcbBase(void* image_address); diff --git a/src/emulator.cpp b/src/emulator.cpp index 836b989e5..a3019c9ca 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -7,6 +7,13 @@ #include "common/debug.h" #include "common/logging/backend.h" #include "common/logging/log.h" +#ifdef ENABLE_QT_GUI +#include +#include "common/memory_patcher.h" +#endif +#include "common/assert.h" +#include "common/discord_rpc_handler.h" +#include "common/elf_info.h" #include "common/ntapi.h" #include "common/path_util.h" #include "common/polyfill_thread.h" @@ -16,14 +23,16 @@ #include "core/file_format/playgo_chunk.h" #include "core/file_format/psf.h" #include "core/file_format/splash.h" +#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/kernel/thread_management.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/ngs2/ngs2.h" +#include "core/libraries/np_trophy/np_trophy.h" #include "core/libraries/rtc/rtc.h" -#include "core/libraries/videoout/video_out.h" #include "core/linker.h" #include "core/memory.h" #include "emulator.h" @@ -38,9 +47,10 @@ Emulator::Emulator() { const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); Config::load(config_dir / "config.toml"); - // Initialize NT API functions + // Initialize NT API functions and set high priority #ifdef _WIN32 Common::NtApi::Initialize(); + SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); #endif // Start logger. @@ -51,17 +61,18 @@ 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, "GPU isNullGpu: {}", Config::nullGpu()); LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders()); - LOG_INFO(Config, "GPU shouldDumpPM4: {}", Config::dumpPM4()); LOG_INFO(Config, "GPU vblankDivider: {}", Config::vblankDiv()); LOG_INFO(Config, "Vulkan gpuId: {}", Config::getGpuId()); LOG_INFO(Config, "Vulkan vkValidation: {}", Config::vkValidationEnabled()); LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled()); LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled()); LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled()); - LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::isMarkersEnabled()); + LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::vkMarkersEnabled()); + LOG_INFO(Config, "Vulkan crashDiagnostics: {}", Config::vkCrashDiagnosticEnabled()); // Defer until after logging is initialized. memory = Core::Memory::Instance(); @@ -70,6 +81,17 @@ Emulator::Emulator() { // Load renderdoc module. VideoCore::LoadRenderDoc(); + + // Start the timer (Play Time) +#ifdef ENABLE_QT_GUI + start_time = std::chrono::steady_clock::now(); + const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + QString filePath = QString::fromStdString((user_dir / "play_time.txt").string()); + QFile file(filePath); + if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { + LOG_INFO(Loader, "Error opening or creating play_time.txt"); + } +#endif } Emulator::~Emulator() { @@ -78,25 +100,60 @@ 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().concat("-UPDATE"); + bool use_game_patch = std::filesystem::exists(game_patch_folder / "sce_sys"); + std::filesystem::path eboot_path = use_game_patch ? 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"); + // Certain games may use /hostapp as well such as CUSA001100 + mnt->Mount(file.parent_path(), "/hostapp"); + + auto& game_info = Common::ElfInfo::Instance(); // Loading param.sfo file if exists std::string id; std::string title; std::string app_version; - std::filesystem::path sce_sys_folder = file.parent_path() / "sce_sys"; + u32 fw_version; + + 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(); - param_sfo->open(sce_sys_folder.string() + "/param.sfo", {}); - id = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); - title = param_sfo->GetString("TITLE"); + 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"); + } + } +#ifdef ENABLE_QT_GUI + 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 +#endif + title = param_sfo->GetString("TITLE").value_or("Unknown title"); LOG_INFO(Loader, "Game id: {} Title: {}", id, title); - u32 fw_version = param_sfo->GetInteger("SYSTEM_VER"); - app_version = param_sfo->GetString("APP_VER"); + 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() == "playgo-chunk.dat") { auto* playgo = Common::Singleton::Instance(); @@ -110,20 +167,27 @@ void Emulator::Run(const std::filesystem::path& file) { if (splash->IsLoaded()) { continue; } - if (!splash->Open(entry.path().string())) { + if (!splash->Open(entry.path())) { LOG_ERROR(Loader, "Game splash: unable to open file"); } } } } + game_info.initialized = true; + game_info.game_serial = id; + game_info.title = title; + game_info.app_ver = app_version; + game_info.firmware_ver = fw_version & 0xFFF00000; + game_info.raw_firmware_ver = fw_version; + std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version); std::string window_title = ""; if (Common::isRelease) { window_title = fmt::format("shadPS4 v{} | {}", Common::VERSION, game_title); } else { - window_title = - fmt::format("shadPS4 v{} {} | {}", Common::VERSION, Common::g_scm_desc, game_title); + window_title = fmt::format("shadPS4 v{} {} {} | {}", Common::VERSION, Common::g_scm_branch, + Common::g_scm_desc, game_title); } window = std::make_unique( Config::getScreenWidth(), Config::getScreenHeight(), controller, window_title); @@ -153,27 +217,42 @@ void Emulator::Run(const std::filesystem::path& file) { if (!std::filesystem::exists(mount_captures_dir)) { std::filesystem::create_directory(mount_captures_dir); } - VideoCore::SetOutputDir(mount_captures_dir.generic_string(), id); + VideoCore::SetOutputDir(mount_captures_dir, id); // Initialize kernel and library facilities. Libraries::Kernel::init_pthreads(); Libraries::InitHLELibs(&linker->GetHLESymbols()); // Load the module with the linker - linker->LoadModule(file); + linker->LoadModule(eboot_path); // check if we have system modules to load - LoadSystemModules(file); + LoadSystemModules(eboot_path); // Load all prx from game's sce_module folder std::filesystem::path sce_module_folder = file.parent_path() / "sce_module"; if (std::filesystem::is_directory(sce_module_folder)) { for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) { - LOG_INFO(Loader, "Loading {}", entry.path().string().c_str()); - linker->LoadModule(entry.path()); + std::filesystem::path module_path = entry.path(); + std::filesystem::path update_module_path = + eboot_path.parent_path() / "sce_module" / entry.path().filename(); + if (std::filesystem::exists(update_module_path) && use_game_patch) { + module_path = update_module_path; + } + LOG_INFO(Loader, "Loading {}", fmt::UTF(module_path.u8string())); + linker->LoadModule(module_path); } } + // Discord RPC + if (Config::getEnableDiscordRPC()) { + auto* rpc = Common::Singleton::Instance(); + if (rpc->getRPCEnabled() == false) { + rpc->init(); + } + rpc->setStatusPlaying(game_info.title, id); + } + // start execution std::jthread mainthread = std::jthread([this](std::stop_token stop_token) { linker->Execute(); }); @@ -182,21 +261,28 @@ void Emulator::Run(const std::filesystem::path& file) { window->waitEvent(); } +#ifdef ENABLE_QT_GUI + UpdatePlayTime(id); +#endif + std::exit(0); } void Emulator::LoadSystemModules(const std::filesystem::path& file) { - constexpr std::array ModulesToLoad{ + constexpr std::array ModulesToLoad{ {{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2}, - {"libSceFiber.sprx", nullptr}, + {"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", nullptr}}, - }; + {"libSceJpegEnc.sprx", nullptr}, + {"libSceFont.sprx", nullptr}, + {"libSceRazorCpu.sprx", nullptr}, + {"libSceCesCs.sprx", nullptr}, + {"libSceRudp.sprx", nullptr}}}; std::vector found_modules; const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir); @@ -220,4 +306,74 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file) { } } +#ifdef ENABLE_QT_GUI +void Emulator::UpdatePlayTime(const std::string& serial) { + const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + QString filePath = QString::fromStdString((user_dir / "play_time.txt").string()); + + QFile file(filePath); + if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { + LOG_INFO(Loader, "Error opening play_time.txt"); + return; + } + + auto end_time = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + int totalSeconds = duration.count(); + + QTextStream in(&file); + QStringList lines; + QString content; + while (!in.atEnd()) { + content += in.readLine() + "\n"; + } + file.close(); + + QStringList existingLines = content.split('\n', Qt::SkipEmptyParts); + int accumulatedSeconds = 0; + bool found = false; + + for (const QString& line : existingLines) { + QStringList parts = line.split(' '); + if (parts.size() == 2 && parts[0] == QString::fromStdString(serial)) { + QStringList timeParts = parts[1].split(':'); + if (timeParts.size() == 3) { + int hours = timeParts[0].toInt(); + int minutes = timeParts[1].toInt(); + int seconds = timeParts[2].toInt(); + accumulatedSeconds = hours * 3600 + minutes * 60 + seconds; + found = true; + break; + } + } + } + accumulatedSeconds += totalSeconds; + int hours = accumulatedSeconds / 3600; + int minutes = (accumulatedSeconds % 3600) / 60; + int seconds = accumulatedSeconds % 60; + QString playTimeSaved = QString::number(hours) + ":" + + QString::number(minutes).rightJustified(2, '0') + ":" + + QString::number(seconds).rightJustified(2, '0'); + + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&file); + bool lineUpdated = false; + + for (const QString& line : existingLines) { + if (line.startsWith(QString::fromStdString(serial))) { + out << QString::fromStdString(serial) + " " + playTimeSaved + "\n"; + lineUpdated = true; + } else { + out << line << "\n"; + } + } + + if (!lineUpdated) { + out << QString::fromStdString(serial) + " " + playTimeSaved + "\n"; + } + } + LOG_INFO(Loader, "Playing time for {}: {}", serial, playTimeSaved.toStdString()); +} +#endif + } // namespace Core diff --git a/src/emulator.h b/src/emulator.h index 01bce7e7c..dc2959af4 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -26,6 +26,7 @@ public: ~Emulator(); void Run(const std::filesystem::path& file); + void UpdatePlayTime(const std::string& serial); private: void LoadSystemModules(const std::filesystem::path& file); @@ -34,6 +35,7 @@ private: Input::GameController* controller; Core::Linker* linker; std::unique_ptr window; + std::chrono::steady_clock::time_point start_time; }; } // namespace Core diff --git a/src/images/dump_icon.png b/src/images/dump_icon.png new file mode 100644 index 000000000..e267181f7 Binary files /dev/null and b/src/images/dump_icon.png differ diff --git a/src/images/flag_china.png b/src/images/flag_china.png index 13bf221e9..33fcdfd86 100644 Binary files a/src/images/flag_china.png and b/src/images/flag_china.png differ diff --git a/src/images/flag_eu.png b/src/images/flag_eu.png index 0922e11ec..461f814e1 100644 Binary files a/src/images/flag_eu.png and b/src/images/flag_eu.png differ diff --git a/src/images/flag_jp.png b/src/images/flag_jp.png index 6433eecfd..fd056962a 100644 Binary files a/src/images/flag_jp.png and b/src/images/flag_jp.png differ diff --git a/src/images/flag_us.png b/src/images/flag_us.png index f4bf3a300..7b0089af4 100644 Binary files a/src/images/flag_us.png and b/src/images/flag_us.png differ diff --git a/src/images/flag_world.png b/src/images/flag_world.png index 0dcccf800..7b96dff11 100644 Binary files a/src/images/flag_world.png and b/src/images/flag_world.png differ diff --git a/src/images/pause_icon.png b/src/images/pause_icon.png index e4356949a..5375689b7 100644 Binary files a/src/images/pause_icon.png and b/src/images/pause_icon.png differ diff --git a/src/images/play_icon.png b/src/images/play_icon.png index c67831a1e..2815be39d 100644 Binary files a/src/images/play_icon.png and b/src/images/play_icon.png differ diff --git a/src/images/settings_icon.png b/src/images/settings_icon.png index 6fd024e36..c88cd7a6f 100644 Binary files a/src/images/settings_icon.png and b/src/images/settings_icon.png differ diff --git a/src/images/stop_icon.png b/src/images/stop_icon.png index 86d772b6e..74c615f65 100644 Binary files a/src/images/stop_icon.png and b/src/images/stop_icon.png differ diff --git a/src/images/themes_icon.png b/src/images/themes_icon.png index 822ef3af0..cc711011e 100644 Binary files a/src/images/themes_icon.png and b/src/images/themes_icon.png differ diff --git a/src/images/update_icon.png b/src/images/update_icon.png new file mode 100644 index 000000000..517f91fa6 Binary files /dev/null and b/src/images/update_icon.png differ diff --git a/src/imgui/imgui_config.h b/src/imgui/imgui_config.h new file mode 100644 index 000000000..ccb084d94 --- /dev/null +++ b/src/imgui/imgui_config.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +// WARNING: All includes from this file must be relative to allow Dear_ImGui project to compile +// without having this project include paths. + +#include + +extern void assert_fail_debug_msg(const char* msg); + +#define ImDrawIdx std::uint32_t + +#define IM_STRINGIZE(x) IM_STRINGIZE2(x) +#define IM_STRINGIZE2(x) #x +#define IM_ASSERT(_EXPR) \ + ([&]() { \ + if (!(_EXPR)) [[unlikely]] { \ + assert_fail_debug_msg(#_EXPR " at " __FILE__ ":" IM_STRINGIZE(__LINE__)); \ + } \ + }()) + +#define IMGUI_ENABLE_STB_TRUETYPE +#define IMGUI_DEFINE_MATH_OPERATORS + +#define IM_VEC2_CLASS_EXTRA \ + constexpr ImVec2(float _v) : x(_v), y(_v) {} + +#define IM_VEC4_CLASS_EXTRA \ + constexpr ImVec4(float _v) : x(_v), y(_v), z(_v), w(_v) {} + +#ifdef IMGUI_USE_WCHAR32 +#error "This project uses 16 bits wchar standard like Orbis" +#endif \ No newline at end of file diff --git a/src/imgui/imgui_layer.h b/src/imgui/imgui_layer.h new file mode 100644 index 000000000..a6c7e2a4a --- /dev/null +++ b/src/imgui/imgui_layer.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +namespace ImGui { + +class Layer { +public: + virtual ~Layer() = default; + static void AddLayer(Layer* layer); + static void RemoveLayer(Layer* layer); + + virtual void Draw() = 0; +}; + +} // namespace ImGui \ No newline at end of file diff --git a/src/imgui/imgui_std.h b/src/imgui/imgui_std.h new file mode 100644 index 000000000..cd7208064 --- /dev/null +++ b/src/imgui/imgui_std.h @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "imgui_internal.h" + +#define IM_COL32_GRAY(x) IM_COL32(x, x, x, 0xFF) + +#define IMGUI_FONT_TEXT 0 +#define IMGUI_FONT_MONO 1 + +namespace ImGui { + +namespace Easing { + +inline float FastInFastOutCubic(float x) { + constexpr float c4 = 1.587401f; // 4^(1/3) + constexpr float c05 = 0.7937f; // 0.5^(1/3) + return std::pow(c4 * x - c05, 3.0f) + 0.5f; +} + +} // namespace Easing + +inline void CentralizeNextWindow() { + const auto display_size = GetIO().DisplaySize; + SetNextWindowPos(display_size / 2.0f, ImGuiCond_Always, {0.5f}); +} + +inline void CentralizeWindow() { + const auto display_size = GetIO().DisplaySize - GetCurrentWindowRead()->SizeFull; + SetWindowPos(display_size / 2.0f); +} + +inline void KeepWindowInside(ImVec2 display_size = GetIO().DisplaySize) { + const auto cur_pos = GetWindowPos(); + if (cur_pos.x < 0.0f || cur_pos.y < 0.0f) { + SetWindowPos(ImMax(cur_pos, ImVec2(0.0f, 0.0f))); + return; + } + const auto cur_size = GetCurrentWindowRead()->SizeFull; + const auto bottom_right = cur_pos + cur_size; + if (bottom_right.x > display_size.x || bottom_right.y > display_size.y) { + const auto max_pos = display_size - cur_size; + SetWindowPos(ImMin(cur_pos, max_pos)); + } +} + +inline void KeepNavHighlight() { + GetCurrentContext()->NavDisableHighlight = false; +} + +inline void SetItemCurrentNavFocus(const ImGuiID id = -1) { + const auto ctx = GetCurrentContext(); + SetFocusID(id == -1 ? ctx->LastItemData.ID : id, ctx->CurrentWindow); + ctx->NavInitResult.Clear(); + ctx->NavDisableHighlight = false; +} + +inline void DrawPrettyBackground() { + const double time = GetTime() / 1.5f; + const float x = ((float)std::cos(time) + 1.0f) / 2.0f; + const float d = Easing::FastInFastOutCubic(x); + u8 top_left = ImLerp(0x13, 0x05, d); + u8 top_right = ImLerp(0x00, 0x07, d); + u8 bottom_right = ImLerp(0x03, 0x27, d); + u8 bottom_left = ImLerp(0x05, 0x00, d); + + auto& window = *GetCurrentWindowRead(); + auto inner_pos = window.DC.CursorPos - window.WindowPadding; + auto inner_size = GetContentRegionAvail() + window.WindowPadding * 2.0f; + GetWindowDrawList()->AddRectFilledMultiColor( + inner_pos, inner_pos + inner_size, IM_COL32_GRAY(top_left), IM_COL32_GRAY(top_right), + IM_COL32_GRAY(bottom_right), IM_COL32_GRAY(bottom_left)); +} + +static void DrawCenteredText(const char* text, const char* text_end = nullptr, + ImVec2 content = GetContentRegionAvail()) { + auto pos = GetCursorPos(); + const auto text_size = CalcTextSize(text, text_end, false, content.x - 40.0f); + PushTextWrapPos(content.x); + SetCursorPos(pos + (content - text_size) / 2.0f); + TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); + PopTextWrapPos(); + SetCursorPos(pos + content); +} + +} // namespace ImGui diff --git a/src/imgui/imgui_texture.h b/src/imgui/imgui_texture.h new file mode 100644 index 000000000..1a38066d0 --- /dev/null +++ b/src/imgui/imgui_texture.h @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +namespace ImGui { + +namespace Core::TextureManager { +struct Inner; +} // namespace Core::TextureManager + +class RefCountedTexture { + Core::TextureManager::Inner* inner; + + explicit RefCountedTexture(Core::TextureManager::Inner* inner); + +public: + struct Image { + ImTextureID im_id; + u32 width; + u32 height; + }; + + static RefCountedTexture DecodePngTexture(std::vector data); + + static RefCountedTexture DecodePngFile(std::filesystem::path path); + + RefCountedTexture(); + + RefCountedTexture(const RefCountedTexture& other); + RefCountedTexture(RefCountedTexture&& other) noexcept; + RefCountedTexture& operator=(const RefCountedTexture& other); + RefCountedTexture& operator=(RefCountedTexture&& other) noexcept; + + virtual ~RefCountedTexture(); + + [[nodiscard]] Image GetTexture() const; + + explicit(false) operator bool() const; +}; + +}; // namespace ImGui \ No newline at end of file diff --git a/src/imgui/renderer/CMakeLists.txt b/src/imgui/renderer/CMakeLists.txt new file mode 100644 index 000000000..5d74632f9 --- /dev/null +++ b/src/imgui/renderer/CMakeLists.txt @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +project(ImGui_Resources) + +add_executable(Dear_ImGui_FontEmbed ${CMAKE_SOURCE_DIR}/externals/dear_imgui/misc/fonts/binary_to_compressed_c.cpp) + +set(FONT_LIST + NotoSansJP-Regular.ttf + ProggyVector-Regular.ttf +) + +set(OutputList "") +FOREACH (FONT_FILE ${FONT_LIST}) + string(REGEX REPLACE "-" "_" fontname ${FONT_FILE}) + string(TOLOWER ${fontname} fontname) + string(REGEX REPLACE ".ttf" "" fontname_cpp ${fontname}) + set(fontname_cpp "imgui_font_${fontname_cpp}") + + MESSAGE(STATUS "Embedding font ${FONT_FILE}") + set(OUTPUT "generated_fonts/imgui_fonts/${fontname}") + add_custom_command( + OUTPUT "${OUTPUT}.g.cpp" + COMMAND ${CMAKE_COMMAND} -E make_directory "generated_fonts/imgui_fonts" + COMMAND $ -nostatic "${CMAKE_CURRENT_SOURCE_DIR}/fonts/${FONT_FILE}" ${fontname_cpp} > "${OUTPUT}.g.cpp" + DEPENDS Dear_ImGui_FontEmbed "fonts/${FONT_FILE}" + USES_TERMINAL + ) + list(APPEND OutputList "${OUTPUT}.g.cpp") +ENDFOREACH () + +add_library(ImGui_Resources STATIC ${OutputList}) +set(IMGUI_RESOURCES_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/generated_fonts PARENT_SCOPE) diff --git a/src/imgui/renderer/fonts/NotoSansJP-Regular.ttf b/src/imgui/renderer/fonts/NotoSansJP-Regular.ttf new file mode 100644 index 000000000..b2dad730d Binary files /dev/null and b/src/imgui/renderer/fonts/NotoSansJP-Regular.ttf differ diff --git a/src/imgui/renderer/fonts/ProggyVector-Regular.ttf b/src/imgui/renderer/fonts/ProggyVector-Regular.ttf new file mode 100644 index 000000000..0865b6561 Binary files /dev/null and b/src/imgui/renderer/fonts/ProggyVector-Regular.ttf differ diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp new file mode 100644 index 000000000..311e86a3c --- /dev/null +++ b/src/imgui/renderer/imgui_core.cpp @@ -0,0 +1,244 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#include "common/config.h" +#include "common/path_util.h" +#include "core/devtools/layer.h" +#include "imgui/imgui_layer.h" +#include "imgui_core.h" +#include "imgui_impl_sdl3.h" +#include "imgui_impl_vulkan.h" +#include "imgui_internal.h" +#include "sdl_window.h" +#include "texture_manager.h" +#include "video_core/renderer_vulkan/renderer_vulkan.h" + +#include "imgui_fonts/notosansjp_regular.ttf.g.cpp" +#include "imgui_fonts/proggyvector_regular.ttf.g.cpp" + +static void CheckVkResult(const vk::Result err) { + LOG_ERROR(ImGui, "Vulkan error {}", vk::to_string(err)); +} + +static std::vector layers; + +// Update layers before rendering to allow layer changes to be applied during rendering. +// Using deque to keep the order of changes in case a Layer is removed then added again between +// frames. +static std::deque> change_layers{}; +static std::mutex change_layers_mutex{}; + +static ImGuiID dock_id; + +namespace ImGui { + +namespace Core { + +void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& window, + const u32 image_count, vk::Format surface_format, + const vk::AllocationCallbacks* allocator) { + + const auto config_path = GetUserPath(Common::FS::PathType::UserDir) / "imgui.ini"; + const auto log_path = GetUserPath(Common::FS::PathType::LogDir) / "imgui_log.txt"; + + CreateContext(); + ImGuiIO& io = GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.DisplaySize = ImVec2((float)window.getWidth(), (float)window.getHeight()); + PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f); // Makes the window edges rounded + + auto path = config_path.u8string(); + char* config_file_buf = new char[path.size() + 1](); + std::memcpy(config_file_buf, path.c_str(), path.size()); + io.IniFilename = config_file_buf; + + path = log_path.u8string(); + char* log_file_buf = new char[path.size() + 1](); + std::memcpy(log_file_buf, path.c_str(), path.size()); + io.LogFilename = log_file_buf; + + ImFontGlyphRangesBuilder rb{}; + rb.AddRanges(io.Fonts->GetGlyphRangesDefault()); + rb.AddRanges(io.Fonts->GetGlyphRangesGreek()); + rb.AddRanges(io.Fonts->GetGlyphRangesKorean()); + rb.AddRanges(io.Fonts->GetGlyphRangesJapanese()); + rb.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); + ImVector ranges{}; + rb.BuildRanges(&ranges); + ImFontConfig font_cfg{}; + font_cfg.OversampleH = 2; + font_cfg.OversampleV = 1; + io.FontDefault = io.Fonts->AddFontFromMemoryCompressedTTF( + imgui_font_notosansjp_regular_compressed_data, + imgui_font_notosansjp_regular_compressed_size, 16.0f, &font_cfg, ranges.Data); + io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_proggyvector_regular_compressed_data, + imgui_font_proggyvector_regular_compressed_size, + 16.0f); + + StyleColorsDark(); + + ::Core::Devtools::Layer::SetupSettings(); + Sdl::Init(window.GetSdlWindow()); + + const Vulkan::InitInfo vk_info{ + .instance = instance.GetInstance(), + .physical_device = instance.GetPhysicalDevice(), + .device = instance.GetDevice(), + .queue_family = instance.GetPresentQueueFamilyIndex(), + .queue = instance.GetPresentQueue(), + .image_count = image_count, + .min_allocation_size = 1024 * 1024, + .pipeline_rendering_create_info{ + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &surface_format, + }, + .allocator = allocator, + .check_vk_result_fn = &CheckVkResult, + }; + Vulkan::Init(vk_info); + + TextureManager::StartWorker(); + + char label[32]; + ImFormatString(label, IM_ARRAYSIZE(label), "WindowOverViewport_%08X", GetMainViewport()->ID); + dock_id = ImHashStr(label); + + if (const auto dpi = SDL_GetWindowDisplayScale(window.GetSdlWindow()); dpi > 0.0f) { + GetIO().FontGlobalScale = dpi; + } +} + +void OnResize() { + Sdl::OnResize(); +} + +void Shutdown(const vk::Device& device) { + auto result = device.waitIdle(); + if (result != vk::Result::eSuccess) { + LOG_WARNING(ImGui, "Failed to wait for Vulkan device idle on shutdown: {}", + vk::to_string(result)); + } + + TextureManager::StopWorker(); + + const ImGuiIO& io = GetIO(); + const auto ini_filename = (void*)io.IniFilename; + const auto log_filename = (void*)io.LogFilename; + + Vulkan::Shutdown(); + Sdl::Shutdown(); + DestroyContext(); + + delete[] (char*)ini_filename; + delete[] (char*)log_filename; +} + +bool ProcessEvent(SDL_Event* event) { + Sdl::ProcessEvent(event); + switch (event->type) { + // Don't block release/up events + case SDL_EVENT_MOUSE_MOTION: + case SDL_EVENT_MOUSE_WHEEL: + case SDL_EVENT_MOUSE_BUTTON_DOWN: { + const auto& io = GetIO(); + return io.WantCaptureMouse && io.Ctx->NavWindow != nullptr && + io.Ctx->NavWindow->ID != dock_id; + } + case SDL_EVENT_TEXT_INPUT: + case SDL_EVENT_KEY_DOWN: { + const auto& io = GetIO(); + return io.WantCaptureKeyboard && io.Ctx->NavWindow != nullptr && + io.Ctx->NavWindow->ID != dock_id; + } + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: { + const auto& io = GetIO(); + return io.NavActive && io.Ctx->NavWindow != nullptr && io.Ctx->NavWindow->ID != dock_id; + } + default: + return false; + } +} + +void NewFrame() { + { + std::scoped_lock lock{change_layers_mutex}; + while (!change_layers.empty()) { + const auto [to_be_added, layer] = change_layers.front(); + if (to_be_added) { + layers.push_back(layer); + } else { + const auto [begin, end] = std::ranges::remove(layers, layer); + layers.erase(begin, end); + } + change_layers.pop_front(); + } + } + + Sdl::NewFrame(); + ImGui::NewFrame(); + + DockSpaceOverViewport(0, GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode); + + for (auto* layer : layers) { + layer->Draw(); + } +} + +void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) { + ImGui::Render(); + ImDrawData* draw_data = GetDrawData(); + if (draw_data->CmdListsCount == 0) { + return; + } + + if (Config::vkMarkersEnabled()) { + cmdbuf.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{ + .pLabelName = "ImGui Render", + }); + } + + vk::RenderingAttachmentInfo color_attachments[1]{ + { + .imageView = frame->image_view, + .imageLayout = vk::ImageLayout::eColorAttachmentOptimal, + .loadOp = vk::AttachmentLoadOp::eLoad, + .storeOp = vk::AttachmentStoreOp::eStore, + }, + }; + vk::RenderingInfo render_info{}; + render_info.renderArea = vk::Rect2D{ + .offset = {0, 0}, + .extent = {frame->width, frame->height}, + }; + render_info.layerCount = 1; + render_info.colorAttachmentCount = 1; + render_info.pColorAttachments = color_attachments; + cmdbuf.beginRendering(render_info); + Vulkan::RenderDrawData(*draw_data, cmdbuf); + cmdbuf.endRendering(); + if (Config::vkMarkersEnabled()) { + cmdbuf.endDebugUtilsLabelEXT(); + } +} + +} // namespace Core + +void Layer::AddLayer(Layer* layer) { + std::scoped_lock lock{change_layers_mutex}; + change_layers.emplace_back(true, layer); +} + +void Layer::RemoveLayer(Layer* layer) { + std::scoped_lock lock{change_layers_mutex}; + change_layers.emplace_back(false, layer); +} + +} // namespace ImGui diff --git a/src/imgui/renderer/imgui_core.h b/src/imgui/renderer/imgui_core.h new file mode 100644 index 000000000..9ad708f81 --- /dev/null +++ b/src/imgui/renderer/imgui_core.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "video_core/renderer_vulkan/vk_instance.h" +#include "vulkan/vulkan_handles.hpp" + +union SDL_Event; + +namespace Vulkan { +struct Frame; +} + +namespace ImGui::Core { + +void Initialize(const Vulkan::Instance& instance, const Frontend::WindowSDL& window, + u32 image_count, vk::Format surface_format, + const vk::AllocationCallbacks* allocator = nullptr); + +void OnResize(); + +void Shutdown(const vk::Device& device); + +bool ProcessEvent(SDL_Event* event); + +void NewFrame(); + +void Render(const vk::CommandBuffer& cmdbuf, Vulkan::Frame* frame); + +} // namespace ImGui::Core diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp new file mode 100644 index 000000000..230d396f0 --- /dev/null +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -0,0 +1,827 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Based on imgui_impl_sdl3.cpp from Dear ImGui repository + +#include +#include "common/config.h" +#include "imgui_impl_sdl3.h" + +// SDL +#include +#if defined(__APPLE__) +#include +#endif +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + +namespace ImGui::Sdl { + +// SDL Data +struct SdlData { + SDL_Window* window{}; + SDL_WindowID window_id{}; + Uint64 time{}; + const char* clipboard_text_data{}; + + // IME handling + SDL_Window* ime_window{}; + + // Mouse handling + Uint32 mouse_window_id{}; + int mouse_buttons_down{}; + SDL_Cursor* mouse_cursors[ImGuiMouseCursor_COUNT]{}; + SDL_Cursor* mouse_last_cursor{}; + int mouse_pending_leave_frame{}; + ImVec2 prev_mouse_pos{0, 0}; + Uint64 lastCursorMoveTime{}; + + // Gamepad handling + ImVector gamepads{}; + GamepadMode gamepad_mode{}; + bool want_update_gamepads_list{}; +}; + +// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui +// contexts It is STRONGLY preferred that you use docking branch with multi-viewports (== single +// Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static SdlData* GetBackendData() { + return ImGui::GetCurrentContext() ? (SdlData*)ImGui::GetIO().BackendPlatformUserData : nullptr; +} + +static const char* GetClipboardText(ImGuiContext*) { + SdlData* bd = GetBackendData(); + if (bd->clipboard_text_data) + SDL_free((void*)bd->clipboard_text_data); + const char* sdl_clipboard_text = SDL_GetClipboardText(); + bd->clipboard_text_data = sdl_clipboard_text; + return bd->clipboard_text_data; +} + +static void SetClipboardText(ImGuiContext*, const char* text) { + SDL_SetClipboardText(text); +} + +static void PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) { + SdlData* bd = GetBackendData(); + auto window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle; + SDL_Window* window = SDL_GetWindowFromID(window_id); + if ((!data->WantVisible || bd->ime_window != window) && bd->ime_window != nullptr) { + SDL_StopTextInput(bd->ime_window); + bd->ime_window = nullptr; + } + if (data->WantVisible) { + SDL_Rect r; + r.x = (int)data->InputPos.x; + r.y = (int)data->InputPos.y; + r.w = 1; + r.h = (int)data->InputLineHeight; + SDL_SetTextInputArea(window, &r, 0); + SDL_StartTextInput(window); + bd->ime_window = window; + } +} + +static ImGuiKey KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode) { + // Keypad doesn't have individual key values in SDL3 + switch (scancode) { + case SDL_SCANCODE_KP_0: + return ImGuiKey_Keypad0; + case SDL_SCANCODE_KP_1: + return ImGuiKey_Keypad1; + case SDL_SCANCODE_KP_2: + return ImGuiKey_Keypad2; + case SDL_SCANCODE_KP_3: + return ImGuiKey_Keypad3; + case SDL_SCANCODE_KP_4: + return ImGuiKey_Keypad4; + case SDL_SCANCODE_KP_5: + return ImGuiKey_Keypad5; + case SDL_SCANCODE_KP_6: + return ImGuiKey_Keypad6; + case SDL_SCANCODE_KP_7: + return ImGuiKey_Keypad7; + case SDL_SCANCODE_KP_8: + return ImGuiKey_Keypad8; + case SDL_SCANCODE_KP_9: + return ImGuiKey_Keypad9; + case SDL_SCANCODE_KP_PERIOD: + return ImGuiKey_KeypadDecimal; + case SDL_SCANCODE_KP_DIVIDE: + return ImGuiKey_KeypadDivide; + case SDL_SCANCODE_KP_MULTIPLY: + return ImGuiKey_KeypadMultiply; + case SDL_SCANCODE_KP_MINUS: + return ImGuiKey_KeypadSubtract; + case SDL_SCANCODE_KP_PLUS: + return ImGuiKey_KeypadAdd; + case SDL_SCANCODE_KP_ENTER: + return ImGuiKey_KeypadEnter; + case SDL_SCANCODE_KP_EQUALS: + return ImGuiKey_KeypadEqual; + default: + break; + } + switch (keycode) { + case SDLK_TAB: + return ImGuiKey_Tab; + case SDLK_LEFT: + return ImGuiKey_LeftArrow; + case SDLK_RIGHT: + return ImGuiKey_RightArrow; + case SDLK_UP: + return ImGuiKey_UpArrow; + case SDLK_DOWN: + return ImGuiKey_DownArrow; + case SDLK_PAGEUP: + return ImGuiKey_PageUp; + case SDLK_PAGEDOWN: + return ImGuiKey_PageDown; + case SDLK_HOME: + return ImGuiKey_Home; + case SDLK_END: + return ImGuiKey_End; + case SDLK_INSERT: + return ImGuiKey_Insert; + case SDLK_DELETE: + return ImGuiKey_Delete; + case SDLK_BACKSPACE: + return ImGuiKey_Backspace; + case SDLK_SPACE: + return ImGuiKey_Space; + case SDLK_RETURN: + return ImGuiKey_Enter; + case SDLK_ESCAPE: + return ImGuiKey_Escape; + case SDLK_APOSTROPHE: + return ImGuiKey_Apostrophe; + case SDLK_COMMA: + return ImGuiKey_Comma; + case SDLK_MINUS: + return ImGuiKey_Minus; + case SDLK_PERIOD: + return ImGuiKey_Period; + case SDLK_SLASH: + return ImGuiKey_Slash; + case SDLK_SEMICOLON: + return ImGuiKey_Semicolon; + case SDLK_EQUALS: + return ImGuiKey_Equal; + case SDLK_LEFTBRACKET: + return ImGuiKey_LeftBracket; + case SDLK_BACKSLASH: + return ImGuiKey_Backslash; + case SDLK_RIGHTBRACKET: + return ImGuiKey_RightBracket; + case SDLK_GRAVE: + return ImGuiKey_GraveAccent; + case SDLK_CAPSLOCK: + return ImGuiKey_CapsLock; + case SDLK_SCROLLLOCK: + return ImGuiKey_ScrollLock; + case SDLK_NUMLOCKCLEAR: + return ImGuiKey_NumLock; + case SDLK_PRINTSCREEN: + return ImGuiKey_PrintScreen; + case SDLK_PAUSE: + return ImGuiKey_Pause; + case SDLK_LCTRL: + return ImGuiKey_LeftCtrl; + case SDLK_LSHIFT: + return ImGuiKey_LeftShift; + case SDLK_LALT: + return ImGuiKey_LeftAlt; + case SDLK_LGUI: + return ImGuiKey_LeftSuper; + case SDLK_RCTRL: + return ImGuiKey_RightCtrl; + case SDLK_RSHIFT: + return ImGuiKey_RightShift; + case SDLK_RALT: + return ImGuiKey_RightAlt; + case SDLK_RGUI: + return ImGuiKey_RightSuper; + case SDLK_APPLICATION: + return ImGuiKey_Menu; + case SDLK_0: + return ImGuiKey_0; + case SDLK_1: + return ImGuiKey_1; + case SDLK_2: + return ImGuiKey_2; + case SDLK_3: + return ImGuiKey_3; + case SDLK_4: + return ImGuiKey_4; + case SDLK_5: + return ImGuiKey_5; + case SDLK_6: + return ImGuiKey_6; + case SDLK_7: + return ImGuiKey_7; + case SDLK_8: + return ImGuiKey_8; + case SDLK_9: + return ImGuiKey_9; + case SDLK_A: + return ImGuiKey_A; + case SDLK_B: + return ImGuiKey_B; + case SDLK_C: + return ImGuiKey_C; + case SDLK_D: + return ImGuiKey_D; + case SDLK_E: + return ImGuiKey_E; + case SDLK_F: + return ImGuiKey_F; + case SDLK_G: + return ImGuiKey_G; + case SDLK_H: + return ImGuiKey_H; + case SDLK_I: + return ImGuiKey_I; + case SDLK_J: + return ImGuiKey_J; + case SDLK_K: + return ImGuiKey_K; + case SDLK_L: + return ImGuiKey_L; + case SDLK_M: + return ImGuiKey_M; + case SDLK_N: + return ImGuiKey_N; + case SDLK_O: + return ImGuiKey_O; + case SDLK_P: + return ImGuiKey_P; + case SDLK_Q: + return ImGuiKey_Q; + case SDLK_R: + return ImGuiKey_R; + case SDLK_S: + return ImGuiKey_S; + case SDLK_T: + return ImGuiKey_T; + case SDLK_U: + return ImGuiKey_U; + case SDLK_V: + return ImGuiKey_V; + case SDLK_W: + return ImGuiKey_W; + case SDLK_X: + return ImGuiKey_X; + case SDLK_Y: + return ImGuiKey_Y; + case SDLK_Z: + return ImGuiKey_Z; + case SDLK_F1: + return ImGuiKey_F1; + case SDLK_F2: + return ImGuiKey_F2; + case SDLK_F3: + return ImGuiKey_F3; + case SDLK_F4: + return ImGuiKey_F4; + case SDLK_F5: + return ImGuiKey_F5; + case SDLK_F6: + return ImGuiKey_F6; + case SDLK_F7: + return ImGuiKey_F7; + case SDLK_F8: + return ImGuiKey_F8; + case SDLK_F9: + return ImGuiKey_F9; + case SDLK_F10: + return ImGuiKey_F10; + case SDLK_F11: + return ImGuiKey_F11; + case SDLK_F12: + return ImGuiKey_F12; + case SDLK_F13: + return ImGuiKey_F13; + case SDLK_F14: + return ImGuiKey_F14; + case SDLK_F15: + return ImGuiKey_F15; + case SDLK_F16: + return ImGuiKey_F16; + case SDLK_F17: + return ImGuiKey_F17; + case SDLK_F18: + return ImGuiKey_F18; + case SDLK_F19: + return ImGuiKey_F19; + case SDLK_F20: + return ImGuiKey_F20; + case SDLK_F21: + return ImGuiKey_F21; + case SDLK_F22: + return ImGuiKey_F22; + case SDLK_F23: + return ImGuiKey_F23; + case SDLK_F24: + return ImGuiKey_F24; + case SDLK_AC_BACK: + return ImGuiKey_AppBack; + case SDLK_AC_FORWARD: + return ImGuiKey_AppForward; + default: + break; + } + return ImGuiKey_None; +} + +static void UpdateKeyModifiers(SDL_Keymod sdl_key_mods) { + ImGuiIO& io = ImGui::GetIO(); + io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & SDL_KMOD_CTRL) != 0); + io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & SDL_KMOD_SHIFT) != 0); + io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & SDL_KMOD_ALT) != 0); + io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0); +} + +static ImGuiViewport* GetViewportForWindowId(SDL_WindowID window_id) { + SdlData* bd = GetBackendData(); + return (window_id == bd->window_id) ? ImGui::GetMainViewport() : nullptr; +} + +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to +// use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or +// clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main +// application, or clear/overwrite your copy of the keyboard data. Generally you may always pass all +// inputs to dear imgui, and hide them from your application based on those two flags. If you have +// multiple SDL events and some of them are not meant to be used by dear imgui, you may need to +// filter events based on their windowID field. +bool ProcessEvent(const SDL_Event* event) { + SdlData* bd = GetBackendData(); + IM_ASSERT(bd != nullptr && + "Context or backend not initialized! Did you call ImGui_ImplSDL3_Init()?"); + ImGuiIO& io = ImGui::GetIO(); + + switch (event->type) { + case SDL_EVENT_MOUSE_MOTION: { + if (GetViewportForWindowId(event->motion.windowID) == NULL) + return false; + ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); + io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID + ? ImGuiMouseSource_TouchScreen + : ImGuiMouseSource_Mouse); + io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); + if (mouse_pos.x != bd->prev_mouse_pos.x || mouse_pos.y != bd->prev_mouse_pos.y) { + bd->prev_mouse_pos.x = mouse_pos.x; + bd->prev_mouse_pos.y = mouse_pos.y; + if (Config::getCursorState() == Config::HideCursorState::Idle) { + bd->lastCursorMoveTime = bd->time; + } + } + return true; + } + case SDL_EVENT_MOUSE_WHEEL: { + if (GetViewportForWindowId(event->wheel.windowID) == NULL) + return false; + // IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, + // (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); + float wheel_x = -event->wheel.x; + float wheel_y = event->wheel.y; +#ifdef __EMSCRIPTEN__ + wheel_x /= 100.0f; +#endif + io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID + ? ImGuiMouseSource_TouchScreen + : ImGuiMouseSource_Mouse); + io.AddMouseWheelEvent(wheel_x, wheel_y); + return true; + } + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: { + if (GetViewportForWindowId(event->button.windowID) == NULL) + return false; + int mouse_button = -1; + if (event->button.button == SDL_BUTTON_LEFT) { + mouse_button = 0; + } + if (event->button.button == SDL_BUTTON_RIGHT) { + mouse_button = 1; + } + if (event->button.button == SDL_BUTTON_MIDDLE) { + mouse_button = 2; + } + if (event->button.button == SDL_BUTTON_X1) { + mouse_button = 3; + } + if (event->button.button == SDL_BUTTON_X2) { + mouse_button = 4; + } + if (mouse_button == -1) + break; + io.AddMouseSourceEvent(event->button.which == SDL_TOUCH_MOUSEID + ? ImGuiMouseSource_TouchScreen + : ImGuiMouseSource_Mouse); + io.AddMouseButtonEvent(mouse_button, (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)); + bd->mouse_buttons_down = (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) + ? (bd->mouse_buttons_down | (1 << mouse_button)) + : (bd->mouse_buttons_down & ~(1 << mouse_button)); + return true; + } + case SDL_EVENT_TEXT_INPUT: { + if (GetViewportForWindowId(event->text.windowID) == NULL) + return false; + io.AddInputCharactersUTF8(event->text.text); + return true; + } + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: { + if (GetViewportForWindowId(event->key.windowID) == NULL) + return false; + // IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%d: key=%d, scancode=%d, mod=%X\n", (event->type == + // SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP", event->key.key, event->key.scancode, + // event->key.mod); + UpdateKeyModifiers((SDL_Keymod)event->key.mod); + ImGuiKey key = KeyEventToImGuiKey(event->key.key, event->key.scancode); + io.AddKeyEvent(key, (event->type == SDL_EVENT_KEY_DOWN)); + io.SetKeyEventNativeData( + key, event->key.key, event->key.scancode, + event->key.scancode); // To support legacy indexing (<1.87 user code). Legacy backend + // uses SDLK_*** as indices to IsKeyXXX() functions. + return true; + } + case SDL_EVENT_WINDOW_MOUSE_ENTER: { + if (GetViewportForWindowId(event->window.windowID) == NULL) + return false; + bd->mouse_window_id = event->window.windowID; + bd->mouse_pending_leave_frame = 0; + bd->lastCursorMoveTime = bd->time; + return true; + } + // - In some cases, when detaching a window from main viewport SDL may send + // SDL_WINDOWEVENT_ENTER one frame too late, + // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse + // position. This is why we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See + // issue #5012 for details. + // FIXME: Unconfirmed whether this is still needed with SDL3. + case SDL_EVENT_WINDOW_MOUSE_LEAVE: { + if (GetViewportForWindowId(event->window.windowID) == NULL) + return false; + bd->mouse_pending_leave_frame = ImGui::GetFrameCount() + 1; + bd->lastCursorMoveTime = bd->time; + return true; + } + case SDL_EVENT_WINDOW_FOCUS_GAINED: + case SDL_EVENT_WINDOW_FOCUS_LOST: { + if (GetViewportForWindowId(event->window.windowID) == NULL) + return false; + io.AddFocusEvent(event->type == SDL_EVENT_WINDOW_FOCUS_GAINED); + return true; + } + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: { + bd->want_update_gamepads_list = true; + return true; + } + } + return false; +} + +static void SetupPlatformHandles(ImGuiViewport* viewport, SDL_Window* window) { + viewport->PlatformHandle = (void*)(intptr_t)SDL_GetWindowID(window); + viewport->PlatformHandleRaw = nullptr; +#if defined(_WIN32) && !defined(__WINRT__) + viewport->PlatformHandleRaw = (HWND)SDL_GetPointerProperty( + SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); +#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA) + viewport->PlatformHandleRaw = SDL_GetPointerProperty( + SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr); +#endif +} + +bool Init(SDL_Window* window) { + ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); + IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); + + // Setup backend capabilities flags + SdlData* bd = IM_NEW(SdlData)(); + io.BackendPlatformUserData = (void*)bd; + io.BackendPlatformName = "imgui_impl_sdl3_shadps4"; + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests + // (optional, rarely used) + + bd->window = window; + bd->window_id = SDL_GetWindowID(window); + + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_SetClipboardTextFn = SetClipboardText; + platform_io.Platform_GetClipboardTextFn = GetClipboardText; + platform_io.Platform_SetImeDataFn = PlatformSetImeData; + + // Gamepad handling + bd->gamepad_mode = ImGui_ImplSDL3_GamepadMode_AutoFirst; + bd->want_update_gamepads_list = true; + + // Load mouse cursors +#define CURSOR(left, right) \ + bd->mouse_cursors[ImGuiMouseCursor_##left] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_##right) + CURSOR(Arrow, DEFAULT); + CURSOR(TextInput, TEXT); + CURSOR(ResizeAll, MOVE); + CURSOR(ResizeNS, NS_RESIZE); + CURSOR(ResizeEW, EW_RESIZE); + CURSOR(ResizeNESW, NESW_RESIZE); + CURSOR(ResizeNWSE, NWSE_RESIZE); + CURSOR(Hand, POINTER); + CURSOR(NotAllowed, NOT_ALLOWED); +#undef CURSOR + + // Set platform dependent data in viewport + // Our mouse update function expect PlatformHandle to be filled for the main viewport + ImGuiViewport* main_viewport = ImGui::GetMainViewport(); + SetupPlatformHandles(main_viewport, window); + + // From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't + // emit the event. Without this, when clicking to gain focus, our widgets wouldn't activate even + // though they showed as hovered. (This is unfortunately a global SDL setting, so enabling it + // might have a side-effect on your application. It is unlikely to make a difference, but if + // your app absolutely needs to ignore the initial on-focus click: you can ignore + // SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED) +#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH + SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); +#endif + + // From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows + // (see #5710) +#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE + SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0"); +#endif + + return true; +} + +static void CloseGamepads(); + +void Shutdown() { + SdlData* bd = GetBackendData(); + IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + + if (bd->clipboard_text_data) { + SDL_free((void*)bd->clipboard_text_data); + } + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) + SDL_DestroyCursor(bd->mouse_cursors[cursor_n]); + CloseGamepads(); + + io.BackendPlatformName = nullptr; + io.BackendPlatformUserData = nullptr; + io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | + ImGuiBackendFlags_HasGamepad); + IM_DELETE(bd); +} + +static void UpdateMouseData() { + SdlData* bd = GetBackendData(); + ImGuiIO& io = ImGui::GetIO(); + + // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused + // (below) + // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries + // shouldn't e.g. trigger other operations outside + SDL_CaptureMouse((bd->mouse_buttons_down != 0) ? true : false); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); + const bool is_app_focused = (bd->window == focused_window); + + if (is_app_focused) { + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when + // ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + SDL_WarpMouseInWindow(bd->window, io.MousePos.x, io.MousePos.y); + + // (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION + // already provides this when hovered or captured) + if (bd->mouse_buttons_down == 0) { + // Single-viewport mode: mouse position in client window coordinates (io.MousePos is + // (0,0) when the mouse is on the upper-left corner of the app window) + float mouse_x_global, mouse_y_global; + int window_x, window_y; + SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); + SDL_GetWindowPosition(focused_window, &window_x, &window_y); + mouse_x_global -= (float)window_x; + mouse_y_global -= (float)window_y; + io.AddMousePosEvent(mouse_x_global, mouse_y_global); + // SDL_EVENT_MOUSE_MOTION isn't triggered before the first frame is rendered + // force update the prev_cursor coords + if (mouse_x_global != bd->prev_mouse_pos.x || mouse_y_global != bd->prev_mouse_pos.y && + bd->prev_mouse_pos.y == 0 && + bd->prev_mouse_pos.x == 0) { + bd->prev_mouse_pos.x = mouse_x_global; + bd->prev_mouse_pos.y = mouse_y_global; + bd->lastCursorMoveTime = bd->time; + } + } + } +} + +static void UpdateMouseCursor() { + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) + return; + SdlData* bd = GetBackendData(); + + s16 cursorState = Config::getCursorState(); + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None || + cursorState == Config::HideCursorState::Always) { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + SDL_HideCursor(); + + } else if (cursorState == Config::HideCursorState::Idle && + bd->time - bd->lastCursorMoveTime >= + Config::getCursorHideTimeout() * SDL_GetPerformanceFrequency()) { + + bool wasCursorVisible = SDL_CursorVisible(); + SDL_HideCursor(); + + if (wasCursorVisible) { + SDL_WarpMouseInWindow(SDL_GetKeyboardFocus(), bd->prev_mouse_pos.x, + bd->prev_mouse_pos.y); // Force refresh the cursor state + } + + } else { + // Show OS mouse cursor + SDL_Cursor* expected_cursor = bd->mouse_cursors[imgui_cursor] + ? bd->mouse_cursors[imgui_cursor] + : bd->mouse_cursors[ImGuiMouseCursor_Arrow]; + if (bd->mouse_last_cursor != expected_cursor) { + SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113) + bd->mouse_last_cursor = expected_cursor; + } + SDL_ShowCursor(); + } +} + +static void CloseGamepads() { + SdlData* bd = GetBackendData(); + if (bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) + for (SDL_Gamepad* gamepad : bd->gamepads) + SDL_CloseGamepad(gamepad); + bd->gamepads.resize(0); +} + +void SetGamepadMode(GamepadMode mode, SDL_Gamepad** manual_gamepads_array, + int manual_gamepads_count) { + SdlData* bd = GetBackendData(); + CloseGamepads(); + if (mode == ImGui_ImplSDL3_GamepadMode_Manual) { + IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0); + for (int n = 0; n < manual_gamepads_count; n++) + bd->gamepads.push_back(manual_gamepads_array[n]); + } else { + IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0); + bd->want_update_gamepads_list = true; + } + bd->gamepad_mode = mode; +} + +static void UpdateGamepadButton(SdlData* bd, ImGuiIO& io, ImGuiKey key, + SDL_GamepadButton button_no) { + bool merged_value = false; + for (SDL_Gamepad* gamepad : bd->gamepads) + merged_value |= SDL_GetGamepadButton(gamepad, button_no) != 0; + io.AddKeyEvent(key, merged_value); +} + +static inline float Saturate(float v) { + return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; +} +static void UpdateGamepadAnalog(SdlData* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadAxis axis_no, + float v0, float v1) { + float merged_value = 0.0f; + for (SDL_Gamepad* gamepad : bd->gamepads) { + float vn = Saturate((float)(SDL_GetGamepadAxis(gamepad, axis_no) - v0) / (float)(v1 - v0)); + if (merged_value < vn) + merged_value = vn; + } + io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value); +} + +static void UpdateGamepads() { + ImGuiIO& io = ImGui::GetIO(); + SdlData* bd = GetBackendData(); + + // Update list of gamepads to use + if (bd->want_update_gamepads_list && bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) { + CloseGamepads(); + int sdl_gamepads_count = 0; + const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); + for (int n = 0; n < sdl_gamepads_count; n++) + if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) { + bd->gamepads.push_back(gamepad); + if (bd->gamepad_mode == ImGui_ImplSDL3_GamepadMode_AutoFirst) + break; + } + bd->want_update_gamepads_list = false; + } + + // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. + if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) + return; + io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; + if (bd->gamepads.Size == 0) + return; + io.BackendFlags |= ImGuiBackendFlags_HasGamepad; + + // Update gamepad inputs + const int thumb_dead_zone = 8000; // SDL_gamepad.h suggests using this value. + UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK); + /*UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, + SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square*/ // Disable to avoid menu toggle + UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, + SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle + UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, + SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle + UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, + SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross + UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK); + UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, + -thumb_dead_zone, -32768); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, + +thumb_dead_zone, +32767); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, + -32768); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, + +thumb_dead_zone, +32767); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, + -thumb_dead_zone, -32768); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, + +thumb_dead_zone, +32767); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, + -32768); + UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, + +thumb_dead_zone, +32767); +} + +void NewFrame() { + SdlData* bd = GetBackendData(); + IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + + // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) + // (Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. Happens + // in VMs and Emscripten, see #6189, #6114, #3644) + static Uint64 frequency = SDL_GetPerformanceFrequency(); + Uint64 current_time = SDL_GetPerformanceCounter(); + if (current_time <= bd->time) + current_time = bd->time + 1; + io.DeltaTime = bd->time > 0 ? (float)((double)(current_time - bd->time) / (double)frequency) + : (float)(1.0f / 60.0f); + bd->time = current_time; + + if (bd->mouse_pending_leave_frame && bd->mouse_pending_leave_frame >= ImGui::GetFrameCount() && + bd->mouse_buttons_down == 0) { + bd->mouse_window_id = 0; + bd->mouse_pending_leave_frame = 0; + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + } + + UpdateMouseData(); + UpdateMouseCursor(); + + // Update game controllers (if enabled and available) + UpdateGamepads(); +} + +void OnResize() { + SdlData* bd = GetBackendData(); + ImGuiIO& io = ImGui::GetIO(); + + int w, h; + int display_w, display_h; + SDL_GetWindowSize(bd->window, &w, &h); + if (SDL_GetWindowFlags(bd->window) & SDL_WINDOW_MINIMIZED) { + w = h = 0; + } + SDL_GetWindowSizeInPixels(bd->window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + if (w > 0 && h > 0) { + io.DisplayFramebufferScale = {(float)display_w / (float)w, (float)display_h / (float)h}; + } +} + +} // namespace ImGui::Sdl diff --git a/src/imgui/renderer/imgui_impl_sdl3.h b/src/imgui/renderer/imgui_impl_sdl3.h new file mode 100644 index 000000000..59b1a6856 --- /dev/null +++ b/src/imgui/renderer/imgui_impl_sdl3.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Based on imgui_impl_sdl3.h from Dear ImGui repository + +#pragma once + +struct SDL_Window; +struct SDL_Renderer; +struct SDL_Gamepad; +typedef union SDL_Event SDL_Event; + +namespace ImGui::Sdl { + +bool Init(SDL_Window* window); +void Shutdown(); +void NewFrame(); +bool ProcessEvent(const SDL_Event* event); +void OnResize(); + +// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. +// You may override this. When using manual mode, caller is responsible for opening/closing gamepad. +enum GamepadMode { + ImGui_ImplSDL3_GamepadMode_AutoFirst, + ImGui_ImplSDL3_GamepadMode_AutoAll, + ImGui_ImplSDL3_GamepadMode_Manual +}; +void SetGamepadMode(GamepadMode mode, SDL_Gamepad** manual_gamepads_array = NULL, + int manual_gamepads_count = -1); + +}; // namespace ImGui::Sdl diff --git a/src/imgui/renderer/imgui_impl_vulkan.cpp b/src/imgui/renderer/imgui_impl_vulkan.cpp new file mode 100644 index 000000000..7f7ade2a5 --- /dev/null +++ b/src/imgui/renderer/imgui_impl_vulkan.cpp @@ -0,0 +1,1269 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Based on imgui_impl_vulkan.cpp from Dear ImGui repository + +#include +#include + +#include + +#include "imgui_impl_vulkan.h" + +#ifndef IM_MAX +#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B)) +#endif + +#define IDX_SIZE sizeof(ImDrawIdx) + +namespace ImGui::Vulkan { + +struct RenderBuffer { + vk::DeviceMemory buffer_memory{}; + vk::DeviceSize buffer_size{}; + vk::Buffer buffer{}; +}; + +// Reusable buffers used for rendering 1 current in-flight frame, for RenderDrawData() +struct FrameRenderBuffers { + RenderBuffer vertex; + RenderBuffer index; +}; + +// Each viewport will hold 1 WindowRenderBuffers +struct WindowRenderBuffers { + uint32_t index{}; + uint32_t count{}; + std::vector frame_render_buffers{}; +}; + +// Vulkan data +struct VkData { + const InitInfo init_info; + vk::DeviceSize buffer_memory_alignment = 256; + vk::PipelineCreateFlags pipeline_create_flags{}; + vk::DescriptorPool descriptor_pool{}; + vk::DescriptorSetLayout descriptor_set_layout{}; + vk::PipelineLayout pipeline_layout{}; + vk::Pipeline pipeline{}; + vk::ShaderModule shader_module_vert{}; + vk::ShaderModule shader_module_frag{}; + + std::mutex command_pool_mutex; + vk::CommandPool command_pool{}; + vk::Sampler simple_sampler{}; + + // Font data + vk::DeviceMemory font_memory{}; + vk::Image font_image{}; + vk::ImageView font_view{}; + vk::DescriptorSet font_descriptor_set{}; + vk::CommandBuffer font_command_buffer{}; + + // Render buffers + WindowRenderBuffers render_buffers{}; + + VkData(const InitInfo init_info) : init_info(init_info) { + render_buffers.count = init_info.image_count; + render_buffers.frame_render_buffers.resize(render_buffers.count); + } +}; + +//----------------------------------------------------------------------------- +// SHADERS +//----------------------------------------------------------------------------- + +// backends/vulkan/glsl_shader.vert, compiled with: +// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert +/* +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; +layout(push_constant) uniform uPushConstant { vec2 uScale; vec2 uTranslate; } pc; + +out gl_PerVertex { vec4 gl_Position; }; +layout(location = 0) out struct { vec4 Color; vec2 UV; } Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1); +} +*/ +static uint32_t glsl_shader_vert_spv[] = { + 0x07230203, 0x00010000, 0x00080001, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, + 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, + 0x000a000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x0000000f, 0x00000015, + 0x0000001b, 0x0000001c, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, + 0x00000000, 0x00030005, 0x00000009, 0x00000000, 0x00050006, 0x00000009, 0x00000000, 0x6f6c6f43, + 0x00000072, 0x00040006, 0x00000009, 0x00000001, 0x00005655, 0x00030005, 0x0000000b, 0x0074754f, + 0x00040005, 0x0000000f, 0x6c6f4361, 0x0000726f, 0x00030005, 0x00000015, 0x00565561, 0x00060005, + 0x00000019, 0x505f6c67, 0x65567265, 0x78657472, 0x00000000, 0x00060006, 0x00000019, 0x00000000, + 0x505f6c67, 0x7469736f, 0x006e6f69, 0x00030005, 0x0000001b, 0x00000000, 0x00040005, 0x0000001c, + 0x736f5061, 0x00000000, 0x00060005, 0x0000001e, 0x73755075, 0x6e6f4368, 0x6e617473, 0x00000074, + 0x00050006, 0x0000001e, 0x00000000, 0x61635375, 0x0000656c, 0x00060006, 0x0000001e, 0x00000001, + 0x61725475, 0x616c736e, 0x00006574, 0x00030005, 0x00000020, 0x00006370, 0x00040047, 0x0000000b, + 0x0000001e, 0x00000000, 0x00040047, 0x0000000f, 0x0000001e, 0x00000002, 0x00040047, 0x00000015, + 0x0000001e, 0x00000001, 0x00050048, 0x00000019, 0x00000000, 0x0000000b, 0x00000000, 0x00030047, + 0x00000019, 0x00000002, 0x00040047, 0x0000001c, 0x0000001e, 0x00000000, 0x00050048, 0x0000001e, + 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000008, + 0x00030047, 0x0000001e, 0x00000002, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, + 0x00030016, 0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040017, + 0x00000008, 0x00000006, 0x00000002, 0x0004001e, 0x00000009, 0x00000007, 0x00000008, 0x00040020, + 0x0000000a, 0x00000003, 0x00000009, 0x0004003b, 0x0000000a, 0x0000000b, 0x00000003, 0x00040015, + 0x0000000c, 0x00000020, 0x00000001, 0x0004002b, 0x0000000c, 0x0000000d, 0x00000000, 0x00040020, + 0x0000000e, 0x00000001, 0x00000007, 0x0004003b, 0x0000000e, 0x0000000f, 0x00000001, 0x00040020, + 0x00000011, 0x00000003, 0x00000007, 0x0004002b, 0x0000000c, 0x00000013, 0x00000001, 0x00040020, + 0x00000014, 0x00000001, 0x00000008, 0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x00040020, + 0x00000017, 0x00000003, 0x00000008, 0x0003001e, 0x00000019, 0x00000007, 0x00040020, 0x0000001a, + 0x00000003, 0x00000019, 0x0004003b, 0x0000001a, 0x0000001b, 0x00000003, 0x0004003b, 0x00000014, + 0x0000001c, 0x00000001, 0x0004001e, 0x0000001e, 0x00000008, 0x00000008, 0x00040020, 0x0000001f, + 0x00000009, 0x0000001e, 0x0004003b, 0x0000001f, 0x00000020, 0x00000009, 0x00040020, 0x00000021, + 0x00000009, 0x00000008, 0x0004002b, 0x00000006, 0x00000028, 0x00000000, 0x0004002b, 0x00000006, + 0x00000029, 0x3f800000, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, + 0x00000005, 0x0004003d, 0x00000007, 0x00000010, 0x0000000f, 0x00050041, 0x00000011, 0x00000012, + 0x0000000b, 0x0000000d, 0x0003003e, 0x00000012, 0x00000010, 0x0004003d, 0x00000008, 0x00000016, + 0x00000015, 0x00050041, 0x00000017, 0x00000018, 0x0000000b, 0x00000013, 0x0003003e, 0x00000018, + 0x00000016, 0x0004003d, 0x00000008, 0x0000001d, 0x0000001c, 0x00050041, 0x00000021, 0x00000022, + 0x00000020, 0x0000000d, 0x0004003d, 0x00000008, 0x00000023, 0x00000022, 0x00050085, 0x00000008, + 0x00000024, 0x0000001d, 0x00000023, 0x00050041, 0x00000021, 0x00000025, 0x00000020, 0x00000013, + 0x0004003d, 0x00000008, 0x00000026, 0x00000025, 0x00050081, 0x00000008, 0x00000027, 0x00000024, + 0x00000026, 0x00050051, 0x00000006, 0x0000002a, 0x00000027, 0x00000000, 0x00050051, 0x00000006, + 0x0000002b, 0x00000027, 0x00000001, 0x00070050, 0x00000007, 0x0000002c, 0x0000002a, 0x0000002b, + 0x00000028, 0x00000029, 0x00050041, 0x00000011, 0x0000002d, 0x0000001b, 0x0000000d, 0x0003003e, + 0x0000002d, 0x0000002c, 0x000100fd, 0x00010038}; + +// backends/vulkan/glsl_shader.frag, compiled with: +// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag +/* +#version 450 core +layout(location = 0) out vec4 fColor; +layout(set=0, binding=0) uniform sampler2D sTexture; +layout(location = 0) in struct { vec4 Color; vec2 UV; } In; +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} +*/ +static uint32_t glsl_shader_frag_spv[] = { + 0x07230203, 0x00010000, 0x00080001, 0x0000001e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, + 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, + 0x0007000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x0000000d, 0x00030010, + 0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, + 0x00000000, 0x00040005, 0x00000009, 0x6c6f4366, 0x0000726f, 0x00030005, 0x0000000b, 0x00000000, + 0x00050006, 0x0000000b, 0x00000000, 0x6f6c6f43, 0x00000072, 0x00040006, 0x0000000b, 0x00000001, + 0x00005655, 0x00030005, 0x0000000d, 0x00006e49, 0x00050005, 0x00000016, 0x78655473, 0x65727574, + 0x00000000, 0x00040047, 0x00000009, 0x0000001e, 0x00000000, 0x00040047, 0x0000000d, 0x0000001e, + 0x00000000, 0x00040047, 0x00000016, 0x00000022, 0x00000000, 0x00040047, 0x00000016, 0x00000021, + 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, + 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000003, + 0x00000007, 0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00040017, 0x0000000a, 0x00000006, + 0x00000002, 0x0004001e, 0x0000000b, 0x00000007, 0x0000000a, 0x00040020, 0x0000000c, 0x00000001, + 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000001, 0x00040015, 0x0000000e, 0x00000020, + 0x00000001, 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000, 0x00040020, 0x00000010, 0x00000001, + 0x00000007, 0x00090019, 0x00000013, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x0003001b, 0x00000014, 0x00000013, 0x00040020, 0x00000015, 0x00000000, + 0x00000014, 0x0004003b, 0x00000015, 0x00000016, 0x00000000, 0x0004002b, 0x0000000e, 0x00000018, + 0x00000001, 0x00040020, 0x00000019, 0x00000001, 0x0000000a, 0x00050036, 0x00000002, 0x00000004, + 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x00050041, 0x00000010, 0x00000011, 0x0000000d, + 0x0000000f, 0x0004003d, 0x00000007, 0x00000012, 0x00000011, 0x0004003d, 0x00000014, 0x00000017, + 0x00000016, 0x00050041, 0x00000019, 0x0000001a, 0x0000000d, 0x00000018, 0x0004003d, 0x0000000a, + 0x0000001b, 0x0000001a, 0x00050057, 0x00000007, 0x0000001c, 0x00000017, 0x0000001b, 0x00050085, + 0x00000007, 0x0000001d, 0x00000012, 0x0000001c, 0x0003003e, 0x00000009, 0x0000001d, 0x000100fd, + 0x00010038}; + +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui +// contexts It is STRONGLY preferred that you use docking branch with multi-viewports (== single +// Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static VkData* GetBackendData() { + return ImGui::GetCurrentContext() ? (VkData*)ImGui::GetIO().BackendRendererUserData : nullptr; +} + +static uint32_t FindMemoryType(vk::MemoryPropertyFlags properties, uint32_t type_bits) { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + const auto prop = v.physical_device.getMemoryProperties(); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1 << i)) + return i; + return 0xFFFFFFFF; // Unable to find memoryType +} + +template +static T CheckVkResult(vk::ResultValue res) { + if (res.result == vk::Result::eSuccess) { + return res.value; + } + const VkData* bd = GetBackendData(); + if (!bd) { + return res.value; + } + const InitInfo& v = bd->init_info; + if (v.check_vk_result_fn) { + v.check_vk_result_fn(res.result); + } + return res.value; +} + +static void CheckVkErr(vk::Result res) { + if (res == vk::Result::eSuccess) { + return; + } + const VkData* bd = GetBackendData(); + if (!bd) { + return; + } + const InitInfo& v = bd->init_info; + if (v.check_vk_result_fn) { + v.check_vk_result_fn(res); + } +} + +// Same as IM_MEMALIGN(). 'alignment' must be a power of two. +static inline vk::DeviceSize AlignBufferSize(vk::DeviceSize size, vk::DeviceSize alignment) { + return (size + alignment - 1) & ~(alignment - 1); +} + +void UploadTextureData::Upload() { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + vk::SubmitInfo submit_info{ + .commandBufferCount = 1, + .pCommandBuffers = &command_buffer, + }; + CheckVkErr(v.queue.submit({submit_info})); + CheckVkErr(v.queue.waitIdle()); + + v.device.destroyBuffer(upload_buffer, v.allocator); + v.device.freeMemory(upload_buffer_memory, v.allocator); + { + std::unique_lock lk(bd->command_pool_mutex); + v.device.freeCommandBuffers(bd->command_pool, {command_buffer}); + } + upload_buffer = VK_NULL_HANDLE; + upload_buffer_memory = VK_NULL_HANDLE; +} + +void UploadTextureData::Destroy() { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + CheckVkErr(v.device.waitIdle()); + RemoveTexture(descriptor_set); + descriptor_set = VK_NULL_HANDLE; + + v.device.destroyImageView(image_view, v.allocator); + image_view = VK_NULL_HANDLE; + v.device.destroyImage(image, v.allocator); + image = VK_NULL_HANDLE; + v.device.freeMemory(image_memory, v.allocator); + image_memory = VK_NULL_HANDLE; +} + +// Register a texture +vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout, + vk::Sampler sampler) { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + if (sampler == VK_NULL_HANDLE) { + sampler = bd->simple_sampler; + } + + // Create Descriptor Set: + vk::DescriptorSet descriptor_set; + { + vk::DescriptorSetAllocateInfo alloc_info{ + .descriptorPool = bd->descriptor_pool, + .descriptorSetCount = 1, + .pSetLayouts = &bd->descriptor_set_layout, + }; + descriptor_set = CheckVkResult(v.device.allocateDescriptorSets(alloc_info)).front(); + } + + // Update the Descriptor Set: + { + vk::DescriptorImageInfo desc_image[1]{ + { + .sampler = sampler, + .imageView = image_view, + .imageLayout = image_layout, + }, + }; + vk::WriteDescriptorSet write_desc[1]{ + { + .dstSet = descriptor_set, + .descriptorCount = 1, + .descriptorType = vk::DescriptorType::eCombinedImageSampler, + .pImageInfo = desc_image, + }, + }; + v.device.updateDescriptorSets({write_desc}, {}); + } + return descriptor_set; +} +UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height, + size_t size) { + ImGuiIO& io = GetIO(); + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + UploadTextureData info{}; + { + std::unique_lock lk(bd->command_pool_mutex); + info.command_buffer = + CheckVkResult(v.device.allocateCommandBuffers(vk::CommandBufferAllocateInfo{ + .commandPool = bd->command_pool, + .commandBufferCount = 1, + })) + .front(); + CheckVkErr(info.command_buffer.begin(vk::CommandBufferBeginInfo{ + .flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit, + })); + } + + // Create Image + { + vk::ImageCreateInfo image_info{ + .imageType = vk::ImageType::e2D, + .format = format, + .extent{ + .width = width, + .height = height, + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .samples = vk::SampleCountFlagBits::e1, + .tiling = vk::ImageTiling::eOptimal, + .usage = vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, + .sharingMode = vk::SharingMode::eExclusive, + .initialLayout = vk::ImageLayout::eUndefined, + }; + info.image = CheckVkResult(v.device.createImage(image_info, v.allocator)); + auto req = v.device.getImageMemoryRequirements(info.image); + vk::MemoryAllocateInfo alloc_info{ + .allocationSize = IM_MAX(v.min_allocation_size, req.size), + .memoryTypeIndex = + FindMemoryType(vk::MemoryPropertyFlagBits::eDeviceLocal, req.memoryTypeBits), + }; + info.image_memory = CheckVkResult(v.device.allocateMemory(alloc_info, v.allocator)); + CheckVkErr(v.device.bindImageMemory(info.image, info.image_memory, 0)); + } + + // Create Image View + { + vk::ImageViewCreateInfo view_info{ + .image = info.image, + .viewType = vk::ImageViewType::e2D, + .format = format, + .subresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .layerCount = 1, + }, + }; + info.image_view = CheckVkResult(v.device.createImageView(view_info, v.allocator)); + } + + // Create descriptor set (ImTextureID) + info.descriptor_set = AddTexture(info.image_view, vk::ImageLayout::eShaderReadOnlyOptimal); + + // Create Upload Buffer + { + vk::BufferCreateInfo buffer_info{ + .size = size, + .usage = vk::BufferUsageFlagBits::eTransferSrc, + .sharingMode = vk::SharingMode::eExclusive, + }; + info.upload_buffer = CheckVkResult(v.device.createBuffer(buffer_info, v.allocator)); + auto req = v.device.getBufferMemoryRequirements(info.upload_buffer); + auto alignemtn = IM_MAX(bd->buffer_memory_alignment, req.alignment); + vk::MemoryAllocateInfo alloc_info{ + .allocationSize = IM_MAX(v.min_allocation_size, req.size), + .memoryTypeIndex = + FindMemoryType(vk::MemoryPropertyFlagBits::eHostVisible, req.memoryTypeBits), + }; + info.upload_buffer_memory = CheckVkResult(v.device.allocateMemory(alloc_info, v.allocator)); + CheckVkErr(v.device.bindBufferMemory(info.upload_buffer, info.upload_buffer_memory, 0)); + } + + // Upload to Buffer + { + char* map = (char*)CheckVkResult(v.device.mapMemory(info.upload_buffer_memory, 0, size)); + memcpy(map, data, size); + vk::MappedMemoryRange range[1]{ + { + .memory = info.upload_buffer_memory, + .size = size, + }, + }; + CheckVkErr(v.device.flushMappedMemoryRanges(range)); + v.device.unmapMemory(info.upload_buffer_memory); + } + + // Copy to Image + { + vk::ImageMemoryBarrier copy_barrier[1]{ + { + .dstAccessMask = vk::AccessFlagBits::eTransferWrite, + .oldLayout = vk::ImageLayout::eUndefined, + .newLayout = vk::ImageLayout::eTransferDstOptimal, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = info.image, + .subresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .layerCount = 1, + }, + }, + }; + info.command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eHost, + vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, + {copy_barrier}); + + vk::BufferImageCopy region{ + .imageSubresource{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .layerCount = 1, + }, + .imageExtent{ + .width = width, + .height = height, + .depth = 1, + }, + }; + info.command_buffer.copyBufferToImage(info.upload_buffer, info.image, + vk::ImageLayout::eTransferDstOptimal, {region}); + + vk::ImageMemoryBarrier use_barrier[1]{{ + .srcAccessMask = vk::AccessFlagBits::eTransferWrite, + .dstAccessMask = vk::AccessFlagBits::eShaderRead, + .oldLayout = vk::ImageLayout::eTransferDstOptimal, + .newLayout = vk::ImageLayout::eShaderReadOnlyOptimal, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = info.image, + .subresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .layerCount = 1, + }, + }}; + info.command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, + vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, + {use_barrier}); + } + + CheckVkErr(info.command_buffer.end()); + + return info; +} + +void RemoveTexture(vk::DescriptorSet descriptor_set) { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + v.device.freeDescriptorSets(bd->descriptor_pool, {descriptor_set}); +} + +static void CreateOrResizeBuffer(RenderBuffer& rb, size_t new_size, vk::BufferUsageFlagBits usage) { + VkData* bd = GetBackendData(); + IM_ASSERT(bd != nullptr); + const InitInfo& v = bd->init_info; + if (rb.buffer != VK_NULL_HANDLE) { + v.device.destroyBuffer(rb.buffer, v.allocator); + } + if (rb.buffer_memory != VK_NULL_HANDLE) { + v.device.freeMemory(rb.buffer_memory, v.allocator); + } + + const vk::DeviceSize buffer_size_aligned = + AlignBufferSize(IM_MAX(v.min_allocation_size, new_size), bd->buffer_memory_alignment); + vk::BufferCreateInfo buffer_info{ + .size = buffer_size_aligned, + .usage = usage, + .sharingMode = vk::SharingMode::eExclusive, + }; + rb.buffer = CheckVkResult(v.device.createBuffer(buffer_info, v.allocator)); + + const vk::MemoryRequirements req = v.device.getBufferMemoryRequirements(rb.buffer); + bd->buffer_memory_alignment = IM_MAX(bd->buffer_memory_alignment, req.alignment); + vk::MemoryAllocateInfo alloc_info{ + .allocationSize = req.size, + .memoryTypeIndex = + FindMemoryType(vk::MemoryPropertyFlagBits::eHostVisible, req.memoryTypeBits), + }; + rb.buffer_memory = CheckVkResult(v.device.allocateMemory(alloc_info, v.allocator)); + + CheckVkErr(v.device.bindBufferMemory(rb.buffer, rb.buffer_memory, 0)); + rb.buffer_size = buffer_size_aligned; +} + +static void SetupRenderState(ImDrawData& draw_data, vk::Pipeline pipeline, vk::CommandBuffer cmdbuf, + FrameRenderBuffers& frb, int fb_width, int fb_height) { + VkData* bd = GetBackendData(); + + // Bind pipeline: + cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); + + // Bind Vertex And Index Buffer: + if (draw_data.TotalVtxCount > 0) { + vk::Buffer vertex_buffers[1] = {frb.vertex.buffer}; + vk::DeviceSize vertex_offset[1] = {0}; + cmdbuf.bindVertexBuffers(0, {vertex_buffers}, vertex_offset); + cmdbuf.bindIndexBuffer(frb.index.buffer, 0, + IDX_SIZE == 2 ? vk::IndexType::eUint16 : vk::IndexType::eUint32); + } + + // Setup viewport: + { + vk::Viewport viewport{ + .x = 0, + .y = 0, + .width = (float)fb_width, + .height = (float)fb_height, + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + cmdbuf.setViewport(0, {viewport}); + } + + // Setup scale and translation: + // Our visible imgui space lies from draw_data->DisplayPps (top left) to + // draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single + // viewport apps. + { + float scale[2]; + scale[0] = 2.0f / draw_data.DisplaySize.x; + scale[1] = 2.0f / draw_data.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f - draw_data.DisplayPos.x * scale[0]; + translate[1] = -1.0f - draw_data.DisplayPos.y * scale[1]; + cmdbuf.pushConstants(bd->pipeline_layout, vk::ShaderStageFlagBits::eVertex, + sizeof(float) * 0, sizeof(float) * 2, scale); + cmdbuf.pushConstants(bd->pipeline_layout, vk::ShaderStageFlagBits::eVertex, + sizeof(float) * 2, sizeof(float) * 2, translate); + } +} + +// Render function +void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer, + vk::Pipeline pipeline) { + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != + // framebuffer coordinates) + int fb_width = (int)(draw_data.DisplaySize.x * draw_data.FramebufferScale.x); + int fb_height = (int)(draw_data.DisplaySize.y * draw_data.FramebufferScale.y); + if (fb_width <= 0 || fb_height <= 0) { + return; + } + + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + if (pipeline == VK_NULL_HANDLE) { + pipeline = bd->pipeline; + } + + // Allocate array to store enough vertex/index buffers + WindowRenderBuffers& wrb = bd->render_buffers; + wrb.index = (wrb.index + 1) % wrb.count; + FrameRenderBuffers& frb = wrb.frame_render_buffers[wrb.index]; + + if (draw_data.TotalVtxCount > 0) { + // Create or resize the vertex/index buffers + size_t vertex_size = AlignBufferSize(draw_data.TotalVtxCount * sizeof(ImDrawVert), + bd->buffer_memory_alignment); + size_t index_size = + AlignBufferSize(draw_data.TotalIdxCount * IDX_SIZE, bd->buffer_memory_alignment); + if (frb.vertex.buffer == VK_NULL_HANDLE || frb.vertex.buffer_size < vertex_size) { + CreateOrResizeBuffer(frb.vertex, vertex_size, vk::BufferUsageFlagBits::eVertexBuffer); + } + if (frb.index.buffer == VK_NULL_HANDLE || frb.index.buffer_size < index_size) { + CreateOrResizeBuffer(frb.index, index_size, vk::BufferUsageFlagBits::eIndexBuffer); + } + + // Upload vertex/index data into a single contiguous GPU buffer + ImDrawVert* vtx_dst = nullptr; + ImDrawIdx* idx_dst = nullptr; + vtx_dst = (ImDrawVert*)CheckVkResult( + v.device.mapMemory(frb.vertex.buffer_memory, 0, vertex_size, vk::MemoryMapFlags{})); + idx_dst = (ImDrawIdx*)CheckVkResult( + v.device.mapMemory(frb.index.buffer_memory, 0, index_size, vk::MemoryMapFlags{})); + for (int n = 0; n < draw_data.CmdListsCount; n++) { + const ImDrawList* cmd_list = draw_data.CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, + cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * IDX_SIZE); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + vk::MappedMemoryRange range[2]{ + { + .memory = frb.vertex.buffer_memory, + .size = VK_WHOLE_SIZE, + }, + { + .memory = frb.index.buffer_memory, + .size = VK_WHOLE_SIZE, + }, + }; + CheckVkErr(v.device.flushMappedMemoryRanges({range})); + v.device.unmapMemory(frb.vertex.buffer_memory); + v.device.unmapMemory(frb.index.buffer_memory); + } + + // Setup desired Vulkan state + SetupRenderState(draw_data, pipeline, command_buffer, frb, fb_width, fb_height); + + // Will project scissor/clipping rectangles into framebuffer space + + // (0,0) unless using multi-viewports + ImVec2 clip_off = draw_data.DisplayPos; + // (1,1) unless using retina display which are often (2,2) + ImVec2 clip_scale = draw_data.FramebufferScale; + + // Render command lists + // (Because we merged all buffers into a single one, we maintain our own offset into them) + int global_vtx_offset = 0; + int global_idx_offset = 0; + for (int n = 0; n < draw_data.CmdListsCount; n++) { + const ImDrawList* cmd_list = draw_data.CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != nullptr) { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to + // request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) { + SetupRenderState(draw_data, pipeline, command_buffer, frb, fb_width, fb_height); + } else { + pcmd->UserCallback(cmd_list, pcmd); + } + } else { + // Project scissor/clipping rectangles into framebuffer space + ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, + (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); + ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, + (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); + + // Clamp to viewport as vk::CmdSetScissor() won't accept values that are off bounds + if (clip_min.x < 0.0f) { + clip_min.x = 0.0f; + } + if (clip_min.y < 0.0f) { + clip_min.y = 0.0f; + } + if (clip_max.x > fb_width) { + clip_max.x = (float)fb_width; + } + if (clip_max.y > fb_height) { + clip_max.y = (float)fb_height; + } + if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) + continue; + + // Apply scissor/clipping rectangle + vk::Rect2D scissor{ + .offset{ + .x = (int32_t)(clip_min.x), + .y = (int32_t)(clip_min.y), + }, + .extent{ + .width = (uint32_t)(clip_max.x - clip_min.x), + .height = (uint32_t)(clip_max.y - clip_min.y), + }, + }; + command_buffer.setScissor(0, 1, &scissor); + + // Bind DescriptorSet with font or user texture + vk::DescriptorSet desc_set[1]{(VkDescriptorSet)pcmd->TextureId}; + if (sizeof(ImTextureID) < sizeof(ImU64)) { + // We don't support texture switches if ImTextureID hasn't been redefined to be + // 64-bit. Do a flaky check that other textures haven't been used. + IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->font_descriptor_set); + desc_set[0] = bd->font_descriptor_set; + } + command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, + bd->pipeline_layout, 0, {desc_set}, {}); + + // Draw + command_buffer.drawIndexed(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, + pcmd->VtxOffset + global_vtx_offset, 0); + } + } + global_idx_offset += cmd_list->IdxBuffer.Size; + global_vtx_offset += cmd_list->VtxBuffer.Size; + } + // vk::Rect2D scissor = {{0, 0}, {(uint32_t)fb_width, (uint32_t)fb_height}}; + // command_buffer.setScissor(0, 1, &scissor); +} + +static void DestroyFontsTexture(); + +static bool CreateFontsTexture() { + ImGuiIO& io = ImGui::GetIO(); + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + // Destroy existing texture (if any) + if (bd->font_view || bd->font_image || bd->font_memory || bd->font_descriptor_set) { + CheckVkErr(v.queue.waitIdle()); + DestroyFontsTexture(); + } + + // Create command buffer + if (bd->font_command_buffer == VK_NULL_HANDLE) { + vk::CommandBufferAllocateInfo info{ + .commandPool = bd->command_pool, + .commandBufferCount = 1, + }; + std::unique_lock lk(bd->command_pool_mutex); + bd->font_command_buffer = CheckVkResult(v.device.allocateCommandBuffers(info)).front(); + } + + // Start command buffer + { + CheckVkErr(bd->font_command_buffer.reset()); + vk::CommandBufferBeginInfo begin_info{}; + begin_info.flags |= vk::CommandBufferUsageFlagBits::eOneTimeSubmit; + CheckVkErr(bd->font_command_buffer.begin(&begin_info)); + } + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width * height * 4 * sizeof(char); + + // Create the Image: + { + vk::ImageCreateInfo info{ + .imageType = vk::ImageType::e2D, + .format = vk::Format::eR8G8B8A8Unorm, + .extent{ + .width = static_cast(width), + .height = static_cast(height), + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .samples = vk::SampleCountFlagBits::e1, + .tiling = vk::ImageTiling::eOptimal, + .usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst, + .sharingMode = vk::SharingMode::eExclusive, + .initialLayout = vk::ImageLayout::eUndefined, + }; + bd->font_image = CheckVkResult(v.device.createImage(info, v.allocator)); + vk::MemoryRequirements req = v.device.getImageMemoryRequirements(bd->font_image); + vk::MemoryAllocateInfo alloc_info{ + .allocationSize = IM_MAX(v.min_allocation_size, req.size), + .memoryTypeIndex = + FindMemoryType(vk::MemoryPropertyFlagBits::eDeviceLocal, req.memoryTypeBits), + }; + bd->font_memory = CheckVkResult(v.device.allocateMemory(alloc_info, v.allocator)); + CheckVkErr(v.device.bindImageMemory(bd->font_image, bd->font_memory, 0)); + } + + // Create the Image View: + { + vk::ImageViewCreateInfo info{ + .image = bd->font_image, + .viewType = vk::ImageViewType::e2D, + .format = vk::Format::eR8G8B8A8Unorm, + .subresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .layerCount = 1, + }, + }; + bd->font_view = CheckVkResult(v.device.createImageView(info, v.allocator)); + } + + // Create the Descriptor Set: + bd->font_descriptor_set = AddTexture(bd->font_view, vk::ImageLayout::eShaderReadOnlyOptimal); + + // Create the Upload Buffer: + vk::DeviceMemory upload_buffer_memory{}; + vk::Buffer upload_buffer{}; + { + vk::BufferCreateInfo buffer_info{ + .size = upload_size, + .usage = vk::BufferUsageFlagBits::eTransferSrc, + .sharingMode = vk::SharingMode::eExclusive, + }; + upload_buffer = CheckVkResult(v.device.createBuffer(buffer_info, v.allocator)); + vk::MemoryRequirements req = v.device.getBufferMemoryRequirements(upload_buffer); + bd->buffer_memory_alignment = IM_MAX(bd->buffer_memory_alignment, req.alignment); + vk::MemoryAllocateInfo alloc_info{ + .allocationSize = IM_MAX(v.min_allocation_size, req.size), + .memoryTypeIndex = + FindMemoryType(vk::MemoryPropertyFlagBits::eHostVisible, req.memoryTypeBits), + }; + upload_buffer_memory = CheckVkResult(v.device.allocateMemory(alloc_info, v.allocator)); + CheckVkErr(v.device.bindBufferMemory(upload_buffer, upload_buffer_memory, 0)); + } + + // Upload to Buffer: + { + char* map = (char*)CheckVkResult(v.device.mapMemory(upload_buffer_memory, 0, upload_size)); + memcpy(map, pixels, upload_size); + vk::MappedMemoryRange range[1]{ + { + .memory = upload_buffer_memory, + .size = upload_size, + }, + }; + CheckVkErr(v.device.flushMappedMemoryRanges({range})); + v.device.unmapMemory(upload_buffer_memory); + } + + // Copy to Image: + { + vk::ImageMemoryBarrier copy_barrier[1]{ + { + .dstAccessMask = vk::AccessFlagBits::eTransferWrite, + .oldLayout = vk::ImageLayout::eUndefined, + .newLayout = vk::ImageLayout::eTransferDstOptimal, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = bd->font_image, + .subresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .layerCount = 1, + }, + }, + }; + bd->font_command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eHost, + vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, + {copy_barrier}); + + vk::BufferImageCopy region{ + .imageSubresource{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .layerCount = 1, + }, + .imageExtent{ + .width = static_cast(width), + .height = static_cast(height), + .depth = 1, + }, + }; + bd->font_command_buffer.copyBufferToImage(upload_buffer, bd->font_image, + vk::ImageLayout::eTransferDstOptimal, {region}); + + vk::ImageMemoryBarrier use_barrier[1]{{ + .srcAccessMask = vk::AccessFlagBits::eTransferWrite, + .dstAccessMask = vk::AccessFlagBits::eShaderRead, + .oldLayout = vk::ImageLayout::eTransferDstOptimal, + .newLayout = vk::ImageLayout::eShaderReadOnlyOptimal, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = bd->font_image, + .subresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .levelCount = 1, + .layerCount = 1, + }, + }}; + bd->font_command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, + vk::PipelineStageFlagBits::eFragmentShader, {}, {}, + {}, {use_barrier}); + } + + // Store our identifier + io.Fonts->SetTexID(bd->font_descriptor_set); + + // End command buffer + vk::SubmitInfo end_info = {}; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &bd->font_command_buffer; + CheckVkErr(bd->font_command_buffer.end()); + CheckVkErr(v.queue.submit({end_info})); + + CheckVkErr(v.queue.waitIdle()); + + v.device.destroyBuffer(upload_buffer, v.allocator); + v.device.freeMemory(upload_buffer_memory, v.allocator); + + return true; +} + +// You probably never need to call this, as it is called by CreateFontsTexture() +// and Shutdown(). +static void DestroyFontsTexture() { + ImGuiIO& io = ImGui::GetIO(); + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + if (bd->font_descriptor_set) { + RemoveTexture(bd->font_descriptor_set); + bd->font_descriptor_set = VK_NULL_HANDLE; + io.Fonts->SetTexID(nullptr); + } + + if (bd->font_view) { + v.device.destroyImageView(bd->font_view, v.allocator); + bd->font_view = VK_NULL_HANDLE; + } + if (bd->font_image) { + v.device.destroyImage(bd->font_image, v.allocator); + bd->font_image = VK_NULL_HANDLE; + } + if (bd->font_memory) { + v.device.freeMemory(bd->font_memory, v.allocator); + bd->font_memory = VK_NULL_HANDLE; + } +} + +static void DestroyFrameRenderBuffers(vk::Device device, RenderBuffer& rb, + const vk::AllocationCallbacks* allocator) { + if (rb.buffer) { + device.destroyBuffer(rb.buffer, allocator); + rb.buffer = VK_NULL_HANDLE; + } + if (rb.buffer_memory) { + device.freeMemory(rb.buffer_memory, allocator); + rb.buffer_memory = VK_NULL_HANDLE; + } + rb.buffer_size = 0; +} + +static void DestroyWindowRenderBuffers(vk::Device device, WindowRenderBuffers& buffers, + const vk::AllocationCallbacks* allocator) { + for (uint32_t n = 0; n < buffers.count; n++) { + auto& frb = buffers.frame_render_buffers[n]; + DestroyFrameRenderBuffers(device, frb.index, allocator); + DestroyFrameRenderBuffers(device, frb.vertex, allocator); + } + buffers = {}; +} + +static void CreateShaderModules(vk::Device device, const vk::AllocationCallbacks* allocator) { + // Create the shader modules + VkData* bd = GetBackendData(); + if (bd->shader_module_vert == VK_NULL_HANDLE) { + vk::ShaderModuleCreateInfo vert_info{ + .codeSize = sizeof(glsl_shader_vert_spv), + .pCode = (uint32_t*)glsl_shader_vert_spv, + }; + bd->shader_module_vert = CheckVkResult(device.createShaderModule(vert_info, allocator)); + } + if (bd->shader_module_frag == VK_NULL_HANDLE) { + vk::ShaderModuleCreateInfo frag_info{ + .codeSize = sizeof(glsl_shader_frag_spv), + .pCode = (uint32_t*)glsl_shader_frag_spv, + }; + bd->shader_module_frag = CheckVkResult(device.createShaderModule(frag_info, allocator)); + } +} + +static void CreatePipeline(vk::Device device, const vk::AllocationCallbacks* allocator, + vk::PipelineCache pipeline_cache, vk::RenderPass render_pass, + vk::Pipeline* pipeline, uint32_t subpass) { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + + CreateShaderModules(device, allocator); + + vk::PipelineShaderStageCreateInfo stage[2]{ + { + .stage = vk::ShaderStageFlagBits::eVertex, + .module = bd->shader_module_vert, + .pName = "main", + }, + { + .stage = vk::ShaderStageFlagBits::eFragment, + .module = bd->shader_module_frag, + .pName = "main", + }, + }; + + vk::VertexInputBindingDescription binding_desc[1]{ + { + .stride = sizeof(ImDrawVert), + .inputRate = vk::VertexInputRate::eVertex, + }, + }; + + vk::VertexInputAttributeDescription attribute_desc[3]{ + { + .location = 0, + .binding = binding_desc[0].binding, + .format = vk::Format::eR32G32Sfloat, + .offset = offsetof(ImDrawVert, pos), + }, + { + .location = 1, + .binding = binding_desc[0].binding, + .format = vk::Format::eR32G32Sfloat, + .offset = offsetof(ImDrawVert, uv), + }, + { + .location = 2, + .binding = binding_desc[0].binding, + .format = vk::Format::eR8G8B8A8Unorm, + .offset = offsetof(ImDrawVert, col), + }, + }; + + vk::PipelineVertexInputStateCreateInfo vertex_info{ + .vertexBindingDescriptionCount = 1, + .pVertexBindingDescriptions = binding_desc, + .vertexAttributeDescriptionCount = 3, + .pVertexAttributeDescriptions = attribute_desc, + }; + + vk::PipelineInputAssemblyStateCreateInfo ia_info{ + .topology = vk::PrimitiveTopology::eTriangleList, + }; + + vk::PipelineViewportStateCreateInfo viewport_info{ + .viewportCount = 1, + .scissorCount = 1, + }; + + vk::PipelineRasterizationStateCreateInfo raster_info{ + .polygonMode = vk::PolygonMode::eFill, + .cullMode = vk::CullModeFlagBits::eNone, + .frontFace = vk::FrontFace::eCounterClockwise, + .lineWidth = 1.0f, + }; + + vk::PipelineMultisampleStateCreateInfo ms_info{ + .rasterizationSamples = vk::SampleCountFlagBits::e1, + }; + + vk::PipelineColorBlendAttachmentState color_attachment[1]{ + { + .blendEnable = VK_TRUE, + .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .colorBlendOp = vk::BlendOp::eAdd, + .srcAlphaBlendFactor = vk::BlendFactor::eOne, + .dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .alphaBlendOp = vk::BlendOp::eAdd, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | + vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + }, + }; + + vk::PipelineDepthStencilStateCreateInfo depth_info{}; + + vk::PipelineColorBlendStateCreateInfo blend_info{ + .attachmentCount = 1, + .pAttachments = color_attachment, + }; + + vk::DynamicState dynamic_states[2]{ + vk::DynamicState::eViewport, + vk::DynamicState::eScissor, + }; + vk::PipelineDynamicStateCreateInfo dynamic_state{ + .dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states), + .pDynamicStates = dynamic_states, + }; + + vk::GraphicsPipelineCreateInfo info{ + .pNext = &v.pipeline_rendering_create_info, + .flags = bd->pipeline_create_flags, + .stageCount = 2, + .pStages = stage, + .pVertexInputState = &vertex_info, + .pInputAssemblyState = &ia_info, + .pViewportState = &viewport_info, + .pRasterizationState = &raster_info, + .pMultisampleState = &ms_info, + .pDepthStencilState = &depth_info, + .pColorBlendState = &blend_info, + .pDynamicState = &dynamic_state, + .layout = bd->pipeline_layout, + .renderPass = render_pass, + .subpass = subpass, + }; + + *pipeline = + CheckVkResult(device.createGraphicsPipelines(pipeline_cache, {info}, allocator)).front(); +} + +bool CreateDeviceObjects() { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + vk::Result err; + + if (!bd->descriptor_pool) { + // large enough descriptor pool + vk::DescriptorPoolSize pool_sizes[]{ + {vk::DescriptorType::eSampler, 1000}, + {vk::DescriptorType::eCombinedImageSampler, 1000}, + {vk::DescriptorType::eSampledImage, 1000}, + {vk::DescriptorType::eStorageImage, 1000}, + {vk::DescriptorType::eUniformTexelBuffer, 1000}, + {vk::DescriptorType::eStorageTexelBuffer, 1000}, + {vk::DescriptorType::eUniformBuffer, 1000}, + {vk::DescriptorType::eStorageBuffer, 1000}, + {vk::DescriptorType::eUniformBufferDynamic, 1000}, + {vk::DescriptorType::eStorageBufferDynamic, 1000}, + {vk::DescriptorType::eInputAttachment, 1000}, + }; + + vk::DescriptorPoolCreateInfo pool_info{ + .flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, + .maxSets = 1000, + .poolSizeCount = std::size(pool_sizes), + .pPoolSizes = pool_sizes, + }; + + bd->descriptor_pool = CheckVkResult(v.device.createDescriptorPool(pool_info)); + } + + if (!bd->descriptor_set_layout) { + vk::DescriptorSetLayoutBinding binding[1]{ + { + .descriptorType = vk::DescriptorType::eCombinedImageSampler, + .descriptorCount = 1, + .stageFlags = vk::ShaderStageFlagBits::eFragment, + }, + }; + vk::DescriptorSetLayoutCreateInfo info{ + .bindingCount = 1, + .pBindings = binding, + }; + bd->descriptor_set_layout = + CheckVkResult(v.device.createDescriptorSetLayout(info, v.allocator)); + } + + if (!bd->pipeline_layout) { + // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection + // matrix + vk::PushConstantRange push_constants[1]{ + { + .stageFlags = vk::ShaderStageFlagBits::eVertex, + .offset = sizeof(float) * 0, + .size = sizeof(float) * 4, + }, + }; + vk::DescriptorSetLayout set_layout[1] = {bd->descriptor_set_layout}; + vk::PipelineLayoutCreateInfo layout_info{ + .setLayoutCount = 1, + .pSetLayouts = set_layout, + .pushConstantRangeCount = 1, + .pPushConstantRanges = push_constants, + }; + bd->pipeline_layout = + CheckVkResult(v.device.createPipelineLayout(layout_info, v.allocator)); + } + + CreatePipeline(v.device, v.allocator, v.pipeline_cache, nullptr, &bd->pipeline, v.subpass); + + if (bd->command_pool == VK_NULL_HANDLE) { + vk::CommandPoolCreateInfo info{ + .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, + .queueFamilyIndex = v.queue_family, + }; + std::unique_lock lk(bd->command_pool_mutex); + bd->command_pool = CheckVkResult(v.device.createCommandPool(info, v.allocator)); + } + + if (!bd->simple_sampler) { + // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= + // ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow + // point/nearest sampling. + vk::SamplerCreateInfo info{ + .magFilter = vk::Filter::eLinear, + .minFilter = vk::Filter::eLinear, + .mipmapMode = vk::SamplerMipmapMode::eLinear, + .addressModeU = vk::SamplerAddressMode::eRepeat, + .addressModeV = vk::SamplerAddressMode::eRepeat, + .addressModeW = vk::SamplerAddressMode::eRepeat, + .maxAnisotropy = 1.0f, + .minLod = -1000, + .maxLod = 1000, + }; + bd->simple_sampler = CheckVkResult(v.device.createSampler(info, v.allocator)); + } + + return true; +} + +void ImGuiImplVulkanDestroyDeviceObjects() { + VkData* bd = GetBackendData(); + const InitInfo& v = bd->init_info; + DestroyWindowRenderBuffers(v.device, bd->render_buffers, v.allocator); + DestroyFontsTexture(); + + if (bd->font_command_buffer) { + std::unique_lock lk(bd->command_pool_mutex); + v.device.freeCommandBuffers(bd->command_pool, {bd->font_command_buffer}); + bd->font_command_buffer = VK_NULL_HANDLE; + } + if (bd->command_pool) { + std::unique_lock lk(bd->command_pool_mutex); + v.device.destroyCommandPool(bd->command_pool, v.allocator); + bd->command_pool = VK_NULL_HANDLE; + } + if (bd->shader_module_vert) { + v.device.destroyShaderModule(bd->shader_module_vert, v.allocator); + bd->shader_module_vert = VK_NULL_HANDLE; + } + if (bd->shader_module_frag) { + v.device.destroyShaderModule(bd->shader_module_frag, v.allocator); + bd->shader_module_frag = VK_NULL_HANDLE; + } + if (bd->simple_sampler) { + v.device.destroySampler(bd->simple_sampler, v.allocator); + bd->simple_sampler = VK_NULL_HANDLE; + } + if (bd->descriptor_set_layout) { + v.device.destroyDescriptorSetLayout(bd->descriptor_set_layout, v.allocator); + bd->descriptor_set_layout = VK_NULL_HANDLE; + } + if (bd->pipeline_layout) { + v.device.destroyPipelineLayout(bd->pipeline_layout, v.allocator); + bd->pipeline_layout = VK_NULL_HANDLE; + } + if (bd->pipeline) { + v.device.destroyPipeline(bd->pipeline, v.allocator); + bd->pipeline = VK_NULL_HANDLE; + } +} + +bool Init(InitInfo info) { + + IM_ASSERT(info.instance != VK_NULL_HANDLE); + IM_ASSERT(info.physical_device != VK_NULL_HANDLE); + IM_ASSERT(info.device != VK_NULL_HANDLE); + IM_ASSERT(info.image_count >= 2); + + ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); + IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); + + // Setup backend capabilities flags + auto* bd = IM_NEW(VkData)(info); + io.BackendRendererUserData = (void*)bd; + io.BackendRendererName = "imgui_impl_vulkan_shadps4"; + // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; + + CreateDeviceObjects(); + CreateFontsTexture(); + + return true; +} + +void Shutdown() { + VkData* bd = GetBackendData(); + IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + + ImGuiImplVulkanDestroyDeviceObjects(); + io.BackendRendererName = nullptr; + io.BackendRendererUserData = nullptr; + io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; + IM_DELETE(bd); +} + +} // namespace ImGui::Vulkan diff --git a/src/imgui/renderer/imgui_impl_vulkan.h b/src/imgui/renderer/imgui_impl_vulkan.h new file mode 100644 index 000000000..e325e2a8d --- /dev/null +++ b/src/imgui/renderer/imgui_impl_vulkan.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Based on imgui_impl_vulkan.h from Dear ImGui repository + +#pragma once + +#include "common/types.h" +#include "video_core/renderer_vulkan/vk_common.h" + +struct ImDrawData; + +namespace ImGui::Vulkan { + +struct InitInfo { + vk::Instance instance; + vk::PhysicalDevice physical_device; + vk::Device device; + uint32_t queue_family; + vk::Queue queue; + uint32_t image_count; // >= 2 + vk::DeviceSize min_allocation_size; // Minimum allocation size + vk::PipelineCache pipeline_cache; + uint32_t subpass; + vk::PipelineRenderingCreateInfoKHR pipeline_rendering_create_info; + + // (Optional) Allocation, Logging + const vk::AllocationCallbacks* allocator{}; + void (*check_vk_result_fn)(vk::Result err); +}; + +// Prepare all resources needed for uploading textures +// Caller should clean up the returned data. +struct UploadTextureData { + vk::Image image; + vk::ImageView image_view; + vk::DescriptorSet descriptor_set; + vk::DeviceMemory image_memory; + + vk::CommandBuffer command_buffer; // Submit to the queue + vk::Buffer upload_buffer; + vk::DeviceMemory upload_buffer_memory; + + void Upload(); + + void Destroy(); +}; + +vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout, + vk::Sampler sampler = VK_NULL_HANDLE); + +UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height, + size_t size); + +void RemoveTexture(vk::DescriptorSet descriptor_set); + +bool Init(InitInfo info); +void Shutdown(); +void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer, + vk::Pipeline pipeline = VK_NULL_HANDLE); + +} // namespace ImGui::Vulkan \ No newline at end of file diff --git a/src/imgui/renderer/texture_manager.cpp b/src/imgui/renderer/texture_manager.cpp new file mode 100644 index 000000000..7f9c69d49 --- /dev/null +++ b/src/imgui/renderer/texture_manager.cpp @@ -0,0 +1,249 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#include + +#include "common/assert.h" +#include "common/config.h" +#include "common/io_file.h" +#include "common/polyfill_thread.h" +#include "imgui_impl_vulkan.h" +#include "texture_manager.h" + +namespace ImGui { + +namespace Core::TextureManager { +struct Inner { + std::atomic_int count = 0; + ImTextureID texture_id = nullptr; + u32 width = 0; + u32 height = 0; + + Vulkan::UploadTextureData upload_data; + + ~Inner(); +}; +} // namespace Core::TextureManager + +using namespace Core::TextureManager; + +RefCountedTexture::RefCountedTexture(Inner* inner) : inner(inner) { + ++inner->count; +} + +RefCountedTexture RefCountedTexture::DecodePngTexture(std::vector data) { + const auto core = new Inner; + Core::TextureManager::DecodePngTexture(std::move(data), core); + return RefCountedTexture(core); +} + +RefCountedTexture RefCountedTexture::DecodePngFile(std::filesystem::path path) { + const auto core = new Inner; + Core::TextureManager::DecodePngFile(std::move(path), core); + return RefCountedTexture(core); +} + +RefCountedTexture::RefCountedTexture() : inner(nullptr) {} + +RefCountedTexture::RefCountedTexture(const RefCountedTexture& other) : inner(other.inner) { + if (inner != nullptr) { + ++inner->count; + } +} + +RefCountedTexture::RefCountedTexture(RefCountedTexture&& other) noexcept : inner(other.inner) { + other.inner = nullptr; +} + +RefCountedTexture& RefCountedTexture::operator=(const RefCountedTexture& other) { + if (this == &other) + return *this; + inner = other.inner; + if (inner != nullptr) { + ++inner->count; + } + return *this; +} + +RefCountedTexture& RefCountedTexture::operator=(RefCountedTexture&& other) noexcept { + if (this == &other) + return *this; + std::swap(inner, other.inner); + return *this; +} + +RefCountedTexture::~RefCountedTexture() { + if (inner != nullptr) { + if (inner->count.fetch_sub(1) == 1) { + delete inner; + } + } +} +RefCountedTexture::Image RefCountedTexture::GetTexture() const { + if (inner == nullptr) { + return {}; + } + return Image{ + .im_id = inner->texture_id, + .width = inner->width, + .height = inner->height, + }; +} +RefCountedTexture::operator bool() const { + return inner != nullptr && inner->texture_id != nullptr; +} + +struct Job { + Inner* core; + std::vector data; + std::filesystem::path path; +}; + +struct UploadJob { + Inner* core = nullptr; + Vulkan::UploadTextureData data; + int tick = 0; // Used to skip the first frame when destroying to await the current frame to draw +}; + +static bool g_is_worker_running = false; +static std::jthread g_worker_thread; +static std::condition_variable g_worker_cv; + +static std::mutex g_job_list_mtx; +static std::deque g_job_list; + +static std::mutex g_upload_mtx; +static std::deque g_upload_list; + +namespace Core::TextureManager { + +Inner::~Inner() { + if (upload_data.descriptor_set != nullptr) { + std::unique_lock lk{g_upload_mtx}; + g_upload_list.emplace_back(UploadJob{ + .data = this->upload_data, + .tick = 2, + }); + } +} + +void WorkerLoop() { + std::mutex mtx; + while (g_is_worker_running) { + std::unique_lock lk{mtx}; + g_worker_cv.wait(lk); + if (!g_is_worker_running) { + break; + } + while (true) { + g_job_list_mtx.lock(); + if (g_job_list.empty()) { + g_job_list_mtx.unlock(); + break; + } + auto [core, png_raw, path] = std::move(g_job_list.front()); + g_job_list.pop_front(); + g_job_list_mtx.unlock(); + + if (Config::vkCrashDiagnosticEnabled()) { + // FIXME: Crash diagnostic hangs when building the command buffer here + continue; + } + + if (!path.empty()) { // Decode PNG from file + Common::FS::IOFile file(path, Common::FS::FileAccessMode::Read); + if (!file.IsOpen()) { + LOG_ERROR(ImGui, "Failed to open PNG file: {}", path.string()); + continue; + } + png_raw.resize(file.GetSize()); + file.Seek(0); + file.ReadRaw(png_raw.data(), png_raw.size()); + file.Close(); + } + + int width, height; + const stbi_uc* pixels = + stbi_load_from_memory(png_raw.data(), png_raw.size(), &width, &height, nullptr, 4); + + auto texture = Vulkan::UploadTexture(pixels, vk::Format::eR8G8B8A8Unorm, width, height, + width * height * 4 * sizeof(stbi_uc)); + + core->upload_data = texture; + core->width = width; + core->height = height; + + std::unique_lock upload_lk{g_upload_mtx}; + g_upload_list.emplace_back(UploadJob{ + .core = core, + }); + } + } +} + +void StartWorker() { + ASSERT(!g_is_worker_running); + g_worker_thread = std::jthread(WorkerLoop); + g_is_worker_running = true; +} + +void StopWorker() { + ASSERT(g_is_worker_running); + g_is_worker_running = false; + g_worker_cv.notify_one(); +} + +void DecodePngTexture(std::vector data, Inner* core) { + ++core->count; + Job job{ + .core = core, + .data = std::move(data), + }; + std::unique_lock lk{g_job_list_mtx}; + g_job_list.push_back(std::move(job)); + g_worker_cv.notify_one(); +} + +void DecodePngFile(std::filesystem::path path, Inner* core) { + ++core->count; + Job job{ + .core = core, + .path = std::move(path), + }; + std::unique_lock lk{g_job_list_mtx}; + g_job_list.push_back(std::move(job)); + g_worker_cv.notify_one(); +} + +void Submit() { + UploadJob upload; + { + std::unique_lock lk{g_upload_mtx}; + if (g_upload_list.empty()) { + return; + } + // Upload one texture at a time to avoid slow down + upload = g_upload_list.front(); + g_upload_list.pop_front(); + if (upload.tick > 0) { + --upload.tick; + g_upload_list.emplace_back(upload); + return; + } + } + if (upload.core != nullptr) { + upload.core->upload_data.Upload(); + upload.core->texture_id = upload.core->upload_data.descriptor_set; + if (upload.core->count.fetch_sub(1) == 1) { + delete upload.core; + } + } else { + upload.data.Destroy(); + } +} +} // namespace Core::TextureManager + +} // namespace ImGui \ No newline at end of file diff --git a/src/imgui/renderer/texture_manager.h b/src/imgui/renderer/texture_manager.h new file mode 100644 index 000000000..4fa7b9924 --- /dev/null +++ b/src/imgui/renderer/texture_manager.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/types.h" +#include "imgui/imgui_texture.h" + +namespace vk { +class CommandBuffer; +} + +namespace ImGui::Core::TextureManager { + +struct Inner; + +void StartWorker(); + +void StopWorker(); + +void DecodePngTexture(std::vector data, Inner* core); + +void DecodePngFile(std::filesystem::path path, Inner* core); + +void Submit(); + +}; // namespace ImGui::Core::TextureManager \ No newline at end of file diff --git a/src/input/controller.cpp b/src/input/controller.cpp index 4a3db1633..dcd8ed946 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -127,20 +127,34 @@ void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) { bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) { if (m_sdl_gamepad != nullptr) { return SDL_RumbleGamepad(m_sdl_gamepad, (smallMotor / 255.0f) * 0xFFFF, - (largeMotor / 255.0f) * 0xFFFF, -1) == 0; + (largeMotor / 255.0f) * 0xFFFF, -1); } return true; } +void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) { + if (touchIndex < 2) { + std::scoped_lock lock{m_mutex}; + auto state = GetLastState(); + state.time = Libraries::Kernel::sceKernelGetProcessTime(); + + state.touchpad[touchIndex].state = touchDown; + state.touchpad[touchIndex].x = static_cast(x * 1920); + state.touchpad[touchIndex].y = static_cast(y * 941); + + AddState(state); + } +} + void GameController::TryOpenSDLController() { if (m_sdl_gamepad == nullptr || !SDL_GamepadConnected(m_sdl_gamepad)) { int gamepad_count; SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr; SDL_free(gamepads); - } - SetLightBarRGB(0, 0, 255); + SetLightBarRGB(0, 0, 255); + } } } // namespace Input diff --git a/src/input/controller.h b/src/input/controller.h index ef0991568..0a0d663a1 100644 --- a/src/input/controller.h +++ b/src/input/controller.h @@ -21,10 +21,17 @@ enum class Axis { AxisMax }; +struct TouchpadEntry { + bool state{}; + u16 x{}; + u16 y{}; +}; + struct State { u32 buttonsState = 0; u64 time = 0; int axes[static_cast(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0}; + TouchpadEntry touchpad[2] = {{false, 0, 0}, {false, 0, 0}}; }; inline int GetAxis(int min, int max, int value) { @@ -47,6 +54,7 @@ public: void Axis(int id, Input::Axis axis, int value); void SetLightBarRGB(u8 r, u8 g, u8 b); bool SetVibration(u8 smallMotor, u8 largeMotor); + void SetTouchpadState(int touchIndex, bool touchDown, float x, float y); void TryOpenSDLController(); private: diff --git a/src/main.cpp b/src/main.cpp index 9df14f138..de1d92326 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,15 +2,38 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/memory_patcher.h" #include "emulator.h" +#ifdef _WIN32 +#include +#endif + int main(int argc, char* argv[]) { +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); +#endif + if (argc == 1) { fmt::print("Usage: {} \n", argv[0]); return -1; } + // check if eboot file exists + if (!std::filesystem::exists(argv[1])) { + fmt::print("Eboot.bin file not found\n"); + return -1; + } + + for (int i = 0; i < argc; i++) { + std::string curArg = argv[i]; + if (curArg == "-p") { + std::string patchFile = argv[i + 1]; + MemoryPatcher::patchFile = patchFile; + } + } Core::Emulator emulator; emulator.Run(argv[1]); + return 0; } diff --git a/src/qt_gui/background_music_player.cpp b/src/qt_gui/background_music_player.cpp new file mode 100644 index 000000000..a40c5bfae --- /dev/null +++ b/src/qt_gui/background_music_player.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "background_music_player.h" + +BackgroundMusicPlayer::BackgroundMusicPlayer(QObject* parent) : QObject(parent) { + m_mediaPlayer = new QMediaPlayer(this); + m_audioOutput = new QAudioOutput(this); + m_mediaPlayer->setAudioOutput(m_audioOutput); + m_mediaPlayer->setLoops(QMediaPlayer::Infinite); +} + +void BackgroundMusicPlayer::setVolume(int volume) { + float linearVolume = QAudio::convertVolume(volume / 100.0f, QAudio::LogarithmicVolumeScale, + QAudio::LinearVolumeScale); + m_audioOutput->setVolume(linearVolume); +} + +void BackgroundMusicPlayer::playMusic(const QString& snd0path) { + if (snd0path.isEmpty()) { + stopMusic(); + return; + } + const auto newMusic = QUrl::fromLocalFile(snd0path); + if (m_mediaPlayer->playbackState() == QMediaPlayer::PlayingState && + m_currentMusic == newMusic) { + // already playing the correct music + return; + } + + m_currentMusic = newMusic; + m_mediaPlayer->setSource(newMusic); + m_mediaPlayer->play(); +} + +void BackgroundMusicPlayer::stopMusic() { + m_mediaPlayer->stop(); +} diff --git a/src/qt_gui/background_music_player.h b/src/qt_gui/background_music_player.h new file mode 100644 index 000000000..6d70fe68c --- /dev/null +++ b/src/qt_gui/background_music_player.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +class BackgroundMusicPlayer : public QObject { + Q_OBJECT + +public: + static BackgroundMusicPlayer& getInstance() { + static BackgroundMusicPlayer instance; + return instance; + } + + void setVolume(int volume); + void playMusic(const QString& snd0path); + void stopMusic(); + +private: + BackgroundMusicPlayer(QObject* parent = nullptr); + + QMediaPlayer* m_mediaPlayer; + QAudioOutput* m_audioOutput; + QUrl m_currentMusic; +}; diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp new file mode 100644 index 000000000..c044c2c3c --- /dev/null +++ b/src/qt_gui/cheats_patches.cpp @@ -0,0 +1,1286 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cheats_patches.h" +#include "common/memory_patcher.h" +#include "common/path_util.h" +#include "core/module.h" + +using namespace Common::FS; + +CheatsPatches::CheatsPatches(const QString& gameName, const QString& gameSerial, + const QString& gameVersion, const QString& gameSize, + const QPixmap& gameImage, QWidget* parent) + : QWidget(parent), m_gameName(gameName), m_gameSerial(gameSerial), m_gameVersion(gameVersion), + m_gameSize(gameSize), m_gameImage(gameImage), manager(new QNetworkAccessManager(this)) { + setupUI(); + resize(500, 400); + setWindowTitle(tr("Cheats / Patches")); +} + +CheatsPatches::~CheatsPatches() {} + +void CheatsPatches::setupUI() { + defaultTextEdit = tr("defaultTextEdit_MSG"); + defaultTextEdit.replace("\\n", "\n"); + + QString CHEATS_DIR_QString; + Common::FS::PathToQString(CHEATS_DIR_QString, + Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); + QString NameCheatJson = m_gameSerial + "_" + m_gameVersion + ".json"; + m_cheatFilePath = CHEATS_DIR_QString + "/" + NameCheatJson; + + QHBoxLayout* mainLayout = new QHBoxLayout(this); + + // Create the game info group box + QGroupBox* gameInfoGroupBox = new QGroupBox(); + QVBoxLayout* gameInfoLayout = new QVBoxLayout(gameInfoGroupBox); + gameInfoLayout->setAlignment(Qt::AlignTop); + + QLabel* gameImageLabel = new QLabel(); + if (!m_gameImage.isNull()) { + gameImageLabel->setPixmap(m_gameImage.scaled(275, 275, Qt::KeepAspectRatio)); + } else { + gameImageLabel->setText(tr("No Image Available")); + } + gameImageLabel->setAlignment(Qt::AlignCenter); + gameInfoLayout->addWidget(gameImageLabel, 0, Qt::AlignCenter); + + QLabel* gameNameLabel = new QLabel(m_gameName); + gameNameLabel->setAlignment(Qt::AlignLeft); + gameNameLabel->setWordWrap(true); + gameInfoLayout->addWidget(gameNameLabel); + + QLabel* gameSerialLabel = new QLabel(tr("Serial: ") + m_gameSerial); + gameSerialLabel->setAlignment(Qt::AlignLeft); + gameInfoLayout->addWidget(gameSerialLabel); + + QLabel* gameVersionLabel = new QLabel(tr("Version: ") + m_gameVersion); + gameVersionLabel->setAlignment(Qt::AlignLeft); + gameInfoLayout->addWidget(gameVersionLabel); + + QLabel* gameSizeLabel = new QLabel(tr("Size: ") + m_gameSize); + gameSizeLabel->setAlignment(Qt::AlignLeft); + gameInfoLayout->addWidget(gameSizeLabel); + + // Add a text area for instructions and 'Patch' descriptions + instructionsTextEdit = new QTextEdit(); + instructionsTextEdit->setText(defaultTextEdit); + instructionsTextEdit->setReadOnly(true); + instructionsTextEdit->setFixedHeight(290); + gameInfoLayout->addWidget(instructionsTextEdit); + + // Create the tab widget + QTabWidget* tabWidget = new QTabWidget(); + QWidget* cheatsTab = new QWidget(); + QWidget* patchesTab = new QWidget(); + + // Layouts for the tabs + QVBoxLayout* cheatsLayout = new QVBoxLayout(); + QVBoxLayout* patchesLayout = new QVBoxLayout(); + + // Setup the cheats tab + QGroupBox* cheatsGroupBox = new QGroupBox(); + rightLayout = new QVBoxLayout(cheatsGroupBox); + rightLayout->setAlignment(Qt::AlignTop); + + cheatsGroupBox->setLayout(rightLayout); + QScrollArea* scrollArea = new QScrollArea(); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(cheatsGroupBox); + scrollArea->setMinimumHeight(490); + cheatsLayout->addWidget(scrollArea); + + // QListView + listView_selectFile = new QListView(); + listView_selectFile->setSelectionMode(QAbstractItemView::SingleSelection); + listView_selectFile->setEditTriggers(QAbstractItemView::NoEditTriggers); + + // Add QListView to layout + QVBoxLayout* fileListLayout = new QVBoxLayout(); + fileListLayout->addWidget(new QLabel(tr("Select Cheat File:"))); + fileListLayout->addWidget(listView_selectFile); + cheatsLayout->addLayout(fileListLayout, 2); + + // Call the method to fill the list of cheat files + populateFileListCheats(); + + QLabel* repositoryLabel = new QLabel(tr("Repository:")); + repositoryLabel->setAlignment(Qt::AlignLeft); + repositoryLabel->setAlignment(Qt::AlignVCenter); + + // Add a combo box and a download button + QHBoxLayout* controlLayout = new QHBoxLayout(); + controlLayout->addWidget(repositoryLabel); + controlLayout->setAlignment(Qt::AlignLeft); + QComboBox* downloadComboBox = new QComboBox(); + + downloadComboBox->addItem("wolf2022", "wolf2022"); + downloadComboBox->addItem("GoldHEN", "GoldHEN"); + downloadComboBox->addItem("shadPS4", "shadPS4"); + + controlLayout->addWidget(downloadComboBox); + + QPushButton* downloadButton = new QPushButton(tr("Download Cheats")); + connect(downloadButton, &QPushButton::clicked, [this, downloadComboBox]() { + QString source = downloadComboBox->currentData().toString(); + downloadCheats(source, m_gameSerial, m_gameVersion, true); + }); + + QPushButton* deleteCheatButton = new QPushButton(tr("Delete File")); + connect(deleteCheatButton, &QPushButton::clicked, [this, CHEATS_DIR_QString]() { + QStringListModel* model = qobject_cast(listView_selectFile->model()); + if (!model) { + return; + } + QItemSelectionModel* selectionModel = listView_selectFile->selectionModel(); + if (!selectionModel) { + return; + } + QModelIndexList selectedIndexes = selectionModel->selectedIndexes(); + if (selectedIndexes.isEmpty()) { + QMessageBox::warning( + this, tr("Delete File"), + tr("No files selected.") + "\n" + + tr("You can delete the cheats you don't want after downloading them.")); + return; + } + QModelIndex selectedIndex = selectedIndexes.first(); + QString selectedFileName = model->data(selectedIndex).toString(); + + int ret = QMessageBox::warning( + this, tr("Delete File"), + QString(tr("Do you want to delete the selected file?\\n%1").replace("\\n", "\n")) + .arg(selectedFileName), + QMessageBox::Yes | QMessageBox::No); + + if (ret == QMessageBox::Yes) { + QString filePath = CHEATS_DIR_QString + "/" + selectedFileName; + QFile::remove(filePath); + populateFileListCheats(); + } + }); + + controlLayout->addWidget(downloadButton); + controlLayout->addWidget(deleteCheatButton); + + cheatsLayout->addLayout(controlLayout); + cheatsTab->setLayout(cheatsLayout); + + // Setup the patches tab + QGroupBox* patchesGroupBox = new QGroupBox(); + patchesGroupBoxLayout = new QVBoxLayout(patchesGroupBox); + patchesGroupBoxLayout->setAlignment(Qt::AlignTop); + patchesGroupBox->setLayout(patchesGroupBoxLayout); + + QScrollArea* patchesScrollArea = new QScrollArea(); + patchesScrollArea->setWidgetResizable(true); + patchesScrollArea->setWidget(patchesGroupBox); + patchesScrollArea->setMinimumHeight(490); + patchesLayout->addWidget(patchesScrollArea); + + // List of files in patchesListView + patchesListView = new QListView(); + patchesListView->setSelectionMode(QAbstractItemView::SingleSelection); + patchesListView->setEditTriggers(QAbstractItemView::NoEditTriggers); + + // Add new label "Select Patch File:" above the QListView + QVBoxLayout* patchFileListLayout = new QVBoxLayout(); + patchFileListLayout->addWidget(new QLabel(tr("Select Patch File:"))); + patchFileListLayout->addWidget(patchesListView); + patchesLayout->addLayout(patchFileListLayout, 2); + + QStringListModel* patchesModel = new QStringListModel(); + patchesListView->setModel(patchesModel); + + QHBoxLayout* patchesControlLayout = new QHBoxLayout(); + + QLabel* patchesRepositoryLabel = new QLabel(tr("Repository:")); + patchesRepositoryLabel->setAlignment(Qt::AlignLeft); + patchesRepositoryLabel->setAlignment(Qt::AlignVCenter); + patchesControlLayout->addWidget(patchesRepositoryLabel); + + // Add the combo box with options + patchesComboBox = new QComboBox(); + patchesComboBox->addItem("GoldHEN", "GoldHEN"); + patchesComboBox->addItem("shadPS4", "shadPS4"); + patchesControlLayout->addWidget(patchesComboBox); + + QPushButton* patchesButton = new QPushButton(tr("Download Patches")); + connect(patchesButton, &QPushButton::clicked, [this]() { + QString selectedOption = patchesComboBox->currentData().toString(); + downloadPatches(selectedOption, true); + }); + patchesControlLayout->addWidget(patchesButton); + + QPushButton* saveButton = new QPushButton(tr("Save")); + connect(saveButton, &QPushButton::clicked, this, &CheatsPatches::onSaveButtonClicked); + + patchesControlLayout->addWidget(saveButton); + + patchesLayout->addLayout(patchesControlLayout); + patchesTab->setLayout(patchesLayout); + + tabWidget->addTab(cheatsTab, tr("Cheats")); + tabWidget->addTab(patchesTab, tr("Patches")); + + connect(tabWidget, &QTabWidget::currentChanged, this, [this](int index) { + if (index == 1) { + populateFileListPatches(); + } + }); + + mainLayout->addWidget(gameInfoGroupBox, 1); + mainLayout->addWidget(tabWidget, 3); + + manager = new QNetworkAccessManager(this); + + setLayout(mainLayout); +} + +void CheatsPatches::onSaveButtonClicked() { + // Get the name of the selected folder in the patchesListView + QString selectedPatchName; + QModelIndexList selectedIndexes = patchesListView->selectionModel()->selectedIndexes(); + if (selectedIndexes.isEmpty()) { + QMessageBox::warning(this, tr("Error"), tr("No patch selected.")); + return; + } + selectedPatchName = patchesListView->model()->data(selectedIndexes.first()).toString(); + int separatorIndex = selectedPatchName.indexOf(" | "); + selectedPatchName = selectedPatchName.mid(separatorIndex + 3); + + QString patchDir; + Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + patchDir += "/" + selectedPatchName; + + QString filesJsonPath = patchDir + "/files.json"; + QFile jsonFile(filesJsonPath); + if (!jsonFile.open(QIODevice::ReadOnly)) { + QMessageBox::critical(this, tr("Error"), tr("Unable to open files.json for reading.")); + return; + } + + QByteArray jsonData = jsonFile.readAll(); + jsonFile.close(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + + QString selectedFileName; + QString serial = m_gameSerial; + + for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) { + QString filePath = it.key(); + QJsonArray idsArray = it.value().toArray(); + + if (idsArray.contains(QJsonValue(serial))) { + selectedFileName = filePath; + break; + } + } + + if (selectedFileName.isEmpty()) { + QMessageBox::critical(this, tr("Error"), tr("No patch file found for the current serial.")); + return; + } + + QString filePath = patchDir + "/" + selectedFileName; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(this, tr("Error"), tr("Unable to open the file for reading.")); + return; + } + + QByteArray xmlData = file.readAll(); + file.close(); + + QString newXmlData; + QXmlStreamWriter xmlWriter(&newXmlData); + xmlWriter.setAutoFormatting(true); + xmlWriter.writeStartDocument(); + + QXmlStreamReader xmlReader(xmlData); + bool insideMetadata = false; + + while (!xmlReader.atEnd()) { + xmlReader.readNext(); + + if (xmlReader.isStartElement()) { + if (xmlReader.name() == QStringLiteral("Metadata")) { + insideMetadata = true; + xmlWriter.writeStartElement(xmlReader.name().toString()); + + QString name = xmlReader.attributes().value("Name").toString(); + bool isEnabled = false; + bool hasIsEnabled = false; + bool foundPatchInfo = false; + + // Check and update the isEnabled attribute + for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { + if (attr.name() == QStringLiteral("isEnabled")) { + hasIsEnabled = true; + auto it = m_patchInfos.find(name); + if (it != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(it->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + xmlWriter.writeAttribute("isEnabled", isEnabled ? "true" : "false"); + } + } + if (!foundPatchInfo) { + auto maskIt = m_patchInfos.find(name + " (any version)"); + if (maskIt != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(maskIt->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + xmlWriter.writeAttribute("isEnabled", + isEnabled ? "true" : "false"); + } + } + } + + } else { + xmlWriter.writeAttribute(attr.name().toString(), attr.value().toString()); + } + } + + if (!hasIsEnabled) { + auto it = m_patchInfos.find(name); + if (it != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(it->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + } + } + if (!foundPatchInfo) { + auto maskIt = m_patchInfos.find(name + " (any version)"); + if (maskIt != m_patchInfos.end()) { + QCheckBox* checkBox = findCheckBoxByName(maskIt->name); + if (checkBox) { + foundPatchInfo = true; + isEnabled = checkBox->isChecked(); + } + } + } + xmlWriter.writeAttribute("isEnabled", isEnabled ? "true" : "false"); + } + } else { + xmlWriter.writeStartElement(xmlReader.name().toString()); + for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { + xmlWriter.writeAttribute(attr.name().toString(), attr.value().toString()); + } + } + } else if (xmlReader.isEndElement()) { + if (xmlReader.name() == QStringLiteral("Metadata")) { + insideMetadata = false; + } + xmlWriter.writeEndElement(); + } else if (xmlReader.isCharacters() && !xmlReader.isWhitespace()) { + xmlWriter.writeCharacters(xmlReader.text().toString()); + } + } + + xmlWriter.writeEndDocument(); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(this, tr("Error"), tr("Unable to open the file for writing.")); + return; + } + + QTextStream textStream(&file); + textStream << newXmlData; + file.close(); + + if (xmlReader.hasError()) { + QMessageBox::critical(this, tr("Error"), + tr("Failed to parse XML: ") + "\n" + xmlReader.errorString()); + } else { + QMessageBox::information(this, tr("Success"), tr("Options saved successfully.")); + } +} + +QCheckBox* CheatsPatches::findCheckBoxByName(const QString& name) { + for (int i = 0; i < patchesGroupBoxLayout->count(); ++i) { + QLayoutItem* item = patchesGroupBoxLayout->itemAt(i); + if (item) { + QWidget* widget = item->widget(); + QCheckBox* checkBox = qobject_cast(widget); + if (checkBox) { + if (checkBox->text().toStdString().find(name.toStdString()) != std::string::npos) { + return checkBox; + } + } + } + } + return nullptr; +} + +void CheatsPatches::downloadCheats(const QString& source, const QString& gameSerial, + const QString& gameVersion, const bool showMessageBox) { + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); + if (!dir.exists()) { + dir.mkpath("."); + } + + QString url; + if (source == "GoldHEN") { + url = "https://raw.githubusercontent.com/GoldHEN/GoldHEN_Cheat_Repository/main/json.txt"; + } else if (source == "wolf2022") { + url = "https://wolf2022.ir/trainer/list.json"; + } else if (source == "shadPS4") { + url = "https://raw.githubusercontent.com/shadps4-emu/ps4_cheats/main/CHEATS_JSON.txt"; + } else { + QMessageBox::warning(this, tr("Invalid Source"), + QString(tr("The selected source is invalid.") + "\n%1").arg(source)); + return; + } + + QNetworkRequest request(url); + QNetworkReply* reply = manager->get(request); + + connect(reply, &QNetworkReply::finished, [=, this]() { + if (reply->error() == QNetworkReply::NoError) { + QByteArray jsonData = reply->readAll(); + bool foundFiles = false; + + if (source == "wolf2022") { + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonArray gamesArray = jsonDoc.object().value("games").toArray(); + + foreach (const QJsonValue& value, gamesArray) { + QJsonObject gameObject = value.toObject(); + QString title = gameObject.value("title").toString(); + QString version = gameObject.value("version").toString(); + + if (title == gameSerial && + (version == gameVersion || version == gameVersion.mid(1))) { + QString fileUrl = + "https://wolf2022.ir/trainer/" + gameObject.value("url").toString(); + + QString localFileName = gameObject.value("url").toString(); + localFileName = + localFileName.left(localFileName.lastIndexOf('.')) + "_wolf2022.json"; + + QString localFilePath = dir.filePath(localFileName); + + if (QFile::exists(localFilePath) && showMessageBox) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, tr("File Exists"), + tr("File already exists. Do you want to replace it?") + "\n" + + localFileName, + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) { + continue; + } + } + QNetworkRequest fileRequest(fileUrl); + QNetworkReply* fileReply = manager->get(fileRequest); + + connect(fileReply, &QNetworkReply::finished, [=, this]() { + if (fileReply->error() == QNetworkReply::NoError) { + QByteArray fileData = fileReply->readAll(); + QFile localFile(localFilePath); + if (localFile.open(QIODevice::WriteOnly)) { + localFile.write(fileData); + localFile.close(); + } else { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save file:") + "\n%1") + .arg(localFilePath)); + } + } else { + QMessageBox::warning(this, tr("Error"), + QString(tr("Failed to download file:") + + "%1\n\n" + tr("Error:") + "%2") + .arg(fileUrl) + .arg(fileReply->errorString())); + } + fileReply->deleteLater(); + }); + + foundFiles = true; + } + } + if (!foundFiles && showMessageBox) { + QMessageBox::warning(this, tr("Cheats Not Found"), tr("CheatsNotFound_MSG")); + } + } else if (source == "GoldHEN" || source == "shadPS4") { + QString textContent(jsonData); + QRegularExpression regex( + QString("%1_%2[^=]*\\.json").arg(gameSerial).arg(gameVersion)); + QRegularExpressionMatchIterator matches = regex.globalMatch(textContent); + QString baseUrl; + + if (source == "GoldHEN") { + baseUrl = "https://raw.githubusercontent.com/GoldHEN/GoldHEN_Cheat_Repository/" + "main/json/"; + } else { + baseUrl = "https://raw.githubusercontent.com/shadps4-emu/ps4_cheats/" + "main/CHEATS/"; + } + + while (matches.hasNext()) { + QRegularExpressionMatch match = matches.next(); + QString fileName = match.captured(0); + + if (!fileName.isEmpty()) { + QString newFileName = fileName; + int dotIndex = newFileName.lastIndexOf('.'); + if (dotIndex != -1) { + + if (source == "GoldHEN") { + newFileName.insert(dotIndex, "_GoldHEN"); + } else { + newFileName.insert(dotIndex, "_shadPS4"); + } + } + QString fileUrl = baseUrl + fileName; + QString localFilePath = dir.filePath(newFileName); + + if (QFile::exists(localFilePath) && showMessageBox) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, tr("File Exists"), + tr("File already exists. Do you want to replace it?") + "\n" + + newFileName, + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) { + continue; + } + } + QNetworkRequest fileRequest(fileUrl); + QNetworkReply* fileReply = manager->get(fileRequest); + + connect(fileReply, &QNetworkReply::finished, [=, this]() { + if (fileReply->error() == QNetworkReply::NoError) { + QByteArray fileData = fileReply->readAll(); + QFile localFile(localFilePath); + if (localFile.open(QIODevice::WriteOnly)) { + localFile.write(fileData); + localFile.close(); + } else { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save file:") + "\n%1") + .arg(localFilePath)); + } + } else { + QMessageBox::warning(this, tr("Error"), + QString(tr("Failed to download file:") + + "%1\n\n" + tr("Error:") + "%2") + .arg(fileUrl) + .arg(fileReply->errorString())); + } + fileReply->deleteLater(); + }); + + foundFiles = true; + } + } + if (!foundFiles && showMessageBox) { + QMessageBox::warning(this, tr("Cheats Not Found"), tr("CheatsNotFound_MSG")); + } + } + if (foundFiles && showMessageBox) { + QMessageBox::information(this, tr("Cheats Downloaded Successfully"), + tr("CheatsDownloadedSuccessfully_MSG")); + populateFileListCheats(); + } + + } else { + if (showMessageBox) { + QMessageBox::warning(this, tr("Cheats Not Found"), tr("CheatsNotFound_MSG")); + } + } + reply->deleteLater(); + emit downloadFinished(); + }); + + // connect(reply, &QNetworkReply::errorOccurred, [=](QNetworkReply::NetworkError code) { + // if (showMessageBox) + // QMessageBox::warning(this, "Download Error", + // QString("Error in response: %1").arg(reply->errorString())); + // }); +} + +void CheatsPatches::populateFileListPatches() { + QLayoutItem* item; + while ((item = patchesGroupBoxLayout->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + m_patchInfos.clear(); + + QString patchesDir; + Common::FS::PathToQString(patchesDir, + Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QDir dir(patchesDir); + + QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + QStringList matchingFiles; + + foreach (const QString& folder, folders) { + QString folderPath = dir.filePath(folder); + QDir subDir(folderPath); + + QString filesJsonPath = subDir.filePath("files.json"); + QFile file(filesJsonPath); + + if (file.open(QIODevice::ReadOnly)) { + QByteArray fileData = file.readAll(); + file.close(); + + QJsonDocument jsonDoc(QJsonDocument::fromJson(fileData)); + QJsonObject jsonObj = jsonDoc.object(); + + for (auto it = jsonObj.constBegin(); it != jsonObj.constEnd(); ++it) { + QString fileName = it.key(); + QJsonArray serials = it.value().toArray(); + + if (serials.contains(QJsonValue(m_gameSerial))) { + QString fileEntry = fileName + " | " + folder; + if (!matchingFiles.contains(fileEntry)) { + matchingFiles << fileEntry; + } + } + } + } + } + QStringListModel* model = new QStringListModel(matchingFiles, this); + patchesListView->setModel(model); + + connect( + patchesListView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this]() { + QModelIndexList selectedIndexes = patchesListView->selectionModel()->selectedIndexes(); + if (!selectedIndexes.isEmpty()) { + QString selectedText = selectedIndexes.first().data().toString(); + addPatchesToLayout(selectedText); + } + }); + + if (!matchingFiles.isEmpty()) { + QModelIndex firstIndex = model->index(0, 0); + patchesListView->selectionModel()->select(firstIndex, QItemSelectionModel::Select | + QItemSelectionModel::Rows); + patchesListView->setCurrentIndex(firstIndex); + } +} + +void CheatsPatches::downloadPatches(const QString repository, const bool showMessageBox) { + QString url; + if (repository == "GoldHEN") { + url = "https://api.github.com/repos/illusion0001/PS4-PS5-Game-Patch/contents/patches/xml"; + } + if (repository == "shadPS4") { + url = "https://api.github.com/repos/shadps4-emu/ps4_cheats/contents/PATCHES"; + } + QNetworkAccessManager* manager = new QNetworkAccessManager(this); + QNetworkRequest request(url); + request.setRawHeader("Accept", "application/vnd.github.v3+json"); + QNetworkReply* reply = manager->get(request); + + connect(reply, &QNetworkReply::finished, [=, this]() { + if (reply->error() == QNetworkReply::NoError) { + QByteArray jsonData = reply->readAll(); + reply->deleteLater(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonArray itemsArray = jsonDoc.array(); + + if (itemsArray.isEmpty()) { + if (showMessageBox) { + QMessageBox::warning(this, tr("Error"), + tr("Failed to parse JSON data from HTML.")); + } + return; + } + + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString fullPath = dir.filePath(repository); + if (!dir.exists(fullPath)) { + dir.mkpath(fullPath); + } + dir.setPath(fullPath); + + foreach (const QJsonValue& value, itemsArray) { + QJsonObject fileObj = value.toObject(); + QString fileName = fileObj["name"].toString(); + QString filePath = fileObj["path"].toString(); + QString downloadUrl = fileObj["download_url"].toString(); + + if (fileName.endsWith(".xml")) { + QNetworkRequest fileRequest(downloadUrl); + QNetworkReply* fileReply = manager->get(fileRequest); + + connect(fileReply, &QNetworkReply::finished, [=, this]() { + if (fileReply->error() == QNetworkReply::NoError) { + QByteArray fileData = fileReply->readAll(); + QFile localFile(dir.filePath(fileName)); + if (localFile.open(QIODevice::WriteOnly)) { + localFile.write(fileData); + localFile.close(); + } else { + if (showMessageBox) { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save:") + "\n%1").arg(fileName)); + } + } + } else { + if (showMessageBox) { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to download:") + "\n%1").arg(downloadUrl)); + } + } + fileReply->deleteLater(); + }); + } + } + if (showMessageBox) { + QMessageBox::information(this, tr("Download Complete"), + QString(tr("DownloadComplete_MSG"))); + } + // Create the files.json file with the identification of which file to open + createFilesJson(repository); + populateFileListPatches(); + } else { + if (showMessageBox) { + QMessageBox::warning(this, tr("Error"), + QString(tr("Failed to retrieve HTML page.") + "\n%1") + .arg(reply->errorString())); + } + } + emit downloadFinished(); + }); +} + +void CheatsPatches::createFilesJson(const QString& repository) { + + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString fullPath = dir.filePath(repository); + if (!dir.exists(fullPath)) { + dir.mkpath(fullPath); + } + dir.setPath(fullPath); + + QJsonObject filesObject; + QStringList xmlFiles = dir.entryList(QStringList() << "*.xml", QDir::Files); + + foreach (const QString& xmlFile, xmlFiles) { + QFile file(dir.filePath(xmlFile)); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::warning(this, tr("ERROR"), + QString(tr("Failed to open file:") + "\n%1").arg(xmlFile)); + continue; + } + + QXmlStreamReader xmlReader(&file); + QJsonArray titleIdsArray; + + while (!xmlReader.atEnd() && !xmlReader.hasError()) { + QXmlStreamReader::TokenType token = xmlReader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (xmlReader.name() == QStringLiteral("ID")) { + titleIdsArray.append(xmlReader.readElementText()); + } + } + } + + if (xmlReader.hasError()) { + QMessageBox::warning(this, tr("ERROR"), + QString(tr("XML ERROR:") + "\n%1").arg(xmlReader.errorString())); + } + filesObject[xmlFile] = titleIdsArray; + } + + QFile jsonFile(dir.absolutePath() + "/files.json"); + if (!jsonFile.open(QIODevice::WriteOnly)) { + QMessageBox::warning(this, tr("ERROR"), tr("Failed to open files.json for writing")); + return; + } + + QJsonDocument jsonDoc(filesObject); + jsonFile.write(jsonDoc.toJson()); + jsonFile.close(); +} + +void CheatsPatches::addCheatsToLayout(const QJsonArray& modsArray, const QJsonArray& creditsArray) { + QLayoutItem* item; + while ((item = rightLayout->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + m_cheats.clear(); + m_cheatCheckBoxes.clear(); + + int maxWidthButton = 0; + + for (const QJsonValue& modValue : modsArray) { + QJsonObject modObject = modValue.toObject(); + QString modName = modObject["name"].toString(); + QString modType = modObject["type"].toString(); + + Cheat cheat; + cheat.name = modName; + cheat.type = modType; + + QJsonArray memoryArray = modObject["memory"].toArray(); + for (const QJsonValue& memoryValue : memoryArray) { + QJsonObject memoryObject = memoryValue.toObject(); + MemoryMod memoryMod; + memoryMod.offset = memoryObject["offset"].toString(); + memoryMod.on = memoryObject["on"].toString(); + memoryMod.off = memoryObject["off"].toString(); + cheat.memoryMods.append(memoryMod); + } + + // Check for the presence of 'hint' field + cheat.hasHint = modObject.contains("hint"); + + m_cheats[modName] = cheat; + + if (modType == "checkbox") { + QCheckBox* cheatCheckBox = new QCheckBox(modName); + rightLayout->addWidget(cheatCheckBox); + m_cheatCheckBoxes.append(cheatCheckBox); + connect(cheatCheckBox, &QCheckBox::toggled, + [this, modName](bool checked) { applyCheat(modName, checked); }); + } else if (modType == "button") { + QPushButton* cheatButton = new QPushButton(modName); + cheatButton->adjustSize(); + int buttonWidth = cheatButton->sizeHint().width(); + if (buttonWidth > maxWidthButton) { + maxWidthButton = buttonWidth; + } + + // Create a horizontal layout for buttons + QHBoxLayout* buttonLayout = new QHBoxLayout(); + buttonLayout->setContentsMargins(0, 0, 0, 0); + buttonLayout->addWidget(cheatButton); + buttonLayout->addStretch(); + + rightLayout->addLayout(buttonLayout); + connect(cheatButton, &QPushButton::clicked, + [this, modName]() { applyCheat(modName, true); }); + } + } + + // Set minimum and fixed size for all buttons + 20 + for (int i = 0; i < rightLayout->count(); ++i) { + QLayoutItem* layoutItem = rightLayout->itemAt(i); + QWidget* widget = layoutItem->widget(); + if (widget) { + QPushButton* button = qobject_cast(widget); + if (button) { + button->setMinimumWidth(maxWidthButton); + button->setFixedWidth(maxWidthButton + 20); + } + } else { + QLayout* layout = layoutItem->layout(); + if (layout) { + for (int j = 0; j < layout->count(); ++j) { + QLayoutItem* innerItem = layout->itemAt(j); + QWidget* innerWidget = innerItem->widget(); + if (innerWidget) { + QPushButton* button = qobject_cast(innerWidget); + if (button) { + button->setMinimumWidth(maxWidthButton); + button->setFixedWidth(maxWidthButton + 20); + } + } + } + } + } + } + + // Set credits label + QLabel* creditsLabel = new QLabel(); + QString creditsText = tr("Author: "); + if (!creditsArray.isEmpty()) { + creditsText += creditsArray[0].toString(); + } + creditsLabel->setText(creditsText); + creditsLabel->setAlignment(Qt::AlignLeft); + rightLayout->addWidget(creditsLabel); +} + +void CheatsPatches::populateFileListCheats() { + QString cheatsDir; + Common::FS::PathToQString(cheatsDir, Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); + + QString fullGameVersion = m_gameVersion; + QString modifiedGameVersion = m_gameVersion.mid(1); + + QString patternWithFirstChar = m_gameSerial + "_" + fullGameVersion + "*.json"; + QString patternWithoutFirstChar = m_gameSerial + "_" + modifiedGameVersion + "*.json"; + + QDir dir(cheatsDir); + QStringList filters; + filters << patternWithFirstChar << patternWithoutFirstChar; + dir.setNameFilters(filters); + + QFileInfoList fileList = dir.entryInfoList(QDir::Files); + QStringList fileNames; + + for (const QFileInfo& fileInfo : fileList) { + fileNames << fileInfo.fileName(); + } + + QStringListModel* model = new QStringListModel(fileNames, this); + listView_selectFile->setModel(model); + + connect(listView_selectFile->selectionModel(), &QItemSelectionModel::selectionChanged, this, + [this]() { + QModelIndexList selectedIndexes = + listView_selectFile->selectionModel()->selectedIndexes(); + if (!selectedIndexes.isEmpty()) { + + QString selectedFileName = selectedIndexes.first().data().toString(); + QString cheatsDir; + Common::FS::PathToQString( + cheatsDir, Common::FS::GetUserPath(Common::FS::PathType::CheatsDir)); + + QFile file(cheatsDir + "/" + selectedFileName); + if (file.open(QIODevice::ReadOnly)) { + QByteArray jsonData = file.readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + QJsonArray modsArray = jsonObject["mods"].toArray(); + QJsonArray creditsArray = jsonObject["credits"].toArray(); + addCheatsToLayout(modsArray, creditsArray); + } + } + }); + + if (!fileNames.isEmpty()) { + QModelIndex firstIndex = model->index(0, 0); + listView_selectFile->selectionModel()->select(firstIndex, QItemSelectionModel::Select | + QItemSelectionModel::Rows); + listView_selectFile->setCurrentIndex(firstIndex); + } +} + +void CheatsPatches::addPatchesToLayout(const QString& filePath) { + if (filePath == "") { + return; + } + QString folderPath = filePath.section(" | ", 1, 1); + + // Clear existing layout items + QLayoutItem* item; + while ((item = patchesGroupBoxLayout->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + m_patchInfos.clear(); + + QDir dir(Common::FS::GetUserPath(Common::FS::PathType::PatchesDir)); + QString fullPath = dir.filePath(folderPath); + + if (!dir.exists(fullPath)) { + QMessageBox::warning(this, tr("ERROR"), + QString(tr("Directory does not exist:") + "\n%1").arg(fullPath)); + return; + } + dir.setPath(fullPath); + + QString filesJsonPath = dir.filePath("files.json"); + + QFile jsonFile(filesJsonPath); + if (!jsonFile.open(QIODevice::ReadOnly)) { + QMessageBox::warning(this, tr("ERROR"), tr("Failed to open files.json for reading.")); + return; + } + + QByteArray jsonData = jsonFile.readAll(); + jsonFile.close(); + + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); + QJsonObject jsonObject = jsonDoc.object(); + + bool patchAdded = false; + + // Iterate over each entry in the JSON file + for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) { + QString xmlFileName = it.key(); + QJsonArray idsArray = it.value().toArray(); + + // Check if the serial is in the ID list + if (idsArray.contains(QJsonValue(m_gameSerial))) { + QString xmlFilePath = dir.filePath(xmlFileName); + QFile xmlFile(xmlFilePath); + + if (!xmlFile.open(QIODevice::ReadOnly)) { + QMessageBox::warning( + this, tr("ERROR"), + QString(tr("Failed to open file:") + "\n%1").arg(xmlFile.fileName())); + continue; + } + QXmlStreamReader xmlReader(&xmlFile); + QString patchName; + QString patchAuthor; + QString patchNote; + QJsonArray patchLines; + bool isEnabled = false; + + while (!xmlReader.atEnd() && !xmlReader.hasError()) { + xmlReader.readNext(); + + if (xmlReader.tokenType() == QXmlStreamReader::StartElement) { + if (xmlReader.name() == QStringLiteral("Metadata")) { + QXmlStreamAttributes attributes = xmlReader.attributes(); + QString appVer = attributes.value("AppVer").toString(); + if (appVer == m_gameVersion) { + patchName = attributes.value("Name").toString(); + patchAuthor = attributes.value("Author").toString(); + patchNote = attributes.value("Note").toString(); + isEnabled = + attributes.value("isEnabled").toString() == QStringLiteral("true"); + } + if (appVer == "mask") { + patchName = attributes.value("Name").toString() + " (any version)"; + patchAuthor = attributes.value("Author").toString(); + patchNote = attributes.value("Note").toString(); + isEnabled = + attributes.value("isEnabled").toString() == QStringLiteral("true"); + } + } else if (xmlReader.name() == QStringLiteral("PatchList")) { + QJsonArray linesArray; + while (!xmlReader.atEnd() && + !(xmlReader.tokenType() == QXmlStreamReader::EndElement && + xmlReader.name() == QStringLiteral("PatchList"))) { + xmlReader.readNext(); + if (xmlReader.tokenType() == QXmlStreamReader::StartElement && + xmlReader.name() == QStringLiteral("Line")) { + QXmlStreamAttributes attributes = xmlReader.attributes(); + QJsonObject lineObject; + lineObject["Type"] = attributes.value("Type").toString(); + lineObject["Address"] = attributes.value("Address").toString(); + lineObject["Value"] = attributes.value("Value").toString(); + linesArray.append(lineObject); + } + } + patchLines = linesArray; + } + } + + if (!patchName.isEmpty() && !patchLines.isEmpty()) { + QCheckBox* patchCheckBox = new QCheckBox(patchName); + patchCheckBox->setChecked(isEnabled); + patchesGroupBoxLayout->addWidget(patchCheckBox); + + PatchInfo patchInfo; + patchInfo.name = patchName; + patchInfo.author = patchAuthor; + patchInfo.note = patchNote; + patchInfo.linesArray = patchLines; + patchInfo.serial = m_gameSerial; + m_patchInfos[patchName] = patchInfo; + + patchCheckBox->installEventFilter(this); + + connect(patchCheckBox, &QCheckBox::toggled, + [this, patchName](bool checked) { applyPatch(patchName, checked); }); + + patchName.clear(); + patchAuthor.clear(); + patchNote.clear(); + patchLines = QJsonArray(); + patchAdded = true; + } + } + xmlFile.close(); + } + } + + // Remove the item from the list view if no patches were added (the game has patches, but not + // for the current version) + if (!patchAdded) { + QStringListModel* model = qobject_cast(patchesListView->model()); + if (model) { + QStringList items = model->stringList(); + int index = items.indexOf(filePath); + if (index != -1) { + items.removeAt(index); + model->setStringList(items); + } + } + } +} + +void CheatsPatches::updateNoteTextEdit(const QString& patchName) { + if (m_patchInfos.contains(patchName)) { + const PatchInfo& patchInfo = m_patchInfos[patchName]; + QString text = QString(tr("Name:") + " %1\n" + tr("Author: ") + "%2\n\n%3") + .arg(patchInfo.name) + .arg(patchInfo.author) + .arg(patchInfo.note); + + foreach (const QJsonValue& value, patchInfo.linesArray) { + QJsonObject lineObject = value.toObject(); + QString type = lineObject["Type"].toString(); + QString address = lineObject["Address"].toString(); + QString patchValue = lineObject["Value"].toString(); + + // add the values ​​to be modified in instructionsTextEdit + // text.append(QString("\nType: %1\nAddress: %2\n\nValue: %3") + // .arg(type) + // .arg(address) + // .arg(patchValue)); + } + text.replace("\\n", "\n"); + instructionsTextEdit->setText(text); + } +} + +bool showErrorMessage = true; +void CheatsPatches::uncheckAllCheatCheckBoxes() { + for (auto& cheatCheckBox : m_cheatCheckBoxes) { + cheatCheckBox->setChecked(false); + } + showErrorMessage = true; +} + +void CheatsPatches::applyCheat(const QString& modName, bool enabled) { + if (!m_cheats.contains(modName)) + return; + + if (MemoryPatcher::g_eboot_address == 0 && enabled) { + QMessageBox::critical(this, tr("Error"), + tr("Can't apply cheats before the game is started")); + uncheckAllCheatCheckBoxes(); + return; + } + + Cheat cheat = m_cheats[modName]; + + for (const MemoryMod& memoryMod : cheat.memoryMods) { + QString value = enabled ? memoryMod.on : memoryMod.off; + + std::string modNameStr = modName.toStdString(); + std::string offsetStr = memoryMod.offset.toStdString(); + std::string valueStr = value.toStdString(); + + if (MemoryPatcher::g_eboot_address == 0) + return; + + // Determine if the hint field is present + bool isHintPresent = m_cheats[modName].hasHint; + MemoryPatcher::PatchMemory(modNameStr, offsetStr, valueStr, !isHintPresent, false); + } +} + +void CheatsPatches::applyPatch(const QString& patchName, bool enabled) { + if (!enabled) + return; + if (m_patchInfos.contains(patchName)) { + const PatchInfo& patchInfo = m_patchInfos[patchName]; + + foreach (const QJsonValue& value, patchInfo.linesArray) { + QJsonObject lineObject = value.toObject(); + QString type = lineObject["Type"].toString(); + QString address = lineObject["Address"].toString(); + QString patchValue = lineObject["Value"].toString(); + QString maskOffsetStr = lineObject["Offset"].toString(); + + patchValue = QString::fromStdString( + MemoryPatcher::convertValueToHex(type.toStdString(), patchValue.toStdString())); + + bool littleEndian = false; + + if (type == "bytes16") { + littleEndian = true; + } else if (type == "bytes32") { + littleEndian = true; + } else if (type == "bytes64") { + littleEndian = true; + } + + MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None; + int maskOffsetValue = 0; + + if (type == "mask") { + patchMask = MemoryPatcher::PatchMask::Mask; + + // im not sure if this works, there is no games to test the mask offset on yet + if (!maskOffsetStr.toStdString().empty()) + maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); + } + + if (type == "mask_jump32") + patchMask = MemoryPatcher::PatchMask::Mask_Jump32; + + if (MemoryPatcher::g_eboot_address == 0) { + MemoryPatcher::patchInfo addingPatch; + addingPatch.gameSerial = patchInfo.serial.toStdString(); + addingPatch.modNameStr = patchName.toStdString(); + addingPatch.offsetStr = address.toStdString(); + addingPatch.valueStr = patchValue.toStdString(); + addingPatch.isOffset = false; + addingPatch.littleEndian = littleEndian; + addingPatch.patchMask = patchMask; + addingPatch.maskOffset = maskOffsetValue; + + MemoryPatcher::AddPatchToQueue(addingPatch); + continue; + } + MemoryPatcher::PatchMemory(patchName.toStdString(), address.toStdString(), + patchValue.toStdString(), false, littleEndian, patchMask); + } + } +} + +bool CheatsPatches::eventFilter(QObject* obj, QEvent* event) { + if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave) { + QCheckBox* checkBox = qobject_cast(obj); + if (checkBox) { + bool hovered = (event->type() == QEvent::HoverEnter); + onPatchCheckBoxHovered(checkBox, hovered); + return true; + } + } + // Pass the event on to base class + return QWidget::eventFilter(obj, event); +} + +void CheatsPatches::onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered) { + if (hovered) { + QString text = checkBox->text(); + updateNoteTextEdit(text); + } else { + instructionsTextEdit->setText(defaultTextEdit); + } +} \ No newline at end of file diff --git a/src/qt_gui/cheats_patches.h b/src/qt_gui/cheats_patches.h new file mode 100644 index 000000000..a9932886c --- /dev/null +++ b/src/qt_gui/cheats_patches.h @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef CHEATS_PATCHES_H +#define CHEATS_PATCHES_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class CheatsPatches : public QWidget { + Q_OBJECT + +public: + CheatsPatches(const QString& gameName, const QString& gameSerial, const QString& gameVersion, + const QString& gameSize, const QPixmap& gameImage, QWidget* parent = nullptr); + ~CheatsPatches(); + + // Public Methods + void downloadCheats(const QString& source, const QString& m_gameSerial, + const QString& m_gameVersion, bool showMessageBox); + void downloadPatches(const QString repository, const bool showMessageBox); + void createFilesJson(const QString& repository); + +signals: + void downloadFinished(); + +private: + // UI Setup and Event Handlers + void setupUI(); + void onSaveButtonClicked(); + QCheckBox* findCheckBoxByName(const QString& name); + bool eventFilter(QObject* obj, QEvent* event); + void onPatchCheckBoxHovered(QCheckBox* checkBox, bool hovered); + + // Cheat and Patch Management + void populateFileListCheats(); + void populateFileListPatches(); + + void addCheatsToLayout(const QJsonArray& modsArray, const QJsonArray& creditsArray); + void addPatchesToLayout(const QString& serial); + + void applyCheat(const QString& modName, bool enabled); + void applyPatch(const QString& patchName, bool enabled); + + void uncheckAllCheatCheckBoxes(); + void updateNoteTextEdit(const QString& patchName); + + // Network Manager + QNetworkAccessManager* manager; + + // Patch Info Structures + struct MemoryMod { + QString offset; + QString on; + QString off; + }; + + struct Cheat { + QString name; + QString type; + bool hasHint; + QVector memoryMods; + }; + + struct PatchInfo { + QString name; + QString author; + QString note; + QJsonArray linesArray; + QString serial; + }; + + // Members + QString m_gameName; + QString m_gameSerial; + QString m_gameVersion; + QString m_gameSize; + QPixmap m_gameImage; + QString m_cheatFilePath; + QMap m_cheats; + QMap m_patchInfos; + QVector m_cheatCheckBoxes; + + // UI Elements + QVBoxLayout* rightLayout; + QVBoxLayout* patchesGroupBoxLayout; + QGroupBox* patchesGroupBox; + QVBoxLayout* patchesLayout; + QTextEdit* instructionsTextEdit; + QListView* listView_selectFile; + QItemSelectionModel* selectionModel; + QComboBox* patchesComboBox; + QListView* patchesListView; + + QString defaultTextEdit; +}; + +#endif // CHEATS_PATCHES_H \ No newline at end of file diff --git a/src/qt_gui/check_update.cpp b/src/qt_gui/check_update.cpp new file mode 100644 index 000000000..ca6009ca3 --- /dev/null +++ b/src/qt_gui/check_update.cpp @@ -0,0 +1,549 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "check_update.h" + +using namespace Common::FS; +namespace fs = std::filesystem; + +CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent) + : QDialog(parent), networkManager(new QNetworkAccessManager(this)) { + setWindowTitle(tr("Auto Updater")); + setFixedSize(0, 0); + CheckForUpdates(showMessage); +} + +CheckUpdate::~CheckUpdate() {} + +void CheckUpdate::CheckForUpdates(const bool showMessage) { + QString updateChannel; + QUrl url; + + bool checkName = true; + while (checkName) { + updateChannel = QString::fromStdString(Config::getUpdateChannel()); + if (updateChannel == "Nightly") { + url = QUrl("https://api.github.com/repos/shadps4-emu/shadPS4/releases"); + checkName = false; + } else if (updateChannel == "Release") { + url = QUrl("https://api.github.com/repos/shadps4-emu/shadPS4/releases/latest"); + checkName = false; + } else { + if (Common::isRelease) { + Config::setUpdateChannel("Release"); + } else { + Config::setUpdateChannel("Nightly"); + } + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + Config::save(config_dir / "config.toml"); + } + } + + QNetworkRequest request(url); + QNetworkReply* reply = networkManager->get(request); + + connect(reply, &QNetworkReply::finished, this, [this, reply, showMessage, updateChannel]() { + if (reply->error() != QNetworkReply::NoError) { + QMessageBox::warning(this, tr("Error"), + QString(tr("Network error:") + "\n" + reply->errorString())); + reply->deleteLater(); + return; + } + + QByteArray response = reply->readAll(); + QJsonDocument jsonDoc(QJsonDocument::fromJson(response)); + + if (jsonDoc.isNull()) { + QMessageBox::warning(this, tr("Error"), tr("Failed to parse update information.")); + reply->deleteLater(); + return; + } + + QString downloadUrl; + QString latestVersion; + QString latestRev; + QString latestDate; + QString platformString; + +#ifdef Q_OS_WIN + platformString = "win64-qt"; +#elif defined(Q_OS_LINUX) + platformString = "linux-qt"; +#elif defined(Q_OS_MAC) + platformString = "macos-qt"; +#endif + + QJsonObject jsonObj; + if (updateChannel == "Nightly") { + QJsonArray jsonArray = jsonDoc.array(); + for (const QJsonValue& value : jsonArray) { + jsonObj = value.toObject(); + if (jsonObj.contains("prerelease") && jsonObj["prerelease"].toBool()) { + break; + } + } + if (!jsonObj.isEmpty()) { + latestVersion = jsonObj["tag_name"].toString(); + } else { + QMessageBox::warning(this, tr("Error"), tr("No pre-releases found.")); + reply->deleteLater(); + return; + } + } else { + jsonObj = jsonDoc.object(); + if (jsonObj.contains("tag_name")) { + latestVersion = jsonObj["tag_name"].toString(); + } else { + QMessageBox::warning(this, tr("Error"), tr("Invalid release data.")); + reply->deleteLater(); + return; + } + } + + latestRev = latestVersion.right(7); + latestDate = jsonObj["published_at"].toString(); + + QJsonArray assets = jsonObj["assets"].toArray(); + bool found = false; + + for (const QJsonValue& assetValue : assets) { + QJsonObject assetObj = assetValue.toObject(); + if (assetObj["name"].toString().contains(platformString)) { + downloadUrl = assetObj["browser_download_url"].toString(); + found = true; + break; + } + } + + if (!found) { + QMessageBox::warning(this, tr("Error"), + tr("No download URL found for the specified asset.")); + reply->deleteLater(); + return; + } + + QString currentRev = QString::fromStdString(Common::g_scm_rev).left(7); + QString currentDate = Common::g_scm_date; + + QDateTime dateTime = QDateTime::fromString(latestDate, Qt::ISODate); + latestDate = dateTime.isValid() ? dateTime.toString("yyyy-MM-dd HH:mm:ss") : "Unknown date"; + + if (latestRev == currentRev) { + if (showMessage) { + QMessageBox::information(this, tr("Auto Updater"), + tr("Your version is already up to date!")); + } + close(); + return; + } else { + setupUI(downloadUrl, latestDate, latestRev, currentDate, currentRev); + } + reply->deleteLater(); + }); +} + +void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate, + const QString& latestRev, const QString& currentDate, + const QString& currentRev) { + QVBoxLayout* layout = new QVBoxLayout(this); + QHBoxLayout* titleLayout = new QHBoxLayout(); + + QLabel* imageLabel = new QLabel(this); + QPixmap pixmap(":/images/shadps4.ico"); + imageLabel->setPixmap(pixmap); + imageLabel->setScaledContents(true); + imageLabel->setFixedSize(50, 50); + + QLabel* titleLabel = new QLabel("

" + tr("Update Available") + "

", this); + titleLayout->addWidget(imageLabel); + titleLayout->addWidget(titleLabel); + layout->addLayout(titleLayout); + + QString updateChannel = QString::fromStdString(Config::getUpdateChannel()); + + QString updateText = + QString("


" + tr("Update Channel") + ":
" + updateChannel + "
" + + tr("Current Version") + ": %1 (%2)
" + tr("Latest Version") + + ": %3 (%4)

" + tr("Do you want to update?") + "

") + .arg(currentRev, currentDate, latestRev, latestDate); + QLabel* updateLabel = new QLabel(updateText, this); + layout->addWidget(updateLabel); + + // Setup bottom layout with action buttons + QHBoxLayout* bottomLayout = new QHBoxLayout(); + autoUpdateCheckBox = new QCheckBox(tr("Check for Updates at Startup"), this); + yesButton = new QPushButton(tr("Update"), this); + noButton = new QPushButton(tr("No"), this); + yesButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + noButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + bottomLayout->addWidget(autoUpdateCheckBox); + + QSpacerItem* spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + bottomLayout->addItem(spacer); + + bottomLayout->addWidget(yesButton); + bottomLayout->addWidget(noButton); + layout->addLayout(bottomLayout); + + // Don't show changelog button if: + // The current version is a pre-release and the version to be downloaded is a release. + bool current_isRelease = currentRev.startsWith('v', Qt::CaseInsensitive); + bool latest_isRelease = latestRev.startsWith('v', Qt::CaseInsensitive); + if (!current_isRelease && latest_isRelease) { + } else { + QTextEdit* textField = new QTextEdit(this); + textField->setReadOnly(true); + textField->setFixedWidth(500); + textField->setFixedHeight(200); + textField->setVisible(false); + layout->addWidget(textField); + + QPushButton* toggleButton = new QPushButton(tr("Show Changelog"), this); + layout->addWidget(toggleButton); + + connect(toggleButton, &QPushButton::clicked, + [this, textField, toggleButton, currentRev, latestRev, downloadUrl, latestDate, + currentDate]() { + QString updateChannel = QString::fromStdString(Config::getUpdateChannel()); + if (!textField->isVisible()) { + requestChangelog(currentRev, latestRev, downloadUrl, latestDate, + currentDate); + textField->setVisible(true); + toggleButton->setText(tr("Hide Changelog")); + adjustSize(); + } else { + textField->setVisible(false); + toggleButton->setText(tr("Show Changelog")); + adjustSize(); + } + }); + } + + connect(yesButton, &QPushButton::clicked, this, [this, downloadUrl]() { + yesButton->setEnabled(false); + noButton->setEnabled(false); + DownloadUpdate(downloadUrl); + }); + + connect(noButton, &QPushButton::clicked, this, [this]() { close(); }); + + autoUpdateCheckBox->setChecked(Config::autoUpdate()); + connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [](int state) { + const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + Config::setAutoUpdate(state == Qt::Checked); + Config::save(user_dir / "config.toml"); + }); + + setLayout(layout); +} + +void CheckUpdate::requestChangelog(const QString& currentRev, const QString& latestRev, + const QString& downloadUrl, const QString& latestDate, + const QString& currentDate) { + QString compareUrlString = + QString("https://api.github.com/repos/shadps4-emu/shadPS4/compare/%1...%2") + .arg(currentRev) + .arg(latestRev); + + QUrl compareUrl(compareUrlString); + QNetworkRequest compareRequest(compareUrl); + QNetworkReply* compareReply = networkManager->get(compareRequest); + + connect(compareReply, &QNetworkReply::finished, this, + [this, compareReply, downloadUrl, latestDate, latestRev, currentDate, currentRev]() { + if (compareReply->error() != QNetworkReply::NoError) { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Network error:") + "\n%1").arg(compareReply->errorString())); + compareReply->deleteLater(); + return; + } + + QByteArray compareResponse = compareReply->readAll(); + QJsonDocument compareJsonDoc(QJsonDocument::fromJson(compareResponse)); + QJsonObject compareJsonObj = compareJsonDoc.object(); + QJsonArray commits = compareJsonObj["commits"].toArray(); + + QString changes; + for (const QJsonValue& commitValue : commits) { + QJsonObject commitObj = commitValue.toObject(); + QString message = commitObj["commit"].toObject()["message"].toString(); + + // Remove texts after first line break, if any, to make it cleaner + int newlineIndex = message.indexOf('\n'); + if (newlineIndex != -1) { + message = message.left(newlineIndex); + } + if (!changes.isEmpty()) { + changes += "
"; + } + changes += "    • " + message; + } + + // Update the text field with the changelog + QTextEdit* textField = findChild(); + if (textField) { + textField->setHtml("

" + tr("Changes") + ":

" + changes); + } + + compareReply->deleteLater(); + }); +} + +void CheckUpdate::DownloadUpdate(const QString& url) { + QProgressBar* progressBar = new QProgressBar(this); + progressBar->setRange(0, 100); + progressBar->setTextVisible(true); + progressBar->setValue(0); + + layout()->addWidget(progressBar); + + QNetworkRequest request(url); + QNetworkReply* reply = networkManager->get(request); + + connect(reply, &QNetworkReply::downloadProgress, this, + [progressBar](qint64 bytesReceived, qint64 bytesTotal) { + if (bytesTotal > 0) { + int percentage = static_cast((bytesReceived * 100) / bytesTotal); + progressBar->setValue(percentage); + } + }); + + connect(reply, &QNetworkReply::finished, this, [this, reply, progressBar, url]() { + progressBar->setValue(100); + if (reply->error() != QNetworkReply::NoError) { + QMessageBox::warning(this, tr("Error"), + tr("Network error occurred while trying to access the URL") + + ":\n" + url + "\n" + reply->errorString()); + reply->deleteLater(); + progressBar->deleteLater(); + return; + } + + QString userPath; + Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir)); + QString tempDownloadPath = userPath + "/temp_download_update"; + QDir dir(tempDownloadPath); + if (!dir.exists()) { + dir.mkpath("."); + } + + QString downloadPath = tempDownloadPath + "/temp_download_update.zip"; + QFile file(downloadPath); + if (file.open(QIODevice::WriteOnly)) { + file.write(reply->readAll()); + file.close(); + QMessageBox::information(this, tr("Download Complete"), + tr("The update has been downloaded, press OK to install.")); + Install(); + } else { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to save the update file at") + ":\n" + downloadPath)); + } + + reply->deleteLater(); + progressBar->deleteLater(); + }); +} + +void CheckUpdate::Install() { + QString userPath; + Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir)); + + QString rootPath; + Common::FS::PathToQString(rootPath, std::filesystem::current_path()); + + QString tempDirPath = userPath + "/temp_download_update"; + QString startingUpdate = tr("Starting Update..."); + + QString binaryStartingUpdate; + for (QChar c : startingUpdate) { + binaryStartingUpdate.append(QString::number(c.unicode(), 2).rightJustified(16, '0')); + } + + QString scriptContent; + QString scriptFileName; + QStringList arguments; + QString processCommand; + +#ifdef Q_OS_WIN + // Windows Batch Script + scriptFileName = tempDirPath + "/update.ps1"; + scriptContent = QStringLiteral( + "Set-ExecutionPolicy Bypass -Scope Process -Force\n" + "$binaryStartingUpdate = '%1'\n" + "$chars = @()\n" + "for ($i = 0; $i -lt $binaryStartingUpdate.Length; $i += 16) {\n" + " $chars += [char]([convert]::ToInt32($binaryStartingUpdate.Substring($i, 16), 2))\n" + "}\n" + "$startingUpdate = -join $chars\n" + "Write-Output $startingUpdate\n" + "Expand-Archive -Path '%2\\temp_download_update.zip' -DestinationPath '%2' -Force\n" + "Start-Sleep -Seconds 3\n" + "Copy-Item -Recurse -Force '%2\\*' '%3\\'\n" + "Start-Sleep -Seconds 2\n" + "Remove-Item -Force '%3\\update.ps1'\n" + "Remove-Item -Force '%3\\temp_download_update.zip'\n" + "Start-Process '%3\\shadps4.exe'\n" + "Remove-Item -Recurse -Force '%2'\n"); + arguments << "-ExecutionPolicy" + << "Bypass" + << "-File" << scriptFileName; + processCommand = "powershell.exe"; + +#elif defined(Q_OS_LINUX) + // Linux Shell Script + scriptFileName = tempDirPath + "/update.sh"; + scriptContent = QStringLiteral( + "#!/bin/bash\n" + "check_unzip() {\n" + " if ! command -v unzip &> /dev/null && ! command -v 7z &> /dev/null; then\n" + " echo \"Neither 'unzip' nor '7z' is installed.\"\n" + " read -p \"Would you like to install 'unzip'? (y/n): \" response\n" + " if [[ \"$response\" == \"y\" || \"$response\" == \"Y\" ]]; then\n" + " if [[ -f /etc/os-release ]]; then\n" + " . /etc/os-release\n" + " case \"$ID\" in\n" + " ubuntu|debian)\n" + " sudo apt-get install unzip -y\n" + " ;;\n" + " fedora|redhat)\n" + " sudo dnf install unzip -y\n" + " ;;\n" + " *)\n" + " echo \"Unsupported distribution for automatic installation.\"\n" + " exit 1\n" + " ;;\n" + " esac\n" + " else\n" + " echo \"Could not identify the distribution.\"\n" + " exit 1\n" + " fi\n" + " else\n" + " echo \"At least one of 'unzip' or '7z' is required to continue. The process " + "will be terminated.\"\n" + " exit 1\n" + " fi\n" + " fi\n" + "}\n" + "extract_file() {\n" + " if command -v unzip &> /dev/null; then\n" + " unzip -o \"%2/temp_download_update.zip\" -d \"%2/\"\n" + " elif command -v 7z &> /dev/null; then\n" + " 7z x \"%2/temp_download_update.zip\" -o\"%2/\" -y\n" + " else\n" + " echo \"No suitable extraction tool found.\"\n" + " exit 1\n" + " fi\n" + "}\n" + "main() {\n" + " check_unzip\n" + " echo \"%1\"\n" + " sleep 2\n" + " extract_file\n" + " sleep 2\n" + " if pgrep -f \"Shadps4-qt.AppImage\" > /dev/null; then\n" + " pkill -f \"Shadps4-qt.AppImage\"\n" + " sleep 2\n" + " fi\n" + " cp -r \"%2/\"* \"%3/\"\n" + " sleep 2\n" + " rm \"%3/update.sh\"\n" + " rm \"%3/temp_download_update.zip\"\n" + " chmod +x \"%3/Shadps4-qt.AppImage\"\n" + " rm -r \"%2\"\n" + " cd \"%3\" && ./Shadps4-qt.AppImage\n" + "}\n" + "main\n"); + arguments << scriptFileName; + processCommand = "bash"; + +#elif defined(Q_OS_MAC) + // macOS Shell Script + scriptFileName = tempDirPath + "/update.sh"; + scriptContent = QStringLiteral( + "#!/bin/bash\n" + "check_tools() {\n" + " if ! command -v unzip &> /dev/null && ! command -v tar &> /dev/null; then\n" + " echo \"Neither 'unzip' nor 'tar' is installed.\"\n" + " read -p \"Would you like to install 'unzip'? (y/n): \" response\n" + " if [[ \"$response\" == \"y\" || \"$response\" == \"Y\" ]]; then\n" + " echo \"Please install 'unzip' using Homebrew or another package manager.\"\n" + " exit 1\n" + " else\n" + " echo \"At least one of 'unzip' or 'tar' is required to continue. The process " + "will be terminated.\"\n" + " exit 1\n" + " fi\n" + " fi\n" + "}\n" + "check_tools\n" + "echo \"%1\"\n" + "sleep 2\n" + "unzip -o \"%2/temp_download_update.zip\" -d \"%2/\"\n" + "sleep 2\n" + "tar -xzf \"%2/shadps4-macos-qt.tar.gz\" -C \"%3\"\n" + "sleep 2\n" + "rm \"%3/update.sh\"\n" + "chmod +x \"%3/shadps4.app/Contents/MacOS/shadps4\"\n" + "open \"%3/shadps4.app\"\n" + "rm -r \"%2\"\n"); + + arguments << scriptFileName; + processCommand = "bash"; + +#else + QMessageBox::warning(this, tr("Error"), "Unsupported operating system."); + return; +#endif + + QFile scriptFile(scriptFileName); + if (scriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&scriptFile); +#ifdef Q_OS_WIN + out << scriptContent.arg(binaryStartingUpdate).arg(tempDirPath).arg(rootPath); +#endif +#if defined(Q_OS_LINUX) || defined(Q_OS_MAC) + out << scriptContent.arg(startingUpdate).arg(tempDirPath).arg(rootPath); +#endif + scriptFile.close(); + +// Make the script executable on Unix-like systems +#if defined(Q_OS_LINUX) || defined(Q_OS_MAC) + scriptFile.setPermissions(QFileDevice::ExeOwner | QFileDevice::ReadOwner | + QFileDevice::WriteOwner); +#endif + + QProcess::startDetached(processCommand, arguments); + + exit(EXIT_SUCCESS); + } else { + QMessageBox::warning( + this, tr("Error"), + QString(tr("Failed to create the update script file") + ":\n" + scriptFileName)); + } +} diff --git a/src/qt_gui/check_update.h b/src/qt_gui/check_update.h new file mode 100644 index 000000000..dfeb95e73 --- /dev/null +++ b/src/qt_gui/check_update.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef CHECKUPDATE_H +#define CHECKUPDATE_H + +#include +#include +#include +#include + +class CheckUpdate : public QDialog { + Q_OBJECT + +public: + explicit CheckUpdate(const bool showMessage, QWidget* parent = nullptr); + ~CheckUpdate(); + +private slots: + void CheckForUpdates(const bool showMessage); + void DownloadUpdate(const QString& url); + void Install(); + +private: + void setupUI(const QString& downloadUrl, const QString& latestDate, const QString& latestRev, + const QString& currentDate, const QString& currentRev); + + void requestChangelog(const QString& currentRev, const QString& latestRev, + const QString& downloadUrl, const QString& latestDate, + const QString& currentDate); + + QCheckBox* autoUpdateCheckBox; + QPushButton* yesButton; + QPushButton* noButton; + QString updateDownloadUrl; + + QNetworkAccessManager* networkManager; +}; + +#endif // CHECKUPDATE_H diff --git a/src/qt_gui/elf_viewer.cpp b/src/qt_gui/elf_viewer.cpp index 72861d15f..e80fa25c1 100644 --- a/src/qt_gui/elf_viewer.cpp +++ b/src/qt_gui/elf_viewer.cpp @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include - #include "elf_viewer.h" ElfViewer::ElfViewer(QWidget* parent) : QTableWidget(parent) { diff --git a/src/qt_gui/elf_viewer.h b/src/qt_gui/elf_viewer.h index a3b85223d..1a65d70de 100644 --- a/src/qt_gui/elf_viewer.h +++ b/src/qt_gui/elf_viewer.h @@ -3,17 +3,7 @@ #pragma once -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include "core/loader/elf.h" #include "game_list_frame.h" diff --git a/src/qt_gui/game_grid_frame.cpp b/src/qt_gui/game_grid_frame.cpp index 3d5ab14ec..b932e46c3 100644 --- a/src/qt_gui/game_grid_frame.cpp +++ b/src/qt_gui/game_grid_frame.cpp @@ -22,7 +22,7 @@ GameGridFrame::GameGridFrame(std::shared_ptr game_info_get, QWidg this->setContextMenuPolicy(Qt::CustomContextMenu); PopulateGameGrid(m_game_info->m_games, false); - connect(this, &QTableWidget::cellClicked, this, &GameGridFrame::SetGridBackgroundImage); + connect(this, &QTableWidget::currentCellChanged, this, &GameGridFrame::onCurrentCellChanged); connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, &GameGridFrame::RefreshGridBackgroundImage); @@ -31,12 +31,33 @@ GameGridFrame::GameGridFrame(std::shared_ptr game_info_get, QWidg connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) { m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, this, false); }); - connect(this, &QTableWidget::cellClicked, this, [&]() { - cellClicked = true; - crtRow = this->currentRow(); - crtColumn = this->currentColumn(); - columnCnt = this->columnCount(); - }); +} + +void GameGridFrame::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, + int previousColumn) { + cellClicked = true; + crtRow = currentRow; + crtColumn = currentColumn; + columnCnt = this->columnCount(); + + auto itemID = (crtRow * columnCnt) + currentColumn; + if (itemID > m_game_info->m_games.count() - 1) { + validCellSelected = false; + BackgroundMusicPlayer::getInstance().stopMusic(); + return; + } + validCellSelected = true; + SetGridBackgroundImage(crtRow, crtColumn); + auto snd0Path = QString::fromStdString(m_game_info->m_games[itemID].snd0_path.string()); + PlayBackgroundMusic(snd0Path); +} + +void GameGridFrame::PlayBackgroundMusic(QString path) { + if (path.isEmpty() || !Config::getPlayBGM()) { + BackgroundMusicPlayer::getInstance().stopMusic(); + return; + } + BackgroundMusicPlayer::getInstance().playMusic(path); } void GameGridFrame::PopulateGameGrid(QVector m_games_search, bool fromSearch) { @@ -81,7 +102,9 @@ void GameGridFrame::PopulateGameGrid(QVector m_games_search, bool from name_label->setGraphicsEffect(shadowEffect); widget->setLayout(layout); - QString tooltipText = QString::fromStdString(m_games_[gameCounter].name); + QString tooltipText = QString::fromStdString(m_games_[gameCounter].name + " (" + + m_games_[gameCounter].version + ", " + + m_games_[gameCounter].region + ")"); widget->setToolTip(tooltipText); QString tooltipStyle = QString("QToolTip {" "background-color: #ffffff;" @@ -113,14 +136,12 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) { int itemID = (row * this->columnCount()) + column; QWidget* item = this->cellWidget(row, column); if (item) { - QString pic1Path = QString::fromStdString((*m_games_shared)[itemID].pic_path); - const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / - "game_data" / (*m_games_shared)[itemID].serial / "pic1.png"; -#ifdef _WIN32 - const auto blurredPic1PathQt = QString::fromStdWString(blurredPic1Path.wstring()); -#else - const auto blurredPic1PathQt = QString::fromStdString(blurredPic1Path.string()); -#endif + QString pic1Path; + Common::FS::PathToQString(pic1Path, (*m_games_shared)[itemID].pic_path); + const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / + (*m_games_shared)[itemID].serial / "pic1.png"; + QString blurredPic1PathQt; + Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path); backgroundImage = QImage(blurredPic1PathQt); if (backgroundImage.isNull()) { @@ -128,7 +149,8 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) { backgroundImage = m_game_list_utils.BlurImage(image, image.rect(), 16); std::filesystem::path img_path = - std::filesystem::path("user/game_data/") / (*m_games_shared)[itemID].serial; + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / + (*m_games_shared)[itemID].serial; std::filesystem::create_directories(img_path); if (!backgroundImage.save(blurredPic1PathQt, "PNG")) { // qDebug() << "Error: Unable to save image."; @@ -148,3 +170,7 @@ void GameGridFrame::RefreshGridBackgroundImage() { this->setPalette(palette); } } + +bool GameGridFrame::IsValidCellSelected() { + return validCellSelected; +} diff --git a/src/qt_gui/game_grid_frame.h b/src/qt_gui/game_grid_frame.h index ce775315e..c09767684 100644 --- a/src/qt_gui/game_grid_frame.h +++ b/src/qt_gui/game_grid_frame.h @@ -3,18 +3,9 @@ #pragma once -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include "background_music_player.h" #include "common/config.h" #include "game_info.h" #include "game_list_utils.h" @@ -29,6 +20,9 @@ Q_SIGNALS: public Q_SLOTS: void SetGridBackgroundImage(int row, int column); void RefreshGridBackgroundImage(); + void PlayBackgroundMusic(QString path); + void onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, + int previousColumn); private: QImage backgroundImage; @@ -36,10 +30,12 @@ private: GuiContextMenus m_gui_context_menus; std::shared_ptr m_game_info; std::shared_ptr> m_games_shared; + bool validCellSelected = false; public: explicit GameGridFrame(std::shared_ptr game_info_get, QWidget* parent = nullptr); void PopulateGameGrid(QVector m_games, bool fromSearch); + bool IsValidCellSelected(); bool cellClicked = false; int icon_size; diff --git a/src/qt_gui/game_info.cpp b/src/qt_gui/game_info.cpp index 0a472eaef..48643f8ed 100644 --- a/src/qt_gui/game_info.cpp +++ b/src/qt_gui/game_info.cpp @@ -1,33 +1,34 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include #include -#include +#include "common/path_util.h" #include "game_info.h" GameInfoClass::GameInfoClass() = default; GameInfoClass::~GameInfoClass() = default; void GameInfoClass::GetGameInfo(QWidget* parent) { - QString installDir = QString::fromStdString(Config::getGameInstallDir()); QStringList filePaths; - QDir parentFolder(installDir); - QFileInfoList fileList = parentFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - for (const auto& fileInfo : fileList) { - if (fileInfo.isDir()) { - filePaths.append(fileInfo.absoluteFilePath()); + for (const auto& installLoc : Config::getGameInstallDirs()) { + QString installDir; + Common::FS::PathToQString(installDir, installLoc); + QDir parentFolder(installDir); + QFileInfoList fileList = parentFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const auto& fileInfo : fileList) { + if (fileInfo.isDir() && !fileInfo.filePath().endsWith("-UPDATE")) { + filePaths.append(fileInfo.absoluteFilePath()); + } } } m_games = QtConcurrent::mapped(filePaths, [&](const QString& path) { - return readGameInfo(path.toStdString()); + return readGameInfo(Common::FS::PathFromQString(path)); }).results(); // Progress bar, please be patient :) - QProgressDialog dialog("Loading game list, please wait :3", "Cancel", 0, 0, parent); - dialog.setWindowTitle("Loading..."); + QProgressDialog dialog(tr("Loading game list, please wait :3"), tr("Cancel"), 0, 0, parent); + dialog.setWindowTitle(tr("Loading...")); QFutureWatcher futureWatcher; GameListUtils game_util; diff --git a/src/qt_gui/game_info.h b/src/qt_gui/game_info.h index b2b102e00..99805cd52 100644 --- a/src/qt_gui/game_info.h +++ b/src/qt_gui/game_info.h @@ -3,10 +3,8 @@ #pragma once -#include -#include -#include -#include +#include +#include #include "common/config.h" #include "core/file_format/psf.h" @@ -24,26 +22,53 @@ public: return a.name < b.name; } - static GameInfo readGameInfo(const std::string& filePath) { + static GameInfo readGameInfo(const std::filesystem::path& filePath) { GameInfo game; game.path = filePath; + std::filesystem::path sce_folder_path = filePath / "sce_sys" / "param.sfo"; + std::filesystem::path game_update_path = filePath; + game_update_path += "-UPDATE"; + if (std::filesystem::exists(game_update_path / "sce_sys" / "param.sfo")) { + sce_folder_path = game_update_path / "sce_sys" / "param.sfo"; + } PSF psf; - if (psf.open(game.path + "/sce_sys/param.sfo", {})) { - game.icon_path = game.path + "/sce_sys/icon0.png"; - QString iconpath = QString::fromStdString(game.icon_path); + if (psf.Open(sce_folder_path)) { + game.icon_path = game.path / "sce_sys" / "icon0.png"; + QString iconpath; + Common::FS::PathToQString(iconpath, game.icon_path); game.icon = QImage(iconpath); - game.pic_path = game.path + "/sce_sys/pic1.png"; - game.name = psf.GetString("TITLE"); - game.serial = psf.GetString("TITLE_ID"); - game.region = GameListUtils::GetRegion(psf.GetString("CONTENT_ID").at(0)).toStdString(); - u32 fw_int = psf.GetInteger("SYSTEM_VER"); - QString fw = QString::number(fw_int, 16); - QString fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.') - : fw.left(3).insert(1, '.'); - game.fw = (fw_int == 0) ? "0.00" : fw_.toStdString(); - game.version = psf.GetString("APP_VER"); - game.category = psf.GetString("CATEGORY"); + game.pic_path = game.path / "sce_sys" / "pic1.png"; + game.snd0_path = game.path / "sce_sys" / "snd0.at9"; + + if (const auto title = psf.GetString("TITLE"); title.has_value()) { + game.name = *title; + } + if (const auto title_id = psf.GetString("TITLE_ID"); title_id.has_value()) { + game.serial = *title_id; + } + if (const auto content_id = psf.GetString("CONTENT_ID"); + content_id.has_value() && !content_id->empty()) { + game.region = GameListUtils::GetRegion(content_id->at(0)).toStdString(); + } + if (const auto fw_int_opt = psf.GetInteger("SYSTEM_VER"); fw_int_opt.has_value()) { + auto fw_int = *fw_int_opt; + if (fw_int == 0) { + game.fw = "0.00"; + } else { + QString fw = QString::number(fw_int, 16); + QString fw_ = fw.length() > 7 + ? QString::number(fw_int, 16).left(3).insert(2, '.') + : fw.left(3).insert(1, '.'); + game.fw = fw_.toStdString(); + } + } + if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) { + game.version = *app_ver; + } + if (const auto play_time = psf.GetString("PLAY_TIME"); play_time.has_value()) { + game.play_time = *play_time; + } } return game; } diff --git a/src/qt_gui/game_install_dialog.cpp b/src/qt_gui/game_install_dialog.cpp index 4b2b8528b..e53c58315 100644 --- a/src/qt_gui/game_install_dialog.cpp +++ b/src/qt_gui/game_install_dialog.cpp @@ -18,38 +18,74 @@ GameInstallDialog::GameInstallDialog() : m_gamesDirectory(nullptr) { auto layout = new QVBoxLayout(this); layout->addWidget(SetupGamesDirectory()); + layout->addWidget(SetupAddonsDirectory()); layout->addStretch(); layout->addWidget(SetupDialogActions()); - setWindowTitle("shadPS4 - Choose directory"); + setWindowTitle(tr("shadPS4 - Choose directory")); setWindowIcon(QIcon(":images/shadps4.ico")); } GameInstallDialog::~GameInstallDialog() {} -void GameInstallDialog::Browse() { - auto path = QFileDialog::getExistingDirectory(this, "Directory to install games"); +void GameInstallDialog::BrowseGamesDirectory() { + auto path = QFileDialog::getExistingDirectory(this, tr("Directory to install games")); if (!path.isEmpty()) { m_gamesDirectory->setText(QDir::toNativeSeparators(path)); } } +void GameInstallDialog::BrowseAddonsDirectory() { + auto path = QFileDialog::getExistingDirectory(this, tr("Directory to install DLC")); + + if (!path.isEmpty()) { + m_addonsDirectory->setText(QDir::toNativeSeparators(path)); + } +} + QWidget* GameInstallDialog::SetupGamesDirectory() { - auto group = new QGroupBox("Directory to install games"); + auto group = new QGroupBox(tr("Directory to install games")); auto layout = new QHBoxLayout(group); // Input. m_gamesDirectory = new QLineEdit(); - m_gamesDirectory->setText(QString::fromStdString(Config::getGameInstallDir())); + QString install_dir; + std::filesystem::path install_path = + Config::getGameInstallDirs().empty() ? "" : Config::getGameInstallDirs().front(); + Common::FS::PathToQString(install_dir, install_path); + m_gamesDirectory->setText(install_dir); m_gamesDirectory->setMinimumWidth(400); layout->addWidget(m_gamesDirectory); // Browse button. - auto browse = new QPushButton("Browse"); + auto browse = new QPushButton(tr("Browse")); - connect(browse, &QPushButton::clicked, this, &GameInstallDialog::Browse); + connect(browse, &QPushButton::clicked, this, &GameInstallDialog::BrowseGamesDirectory); + + layout->addWidget(browse); + + return group; +} + +QWidget* GameInstallDialog::SetupAddonsDirectory() { + auto group = new QGroupBox(tr("Directory to install DLC")); + auto layout = new QHBoxLayout(group); + + // Input. + m_addonsDirectory = new QLineEdit(); + QString install_dir; + Common::FS::PathToQString(install_dir, Config::getAddonInstallDir()); + m_addonsDirectory->setText(install_dir); + m_addonsDirectory->setMinimumWidth(400); + + layout->addWidget(m_addonsDirectory); + + // Browse button. + auto browse = new QPushButton(tr("Browse")); + + connect(browse, &QPushButton::clicked, this, &GameInstallDialog::BrowseAddonsDirectory); layout->addWidget(browse); @@ -68,15 +104,30 @@ QWidget* GameInstallDialog::SetupDialogActions() { void GameInstallDialog::Save() { // Check games directory. auto gamesDirectory = m_gamesDirectory->text(); + auto addonsDirectory = m_addonsDirectory->text(); if (gamesDirectory.isEmpty() || !QDir(gamesDirectory).exists() || !QDir::isAbsolutePath(gamesDirectory)) { - QMessageBox::critical(this, "Error", + QMessageBox::critical(this, tr("Error"), "The value for location to install games is not valid."); return; } - Config::setGameInstallDir(gamesDirectory.toStdString()); + if (addonsDirectory.isEmpty() || !QDir::isAbsolutePath(addonsDirectory)) { + QMessageBox::critical(this, tr("Error"), + "The value for location to install DLC is not valid."); + return; + } + QDir addonsDir(addonsDirectory); + if (!addonsDir.exists()) { + if (!addonsDir.mkpath(".")) { + QMessageBox::critical(this, tr("Error"), + "The DLC install location could not be created."); + return; + } + } + Config::addGameInstallDir(Common::FS::PathFromQString(gamesDirectory)); + Config::setAddonInstallDir(Common::FS::PathFromQString(addonsDirectory)); const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); Config::save(config_dir / "config.toml"); accept(); diff --git a/src/qt_gui/game_install_dialog.h b/src/qt_gui/game_install_dialog.h index 6f439e81d..0a4e29357 100644 --- a/src/qt_gui/game_install_dialog.h +++ b/src/qt_gui/game_install_dialog.h @@ -16,13 +16,16 @@ public: ~GameInstallDialog(); private slots: - void Browse(); + void BrowseGamesDirectory(); + void BrowseAddonsDirectory(); private: QWidget* SetupGamesDirectory(); + QWidget* SetupAddonsDirectory(); QWidget* SetupDialogActions(); void Save(); private: QLineEdit* m_gamesDirectory; + QLineEdit* m_addonsDirectory; }; \ No newline at end of file diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index 2699c9615..99628b083 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/path_util.h" +#include "common/string_util.h" #include "game_list_frame.h" GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidget* parent) @@ -24,23 +25,16 @@ GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidg this->horizontalHeader()->setStretchLastSection(true); this->setContextMenuPolicy(Qt::CustomContextMenu); this->setColumnCount(9); - this->setColumnWidth(1, 250); - this->setColumnWidth(2, 110); - this->setColumnWidth(3, 80); - this->setColumnWidth(4, 90); - this->setColumnWidth(5, 80); - this->setColumnWidth(6, 80); - this->setColumnWidth(7, 80); + this->setColumnWidth(1, 300); // Name + this->setColumnWidth(2, 120); // Serial + this->setColumnWidth(3, 90); // Region + this->setColumnWidth(4, 90); // Firmware + this->setColumnWidth(5, 90); // Size + this->setColumnWidth(6, 90); // Version + this->setColumnWidth(7, 100); // Play Time QStringList headers; - headers << "Icon" - << "Name" - << "Serial" - << "Region" - << "Firmware" - << "Size" - << "Version" - << "Category" - << "Path"; + headers << tr("Icon") << tr("Name") << tr("Serial") << tr("Region") << tr("Firmware") + << tr("Size") << tr("Version") << tr("Play Time") << tr("Path"); this->setHorizontalHeaderLabels(headers); this->horizontalHeader()->setSortIndicatorShown(true); this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); @@ -48,7 +42,7 @@ GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidg this->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); PopulateGameList(); - connect(this, &QTableWidget::itemClicked, this, &GameListFrame::SetListBackgroundImage); + connect(this, &QTableWidget::currentCellChanged, this, &GameListFrame::onCurrentCellChanged); connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, &GameListFrame::RefreshListBackgroundImage); connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, this, @@ -76,6 +70,26 @@ GameListFrame::GameListFrame(std::shared_ptr game_info_get, QWidg }); } +void GameListFrame::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, + int previousColumn) { + QTableWidgetItem* item = this->item(currentRow, currentColumn); + if (!item) { + return; + } + SetListBackgroundImage(item); + PlayBackgroundMusic(item); +} + +void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) { + if (!item || !Config::getPlayBGM()) { + BackgroundMusicPlayer::getInstance().stopMusic(); + return; + } + QString snd0path; + Common::FS::PathToQString(snd0path, m_game_info->m_games[item->row()].snd0_path); + BackgroundMusicPlayer::getInstance().playMusic(snd0path); +} + void GameListFrame::PopulateGameList() { this->setRowCount(m_game_info->m_games.size()); ResizeIcons(icon_size); @@ -87,8 +101,37 @@ void GameListFrame::PopulateGameList() { SetTableItem(i, 4, QString::fromStdString(m_game_info->m_games[i].fw)); SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].size)); SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].version)); - SetTableItem(i, 7, QString::fromStdString(m_game_info->m_games[i].category)); - SetTableItem(i, 8, QString::fromStdString(m_game_info->m_games[i].path)); + + QString playTime = GetPlayTime(m_game_info->m_games[i].serial); + if (playTime.isEmpty()) { + m_game_info->m_games[i].play_time = "0:00:00"; + SetTableItem(i, 7, "0"); + } else { + QStringList timeParts = playTime.split(':'); + int hours = timeParts[0].toInt(); + int minutes = timeParts[1].toInt(); + int seconds = timeParts[2].toInt(); + + QString formattedPlayTime; + if (hours > 0) { + formattedPlayTime += QString("%1h ").arg(hours); + } + if (minutes > 0) { + formattedPlayTime += QString("%1m ").arg(minutes); + } + + formattedPlayTime = formattedPlayTime.trimmed(); + m_game_info->m_games[i].play_time = playTime.toStdString(); + if (formattedPlayTime.isEmpty()) { + SetTableItem(i, 7, "0"); + } else { + SetTableItem(i, 7, formattedPlayTime); + } + } + + QString path; + Common::FS::PathToQString(path, m_game_info->m_games[i].path); + SetTableItem(i, 8, path); } } @@ -98,15 +141,12 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) { return; } - QString pic1Path = QString::fromStdString(m_game_info->m_games[item->row()].pic_path); - const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / - "game_data" / m_game_info->m_games[item->row()].serial / - "pic1.png"; -#ifdef _WIN32 - const auto blurredPic1PathQt = QString::fromStdWString(blurredPic1Path.wstring()); -#else - const auto blurredPic1PathQt = QString::fromStdString(blurredPic1Path.string()); -#endif + QString pic1Path; + Common::FS::PathToQString(pic1Path, m_game_info->m_games[item->row()].pic_path); + const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / + m_game_info->m_games[item->row()].serial / "pic1.png"; + QString blurredPic1PathQt; + Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path); backgroundImage = QImage(blurredPic1PathQt); if (backgroundImage.isNull()) { @@ -114,7 +154,8 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) { backgroundImage = m_game_list_utils.BlurImage(image, image.rect(), 16); std::filesystem::path img_path = - std::filesystem::path("user/game_data/") / m_game_info->m_games[item->row()].serial; + Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / + m_game_info->m_games[item->row()].serial; std::filesystem::create_directories(img_path); if (!backgroundImage.save(blurredPic1PathQt, "PNG")) { // qDebug() << "Error: Unable to save image."; @@ -159,7 +200,7 @@ void GameListFrame::ResizeIcons(int iconSize) { this->setItem(index, 0, iconItem); index++; } - this->horizontalHeader()->setSectionResizeMode(7, QHeaderView::ResizeToContents); + this->horizontalHeader()->setSectionResizeMode(8, QHeaderView::ResizeToContents); } void GameListFrame::SetTableItem(int row, int column, QString itemStr) { @@ -168,7 +209,7 @@ void GameListFrame::SetTableItem(int row, int column, QString itemStr) { QVBoxLayout* layout = new QVBoxLayout(widget); QLabel* label = new QLabel(itemStr, widget); - label->setStyleSheet("color: white; font-size: 15px; font-weight: bold;"); + label->setStyleSheet("color: white; font-size: 16px; font-weight: bold;"); // Create shadow effect QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(); @@ -212,3 +253,33 @@ void GameListFrame::SetRegionFlag(int row, int column, QString itemStr) { this->setItem(row, column, item); this->setCellWidget(row, column, widget); } + +QString GameListFrame::GetPlayTime(const std::string& serial) { + QString playTime; + const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + QString filePath = QString::fromStdString((user_dir / "play_time.txt").string()); + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return playTime; + } + + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString lineStr = QString::fromUtf8(line).trimmed(); + + QStringList parts = lineStr.split(' '); + if (parts.size() >= 2) { + QString fileSerial = parts[0]; + QString time = parts[1]; + + if (fileSerial == QString::fromStdString(serial)) { + playTime = time; + break; + } + } + } + + file.close(); + return playTime; +} diff --git a/src/qt_gui/game_list_frame.h b/src/qt_gui/game_list_frame.h index d8bccf466..6da2734a8 100644 --- a/src/qt_gui/game_list_frame.h +++ b/src/qt_gui/game_list_frame.h @@ -3,20 +3,9 @@ #pragma once -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include "background_music_player.h" #include "game_info.h" #include "game_list_utils.h" #include "gui_context_menus.h" @@ -33,10 +22,14 @@ public Q_SLOTS: void RefreshListBackgroundImage(); void SortNameAscending(int columnIndex); void SortNameDescending(int columnIndex); + void PlayBackgroundMusic(QTableWidgetItem* item); + void onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, + int previousColumn); private: void SetTableItem(int row, int column, QString itemStr); void SetRegionFlag(int row, int column, QString itemStr); + QString GetPlayTime(const std::string& serial); QList m_columnActs; GameInfoClass* game_inf_get = nullptr; bool ListSortedAsc = true; @@ -52,25 +45,58 @@ public: int icon_size; + static float parseAsFloat(const std::string& str, const int& offset) { + return std::stof(str.substr(0, str.size() - offset)); + } + + static float parseSizeMB(const std::string& size) { + float num = parseAsFloat(size, 3); + return (size[size.size() - 2] == 'G') ? num * 1024 : num; + } + static bool CompareStringsAscending(GameInfo a, GameInfo b, int columnIndex) { - if (columnIndex == 1) { + switch (columnIndex) { + case 1: return a.name < b.name; - } else if (columnIndex == 2) { - return a.serial < b.serial; - } else if (columnIndex == 3) { - return a.fw < b.fw; + case 2: + return a.serial.substr(4) < b.serial.substr(4); + case 3: + return a.region < b.region; + case 4: + return parseAsFloat(a.fw, 0) < parseAsFloat(b.fw, 0); + case 5: + return parseSizeMB(b.size) < parseSizeMB(a.size); + case 6: + return a.version < b.version; + case 7: + return a.play_time < b.play_time; + case 8: + return a.path < b.path; + default: + return false; } - return false; } static bool CompareStringsDescending(GameInfo a, GameInfo b, int columnIndex) { - if (columnIndex == 1) { + switch (columnIndex) { + case 1: return a.name > b.name; - } else if (columnIndex == 2) { - return a.serial > b.serial; - } else if (columnIndex == 3) { - return a.fw > b.fw; + case 2: + return a.serial.substr(4) > b.serial.substr(4); + case 3: + return a.region > b.region; + case 4: + return parseAsFloat(a.fw, 0) > parseAsFloat(b.fw, 0); + case 5: + return parseSizeMB(b.size) > parseSizeMB(a.size); + case 6: + return a.version > b.version; + case 7: + return a.play_time > b.play_time; + case 8: + return a.path > b.path; + default: + return false; } - return false; } -}; \ No newline at end of file +}; diff --git a/src/qt_gui/game_list_utils.h b/src/qt_gui/game_list_utils.h index 2e25f1220..3d710c5b7 100644 --- a/src/qt_gui/game_list_utils.h +++ b/src/qt_gui/game_list_utils.h @@ -3,15 +3,14 @@ #pragma once -#include -#include -#include -#include +#include "common/path_util.h" struct GameInfo { - std::string path; // root path of game directory (normaly directory that contains eboot.bin) - std::string icon_path; // path of icon0.png - std::string pic_path; // path of pic1.png + std::filesystem::path path; // root path of game directory + // (normally directory that contains eboot.bin) + std::filesystem::path icon_path; // path of icon0.png + std::filesystem::path pic_path; // path of pic1.png + std::filesystem::path snd0_path; // path of snd0.at9 QImage icon; std::string size; // variables extracted from param.sfo @@ -19,8 +18,9 @@ struct GameInfo { std::string serial = "Unknown"; std::string version = "Unknown"; std::string region = "Unknown"; - std::string category = "Unknown"; std::string fw = "Unknown"; + + std::string play_time = "Unknown"; }; class GameListUtils { @@ -49,7 +49,9 @@ public: } static void GetFolderSize(GameInfo& game) { - QDir dir(QString::fromStdString(game.path)); + QString dirPath; + Common::FS::PathToQString(dirPath, game.path); + QDir dir(dirPath); QDirIterator it(dir.absolutePath(), QDirIterator::Subdirectories); qint64 total = 0; while (it.hasNext()) { diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 2f4b884cf..8d7018522 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -4,20 +4,13 @@ #pragma once #include -#include #include -#include -#include -#include #include #include -#include -#include -#include -#include #include #include +#include "cheats_patches.h" #include "game_info.h" #include "trophy_viewer.h" @@ -27,7 +20,9 @@ #include #include #include +#include #endif +#include "common/path_util.h" class GuiContextMenus : public QObject { Q_OBJECT @@ -42,23 +37,30 @@ public: itemID = widget->currentRow() * widget->columnCount() + widget->currentColumn(); } + // Do not show the menu if an item is selected + if (itemID == -1) { + return; + } + // Setup menu. QMenu menu(widget); - QAction createShortcut("Create Shortcut", widget); - QAction openFolder("Open Game Folder", widget); - QAction openSfoViewer("SFO Viewer", widget); - QAction openTrophyViewer("Trophy Viewer", widget); + QAction createShortcut(tr("Create Shortcut"), widget); + QAction openFolder(tr("Open Game Folder"), widget); + QAction openCheats(tr("Cheats / Patches"), widget); + QAction openSfoViewer(tr("SFO Viewer"), widget); + QAction openTrophyViewer(tr("Trophy Viewer"), widget); menu.addAction(&openFolder); menu.addAction(&createShortcut); + menu.addAction(&openCheats); menu.addAction(&openSfoViewer); menu.addAction(&openTrophyViewer); // "Copy" submenu. - QMenu* copyMenu = new QMenu("Copy info", widget); - QAction* copyName = new QAction("Copy Name", widget); - QAction* copySerial = new QAction("Copy Serial", widget); - QAction* copyNameAll = new QAction("Copy All", widget); + QMenu* copyMenu = new QMenu(tr("Copy info"), widget); + QAction* copyName = new QAction(tr("Copy Name"), widget); + QAction* copySerial = new QAction(tr("Copy Serial"), widget); + QAction* copyNameAll = new QAction(tr("Copy All"), widget); copyMenu->addAction(copyName); copyMenu->addAction(copySerial); @@ -66,6 +68,18 @@ public: menu.addMenu(copyMenu); + // "Delete..." submenu. + QMenu* deleteMenu = new QMenu(tr("Delete..."), widget); + QAction* deleteGame = new QAction(tr("Delete Game"), widget); + QAction* deleteUpdate = new QAction(tr("Delete Update"), widget); + QAction* deleteDLC = new QAction(tr("Delete DLC"), widget); + + deleteMenu->addAction(deleteGame); + deleteMenu->addAction(deleteUpdate); + deleteMenu->addAction(deleteDLC); + + menu.addMenu(deleteMenu); + // Show menu. auto selected = menu.exec(global_pos); if (!selected) { @@ -73,39 +87,68 @@ public: } if (selected == &openFolder) { - QString folderPath = QString::fromStdString(m_games[itemID].path); + QString folderPath; + Common::FS::PathToQString(folderPath, m_games[itemID].path); QDesktopServices::openUrl(QUrl::fromLocalFile(folderPath)); } if (selected == &openSfoViewer) { PSF psf; - if (psf.open(m_games[itemID].path + "/sce_sys/param.sfo", {})) { - int rows = psf.map_strings.size() + psf.map_integers.size(); + QString game_update_path; + Common::FS::PathToQString(game_update_path, m_games[itemID].path.concat("-UPDATE")); + std::filesystem::path game_folder_path = m_games[itemID].path; + if (std::filesystem::exists(Common::FS::PathFromQString(game_update_path))) { + game_folder_path = Common::FS::PathFromQString(game_update_path); + } + if (psf.Open(game_folder_path / "sce_sys" / "param.sfo")) { + int rows = psf.GetEntries().size(); QTableWidget* tableWidget = new QTableWidget(rows, 2); tableWidget->setAttribute(Qt::WA_DeleteOnClose); connect(widget->parent(), &QWidget::destroyed, tableWidget, - [widget, tableWidget]() { tableWidget->deleteLater(); }); + [tableWidget]() { tableWidget->deleteLater(); }); tableWidget->verticalHeader()->setVisible(false); // Hide vertical header int row = 0; - for (const auto& pair : psf.map_strings) { + for (const auto& entry : psf.GetEntries()) { QTableWidgetItem* keyItem = - new QTableWidgetItem(QString::fromStdString(pair.first)); - QTableWidgetItem* valueItem = - new QTableWidgetItem(QString::fromStdString(pair.second)); - - tableWidget->setItem(row, 0, keyItem); - tableWidget->setItem(row, 1, valueItem); - keyItem->setFlags(keyItem->flags() & ~Qt::ItemIsEditable); - valueItem->setFlags(valueItem->flags() & ~Qt::ItemIsEditable); - row++; - } - for (const auto& pair : psf.map_integers) { - QTableWidgetItem* keyItem = - new QTableWidgetItem(QString::fromStdString(pair.first)); - QTableWidgetItem* valueItem = new QTableWidgetItem( - QString("0x").append(QString::number(pair.second, 16))); + new QTableWidgetItem(QString::fromStdString(entry.key)); + QTableWidgetItem* valueItem; + switch (entry.param_fmt) { + case PSFEntryFmt::Binary: { + const auto bin = psf.GetBinary(entry.key); + if (!bin.has_value()) { + valueItem = new QTableWidgetItem(QString("Unknown")); + } else { + std::string text; + text.reserve(bin->size() * 2); + for (const auto& c : *bin) { + static constexpr char hex[] = "0123456789ABCDEF"; + text.push_back(hex[c >> 4 & 0xF]); + text.push_back(hex[c & 0xF]); + } + valueItem = new QTableWidgetItem(QString::fromStdString(text)); + } + } break; + case PSFEntryFmt::Text: { + auto text = psf.GetString(entry.key); + if (!text.has_value()) { + valueItem = new QTableWidgetItem(QString("Unknown")); + } else { + valueItem = + new QTableWidgetItem(QString::fromStdString(std::string{*text})); + } + } break; + case PSFEntryFmt::Integer: { + auto integer = psf.GetInteger(entry.key); + if (!integer.has_value()) { + valueItem = new QTableWidgetItem(QString("Unknown")); + } else { + valueItem = + new QTableWidgetItem(QString("0x") + QString::number(*integer, 16)); + } + } break; + } tableWidget->setItem(row, 0, keyItem); tableWidget->setItem(row, 1, valueItem); @@ -124,26 +167,44 @@ public: tableWidget->horizontalHeader()->setVisible(false); tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); - tableWidget->setWindowTitle("SFO Viewer"); + tableWidget->setWindowTitle(tr("SFO Viewer")); tableWidget->show(); } } + if (selected == &openCheats) { + QString gameName = QString::fromStdString(m_games[itemID].name); + QString gameSerial = QString::fromStdString(m_games[itemID].serial); + QString gameVersion = QString::fromStdString(m_games[itemID].version); + QString gameSize = QString::fromStdString(m_games[itemID].size); + QString iconPath; + Common::FS::PathToQString(iconPath, m_games[itemID].icon_path); + QPixmap gameImage(iconPath); + CheatsPatches* cheatsPatches = + new CheatsPatches(gameName, gameSerial, gameVersion, gameSize, gameImage); + cheatsPatches->show(); + connect(widget->parent(), &QWidget::destroyed, cheatsPatches, + [cheatsPatches]() { cheatsPatches->deleteLater(); }); + } + if (selected == &openTrophyViewer) { - QString trophyPath = QString::fromStdString(m_games[itemID].serial); - QString gameTrpPath = QString::fromStdString(m_games[itemID].path); + QString trophyPath, gameTrpPath; + Common::FS::PathToQString(trophyPath, m_games[itemID].serial); + Common::FS::PathToQString(gameTrpPath, m_games[itemID].path); TrophyViewer* trophyViewer = new TrophyViewer(trophyPath, gameTrpPath); trophyViewer->show(); connect(widget->parent(), &QWidget::destroyed, trophyViewer, - [widget, trophyViewer]() { trophyViewer->deleteLater(); }); + [trophyViewer]() { trophyViewer->deleteLater(); }); } if (selected == &createShortcut) { - QString targetPath = QString::fromStdString(m_games[itemID].path); + QString targetPath; + Common::FS::PathToQString(targetPath, m_games[itemID].path); QString ebootPath = targetPath + "/eboot.bin"; // Get the full path to the icon - QString iconPath = QString::fromStdString(m_games[itemID].icon_path); + QString iconPath; + Common::FS::PathToQString(iconPath, m_games[itemID].icon_path); QFileInfo iconFileInfo(iconPath); QString icoPath = iconFileInfo.absolutePath() + "/" + iconFileInfo.baseName() + ".ico"; @@ -178,15 +239,15 @@ public: if (createShortcutLinux(linkPath, ebootPath, iconPath)) { #endif QMessageBox::information( - nullptr, "Shortcut creation", - QString("Shortcut created successfully!\n %1").arg(linkPath)); + nullptr, tr("Shortcut creation"), + QString(tr("Shortcut created successfully!\n %1")).arg(linkPath)); } else { QMessageBox::critical( - nullptr, "Error", - QString("Error creating shortcut!\n %1").arg(linkPath)); + nullptr, tr("Error"), + QString(tr("Error creating shortcut!\n %1")).arg(linkPath)); } } else { - QMessageBox::critical(nullptr, "Error", "Failed to convert icon."); + QMessageBox::critical(nullptr, tr("Error"), tr("Failed to convert icon.")); } } else { // If the icon is already in ICO format, we just create the shortcut @@ -196,11 +257,12 @@ public: if (createShortcutLinux(linkPath, ebootPath, iconPath)) { #endif QMessageBox::information( - nullptr, "Shortcut creation", - QString("Shortcut created successfully!\n %1").arg(linkPath)); + nullptr, tr("Shortcut creation"), + QString(tr("Shortcut created successfully!\n %1")).arg(linkPath)); } else { - QMessageBox::critical(nullptr, "Error", - QString("Error creating shortcut!\n %1").arg(linkPath)); + QMessageBox::critical( + nullptr, tr("Error"), + QString(tr("Error creating shortcut!\n %1")).arg(linkPath)); } } } @@ -225,6 +287,54 @@ public: .arg(QString::fromStdString(m_games[itemID].size)); clipboard->setText(combinedText); } + + if (selected == deleteGame || selected == deleteUpdate || selected == deleteDLC) { + bool error = false; + QString folder_path, game_update_path, dlc_path; + Common::FS::PathToQString(folder_path, m_games[itemID].path); + Common::FS::PathToQString(game_update_path, m_games[itemID].path.concat("-UPDATE")); + Common::FS::PathToQString( + dlc_path, Config::getAddonInstallDir() / + Common::FS::PathFromQString(folder_path).parent_path().filename()); + QString message_type = tr("Game"); + + if (selected == deleteUpdate) { + if (!Config::getSeparateUpdateEnabled()) { + QMessageBox::critical(nullptr, tr("Error"), + QString(tr("requiresEnableSeparateUpdateFolder_MSG"))); + error = true; + } else if (!std::filesystem::exists( + Common::FS::PathFromQString(game_update_path))) { + QMessageBox::critical(nullptr, tr("Error"), + QString(tr("This game has no update to delete!"))); + error = true; + } else { + folder_path = game_update_path; + message_type = tr("Update"); + } + } else if (selected == deleteDLC) { + if (!std::filesystem::exists(Common::FS::PathFromQString(dlc_path))) { + QMessageBox::critical(nullptr, tr("Error"), + QString(tr("This game has no DLC to delete!"))); + error = true; + } else { + folder_path = dlc_path; + message_type = tr("DLC"); + } + } + if (!error) { + QString gameName = QString::fromStdString(m_games[itemID].name); + QDir dir(folder_path); + QMessageBox::StandardButton reply = QMessageBox::question( + nullptr, QString(tr("Delete %1")).arg(message_type), + QString(tr("Are you sure you want to delete %1's %2 directory?")) + .arg(gameName, message_type), + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) { + dir.removeRecursively(); + } + } + } } int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) { @@ -257,7 +367,7 @@ public: int itemIndex = GetRowIndex(treeWidget, currentItem); // row QMenu menu(treeWidget); - QAction installPackage("Install PKG", treeWidget); + QAction installPackage(tr("Install PKG"), treeWidget); menu.addAction(&installPackage); @@ -268,10 +378,7 @@ public: if (selected == &installPackage) { QStringList pkg_app_ = m_pkg_app_list[itemIndex].split(";;"); - std::filesystem::path path(pkg_app_[9].toStdString()); -#ifdef _WIN32 - path = std::filesystem::path(pkg_app_[9].toStdWString()); -#endif + std::filesystem::path path = Common::FS::PathFromQString(pkg_app_[9]); InstallDragDropPkg(path, 1, 1); } } @@ -305,9 +412,9 @@ private: CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); // Create the ShellLink object - IShellLink* pShellLink = nullptr; + Microsoft::WRL::ComPtr pShellLink; HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID*)&pShellLink); + IID_PPV_ARGS(&pShellLink)); if (SUCCEEDED(hres)) { // Defines the path to the program executable pShellLink->SetPath((LPCWSTR)exePath.utf16()); @@ -323,13 +430,11 @@ private: pShellLink->SetIconLocation((LPCWSTR)iconPath.utf16(), 0); // Save the shortcut - IPersistFile* pPersistFile = nullptr; - hres = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile); + Microsoft::WRL::ComPtr pPersistFile; + hres = pShellLink.As(&pPersistFile); if (SUCCEEDED(hres)) { hres = pPersistFile->Save((LPCWSTR)linkPath.utf16(), TRUE); - pPersistFile->Release(); } - pShellLink->Release(); } CoUninitialize(); diff --git a/src/qt_gui/install_dir_select.cpp b/src/qt_gui/install_dir_select.cpp new file mode 100644 index 000000000..e0951b123 --- /dev/null +++ b/src/qt_gui/install_dir_select.cpp @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "install_dir_select.h" + +InstallDirSelect::InstallDirSelect() : selected_dir() { + selected_dir = Config::getGameInstallDirs().empty() ? "" : Config::getGameInstallDirs().front(); + + if (!Config::getGameInstallDirs().empty() && Config::getGameInstallDirs().size() == 1) { + reject(); + } + + auto layout = new QVBoxLayout(this); + + layout->addWidget(SetupInstallDirList()); + layout->addStretch(); + layout->addWidget(SetupDialogActions()); + + setWindowTitle(tr("shadPS4 - Choose directory")); + setWindowIcon(QIcon(":images/shadps4.ico")); +} + +InstallDirSelect::~InstallDirSelect() {} + +QWidget* InstallDirSelect::SetupInstallDirList() { + auto group = new QGroupBox(tr("Select which directory you want to install to.")); + auto vlayout = new QVBoxLayout(); + + auto m_path_list = new QListWidget(); + QList qt_list; + for (const auto& str : Config::getGameInstallDirs()) { + QString installDirPath; + Common::FS::PathToQString(installDirPath, str); + qt_list.append(installDirPath); + } + m_path_list->insertItems(0, qt_list); + m_path_list->setSpacing(1); + + connect(m_path_list, &QListWidget::itemClicked, this, &InstallDirSelect::setSelectedDirectory); + connect(m_path_list, &QListWidget::itemActivated, this, + &InstallDirSelect::setSelectedDirectory); + + vlayout->addWidget(m_path_list); + + group->setLayout(vlayout); + return group; +} + +void InstallDirSelect::setSelectedDirectory(QListWidgetItem* item) { + if (item) { + const auto highlighted_path = Common::FS::PathFromQString(item->text()); + if (!highlighted_path.empty()) { + selected_dir = highlighted_path; + } + } +} + +QWidget* InstallDirSelect::SetupDialogActions() { + auto actions = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + connect(actions, &QDialogButtonBox::accepted, this, &InstallDirSelect::accept); + connect(actions, &QDialogButtonBox::rejected, this, &InstallDirSelect::reject); + + return actions; +} diff --git a/src/qt_gui/install_dir_select.h b/src/qt_gui/install_dir_select.h new file mode 100644 index 000000000..e3e81575a --- /dev/null +++ b/src/qt_gui/install_dir_select.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/config.h" +#include "common/path_util.h" + +class QLineEdit; + +class InstallDirSelect final : public QDialog { + Q_OBJECT + +public: + InstallDirSelect(); + ~InstallDirSelect(); + + std::filesystem::path getSelectedDirectory() { + return selected_dir; + } + +private: + QWidget* SetupInstallDirList(); + QWidget* SetupDialogActions(); + void setSelectedDirectory(QListWidgetItem* item); + std::filesystem::path selected_dir; +}; diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index cff01cc2b..da8804f69 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -1,31 +1,36 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include - #include "common/config.h" +#include "common/memory_patcher.h" #include "core/file_sys/fs.h" #include "emulator.h" -#include "qt_gui/game_install_dialog.h" -#include "qt_gui/main_window.h" +#include "game_install_dialog.h" +#include "main_window.h" + +#ifdef _WIN32 +#include +#endif // Custom message handler to ignore Qt logs void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} int main(int argc, char* argv[]) { +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); +#endif + QApplication a(argc, argv); // Load configurations and initialize Qt application const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); Config::load(user_dir / "config.toml"); - std::filesystem::create_directory(user_dir / "game_data"); // Check if elf or eboot.bin path was passed as a command line argument bool has_command_line_argument = argc > 1; // Check if the game install directory is set - if (Config::getGameInstallDir() == "" && !has_command_line_argument) { + if (Config::getGameInstallDirs().empty() && !has_command_line_argument) { GameInstallDialog dlg; dlg.exec(); } @@ -40,6 +45,13 @@ int main(int argc, char* argv[]) { // Check for command line arguments if (has_command_line_argument) { Core::Emulator emulator; + for (int i = 0; i < argc; i++) { + std::string curArg = argv[i]; + if (curArg == "-p") { + std::string patchFile = argv[i + 1]; + MemoryPatcher::patchFile = patchFile; + } + } emulator.Run(argv[1]); } diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 34ef0d868..e52820102 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -1,26 +1,29 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include -#include -#include +#include #include -#include -#include #include "about_dialog.h" +#include "cheats_patches.h" +#include "check_update.h" #include "common/io_file.h" +#include "common/path_util.h" +#include "common/scm_rev.h" +#include "common/string_util.h" #include "common/version.h" #include "core/file_format/pkg.h" #include "core/loader.h" #include "game_install_dialog.h" +#include "install_dir_select.h" #include "main_window.h" #include "settings_dialog.h" #include "video_core/renderer_vulkan/vk_instance.h" MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); + installEventFilter(this); setAttribute(Qt::WA_DeleteOnClose); } @@ -37,6 +40,7 @@ bool MainWindow::Init() { CreateActions(); CreateRecentGameActions(); ConfigureGuiFromSettings(); + LoadTranslation(); CreateDockWindows(); CreateConnects(); SetLastUsedTheme(); @@ -44,10 +48,19 @@ bool MainWindow::Init() { GetPhysicalDevices(); // show ui setMinimumSize(350, minimumSizeHint().height()); - setWindowTitle(QString::fromStdString("shadPS4 v" + std::string(Common::VERSION))); + std::string window_title = ""; + if (Common::isRelease) { + window_title = fmt::format("shadPS4 v{}", Common::VERSION); + } else { + window_title = fmt::format("shadPS4 v{} {} {}", Common::VERSION, Common::g_scm_branch, + Common::g_scm_desc); + } + setWindowTitle(QString::fromStdString(window_title)); this->show(); // load game list LoadGameLists(); + // Check for update + CheckUpdateMain(true); auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end - start); @@ -58,6 +71,14 @@ bool MainWindow::Init() { QString statusMessage = "Games: " + QString::number(numGames) + " (" + QString::number(duration.count()) + "ms)"; statusBar->showMessage(statusMessage); + + // Initialize Discord RPC + if (Config::getEnableDiscordRPC()) { + auto* rpc = Common::Singleton::Instance(); + rpc->init(); + rpc->setStatusIdling(); + } + return true; } @@ -90,6 +111,7 @@ void MainWindow::AddUiWidgets() { ui->toolBar->addWidget(ui->playButton); ui->toolBar->addWidget(ui->pauseButton); ui->toolBar->addWidget(ui->stopButton); + ui->toolBar->addWidget(ui->refreshButton); ui->toolBar->addWidget(ui->settingsButton); ui->toolBar->addWidget(ui->controllerButton); QFrame* line = new QFrame(this); @@ -105,7 +127,7 @@ void MainWindow::CreateDockWindows() { QWidget* phCentralWidget = new QWidget(this); setCentralWidget(phCentralWidget); - m_dock_widget.reset(new QDockWidget("Game List", this)); + m_dock_widget.reset(new QDockWidget(tr("Game List"), this)); m_game_list_frame.reset(new GameListFrame(m_game_info, this)); m_game_list_frame->setObjectName("gamelist"); m_game_grid_frame.reset(new GameGridFrame(m_game_info, this)); @@ -120,7 +142,7 @@ void MainWindow::CreateDockWindows() { m_elf_viewer->hide(); m_game_list_frame->show(); m_dock_widget->setWidget(m_game_list_frame.data()); - slider_pos = Config::getSliderPositon(); + slider_pos = Config::getSliderPosition(); ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start; isTableList = true; } else if (table_mode == 1) { // Grid @@ -128,7 +150,7 @@ void MainWindow::CreateDockWindows() { m_elf_viewer->hide(); m_game_grid_frame->show(); m_dock_widget->setWidget(m_game_grid_frame.data()); - slider_pos = Config::getSliderPositonGrid(); + slider_pos = Config::getSliderPositionGrid(); ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start; isTableList = false; } else { @@ -161,6 +183,16 @@ void MainWindow::LoadGameLists() { } } +void MainWindow::CheckUpdateMain(bool checkSave) { + if (checkSave) { + if (!Config::autoUpdate()) { + return; + } + } + auto checkUpdate = new CheckUpdate(false); + checkUpdate->exec(); +} + void MainWindow::GetPhysicalDevices() { Vulkan::Instance instance(false, false); auto physical_devices = instance.GetPhysicalDevices(); @@ -168,7 +200,7 @@ void MainWindow::GetPhysicalDevices() { auto prop = physical_device.getProperties(); QString name = QString::fromUtf8(prop.deviceName, -1); if (prop.apiVersion < Vulkan::TargetVulkanApiVersion) { - name += " * Unsupported Vulkan Version"; + name += tr(" * Unsupported Vulkan Version"); } m_physical_devices.push_back(name); } @@ -179,6 +211,7 @@ void MainWindow::CreateConnects() { connect(ui->mw_searchbar, &QLineEdit::textChanged, this, &MainWindow::SearchGameTable); connect(ui->exitAct, &QAction::triggered, this, &QWidget::close); connect(ui->refreshGameListAct, &QAction::triggered, this, &MainWindow::RefreshGameTable); + connect(ui->refreshButton, &QPushButton::clicked, this, &MainWindow::RefreshGameTable); connect(ui->showGameListAct, &QAction::triggered, this, &MainWindow::ShowGameList); connect(this, &MainWindow::ExtractionFinished, this, &MainWindow::RefreshGameTable); @@ -188,12 +221,12 @@ void MainWindow::CreateConnects() { 36 + value; // 36 is the minimum icon size to use due to text disappearing. m_game_list_frame->ResizeIcons(36 + value); Config::setIconSize(36 + value); - Config::setSliderPositon(value); + Config::setSliderPosition(value); } else { m_game_grid_frame->icon_size = 69 + value; m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); Config::setIconSizeGrid(69 + value); - Config::setSliderPositonGrid(value); + Config::setSliderPositionGrid(value); } }); @@ -205,14 +238,27 @@ void MainWindow::CreateConnects() { connect(ui->configureAct, &QAction::triggered, this, [this]() { auto settingsDialog = new SettingsDialog(m_physical_devices, this); + + connect(settingsDialog, &SettingsDialog::LanguageChanged, this, + &MainWindow::OnLanguageChanged); + settingsDialog->exec(); }); connect(ui->settingsButton, &QPushButton::clicked, this, [this]() { auto settingsDialog = new SettingsDialog(m_physical_devices, this); + + connect(settingsDialog, &SettingsDialog::LanguageChanged, this, + &MainWindow::OnLanguageChanged); + settingsDialog->exec(); }); + connect(ui->updaterAct, &QAction::triggered, this, [this]() { + auto checkUpdate = new CheckUpdate(true); + checkUpdate->exec(); + }); + connect(ui->aboutAct, &QAction::triggered, this, [this]() { auto aboutDialog = new AboutDialog(this); aboutDialog->exec(); @@ -224,11 +270,11 @@ void MainWindow::CreateConnects() { 36; // 36 is the minimum icon size to use due to text disappearing. ui->sizeSlider->setValue(0); // icone_size - 36 Config::setIconSize(36); - Config::setSliderPositon(0); + Config::setSliderPosition(0); } else { ui->sizeSlider->setValue(0); // icone_size - 36 Config::setIconSizeGrid(69); - Config::setSliderPositonGrid(0); + Config::setSliderPositionGrid(0); } }); @@ -237,11 +283,11 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 64; ui->sizeSlider->setValue(28); Config::setIconSize(64); - Config::setSliderPositon(28); + Config::setSliderPosition(28); } else { ui->sizeSlider->setValue(28); Config::setIconSizeGrid(97); - Config::setSliderPositonGrid(28); + Config::setSliderPositionGrid(28); } }); @@ -250,11 +296,11 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 128; ui->sizeSlider->setValue(92); Config::setIconSize(128); - Config::setSliderPositon(92); + Config::setSliderPosition(92); } else { ui->sizeSlider->setValue(92); Config::setIconSizeGrid(160); - Config::setSliderPositonGrid(91); + Config::setSliderPositionGrid(91); } }); @@ -263,15 +309,16 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 256; ui->sizeSlider->setValue(220); Config::setIconSize(256); - Config::setSliderPositon(220); + Config::setSliderPosition(220); } else { ui->sizeSlider->setValue(220); Config::setIconSizeGrid(256); - Config::setSliderPositonGrid(220); + Config::setSliderPositionGrid(220); } }); // List connect(ui->setlistModeListAct, &QAction::triggered, m_dock_widget.data(), [this]() { + BackgroundMusicPlayer::getInstance().stopMusic(); m_dock_widget->setWidget(m_game_list_frame.data()); m_game_grid_frame->hide(); m_elf_viewer->hide(); @@ -282,12 +329,13 @@ void MainWindow::CreateConnects() { } isTableList = true; Config::setTableMode(0); - int slider_pos = Config::getSliderPositon(); + int slider_pos = Config::getSliderPosition(); ui->sizeSlider->setEnabled(true); ui->sizeSlider->setSliderPosition(slider_pos); }); // Grid connect(ui->setlistModeGridAct, &QAction::triggered, m_dock_widget.data(), [this]() { + BackgroundMusicPlayer::getInstance().stopMusic(); m_dock_widget->setWidget(m_game_grid_frame.data()); m_game_grid_frame->show(); m_game_list_frame->hide(); @@ -298,12 +346,13 @@ void MainWindow::CreateConnects() { } isTableList = false; Config::setTableMode(1); - int slider_pos_grid = Config::getSliderPositonGrid(); + int slider_pos_grid = Config::getSliderPositionGrid(); ui->sizeSlider->setEnabled(true); ui->sizeSlider->setSliderPosition(slider_pos_grid); }); // Elf connect(ui->setlistElfAct, &QAction::triggered, m_dock_widget.data(), [this]() { + BackgroundMusicPlayer::getInstance().stopMusic(); m_dock_widget->setWidget(m_elf_viewer.data()); m_game_grid_frame->hide(); m_game_list_frame->hide(); @@ -313,6 +362,85 @@ void MainWindow::CreateConnects() { Config::setTableMode(2); }); + // Cheats/Patches Download. + connect(ui->downloadCheatsPatchesAct, &QAction::triggered, this, [this]() { + QDialog* panelDialog = new QDialog(this); + QVBoxLayout* layout = new QVBoxLayout(panelDialog); + QPushButton* downloadAllCheatsButton = + new QPushButton(tr("Download Cheats For All Installed Games"), panelDialog); + QPushButton* downloadAllPatchesButton = + new QPushButton(tr("Download Patches For All Games"), panelDialog); + + layout->addWidget(downloadAllCheatsButton); + layout->addWidget(downloadAllPatchesButton); + + panelDialog->setLayout(layout); + + connect(downloadAllCheatsButton, &QPushButton::clicked, this, [this, panelDialog]() { + QEventLoop eventLoop; + int pendingDownloads = 0; + + auto onDownloadFinished = [&]() { + if (--pendingDownloads <= 0) { + eventLoop.quit(); + } + }; + + for (const GameInfo& game : m_game_info->m_games) { + QString empty = ""; + QString gameSerial = QString::fromStdString(game.serial); + QString gameVersion = QString::fromStdString(game.version); + + CheatsPatches* cheatsPatches = + new CheatsPatches(empty, empty, empty, empty, empty, nullptr); + connect(cheatsPatches, &CheatsPatches::downloadFinished, onDownloadFinished); + + pendingDownloads += 3; + + cheatsPatches->downloadCheats("wolf2022", gameSerial, gameVersion, false); + cheatsPatches->downloadCheats("GoldHEN", gameSerial, gameVersion, false); + cheatsPatches->downloadCheats("shadPS4", gameSerial, gameVersion, false); + } + eventLoop.exec(); + + QMessageBox::information( + nullptr, tr("Download Complete"), + tr("You have downloaded cheats for all the games you have installed.")); + + panelDialog->accept(); + }); + connect(downloadAllPatchesButton, &QPushButton::clicked, [panelDialog]() { + QEventLoop eventLoop; + int pendingDownloads = 0; + + auto onDownloadFinished = [&]() { + if (--pendingDownloads <= 0) { + eventLoop.quit(); + } + }; + + QString empty = ""; + CheatsPatches* cheatsPatches = + new CheatsPatches(empty, empty, empty, empty, empty, nullptr); + connect(cheatsPatches, &CheatsPatches::downloadFinished, onDownloadFinished); + + pendingDownloads += 2; + + cheatsPatches->downloadPatches("GoldHEN", false); + cheatsPatches->downloadPatches("shadPS4", false); + + eventLoop.exec(); + QMessageBox::information( + nullptr, tr("Download Complete"), + QString(tr("Patches Downloaded Successfully!") + "\n" + + tr("All Patches available for all games have been downloaded."))); + cheatsPatches->createFilesJson("GoldHEN"); + cheatsPatches->createFilesJson("shadPS4"); + panelDialog->accept(); + }); + panelDialog->exec(); + }); + // Dump game list. connect(ui->dumpGameListAct, &QAction::triggered, this, [&] { QString filePath = qApp->applicationDirPath().append("/GameList.txt"); @@ -329,12 +457,14 @@ void MainWindow::CreateConnects() { .arg(" APP VERSION", -11) .arg(" Path"); for (const GameInfo& game : m_game_info->m_games) { + QString game_path; + Common::FS::PathToQString(game_path, game.path); out << QString("%1 %2 %3 %4 %5\n") .arg(QString::fromStdString(game.name), -50) .arg(QString::fromStdString(game.serial), -10) .arg(QString::fromStdString(game.fw), -4) .arg(QString::fromStdString(game.version), -11) - .arg(QString::fromStdString(game.path)); + .arg(game_path); } }); @@ -400,29 +530,36 @@ void MainWindow::CreateConnects() { } void MainWindow::StartGame() { + isGameRunning = true; + BackgroundMusicPlayer::getInstance().stopMusic(); QString gamePath = ""; int table_mode = Config::getTableMode(); if (table_mode == 0) { if (m_game_list_frame->currentItem()) { int itemID = m_game_list_frame->currentItem()->row(); - gamePath = QString::fromStdString(m_game_info->m_games[itemID].path + "/eboot.bin"); + Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin"); } } else if (table_mode == 1) { if (m_game_grid_frame->cellClicked) { int itemID = (m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt) + m_game_grid_frame->crtColumn; - gamePath = QString::fromStdString(m_game_info->m_games[itemID].path + "/eboot.bin"); + Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin"); } } else { if (m_elf_viewer->currentItem()) { int itemID = m_elf_viewer->currentItem()->row(); - gamePath = QString::fromStdString(m_elf_viewer->m_elf_list[itemID].toStdString()); + gamePath = m_elf_viewer->m_elf_list[itemID]; } } if (gamePath != "") { AddRecentFiles(gamePath); Core::Emulator emulator; - emulator.Run(gamePath.toUtf8().constData()); + const auto path = Common::FS::PathFromQString(gamePath); + if (!std::filesystem::exists(path)) { + QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found"))); + return; + } + emulator.Run(path); } } @@ -464,7 +601,7 @@ void MainWindow::RefreshGameTable() { m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); statusBar->clearMessage(); int numGames = m_game_info->m_games.size(); - QString statusMessage = "Games: " + QString::number(numGames); + QString statusMessage = tr("Games: ") + QString::number(numGames); statusBar->showMessage(statusMessage); } @@ -478,6 +615,7 @@ void MainWindow::ConfigureGuiFromSettings() { } else { ui->setlistModeGridAct->setChecked(true); } + BackgroundMusicPlayer::getInstance().setVolume(Config::getBGMvolume()); } void MainWindow::SaveWindowState() const { @@ -490,17 +628,14 @@ void MainWindow::SaveWindowState() const { void MainWindow::InstallPkg() { QFileDialog dialog; dialog.setFileMode(QFileDialog::ExistingFiles); - dialog.setNameFilter(tr("PKG File (*.PKG)")); + dialog.setNameFilter(tr("PKG File (*.PKG *.pkg)")); if (dialog.exec()) { QStringList fileNames = dialog.selectedFiles(); int nPkg = fileNames.size(); int pkgNum = 0; for (const QString& file : fileNames) { ++pkgNum; - std::filesystem::path path(file.toStdString()); -#ifdef _WIN64 - path = std::filesystem::path(file.toStdWString()); -#endif + std::filesystem::path path = Common::FS::PathFromQString(file); MainWindow::InstallDragDropPkg(path, pkgNum, nPkg); } } @@ -515,13 +650,16 @@ void MainWindow::BootGame() { int nFiles = fileNames.size(); if (nFiles > 1) { - QMessageBox::critical(nullptr, "Game Boot", QString("Only one file can be selected!")); + QMessageBox::critical(nullptr, tr("Game Boot"), + QString(tr("Only one file can be selected!"))); } else { - std::filesystem::path path(fileNames[0].toStdString()); -#ifdef _WIN64 - path = std::filesystem::path(fileNames[0].toStdWString()); -#endif + std::filesystem::path path = Common::FS::PathFromQString(fileNames[0]); Core::Emulator emulator; + if (!std::filesystem::exists(path)) { + QMessageBox::critical(nullptr, tr("Run Game"), + QString(tr("Eboot.bin file not found"))); + return; + } emulator.Run(path); } } @@ -529,41 +667,91 @@ void MainWindow::BootGame() { void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int nPkg) { if (Loader::DetectFileType(file) == Loader::FileTypes::Pkg) { - pkg = PKG(); - pkg.Open(file); std::string failreason; - const auto extract_path = - std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID(); + pkg = PKG(); + if (!pkg.Open(file, failreason)) { + QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason)); + return; + } + InstallDirSelect ids; + ids.exec(); + auto game_install_dir = ids.getSelectedDirectory(); + auto game_folder_path = game_install_dir / pkg.GetTitleID(); QString pkgType = QString::fromStdString(pkg.GetPkgFlags()); - QDir game_dir(QString::fromStdString(extract_path.string())); + bool use_game_update = pkgType.contains("PATCH") && Config::getSeparateUpdateEnabled(); + auto game_update_path = use_game_update + ? game_install_dir / (std::string(pkg.GetTitleID()) + "-UPDATE") + : game_folder_path; + QString gameDirPath; + Common::FS::PathToQString(gameDirPath, game_folder_path); + QDir game_dir(gameDirPath); if (game_dir.exists()) { QMessageBox msgBox; - msgBox.setWindowTitle("PKG Extraction"); + msgBox.setWindowTitle(tr("PKG Extraction")); + + if (!psf.Open(pkg.sfo)) { + QMessageBox::critical(this, tr("PKG ERROR"), + "Could not read SFO. Check log for details"); + return; + } + + std::string content_id; + if (auto value = psf.GetString("CONTENT_ID"); value.has_value()) { + content_id = std::string{*value}; + } else { + QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no CONTENT_ID"); + return; + } + std::string entitlement_label = Common::SplitString(content_id, '-')[2]; + + auto addon_extract_path = + Config::getAddonInstallDir() / pkg.GetTitleID() / entitlement_label; + QString addonDirPath; + Common::FS::PathToQString(addonDirPath, addon_extract_path); + QDir addon_dir(addonDirPath); + auto category = psf.GetString("CATEGORY"); + if (pkgType.contains("PATCH")) { - psf.open("", pkg.sfo); - QString pkg_app_version = QString::fromStdString(psf.GetString("APP_VER")); - psf.open(extract_path.string() + "/sce_sys/param.sfo", {}); - QString game_app_version = QString::fromStdString(psf.GetString("APP_VER")); + QString pkg_app_version; + if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) { + pkg_app_version = QString::fromStdString(std::string{*app_ver}); + } else { + QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no APP_VER"); + return; + } + std::filesystem::path sce_folder_path = + std::filesystem::exists(game_update_path / "sce_sys" / "param.sfo") + ? game_update_path / "sce_sys" / "param.sfo" + : game_folder_path / "sce_sys" / "param.sfo"; + psf.Open(sce_folder_path); + QString game_app_version; + if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) { + game_app_version = QString::fromStdString(std::string{*app_ver}); + } else { + QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no APP_VER"); + return; + } double appD = game_app_version.toDouble(); double pkgD = pkg_app_version.toDouble(); if (pkgD == appD) { - msgBox.setText( - QString("Patch detected!\nPKG and Game versions match!: %1\nWould you like " - "to overwrite?") - .arg(pkg_app_version)); + msgBox.setText(QString(tr("Patch detected!") + "\n" + + tr("PKG and Game versions match: ") + pkg_app_version + + "\n" + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } else if (pkgD < appD) { - msgBox.setText(QString("Patch detected!\nPKG Version %1 is older " - "than installed version!: %2\nWould you like " - "to overwrite?") - .arg(pkg_app_version, game_app_version)); + msgBox.setText(QString(tr("Patch detected!") + "\n" + + tr("PKG Version %1 is older than installed version: ") + .arg(pkg_app_version) + + game_app_version + "\n" + + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } else { - msgBox.setText(QString("Patch detected!\nGame is installed: %1\nWould you like " - "to install Patch: %2?") - .arg(game_app_version, pkg_app_version)); + msgBox.setText(QString(tr("Patch detected!") + "\n" + + tr("Game is installed: ") + game_app_version + "\n" + + tr("Would you like to install Patch: ") + + pkg_app_version + " ?")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); } @@ -573,9 +761,36 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } else { return; } + } else if (category == "ac") { + if (!addon_dir.exists()) { + QMessageBox addonMsgBox; + addonMsgBox.setWindowTitle(tr("DLC Installation")); + addonMsgBox.setText(QString(tr("Would you like to install DLC: %1?")) + .arg(QString::fromStdString(entitlement_label))); + + addonMsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + addonMsgBox.setDefaultButton(QMessageBox::No); + int result = addonMsgBox.exec(); + if (result == QMessageBox::Yes) { + game_update_path = addon_extract_path; + } else { + return; + } + } else { + msgBox.setText(QString(tr("DLC already installed:") + "\n" + addonDirPath + + "\n\n" + tr("Would you like to overwrite?"))); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int result = msgBox.exec(); + if (result == QMessageBox::Yes) { + game_update_path = addon_extract_path; + } else { + return; + } + } } else { - msgBox.setText(QString("Game already installed\n%1\nWould you like to overwrite?") - .arg(QString::fromStdString(extract_path.string()))); + msgBox.setText(QString(tr("Game already installed") + "\n" + gameDirPath + "\n" + + tr("Would you like to overwrite?"))); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int result = msgBox.exec(); @@ -588,59 +803,63 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } else { // Do nothing; if (pkgType.contains("PATCH")) { - QMessageBox::information(this, "PKG Extraction", - "PKG is a patch, please install the game first!"); + QMessageBox::information(this, tr("PKG Extraction"), + tr("PKG is a patch, please install the game first!")); return; } // what else? } - - if (!pkg.Extract(file, extract_path, failreason)) { - QMessageBox::critical(this, "PKG ERROR", QString::fromStdString(failreason)); + if (!pkg.Extract(file, game_update_path, failreason)) { + QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason)); } else { int nfiles = pkg.GetNumberOfFiles(); - QVector indices; - for (int i = 0; i < nfiles; i++) { - indices.append(i); - } - - QProgressDialog dialog; - dialog.setWindowTitle("PKG Extraction"); - dialog.setWindowModality(Qt::WindowModal); - QString extractmsg = QString("Extracting PKG %1/%2").arg(pkgNum).arg(nPkg); - dialog.setLabelText(extractmsg); - dialog.setAutoClose(true); - dialog.setRange(0, nfiles); - - QFutureWatcher futureWatcher; - connect(&futureWatcher, &QFutureWatcher::finished, this, [=, this]() { - if (pkgNum == nPkg) { - QString path = QString::fromStdString(Config::getGameInstallDir()); - QMessageBox extractMsgBox(this); - extractMsgBox.setWindowTitle("Extraction Finished"); - extractMsgBox.setText(QString("Game successfully installed at %1").arg(path)); - extractMsgBox.addButton(QMessageBox::Ok); - extractMsgBox.setDefaultButton(QMessageBox::Ok); - connect(&extractMsgBox, &QMessageBox::buttonClicked, this, - [&](QAbstractButton* button) { - if (extractMsgBox.button(QMessageBox::Ok) == button) { - extractMsgBox.close(); - emit ExtractionFinished(); - } - }); - extractMsgBox.exec(); + if (nfiles > 0) { + QVector indices; + for (int i = 0; i < nfiles; i++) { + indices.append(i); } - }); - connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); }); - connect(&futureWatcher, &QFutureWatcher::progressValueChanged, &dialog, - &QProgressDialog::setValue); - futureWatcher.setFuture( - QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); })); - dialog.exec(); + + QProgressDialog dialog; + dialog.setWindowTitle(tr("PKG Extraction")); + dialog.setWindowModality(Qt::WindowModal); + QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg); + dialog.setLabelText(extractmsg); + dialog.setAutoClose(true); + dialog.setRange(0, nfiles); + + QFutureWatcher futureWatcher; + connect(&futureWatcher, &QFutureWatcher::finished, this, [=, this]() { + if (pkgNum == nPkg) { + QString path; + Common::FS::PathToQString(path, game_install_dir); + QMessageBox extractMsgBox(this); + extractMsgBox.setWindowTitle(tr("Extraction Finished")); + extractMsgBox.setText( + QString(tr("Game successfully installed at %1")).arg(path)); + extractMsgBox.addButton(QMessageBox::Ok); + extractMsgBox.setDefaultButton(QMessageBox::Ok); + connect(&extractMsgBox, &QMessageBox::buttonClicked, this, + [&](QAbstractButton* button) { + if (extractMsgBox.button(QMessageBox::Ok) == button) { + extractMsgBox.close(); + emit ExtractionFinished(); + } + }); + extractMsgBox.exec(); + } + }); + connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); }); + connect(&futureWatcher, &QFutureWatcher::progressValueChanged, &dialog, + &QProgressDialog::setValue); + futureWatcher.setFuture( + QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); })); + dialog.exec(); + } } } else { - QMessageBox::critical(this, "PKG ERROR", "File doesn't appear to be a valid PKG file"); + QMessageBox::critical(this, tr("PKG ERROR"), + tr("File doesn't appear to be a valid PKG file")); } } @@ -714,6 +933,10 @@ void MainWindow::SetUiIcons(bool isWhite) { ui->bootInstallPkgAct->setIcon(RecolorIcon(ui->bootInstallPkgAct->icon(), isWhite)); ui->bootGameAct->setIcon(RecolorIcon(ui->bootGameAct->icon(), isWhite)); ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite)); + ui->updaterAct->setIcon(RecolorIcon(ui->updaterAct->icon(), isWhite)); + ui->downloadCheatsPatchesAct->setIcon( + RecolorIcon(ui->downloadCheatsPatchesAct->icon(), isWhite)); + ui->dumpGameListAct->setIcon(RecolorIcon(ui->dumpGameListAct->icon(), isWhite)); ui->aboutAct->setIcon(RecolorIcon(ui->aboutAct->icon(), isWhite)); ui->setlistModeListAct->setIcon(RecolorIcon(ui->setlistModeListAct->icon(), isWhite)); ui->setlistModeGridAct->setIcon(RecolorIcon(ui->setlistModeGridAct->icon(), isWhite)); @@ -723,6 +946,7 @@ void MainWindow::SetUiIcons(bool isWhite) { ui->playButton->setIcon(RecolorIcon(ui->playButton->icon(), isWhite)); ui->pauseButton->setIcon(RecolorIcon(ui->pauseButton->icon(), isWhite)); ui->stopButton->setIcon(RecolorIcon(ui->stopButton->icon(), isWhite)); + ui->refreshButton->setIcon(RecolorIcon(ui->refreshButton->icon(), isWhite)); ui->settingsButton->setIcon(RecolorIcon(ui->settingsButton->icon(), isWhite)); ui->controllerButton->setIcon(RecolorIcon(ui->controllerButton->icon(), isWhite)); ui->refreshGameListAct->setIcon(RecolorIcon(ui->refreshGameListAct->icon(), isWhite)); @@ -780,9 +1004,59 @@ void MainWindow::CreateRecentGameActions() { } connect(m_recent_files_group, &QActionGroup::triggered, this, [this](QAction* action) { - QString gamePath = action->text(); - AddRecentFiles(gamePath); // Update the list. + auto gamePath = Common::FS::PathFromQString(action->text()); + AddRecentFiles(action->text()); // Update the list. Core::Emulator emulator; - emulator.Run(gamePath.toUtf8().constData()); + if (!std::filesystem::exists(gamePath)) { + QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found"))); + return; + } + emulator.Run(gamePath); }); } + +void MainWindow::LoadTranslation() { + auto language = QString::fromStdString(Config::getEmulatorLanguage()); + + const QString base_dir = QStringLiteral(":/translations"); + QString base_path = QStringLiteral("%1/%2.qm").arg(base_dir).arg(language); + + if (QFile::exists(base_path)) { + if (translator != nullptr) { + qApp->removeTranslator(translator); + } + + translator = new QTranslator(qApp); + if (!translator->load(base_path)) { + QMessageBox::warning( + nullptr, QStringLiteral("Translation Error"), + QStringLiteral("Failed to find load translation file for '%1':\n%2") + .arg(language) + .arg(base_path)); + delete translator; + } else { + qApp->installTranslator(translator); + ui->retranslateUi(this); + } + } +} + +void MainWindow::OnLanguageChanged(const std::string& locale) { + Config::setEmulatorLanguage(locale); + + LoadTranslation(); +} + +bool MainWindow::eventFilter(QObject* obj, QEvent* event) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { + auto tblMode = Config::getTableMode(); + if (tblMode != 2 && (tblMode != 1 || m_game_grid_frame->IsValidCellSelected())) { + StartGame(); + return true; + } + } + } + return QMainWindow::eventFilter(obj, event); +} diff --git a/src/qt_gui/main_window.h b/src/qt_gui/main_window.h index 24de15b92..6264978aa 100644 --- a/src/qt_gui/main_window.h +++ b/src/qt_gui/main_window.h @@ -3,15 +3,13 @@ #pragma once -#include #include #include -#include -#include -#include -#include +#include +#include "background_music_player.h" #include "common/config.h" +#include "common/discord_rpc_handler.h" #include "common/path_util.h" #include "core/file_format/psf.h" #include "core/file_sys/fs.h" @@ -48,6 +46,7 @@ private Q_SLOTS: void ShowGameList(); void RefreshGameTable(); void HandleResize(QResizeEvent* event); + void OnLanguageChanged(const std::string& locale); private: Ui_MainWindow* ui; @@ -57,6 +56,7 @@ private: void CreateDockWindows(); void GetPhysicalDevices(); void LoadGameLists(); + void CheckUpdateMain(bool checkSave); void CreateConnects(); void SetLastUsedTheme(); void SetLastIconSizeBullet(); @@ -64,9 +64,12 @@ private: void InstallPkg(); void BootGame(); void AddRecentFiles(QString filePath); + void LoadTranslation(); + void PlayBackgroundMusic(); QIcon RecolorIcon(const QIcon& icon, bool isWhite); bool isIconBlack = false; bool isTableList = true; + bool isGameRunning = false; QActionGroup* m_icon_size_act_group = nullptr; QActionGroup* m_list_mode_act_group = nullptr; QActionGroup* m_theme_act_group = nullptr; @@ -89,7 +92,11 @@ private: std::shared_ptr m_game_info = std::make_shared(); + QTranslator* translator; + protected: + bool eventFilter(QObject* obj, QEvent* event) override; + void dragEnterEvent(QDragEnterEvent* event1) override { if (event1->mimeData()->hasUrls()) { event1->acceptProposedAction(); @@ -104,10 +111,7 @@ protected: int nPkg = urlList.size(); for (const QUrl& url : urlList) { pkgNum++; - std::filesystem::path path(url.toLocalFile().toStdString()); -#ifdef _WIN64 - path = std::filesystem::path(url.toLocalFile().toStdWString()); -#endif + std::filesystem::path path = Common::FS::PathFromQString(url.toLocalFile()); InstallDragDropPkg(path, pkgNum, nPkg); } } diff --git a/src/qt_gui/main_window_themes.cpp b/src/qt_gui/main_window_themes.cpp index c89fa5a00..35e64ef74 100644 --- a/src/qt_gui/main_window_themes.cpp +++ b/src/qt_gui/main_window_themes.cpp @@ -8,13 +8,13 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) { switch (theme) { case Theme::Dark: - mw_searchbar->setStyleSheet("background-color: #1e1e1e; /* Dark background */" - "color: #ffffff; /* White text */" - "border: 1px solid #ffffff; /* White border */" + mw_searchbar->setStyleSheet("background-color: #1e1e1e;" // Dark background + "color: #ffffff;" // White text + "border: 2px solid #ffffff;" // White border "padding: 5px;"); - themePalette.setColor(QPalette::Window, QColor(53, 53, 53)); + themePalette.setColor(QPalette::Window, QColor(50, 50, 50)); themePalette.setColor(QPalette::WindowText, Qt::white); - themePalette.setColor(QPalette::Base, QColor(25, 25, 25)); + themePalette.setColor(QPalette::Base, QColor(20, 20, 20)); themePalette.setColor(QPalette::AlternateBase, QColor(25, 25, 25)); themePalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); themePalette.setColor(QPalette::ToolTipBase, Qt::white); @@ -30,8 +30,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) { break; case Theme::Light: - mw_searchbar->setStyleSheet("background-color: #ffffff; /* Light gray background */" - "color: #000000; /* Black text */" + mw_searchbar->setStyleSheet("background-color: #ffffff;" // Light gray background + "color: #000000;" // Black text + "border: 2px solid #000000;" // Black border "padding: 5px;"); themePalette.setColor(QPalette::Window, QColor(240, 240, 240)); // Light gray themePalette.setColor(QPalette::WindowText, Qt::black); // Black @@ -49,9 +50,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) { break; case Theme::Green: - mw_searchbar->setStyleSheet("background-color: #354535; /* Dark green background */" - "color: #ffffff; /* White text */" - "border: 1px solid #ffffff; /* White border */" + mw_searchbar->setStyleSheet("background-color: #1e1e1e;" // Dark background + "color: #ffffff;" // White text + "border: 2px solid #ffffff;" // White border "padding: 5px;"); themePalette.setColor(QPalette::Window, QColor(53, 69, 53)); // Dark green background themePalette.setColor(QPalette::WindowText, Qt::white); // White text @@ -72,9 +73,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) { break; case Theme::Blue: - mw_searchbar->setStyleSheet("background-color: #283c5a; /* Dark blue background */" - "color: #ffffff; /* White text */" - "border: 1px solid #ffffff; /* White border */" + mw_searchbar->setStyleSheet("background-color: #1e1e1e;" // Dark background + "color: #ffffff;" // White text + "border: 2px solid #ffffff;" // White border "padding: 5px;"); themePalette.setColor(QPalette::Window, QColor(40, 60, 90)); // Dark blue background themePalette.setColor(QPalette::WindowText, Qt::white); // White text @@ -95,9 +96,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) { break; case Theme::Violet: - mw_searchbar->setStyleSheet("background-color: #643278; /* Violet background */" - "color: #ffffff; /* White text */" - "border: 1px solid #ffffff; /* White border */" + mw_searchbar->setStyleSheet("background-color: #1e1e1e;" // Dark background + "color: #ffffff;" // White text + "border: 2px solid #ffffff;" // White border "padding: 5px;"); themePalette.setColor(QPalette::Window, QColor(100, 50, 120)); // Violet background themePalette.setColor(QPalette::WindowText, Qt::white); // White text diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 7d0c58dd2..373b2924e 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -1,31 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -/******************************************************************************** -** Form generated from reading UI file 'main_window.ui' -** -** Created by: Qt User Interface Compiler version 6.6.1 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ +#pragma once -#ifndef MAIN_WINDOW_UI_H -#define MAIN_WINDOW_UI_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE +#include +#include +#include class Ui_MainWindow { public: @@ -43,8 +23,10 @@ public: QAction* setlistModeGridAct; QAction* setlistElfAct; QAction* gameInstallPathAct; + QAction* downloadCheatsPatchesAct; QAction* dumpGameListAct; QAction* pkgViewerAct; + QAction* updaterAct; QAction* aboutAct; QAction* configureAct; QAction* setThemeDark; @@ -57,6 +39,7 @@ public: QPushButton* playButton; QPushButton* pauseButton; QPushButton* stopButton; + QPushButton* refreshButton; QPushButton* settingsButton; QPushButton* controllerButton; @@ -72,7 +55,7 @@ public: QMenu* menuSettings; QMenu* menuUtils; QMenu* menuThemes; - QMenu* menuAbout; + QMenu* menuHelp; QToolBar* toolBar; void setupUi(QMainWindow* MainWindow) { @@ -138,12 +121,18 @@ public: gameInstallPathAct = new QAction(MainWindow); gameInstallPathAct->setObjectName("gameInstallPathAct"); gameInstallPathAct->setIcon(QIcon(":images/folder_icon.png")); + downloadCheatsPatchesAct = new QAction(MainWindow); + downloadCheatsPatchesAct->setObjectName("downloadCheatsPatchesAct"); + downloadCheatsPatchesAct->setIcon(QIcon(":images/update_icon.png")); dumpGameListAct = new QAction(MainWindow); dumpGameListAct->setObjectName("dumpGameList"); + dumpGameListAct->setIcon(QIcon(":images/dump_icon.png")); pkgViewerAct = new QAction(MainWindow); pkgViewerAct->setObjectName("pkgViewer"); - pkgViewerAct->setObjectName("pkgViewer"); pkgViewerAct->setIcon(QIcon(":images/file_icon.png")); + updaterAct = new QAction(MainWindow); + updaterAct->setObjectName("updaterAct"); + updaterAct->setIcon(QIcon(":images/update_icon.png")); aboutAct = new QAction(MainWindow); aboutAct->setObjectName("aboutAct"); aboutAct->setIcon(QIcon(":images/about_icon.png")); @@ -194,10 +183,14 @@ public: stopButton->setFlat(true); stopButton->setIcon(QIcon(":images/stop_icon.png")); stopButton->setIconSize(QSize(40, 40)); + refreshButton = new QPushButton(centralWidget); + refreshButton->setFlat(true); + refreshButton->setIcon(QIcon(":images/refresh_icon.png")); + refreshButton->setIconSize(QSize(32, 32)); settingsButton = new QPushButton(centralWidget); settingsButton->setFlat(true); settingsButton->setIcon(QIcon(":images/settings_icon.png")); - settingsButton->setIconSize(QSize(40, 40)); + settingsButton->setIconSize(QSize(44, 44)); controllerButton = new QPushButton(centralWidget); controllerButton->setFlat(true); controllerButton->setIcon(QIcon(":images/controller_icon.png")); @@ -256,8 +249,8 @@ public: menuThemes = new QMenu(menuView); menuThemes->setObjectName("menuThemes"); menuThemes->setIcon(QIcon(":images/themes_icon.png")); - menuAbout = new QMenu(menuBar); - menuAbout->setObjectName("menuAbout"); + menuHelp = new QMenu(menuBar); + menuHelp->setObjectName("menuHelp"); MainWindow->setMenuBar(menuBar); toolBar = new QToolBar(MainWindow); toolBar->setObjectName("toolBar"); @@ -266,7 +259,7 @@ public: menuBar->addAction(menuFile->menuAction()); menuBar->addAction(menuView->menuAction()); menuBar->addAction(menuSettings->menuAction()); - menuBar->addAction(menuAbout->menuAction()); + menuBar->addAction(menuHelp->menuAction()); menuFile->addAction(bootInstallPkgAct); menuFile->addAction(bootGameAct); menuFile->addAction(addElfFolderAct); @@ -280,8 +273,8 @@ public: menuView->addAction(menuGame_List_Mode->menuAction()); menuView->addAction(menuGame_List_Icons->menuAction()); menuView->addAction(menuThemes->menuAction()); - menuThemes->addAction(setThemeLight); menuThemes->addAction(setThemeDark); + menuThemes->addAction(setThemeLight); menuThemes->addAction(setThemeGreen); menuThemes->addAction(setThemeBlue); menuThemes->addAction(setThemeViolet); @@ -295,9 +288,11 @@ public: menuSettings->addAction(configureAct); menuSettings->addAction(gameInstallPathAct); menuSettings->addAction(menuUtils->menuAction()); + menuUtils->addAction(downloadCheatsPatchesAct); menuUtils->addAction(dumpGameListAct); menuUtils->addAction(pkgViewerAct); - menuAbout->addAction(aboutAct); + menuHelp->addAction(updaterAct); + menuHelp->addAction(aboutAct); retranslateUi(MainWindow); @@ -311,6 +306,8 @@ public: bootInstallPkgAct->setText( QCoreApplication::translate("MainWindow", "Install Packages (PKG)", nullptr)); bootGameAct->setText(QCoreApplication::translate("MainWindow", "Boot Game", nullptr)); + updaterAct->setText( + QCoreApplication::translate("MainWindow", "Check for Updates", nullptr)); aboutAct->setText(QCoreApplication::translate("MainWindow", "About shadPS4", nullptr)); configureAct->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr)); #if QT_CONFIG(tooltip) @@ -341,6 +338,8 @@ public: setlistElfAct->setText(QCoreApplication::translate("MainWindow", "Elf Viewer", nullptr)); gameInstallPathAct->setText( QCoreApplication::translate("MainWindow", "Game Install Directory", nullptr)); + downloadCheatsPatchesAct->setText( + QCoreApplication::translate("MainWindow", "Download Cheats/Patches", nullptr)); dumpGameListAct->setText( QCoreApplication::translate("MainWindow", "Dump Game List", nullptr)); pkgViewerAct->setText(QCoreApplication::translate("MainWindow", "PKG Viewer", nullptr)); @@ -355,7 +354,7 @@ public: menuSettings->setTitle(QCoreApplication::translate("MainWindow", "Settings", nullptr)); menuUtils->setTitle(QCoreApplication::translate("MainWindow", "Utils", nullptr)); menuThemes->setTitle(QCoreApplication::translate("MainWindow", "Themes", nullptr)); - menuAbout->setTitle(QCoreApplication::translate("MainWindow", "About", nullptr)); + menuHelp->setTitle(QCoreApplication::translate("MainWindow", "Help", nullptr)); setThemeDark->setText(QCoreApplication::translate("MainWindow", "Dark", nullptr)); setThemeLight->setText(QCoreApplication::translate("MainWindow", "Light", nullptr)); setThemeGreen->setText(QCoreApplication::translate("MainWindow", "Green", nullptr)); @@ -367,8 +366,4 @@ public: namespace Ui { class MainWindow : public Ui_MainWindow {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // MAIN_WINDOW_UI_H +} // namespace Ui \ No newline at end of file diff --git a/src/qt_gui/pkg_viewer.cpp b/src/qt_gui/pkg_viewer.cpp index cd2ce2b6e..0ffb9b579 100644 --- a/src/qt_gui/pkg_viewer.cpp +++ b/src/qt_gui/pkg_viewer.cpp @@ -1,9 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include - #include "pkg_viewer.h" PKGViewer::PKGViewer(std::shared_ptr game_info_get, QWidget* parent, @@ -54,7 +51,7 @@ PKGViewer::PKGViewer(std::shared_ptr game_info_get, QWidget* pare InstallDragDropPkg); }); - connect(parent, &QWidget::destroyed, this, [parent, this]() { this->deleteLater(); }); + connect(parent, &QWidget::destroyed, this, [this]() { this->deleteLater(); }); } PKGViewer::~PKGViewer() {} @@ -107,18 +104,23 @@ void PKGViewer::ProcessPKGInfo() { m_pkg_patch_list.clear(); m_full_pkg_list.clear(); for (int i = 0; i < m_pkg_list.size(); i++) { - std::filesystem::path path(m_pkg_list[i].toStdString()); -#ifdef _WIN32 - path = std::filesystem::path(m_pkg_list[i].toStdWString()); -#endif - package.Open(path); - psf.open("", package.sfo); - QString title_name = QString::fromStdString(psf.GetString("TITLE")); - QString title_id = QString::fromStdString(psf.GetString("TITLE_ID")); - QString app_type = game_list_util.GetAppType(psf.GetInteger("APP_TYPE")); - QString app_version = QString::fromStdString(psf.GetString("APP_VER")); - QString title_category = QString::fromStdString(psf.GetString("CATEGORY")); - QString pkg_size = game_list_util.FormatSize(package.GetPkgHeader().pkg_size); + std::filesystem::path path = Common::FS::PathFromQString(m_pkg_list[i]); + std::string failreason; + if (!package.Open(path, failreason)) { + QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason)); + return; + } + psf.Open(package.sfo); + QString title_name = + QString::fromStdString(std::string{psf.GetString("TITLE").value_or("Unknown")}); + QString title_id = + QString::fromStdString(std::string{psf.GetString("TITLE_ID").value_or("Unknown")}); + QString app_type = GameListUtils::GetAppType(psf.GetInteger("APP_TYPE").value_or(0)); + QString app_version = + QString::fromStdString(std::string{psf.GetString("APP_VER").value_or("Unknown")}); + QString title_category = + QString::fromStdString(std::string{psf.GetString("CATEGORY").value_or("Unknown")}); + QString pkg_size = GameListUtils::FormatSize(package.GetPkgHeader().pkg_size); pkg_content_flag = package.GetPkgHeader().pkg_content_flags; QString flagss = ""; for (const auto& flag : package.flagNames) { @@ -129,11 +131,17 @@ void PKGViewer::ProcessPKGInfo() { } } - u32 fw_int = psf.GetInteger("SYSTEM_VER"); - QString fw = QString::number(fw_int, 16); - QString fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.') + QString fw_ = "Unknown"; + if (const auto fw_int_opt = psf.GetInteger("SYSTEM_VER"); fw_int_opt.has_value()) { + const u32 fw_int = *fw_int_opt; + if (fw_int == 0) { + fw_ = "0.00"; + } else { + QString fw = QString::number(fw_int, 16); + fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.') : fw.left(3).insert(1, '.'); - fw_ = (fw_int == 0) ? "0.00" : fw_; + } + } char region = package.GetPkgHeader().pkg_content_id[0]; QString pkg_info = ""; if (title_category == "gd" && !flagss.contains("PATCH")) { diff --git a/src/qt_gui/pkg_viewer.h b/src/qt_gui/pkg_viewer.h index e040d5950..265a03b92 100644 --- a/src/qt_gui/pkg_viewer.h +++ b/src/qt_gui/pkg_viewer.h @@ -3,18 +3,9 @@ #pragma once -#include -#include -#include -#include #include -#include -#include #include #include -#include -#include -#include #include "common/io_file.h" #include "core/file_format/pkg.h" @@ -42,7 +33,6 @@ private: PKGHeader pkgheader; PKGEntry entry; PSFHeader header; - PSFEntry psfentry; char pkgTitleID[9]; std::vector pkg; u64 pkgSize = 0; diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index aa2c73384..309b40b46 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -2,6 +2,14 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include + +#include +#include "check_update.h" +#include "common/logging/backend.h" +#include "common/logging/filter.h" +#include "main_window.h" #include "settings_dialog.h" #include "ui_settings_dialog.h" @@ -43,6 +51,7 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); ui->tabWidgetSettings->setUsesScrollButtons(false); + initialHeight = this->height(); const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); ui->buttonBox->button(QDialogButtonBox::StandardButton::Close)->setFocus(); @@ -59,8 +68,21 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge completer->setCaseSensitivity(Qt::CaseInsensitive); ui->consoleLanguageComboBox->setCompleter(completer); + ui->hideCursorComboBox->addItem(tr("Never")); + ui->hideCursorComboBox->addItem(tr("Idle")); + ui->hideCursorComboBox->addItem(tr("Always")); + + ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Left"), "left"); + ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Center"), "center"); + ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Right"), "right"); + ui->backButtonBehaviorComboBox->addItem(tr("None"), "none"); + + InitializeEmulatorLanguages(); LoadValuesFromConfig(); + defaultTextEdit = tr("Point your mouse at an option to display its description."); + ui->descriptionText->setText(defaultTextEdit); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, @@ -74,11 +96,20 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge Config::setDefaultValues(); LoadValuesFromConfig(); } + if (Common::Log::IsActive()) { + Common::Log::Filter filter; + filter.ParseFilterString(Config::getLogFilter()); + Common::Log::SetGlobalFilter(filter); + } }); - connect(ui->tabWidgetSettings, &QTabWidget::currentChanged, this, [this]() { - ui->buttonBox->button(QDialogButtonBox::StandardButton::Close)->setFocus(); - }); + ui->buttonBox->button(QDialogButtonBox::Save)->setText(tr("Save")); + ui->buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Apply")); + ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setText(tr("Restore Defaults")); + ui->buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close")); + + connect(ui->tabWidgetSettings, &QTabWidget::currentChanged, this, + [this]() { ui->buttonBox->button(QDialogButtonBox::Close)->setFocus(); }); // GENERAL TAB { @@ -86,7 +117,7 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge [](const QString& text) { Config::setUserName(text.toStdString()); }); connect(ui->consoleLanguageComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this](int index) { + this, [](int index) { if (index >= 0 && index < languageIndexes.size()) { int languageCode = languageIndexes[index]; Config::setLanguage(languageCode); @@ -96,6 +127,9 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge connect(ui->fullscreenCheckBox, &QCheckBox::stateChanged, this, [](int val) { Config::setFullscreenMode(val); }); + connect(ui->separateUpdatesCheckBox, &QCheckBox::stateChanged, this, + [](int val) { Config::setSeparateUpdateEnabled(val); }); + connect(ui->showSplashCheckBox, &QCheckBox::stateChanged, this, [](int val) { Config::setShowSplash(val); }); @@ -107,6 +141,60 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge connect(ui->logFilterLineEdit, &QLineEdit::textChanged, this, [](const QString& text) { Config::setLogFilter(text.toStdString()); }); + + connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, + [](int state) { Config::setAutoUpdate(state == Qt::Checked); }); + + connect(ui->updateComboBox, &QComboBox::currentTextChanged, this, + [](const QString& channel) { Config::setUpdateChannel(channel.toStdString()); }); + + connect(ui->checkUpdateButton, &QPushButton::clicked, this, []() { + auto checkUpdate = new CheckUpdate(true); + checkUpdate->exec(); + }); + + connect(ui->playBGMCheckBox, &QCheckBox::stateChanged, this, [](int val) { + Config::setPlayBGM(val); + if (val == Qt::Unchecked) { + BackgroundMusicPlayer::getInstance().stopMusic(); + } + }); + + connect(ui->BGMVolumeSlider, &QSlider::valueChanged, this, [](float val) { + Config::setBGMvolume(val); + BackgroundMusicPlayer::getInstance().setVolume(val); + }); + + connect(ui->discordRPCCheckbox, &QCheckBox::stateChanged, this, [](int val) { + Config::setEnableDiscordRPC(val); + auto* rpc = Common::Singleton::Instance(); + if (val == Qt::Checked) { + rpc->init(); + rpc->setStatusIdling(); + } else { + rpc->shutdown(); + } + }); + } + + // Input TAB + { + connect(ui->hideCursorComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [this](s16 index) { + Config::setCursorState(index); + OnCursorStateChanged(index); + }); + + connect(ui->idleTimeoutSpinBox, &QSpinBox::valueChanged, this, + [](int index) { Config::setCursorHideTimeout(index); }); + + connect(ui->backButtonBehaviorComboBox, QOverload::of(&QComboBox::currentIndexChanged), + this, [this](int index) { + if (index >= 0 && index < ui->backButtonBehaviorComboBox->count()) { + QString data = ui->backButtonBehaviorComboBox->itemData(index).toString(); + Config::setBackButtonBehavior(data.toStdString()); + } + }); } // GPU TAB @@ -130,9 +218,35 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge connect(ui->nullGpuCheckBox, &QCheckBox::stateChanged, this, [](int val) { Config::setNullGpu(val); }); + } - connect(ui->dumpPM4CheckBox, &QCheckBox::stateChanged, this, - [](int val) { Config::setDumpPM4(val); }); + // PATH TAB + { + connect(ui->addFolderButton, &QPushButton::clicked, this, [this]() { + const auto config_dir = Config::getGameInstallDirs(); + QString file_path_string = + QFileDialog::getExistingDirectory(this, tr("Directory to install games")); + auto file_path = Common::FS::PathFromQString(file_path_string); + if (!file_path.empty() && Config::addGameInstallDir(file_path)) { + QListWidgetItem* item = new QListWidgetItem(file_path_string); + ui->gameFoldersListWidget->addItem(item); + } + }); + + connect(ui->gameFoldersListWidget, &QListWidget::itemSelectionChanged, this, [this]() { + ui->removeFolderButton->setEnabled( + !ui->gameFoldersListWidget->selectedItems().isEmpty()); + }); + + connect(ui->removeFolderButton, &QPushButton::clicked, this, [this]() { + QListWidgetItem* selected_item = ui->gameFoldersListWidget->currentItem(); + QString item_path_string = selected_item ? selected_item->text() : QString(); + if (!item_path_string.isEmpty()) { + auto file_path = Common::FS::PathFromQString(item_path_string); + Config::removeGameInstallDir(file_path); + delete selected_item; + } + }); } // DEBUG TAB @@ -149,6 +263,48 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge connect(ui->rdocCheckBox, &QCheckBox::stateChanged, this, [](int val) { Config::setRdocEnabled(val); }); } + + // Descriptions + { + // General + ui->consoleLanguageGroupBox->installEventFilter(this); + ui->emulatorLanguageGroupBox->installEventFilter(this); + 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->logTypeGroupBox->installEventFilter(this); + ui->logFilter->installEventFilter(this); + ui->updaterGroupBox->installEventFilter(this); + ui->GUIgroupBox->installEventFilter(this); + + // Input + ui->hideCursorGroupBox->installEventFilter(this); + ui->idleTimeoutGroupBox->installEventFilter(this); + ui->backButtonBehaviorGroupBox->installEventFilter(this); + + // Graphics + ui->graphicsAdapterGroupBox->installEventFilter(this); + ui->widthGroupBox->installEventFilter(this); + ui->heightGroupBox->installEventFilter(this); + ui->heightDivider->installEventFilter(this); + ui->dumpShadersCheckBox->installEventFilter(this); + ui->nullGpuCheckBox->installEventFilter(this); + + // Paths + ui->gameFoldersGroupBox->installEventFilter(this); + ui->gameFoldersListWidget->installEventFilter(this); + ui->addFolderButton->installEventFilter(this); + ui->removeFolderButton->installEventFilter(this); + + // Debug + ui->debugDump->installEventFilter(this); + ui->vkValidationCheckBox->installEventFilter(this); + ui->vkSyncValidationCheckBox->installEventFilter(this); + ui->rdocCheckBox->installEventFilter(this); + } } void SettingsDialog::LoadValuesFromConfig() { @@ -157,15 +313,21 @@ void SettingsDialog::LoadValuesFromConfig() { languageIndexes.begin(), std::find(languageIndexes.begin(), languageIndexes.end(), Config::GetLanguage())) % languageIndexes.size()); + ui->emulatorLanguageComboBox->setCurrentIndex(languages[Config::getEmulatorLanguage()]); + ui->hideCursorComboBox->setCurrentIndex(Config::getCursorState()); + OnCursorStateChanged(Config::getCursorState()); + ui->idleTimeoutSpinBox->setValue(Config::getCursorHideTimeout()); ui->graphicsAdapterBox->setCurrentIndex(Config::getGpuId() + 1); ui->widthSpinBox->setValue(Config::getScreenWidth()); ui->heightSpinBox->setValue(Config::getScreenHeight()); ui->vblankSpinBox->setValue(Config::vblankDiv()); ui->dumpShadersCheckBox->setChecked(Config::dumpShaders()); ui->nullGpuCheckBox->setChecked(Config::nullGpu()); - ui->dumpPM4CheckBox->setChecked(Config::dumpPM4()); - + ui->playBGMCheckBox->setChecked(Config::getPlayBGM()); + ui->BGMVolumeSlider->setValue((Config::getBGMvolume())); + ui->discordRPCCheckbox->setChecked(Config::getEnableDiscordRPC()); ui->fullscreenCheckBox->setChecked(Config::isFullscreenMode()); + ui->separateUpdatesCheckBox->setChecked(Config::getSeparateUpdateEnabled()); ui->showSplashCheckBox->setChecked(Config::showSplash()); ui->ps4proCheckBox->setChecked(Config::isNeoMode()); ui->logTypeComboBox->setCurrentText(QString::fromStdString(Config::getLogType())); @@ -176,6 +338,86 @@ void SettingsDialog::LoadValuesFromConfig() { ui->vkValidationCheckBox->setChecked(Config::vkValidationEnabled()); ui->vkSyncValidationCheckBox->setChecked(Config::vkValidationSyncEnabled()); ui->rdocCheckBox->setChecked(Config::isRdocEnabled()); + + ui->updateCheckBox->setChecked(Config::autoUpdate()); + std::string updateChannel = Config::getUpdateChannel(); + if (updateChannel != "Release" && updateChannel != "Nightly") { + if (Common::isRelease) { + updateChannel = "Release"; + } else { + updateChannel = "Nightly"; + } + } + ui->updateComboBox->setCurrentText(QString::fromStdString(updateChannel)); + + for (const auto& dir : Config::getGameInstallDirs()) { + QString path_string; + Common::FS::PathToQString(path_string, dir); + QListWidgetItem* item = new QListWidgetItem(path_string); + ui->gameFoldersListWidget->addItem(item); + } + + QString backButtonBehavior = QString::fromStdString(Config::getBackButtonBehavior()); + int index = ui->backButtonBehaviorComboBox->findData(backButtonBehavior); + ui->backButtonBehaviorComboBox->setCurrentIndex(index != -1 ? index : 0); + + ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty()); +} + +void SettingsDialog::InitializeEmulatorLanguages() { + QDirIterator it(QStringLiteral(":/translations"), QDirIterator::NoIteratorFlags); + + QVector> languagesList; + + while (it.hasNext()) { + QString locale = it.next(); + locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); + locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); + const QString lang = QLocale::languageToString(QLocale(locale).language()); + const QString country = QLocale::territoryToString(QLocale(locale).territory()); + + QString displayName = QStringLiteral("%1 (%2)").arg(lang, country); + languagesList.append(qMakePair(locale, displayName)); + } + + std::sort(languagesList.begin(), languagesList.end(), + [](const QPair& a, const QPair& b) { + return a.second < b.second; + }); + + int idx = 0; + for (const auto& pair : languagesList) { + const QString& locale = pair.first; + const QString& displayName = pair.second; + + ui->emulatorLanguageComboBox->addItem(displayName, locale); + languages[locale.toStdString()] = idx; + idx++; + } + + connect(ui->emulatorLanguageComboBox, qOverload(&QComboBox::currentIndexChanged), this, + &SettingsDialog::OnLanguageChanged); +} + +void SettingsDialog::OnLanguageChanged(int index) { + if (index == -1) + return; + + ui->retranslateUi(this); + + emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString()); +} + +void SettingsDialog::OnCursorStateChanged(s16 index) { + if (index == -1) + return; + if (index == Config::HideCursorState::Idle) { + ui->idleTimeoutGroupBox->show(); + } else { + if (!ui->idleTimeoutGroupBox->isHidden()) { + ui->idleTimeoutGroupBox->hide(); + } + } } int SettingsDialog::exec() { @@ -183,3 +425,113 @@ int SettingsDialog::exec() { } SettingsDialog::~SettingsDialog() {} + +void SettingsDialog::updateNoteTextEdit(const QString& elementName) { + QString text; // texts are only in .ts translation files for better formatting + + // General + if (elementName == "consoleLanguageGroupBox") { + text = tr("consoleLanguageGroupBox"); + } else if (elementName == "emulatorLanguageGroupBox") { + text = tr("emulatorLanguageGroupBox"); + } else if (elementName == "fullscreenCheckBox") { + text = tr("fullscreenCheckBox"); + } else if (elementName == "separateUpdatesCheckBox") { + 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 == "logTypeGroupBox") { + text = tr("logTypeGroupBox"); + } else if (elementName == "logFilter") { + text = tr("logFilter"); + } else if (elementName == "updaterGroupBox") { + text = tr("updaterGroupBox"); + } else if (elementName == "GUIgroupBox") { + text = tr("GUIgroupBox"); + } + + // Input + if (elementName == "hideCursorGroupBox") { + text = tr("hideCursorGroupBox"); + } else if (elementName == "idleTimeoutGroupBox") { + text = tr("idleTimeoutGroupBox"); + } else if (elementName == "backButtonBehaviorGroupBox") { + text = tr("backButtonBehaviorGroupBox"); + } + + // Graphics + if (elementName == "graphicsAdapterGroupBox") { + text = tr("graphicsAdapterGroupBox"); + } else if (elementName == "widthGroupBox") { + text = tr("resolutionLayout"); + } else if (elementName == "heightGroupBox") { + text = tr("resolutionLayout"); + } else if (elementName == "heightDivider") { + text = tr("heightDivider"); + } else if (elementName == "dumpShadersCheckBox") { + text = tr("dumpShadersCheckBox"); + } else if (elementName == "nullGpuCheckBox") { + text = tr("nullGpuCheckBox"); + } + + // Path + if (elementName == "gameFoldersGroupBox" || elementName == "gameFoldersListWidget") { + text = tr("gameFoldersBox"); + } else if (elementName == "addFolderButton") { + text = tr("addFolderButton"); + } else if (elementName == "removeFolderButton") { + text = tr("removeFolderButton"); + } + + // Debug + if (elementName == "debugDump") { + text = tr("debugDump"); + } else if (elementName == "vkValidationCheckBox") { + text = tr("vkValidationCheckBox"); + } else if (elementName == "vkSyncValidationCheckBox") { + text = tr("vkSyncValidationCheckBox"); + } else if (elementName == "rdocCheckBox") { + text = tr("rdocCheckBox"); + } + + ui->descriptionText->setText(text.replace("\\n", "\n")); +} + +bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) { + if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) { + if (qobject_cast(obj)) { + bool hovered = (event->type() == QEvent::Enter); + QString elementName = obj->objectName(); + + if (hovered) { + updateNoteTextEdit(elementName); + } else { + ui->descriptionText->setText(defaultTextEdit); + } + + // if the text exceeds the size of the box, it will increase the size + QRect currentGeometry = this->geometry(); + int newWidth = currentGeometry.width(); + + int documentHeight = ui->descriptionText->document()->size().height(); + int visibleHeight = ui->descriptionText->viewport()->height(); + if (documentHeight > visibleHeight) { + ui->descriptionText->setMaximumSize(16777215, 110); + this->setGeometry(currentGeometry.x(), currentGeometry.y(), newWidth, + currentGeometry.height() + 40); + } else { + ui->descriptionText->setMaximumSize(16777215, 70); + this->setGeometry(currentGeometry.x(), currentGeometry.y(), newWidth, + initialHeight); + } + return true; + } + } + return QDialog::eventFilter(obj, event); +} \ No newline at end of file diff --git a/src/qt_gui/settings_dialog.h b/src/qt_gui/settings_dialog.h index 7d8701093..8cdded980 100644 --- a/src/qt_gui/settings_dialog.h +++ b/src/qt_gui/settings_dialog.h @@ -5,6 +5,7 @@ #include #include +#include #include #include "common/config.h" @@ -20,10 +21,25 @@ public: explicit SettingsDialog(std::span physical_devices, QWidget* parent = nullptr); ~SettingsDialog(); + bool eventFilter(QObject* obj, QEvent* event) override; + void updateNoteTextEdit(const QString& groupName); + int exec() override; +signals: + void LanguageChanged(const std::string& locale); + private: void LoadValuesFromConfig(); + void InitializeEmulatorLanguages(); + void OnLanguageChanged(int index); + void OnCursorStateChanged(s16 index); std::unique_ptr ui; + + std::map languages; + + QString defaultTextEdit; + + int initialHeight; }; diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index d11f177d1..cce728f65 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -12,7 +12,7 @@ 0 0 854 - 480 + 660 @@ -34,9 +34,18 @@ :/images/shadps4.ico:/images/shadps4.ico + + false + + + false + + + true + QFrame::Shape::NoFrame @@ -51,8 +60,8 @@ 0 0 - 836 - 428 + 832 + 431 @@ -70,7 +79,7 @@ - + @@ -79,32 +88,6 @@ System - - - - 6 - - - 0 - - - - - - - Username - - - - - - - - - - - - @@ -117,6 +100,18 @@ + + + + Emulator Language + + + + + + + +
@@ -139,6 +134,13 @@
+ + + + Enable Separate Update Folder + + + @@ -153,20 +155,40 @@ + + + + Enable Discord Rich Presence + + + - - - Qt::Orientation::Horizontal + + + 6 - - - 40 - 20 - + + 0 - + + + + + + Username + + + + + + + + + + + @@ -256,17 +278,600 @@ - - - Qt::Orientation::Vertical + + + + + QLayout::SizeConstraint::SetDefaultConstraint + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 275 + 0 + + + + + 16777215 + 16777215 + + + + Update + + + + 5 + + + 1 + + + 11 + + + 11 + + + + + + 0 + 0 + + + + + 0 + 75 + + + + + 16777215 + 16777215 + + + + Update Channel + + + + 7 + + + 11 + + + 11 + + + 11 + + + 11 + + + + + + 0 + 0 + + + + + Release + + + + + Nightly + + + + + + + + + + + + 0 + 0 + + + + + 197 + 28 + + + + + 16777215 + 16777215 + + + + Check for Updates + + + + + + + + 0 + 0 + + + + + 11 + false + + + + Check for Updates at Startup + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + GUI Settings + + + + 1 + + + 11 + + + + + 1 + + + 0 + + + + + + 0 + 0 + + + + Play title music + + + + + + + Qt::Orientation::Vertical + + + QSizePolicy::Policy::Fixed + + + + 20 + 2 + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Volume + + + + + + + Set the volume of the background music. + + + 100 + + + 10 + + + 20 + + + 50 + + + Qt::Orientation::Horizontal + + + false + + + false + + + QSlider::TickPosition::NoTicks + + + 10 + + + + + + + + + + 0 + 61 + + + + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Input + + + + + + + + 7 + + + 0 + + + + + Cursor + + + + 0 + + + 11 + + + 11 + + + + + true + + + + 0 + 0 + + + + Hide Cursor + + + + 7 + + + 11 + + + + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Hide Cursor Idle Timeout + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + false + + + + 6 + + + 70 + + + 5 + + + 5 + + + 5 + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 16777215 + 16777215 + + + + Qt::LayoutDirection::LeftToRight + + + false + + + Qt::AlignmentFlag::AlignCenter + + + QAbstractSpinBox::ButtonSymbols::UpDownArrows + + + + + + 3600 + + + 5 + + + 10 + + + + + + + s + + + + + + + + + + + + + + + + + + 0 + 0 + + + + Controller + + + + 0 + + + 11 + + + 11 + + + + + true + + + + 0 + 0 + + + + + 237 + 0 + + + + Back Button Behavior + + + + 11 + + + + + + + + + + + true + + + + 0 + 0 + + + + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 - - - 20 - 40 - - - + + + + Qt::Orientation::Vertical + + + QSizePolicy::Policy::MinimumExpanding + + + + 20 + 20 + + + + + @@ -473,13 +1078,6 @@ - - - - Enable PM4 Dumping - - - @@ -515,6 +1113,76 @@ + + + Paths + + + + + + + + Game Folders + + + + + 0 + 20 + 401 + 331 + + + + + + + 100 + 360 + 91 + 24 + + + + Add... + + + + + + 199 + 360 + 91 + 24 + + + + Remove + + + + + + + + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Preferred + + + + 40 + 20 + + + + + + + + Debug @@ -611,6 +1279,19 @@ + + + + + 16777215 + 70 + + + + true + + + diff --git a/src/qt_gui/translations/ar.ts b/src/qt_gui/translations/ar.ts new file mode 100644 index 000000000..f8f7f5336 --- /dev/null +++ b/src/qt_gui/translations/ar.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + حول shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 هو محاكي تجريبي مفتوح المصدر لجهاز PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + يجب عدم استخدام هذا البرنامج لتشغيل الألعاب التي لم تحصل عليها بشكل قانوني. + + + + ElfViewer + + + Open Folder + فتح المجلد + + + + GameInfoClass + + + Loading game list, please wait :3 + جارٍ تحميل قائمة الألعاب، يرجى الانتظار :3 + + + + Cancel + إلغاء + + + + Loading... + ...جارٍ التحميل + + + + 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. + قيمة موقع تثبيت الألعاب غير صالحة. + + + + GuiContextMenus + + + Create Shortcut + إنشاء اختصار + + + + Open Game Folder + فتح مجلد اللعبة + + + + Cheats / Patches + الغش / التصحيحات + + + + SFO Viewer + عارض SFO + + + + Trophy Viewer + عارض الجوائز + + + + Copy info + نسخ المعلومات + + + + Copy Name + نسخ الاسم + + + + Copy Serial + نسخ الرقم التسلسلي + + + + Copy All + نسخ الكل + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + إنشاء اختصار + + + + Shortcut created successfully!\n %1 + تم إنشاء الاختصار بنجاح!\n %1 + + + + Error + خطأ + + + + Error creating shortcut!\n %1 + !\n %1 خطأ في إنشاء الاختصار + + + + 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? + + + + 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 + شريط الأدوات + + + + PKGViewer + + + Open Folder + فتح المجلد + + + + TrophyViewer + + + Trophy Viewer + عارض الجوائز + + + + 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 + اسم المستخدم + + + + Logger + المسجل + + + + Log Type + نوع السجل + + + + Log Filter + مرشح السجل + + + + Input + إدخال + + + + Cursor + مؤشر + + + + Hide Cursor + إخفاء المؤشر + + + + Hide Cursor Idle Timeout + مهلة إخفاء المؤشر عند الخمول + + + + 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 + إعدادات الواجهة + + + + Play title music + تشغيل موسيقى العنوان + + + + Volume + الصوت + + + + MainWindow + + + 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 صالحًا + + + + CheatsPatches + + + Cheats / Patches + الغش / التصحيحات + + + + defaultTextEdit_MSG + الغش والتصحيحات هي ميزات تجريبية.\nاستخدمها بحذر.\n\nقم بتنزيل الغش بشكل فردي عن طريق اختيار المستودع والنقر على زر التنزيل.\nفي علامة تبويب التصحيحات، يمكنك تنزيل جميع التصحيحات دفعة واحدة، واختيار ما تريد استخدامه، وحفظ اختياراتك.\n\nنظرًا لأننا لا نقوم بتطوير الغش/التصحيحات،\nيرجى الإبلاغ عن أي مشاكل إلى مؤلف الغش.\n\nهل قمت بإنشاء غش جديد؟ قم بزيارة:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + لا تتوفر صورة + + + + Serial: + الرقم التسلسلي: + + + + Version: + الإصدار: + + + + Size: + الحجم: + + + + Select Cheat File: + اختر ملف الغش: + + + + Repository: + المستودع: + + + + Download Cheats + تنزيل الغش + + + + Delete File + حذف الملف + + + + No files selected. + لم يتم اختيار أي ملفات. + + + + You can delete the cheats you don't want after downloading them. + يمكنك حذف الغش الذي لا تريده بعد تنزيله. + + + + Do you want to delete the selected file?\n%1 + هل تريد حذف الملف المحدد؟\n%1 + + + + Select Patch File: + اختر ملف التصحيح: + + + + Download Patches + تنزيل التصحيحات + + + + Save + حفظ + + + + Cheats + الغش + + + + Patches + التصحيحات + + + + Error + خطأ + + + + No patch selected. + لم يتم اختيار أي تصحيح. + + + + Unable to open files.json for reading. + تعذر فتح files.json للقراءة. + + + + No patch file found for the current serial. + لم يتم العثور على ملف تصحيح للرقم التسلسلي الحالي. + + + + Unable to open the file for reading. + تعذر فتح الملف للقراءة. + + + + Unable to open the file for writing. + تعذر فتح الملف للكتابة. + + + + Failed to parse XML: + :فشل في تحليل XML + + + + Success + نجاح + + + + Options saved successfully. + تم حفظ الخيارات بنجاح. + + + + Invalid Source + مصدر غير صالح + + + + The selected source is invalid. + المصدر المحدد غير صالح. + + + + File Exists + الملف موجود + + + + File already exists. Do you want to replace it? + الملف موجود بالفعل. هل تريد استبداله؟ + + + + Failed to save file: + :فشل في حفظ الملف + + + + Failed to download file: + :فشل في تنزيل الملف + + + + Cheats Not Found + لم يتم العثور على الغش + + + + CheatsNotFound_MSG + لم يتم العثور على غش لهذه اللعبة في هذا الإصدار من المستودع المحدد. حاول استخدام مستودع آخر أو إصدار آخر من اللعبة. + + + + Cheats Downloaded Successfully + تم تنزيل الغش بنجاح + + + + CheatsDownloadedSuccessfully_MSG + لقد نجحت في تنزيل الغش لهذا الإصدار من اللعبة من المستودع المحدد. يمكنك محاولة التنزيل من مستودع آخر. إذا كان متاحًا، يمكنك اختياره عن طريق تحديد الملف من القائمة. + + + + Failed to save: + :فشل في الحفظ + + + + Failed to download: + :فشل في التنزيل + + + + Download Complete + اكتمل التنزيل + + + + DownloadComplete_MSG + تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات لجميع الألعاب، ولا داعي لتنزيلها بشكل فردي لكل لعبة كما هو الحال مع الغش. إذا لم يظهر التحديث، قد يكون السبب أنه غير متوفر للإصدار وسيريال اللعبة المحدد. قد تحتاج إلى تحديث اللعبة. + + + + Failed to parse JSON data from HTML. + فشل في تحليل بيانات JSON من HTML. + + + + Failed to retrieve HTML page. + .HTML فشل في استرجاع صفحة + + + + Failed to open file: + :فشل في فتح الملف + + + + XML ERROR: + :خطأ في XML + + + + Failed to open files.json for writing + فشل في فتح files.json للكتابة + + + + Author: + :المؤلف + + + + Directory does not exist: + :المجلد غير موجود + + + + Failed to open files.json for reading. + فشل في فتح files.json للقراءة. + + + + Name: + :الاسم + + + + 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، الذي قد يتم عرضه في بعض الألعاب. + + + + 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إذا كانت اللعبة تدعم ذلك، قم بتمكين تشغيل موسيقى خاصة عند اختيار اللعبة في واجهة المستخدم. + + + + hideCursorGroupBox + إخفاء المؤشر:\nاختر متى سيختفي المؤشر:\nأبداً: سترى الفأرة دائماً.\nعاطل: حدد وقتاً لاختفائه بعد أن يكون غير مستخدم.\nدائماً: لن ترى الفأرة أبداً. + + + + idleTimeoutGroupBox + حدد وقتاً لاختفاء الفأرة بعد أن تكون غير مستخدم. + + + + backButtonBehaviorGroupBox + سلوك زر العودة:\nيضبط زر العودة في وحدة التحكم ليحاكي الضغط على الموضع المحدد على لوحة اللمس في PS4. + + + + 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 لالتقاط وتحليل الإطار الذي يتم عرضه حاليًا. + + + + GameListFrame + + + Icon + أيقونة + + + + Name + اسم + + + + Serial + سيريال + + + + Region + منطقة + + + + Firmware + البرمجيات الثابتة + + + + Size + حجم + + + + Version + إصدار + + + + Path + مسار + + + + Play Time + وقت اللعب + + + + 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 + فشل في إنشاء ملف سكريبت التحديث + + + \ No newline at end of file diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts new file mode 100644 index 000000000..4bdc75828 --- /dev/null +++ b/src/qt_gui/translations/da_DK.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Trick / Patches + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Indtastning + + + + Cursor + Markør + + + + Hide Cursor + Skjul markør + + + + Hide Cursor Idle Timeout + Timeout for skjul markør ved inaktivitet + + + + 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 + + + + Play title music + Afspil titelsang + + + + Volume + Lydstyrke + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Snyd / Patches + + + + defaultTextEdit_MSG + Cheats/Patches er eksperimentelle.\nBrug med forsigtighed.\n\nDownload cheats individuelt ved at vælge lageret og klikke på download-knappen.\nUnder fanen Patches kan du downloade alle patches på én gang, vælge hvilke du vil bruge og gemme valget.\n\nDa vi ikke udvikler cheats/patches,\nvenligst rapporter problemer til cheat-udvikleren.\n\nHar du lavet en ny cheat? Besøg:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Ingen billede tilgængelig + + + + Serial: + Serienummer: + + + + Version: + Version: + + + + Size: + Størrelse: + + + + Select Cheat File: + Vælg snyd-fil: + + + + Repository: + Repository: + + + + Download Cheats + Hent snyd + + + + Delete File + Slet fil + + + + No files selected. + Ingen filer valgt. + + + + You can delete the cheats you don't want after downloading them. + Du kan slette de snyd, du ikke ønsker, efter at have hentet dem. + + + + Do you want to delete the selected file?\n%1 + Ønsker du at slette den valgte fil?\n%1 + + + + Select Patch File: + Vælg patch-fil: + + + + Download Patches + Hent patches + + + + Save + Gem + + + + Cheats + Snyd + + + + Patches + Patches + + + + Error + Fejl + + + + No patch selected. + Ingen patch valgt. + + + + Unable to open files.json for reading. + Kan ikke åbne files.json til læsning. + + + + No patch file found for the current serial. + Ingen patch-fil fundet for det nuværende serienummer. + + + + Unable to open the file for reading. + Kan ikke åbne filen til læsning. + + + + Unable to open the file for writing. + Kan ikke åbne filen til skrivning. + + + + Failed to parse XML: + Kunne ikke analysere XML: + + + + Success + Succes + + + + Options saved successfully. + Indstillinger gemt med succes. + + + + Invalid Source + Ugyldig kilde + + + + The selected source is invalid. + Den valgte kilde er ugyldig. + + + + File Exists + Fil findes + + + + File already exists. Do you want to replace it? + Filen findes allerede. Vil du erstatte den? + + + + Failed to save file: + Kunne ikke gemme fil: + + + + Failed to download file: + Kunne ikke hente fil: + + + + Cheats Not Found + Snyd ikke fundet + + + + CheatsNotFound_MSG + Ingen snyd fundet til dette spil i denne version af det valgte repository, prøv et andet repository eller en anden version af spillet. + + + + Cheats Downloaded Successfully + Snyd hentet med succes + + + + CheatsDownloadedSuccessfully_MSG + Du har succesfuldt hentet snyd for denne version af spillet fra det valgte repository. Du kan prøve at hente fra et andet repository, hvis det er tilgængeligt, vil det også være muligt at bruge det ved at vælge filen fra listen. + + + + Failed to save: + Kunne ikke gemme: + + + + Failed to download: + Kunne ikke hente: + + + + Download Complete + Download fuldført + + + + DownloadComplete_MSG + Patcher hentet med succes! Alle patches til alle spil er blevet hentet, der er ikke behov for at hente dem individuelt for hvert spil, som det sker med snyd. Hvis opdateringen ikke vises, kan det være, at den ikke findes for den specifikke serie og version af spillet. Det kan være nødvendigt at opdatere 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Ikon + + + + Name + Navn + + + + Serial + Seriel + + + + Region + Region + + + + Firmware + Firmware + + + + Size + Størrelse + + + + Version + Version + + + + Path + Sti + + + + Play Time + Spilletid + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts new file mode 100644 index 000000000..2a436ec2c --- /dev/null +++ b/src/qt_gui/translations/de.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Ordner öffnen + + + + GameInfoClass + + + Loading game list, please wait :3 + Lade Spielliste, bitte warten :3 + + + + Cancel + Abbrechen + + + + Loading... + Lade... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Wähle Ordner + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Verknüpfung erstellen + + + + Open Game Folder + Spieleordner öffnen + + + + Cheats / Patches + Cheats / Patches + + + + SFO Viewer + SFO anzeigen + + + + Trophy Viewer + Trophäen anzeigen + + + + 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 + + + + Shortcut creation + Verknüpfungserstellung + + + + Shortcut created successfully!\n %1 + Verknüpfung erfolgreich erstellt!\n %1 + + + + Error + Fehler + + + + Error creating shortcut!\n %1 + Fehler beim Erstellen der Verknüpfung!\n %1 + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Ordner öffnen + + + + TrophyViewer + + + Trophy Viewer + Trophäenansicht + + + + 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 + + + + Logger + Logger + + + + Log Type + Logtyp + + + + Log Filter + Log-Filter + + + + Input + Eingabe + + + + Cursor + Cursor + + + + Hide Cursor + Cursor ausblenden + + + + Hide Cursor Idle Timeout + Inaktivitätszeitüberschreitung zum Ausblenden des Cursors + + + + 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 + + + + Play title music + Titelmusik abspielen + + + + Volume + Lautstärke + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + 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. Möglicherweise müssen Sie das Spiel aktualisieren. + + + + Failed to parse JSON data from HTML. + Fehler beim Parsen der JSON-Daten aus HTML. + + + + Failed to retrieve HTML page. + Fehler beim Abrufen der HTML-Seite. + + + + Failed to open file: + Fehler beim Öffnen der Datei: + + + + XML ERROR: + XML-Fehler: + + + + Failed to open files.json for writing + Kann files.json nicht zum Schreiben öffnen + + + + Author: + Autor: + + + + Directory does not exist: + Verzeichnis existiert nicht: + + + + Failed to open files.json for reading. + Kann files.json nicht zum Lesen öffnen. + + + + Name: + Name: + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Symbol + + + + Name + Name + + + + Serial + Seriennummer + + + + Region + Region + + + + Firmware + Firmware + + + + Size + Größe + + + + Version + Version + + + + Path + Pfad + + + + Play Time + Spielzeit + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts new file mode 100644 index 000000000..b7d51bfb3 --- /dev/null +++ b/src/qt_gui/translations/el.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Kodikí / Enimeróseis + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Είσοδος + + + + Cursor + Δείκτης + + + + Hide Cursor + Απόκρυψη δείκτη + + + + Hide Cursor Idle Timeout + Χρόνος αδράνειας απόκρυψης δείκτη + + + + 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 + + + + Play title music + Αναπαραγωγή μουσικής τίτλου + + + + Volume + ένταση + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Οι cheats/patches είναι πειραματικά.\nΧρησιμοποιήστε τα με προσοχή.\n\nΚατεβάστε τους cheats μεμονωμένα επιλέγοντας το αποθετήριο και κάνοντας κλικ στο κουμπί λήψης.\nΣτην καρτέλα Patches, μπορείτε να κατεβάσετε όλα τα patches ταυτόχρονα, να επιλέξετε ποια θέλετε να χρησιμοποιήσετε και να αποθηκεύσετε την επιλογή.\n\nΔεδομένου ότι δεν αναπτύσσουμε τους cheats/patches,\nπαρακαλώ αναφέρετε προβλήματα στον δημιουργό του cheat.\n\nΔημιουργήσατε ένα νέο cheat; Επισκεφθείτε:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Δεν διατίθεται εικόνα + + + + Serial: + Σειριακός αριθμός: + + + + Version: + Έκδοση: + + + + Size: + Μέγεθος: + + + + Select Cheat File: + Επιλέξτε αρχείο Cheat: + + + + Repository: + Αποθετήριο: + + + + Download Cheats + Λήψη Cheats + + + + Delete File + Διαγραφή αρχείου + + + + No files selected. + Δεν έχουν επιλεγεί αρχεία. + + + + You can delete the cheats you don't want after downloading them. + Μπορείτε να διαγράψετε τα cheats που δεν θέλετε μετά τη λήψη τους. + + + + Do you want to delete the selected file?\n%1 + Θέλετε να διαγράψετε το επιλεγμένο αρχείο;\n%1 + + + + Select Patch File: + Επιλέξτε αρχείο Patch: + + + + Download Patches + Λήψη Patches + + + + Save + Αποθήκευση + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Σφάλμα + + + + No patch selected. + Δεν έχει επιλεγεί κανένα patch. + + + + Unable to open files.json for reading. + Αδυναμία ανοίγματος του files.json για ανάγνωση. + + + + No patch file found for the current serial. + Δεν βρέθηκε αρχείο patch για τον τρέχοντα σειριακό αριθμό. + + + + Unable to open the file for reading. + Αδυναμία ανοίγματος του αρχείου για ανάγνωση. + + + + Unable to open the file for writing. + Αδυναμία ανοίγματος του αρχείου για εγγραφή. + + + + Failed to parse XML: + Αποτυχία ανάλυσης XML: + + + + Success + Επιτυχία + + + + Options saved successfully. + Οι ρυθμίσεις αποθηκεύτηκαν επιτυχώς. + + + + Invalid Source + Μη έγκυρη Πηγή + + + + The selected source is invalid. + Η επιλεγμένη πηγή είναι μη έγκυρη. + + + + File Exists + Η αρχείο υπάρχει + + + + File already exists. Do you want to replace it? + Η αρχείο υπάρχει ήδη. Θέλετε να την αντικαταστήσετε; + + + + Failed to save file: + Αποτυχία αποθήκευσης αρχείου: + + + + Failed to download file: + Αποτυχία λήψης αρχείου: + + + + Cheats Not Found + Δεν βρέθηκαν Cheats + + + + CheatsNotFound_MSG + Δεν βρέθηκαν cheats για αυτό το παιχνίδι στην τρέχουσα έκδοση του επιλεγμένου αποθετηρίου. Δοκιμάστε να κατεβάσετε από άλλο αποθετήριο ή άλλη έκδοση του παιχνιδιού. + + + + Cheats Downloaded Successfully + Cheats κατεβάστηκαν επιτυχώς + + + + CheatsDownloadedSuccessfully_MSG + Κατεβάσατε επιτυχώς cheats για αυτή την έκδοση του παιχνιδιού από το επιλεγμένο αποθετήριο. Μπορείτε να δοκιμάσετε να κατεβάσετε από άλλο αποθετήριο. Αν είναι διαθέσιμο, μπορείτε να το επιλέξετε επιλέγοντας το αρχείο από τη λίστα. + + + + Failed to save: + Αποτυχία αποθήκευσης: + + + + Failed to download: + Αποτυχία λήψης: + + + + Download Complete + Η λήψη ολοκληρώθηκε + + + + DownloadComplete_MSG + Τα Patches κατεβάστηκαν επιτυχώς! Όλα τα Patches για όλα τα παιχνίδια έχουν κατέβει, δεν είναι απαραίτητο να τα κατεβάσετε ένα-ένα για κάθε παιχνίδι, όπως με τα Cheats. Εάν η ενημέρωση δεν εμφανίζεται, μπορεί να μην υπάρχει για τον συγκεκριμένο σειριακό αριθμό και έκδοση του παιχνιδιού. Μπορεί να χρειαστεί να ενημερώσετε το παιχνίδι. + + + + Failed to parse JSON data from HTML. + Αποτυχία ανάλυσης δεδομένων JSON από HTML. + + + + Failed to retrieve HTML page. + Αποτυχία ανάκτησης σελίδας HTML. + + + + Failed to open file: + Αποτυχία ανοίγματος αρχείου: + + + + XML ERROR: + ΣΦΑΛΜΑ XML: + + + + Failed to open files.json for writing + Αποτυχία ανοίγματος του files.json για εγγραφή + + + + Author: + Συγγραφέας: + + + + Directory does not exist: + Ο φάκελος δεν υπάρχει: + + + + Failed to open files.json for reading. + Αποτυχία ανοίγματος του files.json για ανάγνωση. + + + + Name: + Όνομα: + + + + 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, το οποίο μπορεί να εμφανιστεί σε ορισμένα παιχνίδια. + + + + 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Εάν το παιχνίδι το υποστηρίζει, ενεργοποιεί ειδική μουσική κατά την επιλογή του παιχνιδιού από τη διεπαφή χρήστη. + + + + hideCursorGroupBox + Απόκρυψη Κέρσορα:\nΕπιλέξτε πότε θα εξαφανιστεί ο κέρσορας:\nΠοτέ: θα βλέπετε πάντα το ποντίκι.\nΑδρανές: ορίστε έναν χρόνο για να εξαφανιστεί μετά από αδράνεια.\nΠάντα: δεν θα δείτε ποτέ το ποντίκι. + + + + idleTimeoutGroupBox + Ορίστε έναν χρόνο για να εξαφανιστεί το ποντίκι μετά από αδράνεια. + + + + backButtonBehaviorGroupBox + Συμπεριφορά Κουμπιού Επιστροφής:\nΟρίζει το κουμπί επιστροφής του ελεγκτή να προσομοιώνει το πάτημα της καθορισμένης θέσης στην οθόνη αφής PS4. + + + + 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 για τη λήψη και ανάλυση του τρέχοντος καρέ. + + + + GameListFrame + + + Icon + Εικονίδιο + + + + Name + Όνομα + + + + Serial + Σειριακός αριθμός + + + + Region + Περιοχή + + + + Firmware + Λογισμικό + + + + Size + Μέγεθος + + + + Version + Έκδοση + + + + Path + Διαδρομή + + + + Play Time + Χρόνος παιχνιδιού + + + + 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 + Αποτυχία δημιουργίας του αρχείου σεναρίου ενημέρωσης + + + \ No newline at end of file diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts new file mode 100644 index 000000000..5b58d865f --- /dev/null +++ b/src/qt_gui/translations/en.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Cheats / Patches + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Input + + + + Cursor + Cursor + + + + Hide Cursor + Hide Cursor + + + + Hide Cursor Idle Timeout + Hide Cursor Idle Timeout + + + + 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 + + + + Play title music + Play title music + + + + Volume + Volume + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + No Image Available + + + + Serial: + Serial: + + + + Version: + Version: + + + + Size: + Size: + + + + Select Cheat File: + Select Cheat File: + + + + Repository: + Repository: + + + + Download Cheats + Download Cheats + + + + Delete File + Delete File + + + + No files selected. + No files selected. + + + + You can delete the cheats you don't want after downloading them. + You can delete the cheats you don't want after downloading them. + + + + Do you want to delete the selected file?\n%1 + Do you want to delete the selected file?\n%1 + + + + Select Patch File: + Select Patch File: + + + + Download Patches + Download Patches + + + + Save + Save + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Error + + + + No patch selected. + No patch selected. + + + + Unable to open files.json for reading. + Unable to open files.json for reading. + + + + No patch file found for the current serial. + No patch file found for the current serial. + + + + Unable to open the file for reading. + Unable to open the file for reading. + + + + Unable to open the file for writing. + Unable to open the file for writing. + + + + Failed to parse XML: + Failed to parse XML: + + + + Success + Success + + + + Options saved successfully. + Options saved successfully. + + + + Invalid Source + Invalid Source + + + + The selected source is invalid. + The selected source is invalid. + + + + File Exists + File Exists + + + + File already exists. Do you want to replace it? + File already exists. Do you want to replace it? + + + + Failed to save file: + Failed to save file: + + + + Failed to download file: + Failed to download file: + + + + Cheats Not Found + Cheats Not Found + + + + CheatsNotFound_MSG + No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. + + + + Cheats Downloaded Successfully + Cheats Downloaded Successfully + + + + CheatsDownloadedSuccessfully_MSG + You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. + + + + Failed to save: + Failed to save: + + + + Failed to download: + Failed to download: + + + + Download Complete + Download Complete + + + + DownloadComplete_MSG + Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. It may be necessary to update 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. + + + + 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 + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icon + + + + Name + Name + + + + Serial + Serial + + + + Region + Region + + + + Firmware + Firmware + + + + Size + Size + + + + Version + Version + + + + Path + Path + + + + Play Time + Play Time + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts new file mode 100644 index 000000000..032579f91 --- /dev/null +++ b/src/qt_gui/translations/es_ES.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Abrir carpeta + + + + GameInfoClass + + + Loading game list, please wait :3 + Cargando lista de juegos, por favor espera :3 + + + + Cancel + Cancelar + + + + Loading... + Cargando... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Elegir carpeta + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Crear acceso directo + + + + Open Game Folder + Abrir carpeta del juego + + + + Cheats / Patches + Trucos / Parches + + + + SFO Viewer + Vista SFO + + + + Trophy Viewer + Ver trofeos + + + + Copy info + Copiar información + + + + Copy Name + Copiar nombre + + + + Copy Serial + Copiar número de serie + + + + Copy All + Copiar todo + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Acceso directo creado + + + + Shortcut created successfully!\n %1 + ¡Acceso directo creado con éxito!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + ¡Error al crear el acceso directo!\n %1 + + + + Install PKG + Instalar PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Abrir carpeta + + + + TrophyViewer + + + Trophy Viewer + Vista de trofeos + + + + 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 + + + + Logger + Registro + + + + Log Type + Tipo de registro + + + + Log Filter + Filtro de registro + + + + Input + Entrada + + + + Cursor + Cursor + + + + Hide Cursor + Ocultar cursor + + + + Hide Cursor Idle Timeout + Tiempo de espera para ocultar cursor inactivo + + + + 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 + + + + Play title music + Reproducir la música de apertura + + + + Volume + Volumen + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Trucos / Parches + + + + defaultTextEdit_MSG + Los cheats/patches son experimentales.\nÚselos con precaución.\n\nDescargue los cheats individualmente seleccionando el repositorio y haciendo clic en el botón de descarga.\nEn la pestaña Patches, puede descargar todos los patches a la vez, elegir cuáles desea usar y guardar la selección.\n\nComo no desarrollamos los Cheats/Patches,\npor favor informe los problemas al autor del cheat.\n\n¿Creaste un nuevo cheat? Visita:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + No hay imagen disponible + + + + Serial: + 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. Puede ser necesario actualizar el 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icono + + + + Name + Nombre + + + + Serial + Numero de serie + + + + Region + Región + + + + Firmware + Firmware + + + + Size + Tamaño + + + + Version + Versión + + + + Path + Ruta + + + + Play Time + Tiempo de Juego + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts new file mode 100644 index 000000000..8976d185c --- /dev/null +++ b/src/qt_gui/translations/fa_IR.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + درباره ShadPS4 + + + + shadPS4 + ShadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + یک شبیه ساز متن باز برای پلی استیشن 4 است. + + + + This software should not be used to play games you have not legally obtained. + این برنامه نباید برای بازی هایی که شما به صورت غیرقانونی به دست آوردید استفاده شود. + + + + ElfViewer + + + Open Folder + فولدر را بازکن + + + + GameInfoClass + + + Loading game list, please wait :3 + درحال بارگیری لیست بازی ها,لطفا کمی صبرکنید :3 + + + + Cancel + لغو + + + + Loading... + ...درحال بارگیری + + + + 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. + .مکان داده شده برای نصب بازی درست نمی باشد + + + + GuiContextMenus + + + Create Shortcut + ساخت شورتکات + + + + Open Game Folder + بازکردن محل نصب بازی + + + + Cheats / Patches + چیت/پچ ها + + + + SFO Viewer + SFO مشاهده + + + + Trophy Viewer + مشاهده تروفی ها + + + + Copy info + کپی کردن اطلاعات + + + + Copy Name + کپی کردن نام + + + + Copy Serial + کپی کردن سریال + + + + Copy All + کپی کردن تمامی مقادیر + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + سازنده شورتکات + + + + Shortcut created successfully!\n %1 + شورتکات با موفقیت ساخته شد! \n %1 + + + + Error + ارور + + + + Error creating shortcut!\n %1 + مشکلی در هنگام ساخت شورتکات بوجود آمد!\n %1 + + + + 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? + + + + 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 + + + + 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 + نوار ابزار + + + + PKGViewer + + + Open Folder + بازکردن پوشه + + + + 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 + نام کاربری + + + + Logger + Logger + + + + Log Type + Log نوع + + + + Log Filter + Log فیلتر + + + + Input + ورودی + + + + Cursor + نشانگر + + + + Hide Cursor + پنهان کردن نشانگر + + + + Hide Cursor Idle Timeout + مخفی کردن زمان توقف مکان نما + + + + Controller + کنترل کننده + + + + Back Button Behavior + رفتار دکمه بازگشت + + + + Graphics + گرافیک + + + + Graphics Device + کارت گرافیک مورداستفاده + + + + Width + عرض + + + + Height + طول + + + + Vblank Divider + Vblank Divider + + + + 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 + تنظیمات رابط کاربری + + + + Play title music + پخش موسیقی عنوان + + + + Volume + صدا + + + + MainWindow + + + 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 درست به نظر نمی آید + + + + CheatsPatches + + + Cheats / Patches + چیت / پچ ها + + + + defaultTextEdit_MSG + defaultTextEdit_MSG + + + + No Image Available + تصویری موجود نمی باشد + + + + Serial: + سریال: + + + + Version: + ورژن: + + + + Size: + حجم: + + + + Select Cheat File: + فایل چیت را انتخاب کنید: + + + + Repository: + :منبع + + + + Download Cheats + دانلود چیت ها + + + + Delete File + پاک کردن فایل + + + + No files selected. + فایلی انتخاب نشده. + + + + You can delete the cheats you don't want after downloading them. + شما میتوانید بعد از دانلود چیت هایی که نمیخواهید را پاک کنید + + + + Do you want to delete the selected file?\n%1 + آیا میخواهید فایل های انتخاب شده را پاک کنید؟ \n%1 + + + + Select Patch File: + فایل پچ را انتخاب کنید + + + + Download Patches + دانلود کردن پچ ها + + + + Save + ذخیره + + + + Cheats + چیت ها + + + + Patches + پچ ها + + + + Error + ارور + + + + No patch selected. + هیچ پچ انتخاب نشده + + + + Unable to open files.json for reading. + .json مشکل در خواندن فایل + + + + No patch file found for the current serial. + هیچ فایل پچ برای سریال بازی شما پیدا نشد. + + + + Unable to open the file for reading. + خطا در خواندن فایل + + + + Unable to open the file for writing. + خطا در نوشتن فایل + + + + Failed to parse XML: + انجام نشد XML تجزیه فایل: + + + + Success + عملیات موفق بود + + + + Options saved successfully. + تغییرات با موفقیت ذخیره شد✅ + + + + Invalid Source + منبع نامعتبر❌ + + + + The selected source is invalid. + منبع انتخاب شده نامعتبر است + + + + File Exists + فایل وجود دارد + + + + File already exists. Do you want to replace it? + فایل از قبل وجود دارد. آیا می خواهید آن را جایگزین کنید؟ + + + + Failed to save file: + ذخیره فایل موفقیت آمیز نبود: + + + + Failed to download file: + خطا در دانلود فایل: + + + + Cheats Not Found + چیت یافت نشد + + + + CheatsNotFound_MSG + متاسفانه هیچ چیتی از منبع انتخاب شده پیدا نشد! شما میتوانید منابع دیگری را برای دانلود انتخاب و یا چیت های خود را به صورت دستی واردکنید. + + + + Cheats Downloaded Successfully + دانلود چیت ها موفقیت آمیز بود✅ + + + + CheatsDownloadedSuccessfully_MSG + تمامی چیت های موجود برای این بازی از منبع انتخاب شده دانلود شد! شما همچنان میتوانید چیت های دیگری را ازمنابع مختلف دانلود کنید و درصورت موجود بودن از آنها استفاده کنید. + + + + Failed to save: + خطا در ذخیره اطلاعات: + + + + Failed to download: + خطا در دانلود❌ + + + + Download Complete + پچ ها با موفقیت بارگیری شدند! تمام وصله های موجود برای همه بازی ها دانلود شده اند، نیازی به دانلود جداگانه آنها برای هر بازی نیست، همانطور که در Cheats اتفاق می افتد. اگر پچ ظاهر نشد، ممکن است برای سریال و نسخه خاصی از بازی وجود نداشته باشد. ممکن است نیاز به آپدیت بازی باشد.✅ + + + + DownloadComplete_MSG + دانلود با موفقیت به اتمام رسید✅ + + + + Failed to parse JSON data from HTML. + HTML از JSON خطا در تجزیه اطلاعات. + + + + Failed to retrieve HTML page. + HTML خطا دربازیابی صفحه + + + + Failed to open file: + خطا در اجرای فایل: + + + + XML ERROR: + XML ERROR: + + + + Failed to open files.json for writing + .json خطا در نوشتن فایل + + + + Author: + تولید کننده: + + + + Directory does not exist: + پوشه وجود ندارد: + + + + Failed to open files.json for reading. + .json خطا در خواندن فایل + + + + Name: + نام: + + + + 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. + + + + 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:\nآیکون شبیه ساز و اطلاعات مربوطه را در نمایه Discord شما نمایش می دهد. + + + + userName + Username:\nSets the PS4's account username, which may be displayed by some games. + + + + 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. + + + + hideCursorGroupBox + پنهان کردن نشانگر:\nانتخاب کنید که نشانگر چه زمانی ناپدید شود:\nهرگز: شما همیشه ماوس را خواهید دید.\nغیرفعال: زمانی را برای ناپدید شدن بعد از غیرفعالی تعیین کنید.\nهمیشه: شما هرگز ماوس را نخواهید دید. + + + + idleTimeoutGroupBox + زمانی را برای ناپدید شدن ماوس بعد از غیرفعالی تعیین کنید. + + + + backButtonBehaviorGroupBox + رفتار دکمه برگشت:\nدکمه برگشت کنترلر را طوری تنظیم می کند که ضربه زدن روی موقعیت مشخص شده روی صفحه لمسی PS4 را شبیه سازی کند. + + + + 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. + + + + 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 + پوشه های بازی:\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. + + + + 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. + + + + GameListFrame + + + Icon + آیکون + + + + Name + نام + + + + Serial + سریال + + + + Region + منطقه + + + + Firmware + فریمور + + + + Size + اندازه + + + + Version + نسخه + + + + Path + مسیر + + + + Play Time + زمان بازی + + + + 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 + فایل اسکریپت به روز رسانی ایجاد نشد + + + \ No newline at end of file diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts new file mode 100644 index 000000000..c2cb6c5e8 --- /dev/null +++ b/src/qt_gui/translations/fi.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Huijaukset / Korjaukset + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + Check for Updates + Tarkista päivitykset + + + + 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 + Lataa Huijaukset / Korjaukset + + + + 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 + Apua + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Play title music + Soita otsikkomusiikkia + + + + Volume + Äänenvoimakkuus + + + + MainWindow + + + Game List + Pelilista + + + + * Unsupported Vulkan Version + * Tuettu Vulkan-versio + + + + Download Cheats For All Installed Games + Lataa huijaukset kaikille asennetuille peleille + + + + Download Patches For All Games + Lataa korjaukset kaikille peleille + + + + Download Complete + Lataus valmis + + + + You have downloaded cheats for all the games you have installed. + Olet ladannut huijaukset kaikkiin asennettuihin peleihin. + + + + Patches Downloaded Successfully! + Korjaukset ladattu onnistuneesti! + + + + All Patches available for all games have been downloaded. + Kaikki saatavilla olevat korjaukset kaikille peleille on ladattu. + + + + Games: + Pelit: + + + + PKG File (*.PKG) + PKG-tiedosto (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF-tiedostot (*.bin *.elf *.oelf) + + + + Game Boot + Pelin käynnistys + + + + Only one file can be selected! + Vain yksi tiedosto voidaan valita! + + + + PKG Extraction + PKG:n purku + + + + Patch detected! + 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 + + + + Would you like to install DLC: %1? + Haluatko asentaa DLC:n: %1? + + + + DLC already installed: + DLC on jo asennettu: + + + + Game already installed + Peli on jo asennettu + + + + PKG is a patch, please install the game first! + PKG on korjaus, asenna peli ensin! + + + + PKG ERROR + PKG VIRHE + + + + Extracting PKG %1/%2 + Purkaminen PKG %1/%2 + + + + Extraction Finished + Purku valmis + + + + Game successfully installed at %1 + Peli asennettu onnistuneesti kohtaan %1 + + + + File doesn't appear to be a valid PKG file + Tiedosto ei vaikuta olevan kelvollinen PKG-tiedosto + + + + CheatsPatches + + + Cheats / Patches + Huijaukset / Korjaukset + + + + defaultTextEdit_MSG + Cheats/Patches ovat kokeellisia.\nKäytä varoen.\n\nLataa cheats yksitellen valitsemalla repositorio ja napsauttamalla latauspainiketta.\nPatches-välilehdellä voit ladata kaikki patchit kerralla, valita, mitä haluat käyttää, ja tallentaa valinnan.\n\nKoska emme kehitä Cheats/Patches,\nilmoita ongelmista cheatin tekijälle.\n\nLuo uusi cheat? Käy osoitteessa:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Kuvaa ei saatavilla + + + + Serial: + Sarjanumero: + + + + Version: + Versio: + + + + Size: + Koko: + + + + Select Cheat File: + Valitse huijaustiedosto: + + + + Repository: + Repo: + + + + Download Cheats + Lataa huijaukset + + + + Delete File + Poista tiedosto + + + + No files selected. + Ei tiedostoja valittu. + + + + You can delete the cheats you don't want after downloading them. + Voit poistaa ei-toivomasi huijaukset lataamisen jälkeen. + + + + Do you want to delete the selected file?\n%1 + Haluatko poistaa valitun tiedoston?\n%1 + + + + Select Patch File: + Valitse korjaustiedosto: + + + + Download Patches + Lataa korjaukset + + + + Save + Tallenna + + + + Cheats + Huijaukset + + + + Patches + Korjaukset + + + + Error + Virhe + + + + No patch selected. + Ei korjausta valittu. + + + + Unable to open files.json for reading. + Tiedostoa files.json ei voitu avata lukemista varten. + + + + No patch file found for the current serial. + Nykyiselle sarjanumerolle ei löytynyt korjaustiedostoa. + + + + Unable to open the file for reading. + Tiedostoa ei voitu avata lukemista varten. + + + + Unable to open the file for writing. + Tiedostoa ei voitu avata kirjoittamista varten. + + + + Failed to parse XML: + XML:n jäsentäminen epäonnistui: + + + + Success + Onnistui + + + + Options saved successfully. + Vaihtoehdot tallennettu onnistuneesti. + + + + Invalid Source + Virheellinen lähde + + + + The selected source is invalid. + Valittu lähde on virheellinen. + + + + File Exists + Tiedosto on olemassa + + + + File already exists. Do you want to replace it? + Tiedosto on jo olemassa. Haluatko korvata sen? + + + + Failed to save file: + Tiedoston tallentaminen epäonnistui: + + + + Failed to download file: + Tiedoston lataaminen epäonnistui: + + + + Cheats Not Found + Huijauksia ei löytynyt + + + + CheatsNotFound_MSG + Huijauksia ei löytynyt tälle pelille tämän version valitusta repositoriosta, yritä toista repositoriota tai pelin eri versiota. + + + + Cheats Downloaded Successfully + Huijaukset ladattu onnistuneesti + + + + CheatsDownloadedSuccessfully_MSG + Olet ladannut huijaukset onnistuneesti valitusta repositoriosta tälle pelin versiolle. Voit yrittää ladata toisesta repositoriosta, jos se on saatavilla, voit myös käyttää sitä valitsemalla tiedoston luettelosta. + + + + Failed to save: + Tallentaminen epäonnistui: + + + + Failed to download: + Lataaminen epäonnistui: + + + + Download Complete + Lataus valmis + + + + DownloadComplete_MSG + Korjaukset ladattu onnistuneesti! Kaikki saatavilla olevat korjaukset kaikille peleille on ladattu, eikä niitä tarvitse ladata yksittäin jokaiselle pelille kuten huijauksissa. Jos päivitystä ei näy, se saattaa olla, että sitä ei ole saatavilla tietylle sarjanumerolle ja peliversiolle. Saattaa olla tarpeen päivittää peli. + + + + Failed to parse JSON data from HTML. + JSON-tietojen jäsentäminen HTML:stä epäonnistui. + + + + Failed to retrieve HTML page. + HTML-sivun hakeminen epäonnistui. + + + + Failed to open file: + Tiedoston avaaminen epäonnistui: + + + + XML ERROR: + XML VIRHE: + + + + Failed to open files.json for writing + Tiedostoa files.json ei voitu avata kirjoittamista varten + + + + Author: + Tekijä: + + + + Directory does not exist: + Kansiota ei ole olemassa: + + + + Failed to open files.json for reading. + Tiedostoa files.json ei voitu avata lukemista varten. + + + + Name: + Nimi: + + + + Can't apply cheats before the game is started + Ei voi käyttää huijauksia ennen kuin peli on aloitettu. + + + + SettingsDialog + + + Save + Tallenna + + + + Apply + Ota käyttöön + + + + Restore Defaults + 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. + + + + consoleLanguageGroupBox + Konsoli 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ä. + + + + separateUpdatesCheckBox + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + + + + showSplashCheckBox + Näytä Alkunäyttö:\nNäyttää pelin alkunä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ä. + + + + 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ä. + + + + 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. + + + + 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. + + + + GUIgroupBox + Soita Otsikkomusiikkia:\nJos peli tukee sitä, ota käyttöön erityisen musiikin soittaminen pelin valinnan yhteydessä käyttöliittymässä. + + + + 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ä. + + + + idleTimeoutGroupBox + Aseta aika, jolloin 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. + + + + Never + Ei koskaan + + + + Idle + Odotustila + + + + Always + aina + + + + Touchpad Left + Kosketuslevy Vasemmalla + + + + Touchpad Right + Kosketuslevy Oikealla + + + + Touchpad Center + Kosketuslevy Keskellä + + + + 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. + + + + resolutionLayout + Leveys/Korkeus:\nAsettaa emulaattorin ikkunan koon käynnistyksen aikana, 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! + + + + dumpShadersCheckBox + Ota Shadersin dumpaus käyttöön:\nTeknistä vianetsintää varten pelin shadereita tallennetaan kansioon niiden renderöinnin aikana. + + + + nullGpuCheckBox + Ota Null GPU käyttöön:\nTeknistä vianetsintää varten pelin renderöinti estetään niin, että ikään kuin grafiikkakorttia ei olisi. + + + + gameFoldersBox + Pelihakemistot:\nLuettelo hakemistoista asennettujen pelien tarkistamiseksi. + + + + addFolderButton + Lisää:\nLisää hakemisto luetteloon. + + + + removeFolderButton + Poista:\nPoista hakemisto luettelosta. + + + + debugDump + Ota Debug Dumpaus käyttöön:\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ä. + + + + 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ä. + + + + 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. + + + + GameListFrame + + + Icon + Ikoni + + + + Name + Nimi + + + + Serial + Sarjanumero + + + + Region + Alue + + + + Firmware + Ohjelmisto + + + + Size + Koko + + + + Version + Versio + + + + Path + Polku + + + + Play Time + Peliaika + + + + CheckUpdate + + + Auto Updater + Automaattinen päivitys + + + + Error + Virhe + + + + Network error: + Verkkovirhe: + + + + Failed to parse update information. + Päivitysinformaation 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. + + + + Your version is already up to date! + Versiosi on jo ajan tasalla! + + + + Update Available + Päivitys saatavilla + + + + Update Channel + Päivityskanava + + + + Current Version + Nykyinen versio + + + + Latest Version + Uusin versio + + + + Do you want to update? + Haluatko päivittää? + + + + Show Changelog + Näytä muutospäiväkirja + + + + Check for Updates at Startup + Tarkista päivitykset alussa + + + + Update + Päivitä + + + + No + Ei + + + + Hide Changelog + Piilota muutospäiväkirja + + + + Changes + Muutos + + + + Network error occurred while trying to access the URL + Verkkovirhe tapahtui yrittäessäsi päästä URL-osoitteeseen + + + + Download Complete + Download 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 + + + + Starting Update... + Aloitetaan päivitys... + + + + Failed to create the update script file + Päivitysskripttitiedoston luominen epäonnistui + + + \ No newline at end of file diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts new file mode 100644 index 000000000..f891b7475 --- /dev/null +++ b/src/qt_gui/translations/fr.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Ouvrir un dossier + + + + GameInfoClass + + + Loading game list, please wait :3 + Chargement de la liste de jeu, veuillez patienter... + + + + Cancel + Annuler + + + + Loading... + Chargement... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choisir un répertoire + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Créer un raccourci + + + + Open Game Folder + Ouvrir le dossier du jeu + + + + Cheats / Patches + Cheats/Patchs + + + + SFO Viewer + Visionneuse SFO + + + + Trophy Viewer + Visionneuse de trophées + + + + Copy info + Copier infos + + + + Copy Name + Copier le nom + + + + Copy Serial + Copier le N° de série + + + + Copy All + Copier tout + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Création du raccourci + + + + Shortcut created successfully!\n %1 + Raccourci créé avec succès !\n %1 + + + + Error + Erreur + + + + Error creating shortcut!\n %1 + Erreur lors de la création du raccourci !\n %1 + + + + Install PKG + Installer un PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Ouvrir un dossier + + + + TrophyViewer + + + Trophy Viewer + Visionneuse de trophées + + + + 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 + Enable Separate Update Folder + + + + Show Splash + Afficher l'image du jeu + + + + Is PS4 Pro + Mode PS4 Pro + + + + Enable Discord Rich Presence + Activer Discord Rich Presence + + + + Username + Nom d'utilisateur + + + + Logger + Journalisation + + + + Log Type + Type + + + + Log Filter + Filtre + + + + Input + Entrée + + + + Cursor + Curseur + + + + Hide Cursor + Masquer le curseur + + + + Hide Cursor Idle Timeout + Délai d'inactivité pour masquer le curseur + + + + 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 + + + + Play title music + Lire la musique du titre + + + + Volume + Volume + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats/Patches + + + + 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. Il peut être nécessaire de mettre à jour le 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. + + + + 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 + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + + + + 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 + Est-ce un 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icône + + + + Name + Nom + + + + Serial + Série + + + + Region + Région + + + + Firmware + Firmware + + + + Size + Taille + + + + Version + Version + + + + Path + Répertoire + + + + Play Time + Temps de jeu + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts new file mode 100644 index 000000000..500629682 --- /dev/null +++ b/src/qt_gui/translations/hu_HU.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Mappa megnyitása + + + + 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.. + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Mappa kiválasztása + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + 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 érték nem érvényes. + + + + GuiContextMenus + + + Create Shortcut + Parancsikon Létrehozása + + + + Open Game Folder + Játék Mappa Megnyitása + + + + Cheats / Patches + Csalások / Javítások + + + + SFO Viewer + SFO Néző + + + + Trophy Viewer + Trófeák Megtekintése + + + + 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... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Parancsikon létrehozása + + + + Shortcut created successfully!\n %1 + Parancsikon sikeresen létrehozva!\n %1 + + + + Error + Hiba + + + + Error creating shortcut!\n %1 + Hiba a parancsikon létrehozásával!\n %1 + + + + Install PKG + PKG telepítése + + + + 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? + + + + MainWindow + + + Open/Add Elf Folder + Efl Mappa Megnyitása/Hozzáadása + + + + Install Packages (PKG) + PKG-k Telepítése (PKG) + + + + Boot Game + Játék Bootolá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 + + + + Exit the application. + Lépjen ki az 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éző + + + + 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ék Lista Dumpolása + + + + PKG Viewer + PKG Néző + + + + Search... + Keresés... + + + + File + Fájl + + + + View + Megnézés + + + + Game List Icons + Játék Könyvtár Ikonok + + + + Game List Mode + Játék Könyvtár Mód + + + + 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 + + + + PKGViewer + + + Open Folder + Mappa Megnyitása + + + + TrophyViewer + + + Trophy Viewer + Trófeák Megtekintése + + + + 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 + Teljesképernyő Engedélyezése + + + + Enable Separate Update Folder + Enable Separate Update Folder + + + + Show Splash + Indítóképernyő Mutatása + + + + Is PS4 Pro + PS4 Pro + + + + Enable Discord Rich Presence + Engedélyezze a Discord Rich Presence-t + + + + Username + Felhasználónév + + + + Logger + Naplózó + + + + Log Type + Naplózási Típus + + + + Log Filter + Naplózási Filter + + + + Input + Bemenet + + + + Cursor + Kurzor + + + + Hide Cursor + Kurzor elrejtése + + + + Hide Cursor Idle Timeout + Kurzor inaktivitási időtúllépé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 + + + + Play title music + Címzene lejátszása + + + + Volume + Hangerő + + + + MainWindow + + + Game List + Játéklista + + + + * Unsupported Vulkan Version + * Támogatott Vulkan verzió hiányzik + + + + Download Cheats For All Installed Games + Letöltés csalások minden telepített játékhoz + + + + Download Patches For All Games + Frissítések letöltése minden játékhoz + + + + Download Complete + Letöltés befejezve + + + + You have downloaded cheats for all the games you have installed. + Csalásokat töltöttél le az összes telepített játékhoz. + + + + Patches Downloaded Successfully! + Frissítések sikeresen letöltve! + + + + All Patches available for all games have been downloaded. + Az összes játékhoz elérhető frissítés letöltésre került. + + + + Games: + Játékok: + + + + PKG File (*.PKG) + PKG fájl (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF fájlok (*.bin *.elf *.oelf) + + + + Game Boot + Játék indító + + + + Only one file can be selected! + Csak egy fájl választható ki! + + + + PKG Extraction + PKG kicsomagolás + + + + Patch detected! + 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 %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 DLC-t: %1? + + + + 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 + Csalások / Javítások + + + + defaultTextEdit_MSG + A csalások/patchek kísérleti jellegűek.\nHasználja őket óvatosan.\n\nTöltse le a csalásokat egyesével a repository kiválasztásával és a letöltés gombra kattintással.\nA Patches fül alatt egyszerre letöltheti az összes patchet, választhat, melyeket szeretné használni, és elmentheti a választását.\n\nMivel nem fejlesztjük a csalásokat/patch-eket,\nkérjük, jelentse a problémákat a csalás szerzőjének.\n\nKészített egy új csalást? Látogasson el ide:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Nincs elérhető kép + + + + Serial: + Sorozatszám: + + + + Version: + Verzió: + + + + Size: + Méret: + + + + Select Cheat File: + Válaszd ki a csalás fájlt: + + + + Repository: + Tároló: + + + + Download Cheats + Csalások letöltése + + + + Delete File + Fájl törlése + + + + No files selected. + Nincsenek kiválasztott fájlok. + + + + You can delete the cheats you don't want after downloading them. + Törölheted a nem kívánt csalásokat a letöltés után. + + + + Do you want to delete the selected file?\n%1 + Szeretnéd törölni a kiválasztott fájlt?\n%1 + + + + Select Patch File: + Válaszd ki a javítás fájlt: + + + + Download Patches + Javítások letöltése + + + + Save + Mentés + + + + Cheats + Csalások + + + + Patches + Javítások + + + + Error + Hiba + + + + No patch selected. + Nincs kiválasztva javítás. + + + + Unable to open files.json for reading. + Nem sikerült megnyitni a files.json fájlt olvasásra. + + + + No patch file found for the current serial. + Nincs található javítási fájl a jelenlegi sorozatszámhoz. + + + + Unable to open the file for reading. + Nem sikerült megnyitni a fájlt olvasásra. + + + + Unable to open the file for writing. + Nem sikerült megnyitni a fájlt írásra. + + + + Failed to parse XML: + XML elemzési hiba: + + + + Success + Siker + + + + Options saved successfully. + A beállítások sikeresen elmentve. + + + + Invalid Source + Érvénytelen forrás + + + + The selected source is invalid. + A kiválasztott forrás érvénytelen. + + + + File Exists + A fájl létezik + + + + File already exists. Do you want to replace it? + A fájl már létezik. Szeretnéd helyettesíteni? + + + + Failed to save file: + Nem sikerült elmenteni a fájlt: + + + + Failed to download file: + Nem sikerült letölteni a fájlt: + + + + Cheats Not Found + Csalások nem találhatóak + + + + CheatsNotFound_MSG + Nincs található csalás ezen a játékverzión ebben a kiválasztott tárolóban,próbálj meg egy másik tárolót vagy a játék egy másik verzióját. + + + + Cheats Downloaded Successfully + Csalások sikeresen letöltve + + + + CheatsDownloadedSuccessfully_MSG + Sikeresen letöltötted a csalásokat ennek a játéknak a verziójához a kiválasztott tárolóból. Próbálhatsz letölteni egy másik tárolóból is, ha az elérhető, akkor a fájl kiválasztásával az is használható lesz. + + + + Failed to save: + Nem sikerült menteni: + + + + Failed to download: + Nem sikerült letölteni: + + + + Download Complete + Letöltés befejezve + + + + DownloadComplete_MSG + Frissítések sikeresen letöltve! Minden elérhető frissítés letöltésre került, nem szükséges egyesével letölteni őket minden játékhoz, mint a csalások esetében. Ha a javítás nem jelenik meg, lehet, hogy nem létezik a játék adott sorozatszámához és verziójához. Lehet, hogy frissítenie kell a játékot. + + + + Failed to parse JSON data from HTML. + Nem sikerült az JSON adatok elemzése HTML-ből. + + + + Failed to retrieve HTML page. + Nem sikerült HTML oldal lekérése. + + + + Failed to open file: + Nem sikerült megnyitni a fájlt: + + + + XML ERROR: + XML HIBA: + + + + Failed to open files.json for writing + Nem sikerült megnyitni a files.json fájlt írásra + + + + Author: + Szerző: + + + + Directory does not exist: + A könyvtár nem létezik: + + + + Failed to open files.json for reading. + Nem sikerült megnyitni a files.json fájlt olvasásra. + + + + Name: + Név: + + + + 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 + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + + + + 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élyezheti a speciális funkciókat olyan játékokban, amelyek támogatják. + + + + discordRPCCheckbox + Engedélyezze a Discord Rich Presence-t:\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. + + + + 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 a speciális zene lejátszását, amikor a játékot kiválasztja a GUI-ban. + + + + hideCursorGroupBox + Akurátor elrejtése:\nVálassza ki, mikor tűnjön el az egérkurzor:\nSoha: Az egér mindig látható.\nInaktív: Állítson be egy időt, amikor inaktív állapotban eltűnik.\nMindig: soha nem látja az egeret. + + + + idleTimeoutGroupBox + Állítson be egy időt, ameddig az egér inaktív állapot után 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. + + + + Never + Soha + + + + Idle + Inaktív + + + + Always + Mindig + + + + Touchpad Left + Érintőpad Balra + + + + Touchpad Right + Érintőpad Jobbra + + + + Touchpad Center + Érintőpad Középen + + + + None + Semmi + + + + graphicsAdapterGroupBox + Grafikus eszköz:\nTöbb GPU-s rendszereken válassza ki a GPU-t, amelyet az emulátor használ a legördülő listából,\nvagy válassza az "Auto Select" lehetőséget, hogy automatikusan meghatározza 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 osztó:\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 az telepített játékok ellenőrzésére. + + + + 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. + + + + GameListFrame + + + Icon + Ikon + + + + Name + Név + + + + Serial + Sorozatszám + + + + Region + Régió + + + + Firmware + Firmware + + + + Size + Méret + + + + Version + Verzió + + + + Path + Útvonal + + + + Play Time + Játékidő + + + + 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 + Legújabb verzió + + + + Do you want to update? + Szeretnéd frissíteni? + + + + Show Changelog + Módosítások megjelenítése + + + + Check for Updates at Startup + Frissítések keresése indításkor + + + + Update + Frissítés + + + + No + Nem + + + + Hide Changelog + Módosítások elrejtése + + + + Changes + Módosítá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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts new file mode 100644 index 000000000..8721e3a8a --- /dev/null +++ b/src/qt_gui/translations/id.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Cheat / Patch + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Masukan + + + + Cursor + Kursor + + + + Hide Cursor + Sembunyikan kursor + + + + Hide Cursor Idle Timeout + Batas waktu sembunyikan kursor tidak aktif + + + + 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 + + + + Play title music + Putar musik judul + + + + Volume + Volume + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheat / Patch + + + + defaultTextEdit_MSG + Cheats/Patches bersifat eksperimental.\nGunakan dengan hati-hati.\n\nUnduh cheats satu per satu dengan memilih repositori dan mengklik tombol unduh.\nDi tab Patches, Anda dapat mengunduh semua patch sekaligus, memilih yang ingin digunakan, dan menyimpan pilihan Anda.\n\nKarena kami tidak mengembangkan Cheats/Patches,\nharap laporkan masalah kepada pembuat cheat.\n\nMembuat cheat baru? Kunjungi:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Tidak Ada Gambar Tersedia + + + + Serial: + Serial: + + + + Version: + Versi: + + + + Size: + Ukuran: + + + + Select Cheat File: + Pilih File Cheat: + + + + Repository: + Repositori: + + + + Download Cheats + Unduh Cheat + + + + Delete File + Hapus File + + + + No files selected. + Tidak ada file yang dipilih. + + + + You can delete the cheats you don't want after downloading them. + Anda dapat menghapus cheat yang tidak Anda inginkan setelah mengunduhnya. + + + + Do you want to delete the selected file?\n%1 + Apakah Anda ingin menghapus berkas yang dipilih?\n%1 + + + + Select Patch File: + Pilih File Patch: + + + + Download Patches + Unduh Patch + + + + Save + Simpan + + + + Cheats + Cheat + + + + Patches + Patch + + + + Error + Kesalahan + + + + No patch selected. + Tidak ada patch yang dipilih. + + + + Unable to open files.json for reading. + Tidak dapat membuka files.json untuk dibaca. + + + + No patch file found for the current serial. + Tidak ada file patch ditemukan untuk serial saat ini. + + + + Unable to open the file for reading. + Tidak dapat membuka file untuk dibaca. + + + + Unable to open the file for writing. + Tidak dapat membuka file untuk menulis. + + + + Failed to parse XML: + Gagal menganalisis XML: + + + + Success + Sukses + + + + Options saved successfully. + Opsi berhasil disimpan. + + + + Invalid Source + Sumber Tidak Valid + + + + The selected source is invalid. + Sumber yang dipilih tidak valid. + + + + File Exists + File Ada + + + + File already exists. Do you want to replace it? + File sudah ada. Apakah Anda ingin menggantinya? + + + + Failed to save file: + Gagal menyimpan file: + + + + Failed to download file: + Gagal mengunduh file: + + + + Cheats Not Found + Cheat Tidak Ditemukan + + + + CheatsNotFound_MSG + Cheat tidak ditemukan untuk game ini dalam versi repositori yang dipilih,cobalah repositori lain atau versi game yang berbeda. + + + + Cheats Downloaded Successfully + Cheat Berhasil Diunduh + + + + CheatsDownloadedSuccessfully_MSG + Anda telah berhasil mengunduh cheat untuk versi game ini dari repositori yang dipilih. Anda bisa mencoba mengunduh dari repositori lain, jika tersedia akan juga memungkinkan untuk menggunakannya dengan memilih file dari daftar. + + + + Failed to save: + Gagal menyimpan: + + + + Failed to download: + Gagal mengunduh: + + + + Download Complete + Unduhan Selesai + + + + DownloadComplete_MSG + Patch Berhasil Diunduh! Semua Patch yang tersedia untuk semua game telah diunduh, tidak perlu mengunduhnya satu per satu seperti yang terjadi pada Cheat. Jika patch tidak muncul, mungkin patch tersebut tidak ada untuk nomor seri dan versi game yang spesifik. Mungkin perlu memperbarui game. + + + + Failed to parse JSON data from HTML. + Gagal menganalisis data JSON dari HTML. + + + + Failed to retrieve HTML page. + Gagal mengambil halaman HTML. + + + + Failed to open file: + Gagal membuka file: + + + + XML ERROR: + KESALAHAN XML: + + + + Failed to open files.json for writing + Gagal membuka files.json untuk menulis + + + + Author: + Penulis: + + + + Directory does not exist: + Direktori tidak ada: + + + + Failed to open files.json for reading. + Gagal membuka files.json untuk dibaca. + + + + Name: + Nama: + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Ikon + + + + Name + Nama + + + + Serial + Serial + + + + Region + Wilayah + + + + Firmware + Firmware + + + + Size + Ukuran + + + + Version + Versi + + + + Path + Jalur + + + + Play Time + Waktu Bermain + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts new file mode 100644 index 000000000..747148b6e --- /dev/null +++ b/src/qt_gui/translations/it.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Apri Cartella + + + + GameInfoClass + + + Loading game list, please wait :3 + Caricamento lista giochi, attendere :3 + + + + Cancel + Annulla + + + + Loading... + Caricamento... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Scegli cartella + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Crea scorciatoia + + + + Open Game Folder + Apri cartella del gioco + + + + Cheats / Patches + Trucchi / Patch + + + + SFO Viewer + Visualizzatore SFO + + + + Trophy Viewer + Visualizzatore Trofei + + + + Copy info + Copia informazioni + + + + Copy Name + Copia Nome + + + + Copy Serial + Copia Seriale + + + + Copy All + Copia Tutto + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Creazione scorciatoia + + + + Shortcut created successfully!\n %1 + Scorciatoia creata con successo!\n %1 + + + + Error + Errore + + + + Error creating shortcut!\n %1 + Errore nella creazione della scorciatoia!\n %1 + + + + Install PKG + Installa PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Apri Cartella + + + + TrophyViewer + + + Trophy Viewer + Visualizzatore Trofei + + + + 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 + Enable Separate Update Folder + + + + Show Splash + Mostra Schermata Iniziale + + + + Is PS4 Pro + Modalità Ps4Pro + + + + Enable Discord Rich Presence + Abilita Discord Rich Presence + + + + Username + Nome Utente + + + + Logger + Logger + + + + Log Type + Tipo di Log + + + + Log Filter + Filtro Log + + + + Input + Input + + + + Cursor + Cursore + + + + Hide Cursor + Nascondi cursore + + + + Hide Cursor Idle Timeout + Timeout inattivo per nascondere il cursore + + + + Controller + Controller + + + + Back Button Behavior + Comportamento del pulsante Indietro + + + + Graphics + Grafica + + + + Graphics Device + Adattatore grafico + + + + Width + Larghezza + + + + Height + Altezza + + + + Vblank Divider + Divisore Vblank + + + + Advanced + Avanzato + + + + Enable Shaders Dumping + Abilita Dump Shader + + + + Enable NULL GPU + Abilita NULL GPU + + + + Paths + Percorsi + + + + Game Folders + Cartelle di gioco + + + + Add... + Aggiungi... + + + + Remove + Rimuovi + + + + Debug + Debug + + + + Enable Debug Dumping + Abilita Dump Debug + + + + Enable Vulkan Validation Layers + Abilita Vulkan Validation Layers + + + + Enable Vulkan Synchronization Validation + Abilita Vulkan Synchronization Validation + + + + Enable RenderDoc Debugging + Abilita Debugging RenderDoc + + + + 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 + + + + Play title music + Riproduci musica del titolo + + + + Volume + Volume + + + + MainWindow + + + 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 + Scaricamento 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 + Trucchi / Patch + + + + 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. Potrebbe essere necessario aggiornare il 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. + + + + 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 + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + + + + 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. + + + + 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. + + + + 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 + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icona + + + + Name + Nome + + + + Serial + Seriale + + + + Region + Regione + + + + Firmware + Firmware + + + + Size + Dimensione + + + + Version + Versione + + + + Path + Percorso + + + + Play Time + Tempo di Gioco + + + + 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 + Verifica 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts new file mode 100644 index 000000000..a020b1687 --- /dev/null +++ b/src/qt_gui/translations/ja_JP.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + shadPS4について + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4は、PlayStation 4の実験的なオープンソースエミュレーターです。 + + + + This software should not be used to play games you have not legally obtained. + このソフトウェアは、合法的に入手していないゲームをプレイするために使用するものではありません。 + + + + ElfViewer + + + Open Folder + フォルダを開く + + + + GameInfoClass + + + Loading game list, please wait :3 + ゲームリストを読み込み中です。お待ちください :3 + + + + Cancel + キャンセル + + + + Loading... + 読み込み中... + + + + 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. + ゲームをインストールする場所が無効です。 + + + + GuiContextMenus + + + Create Shortcut + ショートカットを作成 + + + + Open Game Folder + ゲームフォルダを開く + + + + Cheats / Patches + チート / パッチ + + + + SFO Viewer + SFOビューワー + + + + Trophy Viewer + トロフィービューワー + + + + Copy info + 情報をコピー + + + + Copy Name + 名前をコピー + + + + Copy Serial + シリアルをコピー + + + + Copy All + すべてコピー + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + ショートカットの作成 + + + + Shortcut created successfully!\n %1 + ショートカットが正常に作成されました!\n %1 + + + + Error + エラー + + + + Error creating shortcut!\n %1 + ショートカットの作成に失敗しました!\n %1 + + + + 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? + + + + 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 + ツールバー + + + + PKGViewer + + + Open Folder + フォルダーを開く + + + + TrophyViewer + + + Trophy Viewer + トロフィービューアー + + + + 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 + ユーザー名 + + + + Logger + ロガー + + + + Log Type + ログタイプ + + + + Log Filter + ログフィルター + + + + Input + 入力 + + + + Cursor + カーソル + + + + Hide Cursor + カーソルを隠す + + + + Hide Cursor Idle Timeout + カーソル非アクティブタイムアウト + + + + 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設定 + + + + Play title music + タイトル音楽を再生する + + + + Volume + 音量 + + + + MainWindow + + + 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ファイルでないようです + + + + CheatsPatches + + + Cheats / Patches + チート / パッチ + + + + defaultTextEdit_MSG + チート/パッチは実験的です。\n使用には注意してください。\n\nリポジトリを選択し、ダウンロードボタンをクリックしてチートを個別にダウンロードします。\n「Patches」タブでは、すべてのパッチを一度にダウンロードし、使用したいものを選択して選択を保存できます。\n\nチート/パッチを開発していないため、\n問題があればチートの作者に報告してください。\n\n新しいチートを作成しましたか?\nhttps://github.com/shadps4-emu/ps4_cheats を訪問してください。 + + + + No Image Available + 画像は利用できません + + + + Serial: + シリアル: + + + + Version: + バージョン: + + + + Size: + サイズ: + + + + Select Cheat File: + チートファイルを選択: + + + + Repository: + リポジトリ: + + + + Download Cheats + チートをダウンロード + + + + Delete File + ファイルを削除 + + + + No files selected. + ファイルが選択されていません。 + + + + You can delete the cheats you don't want after downloading them. + ダウンロード後に不要なチートを削除できます。 + + + + Do you want to delete the selected file?\n%1 + 選択したファイルを削除しますか?\n%1 + + + + Select Patch File: + パッチファイルを選択: + + + + Download Patches + パッチをダウンロード + + + + Save + 保存 + + + + Cheats + チート + + + + Patches + パッチ + + + + Error + エラー + + + + No patch selected. + パッチが選択されていません。 + + + + Unable to open files.json for reading. + files.jsonを読み込み用に開けません。 + + + + No patch file found for the current serial. + 現在のシリアルに対するパッチファイルが見つかりません。 + + + + Unable to open the file for reading. + ファイルを読み込み用に開けません。 + + + + Unable to open the file for writing. + ファイルを記録用に開けません。 + + + + Failed to parse XML: + XMLの解析に失敗しました: + + + + Success + 成功 + + + + Options saved successfully. + オプションが正常に保存されました。 + + + + Invalid Source + 無効なソース + + + + The selected source is invalid. + 選択したソースは無効です。 + + + + File Exists + ファイルが存在します + + + + File already exists. Do you want to replace it? + ファイルはすでに存在します。置き換えますか? + + + + Failed to save file: + ファイルの保存に失敗しました: + + + + Failed to download file: + ファイルのダウンロードに失敗しました: + + + + Cheats Not Found + チートが見つかりません + + + + CheatsNotFound_MSG + このゲームのこのバージョンのチートが選択されたリポジトリに見つかりませんでした。別のリポジトリまたはゲームの別のバージョンを試してください。 + + + + Cheats Downloaded Successfully + チートが正常にダウンロードされました + + + + CheatsDownloadedSuccessfully_MSG + このゲームのこのバージョンのチートをリポジトリから正常にダウンロードしました。 別のリポジトリからのダウンロードも試せます。利用可能であれば、リストからファイルを選択して使用することも可能です。 + + + + Failed to save: + 保存に失敗しました: + + + + Failed to download: + ダウンロードに失敗しました: + + + + Download Complete + ダウンロード完了 + + + + DownloadComplete_MSG + パッチが正常にダウンロードされました! すべてのゲームに利用可能なパッチがダウンロードされました。チートとは異なり、各ゲームごとに個別にダウンロードする必要はありません。 パッチが表示されない場合、特定のシリアル番号とバージョンのゲームには存在しない可能性があります。ゲームを更新する必要があるかもしれません。 + + + + Failed to parse JSON data from HTML. + HTMLからJSONデータの解析に失敗しました。 + + + + Failed to retrieve HTML page. + HTMLページの取得に失敗しました。 + + + + Failed to open file: + ファイルを開くのに失敗しました: + + + + XML ERROR: + XMLエラー: + + + + Failed to open files.json for writing + files.jsonを記録用に開けません + + + + Author: + 著者: + + + + Directory does not exist: + ディレクトリが存在しません: + + + + Failed to open files.json for reading. + files.jsonを読み込み用に開けません。 + + + + Name: + 名前: + + + + 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のアカウントユーザー名を設定します。これは、一部のゲームで表示される場合があります。 + + + + 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でゲームを選択したときに特別な音楽を再生することを有効にします。 + + + + hideCursorGroupBox + カーソルを隠す:\nカーソルが消えるタイミングを選択してください:\n決して: いつでもマウスが見えます。\nアイドル: アイダルの後に消えるまでの時間を設定します。\n常に: マウスは決して見えません。 + + + + idleTimeoutGroupBox + アイドル後にマウスが消えるまでの時間を設定します。 + + + + backButtonBehaviorGroupBox + 戻るボタンの動作:\nコントローラーの戻るボタンを、PS4のタッチパッドの指定された位置をタッチするように設定します。 + + + + 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との互換性を提供し、現在レンダリング中のフレームのキャプチャと分析を可能にします。 + + + + GameListFrame + + + Icon + アイコン + + + + Name + 名前 + + + + Serial + シリアル + + + + Region + 地域 + + + + Firmware + ファームウェア + + + + Size + サイズ + + + + Version + バージョン + + + + Path + パス + + + + Play Time + プレイ時間 + + + + 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 + アップデートスクリプトファイルの作成に失敗しました + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts new file mode 100644 index 000000000..03ab49ad6 --- /dev/null +++ b/src/qt_gui/translations/ko_KR.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + 치트 / 패치 + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Input + + + + Cursor + Cursor + + + + Hide Cursor + Hide Cursor + + + + Hide Cursor Idle Timeout + Hide Cursor Idle Timeout + + + + 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 + + + + Play title music + Play title music + + + + Volume + 음량 + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + No Image Available + + + + Serial: + Serial: + + + + Version: + Version: + + + + Size: + Size: + + + + Select Cheat File: + Select Cheat File: + + + + Repository: + Repository: + + + + Download Cheats + Download Cheats + + + + Delete File + Delete File + + + + No files selected. + No files selected. + + + + You can delete the cheats you don't want after downloading them. + You can delete the cheats you don't want after downloading them. + + + + Do you want to delete the selected file?\n%1 + Do you want to delete the selected file?\n%1 + + + + Select Patch File: + Select Patch File: + + + + Download Patches + Download Patches + + + + Save + Save + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Error + + + + No patch selected. + No patch selected. + + + + Unable to open files.json for reading. + Unable to open files.json for reading. + + + + No patch file found for the current serial. + No patch file found for the current serial. + + + + Unable to open the file for reading. + Unable to open the file for reading. + + + + Unable to open the file for writing. + Unable to open the file for writing. + + + + Failed to parse XML: + Failed to parse XML: + + + + Success + Success + + + + Options saved successfully. + Options saved successfully. + + + + Invalid Source + Invalid Source + + + + The selected source is invalid. + The selected source is invalid. + + + + File Exists + File Exists + + + + File already exists. Do you want to replace it? + File already exists. Do you want to replace it? + + + + Failed to save file: + Failed to save file: + + + + Failed to download file: + Failed to download file: + + + + Cheats Not Found + Cheats Not Found + + + + CheatsNotFound_MSG + No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. + + + + Cheats Downloaded Successfully + Cheats Downloaded Successfully + + + + CheatsDownloadedSuccessfully_MSG + You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. + + + + Failed to save: + Failed to save: + + + + Failed to download: + Failed to download: + + + + Download Complete + Download Complete + + + + DownloadComplete_MSG + Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. It may be necessary to update 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icon + + + + Name + Name + + + + Serial + Serial + + + + Region + Region + + + + Firmware + Firmware + + + + Size + Size + + + + Version + Version + + + + Path + Path + + + + Play Time + Play Time + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts new file mode 100644 index 000000000..aecf5aec9 --- /dev/null +++ b/src/qt_gui/translations/lt_LT.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Apgaulės / Pleistrai + Cheats / Patches + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Įvestis + + + + Cursor + Žymeklis + + + + Hide Cursor + Slėpti žymeklį + + + + Hide Cursor Idle Timeout + Žymeklio paslėpimo neveikimo laikas + + + + 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 + + + + Play title music + Groti antraštės muziką + + + + Volume + Garsumas + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Sukčiavimai / Pataisos + + + + defaultTextEdit_MSG + Cheats/Patches yra eksperimentiniai.\nNaudokite atsargiai.\n\nAtsisiųskite cheats atskirai pasirinkdami saugyklą ir paspausdami atsisiuntimo mygtuką.\nPatches skirtuke galite atsisiųsti visus patch’us vienu metu, pasirinkti, kuriuos norite naudoti, ir išsaugoti pasirinkimą.\n\nKadangi mes nekurime Cheats/Patches,\npraneškite problemas cheat autoriui.\n\nSukūrėte naują cheat? Apsilankykite:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Nuotrauka neprieinama + + + + Serial: + Seriinis numeris: + + + + Version: + Versija: + + + + Size: + Dydis: + + + + Select Cheat File: + Pasirinkite sukčiavimo failą: + + + + Repository: + Saugykla: + + + + Download Cheats + Atsisiųsti sukčiavimus + + + + Delete File + Pašalinti failą + + + + No files selected. + Failai nepasirinkti. + + + + You can delete the cheats you don't want after downloading them. + Galite pašalinti sukčiavimus, kurių nenorite, juos atsisiuntę. + + + + Do you want to delete the selected file?\n%1 + Ar norite ištrinti pasirinktą failą?\n%1 + + + + Select Patch File: + Pasirinkite pataisos failą: + + + + Download Patches + Atsisiųsti pataisas + + + + Save + Įrašyti + + + + Cheats + Sukčiavimai + + + + Patches + Pataisos + + + + Error + Klaida + + + + No patch selected. + Nieko nepataisyta. + + + + Unable to open files.json for reading. + Neįmanoma atidaryti files.json skaitymui. + + + + No patch file found for the current serial. + Nepavyko rasti pataisos failo dabartiniam serijiniam numeriui. + + + + Unable to open the file for reading. + Neįmanoma atidaryti failo skaitymui. + + + + Unable to open the file for writing. + Neįmanoma atidaryti failo rašymui. + + + + Failed to parse XML: + Nepavyko išanalizuoti XML: + + + + Success + Sėkmė + + + + Options saved successfully. + Nustatymai sėkmingai išsaugoti. + + + + Invalid Source + Netinkamas šaltinis + + + + The selected source is invalid. + Pasirinktas šaltinis yra netinkamas. + + + + File Exists + Failas egzistuoja + + + + File already exists. Do you want to replace it? + Failas jau egzistuoja. Ar norite jį pakeisti? + + + + Failed to save file: + Nepavyko išsaugoti failo: + + + + Failed to download file: + Nepavyko atsisiųsti failo: + + + + Cheats Not Found + Sukčiavimai nerasti + + + + CheatsNotFound_MSG + Nerasta sukčiavimų šiam žaidimui šioje pasirinktos saugyklos versijoje,bandykite kitą saugyklą arba skirtingą žaidimo versiją. + + + + Cheats Downloaded Successfully + Sukčiavimai sėkmingai atsisiųsti + + + + CheatsDownloadedSuccessfully_MSG + Sėkmingai atsisiuntėte sukčiavimus šios žaidimo versijos iš pasirinktos saugyklos. Galite pabandyti atsisiųsti iš kitos saugyklos, jei ji yra prieinama, taip pat bus galima ją naudoti pasirinkus failą iš sąrašo. + + + + Failed to save: + Nepavyko išsaugoti: + + + + Failed to download: + Nepavyko atsisiųsti: + + + + Download Complete + Atsisiuntimas baigtas + + + + DownloadComplete_MSG + Pataisos sėkmingai atsisiųstos! Visos pataisos visiems žaidimams buvo atsisiųstos, nebėra reikalo jas atsisiųsti atskirai kiekvienam žaidimui, kaip tai vyksta su sukčiavimais. Jei pleistras nepasirodo, gali būti, kad jo nėra tam tikram žaidimo serijos numeriui ir versijai. Gali prireikti atnaujinti žaidimą. + + + + Failed to parse JSON data from HTML. + Nepavyko išanalizuoti JSON duomenų iš HTML. + + + + Failed to retrieve HTML page. + Nepavyko gauti HTML puslapio. + + + + Failed to open file: + Nepavyko atidaryti failo: + + + + XML ERROR: + XML KLAIDA: + + + + Failed to open files.json for writing + Nepavyko atidaryti files.json rašymui + + + + Author: + Autorius: + + + + Directory does not exist: + Katalogas neegzistuoja: + + + + Failed to open files.json for reading. + Nepavyko atidaryti files.json skaitymui. + + + + Name: + Pavadinimas: + + + + 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. + + + + 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. + + + + 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. + + + + 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ą. + + + + GameListFrame + + + Icon + Ikona + + + + Name + Vardas + + + + Serial + Serijinis numeris + + + + Region + Regionas + + + + Firmware + Firmvare + + + + Size + Dydis + + + + Version + Versija + + + + Path + Kelias + + + + Play Time + Žaidimo laikas + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts new file mode 100644 index 000000000..303b5f831 --- /dev/null +++ b/src/qt_gui/translations/nb.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Juks / Oppdateringer + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + MainWindow + + + Open/Add Elf Folder + Open/Add Elf Folder + + + + Install Packages (PKG) + Install Packages (PKG) + + + + Boot Game + Boot Game + + + + Check for Updates + Sjekk etter oppdateringer + + + + 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 + Last ned Juks / Oppdateringer + + + + 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 + Hjelp + + + + Dark + Dark + + + + Light + Light + + + + Green + Green + + + + Blue + Blue + + + + Violet + Violet + + + + toolBar + toolBar + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Inndata + + + + Cursor + Markør + + + + Hide Cursor + Skjul markør + + + + Hide Cursor Idle Timeout + Timeout for å skjule markør ved inaktivitet + + + + Controller + Kontroller + + + + Back Button Behavior + Tilbakeknapp atferd + + + + 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 + Spillmapper + + + + Add... + Legg til... + + + + 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 + Oppdatering + + + + Check for Updates at Startup + Sjekk etter oppdateringer ved oppstart + + + + Update Channel + Oppdateringskanal + + + + Check for Updates + Sjekk for oppdateringer + + + + GUI Settings + GUI-Innstillinger + + + + Play title music + Spill tittelmusikk + + + + Volume + Volum + + + + MainWindow + + + Game List + Spilliste + + + + * Unsupported Vulkan Version + * Ikke støttet Vulkan-versjon + + + + Download Cheats For All Installed Games + Last ned jukser for alle installerte spill + + + + Download Patches For All Games + Last ned oppdateringer for alle spill + + + + Download Complete + Nedlasting fullført + + + + You have downloaded cheats for all the games you have installed. + Du har lastet ned jukser for alle spillene du har installert. + + + + Patches Downloaded Successfully! + Oppdateringer lastet ned vellykket! + + + + All Patches available for all games have been downloaded. + Alle oppdateringer tilgjengelige for alle spillene har blitt lastet ned. + + + + Games: + Spill: + + + + PKG File (*.PKG) + PKG-fil (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF-filer (*.bin *.elf *.oelf) + + + + Game Boot + Spilloppstart + + + + Only one file can be selected! + Kun én fil kan velges! + + + + PKG Extraction + PKG-ekstraksjon + + + + Patch detected! + Oppdatering oppdaget! + + + + PKG and Game versions match: + PKG- og spillversjoner stemmer overens: + + + + Would you like to overwrite? + Ønsker du å overskrive? + + + + PKG Version %1 is older than installed version: + PKG-versjon %1 er eldre enn installert versjon: + + + + Game is installed: + Spillet er installert: + + + + Would you like to install Patch: + Ønsker du å installere oppdateringen: + + + + DLC Installation + DLC-installasjon + + + + Would you like to install DLC: %1? + Ønsker du å installere DLC: %1? + + + + DLC already installed: + DLC allerede installert: + + + + Game already installed + Spillet er allerede installert + + + + PKG is a patch, please install the game first! + PKG er en oppdatering, vennligst installer spillet først! + + + + PKG ERROR + PKG FEIL + + + + Extracting PKG %1/%2 + Ekstraherer PKG %1/%2 + + + + Extraction Finished + Ekstrahering fullført + + + + Game successfully installed at %1 + Spillet ble installert vellykket på %1 + + + + File doesn't appear to be a valid PKG file + Fil ser ikke ut til å være en gyldig PKG-fil + + + + CheatsPatches + + + Cheats / Patches + Jukser / Oppdateringer + + + + defaultTextEdit_MSG + Cheats/Patches er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned cheats individuelt ved å velge depotet og klikke på nedlastingsknappen.\nPå fanen Patches kan du laste ned alle patches samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Cheats/Patches,\nvær vennlig å rapportere problemer til cheat-utvikleren.\n\nHar du laget en ny cheat? Besøk:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Ingen bilde tilgjengelig + + + + Serial: + Serienummer: + + + + Version: + Versjon: + + + + Size: + Størrelse: + + + + Select Cheat File: + Velg juksfil: + + + + Repository: + Depot: + + + + Download Cheats + Last ned jukser + + + + Delete File + Slett fil + + + + No files selected. + Ingen filer valgt. + + + + You can delete the cheats you don't want after downloading them. + Du kan slette jukser du ikke ønsker etter å ha lastet dem ned. + + + + Do you want to delete the selected file?\n%1 + Ønsker du å slette den valgte filen?\n%1 + + + + Select Patch File: + Velg oppdateringsfil: + + + + Download Patches + Last ned oppdateringer + + + + Save + Lagre + + + + Cheats + Jukser + + + + Patches + Oppdateringer + + + + Error + Feil + + + + No patch selected. + Ingen oppdatering valgt. + + + + Unable to open files.json for reading. + Kan ikke åpne files.json for lesing. + + + + No patch file found for the current serial. + Ingen oppdateringsfil funnet for det aktuelle serienummeret. + + + + Unable to open the file for reading. + Kan ikke åpne filen for lesing. + + + + Unable to open the file for writing. + Kan ikke åpne filen for skriving. + + + + Failed to parse XML: + Feil ved parsing av XML: + + + + Success + Vellykket + + + + Options saved successfully. + Alternativer lagret vellykket. + + + + Invalid Source + Ugyldig kilde + + + + The selected source is invalid. + Den valgte kilden er ugyldig. + + + + File Exists + Fil eksisterer + + + + File already exists. Do you want to replace it? + Fil eksisterer allerede. Ønsker du å erstatte den? + + + + Failed to save file: + Kunne ikke lagre fil: + + + + Failed to download file: + Kunne ikke laste ned fil: + + + + Cheats Not Found + Jukser ikke funnet + + + + CheatsNotFound_MSG + Ingen jukser funnet for dette spillet i denne versjonen av det valgte depotet,prøv et annet depot eller en annen versjon av spillet. + + + + Cheats Downloaded Successfully + Jukser lastet ned vellykket + + + + CheatsDownloadedSuccessfully_MSG + Du har lastet ned jukser vellykket for denne versjonen av spillet fra det valgte depotet. Du kan prøve å laste ned fra et annet depot, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. + + + + Failed to save: + Kunne ikke lagre: + + + + Failed to download: + Kunne ikke laste ned: + + + + Download Complete + Nedlasting fullført + + + + DownloadComplete_MSG + Oppdateringer lastet ned vellykket! Alle oppdateringer tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med jukser. Hvis oppdateringen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. Det kan være nødvendig å oppdatere 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. + + + + Failed to open file: + Kunne ikke åpne fil: + + + + XML ERROR: + XML FEIL: + + + + Failed to open files.json for writing + Kunne ikke åpne files.json for skriving + + + + Author: + Forfatter: + + + + Directory does not exist: + Direktory eksisterer ikke: + + + + Failed to open files.json for reading. + Kunne ikke åpne files.json for lesing. + + + + Name: + Navn: + + + + Can't apply cheats before the game is started + Kan ikke bruke juksetriks før spillet er startet. + + + + SettingsDialog + + + Save + Lag + + + + Apply + Bruk + + + + Restore Defaults + Gjenopprett standardinnstillinger + + + + Close + Lukk + + + + Point your mouse at an option to display its description. + Hold musen over et valg for at 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 + Emulatorspråk:\nAngir språket for emulatorens brukergrensesnitt. + + + + fullscreenCheckBox + Aktiver fullskjerm:\nSetter automatisk spillvinduet i fullskjermmodus.\nDette kan slås av ved å trykke på F11-tasten. + + + + separateUpdatesCheckBox + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + + + + showSplashCheckBox + Vis startskjerm:\nViser spillets startskjerm (et spesialbilde) når spillet starter. + + + + ps4proCheckBox + Er PS4 Pro:\nFår emulatoren til å fungere som en PS4 PRO, noe som kan aktivere spesielle funksjoner i spill som støtter det. + + + + discordRPCCheckbox + Aktiver Discord Rich Presence:\nViser emulatorikonet og relevant informasjon på Discord-profilen din. + + + + userName + Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill. + + + + logTypeGroupBox + Logtype:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter på emulering. + + + + 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. + + + + 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, aktiverer det å spille spesiell musikk når du velger spillet i GUI. + + + + hideCursorGroupBox + Skjul musepeker:\nVelg når musepekeren skal forsvinne:\nAldri: Du vil alltid se musen.\nInaktiv: Sett en tid for at den skal forsvinne etter å ha vært inaktiv.\nAlltid: du vil aldri se musen. + + + + idleTimeoutGroupBox + Sett en tid for når musen 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. + + + + 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 + Grafikkdevice:\nI systemer med flere GPU-er, velg GPU-en emulatoren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å bestemme det automatisk. + + + + resolutionLayout + Bredde/Høyde:\nAngir størrelsen på emulatorkvinduet ved oppstart, som kan endres under spillingen.\nDette er forskjellig fra oppløsningen i spillet. + + + + heightDivider + Vblank divider:\nBilderaten som emulatoren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten på spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! + + + + dumpShadersCheckBox + Aktiver shaderdumping:\nFor teknisk feilsøking lagrer shaderne fra spillet i en mappe mens de gjengis. + + + + nullGpuCheckBox + Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillrendering som om det ikke var noe grafikkort. + + + + gameFoldersBox + Spillmapper:\nListen over mapper for å sjekke installerte spill. + + + + addFolderButton + Legg til:\nLegg til en mappe til listen. + + + + removeFolderButton + Fjern:\nFjern en mappe fra listen. + + + + debugDump + Aktiver feilsøking dumping:\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-rendereren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre emuleringens oppførsel. + + + + vkSyncValidationCheckBox + Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer timingen av Vulkan-renderingsoppgaver. Dette vil redusere ytelsen og sannsynligvis endre emuleringens oppførsel. + + + + rdocCheckBox + Aktiver RenderDoc feilsøking:\nHvis aktivert, vil emulatoren gi kompatibilitet med Renderdoc for å tillate opptak og analyse av det nåværende renderte bildet. + + + + GameListFrame + + + Icon + Ikon + + + + Name + Navn + + + + Serial + Serienummer + + + + Region + Region + + + + Firmware + Firmware + + + + Size + Størrelse + + + + Version + Versjon + + + + Path + Sti + + + + Play Time + Spilletid + + + + CheckUpdate + + + Auto Updater + Automatisk oppdaterer + + + + Error + Feil + + + + Network error: + Nettverksfeil: + + + + Failed to parse update information. + Kunne ikke analysere oppdateringsinformasjonen. + + + + 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 + Sjekk 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 + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts new file mode 100644 index 000000000..c4f49b93e --- /dev/null +++ b/src/qt_gui/translations/nl.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Cheats / Patches + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Invoer + + + + Cursor + Cursor + + + + Hide Cursor + Cursor verbergen + + + + Hide Cursor Idle Timeout + Inactiviteit timeout voor het verbergen van de cursor + + + + 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 + + + + Play title music + Titelmuziek afspelen + + + + Volume + Volume + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches zijn experimenteel.\nGebruik met voorzichtigheid.\n\nDownload cheats afzonderlijk door het repository te selecteren en op de downloadknop te klikken.\nOp het tabblad Patches kun je alle patches tegelijk downloaden, kiezen welke je wilt gebruiken en je selectie opslaan.\n\nAangezien wij de Cheats/Patches niet ontwikkelen,\nmeld problemen bij de auteur van de cheat.\n\nHeb je een nieuwe cheat gemaakt? Bezoek:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Geen afbeelding beschikbaar + + + + Serial: + Serie: + + + + Version: + Versie: + + + + Size: + Grootte: + + + + Select Cheat File: + Selecteer cheatbestand: + + + + Repository: + Repository: + + + + Download Cheats + Download cheats + + + + Delete File + Bestand verwijderen + + + + No files selected. + Geen bestanden geselecteerd. + + + + You can delete the cheats you don't want after downloading them. + Je kunt de cheats die je niet wilt verwijderen nadat je ze hebt gedownload. + + + + Do you want to delete the selected file?\n%1 + Wil je het geselecteerde bestand verwijderen?\n%1 + + + + Select Patch File: + Selecteer patchbestand: + + + + Download Patches + Download patches + + + + Save + Opslaan + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Fout + + + + No patch selected. + Geen patch geselecteerd. + + + + Unable to open files.json for reading. + Kan files.json niet openen voor lezen. + + + + No patch file found for the current serial. + Geen patchbestand gevonden voor het huidige serienummer. + + + + Unable to open the file for reading. + Kan het bestand niet openen voor lezen. + + + + Unable to open the file for writing. + Kan het bestand niet openen voor schrijven. + + + + Failed to parse XML: + XML parsing mislukt: + + + + Success + Succes + + + + Options saved successfully. + Opties succesvol opgeslagen. + + + + Invalid Source + Ongeldige bron + + + + The selected source is invalid. + De geselecteerde bron is ongeldig. + + + + File Exists + Bestand bestaat + + + + File already exists. Do you want to replace it? + Bestand bestaat al. Wil je het vervangen? + + + + Failed to save file: + Kan bestand niet opslaan: + + + + Failed to download file: + Kan bestand niet downloaden: + + + + Cheats Not Found + Cheats niet gevonden + + + + CheatsNotFound_MSG + Geen cheats gevonden voor deze game in deze versie van de geselecteerde repository.Probeer een andere repository of een andere versie van het spel. + + + + Cheats Downloaded Successfully + Cheats succesvol gedownload + + + + CheatsDownloadedSuccessfully_MSG + Je hebt cheats succesvol gedownload voor deze versie van het spel uit de geselecteerde repository. Je kunt proberen te downloaden van een andere repository. Als deze beschikbaar is, kan het ook worden gebruikt door het bestand uit de lijst te selecteren. + + + + Failed to save: + Opslaan mislukt: + + + + Failed to download: + Downloaden mislukt: + + + + Download Complete + Download voltooid + + + + DownloadComplete_MSG + Patches succesvol gedownload! Alle beschikbare patches voor alle spellen zijn gedownload. Het is niet nodig om ze afzonderlijk te downloaden voor elk spel dat cheats heeft. Als de patch niet verschijnt, kan het zijn dat deze niet bestaat voor het specifieke serienummer en de versie van het spel. Het kan nodig zijn om het spel bij te werken. + + + + Failed to parse JSON data from HTML. + Kan JSON-gegevens uit HTML niet parseren. + + + + Failed to retrieve HTML page. + Kan HTML-pagina niet ophalen. + + + + Failed to open file: + Kan bestand niet openen: + + + + XML ERROR: + XML FOUT: + + + + Failed to open files.json for writing + Kan files.json niet openen voor schrijven + + + + Author: + Auteur: + + + + Directory does not exist: + Map bestaat niet: + + + + Failed to open files.json for reading. + Kan files.json niet openen voor lezen. + + + + Name: + Naam: + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Pictogram + + + + Name + Naam + + + + Serial + Serienummer + + + + Region + Regio + + + + Firmware + Firmware + + + + Size + Grootte + + + + Version + Versie + + + + Path + Pad + + + + Play Time + Speeltijd + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts new file mode 100644 index 000000000..0f6a928b4 --- /dev/null +++ b/src/qt_gui/translations/pl_PL.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + O programie + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 to eksperymentalny otwartoźródłowy emulator konsoli PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + To oprogramowanie nie służy do grania w gry pochodzące z nielegalnego źródła. + + + + ElfViewer + + + Open Folder + Otwórz folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Ładowanie listy gier, proszę poczekaj :3 + + + + Cancel + Anuluj + + + + Loading... + Ładowanie... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Wybierz katalog + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Wybierz katalog + + + + Directory to install games + Katalog do instalacji gier + + + + Browse + Przeglądaj + + + + Error + Błąd + + + + The value for location to install games is not valid. + Podana ścieżka do instalacji gier nie jest prawidłowa. + + + + GuiContextMenus + + + Create Shortcut + Utwórz skrót + + + + Open Game Folder + Otwórz katalog gry + + + + Cheats / Patches + Kody / poprawki + + + + SFO Viewer + Menedżer plików SFO + + + + Trophy Viewer + Menedżer trofeów + + + + Copy info + Kopiuj informacje + + + + Copy Name + Kopiuj nazwę + + + + Copy Serial + Kopiuj numer seryjny + + + + Copy All + Kopiuj wszystko + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Tworzenie skrótu + + + + Shortcut created successfully!\n %1 + Utworzenie skrótu zakończone pomyślnie!\n %1 + + + + Error + Błąd + + + + Error creating shortcut!\n %1 + Utworzenie skrótu zakończone niepowodzeniem!\n %1 + + + + Install PKG + Zainstaluj PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Otwórz folder + + + + TrophyViewer + + + Trophy Viewer + Menedżer trofeów + + + + SettingsDialog + + + Settings + Ustawienia + + + + General + Ogólne + + + + System + System + + + + Console Language + Język konsoli + + + + Emulator Language + Język emulatora + + + + Emulator + Emulator + + + + Enable Fullscreen + Włącz pełny ekran + + + + 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 + + + + Logger + Dziennik zdarzeń + + + + Log Type + Typ dziennika + + + + Log Filter + Filtrowanie dziennika + + + + Input + Wejście + + + + Cursor + Kursor + + + + Hide Cursor + Ukryj kursor + + + + Hide Cursor Idle Timeout + Czas oczekiwania na ukrycie kursora przy bezczynności + + + + 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 + + + + Play title music + Odtwórz muzykę tytułową + + + + Volume + Głośność + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Kody / poprawki + + + + defaultTextEdit_MSG + Cheaty/Patche są eksperymentalne.\nUżywaj ich ostrożnie.\n\nPobierz cheaty pojedynczo, wybierając repozytorium i klikając przycisk pobierania.\nNa zakładce Patches możesz pobrać wszystkie patche jednocześnie, wybrać, które chcesz używać, i zapisać wybór.\n\nPonieważ nie rozwijamy Cheats/Patches,\nproszę zgłosić problemy do autora cheatu.\n\nStworzyłeś nowy cheat? Odwiedź:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Brak dostępnego obrazu + + + + Serial: + Numer seryjny: + + + + Version: + Wersja: + + + + Size: + Rozmiar: + + + + Select Cheat File: + Wybierz plik kodu: + + + + Repository: + Repozytorium: + + + + Download Cheats + Pobierz kody + + + + Remove Old Files + Usuń stare pliki + + + + Do you want to delete the files after downloading them? + Czy chcesz usunąć pliki po ich pobraniu? + + + + Do you want to delete the files after downloading them?\n%1 + Czy chcesz usunąć pliki po ich pobraniu?\n%1 + + + + Do you want to delete the selected file?\n%1 + Czy chcesz usunąć wybrany plik?\n%1 + + + + Select Patch File: + Wybierz plik poprawki: + + + + Download Patches + Pobierz poprawki + + + + Save + Zapisz + + + + Cheats + Kody + + + + Patches + Poprawki + + + + Error + Błąd + + + + No patch selected. + Nie wybrano poprawki. + + + + Unable to open files.json for reading. + Nie można otworzyć pliku files.json do odczytu. + + + + No patch file found for the current serial. + Nie znaleziono pliku poprawki dla bieżącego numeru seryjnego. + + + + Unable to open the file for reading. + Nie można otworzyć pliku do odczytu. + + + + Unable to open the file for writing. + Nie można otworzyć pliku do zapisu. + + + + Failed to parse XML: + Nie udało się 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. Może być konieczne zaktualizowanie 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Ikona + + + + Name + Nazwa + + + + Serial + Numer seryjny + + + + Region + Region + + + + Firmware + Oprogramowanie + + + + Size + Rozmiar + + + + Version + Wersja + + + + Path + Ścieżka + + + + Play Time + Czas gry + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts new file mode 100644 index 000000000..c1c2c438b --- /dev/null +++ b/src/qt_gui/translations/pt_BR.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Abrir Pasta + + + + GameInfoClass + + + Loading game list, please wait :3 + Carregando a lista de jogos, por favor aguarde :3 + + + + Cancel + Cancelar + + + + Loading... + Carregando... + + + + 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. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Criar Atalho + + + + Open Game Folder + Abrir Pasta do Jogo + + + + Cheats / Patches + Cheats / Patches + + + + SFO Viewer + Visualizador de SFO + + + + Trophy Viewer + Visualizador de Troféu + + + + Copy info + Copiar informação + + + + Copy Name + Copiar Nome + + + + Copy Serial + Copiar Serial + + + + Copy All + Copiar Tudo + + + + Delete... + Deletar... + + + + Delete Game + Deletar Jogo + + + + Delete Update + Deletar Atualização + + + + Delete DLC + Deletar DLC + + + + Shortcut creation + Criação de atalho + + + + Shortcut created successfully!\n %1 + Atalho criado com sucesso!\n %1 + + + + Error + Erro + + + + Error creating shortcut!\n %1 + Erro ao criar atalho!\n %1 + + + + Install PKG + Instalar PKG + + + + 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 + + + + PKGViewer + + + Open Folder + Abrir Pasta + + + + TrophyViewer + + + Trophy Viewer + Visualizador de Troféu + + + + 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 + + + + Logger + Registro + + + + Log Type + Tipo de Registro + + + + Log Filter + Filtro do Registro + + + + Input + Entradas + + + + Cursor + Cursor + + + + Hide Cursor + Ocultar Cursor + + + + Hide Cursor Idle Timeout + Tempo de Inatividade para Ocultar Cursor + + + + 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 + + + + Play title music + Reproduzir música de abertura + + + + Volume + Volume + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + 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. Pode ser necessário atualizar o 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icone + + + + Name + Nome + + + + Serial + Serial + + + + Region + Região + + + + Firmware + Firmware + + + + Size + Tamanho + + + + Version + Versão + + + + Path + Diretório + + + + Play Time + Tempo Jogado + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts new file mode 100644 index 000000000..ffb6b6547 --- /dev/null +++ b/src/qt_gui/translations/ro_RO.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Trapaças / Patches + Coduri / Patch-uri + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Introducere + + + + Cursor + Cursor + + + + Hide Cursor + Ascunde cursorul + + + + Hide Cursor Idle Timeout + Timeout pentru ascunderea cursorului inactiv + + + + 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 + + + + Play title music + Redă muzica titlului + + + + Volume + Volum + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Cheats / Patches + + + + defaultTextEdit_MSG + Cheats/Patches sunt experimentale.\nUtilizați cu prudență.\n\nDescărcați cheats individual prin selectarea depozitului și făcând clic pe butonul de descărcare.\nÎn fila Patches, puteți descărca toate patch-urile deodată, alege pe cele pe care doriți să le utilizați și salvați selecția.\n\nDeoarece nu dezvoltăm Cheats/Patches,\nte rugăm să raportezi problemele autorului cheat-ului.\n\nAi creat un nou cheat? Vizitează:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Nu este disponibilă imaginea + + + + Serial: + Serial: + + + + Version: + Versiune: + + + + Size: + Dimensiune: + + + + Select Cheat File: + Selectează fișierul Cheat: + + + + Repository: + Repository: + + + + Download Cheats + Descarcă Cheats + + + + Delete File + Șterge Fișierul + + + + No files selected. + Nu sunt fișiere selectate. + + + + You can delete the cheats you don't want after downloading them. + Poti șterge cheats-urile pe care nu le dorești după ce le-ai descărcat. + + + + Do you want to delete the selected file?\n%1 + Vrei să ștergi fișierul selectat?\n%1 + + + + Select Patch File: + Selectează fișierul Patch: + + + + Download Patches + Descarcă Patches + + + + Save + Salvează + + + + Cheats + Cheats + + + + Patches + Patches + + + + Error + Eroare + + + + No patch selected. + Nu este selectat niciun patch. + + + + Unable to open files.json for reading. + Imposibil de deschis files.json pentru citire. + + + + No patch file found for the current serial. + Nu s-a găsit niciun fișier patch pentru serialul curent. + + + + Unable to open the file for reading. + Imposibil de deschis fișierul pentru citire. + + + + Unable to open the file for writing. + Imposibil de deschis fișierul pentru scriere. + + + + Failed to parse XML: + Nu s-a reușit pararea XML: + + + + Success + Succes + + + + Options saved successfully. + Opțiunile au fost salvate cu succes. + + + + Invalid Source + Sursă invalidă + + + + The selected source is invalid. + Sursa selectată este invalidă. + + + + File Exists + Fișier existent + + + + File already exists. Do you want to replace it? + Fișierul există deja. Vrei să-l înlocuiești? + + + + Failed to save file: + Nu s-a reușit salvarea fișierului: + + + + Failed to download file: + Nu s-a reușit descărcarea fișierului: + + + + Cheats Not Found + Cheats Nu au fost găsite + + + + CheatsNotFound_MSG + Nu au fost găsite cheats pentru acest joc în această versiune a repository-ului selectat, încearcă un alt repository sau o versiune diferită a jocului. + + + + Cheats Downloaded Successfully + Cheats descărcate cu succes + + + + CheatsDownloadedSuccessfully_MSG + Ai descărcat cu succes cheats-urile pentru această versiune a jocului din repository-ul selectat. Poți încerca descărcarea din alt repository; dacă este disponibil, va fi posibil să-l folosești selectând fișierul din listă. + + + + Failed to save: + Nu s-a reușit salvarea: + + + + Failed to download: + Nu s-a reușit descărcarea: + + + + Download Complete + Descărcare completă + + + + DownloadComplete_MSG + Patches descărcate cu succes! Toate Patches disponibile pentru toate jocurile au fost descărcate; nu este nevoie să le descarci individual pentru fiecare joc, așa cum se întâmplă cu Cheats. Dacă patch-ul nu apare, este posibil să nu existe pentru seria și versiunea specifică a jocului. Poate fi necesar să actualizați jocul. + + + + Failed to parse JSON data from HTML. + Nu s-a reușit pararea datelor JSON din HTML. + + + + Failed to retrieve HTML page. + Nu s-a reușit obținerea paginii HTML. + + + + Failed to open file: + Nu s-a reușit deschiderea fișierului: + + + + XML ERROR: + EROARE XML: + + + + Failed to open files.json for writing + Nu s-a reușit deschiderea files.json pentru scriere + + + + Author: + Autor: + + + + Directory does not exist: + Directorul nu există: + + + + Failed to open files.json for reading. + Nu s-a reușit deschiderea files.json pentru citire. + + + + Name: + Nume: + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Icon + + + + Name + Nume + + + + Serial + Serie + + + + Region + Regiune + + + + Firmware + Firmware + + + + Size + Dimensiune + + + + Version + Versiune + + + + Path + Drum + + + + Play Time + Timp de Joacă + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts new file mode 100644 index 000000000..73263587d --- /dev/null +++ b/src/qt_gui/translations/ru_RU.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + О shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 это экспериментальный эмулятор с открытым исходным кодом для PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + Это програмное обеспечение не должно использоваться для запуска игр, которые вы получили нелегально. + + + + ElfViewer + + + Open Folder + Открыть папку + + + + GameInfoClass + + + Loading game list, please wait :3 + Загрузка списка игр, пожалуйста подождите :3 + + + + Cancel + Отмена + + + + Loading... + Загрузка... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Выберите папку + + + + 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. + Недопустимое значение местоположения для установки игр. + + + + GuiContextMenus + + + Create Shortcut + Создать ярлык + + + + Open Game Folder + Открыть папку с игрой + + + + Cheats / Patches + Читы и патчи + + + + SFO Viewer + Просмотр SFO + + + + Trophy Viewer + Просмотр трофеев + + + + Copy info + Копировать информацию + + + + Copy Name + Копировать имя + + + + Copy Serial + Копировать серийный номер + + + + Copy All + Копировать все + + + + Delete... + Удаление... + + + + Delete Game + Удалить игру + + + + Delete Update + Удалить обновление + + + + Delete DLC + Удалить DLC + + + + Shortcut creation + Создание ярлыка + + + + Shortcut created successfully!\n %1 + Ярлык создан успешно!\n %1 + + + + Error + Ошибка + + + + Error creating shortcut!\n %1 + Ошибка создания ярлыка!\n %1 + + + + 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? + + + + 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 + Панель инструментов + + + + PKGViewer + + + Open Folder + Открыть папку + + + + 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 + Имя пользователя + + + + Logger + Логирование + + + + Log Type + Тип логов + + + + Log Filter + Фильтр логов + + + + Input + Ввод + + + + Cursor + Курсор мыши + + + + Hide Cursor + Скрывать курсор + + + + Hide Cursor Idle Timeout + Тайм-аут скрытия курсора при бездействии + + + + 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 + Интерфейс + + + + Play title music + Играть заглавную музыку + + + + Volume + Громкость + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Читы и патчи + + + + defaultTextEdit_MSG + Читы и патчи экспериментальны.\nИспользуйте с осторожностью.\n\nСкачивайте читы, выбрав репозиторий и нажав на кнопку загрузки.\nВо вкладке "Патчи" вы можете скачать все патчи сразу, выбирать какие вы хотите использовать, и сохранять выбор.\n\nПоскольку мы не разрабатываем читы/патчи,\nпожалуйста сообщайте о проблемах автору чита/патча.\n\nСоздали новый чит? Посетите:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Изображение недоступно + + + + Serial: + Серийный номер: + + + + Version: + Версия: + + + + Size: + Размер: + + + + Select Cheat File: + Выберите файл чита: + + + + Repository: + Репозиторий: + + + + Download Cheats + Скачать читы + + + + Delete File + Удалить файл + + + + No files selected. + Файлы не выбраны. + + + + You can delete the cheats you don't want after downloading them. + Вы можете удалить ненужные читы после их скачивания. + + + + Do you want to delete the selected file?\n%1 + Вы хотите удалить выбранный файл?\n%1 + + + + Select Patch File: + Выберите файл патча: + + + + Download Patches + Скачать патчи + + + + Save + Сохранить + + + + Cheats + Читы + + + + Patches + Патчи + + + + Error + Ошибка + + + + No patch selected. + Патч не выбран. + + + + Unable to open files.json for reading. + Не удалось открыть файл files.json для чтения. + + + + No patch file found for the current serial. + Не найден файл патча для текущего серийного номера. + + + + Unable to open the file for reading. + Не удалось открыть файл для чтения. + + + + Unable to open the file for writing. + Не удалось открыть файл для записи. + + + + Failed to parse XML: + Не удалось разобрать XML: + + + + Success + Успех + + + + Options saved successfully. + Опции успешно сохранены. + + + + Invalid Source + Неверный источник + + + + The selected source is invalid. + Выбранный источник недействителен. + + + + File Exists + Файл существует + + + + File already exists. Do you want to replace it? + Файл уже существует. Хотите заменить его? + + + + Failed to save file: + Не удалось сохранить файл: + + + + Failed to download file: + Не удалось скачать файл: + + + + Cheats Not Found + Читы не найдены + + + + CheatsNotFound_MSG + Читы не найдены для этой игры в выбранном репозитории. Попробуйте другой репозиторий или другую версию игры. + + + + Cheats Downloaded Successfully + Читы успешно скачаны + + + + CheatsDownloadedSuccessfully_MSG + Вы успешно скачали читы для этой версии игры из выбранного репозитория. Вы можете попробовать скачать из другого репозитория. Если он доступен, его также можно будет использовать, выбрав файл из списка. + + + + Failed to save: + Не удалось сохранить: + + + + Failed to download: + Не удалось скачать: + + + + Download Complete + Скачивание завершено + + + + DownloadComplete_MSG + Патчи успешно скачаны! Все доступные патчи для всех игр были скачаны, нет необходимости скачивать их по отдельности для каждой игры, как это происходит с читами. Если патч не появляется, возможно, его не существует для конкретного серийного номера и версии игры. Возможно, потребуется обновить игру. + + + + Failed to parse JSON data from HTML. + Не удалось разобрать данные JSON из HTML. + + + + Failed to retrieve HTML page. + Не удалось получить HTML-страницу. + + + + Failed to open file: + Не удалось открыть файл: + + + + XML ERROR: + ОШИБКА XML: + + + + Failed to open files.json for writing + Не удалось открыть файл files.json для записи + + + + Author: + Автор: + + + + Directory does not exist: + Каталог не существует: + + + + Failed to open files.json for reading. + Не удалось открыть файл files.json для чтения. + + + + Name: + Имя: + + + + 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Включает воспроизведение специальной музыки при выборе игры в списке, если она это поддерживает. + + + + hideCursorGroupBox + Скрывать курсор:\nВыберите, когда курсор исчезнет:\nНикогда: Вы всегда будете видеть мышь.\nПри бездействии: Установите время, через которое курсор исчезнет при бездействии.\nВсегда: Вы никогда не будете видеть мышь. + + + + idleTimeoutGroupBox + Установите время, через которое курсор исчезнет при бездействии. + + + + backButtonBehaviorGroupBox + Поведение кнопки «Назад»:\nНастраивает кнопку «Назад» контроллера на эмуляцию нажатия на указанную область на сенсорной панели контроллера PS4. + + + + 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, позволяя захватывать и анализировать текущие кадры во время рендеринга. + + + + GameListFrame + + + Icon + Иконка + + + + Name + Название + + + + Serial + Серийный номер + + + + Region + Регион + + + + Firmware + Прошивка + + + + Size + Размер + + + + Version + Версия + + + + Path + Путь + + + + Play Time + Времени в игре + + + + 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 + Не удалось создать файл скрипта обновления + + + \ No newline at end of file diff --git a/src/qt_gui/translations/sq.ts b/src/qt_gui/translations/sq.ts new file mode 100644 index 000000000..fd835cb81 --- /dev/null +++ b/src/qt_gui/translations/sq.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Hap Dosjen + + + + GameInfoClass + + + Loading game list, please wait :3 + Po ngarkohet lista e lojërave, të lutem prit :3 + + + + Cancel + Anulo + + + + Loading... + Duke ngarkuar... + + + + 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. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Krijo Shkurtore + + + + Open Game Folder + Hap Dosjen e Lojës + + + + Cheats / Patches + Mashtrime / Arna + + + + SFO Viewer + Shikuesi i SFO + + + + Trophy Viewer + Shikuesi i Trofeve + + + + Copy info + Kopjo informacionin + + + + Copy Name + Kopjo Emrin + + + + Copy Serial + Kopjo Serikun + + + + Copy All + Kopjo të Gjitha + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Krijim i shkurtores + + + + Shortcut created successfully!\n %1 + Shkurtorja u krijua me sukses!\n %1 + + + + Error + Gabim + + + + Error creating shortcut!\n %1 + Gabim në krijimin e shkurtores!\n %1 + + + + Install PKG + Instalo 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? + + + + 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... + Formëso... + + + + 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 + + + + Grid View + Pamja e Rrjetës + + + + Elf Viewer + 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 + + + + PKGViewer + + + Open Folder + Hap Dosjen + + + + TrophyViewer + + + Trophy Viewer + Shikuesi i Trofeve + + + + 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 + Enable Separate Update Folder + + + + Show Splash + Shfaq Pamjen e nisjes + + + + Is PS4 Pro + Mënyra PS4 Pro + + + + Enable Discord Rich Presence + Aktivizo Discord Rich Presence + + + + Username + Përdoruesi + + + + Logger + Regjistruesi i ditarit + + + + Log Type + Lloji i Ditarit + + + + Log Filter + Filtri i Ditarit + + + + Input + Hyrja + + + + Cursor + Kursori + + + + Hide Cursor + Fshih kursorin + + + + Hide Cursor Idle Timeout + Koha për fshehjen e kursorit joaktiv + + + + 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 + + + + Play title music + Luaj muzikën e titullit + + + + Volume + Vëllimi i zërit + + + + MainWindow + + + 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 + + + + CheatsPatches + + + Cheats / Patches + Mashtrime / Arna + + + + 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 patch-i nuk shfaqet, mund të mos ekzistojë për numrin e serisë dhe versionin specifik të lojës. Mund të jetë e nevojshme të përditësosh lojën. + + + + 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. + + + + 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 se të fillojë loja. + + + + 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 + Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Ikona + + + + Name + Emri + + + + Serial + Seriku + + + + Region + Rajoni + + + + Firmware + Firmueri + + + + Size + Madhësia + + + + Version + Versioni + + + + Path + Shtegu + + + + Play Time + Koha e luajtjes + + + + 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 diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts new file mode 100644 index 000000000..86930764f --- /dev/null +++ b/src/qt_gui/translations/tr_TR.ts @@ -0,0 +1,1456 @@ + + + + + + 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. + + + + ElfViewer + + + Open Folder + Klasörü Aç + + + + GameInfoClass + + + Loading game list, please wait :3 + Oyun listesi yükleniyor, lütfen bekleyin :3 + + + + Cancel + İptal + + + + Loading... + Yükleniyor... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Klasörü Seç + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + 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. + + + + GuiContextMenus + + + Create Shortcut + Kısayol Oluştur + + + + Open Game Folder + Oyun Klasörünü Aç + + + + Cheats / Patches + Hileler / Yamanlar + + + + SFO Viewer + SFO Görüntüleyici + + + + Trophy Viewer + Kupa Görüntüleyici + + + + Copy info + Bilgiyi Kopyala + + + + Copy Name + Adı Kopyala + + + + Copy Serial + Seri Numarasını Kopyala + + + + Copy All + Tümünü Kopyala + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Kısayol oluşturma + + + + Shortcut created successfully!\n %1 + Kısayol başarıyla oluşturuldu!\n %1 + + + + Error + Hata + + + + Error creating shortcut!\n %1 + Kısayol oluşturulurken hata oluştu!\n %1 + + + + Install PKG + PKG Yükle + + + + 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? + + + + 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 + Hileler / Yamanlar İ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 + + + + PKGViewer + + + Open Folder + Klasörü Aç + + + + TrophyViewer + + + Trophy Viewer + Kupa Görüntüleyici + + + + 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 mu + + + + Enable Discord Rich Presence + Discord Rich Presence'i etkinleştir + + + + Username + Kullanıcı Adı + + + + Logger + Kayıt Tutucu + + + + Log Type + Kayıt Türü + + + + Log Filter + Kayıt Filtresi + + + + Input + Girdi + + + + Cursor + İmleç + + + + Hide Cursor + İmleci gizle + + + + Hide Cursor Idle Timeout + İmleç için hareketsizlik zaman aşımı + + + + 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ı + + + + Play title music + Başlık müziğini çal + + + + Volume + Ses seviyesi + + + + MainWindow + + + 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 Yamanları İndir + + + + Download Complete + İndirme Tamamlandı + + + + You have downloaded cheats for all the games you have installed. + Yüklediğiniz tüm oyunlar için hileleri indirdiniz. + + + + Patches Downloaded Successfully! + Yamalar Başarıyla İndirildi! + + + + All Patches available for all games have been downloaded. + Tüm oyunlar için mevcut tüm yamalar indirildi. + + + + Games: + Oyunlar: + + + + PKG File (*.PKG) + PKG Dosyası (*.PKG) + + + + ELF files (*.bin *.elf *.oelf) + ELF Dosyaları (*.bin *.elf *.oelf) + + + + Game Boot + Oyun Başlatma + + + + Only one file can be selected! + Sadece bir dosya seçilebilir! + + + + PKG Extraction + PKG Çıkartma + + + + Patch detected! + Yamanın 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 + Hileler / Yamalar + + + + defaultTextEdit_MSG + Cheats/Patches deneysel niteliktedir.\nDikkatli kullanın.\n\nCheat'leri ayrı ayrı indirerek, depo seçerek ve indirme düğmesine tıklayarak indirin.\nPatches sekmesinde tüm patch'leri bir kerede indirebilir, hangi patch'leri kullanmak istediğinizi seçebilir ve seçiminizi kaydedebilirsiniz.\n\nCheats/Patches'i geliştirmediğimiz için,\nproblemleri cheat yazarına bildirin.\n\nYeni bir cheat mi oluşturduğunuz? Şu adresi ziyaret edin:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Görüntü Mevcut Değil + + + + Serial: + Seri Numarası: + + + + Version: + Sürüm: + + + + Size: + Boyut: + + + + Select Cheat File: + Hile Dosyasını Seçin: + + + + Repository: + Depo: + + + + Download Cheats + Hileleri İndir + + + + 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ını okumak için açılamadı. + + + + No patch file found for the current serial. + Mevcut seri numarası için hiç yama dosyası bulunamadı. + + + + Unable to open the file for reading. + Dosya okumak için açılamadı. + + + + Unable to open the file for writing. + Dosya yazmak için açılamadı. + + + + Failed to parse XML: + XML ayrıştırılamadı: + + + + Success + Başarı + + + + Options saved successfully. + Ayarlar başarıyla kaydedildi. + + + + Invalid Source + Geçersiz Kaynak + + + + The selected source is invalid. + Seçilen kaynak geçersiz. + + + + File Exists + Dosya Var + + + + File already exists. Do you want to replace it? + Dosya zaten var. Üzerine yazmak ister misiniz? + + + + Failed to save file: + Dosya kaydedilemedi: + + + + Failed to download file: + Dosya indirilemedi: + + + + Cheats Not Found + Hileler Bulunamadı + + + + CheatsNotFound_MSG + Bu oyun için seçilen depoda hile bulunamadı.Başka bir depo veya oyun sürümü deneyin. + + + + Cheats Downloaded Successfully + Hileler Başarıyla İndirildi + + + + CheatsDownloadedSuccessfully_MSG + Bu oyun sürümü için hileleri başarıyla indirdiniz. Başka bir depodan indirmeyi deneyebilirsiniz. Eğer mevcutsa, listeden dosyayı seçerek de kullanılabilir. + + + + Failed to save: + Kaydedilemedi: + + + + Failed to download: + İndirilemedi: + + + + Download Complete + İndirme Tamamlandı + + + + DownloadComplete_MSG + Yamalar başarıyla indirildi! Tüm oyunlar için mevcut tüm yamalar indirildi, her oyun için ayrı ayrı indirme yapmanız gerekmez, hilelerle olduğu gibi. Yamanın görünmemesi durumunda, belirli seri numarası ve oyun sürümü için mevcut olmayabilir. Oyunu güncellemeniz gerekebilir. + + + + Failed to parse JSON data from HTML. + HTML'den JSON verileri ayrıştırılamadı. + + + + Failed to retrieve HTML page. + HTML sayfası alınamadı. + + + + Failed to open file: + Dosya açılamadı: + + + + XML ERROR: + XML HATASI: + + + + Failed to open files.json for writing + files.json dosyası yazmak için açılamadı + + + + Author: + Yazar: + + + + Directory does not exist: + Klasör mevcut değil: + + + + Failed to open files.json for reading. + files.json dosyası okumak için açılamadı. + + + + Name: + İsim: + + + + 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 Mu:\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. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Simge + + + + Name + Ad + + + + Serial + Seri Numarası + + + + Region + Bölge + + + + Firmware + Yazılım + + + + Size + Boyut + + + + Version + Sürüm + + + + Path + Yol + + + + Play Time + Oynama Süresi + + + + 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ı + + + \ No newline at end of file diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts new file mode 100644 index 000000000..8bc241ece --- /dev/null +++ b/src/qt_gui/translations/vi_VN.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Mẹo / Bản vá + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + Đầu vào + + + + Cursor + Con trỏ + + + + Hide Cursor + Ẩn con trỏ + + + + Hide Cursor Idle Timeout + Thời gian chờ ẩn con trỏ + + + + 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 + + + + Play title music + Phát nhạc tiêu đề + + + + Volume + Âm lượng + + + + MainWindow + + + 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ệ + + + + CheatsPatches + + + Cheats / Patches + Cheat / Bản vá + + + + defaultTextEdit_MSG + Cheats/Patches là các tính năng thử nghiệm.\nHãy sử dụng cẩn thận.\n\nTải xuống các cheat riêng lẻ bằng cách chọn kho lưu trữ và nhấp vào nút tải xuống.\nTại tab Patches, bạn có thể tải xuống tất cả các patch cùng một lúc, chọn cái nào bạn muốn sử dụng và lưu lựa chọn của mình.\n\nVì chúng tôi không phát triển Cheats/Patches,\nxin vui lòng báo cáo các vấn đề cho tác giả cheat.\n\nBạn đã tạo ra một cheat mới? Truy cập:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + Không có hình ảnh + + + + Serial: + Số seri: + + + + Version: + Phiên bản: + + + + Size: + Kích thước: + + + + Select Cheat File: + Chọn tệp Cheat: + + + + Repository: + Kho lưu trữ: + + + + Download Cheats + Tải xuống Cheat + + + + Delete File + Xóa tệp + + + + No files selected. + Không có tệp nào được chọn. + + + + You can delete the cheats you don't want after downloading them. + Bạn có thể xóa các cheat không muốn sau khi tải xuống. + + + + Do you want to delete the selected file?\n%1 + Bạn có muốn xóa tệp đã chọn?\n%1 + + + + Select Patch File: + Chọn tệp Bản vá: + + + + Download Patches + Tải xuống Bản vá + + + + Save + Lưu + + + + Cheats + Cheat + + + + Patches + Bản vá + + + + Error + Lỗi + + + + No patch selected. + Không có bản vá nào được chọn. + + + + Unable to open files.json for reading. + Không thể mở files.json để đọc. + + + + No patch file found for the current serial. + Không tìm thấy tệp bản vá cho số seri hiện tại. + + + + Unable to open the file for reading. + Không thể mở tệp để đọc. + + + + Unable to open the file for writing. + Không thể mở tệp để ghi. + + + + Failed to parse XML: + Không thể phân tích XML: + + + + Success + Thành công + + + + Options saved successfully. + Các tùy chọn đã được lưu thành công. + + + + Invalid Source + Nguồn không hợp lệ + + + + The selected source is invalid. + Nguồn đã chọn không hợp lệ. + + + + File Exists + Tệp đã tồn tại + + + + File already exists. Do you want to replace it? + Tệp đã tồn tại. Bạn có muốn thay thế nó không? + + + + Failed to save file: + Không thể lưu tệp: + + + + Failed to download file: + Không thể tải xuống tệp: + + + + Cheats Not Found + Không tìm thấy Cheat + + + + CheatsNotFound_MSG + Không tìm thấy Cheat cho trò chơi này trong phiên bản kho lưu trữ đã chọn,hãy thử kho lưu trữ khác hoặc phiên bản khác của trò chơi. + + + + Cheats Downloaded Successfully + Cheat đã tải xuống thành công + + + + CheatsDownloadedSuccessfully_MSG + Bạn đã tải xuống các cheat thành công. Cho phiên bản trò chơi này từ kho lưu trữ đã chọn. Bạn có thể thử tải xuống từ kho lưu trữ khác, nếu có, bạn cũng có thể sử dụng bằng cách chọn tệp từ danh sách. + + + + Failed to save: + Không thể lưu: + + + + Failed to download: + Không thể tải xuống: + + + + Download Complete + Tải xuống hoàn tất + + + + DownloadComplete_MSG + Bản vá đã tải xuống thành công! Tất cả các bản vá có sẵn cho tất cả các trò chơi đã được tải xuống, không cần tải xuống riêng lẻ cho mỗi trò chơi như trong Cheat. 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. Có thể bạn cần phải cập nhật 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. + + + + 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ị. + + + + 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. + + + + 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. + + + + 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. + + + + GameListFrame + + + Icon + Biểu tượng + + + + Name + Tên + + + + Serial + Số seri + + + + 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 + + + + 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 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts new file mode 100644 index 000000000..bc943c860 --- /dev/null +++ b/src/qt_gui/translations/zh_CN.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + 关于 shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 是一款实验性质的开源 PlayStation 4模拟器软件。 + + + + This software should not be used to play games you have not legally obtained. + 本软件不得用于运行未经合法授权而获得的游戏。 + + + + ElfViewer + + + Open Folder + 打开文件夹 + + + + GameInfoClass + + + Loading game list, please wait :3 + 加载游戏列表中, 请稍等 :3 + + + + Cancel + 取消 + + + + Loading... + 加载中... + + + + 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. + 游戏安装位置无效。 + + + + GuiContextMenus + + + Create Shortcut + 创建快捷方式 + + + + Open Game Folder + 打开游戏文件夹 + + + + Cheats / Patches + 作弊码 / 补丁 + + + + SFO Viewer + SFO 查看器 + + + + Trophy Viewer + Trophy 查看器 + + + + Copy info + 复制信息 + + + + Copy Name + 复制名称 + + + + Copy Serial + 复制序列号 + + + + Copy All + 复制全部 + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + 创建快捷方式 + + + + Shortcut created successfully!\n %1 + 创建快捷方式成功!\n %1 + + + + Error + 错误 + + + + Error creating shortcut!\n %1 + 创建快捷方式出错!\n %1 + + + + 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? + + + + MainWindow + + + Open/Add Elf Folder + 打开/添加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 + 工具栏 + + + + PKGViewer + + + Open Folder + 打开文件夹 + + + + TrophyViewer + + + Trophy Viewer + Trophy 查看器 + + + + 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 + 用户名 + + + + Logger + 日志 + + + + Log Type + 日志类型 + + + + Log Filter + 日志过滤 + + + + Input + 输入 + + + + Cursor + 光标 + + + + Hide Cursor + 隐藏光标 + + + + Hide Cursor Idle Timeout + 光标空闲超时隐藏 + + + + 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 + 界面设置 + + + + Play title music + 播放标题音乐 + + + + Volume + 音量 + + + + MainWindow + + + 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 文件 + + + + CheatsPatches + + + Cheats / Patches + 作弊码 / 补丁 + + + + defaultTextEdit_MSG + 作弊/补丁是实验性的。\n请小心使用。\n\n通过选择存储库并点击下载按钮,单独下载作弊程序。\n在“补丁”选项卡中,您可以一次性下载所有补丁,选择要使用的补丁并保存选择。\n\n由于我们不开发作弊程序/补丁,\n请将问题报告给作弊程序的作者。\n\n创建了新的作弊程序?访问:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + 没有可用的图像 + + + + Serial: + 序列号: + + + + Version: + 版本: + + + + Size: + 大小: + + + + Select Cheat File: + 选择作弊码文件: + + + + Repository: + 存储库: + + + + Download Cheats + 下载作弊码 + + + + Delete File + 删除文件 + + + + No files selected. + 没有选择文件。 + + + + You can delete the cheats you don't want after downloading them. + 您可以在下载后删除不想要的作弊码。 + + + + Do you want to delete the selected file?\n%1 + 您要删除选中的文件吗?\n%1 + + + + Select Patch File: + 选择补丁文件: + + + + Download Patches + 下载补丁 + + + + Save + 保存 + + + + Cheats + 作弊码 + + + + Patches + 补丁 + + + + Error + 错误 + + + + No patch selected. + 没有选择补丁。 + + + + Unable to open files.json for reading. + 无法打开 files.json 进行读取。 + + + + No patch file found for the current serial. + 未找到当前序列号的补丁文件。 + + + + Unable to open the file for reading. + 无法打开文件进行读取。 + + + + Unable to open the file for writing. + 无法打开文件进行写入。 + + + + Failed to parse XML: + 解析 XML 失败: + + + + Success + 成功 + + + + Options saved successfully. + 选项已成功保存。 + + + + Invalid Source + 无效的来源 + + + + The selected source is invalid. + 选择的来源无效。 + + + + File Exists + 文件已存在 + + + + File already exists. Do you want to replace it? + 文件已存在。您要替换它吗? + + + + Failed to save file: + 保存文件失败: + + + + Failed to download file: + 下载文件失败: + + + + Cheats Not Found + 未找到作弊码 + + + + CheatsNotFound_MSG + 在所选存储库的版本中找不到该游戏的作弊码,请尝试其他存储库或游戏版本。 + + + + Cheats Downloaded Successfully + 作弊码下载成功 + + + + CheatsDownloadedSuccessfully_MSG + 您已成功下载了该游戏版本的作弊码 从所选存储库中。如果有,您还可以尝试从其他存储库下载,或通过从列表中选择文件来使用它们。 + + + + Failed to save: + 保存失败: + + + + Failed to download: + 下载失败: + + + + Download Complete + 下载完成 + + + + DownloadComplete_MSG + 补丁下载成功!所有可用的补丁已下载完成,无需像作弊码那样单独下载每个游戏的补丁。如果补丁没有出现,可能是该补丁不存在于特定的序列号和游戏版本中。可能需要更新游戏。 + + + + Failed to parse JSON data from HTML. + 无法解析 HTML 中的 JSON 数据。 + + + + Failed to retrieve HTML page. + 无法获取 HTML 页面。 + + + + Failed to open file: + 无法打开文件: + + + + XML ERROR: + XML 错误: + + + + Failed to open files.json for writing + 无法打开 files.json 进行写入 + + + + Author: + 作者: + + + + Directory does not exist: + 目录不存在: + + + + Failed to open files.json for reading. + 无法打开 files.json 进行读取。 + + + + Name: + 名称: + + + + 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 帐户的用户名。某些游戏中可能会显示此名称。 + + + + 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如果游戏支持,在图形界面选择游戏时启用播放特殊音乐。 + + + + hideCursorGroupBox + 隐藏光标:\n选择光标何时消失:\n从不: 您将始终看到鼠标。\n空闲: 设置光标在空闲后消失的时间。\n始终: 您将永远看不到鼠标。 + + + + idleTimeoutGroupBox + 设置鼠标在空闲后消失的时间。 + + + + backButtonBehaviorGroupBox + 返回按钮行为:\n设置控制器的返回按钮以模拟在 PS4 触控板上指定位置的点击。 + + + + 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 + 序列号 + + + + Region + 区域 + + + + Firmware + 固件 + + + + Size + 大小 + + + + Version + 版本 + + + + Path + 路径 + + + + Play Time + 游戏时间 + + + + 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 + 无法创建更新脚本文件 + + + \ No newline at end of file diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts new file mode 100644 index 000000000..c7b923f83 --- /dev/null +++ b/src/qt_gui/translations/zh_TW.ts @@ -0,0 +1,1456 @@ + + + + + + AboutDialog + + + About shadPS4 + About shadPS4 + + + + shadPS4 + shadPS4 + + + + shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 is an experimental open-source emulator for the PlayStation 4. + + + + This software should not be used to play games you have not legally obtained. + This software should not be used to play games you have not legally obtained. + + + + ElfViewer + + + Open Folder + Open Folder + + + + GameInfoClass + + + Loading game list, please wait :3 + Loading game list, please wait :3 + + + + Cancel + Cancel + + + + Loading... + Loading... + + + + InstallDirSelect + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Select which directory you want to install to. + Select which directory you want to install to. + + + + GameInstallDialog + + + shadPS4 - Choose directory + shadPS4 - Choose directory + + + + Directory to install games + Directory to install games + + + + Browse + Browse + + + + Error + Error + + + + The value for location to install games is not valid. + The value for location to install games is not valid. + + + + GuiContextMenus + + + Create Shortcut + Create Shortcut + + + + Open Game Folder + Open Game Folder + + + + Cheats / Patches + Zuòbì / Xiūbǔ chéngshì + + + + SFO Viewer + SFO Viewer + + + + Trophy Viewer + Trophy Viewer + + + + Copy info + Copy info + + + + Copy Name + Copy Name + + + + Copy Serial + Copy Serial + + + + Copy All + Copy All + + + + Delete... + Delete... + + + + Delete Game + Delete Game + + + + Delete Update + Delete Update + + + + Delete DLC + Delete DLC + + + + Shortcut creation + Shortcut creation + + + + Shortcut created successfully!\n %1 + Shortcut created successfully!\n %1 + + + + Error + Error + + + + Error creating shortcut!\n %1 + Error creating shortcut!\n %1 + + + + Install PKG + Install PKG + + + + 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? + + + + 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 + + + + PKGViewer + + + Open Folder + Open Folder + + + + TrophyViewer + + + Trophy Viewer + Trophy Viewer + + + + SettingsDialog + + + Settings + Settings + + + + General + General + + + + System + System + + + + Console Language + Console Language + + + + Emulator Language + Emulator Language + + + + Emulator + Emulator + + + + Enable Fullscreen + Enable Fullscreen + + + + 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 + + + + Logger + Logger + + + + Log Type + Log Type + + + + Log Filter + Log Filter + + + + Input + 輸入 + + + + Cursor + 游標 + + + + Hide Cursor + 隱藏游標 + + + + Hide Cursor Idle Timeout + 游標空閒超時隱藏 + + + + 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 + 介面設置 + + + + Play title music + 播放標題音樂 + + + + Volume + 音量 + + + + MainWindow + + + 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 檔案 + + + + CheatsPatches + + + Cheats / Patches + 作弊碼 / 修補檔 + + + + defaultTextEdit_MSG + 作弊/補丁為實驗性功能。\n請小心使用。\n\n透過選擇儲存庫並點擊下載按鈕來單獨下載作弊程式。\n在“補丁”標籤頁中,您可以一次下載所有補丁,選擇要使用的補丁並保存您的選擇。\n\n由於我們不開發作弊/補丁,\n請將問題報告給作弊程式的作者。\n\n創建了新的作弊程式?請訪問:\nhttps://github.com/shadps4-emu/ps4_cheats + + + + No Image Available + 沒有可用的圖片 + + + + Serial: + 序號: + + + + Version: + 版本: + + + + Size: + 大小: + + + + Select Cheat File: + 選擇作弊檔案: + + + + Repository: + 儲存庫: + + + + Download Cheats + 下載作弊碼 + + + + Delete File + 刪除檔案 + + + + No files selected. + 沒有選擇檔案。 + + + + You can delete the cheats you don't want after downloading them. + 您可以在下載後刪除不需要的作弊碼。 + + + + Do you want to delete the selected file?\n%1 + 您是否要刪除選定的檔案?\n%1 + + + + Select Patch File: + 選擇修補檔案: + + + + Download Patches + 下載修補檔 + + + + Save + 儲存 + + + + Cheats + 作弊碼 + + + + Patches + 修補檔 + + + + Error + 錯誤 + + + + No patch selected. + 未選擇修補檔。 + + + + Unable to open files.json for reading. + 無法打開 files.json 進行讀取。 + + + + No patch file found for the current serial. + 找不到當前序號的修補檔。 + + + + Unable to open the file for reading. + 無法打開檔案進行讀取。 + + + + Unable to open the file for writing. + 無法打開檔案進行寫入。 + + + + Failed to parse XML: + 解析 XML 失敗: + + + + Success + 成功 + + + + Options saved successfully. + 選項已成功儲存。 + + + + Invalid Source + 無效的來源 + + + + The selected source is invalid. + 選擇的來源無效。 + + + + File Exists + 檔案已存在 + + + + File already exists. Do you want to replace it? + 檔案已存在。您是否希望替換它? + + + + Failed to save file: + 無法儲存檔案: + + + + Failed to download file: + 無法下載檔案: + + + + Cheats Not Found + 未找到作弊碼 + + + + CheatsNotFound_MSG + 在此版本的儲存庫中未找到該遊戲的作弊碼,請嘗試另一個儲存庫或不同版本的遊戲。 + + + + Cheats Downloaded Successfully + 作弊碼下載成功 + + + + CheatsDownloadedSuccessfully_MSG + 您已成功下載該遊戲版本的作弊碼 從選定的儲存庫中。 您可以嘗試從其他儲存庫下載,如果可用,您也可以選擇從列表中選擇檔案來使用它。 + + + + Failed to save: + 儲存失敗: + + + + Failed to download: + 下載失敗: + + + + Download Complete + 下載完成 + + + + DownloadComplete_MSG + 修補檔下載成功!所有遊戲的修補檔已下載完成,無需像作弊碼那樣為每個遊戲單獨下載。如果補丁未顯示,可能是該補丁不適用於特定的序號和遊戲版本。可能需要更新遊戲。 + + + + Failed to parse JSON data from HTML. + 無法從 HTML 解析 JSON 數據。 + + + + Failed to retrieve HTML page. + 無法檢索 HTML 頁面。 + + + + Failed to open file: + 無法打開檔案: + + + + XML ERROR: + XML 錯誤: + + + + Failed to open files.json for writing + 無法打開 files.json 進行寫入 + + + + Author: + 作者: + + + + Directory does not exist: + 目錄不存在: + + + + Failed to open files.json for reading. + 無法打開 files.json 進行讀取。 + + + + Name: + 名稱: + + + + 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帳號的用戶名,某些遊戲中可能會顯示。 + + + + 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中選擇遊戲時播放特殊音樂。 + + + + hideCursorGroupBox + 隱藏游標:\n選擇游標何時消失:\n從不: 您將始終看到滑鼠。\n閒置: 設定在閒置後消失的時間。\n始終: 您將永遠看不到滑鼠。 + + + + idleTimeoutGroupBox + 設定滑鼠在閒置後消失的時間。 + + + + backButtonBehaviorGroupBox + 返回按鈕行為:\n設定控制器的返回按鈕模擬在 PS4 觸控板上指定位置的觸碰。 + + + + 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 + 序號 + + + + Region + 區域 + + + + Firmware + 固件 + + + + Size + 大小 + + + + Version + 版本 + + + + Path + 路徑 + + + + Play Time + 遊玩時間 + + + + 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 + 無法創建更新腳本文件 + + + \ No newline at end of file diff --git a/src/qt_gui/trophy_viewer.cpp b/src/qt_gui/trophy_viewer.cpp index bb17dfc3a..49fb993eb 100644 --- a/src/qt_gui/trophy_viewer.cpp +++ b/src/qt_gui/trophy_viewer.cpp @@ -5,11 +5,12 @@ #include "trophy_viewer.h" TrophyViewer::TrophyViewer(QString trophyPath, QString gameTrpPath) : QMainWindow() { - this->setWindowTitle("Trophy Viewer"); + this->setWindowTitle(tr("Trophy Viewer")); this->setAttribute(Qt::WA_DeleteOnClose); tabWidget = new QTabWidget(this); gameTrpPath_ = gameTrpPath; - headers << "Trophy" + headers << "Unlocked" + << "Trophy" << "Name" << "Description" << "ID" @@ -20,23 +21,15 @@ TrophyViewer::TrophyViewer(QString trophyPath, QString gameTrpPath) : QMainWindo } void TrophyViewer::PopulateTrophyWidget(QString title) { -#ifdef _WIN32 - const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "game_data" / - title.toStdWString() / "TrophyFiles"; - const auto trophyDirQt = QString::fromStdWString(trophyDir.wstring()); -#else - const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "game_data" / - title.toStdString() / "TrophyFiles"; - const auto trophyDirQt = QString::fromStdString(trophyDir.string()); -#endif + const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / + Common::FS::PathFromQString(title) / "TrophyFiles"; + QString trophyDirQt; + Common::FS::PathToQString(trophyDirQt, trophyDir); QDir dir(trophyDirQt); if (!dir.exists()) { - std::filesystem::path path(gameTrpPath_.toStdString()); -#ifdef _WIN64 - path = std::filesystem::path(gameTrpPath_.toStdWString()); -#endif - if (!trp.Extract(path)) + std::filesystem::path path = Common::FS::PathFromQString(gameTrpPath_); + if (!trp.Extract(path, title.toStdString())) return; } QFileInfoList dirList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); @@ -61,6 +54,7 @@ void TrophyViewer::PopulateTrophyWidget(QString title) { QStringList trpId; QStringList trpHidden; + QStringList trpUnlocked; QStringList trpType; QStringList trpPid; QStringList trophyNames; @@ -81,6 +75,15 @@ void TrophyViewer::PopulateTrophyWidget(QString title) { trpHidden.append(reader.attributes().value("hidden").toString()); trpType.append(reader.attributes().value("ttype").toString()); trpPid.append(reader.attributes().value("pid").toString()); + if (reader.attributes().hasAttribute("unlockstate")) { + if (reader.attributes().value("unlockstate").toString() == "true") { + trpUnlocked.append("unlocked"); + } else { + trpUnlocked.append("locked"); + } + } else { + trpUnlocked.append("locked"); + } } if (reader.name().toString() == "name" && !trpId.isEmpty()) { @@ -93,7 +96,7 @@ void TrophyViewer::PopulateTrophyWidget(QString title) { } QTableWidget* tableWidget = new QTableWidget(this); tableWidget->setShowGrid(false); - tableWidget->setColumnCount(7); + tableWidget->setColumnCount(8); tableWidget->setHorizontalHeaderLabels(headers); tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); @@ -105,21 +108,22 @@ void TrophyViewer::PopulateTrophyWidget(QString title) { QTableWidgetItem* item = new QTableWidgetItem(); item->setData(Qt::DecorationRole, icon); item->setFlags(item->flags() & ~Qt::ItemIsEditable); - tableWidget->setItem(row, 0, item); + tableWidget->setItem(row, 1, item); if (!trophyNames.isEmpty() && !trophyDetails.isEmpty()) { - SetTableItem(tableWidget, row, 1, trophyNames[row]); - SetTableItem(tableWidget, row, 2, trophyDetails[row]); - SetTableItem(tableWidget, row, 3, trpId[row]); - SetTableItem(tableWidget, row, 4, trpHidden[row]); - SetTableItem(tableWidget, row, 5, GetTrpType(trpType[row].at(0))); - SetTableItem(tableWidget, row, 6, trpPid[row]); + SetTableItem(tableWidget, row, 0, trpUnlocked[row]); + SetTableItem(tableWidget, row, 2, trophyNames[row]); + SetTableItem(tableWidget, row, 3, trophyDetails[row]); + SetTableItem(tableWidget, row, 4, trpId[row]); + SetTableItem(tableWidget, row, 5, trpHidden[row]); + SetTableItem(tableWidget, row, 6, GetTrpType(trpType[row].at(0))); + SetTableItem(tableWidget, row, 7, trpPid[row]); } tableWidget->verticalHeader()->resizeSection(row, icon.height()); row++; } tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); int width = 16; - for (int i = 0; i < 7; i++) { + for (int i = 0; i < 8; i++) { width += tableWidget->horizontalHeader()->sectionSize(i); } tableWidget->resize(width, 720); diff --git a/src/qt_gui/trophy_viewer.h b/src/qt_gui/trophy_viewer.h index 2b794593f..81b9b1adc 100644 --- a/src/qt_gui/trophy_viewer.h +++ b/src/qt_gui/trophy_viewer.h @@ -10,11 +10,9 @@ #include #include #include -#include #include #include #include -#include #include #include "common/types.h" diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index eec31c901..bf29b37f6 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -9,6 +9,7 @@ #include "common/config.h" #include "common/version.h" #include "core/libraries/pad/pad.h" +#include "imgui/renderer/imgui_core.h" #include "input/controller.h" #include "sdl_window.h" #include "video_core/renderdoc.h" @@ -22,7 +23,7 @@ namespace Frontend { WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_, std::string_view window_title) : width{width_}, height{height_}, controller{controller_} { - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (!SDL_Init(SDL_INIT_VIDEO)) { UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError()); } SDL_InitSubSystem(SDL_INIT_AUDIO); @@ -35,6 +36,7 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height); SDL_SetNumberProperty(props, "flags", SDL_WINDOW_VULKAN); + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); if (window == nullptr) { @@ -80,6 +82,10 @@ void WindowSDL::waitEvent() { return; } + if (ImGui::Core::ProcessEvent(&event)) { + return; + } + switch (event.type) { case SDL_EVENT_WINDOW_RESIZED: case SDL_EVENT_WINDOW_MAXIMIZED: @@ -98,6 +104,11 @@ void WindowSDL::waitEvent() { case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: case SDL_EVENT_GAMEPAD_AXIS_MOTION: + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: onGamepadEvent(&event); break; case SDL_EVENT_QUIT: @@ -110,6 +121,7 @@ void WindowSDL::waitEvent() { void WindowSDL::onResize() { SDL_GetWindowSizeInPixels(window, &width, &height); + ImGui::Core::OnResize(); } void WindowSDL::onKeyPress(const SDL_Event* event) { @@ -133,6 +145,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { Input::Axis axis = Input::Axis::AxisMax; int axisvalue = 0; int ax = 0; + std::string backButtonBehavior = Config::getBackButtonBehavior(); switch (event->key.key) { case SDLK_UP: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP; @@ -189,11 +202,6 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; case SDLK_S: - if (event->key.mod == SDL_KMOD_LCTRL) { - // Trigger rdoc capture - VideoCore::TriggerCapture(); - break; - } axis = Input::Axis::LeftY; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += 127; @@ -271,7 +279,30 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { ax = Input::GetAxis(0, 0x80, axisvalue); break; case SDLK_SPACE: - button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; + if (backButtonBehavior != "none") { + float x = backButtonBehavior == "left" ? 0.25f + : (backButtonBehavior == "right" ? 0.75f : 0.5f); + // trigger a touchpad event so that the touchpad emulation for back button works + controller->SetTouchpadState(0, true, x, 0.5f); + button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; + } else { + button = 0; + } + break; + case SDLK_F11: + if (event->type == SDL_EVENT_KEY_DOWN) { + { + SDL_WindowFlags flag = SDL_GetWindowFlags(window); + bool is_fullscreen = flag & SDL_WINDOW_FULLSCREEN; + SDL_SetWindowFullscreen(window, !is_fullscreen); + } + } + break; + case SDLK_F12: + if (event->type == SDL_EVENT_KEY_DOWN) { + // Trigger rdoc capture + VideoCore::TriggerCapture(); + } break; default: break; @@ -290,11 +321,35 @@ void WindowSDL::onGamepadEvent(const SDL_Event* event) { u32 button = 0; Input::Axis axis = Input::Axis::AxisMax; switch (event->type) { + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + controller->TryOpenSDLController(); + break; + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: + controller->SetTouchpadState(event->gtouchpad.finger, + event->type != SDL_EVENT_GAMEPAD_TOUCHPAD_UP, + event->gtouchpad.x, event->gtouchpad.y); + break; case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: button = sdlGamepadToOrbisButton(event->gbutton.button); if (button != 0) { - controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); + if (event->gbutton.button == SDL_GAMEPAD_BUTTON_BACK) { + std::string backButtonBehavior = Config::getBackButtonBehavior(); + if (backButtonBehavior != "none") { + float x = backButtonBehavior == "left" + ? 0.25f + : (backButtonBehavior == "right" ? 0.75f : 0.5f); + // trigger a touchpad event so that the touchpad emulation for back button works + controller->SetTouchpadState(0, true, x, 0.5f); + controller->CheckButton(0, button, + event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); + } + } else { + controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); + } } break; case SDL_EVENT_GAMEPAD_AXIS_MOTION: diff --git a/src/sdl_window.h b/src/sdl_window.h index cf6c37116..2a5aeb38c 100644 --- a/src/sdl_window.h +++ b/src/sdl_window.h @@ -25,9 +25,6 @@ enum class WindowSystemType : u8 { }; struct WindowSystemInfo { - // Window system type. Determines which GL context or Vulkan WSI is used. - WindowSystemType type = WindowSystemType::Headless; - // Connection to a display server. This is used on X11 and Wayland platforms. void* display_connection = nullptr; @@ -38,6 +35,9 @@ struct WindowSystemInfo { // Scale of the render surface. For hidpi systems, this will be >1. float render_surface_scale = 1.0f; + + // Window system type. Determines which GL context or Vulkan WSI is used. + WindowSystemType type = WindowSystemType::Headless; }; class WindowSDL { @@ -58,6 +58,10 @@ public: return is_open; } + [[nodiscard]] SDL_Window* GetSdlWindow() const { + return window; + } + WindowSystemInfo getWindowInfo() const { return window_info; } diff --git a/src/shader_recompiler/backend/bindings.h b/src/shader_recompiler/backend/bindings.h index 1b53c74eb..510b0c0ec 100644 --- a/src/shader_recompiler/backend/bindings.h +++ b/src/shader_recompiler/backend/bindings.h @@ -9,10 +9,10 @@ namespace Shader::Backend { struct Bindings { u32 unified{}; - u32 uniform_buffer{}; - u32 storage_buffer{}; - u32 texture{}; - u32 image{}; + u32 buffer{}; + u32 user_data{}; + + auto operator<=>(const Bindings&) const = default; }; } // namespace Shader::Backend diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index c70427635..e84908a57 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "common/assert.h" #include "common/func_traits.h" #include "shader_recompiler/backend/spirv/emit_spirv.h" #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" @@ -12,10 +13,40 @@ #include "shader_recompiler/frontend/translate/translate.h" #include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/program.h" +#include "video_core/amdgpu/types.h" namespace Shader::Backend::SPIRV { namespace { +static constexpr spv::ExecutionMode GetInputPrimitiveType(AmdGpu::PrimitiveType type) { + switch (type) { + case AmdGpu::PrimitiveType::PointList: + return spv::ExecutionMode::InputPoints; + case AmdGpu::PrimitiveType::LineList: + return spv::ExecutionMode::InputLines; + case AmdGpu::PrimitiveType::TriangleList: + case AmdGpu::PrimitiveType::TriangleStrip: + return spv::ExecutionMode::Triangles; + case AmdGpu::PrimitiveType::AdjTriangleList: + return spv::ExecutionMode::InputTrianglesAdjacency; + default: + UNREACHABLE_MSG("Unknown input primitive type {}", u32(type)); + } +} + +static constexpr spv::ExecutionMode GetOutputPrimitiveType(AmdGpu::GsOutputPrimitiveType type) { + switch (type) { + case AmdGpu::GsOutputPrimitiveType::PointList: + return spv::ExecutionMode::OutputVertices; + case AmdGpu::GsOutputPrimitiveType::LineStrip: + return spv::ExecutionMode::OutputLineStrip; + case AmdGpu::GsOutputPrimitiveType::TriangleStrip: + return spv::ExecutionMode::OutputTriangleStrip; + default: + UNREACHABLE_MSG("Unknown output primitive type {}", u32(type)); + } +} + template void SetDefinition(EmitContext& ctx, IR::Inst* inst, Args... args) { inst->SetDefinition(func(ctx, std::forward(args)...)); @@ -39,6 +70,8 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) { return arg.ScalarReg(); } else if constexpr (std::is_same_v) { return arg.VectorReg(); + } else if constexpr (std::is_same_v) { + return arg.StringLiteral(); } } @@ -99,7 +132,7 @@ Id TypeId(const EmitContext& ctx, IR::Type type) { } } -void Traverse(EmitContext& ctx, IR::Program& program) { +void Traverse(EmitContext& ctx, const IR::Program& program) { IR::Block* current_block{}; for (const IR::AbstractSyntaxNode& node : program.syntax_list) { switch (node.type) { @@ -162,7 +195,7 @@ void Traverse(EmitContext& ctx, IR::Program& program) { } } -Id DefineMain(EmitContext& ctx, IR::Program& program) { +Id DefineMain(EmitContext& ctx, const IR::Program& program) { const Id void_function{ctx.TypeFunction(ctx.void_id)}; const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; for (IR::Block* const block : program.blocks) { @@ -173,28 +206,66 @@ Id DefineMain(EmitContext& ctx, IR::Program& program) { return main; } -void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { - const auto& info = program.info; - const std::span interfaces(ctx.interfaces.data(), ctx.interfaces.size()); - spv::ExecutionModel execution_model{}; +void SetupCapabilities(const Info& info, EmitContext& ctx) { ctx.AddCapability(spv::Capability::Image1D); ctx.AddCapability(spv::Capability::Sampled1D); + ctx.AddCapability(spv::Capability::ImageQuery); if (info.uses_fp16) { ctx.AddCapability(spv::Capability::Float16); ctx.AddCapability(spv::Capability::Int16); } - ctx.AddCapability(spv::Capability::Int64); - if (info.has_storage_images) { - ctx.AddCapability(spv::Capability::StorageImageExtendedFormats); + if (info.uses_fp64) { + ctx.AddCapability(spv::Capability::Float64); } + ctx.AddCapability(spv::Capability::Int64); + if (info.has_storage_images || info.has_image_buffers) { + ctx.AddCapability(spv::Capability::StorageImageExtendedFormats); + ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); + ctx.AddCapability(spv::Capability::StorageImageWriteWithoutFormat); + } + if (info.has_texel_buffers) { + ctx.AddCapability(spv::Capability::SampledBuffer); + } + if (info.has_image_buffers) { + ctx.AddCapability(spv::Capability::ImageBuffer); + } + if (info.has_image_gather) { + ctx.AddCapability(spv::Capability::ImageGatherExtended); + } + if (info.has_image_query) { + ctx.AddCapability(spv::Capability::ImageQuery); + } + if (info.uses_lane_id) { + ctx.AddCapability(spv::Capability::GroupNonUniform); + } + if (info.uses_group_quad) { + ctx.AddCapability(spv::Capability::GroupNonUniformQuad); + } + if (info.uses_group_ballot) { + ctx.AddCapability(spv::Capability::GroupNonUniformBallot); + } + if (info.stage == Stage::Export || info.stage == Stage::Vertex) { + ctx.AddExtension("SPV_KHR_shader_draw_parameters"); + ctx.AddCapability(spv::Capability::DrawParameters); + } + if (info.stage == Stage::Geometry) { + ctx.AddCapability(spv::Capability::Geometry); + } +} + +void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { + const auto& info = program.info; + const std::span interfaces(ctx.interfaces.data(), ctx.interfaces.size()); + spv::ExecutionModel execution_model{}; switch (program.info.stage) { case Stage::Compute: { - const std::array workgroup_size{program.info.workgroup_size}; + const std::array workgroup_size{ctx.runtime_info.cs_info.workgroup_size}; execution_model = spv::ExecutionModel::GLCompute; ctx.AddExecutionMode(main, spv::ExecutionMode::LocalSize, workgroup_size[0], workgroup_size[1], workgroup_size[2]); break; } + case Stage::Export: case Stage::Vertex: execution_model = spv::ExecutionModel::Vertex; break; @@ -205,30 +276,49 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { } else { ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft); } - ctx.AddCapability(spv::Capability::GroupNonUniform); - if (info.uses_group_quad) { - ctx.AddCapability(spv::Capability::GroupNonUniformQuad); - } if (info.has_discard) { + ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); } - if (info.has_image_gather) { - ctx.AddCapability(spv::Capability::ImageGatherExtended); - } - if (info.has_image_query) { - ctx.AddCapability(spv::Capability::ImageQuery); - } if (info.stores.Get(IR::Attribute::Depth)) { ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); } break; + case Stage::Geometry: + execution_model = spv::ExecutionModel::Geometry; + ctx.AddExecutionMode(main, GetInputPrimitiveType(ctx.runtime_info.gs_info.in_primitive)); + ctx.AddExecutionMode(main, + GetOutputPrimitiveType(ctx.runtime_info.gs_info.out_primitive[0])); + ctx.AddExecutionMode(main, spv::ExecutionMode::OutputVertices, + ctx.runtime_info.gs_info.output_vertices); + ctx.AddExecutionMode(main, spv::ExecutionMode::Invocations, + ctx.runtime_info.gs_info.num_invocations); + break; default: throw NotImplementedException("Stage {}", u32(program.info.stage)); } ctx.AddEntryPoint(execution_model, main, "main", interfaces); } -void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { +void SetupFloatMode(EmitContext& ctx, const Profile& profile, const RuntimeInfo& runtime_info, + Id main_func) { + ctx.AddExtension("SPV_KHR_float_controls"); + const auto fp_denorm_mode = runtime_info.fp_denorm_mode32; + if (fp_denorm_mode == AmdGpu::FpDenormMode::InOutFlush) { + if (profile.support_fp32_denorm_flush) { + ctx.AddCapability(spv::Capability::DenormFlushToZero); + ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 32U); + } + } else { + LOG_WARNING(Render_Vulkan, "Unknown FP denorm mode {}", u32(fp_denorm_mode)); + } + const auto fp_round_mode = runtime_info.fp_round_mode32; + if (fp_round_mode != AmdGpu::FpRoundMode::NearestEven) { + LOG_WARNING(Render_Vulkan, "Unknown FP rounding mode {}", u32(fp_round_mode)); + } +} + +void PatchPhiNodes(const IR::Program& program, EmitContext& ctx) { auto inst{program.blocks.front()->begin()}; size_t block_index{0}; ctx.PatchDeferredPhi([&](size_t phi_arg) { @@ -247,15 +337,15 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { } } // Anonymous namespace -std::vector EmitSPIRV(const Profile& profile, IR::Program& program, u32& binding) { - EmitContext ctx{profile, program, binding}; +std::vector EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, + const IR::Program& program, Bindings& binding) { + EmitContext ctx{profile, runtime_info, program.info, binding}; const Id main{DefineMain(ctx, program)}; DefineEntryPoint(program, ctx, main); - if (program.info.stage == Stage::Vertex) { - ctx.AddExtension("SPV_KHR_shader_draw_parameters"); - ctx.AddCapability(spv::Capability::DrawParameters); - } + SetupCapabilities(program.info, ctx); + SetupFloatMode(ctx, profile, runtime_info, main); PatchPhiNodes(program, ctx); + binding.user_data += program.info.ud_mask.NumRegs(); return ctx.Assemble(); } @@ -315,6 +405,10 @@ void EmitGetVccHi(EmitContext& ctx) { UNREACHABLE_MSG("Unreachable instruction"); } +void EmitGetM0(EmitContext& ctx) { + UNREACHABLE_MSG("Unreachable instruction"); +} + void EmitSetScc(EmitContext& ctx) { UNREACHABLE_MSG("Unreachable instruction"); } @@ -339,4 +433,8 @@ void EmitSetVccHi(EmitContext& ctx) { UNREACHABLE_MSG("Unreachable instruction"); } +void EmitSetM0(EmitContext& ctx) { + UNREACHABLE_MSG("Unreachable instruction"); +} + } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index e513975b3..5b8da4496 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h @@ -4,12 +4,13 @@ #pragma once #include +#include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/ir/program.h" #include "shader_recompiler/profile.h" namespace Shader::Backend::SPIRV { -[[nodiscard]] std::vector EmitSPIRV(const Profile& profile, IR::Program& program, - u32& binding); +[[nodiscard]] std::vector EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, + const IR::Program& program, Bindings& binding); } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 37e91d3b1..a58b2778f 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -102,7 +102,7 @@ Id EmitBufferAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addres return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicXor); } -Id EmitBufferAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { +Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicExchange); } @@ -152,4 +152,20 @@ Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id co return ImageAtomicU32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicExchange); } +Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding) { + auto& buffer = ctx.buffers[binding]; + const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, + ctx.ConstU32(gds_addr)); + const auto [scope, semantics]{AtomicArgs(ctx)}; + return ctx.OpAtomicIIncrement(ctx.U32[1], ptr, scope, semantics); +} + +Id EmitDataConsume(EmitContext& ctx, u32 gds_addr, u32 binding) { + auto& buffer = ctx.buffers[binding]; + const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, + ctx.ConstU32(gds_addr)); + const auto [scope, semantics]{AtomicArgs(ctx)}; + return ctx.OpAtomicIDecrement(ctx.U32[1], ptr, scope, semantics); +} + } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp index 03a0a00f0..02ac74e19 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp @@ -14,8 +14,8 @@ Id EmitBitCastU32F32(EmitContext& ctx, Id value) { return ctx.OpBitcast(ctx.U32[1], value); } -void EmitBitCastU64F64(EmitContext&) { - UNREACHABLE_MSG("SPIR-V Instruction"); +Id EmitBitCastU64F64(EmitContext& ctx, Id value) { + return ctx.OpBitcast(ctx.U64, value); } Id EmitBitCastF16U16(EmitContext& ctx, Id value) { @@ -38,6 +38,10 @@ Id EmitUnpackUint2x32(EmitContext& ctx, Id value) { return ctx.OpBitcast(ctx.U32[2], value); } +Id EmitPackFloat2x32(EmitContext& ctx, Id value) { + return ctx.OpBitcast(ctx.F64[1], value); +} + Id EmitPackFloat2x16(EmitContext& ctx, Id value) { return ctx.OpBitcast(ctx.U32[1], value); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 0b02f3a37..2d48999c0 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 @@ -46,47 +46,72 @@ Id OutputAttrPointer(EmitContext& ctx, IR::Attribute attr, u32 element) { if (IR::IsParam(attr)) { const u32 index{u32(attr) - u32(IR::Attribute::Param0)}; const auto& info{ctx.output_params.at(index)}; + ASSERT(info.num_components > 0); if (info.num_components == 1) { return info.id; } else { - return ctx.OpAccessChain(ctx.output_f32, info.id, ctx.ConstU32(element)); + return ctx.OpAccessChain(info.pointer_type, info.id, ctx.ConstU32(element)); + } + } + if (IR::IsMrt(attr)) { + const u32 index{u32(attr) - u32(IR::Attribute::RenderTarget0)}; + const auto& info{ctx.frag_outputs.at(index)}; + if (info.num_components == 1) { + return info.id; + } else { + return ctx.OpAccessChain(info.pointer_type, info.id, ctx.ConstU32(element)); } } switch (attr) { case IR::Attribute::Position0: { return ctx.OpAccessChain(ctx.output_f32, ctx.output_position, ctx.ConstU32(element)); + } case IR::Attribute::Position1: case IR::Attribute::Position2: case IR::Attribute::Position3: { const u32 index = u32(attr) - u32(IR::Attribute::Position1); - return VsOutputAttrPointer(ctx, ctx.info.vs_outputs[index][element]); - } - case IR::Attribute::RenderTarget0: - case IR::Attribute::RenderTarget1: - case IR::Attribute::RenderTarget2: - case IR::Attribute::RenderTarget3: - case IR::Attribute::RenderTarget4: - case IR::Attribute::RenderTarget5: - case IR::Attribute::RenderTarget6: - case IR::Attribute::RenderTarget7: { - const u32 index = u32(attr) - u32(IR::Attribute::RenderTarget0); - if (ctx.frag_num_comp[index] > 1) { - return ctx.OpAccessChain(ctx.output_f32, ctx.frag_color[index], ctx.ConstU32(element)); - } else { - return ctx.frag_color[index]; - } + return VsOutputAttrPointer(ctx, ctx.runtime_info.vs_info.outputs[index][element]); } case IR::Attribute::Depth: return ctx.frag_depth; default: - throw NotImplementedException("Read attribute {}", attr); + throw NotImplementedException("Write attribute {}", attr); } +} + +std::pair OutputAttrComponentType(EmitContext& ctx, IR::Attribute attr) { + if (IR::IsParam(attr)) { + const u32 index{u32(attr) - u32(IR::Attribute::Param0)}; + const auto& info{ctx.output_params.at(index)}; + return {info.component_type, info.is_integer}; + } + if (IR::IsMrt(attr)) { + const u32 index{u32(attr) - u32(IR::Attribute::RenderTarget0)}; + const auto& info{ctx.frag_outputs.at(index)}; + return {info.component_type, info.is_integer}; + } + switch (attr) { + case IR::Attribute::Position0: + case IR::Attribute::Position1: + case IR::Attribute::Position2: + case IR::Attribute::Position3: + case IR::Attribute::Depth: + return {ctx.F32[1], false}; + default: + throw NotImplementedException("Write attribute {}", attr); } } } // Anonymous namespace Id EmitGetUserData(EmitContext& ctx, IR::ScalarReg reg) { - return ctx.ConstU32(ctx.info.user_data[static_cast(reg)]); + const u32 index = ctx.binding.user_data + ctx.info.ud_mask.Index(reg); + const u32 half = PushData::UdRegsIndex + (index >> 2); + const Id ud_ptr{ctx.OpAccessChain(ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1]), + ctx.push_data_block, ctx.ConstU32(half), + ctx.ConstU32(index & 3))}; + const Id ud_reg{ctx.OpLoad(ctx.U32[1], ud_ptr)}; + ctx.Name(ud_reg, fmt::format("ud_{}", u32(reg))); + return ud_reg; } void EmitGetThreadBitScalarReg(EmitContext& ctx) { @@ -133,10 +158,6 @@ Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index) { return ctx.OpLoad(buffer.data_types->Get(1), ptr); } -Id EmitReadConstBufferU32(EmitContext& ctx, u32 handle, Id index) { - return ctx.OpBitcast(ctx.U32[1], EmitReadConstBuffer(ctx, handle, index)); -} - Id EmitReadStepRate(EmitContext& ctx, int rate_idx) { return ctx.OpLoad( ctx.U32[1], ctx.OpAccessChain(ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1]), @@ -144,7 +165,30 @@ Id EmitReadStepRate(EmitContext& ctx, int rate_idx) { rate_idx == 0 ? ctx.u32_zero_value : ctx.u32_one_value)); } -Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) { +Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index) { + if (ctx.info.stage == Stage::Geometry) { + if (IR::IsPosition(attr)) { + ASSERT(attr == IR::Attribute::Position0); + const auto position_arr_ptr = ctx.TypePointer(spv::StorageClass::Input, ctx.F32[4]); + const auto pointer{ctx.OpAccessChain(position_arr_ptr, ctx.gl_in, ctx.ConstU32(index), + ctx.ConstU32(0u))}; + 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))); + } + + 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, ctx.ConstU32(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(); + } + if (IR::IsParam(attr)) { const u32 index{u32(attr) - u32(IR::Attribute::Param0)}; const auto& param{ctx.input_params.at(index)}; @@ -153,17 +197,21 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) { // Attribute is disabled or varying component is not written return ctx.ConstF32(comp == 3 ? 1.0f : 0.0f); } - if (param.is_default) { - return ctx.OpCompositeExtract(param.component_type, param.id, comp); - } - if (param.num_components > 1) { + Id result; + if (param.is_default) { + result = ctx.OpCompositeExtract(param.component_type, param.id, comp); + } else if (param.num_components > 1) { const Id pointer{ ctx.OpAccessChain(param.pointer_type, param.id, ctx.ConstU32(comp))}; - return ctx.OpLoad(param.component_type, pointer); + result = ctx.OpLoad(param.component_type, pointer); } else { - return ctx.OpLoad(param.component_type, param.id); + result = ctx.OpLoad(param.component_type, param.id); } + if (param.is_integer) { + result = ctx.OpBitcast(ctx.F32[1], result); + } + return result; } else { const auto step_rate = EmitReadStepRate(ctx, param.id.value); const auto offset = ctx.OpIAdd( @@ -208,6 +256,9 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp) { case IR::Attribute::IsFrontFace: return ctx.OpSelect(ctx.U32[1], ctx.OpLoad(ctx.U1[1], ctx.front_facing), ctx.u32_one_value, ctx.u32_zero_value); + case IR::Attribute::PrimitiveId: + ASSERT(ctx.info.stage == Stage::Geometry); + return ctx.OpLoad(ctx.U32[1], ctx.primitive_id); default: throw NotImplementedException("Read U32 attribute {}", attr); } @@ -219,15 +270,16 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, u32 elemen return; } const Id pointer{OutputAttrPointer(ctx, attr, element)}; - ctx.OpStore(pointer, ctx.OpBitcast(ctx.F32[1], value)); -} - -Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferF32(ctx, inst, handle, address); + const auto component_type{OutputAttrComponentType(ctx, attr)}; + if (component_type.second) { + ctx.OpStore(pointer, ctx.OpBitcast(component_type.first, value)); + } else { + ctx.OpStore(pointer, value); + } } template -static Id EmitLoadBufferF32xN(EmitContext& ctx, u32 handle, Id address) { +static Id EmitLoadBufferU32xN(EmitContext& ctx, u32 handle, Id address) { auto& buffer = ctx.buffers[handle]; address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); @@ -246,191 +298,36 @@ static Id EmitLoadBufferF32xN(EmitContext& ctx, u32 handle, Id address) { } } -Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferF32xN<1>(ctx, handle, address); +Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { + return EmitLoadBufferU32xN<1>(ctx, handle, address); } -Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferF32xN<2>(ctx, handle, address); +Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { + return EmitLoadBufferU32xN<2>(ctx, handle, address); } -Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferF32xN<3>(ctx, handle, address); +Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { + return EmitLoadBufferU32xN<3>(ctx, handle, address); } -Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { - return EmitLoadBufferF32xN<4>(ctx, handle, address); -} - -static bool IsSignedInteger(AmdGpu::NumberFormat format) { - switch (format) { - case AmdGpu::NumberFormat::Unorm: - case AmdGpu::NumberFormat::Uscaled: - case AmdGpu::NumberFormat::Uint: - return false; - case AmdGpu::NumberFormat::Snorm: - case AmdGpu::NumberFormat::Sscaled: - case AmdGpu::NumberFormat::Sint: - case AmdGpu::NumberFormat::SnormNz: - return true; - case AmdGpu::NumberFormat::Float: - default: - UNREACHABLE(); - } -} - -static u32 UXBitsMax(u32 bit_width) { - return (1u << bit_width) - 1u; -} - -static u32 SXBitsMax(u32 bit_width) { - return (1u << (bit_width - 1u)) - 1u; -} - -static Id ConvertValue(EmitContext& ctx, Id value, AmdGpu::NumberFormat format, u32 bit_width) { - switch (format) { - case AmdGpu::NumberFormat::Unorm: - return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(UXBitsMax(bit_width)))); - case AmdGpu::NumberFormat::Snorm: - return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(SXBitsMax(bit_width)))); - case AmdGpu::NumberFormat::SnormNz: - // (x * 2 + 1) / (Format::SMAX * 2) - value = ctx.OpFMul(ctx.F32[1], value, ctx.ConstF32(2.f)); - value = ctx.OpFAdd(ctx.F32[1], value, ctx.ConstF32(1.f)); - return ctx.OpFDiv(ctx.F32[1], value, ctx.ConstF32(float(SXBitsMax(bit_width) * 2))); - case AmdGpu::NumberFormat::Uscaled: - case AmdGpu::NumberFormat::Sscaled: - case AmdGpu::NumberFormat::Uint: - case AmdGpu::NumberFormat::Sint: - case AmdGpu::NumberFormat::Float: - return value; - default: - UNREACHABLE_MSG("Unsupported number fromat for conversion: {}", - magic_enum::enum_name(format)); - } -} - -static Id ComponentOffset(EmitContext& ctx, Id address, u32 stride, u32 bit_offset) { - Id comp_offset = ctx.ConstU32(bit_offset); - if (stride < 4) { - // comp_offset += (address % 4) * 8; - const Id byte_offset = ctx.OpUMod(ctx.U32[1], address, ctx.ConstU32(4u)); - const Id bit_offset = ctx.OpShiftLeftLogical(ctx.U32[1], byte_offset, ctx.ConstU32(3u)); - comp_offset = ctx.OpIAdd(ctx.U32[1], comp_offset, bit_offset); - } - return comp_offset; -} - -static Id GetBufferFormatValue(EmitContext& ctx, u32 handle, Id address, u32 comp) { - auto& buffer = ctx.buffers[handle]; - const auto format = buffer.dfmt; - switch (format) { - case AmdGpu::DataFormat::FormatInvalid: - return ctx.f32_zero_value; - case AmdGpu::DataFormat::Format8: - case AmdGpu::DataFormat::Format16: - case AmdGpu::DataFormat::Format32: - case AmdGpu::DataFormat::Format8_8: - case AmdGpu::DataFormat::Format16_16: - case AmdGpu::DataFormat::Format10_11_11: - case AmdGpu::DataFormat::Format11_11_10: - case AmdGpu::DataFormat::Format10_10_10_2: - case AmdGpu::DataFormat::Format2_10_10_10: - case AmdGpu::DataFormat::Format8_8_8_8: - case AmdGpu::DataFormat::Format32_32: - case AmdGpu::DataFormat::Format16_16_16_16: - case AmdGpu::DataFormat::Format32_32_32: - case AmdGpu::DataFormat::Format32_32_32_32: { - const u32 num_components = AmdGpu::NumComponents(format); - if (comp >= num_components) { - return ctx.f32_zero_value; - } - - // uint index = address / 4; - Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); - const u32 stride = buffer.stride; - if (stride > 4) { - const u32 index_offset = u32(AmdGpu::ComponentOffset(format, comp) / 32); - if (index_offset > 0) { - // index += index_offset; - index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(index_offset)); - } - } - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index); - - const u32 bit_offset = AmdGpu::ComponentOffset(format, comp) % 32; - const u32 bit_width = AmdGpu::ComponentBits(format, comp); - const auto num_format = buffer.nfmt; - if (num_format == AmdGpu::NumberFormat::Float) { - if (bit_width == 32) { - return ctx.OpLoad(ctx.F32[1], ptr); - } else if (bit_width == 16) { - const Id comp_offset = ComponentOffset(ctx, address, stride, bit_offset); - Id value = ctx.OpLoad(ctx.U32[1], ptr); - value = - ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset, ctx.ConstU32(bit_width)); - value = ctx.OpSConvert(ctx.U16, value); - value = ctx.OpBitcast(ctx.F16[1], value); - return ctx.OpFConvert(ctx.F32[1], value); - } else { - UNREACHABLE_MSG("Invalid float bit width {}", bit_width); - } - } else { - Id value = ctx.OpLoad(ctx.U32[1], ptr); - const bool is_signed = IsSignedInteger(num_format); - if (bit_width < 32) { - const Id comp_offset = ComponentOffset(ctx, address, stride, bit_offset); - if (is_signed) { - value = ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset, - ctx.ConstU32(bit_width)); - } else { - value = ctx.OpBitFieldUExtract(ctx.U32[1], value, comp_offset, - ctx.ConstU32(bit_width)); - } - } - value = ctx.OpBitcast(ctx.F32[1], value); - return ConvertValue(ctx, value, num_format, bit_width); - } - break; - } - default: - UNREACHABLE_MSG("Invalid format for conversion: {}", magic_enum::enum_name(format)); - } -} - -template -static Id EmitLoadBufferFormatF32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - auto& buffer = ctx.buffers[handle]; - address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); - if constexpr (N == 1) { - return GetBufferFormatValue(ctx, handle, address, 0); - } else { - boost::container::static_vector ids; - for (u32 i = 0; i < N; i++) { - ids.push_back(GetBufferFormatValue(ctx, handle, address, i)); - } - return ctx.OpCompositeConstruct(ctx.F32[N], ids); - } +Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst*, u32 handle, Id address) { + return EmitLoadBufferU32xN<4>(ctx, handle, address); } Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<1>(ctx, inst, handle, address); -} - -Id EmitLoadBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<2>(ctx, inst, handle, address); -} - -Id EmitLoadBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<3>(ctx, inst, handle, address); -} - -Id EmitLoadBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) { - return EmitLoadBufferFormatF32xN<4>(ctx, inst, handle, address); + const auto& buffer = ctx.texture_buffers[handle]; + const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id); + const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset); + Id texel = buffer.is_storage ? ctx.OpImageRead(buffer.result_type, tex_buffer, coord) + : ctx.OpImageFetch(buffer.result_type, tex_buffer, coord); + if (buffer.is_integer) { + texel = ctx.OpBitcast(ctx.F32[4], texel); + } + return texel; } template -static void EmitStoreBufferF32xN(EmitContext& ctx, u32 handle, Id address, Id value) { +static void EmitStoreBufferU32xN(EmitContext& ctx, u32 handle, Id address, Id value) { auto& buffer = ctx.buffers[handle]; address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); @@ -442,122 +339,35 @@ static void EmitStoreBufferF32xN(EmitContext& ctx, u32 handle, Id address, Id va const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index_i); - ctx.OpStore(ptr, ctx.OpCompositeExtract(ctx.F32[1], value, i)); + ctx.OpStore(ptr, ctx.OpCompositeExtract(buffer.data_types->Get(1), value, i)); } } } -void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferF32xN<1>(ctx, handle, address, value); -} - -void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferF32xN<2>(ctx, handle, address, value); -} - -void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferF32xN<3>(ctx, handle, address, value); -} - -void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferF32xN<4>(ctx, handle, address, value); -} - void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferF32xN<1>(ctx, handle, address, value); + EmitStoreBufferU32xN<1>(ctx, handle, address, value); } -static Id ConvertF32ToFormat(EmitContext& ctx, Id value, AmdGpu::NumberFormat format, - u32 bit_width) { - switch (format) { - case AmdGpu::NumberFormat::Unorm: - return ctx.OpConvertFToU( - ctx.U32[1], ctx.OpFMul(ctx.F32[1], value, ctx.ConstF32(float(UXBitsMax(bit_width))))); - case AmdGpu::NumberFormat::Uint: - return ctx.OpBitcast(ctx.U32[1], value); - case AmdGpu::NumberFormat::Float: - return value; - default: - UNREACHABLE_MSG("Unsupported number fromat for conversion: {}", - magic_enum::enum_name(format)); - } +void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferU32xN<2>(ctx, handle, address, value); } -template -static void EmitStoreBufferFormatF32xN(EmitContext& ctx, u32 handle, Id address, Id value) { - auto& buffer = ctx.buffers[handle]; - const auto format = buffer.dfmt; - const auto num_format = buffer.nfmt; +void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferU32xN<3>(ctx, handle, address, value); +} - switch (format) { - case AmdGpu::DataFormat::FormatInvalid: - return; - case AmdGpu::DataFormat::Format8_8_8_8: - case AmdGpu::DataFormat::Format16: - case AmdGpu::DataFormat::Format32: - case AmdGpu::DataFormat::Format32_32: - case AmdGpu::DataFormat::Format32_32_32_32: { - ASSERT(N == AmdGpu::NumComponents(format)); - - address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset); - const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u)); - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, ctx.u32_zero_value, index); - - Id packed_value{}; - for (u32 i = 0; i < N; i++) { - const u32 bit_width = AmdGpu::ComponentBits(format, i); - const u32 bit_offset = AmdGpu::ComponentOffset(format, i) % 32; - - const Id comp{ConvertF32ToFormat( - ctx, N == 1 ? value : ctx.OpCompositeExtract(ctx.F32[1], value, i), num_format, - bit_width)}; - - if (bit_width == 32) { - if constexpr (N == 1) { - ctx.OpStore(ptr, comp); - } else { - const Id index_i = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i)); - const Id ptr = ctx.OpAccessChain(buffer.pointer_type, buffer.id, - ctx.u32_zero_value, index_i); - ctx.OpStore(ptr, comp); - } - } else { - if (i == 0) { - packed_value = comp; - } else { - packed_value = - ctx.OpBitFieldInsert(ctx.U32[1], packed_value, comp, - ctx.ConstU32(bit_offset), ctx.ConstU32(bit_width)); - } - - if (i == N - 1) { - ctx.OpStore(ptr, packed_value); - } - } - } - } break; - default: - UNREACHABLE_MSG("Invalid format for conversion: {}", magic_enum::enum_name(format)); - } +void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { + EmitStoreBufferU32xN<4>(ctx, handle, address, value); } void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { - EmitStoreBufferFormatF32xN<1>(ctx, handle, address, value); -} - -void EmitStoreBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, - Id value) { - EmitStoreBufferFormatF32xN<2>(ctx, handle, address, value); -} - -void EmitStoreBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, - Id value) { - EmitStoreBufferFormatF32xN<3>(ctx, handle, address, value); -} - -void EmitStoreBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, - Id value) { - EmitStoreBufferFormatF32xN<4>(ctx, handle, address, value); + const auto& buffer = ctx.texture_buffers[handle]; + const Id tex_buffer = ctx.OpLoad(buffer.image_type, buffer.id); + const Id coord = ctx.OpIAdd(ctx.U32[1], address, buffer.coord_offset); + if (buffer.is_integer) { + value = ctx.OpBitcast(buffer.result_type, value); + } + ctx.OpImageWrite(tex_buffer, coord, value); } } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 5526e5411..fc99b8925 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -16,6 +16,12 @@ struct ImageOperands { static_cast(new_mask)); operands.push_back(value); } + void Add(spv::ImageOperandsMask new_mask, Id value1, Id value2) { + mask = static_cast(static_cast(mask) | + static_cast(new_mask)); + operands.push_back(value1); + operands.push_back(value2); + } void AddOffset(EmitContext& ctx, const IR::Value& offset, bool can_use_runtime_offsets = false) { @@ -53,85 +59,113 @@ struct ImageOperands { } } + void AddDerivatives(EmitContext& ctx, Id derivatives_dx, Id derivatives_dy) { + if (!Sirit::ValidId(derivatives_dx) || !Sirit::ValidId(derivatives_dy)) { + return; + } + Add(spv::ImageOperandsMask::Grad, derivatives_dx, derivatives_dy); + } + spv::ImageOperandsMask mask{}; boost::container::static_vector operands; }; +Id EmitImageSampleRaw(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address1, Id address2, + Id address3, Id address4) { + UNREACHABLE_MSG("Unreachable instruction"); +} + Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias, const IR::Value& offset) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(4); const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); ImageOperands operands; operands.Add(spv::ImageOperandsMask::Bias, bias); operands.AddOffset(ctx, offset); - return ctx.OpImageSampleImplicitLod(ctx.F32[4], sampled_image, coords, operands.mask, - operands.operands); + const Id sample = ctx.OpImageSampleImplicitLod(result_type, sampled_image, coords, + operands.mask, operands.operands); + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], sample) : sample; } Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, const IR::Value& offset) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(4); const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); ImageOperands operands; operands.Add(spv::ImageOperandsMask::Lod, lod); operands.AddOffset(ctx, offset); - return ctx.OpImageSampleExplicitLod(ctx.F32[4], sampled_image, coords, operands.mask, - operands.operands); + const Id sample = ctx.OpImageSampleExplicitLod(result_type, sampled_image, coords, + operands.mask, operands.operands); + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], sample) : sample; } Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref, Id bias, const IR::Value& offset) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(1); const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); ImageOperands operands; operands.Add(spv::ImageOperandsMask::Bias, bias); operands.AddOffset(ctx, offset); - return ctx.OpImageSampleDrefImplicitLod(ctx.F32[1], sampled_image, coords, dref, operands.mask, - operands.operands); + const Id sample = ctx.OpImageSampleDrefImplicitLod(result_type, sampled_image, coords, dref, + operands.mask, operands.operands); + const Id sample_typed = texture.is_integer ? ctx.OpBitcast(ctx.F32[1], sample) : sample; + return ctx.OpCompositeConstruct(ctx.F32[4], sample_typed, ctx.f32_zero_value, + ctx.f32_zero_value, ctx.f32_zero_value); } Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref, Id lod, const IR::Value& offset) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(1); const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); ImageOperands operands; operands.AddOffset(ctx, offset); operands.Add(spv::ImageOperandsMask::Lod, lod); - return ctx.OpImageSampleDrefExplicitLod(ctx.F32[1], sampled_image, coords, dref, operands.mask, - operands.operands); + const Id sample = ctx.OpImageSampleDrefExplicitLod(result_type, sampled_image, coords, dref, + operands.mask, operands.operands); + const Id sample_typed = texture.is_integer ? ctx.OpBitcast(ctx.F32[1], sample) : sample; + return ctx.OpCompositeConstruct(ctx.F32[4], sample_typed, ctx.f32_zero_value, + ctx.f32_zero_value, ctx.f32_zero_value); } Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const IR::Value& offset) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(4); const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); const u32 comp = inst->Flags().gather_comp.Value(); ImageOperands operands; - operands.AddOffset(ctx, offset); - return ctx.OpImageGather(ctx.F32[4], sampled_image, coords, ctx.ConstU32(comp), operands.mask, - operands.operands); + operands.AddOffset(ctx, offset, true); + const Id texels = ctx.OpImageGather(result_type, sampled_image, coords, ctx.ConstU32(comp), + operands.mask, operands.operands); + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texels) : texels; } Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const IR::Value& offset, Id dref) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(4); const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); ImageOperands operands; - operands.AddOffset(ctx, offset); - return ctx.OpImageDrefGather(ctx.F32[4], sampled_image, coords, dref, operands.mask, - operands.operands); + operands.AddOffset(ctx, offset, true); + const Id texels = ctx.OpImageDrefGather(result_type, sampled_image, coords, dref, operands.mask, + operands.operands); + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texels) : texels; } Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const IR::Value& offset, @@ -142,17 +176,20 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const ImageOperands operands; operands.AddOffset(ctx, offset); operands.Add(spv::ImageOperandsMask::Lod, lod); - return ctx.OpBitcast( - ctx.F32[4], ctx.OpImageFetch(result_type, image, coords, operands.mask, operands.operands)); + const Id texel = + texture.is_storage + ? ctx.OpImageRead(result_type, image, coords, operands.mask, operands.operands) + : ctx.OpImageFetch(result_type, image, coords, operands.mask, operands.operands); + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texel) : texel; } -Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips) { +Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool has_mips) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); const auto type = ctx.info.images[handle & 0xFFFF].type; const Id zero = ctx.u32_zero_value; - const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; - const bool uses_lod{type != AmdGpu::ImageType::Color2DMsaa}; + 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 auto query{[&](Id type) { return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod) : ctx.OpImageQuerySize(type, image); @@ -163,6 +200,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod 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: case AmdGpu::ImageType::Color3D: @@ -181,9 +219,19 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords) { return ctx.OpImageQueryLod(ctx.F32[2], sampled_image, coords); } -Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivatives, const IR::Value& offset, Id lod_clamp) { - UNREACHABLE_MSG("SPIR-V Instruction"); +Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives_dx, + Id derivatives_dy, const IR::Value& offset, const IR::Value& lod_clamp) { + const auto& texture = ctx.images[handle & 0xFFFF]; + const Id image = ctx.OpLoad(texture.image_type, texture.id); + const Id result_type = texture.data_types->Get(4); + const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]); + const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler); + ImageOperands operands; + operands.AddDerivatives(ctx, derivatives_dx, derivatives_dy); + operands.AddOffset(ctx, offset); + const Id sample = ctx.OpImageSampleExplicitLod(result_type, sampled_image, coords, + operands.mask, operands.operands); + return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], sample) : sample; } Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index bc39bc0f3..02b98b343 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -27,7 +27,6 @@ Id EmitConditionRef(EmitContext& ctx, const IR::Value& value); void EmitReference(EmitContext&); void EmitPhiMove(EmitContext&); void EmitJoin(EmitContext& ctx); -void EmitBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx); void EmitGetScc(EmitContext& ctx); @@ -36,17 +35,20 @@ void EmitGetVcc(EmitContext& ctx); void EmitGetSccLo(EmitContext& ctx); void EmitGetVccLo(EmitContext& ctx); void EmitGetVccHi(EmitContext& ctx); +void EmitGetM0(EmitContext& ctx); void EmitSetScc(EmitContext& ctx); void EmitSetExec(EmitContext& ctx); void EmitSetVcc(EmitContext& ctx); void EmitSetSccLo(EmitContext& ctx); void EmitSetVccLo(EmitContext& ctx); void EmitSetVccHi(EmitContext& ctx); +void EmitSetM0(EmitContext& ctx); void EmitFPCmpClass32(EmitContext& ctx); void EmitPrologue(EmitContext& ctx); void EmitEpilogue(EmitContext& ctx); void EmitDiscard(EmitContext& ctx); void EmitDiscardCond(EmitContext& ctx, Id condition); +void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4); void EmitBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx); @@ -62,25 +64,16 @@ void EmitGetGotoVariable(EmitContext& ctx); void EmitSetScc(EmitContext& ctx); Id EmitReadConst(EmitContext& ctx); Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index); -Id EmitReadConstBufferU32(EmitContext& ctx, u32 handle, Id index); -Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferFormatF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferFormatF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferFormatF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); +Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); +Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); +Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicUMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); @@ -91,8 +84,8 @@ Id EmitBufferAtomicDec32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addres Id EmitBufferAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); Id EmitBufferAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp); +Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); +Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index); Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp); void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, u32 comp); void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value); @@ -165,12 +158,13 @@ Id EmitSelectF32(EmitContext& ctx, Id cond, Id true_value, Id false_value); Id EmitSelectF64(EmitContext& ctx, Id cond, Id true_value, Id false_value); Id EmitBitCastU16F16(EmitContext& ctx, Id value); Id EmitBitCastU32F32(EmitContext& ctx, Id value); -void EmitBitCastU64F64(EmitContext& ctx); +Id EmitBitCastU64F64(EmitContext& ctx, Id value); Id EmitBitCastF16U16(EmitContext& ctx, Id value); Id EmitBitCastF32U32(EmitContext& ctx, Id value); void EmitBitCastF64U64(EmitContext& ctx); Id EmitPackUint2x32(EmitContext& ctx, Id value); Id EmitUnpackUint2x32(EmitContext& ctx, Id value); +Id EmitPackFloat2x32(EmitContext& ctx, Id value); Id EmitPackFloat2x16(EmitContext& ctx, Id value); Id EmitUnpackFloat2x16(EmitContext& ctx, Id value); Id EmitPackHalf2x16(EmitContext& ctx, Id value); @@ -276,6 +270,8 @@ Id EmitIMul32(EmitContext& ctx, Id a, Id b); Id EmitIMul64(EmitContext& ctx, Id a, Id b); Id EmitSDiv32(EmitContext& ctx, Id a, Id b); Id EmitUDiv32(EmitContext& ctx, Id a, Id b); +Id EmitSMod32(EmitContext& ctx, Id a, Id b); +Id EmitUMod32(EmitContext& ctx, Id a, Id b); Id EmitINeg32(EmitContext& ctx, Id value); Id EmitINeg64(EmitContext& ctx, Id value); Id EmitIAbs32(EmitContext& ctx, Id value); @@ -286,6 +282,7 @@ Id EmitShiftRightLogical64(EmitContext& ctx, Id base, Id shift); Id EmitShiftRightArithmetic32(EmitContext& ctx, Id base, Id shift); Id EmitShiftRightArithmetic64(EmitContext& ctx, Id base, Id shift); Id EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); +Id EmitBitwiseAnd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitBitwiseOr64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); @@ -371,6 +368,8 @@ Id EmitConvertF64U64(EmitContext& ctx, Id value); Id EmitConvertU16U32(EmitContext& ctx, Id value); Id EmitConvertU32U16(EmitContext& ctx, Id value); +Id EmitImageSampleRaw(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address1, Id address2, + Id address3, Id address4); Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias, const IR::Value& offset); Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, @@ -387,8 +386,8 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, const Id lod, Id ms); Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords); -Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivatives, const IR::Value& offset, Id lod_clamp); +Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives_dx, + Id derivatives_dy, const IR::Value& offset, const IR::Value& lod_clamp); Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id color); @@ -403,9 +402,16 @@ 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 EmitLaneId(EmitContext& ctx); Id EmitWarpId(EmitContext& ctx); Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index); +Id EmitReadFirstLane(EmitContext& ctx, Id value); +Id EmitReadLane(EmitContext& ctx, Id value, u32 lane); +Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane); +Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding); +Id EmitDataConsume(EmitContext& ctx, u32 gds_addr, u32 binding); + +void EmitEmitVertex(EmitContext& ctx); +void EmitEmitPrimitive(EmitContext& ctx); } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index f20c4fac2..02af92385 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -96,6 +96,14 @@ Id EmitUDiv32(EmitContext& ctx, Id a, Id b) { return ctx.OpUDiv(ctx.U32[1], a, b); } +Id EmitSMod32(EmitContext& ctx, Id a, Id b) { + return ctx.OpSMod(ctx.U32[1], a, b); +} + +Id EmitUMod32(EmitContext& ctx, Id a, Id b) { + return ctx.OpUMod(ctx.U32[1], a, b); +} + Id EmitINeg32(EmitContext& ctx, Id value) { return ctx.OpSNegate(ctx.U32[1], value); } @@ -139,6 +147,13 @@ Id EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { return result; } +Id EmitBitwiseAnd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { + const Id result{ctx.OpBitwiseAnd(ctx.U64, a, b)}; + SetZeroFlag(ctx, inst, result); + SetSignFlag(ctx, inst, result); + return result; +} + Id EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { const Id result{ctx.OpBitwiseOr(ctx.U32[1], a, b)}; SetZeroFlag(ctx, inst, result); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index 3ed89692b..e9ffdcce8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -3,6 +3,7 @@ #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" +#include "shader_recompiler/ir/debug_print.h" namespace Shader::Backend::SPIRV { @@ -10,7 +11,21 @@ void EmitPrologue(EmitContext& ctx) { ctx.DefineBufferOffsets(); } -void EmitEpilogue(EmitContext& ctx) {} +void ConvertDepthMode(EmitContext& ctx) { + const Id type{ctx.F32[1]}; + const Id position{ctx.OpLoad(ctx.F32[4], ctx.output_position)}; + const Id z{ctx.OpCompositeExtract(type, position, 2u)}; + const Id w{ctx.OpCompositeExtract(type, position, 3u)}; + const Id screen_depth{ctx.OpFMul(type, ctx.OpFAdd(type, z, w), ctx.Constant(type, 0.5f))}; + const Id vector{ctx.OpCompositeInsert(ctx.F32[4], screen_depth, position, 2u)}; + ctx.OpStore(ctx.output_position, vector); +} + +void EmitEpilogue(EmitContext& ctx) { + if (ctx.stage == Stage::Vertex && ctx.runtime_info.vs_info.emulate_depth_negative_one_to_one) { + ConvertDepthMode(ctx); + } +} void EmitDiscard(EmitContext& ctx) { ctx.OpDemoteToHelperInvocationEXT(); @@ -27,6 +42,14 @@ void EmitDiscardCond(EmitContext& ctx, Id condition) { ctx.AddLabel(merge_label); } +void EmitEmitVertex(EmitContext& ctx) { + ctx.OpEmitVertex(); +} + +void EmitEmitPrimitive(EmitContext& ctx) { + ctx.OpEndPrimitive(); +} + void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { throw NotImplementedException("Geometry streams"); } @@ -35,4 +58,11 @@ void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { throw NotImplementedException("Geometry streams"); } +void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt, Id arg0, Id arg1, Id arg2, Id arg3) { + IR::DebugPrintFlags flags = inst->Flags(); + std::array fmt_args = {arg0, arg1, arg2, arg3}; + auto fmt_args_span = std::span(fmt_args.begin(), fmt_args.begin() + flags.num_args); + ctx.OpDebugPrintf(fmt, fmt_args_span); +} + } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index 38afd90f1..2d13d09f0 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp @@ -22,4 +22,17 @@ Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index) { return ctx.OpGroupNonUniformQuadBroadcast(ctx.U32[1], SubgroupScope(ctx), value, index); } +Id EmitReadFirstLane(EmitContext& ctx, Id value) { + return ctx.OpGroupNonUniformBroadcastFirst(ctx.U32[1], SubgroupScope(ctx), value); +} + +Id EmitReadLane(EmitContext& ctx, Id value, u32 lane) { + return ctx.OpGroupNonUniformBroadcast(ctx.U32[1], SubgroupScope(ctx), value, + ctx.ConstU32(lane)); +} + +Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane) { + return ctx.u32_zero_value; +} + } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index d61e108f6..6581a7a56 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1,8 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/assert.h" #include "common/div_ceil.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" +#include "video_core/amdgpu/types.h" #include #include @@ -32,6 +34,22 @@ std::string_view StageName(Stage stage) { throw InvalidArgument("Invalid stage {}", u32(stage)); } +static constexpr u32 NumVertices(AmdGpu::PrimitiveType type) { + switch (type) { + case AmdGpu::PrimitiveType::PointList: + return 1u; + case AmdGpu::PrimitiveType::LineList: + return 2u; + case AmdGpu::PrimitiveType::TriangleList: + case AmdGpu::PrimitiveType::TriangleStrip: + return 3u; + case AmdGpu::PrimitiveType::AdjTriangleList: + return 6u; + default: + UNREACHABLE(); + } +} + template void Name(EmitContext& ctx, Id object, std::string_view format_str, Args&&... args) { ctx.Name(object, fmt::format(fmt::runtime(format_str), StageName(ctx.stage), @@ -41,13 +59,15 @@ void Name(EmitContext& ctx, Id object, std::string_view format_str, Args&&... ar } // Anonymous namespace -EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& binding_) - : Sirit::Module(profile_.supported_spirv), info{program.info}, profile{profile_}, - stage{program.info.stage}, binding{binding_} { +EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_info_, + const Info& info_, Bindings& binding_) + : Sirit::Module(profile_.supported_spirv), info{info_}, runtime_info{runtime_info_}, + profile{profile_}, stage{info.stage}, binding{binding_} { AddCapability(spv::Capability::Shader); DefineArithmeticTypes(); DefineInterfaces(); DefineBuffers(); + DefineTextureBuffers(); DefineImagesAndSamplers(); DefineSharedMemory(); } @@ -71,6 +91,8 @@ Id EmitContext::Def(const IR::Value& value) { return ConstF32(value.F32()); case IR::Type::F64: return Constant(F64[1], value.F64()); + case IR::Type::StringLiteral: + return String(value.StringLiteral()); default: throw NotImplementedException("Immediate type {}", value.Type()); } @@ -83,6 +105,9 @@ void EmitContext::DefineArithmeticTypes() { F16[1] = Name(TypeFloat(16), "f16_id"); U16 = Name(TypeUInt(16), "u16_id"); } + if (info.uses_fp64) { + F64[1] = Name(TypeFloat(64), "f64_id"); + } F32[1] = Name(TypeFloat(32), "f32_id"); S32[1] = Name(TypeSInt(32), "i32_id"); U32[1] = Name(TypeUInt(32), "u32_id"); @@ -92,6 +117,9 @@ void EmitContext::DefineArithmeticTypes() { if (info.uses_fp16) { F16[i] = Name(TypeVector(F16[1], i), fmt::format("f16vec{}_id", i)); } + if (info.uses_fp64) { + F64[i] = Name(TypeVector(F64[1], i), fmt::format("f64vec{}_id", i)); + } F32[i] = Name(TypeVector(F32[1], i), fmt::format("f32vec{}_id", i)); S32[i] = Name(TypeVector(S32[1], i), fmt::format("i32vec{}_id", i)); U32[i] = Name(TypeVector(U32[1], i), fmt::format("u32vec{}_id", i)); @@ -112,6 +140,7 @@ void EmitContext::DefineArithmeticTypes() { output_f32 = Name(TypePointer(spv::StorageClass::Output, F32[1]), "output_f32"); output_u32 = Name(TypePointer(spv::StorageClass::Output, U32[1]), "output_u32"); + output_s32 = Name(TypePointer(spv::StorageClass::Output, S32[1]), "output_s32"); full_result_i32x2 = Name(TypeStruct(S32[1], S32[1]), "full_result_i32x2"); full_result_u32x2 = Name(TypeStruct(U32[1], U32[1]), "full_result_u32x2"); @@ -123,59 +152,71 @@ void EmitContext::DefineInterfaces() { DefineOutputs(); } -Id GetAttributeType(EmitContext& ctx, AmdGpu::NumberFormat fmt) { +const VectorIds& GetAttributeType(EmitContext& ctx, AmdGpu::NumberFormat fmt) { switch (fmt) { case AmdGpu::NumberFormat::Float: case AmdGpu::NumberFormat::Unorm: case AmdGpu::NumberFormat::Snorm: case AmdGpu::NumberFormat::SnormNz: - return ctx.F32[4]; - case AmdGpu::NumberFormat::Sint: - return ctx.S32[4]; - case AmdGpu::NumberFormat::Uint: - return ctx.U32[4]; case AmdGpu::NumberFormat::Sscaled: - return ctx.F32[4]; case AmdGpu::NumberFormat::Uscaled: - return ctx.F32[4]; + case AmdGpu::NumberFormat::Srgb: + return ctx.F32; + case AmdGpu::NumberFormat::Sint: + return ctx.S32; + case AmdGpu::NumberFormat::Uint: + return ctx.U32; default: break; } - throw InvalidArgument("Invalid attribute type {}", fmt); + UNREACHABLE_MSG("Invalid attribute type {}", fmt); } -EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id) { +EmitContext::SpirvAttribute EmitContext::GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id, + u32 num_components, bool output) { switch (fmt) { case AmdGpu::NumberFormat::Float: case AmdGpu::NumberFormat::Unorm: case AmdGpu::NumberFormat::Snorm: case AmdGpu::NumberFormat::SnormNz: - return {id, input_f32, F32[1], 4}; - case AmdGpu::NumberFormat::Uint: - return {id, input_u32, U32[1], 4}; - case AmdGpu::NumberFormat::Sint: - return {id, input_s32, S32[1], 4}; case AmdGpu::NumberFormat::Sscaled: - return {id, input_f32, F32[1], 4}; case AmdGpu::NumberFormat::Uscaled: - return {id, input_f32, F32[1], 4}; + case AmdGpu::NumberFormat::Srgb: + return {id, output ? output_f32 : input_f32, F32[1], num_components, false}; + case AmdGpu::NumberFormat::Uint: + return {id, output ? output_u32 : input_u32, U32[1], num_components, true}; + case AmdGpu::NumberFormat::Sint: + return {id, output ? output_s32 : input_s32, S32[1], num_components, true}; default: break; } - throw InvalidArgument("Invalid attribute type {}", fmt); + UNREACHABLE_MSG("Invalid attribute type {}", fmt); } void EmitContext::DefineBufferOffsets() { - for (auto& buffer : buffers) { + for (BufferDefinition& buffer : buffers) { const u32 binding = buffer.binding; - const u32 half = Shader::PushData::BufOffsetIndex + (binding >> 4); + const u32 half = PushData::BufOffsetIndex + (binding >> 4); const u32 comp = (binding & 0xf) >> 2; const u32 offset = (binding & 0x3) << 3; const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]), push_data_block, ConstU32(half), ConstU32(comp))}; const Id value{OpLoad(U32[1], ptr)}; buffer.offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U)); + Name(buffer.offset, fmt::format("buf{}_off", binding)); buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U)); + Name(buffer.offset_dwords, fmt::format("buf{}_dword_off", binding)); + } + for (TextureBufferDefinition& tex_buffer : texture_buffers) { + const u32 binding = tex_buffer.binding; + const u32 half = PushData::BufOffsetIndex + (binding >> 4); + const u32 comp = (binding & 0xf) >> 2; + const u32 offset = (binding & 0x3) << 3; + const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]), + push_data_block, ConstU32(half), ConstU32(comp))}; + const Id value{OpLoad(U32[1], ptr)}; + tex_buffer.coord_offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(6U)); + Name(tex_buffer.coord_offset, fmt::format("texbuf{}_off", binding)); } } @@ -195,14 +236,21 @@ Id MakeDefaultValue(EmitContext& ctx, u32 default_value) { } void EmitContext::DefineInputs() { + if (info.uses_lane_id) { + subgroup_local_invocation_id = DefineVariable( + U32[1], spv::BuiltIn::SubgroupLocalInvocationId, spv::StorageClass::Input); + Decorate(subgroup_local_invocation_id, spv::Decoration::Flat); + } switch (stage) { + case Stage::Export: case Stage::Vertex: { vertex_index = DefineVariable(U32[1], spv::BuiltIn::VertexIndex, spv::StorageClass::Input); base_vertex = DefineVariable(U32[1], spv::BuiltIn::BaseVertex, spv::StorageClass::Input); instance_id = DefineVariable(U32[1], spv::BuiltIn::InstanceIndex, spv::StorageClass::Input); for (const auto& input : info.vs_inputs) { - const Id type{GetAttributeType(*this, input.fmt)}; + ASSERT(input.binding < IR::NumParams); + const Id type{GetAttributeType(*this, input.fmt)[4]}; if (input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate0 || input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate1) { @@ -211,9 +259,13 @@ void EmitContext::DefineInputs() { : 1; // Note that we pass index rather than Id input_params[input.binding] = { - rate_idx, input_u32, - U32[1], input.num_components, - false, input.instance_data_buf, + rate_idx, + input_u32, + U32[1], + input.num_components, + true, + false, + input.instance_data_buf, }; } else { Id id{DefineInput(type, input.binding)}; @@ -222,24 +274,24 @@ void EmitContext::DefineInputs() { } else { Name(id, fmt::format("vs_in_attr{}", input.binding)); } - input_params[input.binding] = GetAttributeInfo(input.fmt, id); + input_params[input.binding] = GetAttributeInfo(input.fmt, id, 4, false); interfaces.push_back(id); } } break; } case Stage::Fragment: - subgroup_local_invocation_id = DefineVariable( - U32[1], spv::BuiltIn::SubgroupLocalInvocationId, spv::StorageClass::Input); - Decorate(subgroup_local_invocation_id, spv::Decoration::Flat); frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input); frag_depth = DefineVariable(F32[1], spv::BuiltIn::FragDepth, spv::StorageClass::Output); front_facing = DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input); - for (const auto& input : info.ps_inputs) { + for (s32 i = 0; i < runtime_info.fs_info.num_inputs; i++) { + const auto& input = runtime_info.fs_info.inputs[i]; const u32 semantic = input.param_index; - if (input.is_default) { - input_params[semantic] = {MakeDefaultValue(*this, input.default_value), F32[1], - F32[1], 4, true}; + ASSERT(semantic < IR::NumParams); + if (input.is_default && !input.is_flat) { + input_params[semantic] = { + MakeDefaultValue(*this, input.default_value), input_f32, F32[1], 4, false, true, + }; continue; } const IR::Attribute param{IR::Attribute::Param0 + input.param_index}; @@ -250,7 +302,8 @@ void EmitContext::DefineInputs() { Decorate(id, spv::Decoration::Flat); } Name(id, fmt::format("fs_in_attr{}", semantic)); - input_params[semantic] = {id, input_f32, F32[1], num_components}; + input_params[semantic] = + GetAttributeInfo(AmdGpu::NumberFormat::Float, id, num_components, false); interfaces.push_back(id); } break; @@ -259,6 +312,36 @@ void EmitContext::DefineInputs() { local_invocation_id = DefineVariable(U32[3], spv::BuiltIn::LocalInvocationId, spv::StorageClass::Input); break; + case Stage::Geometry: { + primitive_id = DefineVariable(U32[1], spv::BuiltIn::PrimitiveId, spv::StorageClass::Input); + const auto gl_per_vertex = + Name(TypeStruct(TypeVector(F32[1], 4), F32[1], TypeArray(F32[1], ConstU32(1u))), + "gl_PerVertex"); + MemberName(gl_per_vertex, 0, "gl_Position"); + MemberName(gl_per_vertex, 1, "gl_PointSize"); + MemberName(gl_per_vertex, 2, "gl_ClipDistance"); + MemberDecorate(gl_per_vertex, 0, spv::Decoration::BuiltIn, + static_cast(spv::BuiltIn::Position)); + MemberDecorate(gl_per_vertex, 1, spv::Decoration::BuiltIn, + static_cast(spv::BuiltIn::PointSize)); + MemberDecorate(gl_per_vertex, 2, spv::Decoration::BuiltIn, + static_cast(spv::BuiltIn::ClipDistance)); + Decorate(gl_per_vertex, spv::Decoration::Block); + const auto num_verts_in = NumVertices(runtime_info.gs_info.in_primitive); + const auto vertices_in = TypeArray(gl_per_vertex, ConstU32(num_verts_in)); + gl_in = Name(DefineVar(vertices_in, spv::StorageClass::Input), "gl_in"); + interfaces.push_back(gl_in); + + const auto num_params = runtime_info.gs_info.in_vertex_data_size / 4 - 1u; + for (int param_id = 0; param_id < num_params; ++param_id) { + const Id type{TypeArray(F32[4], ConstU32(num_verts_in))}; + const Id id{DefineInput(type, param_id)}; + Name(id, fmt::format("in_attr{}", param_id)); + input_params[param_id] = {id, input_f32, F32[1], 4}; + interfaces.push_back(id); + } + break; + } default: break; } @@ -266,6 +349,7 @@ void EmitContext::DefineInputs() { void EmitContext::DefineOutputs() { switch (stage) { + case Stage::Export: case Stage::Vertex: { output_position = DefineVariable(F32[4], spv::BuiltIn::Position, spv::StorageClass::Output); const bool has_extra_pos_stores = info.stores.Get(IR::Attribute::Position1) || @@ -286,7 +370,8 @@ void EmitContext::DefineOutputs() { const u32 num_components = info.stores.NumComponents(param); const Id id{DefineOutput(F32[num_components], i)}; Name(id, fmt::format("out_attr{}", i)); - output_params[i] = {id, output_f32, F32[1], num_components}; + output_params[i] = + GetAttributeInfo(AmdGpu::NumberFormat::Float, id, num_components, true); interfaces.push_back(id); } break; @@ -298,12 +383,25 @@ void EmitContext::DefineOutputs() { continue; } const u32 num_components = info.stores.NumComponents(mrt); - frag_color[i] = DefineOutput(F32[num_components], i); - frag_num_comp[i] = num_components; - Name(frag_color[i], fmt::format("frag_color{}", i)); - interfaces.push_back(frag_color[i]); + const AmdGpu::NumberFormat num_format{runtime_info.fs_info.color_buffers[i].num_format}; + const Id type{GetAttributeType(*this, num_format)[num_components]}; + const Id id{DefineOutput(type, i)}; + Name(id, fmt::format("frag_color{}", i)); + frag_outputs[i] = GetAttributeInfo(num_format, id, num_components, true); + interfaces.push_back(id); } break; + case Stage::Geometry: { + output_position = DefineVariable(F32[4], spv::BuiltIn::Position, spv::StorageClass::Output); + + for (u32 attr_id = 0; attr_id < info.gs_copy_data.num_attrs; attr_id++) { + const Id id{DefineOutput(F32[4], attr_id)}; + Name(id, fmt::format("out_attr{}", attr_id)); + output_params[attr_id] = {id, output_f32, F32[1], 4u}; + interfaces.push_back(id); + } + break; + } default: break; } @@ -311,16 +409,25 @@ void EmitContext::DefineOutputs() { void EmitContext::DefinePushDataBlock() { // Create push constants block for instance steps rates - const Id struct_type{Name(TypeStruct(U32[1], U32[1], U32[4], U32[4]), "AuxData")}; + const Id struct_type{Name( + TypeStruct(U32[1], U32[1], U32[4], U32[4], U32[4], U32[4], U32[4], U32[4]), "AuxData")}; Decorate(struct_type, spv::Decoration::Block); MemberName(struct_type, 0, "sr0"); MemberName(struct_type, 1, "sr1"); MemberName(struct_type, 2, "buf_offsets0"); MemberName(struct_type, 3, "buf_offsets1"); + MemberName(struct_type, 4, "ud_regs0"); + MemberName(struct_type, 5, "ud_regs1"); + MemberName(struct_type, 6, "ud_regs2"); + MemberName(struct_type, 7, "ud_regs3"); MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); MemberDecorate(struct_type, 1, spv::Decoration::Offset, 4U); MemberDecorate(struct_type, 2, spv::Decoration::Offset, 8U); MemberDecorate(struct_type, 3, spv::Decoration::Offset, 24U); + MemberDecorate(struct_type, 4, spv::Decoration::Offset, 40U); + MemberDecorate(struct_type, 5, spv::Decoration::Offset, 56U); + MemberDecorate(struct_type, 6, spv::Decoration::Offset, 72U); + MemberDecorate(struct_type, 7, spv::Decoration::Offset, 88U); push_data_block = DefineVar(struct_type, spv::StorageClass::PushConstant); Name(push_data_block, "push_data"); interfaces.push_back(push_data_block); @@ -328,47 +435,76 @@ void EmitContext::DefinePushDataBlock() { void EmitContext::DefineBuffers() { boost::container::small_vector type_ids; - for (u32 i = 0; const auto& buffer : info.buffers) { - const auto* data_types = True(buffer.used_types & IR::Type::F32) ? &F32 : &U32; - const Id data_type = (*data_types)[1]; - const Id record_array_type{buffer.is_storage - ? TypeRuntimeArray(data_type) - : TypeArray(data_type, ConstU32(buffer.length))}; + const auto define_struct = [&](Id record_array_type, bool is_instance_data) { const Id struct_type{TypeStruct(record_array_type)}; - if (std::ranges::find(type_ids, record_array_type.value, &Id::value) == type_ids.end()) { - Decorate(record_array_type, spv::Decoration::ArrayStride, 4); - const auto name = - buffer.is_instance_data - ? fmt::format("{}_instance_data{}_{}{}", stage, i, 'f', - sizeof(float) * CHAR_BIT) - : fmt::format("{}_cbuf_block_{}{}", stage, 'f', sizeof(float) * CHAR_BIT); - Name(struct_type, name); - Decorate(struct_type, spv::Decoration::Block); - MemberName(struct_type, 0, "data"); - MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); - type_ids.push_back(record_array_type); + if (std::ranges::find(type_ids, record_array_type.value, &Id::value) != type_ids.end()) { + return struct_type; } + Decorate(record_array_type, spv::Decoration::ArrayStride, 4); + const auto name = is_instance_data ? fmt::format("{}_instance_data_f32", stage) + : fmt::format("{}_cbuf_block_f32", stage); + Name(struct_type, name); + Decorate(struct_type, spv::Decoration::Block); + MemberName(struct_type, 0, "data"); + MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); + type_ids.push_back(record_array_type); + return struct_type; + }; + + for (const auto& desc : info.buffers) { + const auto sharp = desc.GetSharp(info); + const bool is_storage = desc.IsStorage(sharp); + const u32 array_size = sharp.NumDwords() != 0 ? sharp.NumDwords() : MaxUboDwords; + const auto* data_types = True(desc.used_types & IR::Type::F32) ? &F32 : &U32; + const Id data_type = (*data_types)[1]; + const Id record_array_type{is_storage ? TypeRuntimeArray(data_type) + : TypeArray(data_type, ConstU32(array_size))}; + const Id struct_type{define_struct(record_array_type, desc.is_instance_data)}; const auto storage_class = - buffer.is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform; + is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform; const Id struct_pointer_type{TypePointer(storage_class, struct_type)}; const Id pointer_type = TypePointer(storage_class, data_type); const Id id{AddGlobalVariable(struct_pointer_type, storage_class)}; - Decorate(id, spv::Decoration::Binding, binding); + Decorate(id, spv::Decoration::Binding, binding.unified++); Decorate(id, spv::Decoration::DescriptorSet, 0U); - Name(id, fmt::format("{}_{}", buffer.is_storage ? "ssbo" : "cbuf", buffer.sgpr_base)); + if (is_storage && !desc.is_written) { + Decorate(id, spv::Decoration::NonWritable); + } + Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "cbuf", desc.sgpr_base)); buffers.push_back({ .id = id, - .binding = binding++, + .binding = binding.buffer++, .data_types = data_types, .pointer_type = pointer_type, - .dfmt = buffer.dfmt, - .nfmt = buffer.nfmt, - .stride = buffer.GetVsharp(info).GetStride(), }); interfaces.push_back(id); - i++; + } +} + +void EmitContext::DefineTextureBuffers() { + for (const auto& desc : info.texture_buffers) { + const bool is_integer = + desc.nfmt == AmdGpu::NumberFormat::Uint || desc.nfmt == AmdGpu::NumberFormat::Sint; + const VectorIds& sampled_type{GetAttributeType(*this, desc.nfmt)}; + const u32 sampled = desc.is_written ? 2 : 1; + const Id image_type{TypeImage(sampled_type[1], spv::Dim::Buffer, false, false, false, + sampled, spv::ImageFormat::Unknown)}; + const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; + const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; + Decorate(id, spv::Decoration::Binding, binding.unified++); + Decorate(id, spv::Decoration::DescriptorSet, 0U); + Name(id, fmt::format("{}_{}", desc.is_written ? "imgbuf" : "texbuf", desc.sgpr_base)); + texture_buffers.push_back({ + .id = id, + .binding = binding.buffer++, + .image_type = image_type, + .result_type = sampled_type[4], + .is_integer = is_integer, + .is_storage = desc.is_written, + }); + interfaces.push_back(id); } } @@ -405,6 +541,10 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { image.GetNumberFmt() == AmdGpu::NumberFormat::Float) { return spv::ImageFormat::Rg16f; } + if (image.GetDataFmt() == AmdGpu::DataFormat::Format16_16 && + image.GetNumberFmt() == AmdGpu::NumberFormat::Snorm) { + return spv::ImageFormat::Rg16Snorm; + } if (image.GetDataFmt() == AmdGpu::DataFormat::Format8_8 && image.GetNumberFmt() == AmdGpu::NumberFormat::Unorm) { return spv::ImageFormat::Rg8; @@ -443,7 +583,7 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { const auto image = ctx.info.ReadUd(desc.sgpr_base, desc.dword_offset); - const auto format = desc.is_storage ? GetFormat(image) : spv::ImageFormat::Unknown; + const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown; const u32 sampled = desc.is_storage ? 2 : 1; switch (desc.type) { case AmdGpu::ImageType::Color1D: @@ -454,10 +594,13 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, false, sampled, format); case AmdGpu::ImageType::Color2DArray: return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, true, false, sampled, format); + case AmdGpu::ImageType::Color2DMsaa: + 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, false, false, sampled, format); + return ctx.TypeImage(sampled_type, spv::Dim::Cube, false, desc.is_array, false, sampled, + format); default: break; } @@ -466,64 +609,57 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) { void EmitContext::DefineImagesAndSamplers() { for (const auto& image_desc : info.images) { - const VectorIds* data_types = [&] { - switch (image_desc.nfmt) { - case AmdGpu::NumberFormat::Uint: - return &U32; - case AmdGpu::NumberFormat::Sint: - return &S32; - default: - return &F32; - } - }(); - const Id sampled_type = data_types->Get(1); + const bool is_integer = image_desc.nfmt == AmdGpu::NumberFormat::Uint || + image_desc.nfmt == AmdGpu::NumberFormat::Sint; + const VectorIds& data_types = GetAttributeType(*this, image_desc.nfmt); + const Id sampled_type = data_types[1]; const Id image_type{ImageType(*this, image_desc, sampled_type)}; const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; - Decorate(id, spv::Decoration::Binding, binding); + Decorate(id, spv::Decoration::Binding, binding.unified++); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, fmt::format("{}_{}{}_{:02x}", stage, "img", image_desc.sgpr_base, image_desc.dword_offset)); images.push_back({ + .data_types = &data_types, .id = id, - .data_types = data_types, .sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type), .pointer_type = pointer_type, .image_type = image_type, + .is_integer = is_integer, + .is_storage = image_desc.is_storage, }); interfaces.push_back(id); - ++binding; } - - image_u32 = TypePointer(spv::StorageClass::Image, U32[1]); - + if (std::ranges::any_of(info.images, &ImageResource::is_atomic)) { + image_u32 = TypePointer(spv::StorageClass::Image, U32[1]); + } if (info.samplers.empty()) { return; } - sampler_type = TypeSampler(); sampler_pointer_type = TypePointer(spv::StorageClass::UniformConstant, sampler_type); for (const auto& samp_desc : info.samplers) { const Id id{AddGlobalVariable(sampler_pointer_type, spv::StorageClass::UniformConstant)}; - Decorate(id, spv::Decoration::Binding, binding); + Decorate(id, spv::Decoration::Binding, binding.unified++); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, fmt::format("{}_{}{}_{:02x}", stage, "samp", samp_desc.sgpr_base, samp_desc.dword_offset)); samplers.push_back(id); interfaces.push_back(id); - ++binding; } } void EmitContext::DefineSharedMemory() { - static constexpr size_t DefaultSharedMemSize = 16_KB; + static constexpr size_t DefaultSharedMemSize = 2_KB; if (!info.uses_shared) { return; } - if (info.shared_memory_size == 0) { - info.shared_memory_size = DefaultSharedMemSize; + u32 shared_memory_size = runtime_info.cs_info.shared_memory_size; + if (shared_memory_size == 0) { + shared_memory_size = DefaultSharedMemSize; } - const u32 num_elements{Common::DivCeil(info.shared_memory_size, 4U)}; + const u32 num_elements{Common::DivCeil(shared_memory_size, 4U)}; const Id type{TypeArray(U32[1], ConstU32(num_elements))}; shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 768b591f5..147b4c845 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -6,9 +6,10 @@ #include #include +#include "shader_recompiler/backend/bindings.h" +#include "shader_recompiler/info.h" #include "shader_recompiler/ir/program.h" #include "shader_recompiler/profile.h" -#include "shader_recompiler/runtime_info.h" namespace Shader::Backend::SPIRV { @@ -36,7 +37,8 @@ struct VectorIds { class EmitContext final : public Sirit::Module { public: - explicit EmitContext(const Profile& profile, IR::Program& program, u32& binding); + explicit EmitContext(const Profile& profile, const RuntimeInfo& runtime_info, const Info& info, + Bindings& binding); ~EmitContext(); Id Def(const IR::Value& value); @@ -124,7 +126,8 @@ public: return ConstantComposite(type, constituents); } - Info& info; + const Info& info; + const RuntimeInfo& runtime_info; const Profile& profile; Stage stage{}; @@ -163,10 +166,14 @@ public: Id input_s32{}; Id output_u32{}; Id output_f32{}; + Id output_s32{}; + + Id gl_in{}; boost::container::small_vector interfaces; Id output_position{}; + Id primitive_id{}; Id vertex_index{}; Id instance_id{}; Id push_data_block{}; @@ -174,8 +181,6 @@ public: Id frag_coord{}; Id front_facing{}; Id frag_depth{}; - std::array frag_color{}; - std::array frag_num_comp{}; Id clip_distances{}; Id cull_distances{}; @@ -193,11 +198,13 @@ public: Id shared_memory_u32_type{}; struct TextureDefinition { - Id id; const VectorIds* data_types; + Id id; Id sampled_type; Id pointer_type; Id image_type; + bool is_integer = false; + bool is_storage = false; }; struct BufferDefinition { @@ -207,13 +214,20 @@ public: u32 binding; const VectorIds* data_types; Id pointer_type; - AmdGpu::DataFormat dfmt; - AmdGpu::NumberFormat nfmt; - u32 stride; + }; + struct TextureBufferDefinition { + Id id; + Id coord_offset; + u32 binding; + Id image_type; + Id result_type; + bool is_integer = false; + bool is_storage = false; }; - u32& binding; + Bindings& binding; boost::container::small_vector buffers; + boost::container::small_vector texture_buffers; boost::container::small_vector images; boost::container::small_vector samplers; @@ -225,11 +239,13 @@ public: Id pointer_type; Id component_type; u32 num_components; + bool is_integer{}; bool is_default{}; s32 buffer_handle{-1}; }; - std::array input_params{}; - std::array output_params{}; + std::array input_params{}; + std::array output_params{}; + std::array frag_outputs{}; private: void DefineArithmeticTypes(); @@ -238,10 +254,12 @@ private: void DefineOutputs(); void DefinePushDataBlock(); void DefineBuffers(); + void DefineTextureBuffers(); void DefineImagesAndSamplers(); void DefineSharedMemory(); - SpirvAttribute GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id); + SpirvAttribute GetAttributeInfo(AmdGpu::NumberFormat fmt, Id id, u32 num_components, + bool output); }; } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp index f79dc6b50..354196d31 100644 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ b/src/shader_recompiler/frontend/control_flow_graph.cpp @@ -21,8 +21,12 @@ struct Compare { } }; -static IR::Condition MakeCondition(Opcode opcode) { - switch (opcode) { +static IR::Condition MakeCondition(const GcnInst& inst) { + if (inst.IsCmpx()) { + return IR::Condition::Execnz; + } + + switch (inst.opcode) { case Opcode::S_CBRANCH_SCC0: return IR::Condition::Scc0; case Opcode::S_CBRANCH_SCC1: @@ -37,7 +41,6 @@ static IR::Condition MakeCondition(Opcode opcode) { return IR::Condition::Execnz; case Opcode::S_AND_SAVEEXEC_B64: case Opcode::S_ANDN2_B64: - case Opcode::V_CMPX_NE_U32: return IR::Condition::Execnz; default: return IR::Condition::True; @@ -94,7 +97,8 @@ void CFG::EmitDivergenceLabels() { // While this instruction does not save EXEC it is often used paired // with SAVEEXEC to mask the threads that didn't pass the condition // of initial branch. - inst.opcode == Opcode::S_ANDN2_B64 || inst.opcode == Opcode::V_CMPX_NE_U32; + (inst.opcode == Opcode::S_ANDN2_B64 && inst.dst[0].field == OperandField::ExecLo) || + inst.IsCmpx(); }; const auto is_close_scope = [](const GcnInst& inst) { // Closing an EXEC scope can be either a branch instruction @@ -104,7 +108,8 @@ void CFG::EmitDivergenceLabels() { // Sometimes compiler might insert instructions between the SAVEEXEC and the branch. // Those instructions need to be wrapped in the condition as well so allow branch // as end scope instruction. - inst.opcode == Opcode::S_CBRANCH_EXECZ || inst.opcode == Opcode::S_ANDN2_B64; + inst.opcode == Opcode::S_CBRANCH_EXECZ || inst.opcode == Opcode::S_ENDPGM || + (inst.opcode == Opcode::S_ANDN2_B64 && inst.dst[0].field == OperandField::ExecLo); }; // Since we will be adding new labels, avoid iterating those as well. @@ -121,7 +126,8 @@ void CFG::EmitDivergenceLabels() { s32 curr_begin = -1; for (size_t index = GetIndex(start); index < end_index; index++) { const auto& inst = inst_list[index]; - if (is_close_scope(inst) && curr_begin != -1) { + const bool is_close = is_close_scope(inst); + if ((is_close || index == end_index - 1) && curr_begin != -1) { // If there are no instructions inside scope don't do anything. if (index - curr_begin == 1) { curr_begin = -1; @@ -132,8 +138,16 @@ void CFG::EmitDivergenceLabels() { const auto& save_inst = inst_list[curr_begin]; const Label label = index_to_pc[curr_begin] + save_inst.length; AddLabel(label); - // Add a label to the close scope instruction as well. - AddLabel(index_to_pc[index]); + // Add a label to the close scope instruction. + // There are 3 cases where we need to close a scope. + // * Close scope instruction inside the block + // * Close scope instruction at the end of the block (cbranch or endpgm) + // * Normal instruction at the end of the block + // For the last case we must NOT add a label as that would cause + // the instruction to be separated into its own basic block. + if (is_close) { + AddLabel(index_to_pc[index]); + } // Reset scope begin. curr_begin = -1; } @@ -171,7 +185,7 @@ void CFG::EmitBlocks() { block->begin_index = GetIndex(start); block->end_index = end_index; block->end_inst = end_inst; - block->cond = MakeCondition(end_inst.opcode); + block->cond = MakeCondition(end_inst); blocks.insert(*block); } } @@ -188,7 +202,7 @@ void CFG::LinkBlocks() { const auto end_inst{block.end_inst}; // Handle divergence block inserted here. if (end_inst.opcode == Opcode::S_AND_SAVEEXEC_B64 || - end_inst.opcode == Opcode::S_ANDN2_B64 || end_inst.opcode == Opcode::V_CMPX_NE_U32) { + end_inst.opcode == Opcode::S_ANDN2_B64 || end_inst.IsCmpx()) { // Blocks are stored ordered by address in the set auto next_it = std::next(it); auto* target_block = &(*next_it); diff --git a/src/shader_recompiler/frontend/copy_shader.cpp b/src/shader_recompiler/frontend/copy_shader.cpp new file mode 100644 index 000000000..b2c795667 --- /dev/null +++ b/src/shader_recompiler/frontend/copy_shader.cpp @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "shader_recompiler/frontend/copy_shader.h" +#include "shader_recompiler/frontend/decode.h" +#include "shader_recompiler/ir/attribute.h" + +namespace Shader { + +CopyShaderData ParseCopyShader(std::span code) { + Gcn::GcnCodeSlice code_slice{code.data(), code.data() + code.size()}; + Gcn::GcnDecodeContext decoder; + + constexpr u32 token_mov_vcchi = 0xBEEB03FF; + ASSERT_MSG(code[0] == token_mov_vcchi, "First instruction is not s_mov_b32 vcc_hi, #imm"); + + std::array offsets{}; + offsets.fill(-1); + + std::array sources{}; + sources.fill(-1); + + CopyShaderData data{}; + auto last_attr{IR::Attribute::Position0}; + while (!code_slice.atEnd()) { + auto inst = decoder.decodeInstruction(code_slice); + switch (inst.opcode) { + case Gcn::Opcode::S_MOVK_I32: { + sources[inst.dst[0].code] = inst.control.sopk.simm; + break; + } + case Gcn::Opcode::EXP: { + const auto& exp = inst.control.exp; + const IR::Attribute semantic = static_cast(exp.target); + for (int i = 0; i < inst.src_count; ++i) { + const auto ofs = offsets[inst.src[i].code]; + if (ofs != -1) { + data.attr_map[ofs] = {semantic, i}; + if (semantic > last_attr) { + last_attr = semantic; + } + } + } + break; + } + case Gcn::Opcode::BUFFER_LOAD_DWORD: { + offsets[inst.src[1].code] = inst.control.mubuf.offset; + if (inst.src[3].field != Gcn::OperandField::ConstZero) { + const u32 index = inst.src[3].code; + ASSERT(sources[index] != -1); + offsets[inst.src[1].code] += sources[index]; + } + break; + } + default: + break; + } + } + + if (last_attr != IR::Attribute::Position0) { + data.num_attrs = static_cast(last_attr) - static_cast(IR::Attribute::Param0) + 1; + } + + return data; +} + +} // namespace Shader diff --git a/src/shader_recompiler/frontend/copy_shader.h b/src/shader_recompiler/frontend/copy_shader.h new file mode 100644 index 000000000..55cc31ebd --- /dev/null +++ b/src/shader_recompiler/frontend/copy_shader.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/types.h" +#include "shader_recompiler/ir/attribute.h" + +namespace Shader { + +struct CopyShaderData { + std::unordered_map> attr_map; + u32 num_attrs{0}; +}; + +CopyShaderData ParseCopyShader(std::span code); + +} // namespace Shader diff --git a/src/shader_recompiler/frontend/decode.cpp b/src/shader_recompiler/frontend/decode.cpp index b5c02d747..796bed127 100644 --- a/src/shader_recompiler/frontend/decode.cpp +++ b/src/shader_recompiler/frontend/decode.cpp @@ -5,6 +5,8 @@ #include "common/assert.h" #include "shader_recompiler/frontend/decode.h" +#include "magic_enum.hpp" + namespace Shader::Gcn { namespace bit { @@ -160,6 +162,8 @@ uint32_t GcnDecodeContext::getEncodingLength(InstEncoding encoding) { case InstEncoding::EXP: instLength = sizeof(uint64_t); break; + default: + break; } return instLength; } @@ -215,6 +219,8 @@ uint32_t GcnDecodeContext::getOpMapOffset(InstEncoding encoding) { case InstEncoding::VOP2: offset = (uint32_t)OpcodeMap::OP_MAP_VOP2; break; + default: + break; } return offset; } @@ -253,7 +259,9 @@ void GcnDecodeContext::updateInstructionMeta(InstEncoding encoding) { ASSERT_MSG(instFormat.src_type != ScalarType::Undefined && instFormat.dst_type != ScalarType::Undefined, - "TODO: Instruction format table not complete, please fix it manually."); + "Instruction format table incomplete for opcode {} ({}, encoding = {})", + magic_enum::enum_name(m_instruction.opcode), u32(m_instruction.opcode), + magic_enum::enum_name(encoding)); m_instruction.inst_class = instFormat.inst_class; m_instruction.category = instFormat.inst_category; @@ -305,8 +313,11 @@ void GcnDecodeContext::repairOperandType() { m_instruction.src[2].type = ScalarType::Uint64; break; case Opcode::IMAGE_GATHER4_C: + case Opcode::IMAGE_GATHER4_C_O: m_instruction.src[0].type = ScalarType::Any; break; + default: + break; } } @@ -359,6 +370,8 @@ void GcnDecodeContext::decodeInstruction32(InstEncoding encoding, GcnCodeSlice& case InstEncoding::VINTRP: decodeInstructionVINTRP(hexInstruction); break; + default: + break; } } @@ -383,6 +396,8 @@ void GcnDecodeContext::decodeInstruction64(InstEncoding encoding, GcnCodeSlice& case InstEncoding::EXP: decodeInstructionEXP(hexInstruction); break; + default: + break; } } @@ -489,9 +504,8 @@ void GcnDecodeContext::decodeInstructionVOP1(u32 hexInstruction) { OpcodeVOP1 vop1Op = static_cast(op); if (vop1Op == OpcodeVOP1::V_READFIRSTLANE_B32) { - m_instruction.dst[1].field = getOperandField(vdst); - m_instruction.dst[1].type = ScalarType::Uint32; - m_instruction.dst[1].code = vdst; + m_instruction.dst[0].field = getOperandField(vdst); + m_instruction.dst[0].type = ScalarType::Uint32; } } @@ -533,13 +547,15 @@ void GcnDecodeContext::decodeInstructionVOP2(u32 hexInstruction) { m_instruction.dst_count = 1; OpcodeVOP2 vop2Op = static_cast(op); - if (vop2Op == OpcodeVOP2::V_READLANE_B32 || vop2Op == OpcodeVOP2::V_WRITELANE_B32) { + if (vop2Op == OpcodeVOP2::V_READLANE_B32) { // vsrc1 is scalar for lane instructions m_instruction.src[1].field = getOperandField(vsrc1); // dst is sgpr - m_instruction.dst[1].field = OperandField::ScalarGPR; - m_instruction.dst[1].type = ScalarType::Uint32; - m_instruction.dst[1].code = vdst; + m_instruction.dst[0].field = getOperandField(vdst); + m_instruction.dst[0].type = ScalarType::Uint32; + } else if (vop2Op == OpcodeVOP2::V_WRITELANE_B32) { + m_instruction.src[1].field = getOperandField(vsrc1); + // dst is vgpr, as normal } else if (IsVop3BEncoding(m_instruction.opcode)) { m_instruction.dst[1].field = OperandField::VccLo; m_instruction.dst[1].type = ScalarType::Uint64; @@ -638,7 +654,7 @@ void GcnDecodeContext::decodeInstructionVOP3(uint64_t hexInstruction) { OpcodeVOP3 vop3Op = static_cast(op); if (IsVop3BEncoding(m_instruction.opcode)) { - m_instruction.dst[1].field = OperandField::ScalarGPR; + m_instruction.dst[1].field = getOperandField(sdst); m_instruction.dst[1].type = ScalarType::Uint64; m_instruction.dst[1].code = sdst; } else { @@ -646,13 +662,11 @@ void GcnDecodeContext::decodeInstructionVOP3(uint64_t hexInstruction) { m_instruction.dst[1].field = getOperandField(vdst); m_instruction.dst[1].type = ScalarType::Uint64; m_instruction.dst[1].code = vdst; - } else if (vop3Op >= OpcodeVOP3::V_READLANE_B32 && vop3Op <= OpcodeVOP3::V_WRITELANE_B32) { - // vsrc1 is scalar for lane instructions - m_instruction.src[1].field = getOperandField(src1); - // dst is sgpr for lane instruction - m_instruction.dst[1].field = OperandField::ScalarGPR; - m_instruction.dst[1].type = ScalarType::Uint32; - m_instruction.dst[1].code = vdst; + } else if (vop3Op == OpcodeVOP3::V_READLANE_B32 || + vop3Op == OpcodeVOP3::V_READFIRSTLANE_B32) { + m_instruction.dst[0].field = getOperandField(vdst); + m_instruction.dst[0].type = ScalarType::Uint32; + // WRITELANE can be decoded like other VOP3's } } @@ -991,6 +1005,8 @@ u32 GcnDecodeContext::getMimgModifier(Opcode opcode) { flags.set(MimgModifier::Pcf, MimgModifier::CoarseDerivative, MimgModifier::LodClamp, MimgModifier::Offset); break; + default: + break; } return flags.raw(); @@ -1016,6 +1032,7 @@ void GcnDecodeContext::decodeInstructionMIMG(uint64_t hexInstruction) { m_instruction.control.mimg = *reinterpret_cast(&hexInstruction); m_instruction.control.mimg.mod = getMimgModifier(m_instruction.opcode); + ASSERT(m_instruction.control.mimg.r128 == 0); } void GcnDecodeContext::decodeInstructionDS(uint64_t hexInstruction) { diff --git a/src/shader_recompiler/frontend/fetch_shader.cpp b/src/shader_recompiler/frontend/fetch_shader.cpp index 81e4093f2..16938410c 100644 --- a/src/shader_recompiler/frontend/fetch_shader.cpp +++ b/src/shader_recompiler/frontend/fetch_shader.cpp @@ -3,6 +3,7 @@ #include #include +#include "common/assert.h" #include "shader_recompiler/frontend/decode.h" #include "shader_recompiler/frontend/fetch_shader.h" @@ -33,8 +34,8 @@ namespace Shader::Gcn { * We take the reverse way, extract the original input semantics from these instructions. **/ -std::vector ParseFetchShader(const u32* code, u32* out_size) { - std::vector attributes; +FetchShaderData ParseFetchShader(const u32* code, u32* out_size) { + FetchShaderData data{}; GcnCodeSlice code_slice(code, code + std::numeric_limits::max()); GcnDecodeContext decoder; @@ -59,6 +60,21 @@ std::vector ParseFetchShader(const u32* code, u32* out_size) { continue; } + if (inst.opcode == Opcode::V_ADD_I32) { + const auto vgpr = inst.dst[0].code; + const auto sgpr = s8(inst.src[0].code); + switch (vgpr) { + case 0: // V0 is always the vertex offset + data.vertex_offset_sgpr = sgpr; + break; + case 3: // V3 is always the instance offset + data.instance_offset_sgpr = sgpr; + break; + default: + UNREACHABLE(); + } + } + if (inst.inst_class == InstClass::VectorMemBufFmt) { // SRSRC is in units of 4 SPGRs while SBASE is in pairs of SGPRs const u32 base_sgpr = inst.src[2].code * 4; @@ -68,7 +84,7 @@ std::vector ParseFetchShader(const u32* code, u32* out_size) { const auto it = std::ranges::find_if( loads, [&](VsharpLoad& load) { return load.dst_reg == base_sgpr; }); - auto& attrib = attributes.emplace_back(); + auto& attrib = data.attributes.emplace_back(); attrib.semantic = semantic_index++; attrib.dest_vgpr = inst.src[1].code; attrib.num_elements = inst.control.mubuf.count; @@ -83,7 +99,7 @@ std::vector ParseFetchShader(const u32* code, u32* out_size) { } } - return attributes; + return data; } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/fetch_shader.h b/src/shader_recompiler/frontend/fetch_shader.h index 0858061a1..0e5d15419 100644 --- a/src/shader_recompiler/frontend/fetch_shader.h +++ b/src/shader_recompiler/frontend/fetch_shader.h @@ -17,6 +17,12 @@ struct VertexAttribute { u8 instance_data; ///< Indicates that the buffer will be accessed in instance rate }; -std::vector ParseFetchShader(const u32* code, u32* out_size); +struct FetchShaderData { + std::vector attributes; + s8 vertex_offset_sgpr = -1; ///< SGPR of vertex offset from VADDR + s8 instance_offset_sgpr = -1; ///< SGPR of instance offset from VADDR +}; + +FetchShaderData ParseFetchShader(const u32* code, u32* out_size); } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/format.cpp b/src/shader_recompiler/frontend/format.cpp index 8df3ac364..4f0922e2e 100644 --- a/src/shader_recompiler/frontend/format.cpp +++ b/src/shader_recompiler/frontend/format.cpp @@ -1786,8 +1786,7 @@ constexpr std::array InstructionFormatVOP3 = {{ constexpr std::array InstructionFormatVOP1 = {{ // 0 = V_NOP - {InstClass::VectorMisc, InstCategory::VectorALU, 0, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMisc, InstCategory::VectorALU, 0, 1, ScalarType::Any, ScalarType::Any}, // 1 = V_MOV_B32 {InstClass::VectorRegMov, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, @@ -3603,8 +3602,8 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, // 79 = IMAGE_GATHER4_C_LZ - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Uint32}, // 80 = IMAGE_GATHER4_O {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, @@ -3626,8 +3625,8 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, // 88 = IMAGE_GATHER4_C_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 89 = IMAGE_GATHER4_C_CL_O {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, @@ -3643,8 +3642,8 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, // 95 = IMAGE_GATHER4_C_LZ_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 96 = IMAGE_GET_LOD {InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, ScalarType::Float32}, @@ -3656,8 +3655,8 @@ constexpr std::array InstructionFormatMIMG = {{ {}, {}, // 104 = IMAGE_SAMPLE_CD - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, + ScalarType::Float32}, // 105 = IMAGE_SAMPLE_CD_CL {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, @@ -3719,8 +3718,9 @@ InstFormat InstructionFormat(InstEncoding encoding, uint32_t opcode) { return InstructionFormatSOP2[opcode]; case InstEncoding::VOP2: return InstructionFormatVOP2[opcode]; + default: + UNREACHABLE(); } - UNREACHABLE(); return {}; } diff --git a/src/shader_recompiler/frontend/instruction.cpp b/src/shader_recompiler/frontend/instruction.cpp index d4847708b..a0c132053 100644 --- a/src/shader_recompiler/frontend/instruction.cpp +++ b/src/shader_recompiler/frontend/instruction.cpp @@ -7,7 +7,7 @@ namespace Shader::Gcn { u32 GcnInst::BranchTarget(u32 pc) const { - const s16 simm = static_cast(control.sopp.simm * 4); + const s32 simm = static_cast(control.sopp.simm) * 4; const u32 target = pc + simm + 4; return target; } @@ -47,4 +47,18 @@ bool GcnInst::IsConditionalBranch() const { return false; } +bool GcnInst::IsCmpx() const { + if ((opcode >= Opcode::V_CMPX_F_F32 && opcode <= Opcode::V_CMPX_T_F32) || + (opcode >= Opcode::V_CMPX_F_F64 && opcode <= Opcode::V_CMPX_T_F64) || + (opcode >= Opcode::V_CMPSX_F_F32 && opcode <= Opcode::V_CMPSX_T_F32) || + (opcode >= Opcode::V_CMPSX_F_F64 && opcode <= Opcode::V_CMPSX_T_F64) || + (opcode >= Opcode::V_CMPX_F_I32 && opcode <= Opcode::V_CMPX_CLASS_F32) || + (opcode >= Opcode::V_CMPX_F_I64 && opcode <= Opcode::V_CMPX_CLASS_F64) || + (opcode >= Opcode::V_CMPX_F_U32 && opcode <= Opcode::V_CMPX_T_U32) || + (opcode >= Opcode::V_CMPX_F_U64 && opcode <= Opcode::V_CMPX_T_U64)) { + return true; + } + return false; +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/instruction.h b/src/shader_recompiler/frontend/instruction.h index f83f43db5..7c2e0bd1e 100644 --- a/src/shader_recompiler/frontend/instruction.h +++ b/src/shader_recompiler/frontend/instruction.h @@ -203,6 +203,7 @@ struct GcnInst { bool IsUnconditionalBranch() const; bool IsConditionalBranch() const; bool IsFork() const; + bool IsCmpx() const; }; } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/opcodes.h b/src/shader_recompiler/frontend/opcodes.h index cdc1e4746..7390a3940 100644 --- a/src/shader_recompiler/frontend/opcodes.h +++ b/src/shader_recompiler/frontend/opcodes.h @@ -2491,4 +2491,23 @@ enum class ImageAddrComponent : u32 { Clamp, }; +struct SendMsgSimm { + enum class Message : u32 { + Interrupt = 1, + Gs = 2, + GsDone = 3, + System = 15, + }; + + enum class GsOp : u32 { + Nop = 0, + Cut = 1, + Emit = 2, + EmitCut = 3, + }; + + Message msg : 4; + GsOp op : 2; +}; + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/structured_control_flow.cpp b/src/shader_recompiler/frontend/structured_control_flow.cpp index a1231b39a..11b40d07c 100644 --- a/src/shader_recompiler/frontend/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/structured_control_flow.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -601,13 +602,14 @@ public: Common::ObjectPool& block_pool_, Common::ObjectPool& stmt_pool_, Statement& root_stmt, IR::AbstractSyntaxList& syntax_list_, std::span inst_list_, - Info& info_, const Profile& profile_) + Info& info_, const RuntimeInfo& runtime_info_, const Profile& profile_) : stmt_pool{stmt_pool_}, inst_pool{inst_pool_}, block_pool{block_pool_}, - syntax_list{syntax_list_}, inst_list{inst_list_}, info{info_}, profile{profile_} { + syntax_list{syntax_list_}, inst_list{inst_list_}, info{info_}, + runtime_info{runtime_info_}, profile{profile_} { Visit(root_stmt, nullptr, nullptr); IR::Block& first_block{*syntax_list.front().data.block}; - Translator{&first_block, info, profile}.EmitPrologue(); + Translator{&first_block, info, runtime_info, profile}.EmitPrologue(); } private: @@ -636,7 +638,7 @@ private: const u32 start = stmt.block->begin_index; const u32 size = stmt.block->end_index - start + 1; Translate(current_block, stmt.block->begin, inst_list.subspan(start, size), - info, profile); + info, runtime_info, profile); } break; } @@ -816,19 +818,20 @@ private: const Block dummy_flow_block{.is_dummy = true}; std::span inst_list; Info& info; + const RuntimeInfo& runtime_info; const Profile& profile; }; } // Anonymous namespace IR::AbstractSyntaxList BuildASL(Common::ObjectPool& inst_pool, Common::ObjectPool& block_pool, CFG& cfg, Info& info, - const Profile& profile) { + const RuntimeInfo& runtime_info, const Profile& profile) { Common::ObjectPool stmt_pool{64}; GotoPass goto_pass{cfg, stmt_pool}; Statement& root{goto_pass.RootStatement()}; IR::AbstractSyntaxList syntax_list; - TranslatePass{inst_pool, block_pool, stmt_pool, root, - syntax_list, cfg.inst_list, info, profile}; + TranslatePass{inst_pool, block_pool, stmt_pool, root, syntax_list, + cfg.inst_list, info, runtime_info, profile}; ASSERT_MSG(!info.translation_failed, "Shader translation has failed"); return syntax_list; } diff --git a/src/shader_recompiler/frontend/structured_control_flow.h b/src/shader_recompiler/frontend/structured_control_flow.h index f5a540518..2119484e3 100644 --- a/src/shader_recompiler/frontend/structured_control_flow.h +++ b/src/shader_recompiler/frontend/structured_control_flow.h @@ -11,12 +11,14 @@ namespace Shader { struct Info; struct Profile; +struct RuntimeInfo; } // namespace Shader namespace Shader::Gcn { [[nodiscard]] IR::AbstractSyntaxList BuildASL(Common::ObjectPool& inst_pool, Common::ObjectPool& block_pool, CFG& cfg, - Info& info, const Profile& profile); + Info& info, const RuntimeInfo& runtime_info, + const Profile& profile); } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index b7b5aa138..a453023fc 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -7,41 +7,150 @@ namespace Shader::Gcn { void Translator::EmitDataShare(const GcnInst& inst) { switch (inst.opcode) { - case Opcode::DS_SWIZZLE_B32: - return DS_SWIZZLE_B32(inst); - case Opcode::DS_READ_B32: - return DS_READ(32, false, false, inst); - case Opcode::DS_READ_B64: - return DS_READ(64, false, false, inst); - case Opcode::DS_READ2_B32: - return DS_READ(32, false, true, inst); - case Opcode::DS_READ2_B64: - return DS_READ(64, false, true, inst); - case Opcode::DS_WRITE_B32: - return DS_WRITE(32, false, false, inst); - case Opcode::DS_WRITE_B64: - return DS_WRITE(64, false, false, inst); - case Opcode::DS_WRITE2_B32: - return DS_WRITE(32, false, true, inst); - case Opcode::DS_WRITE2_B64: - return DS_WRITE(64, false, true, inst); + // DS case Opcode::DS_ADD_U32: return DS_ADD_U32(inst, false); + case Opcode::DS_MIN_I32: + return DS_MIN_U32(inst, true, false); + case Opcode::DS_MAX_I32: + return DS_MAX_U32(inst, true, false); case Opcode::DS_MIN_U32: - return DS_MIN_U32(inst, false); + return DS_MIN_U32(inst, false, false); case Opcode::DS_MAX_U32: - return DS_MAX_U32(inst, false); + return DS_MAX_U32(inst, false, false); + case Opcode::DS_WRITE_B32: + return DS_WRITE(32, false, false, false, inst); + case Opcode::DS_WRITE2_B32: + return DS_WRITE(32, false, true, false, inst); + case Opcode::DS_WRITE2ST64_B32: + return DS_WRITE(32, false, true, true, inst); case Opcode::DS_ADD_RTN_U32: return DS_ADD_U32(inst, true); case Opcode::DS_MIN_RTN_U32: - return DS_MIN_U32(inst, true); + return DS_MIN_U32(inst, false, true); case Opcode::DS_MAX_RTN_U32: - return DS_MAX_U32(inst, true); + return DS_MAX_U32(inst, false, true); + case Opcode::DS_SWIZZLE_B32: + return DS_SWIZZLE_B32(inst); + case Opcode::DS_READ_B32: + return DS_READ(32, false, false, false, inst); + case Opcode::DS_READ2_B32: + return DS_READ(32, false, true, false, inst); + case Opcode::DS_READ2ST64_B32: + return DS_READ(32, false, true, true, inst); + case Opcode::DS_CONSUME: + return DS_CONSUME(inst); + case Opcode::DS_APPEND: + return DS_APPEND(inst); + case Opcode::DS_WRITE_B64: + return DS_WRITE(64, false, false, false, inst); + case Opcode::DS_WRITE2_B64: + return DS_WRITE(64, false, true, false, inst); + case Opcode::DS_READ_B64: + return DS_READ(64, false, false, false, inst); + case Opcode::DS_READ2_B64: + return DS_READ(64, false, true, false, inst); default: LogMissingOpcode(inst); } } +// VOP2 + +void Translator::V_READFIRSTLANE_B32(const GcnInst& inst) { + const IR::U32 value{GetSrc(inst.src[0])}; + + if (info.stage != Stage::Compute) { + SetDst(inst.dst[0], value); + } else { + SetDst(inst.dst[0], ir.ReadFirstLane(value)); + } +} + +void Translator::V_READLANE_B32(const GcnInst& inst) { + const IR::ScalarReg dst{inst.dst[0].code}; + const IR::U32 value{GetSrc(inst.src[0])}; + const IR::U32 lane{GetSrc(inst.src[1])}; + ir.SetScalarReg(dst, ir.ReadLane(value, lane)); +} + +void Translator::V_WRITELANE_B32(const GcnInst& inst) { + const IR::VectorReg dst{inst.dst[0].code}; + const IR::U32 value{GetSrc(inst.src[0])}; + const IR::U32 lane{GetSrc(inst.src[1])}; + const IR::U32 old_value{GetSrc(inst.dst[0])}; + ir.SetVectorReg(dst, ir.WriteLane(old_value, value, lane)); +} + +// DS + +void Translator::DS_ADD_U32(const GcnInst& inst, bool rtn) { + const IR::U32 addr{GetSrc(inst.src[0])}; + const IR::U32 data{GetSrc(inst.src[1])}; + const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); + const IR::U32 addr_offset = ir.IAdd(addr, offset); + const IR::Value original_val = ir.SharedAtomicIAdd(addr_offset, data); + if (rtn) { + SetDst(inst.dst[0], IR::U32{original_val}); + } +} + +void Translator::DS_MIN_U32(const GcnInst& inst, bool is_signed, bool rtn) { + const IR::U32 addr{GetSrc(inst.src[0])}; + const IR::U32 data{GetSrc(inst.src[1])}; + const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); + const IR::U32 addr_offset = ir.IAdd(addr, offset); + const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, is_signed); + if (rtn) { + SetDst(inst.dst[0], IR::U32{original_val}); + } +} + +void Translator::DS_MAX_U32(const GcnInst& inst, bool is_signed, bool rtn) { + const IR::U32 addr{GetSrc(inst.src[0])}; + const IR::U32 data{GetSrc(inst.src[1])}; + const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); + const IR::U32 addr_offset = ir.IAdd(addr, offset); + const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, is_signed); + if (rtn) { + SetDst(inst.dst[0], IR::U32{original_val}); + } +} + +void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, + const GcnInst& inst) { + const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; + const IR::VectorReg data0{inst.src[1].code}; + const IR::VectorReg data1{inst.src[2].code}; + if (is_pair) { + const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1); + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); + if (bit_size == 32) { + ir.WriteShared(32, ir.GetVectorReg(data0), addr0); + } else { + ir.WriteShared( + 64, ir.CompositeConstruct(ir.GetVectorReg(data0), ir.GetVectorReg(data0 + 1)), + addr0); + } + const IR::U32 addr1 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset1 * adj))); + if (bit_size == 32) { + ir.WriteShared(32, ir.GetVectorReg(data1), addr1); + } else { + ir.WriteShared( + 64, ir.CompositeConstruct(ir.GetVectorReg(data1), ir.GetVectorReg(data1 + 1)), + addr1); + } + } else if (bit_size == 64) { + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0))); + const IR::Value data = + ir.CompositeConstruct(ir.GetVectorReg(data0), ir.GetVectorReg(data0 + 1)); + ir.WriteShared(bit_size, data, addr0); + } else { + const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0))); + ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0); + } +} + void Translator::DS_SWIZZLE_B32(const GcnInst& inst) { const u8 offset0 = inst.control.ds.offset0; const u8 offset1 = inst.control.ds.offset1; @@ -55,12 +164,13 @@ void Translator::DS_SWIZZLE_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.QuadShuffle(src, index)); } -void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst) { +void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, + const GcnInst& inst) { const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; IR::VectorReg dst_reg{inst.dst[0].code}; if (is_pair) { // Pair loads are either 32 or 64-bit - const u32 adj = bit_size == 32 ? 4 : 8; + const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1); const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); const IR::Value data0 = ir.LoadShared(bit_size, is_signed, addr0); if (bit_size == 32) { @@ -89,92 +199,18 @@ void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnIn } } -void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst) { - const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; - const IR::VectorReg data0{inst.src[1].code}; - const IR::VectorReg data1{inst.src[2].code}; - if (is_pair) { - const u32 adj = bit_size == 32 ? 4 : 8; - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); - if (bit_size == 32) { - ir.WriteShared(32, ir.GetVectorReg(data0), addr0); - } else { - ir.WriteShared( - 64, ir.CompositeConstruct(ir.GetVectorReg(data0), ir.GetVectorReg(data0 + 1)), - addr0); - } - const IR::U32 addr1 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset1 * adj))); - if (bit_size == 32) { - ir.WriteShared(32, ir.GetVectorReg(data1), addr1); - } else { - ir.WriteShared( - 64, ir.CompositeConstruct(ir.GetVectorReg(data1), ir.GetVectorReg(data1 + 1)), - addr1); - } - } else if (bit_size == 64) { - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0))); - const IR::Value data = - ir.CompositeConstruct(ir.GetVectorReg(data0), ir.GetVectorReg(data0 + 1)); - ir.WriteShared(bit_size, data, addr0); - } else { - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0))); - ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0); - } +void Translator::DS_APPEND(const GcnInst& inst) { + const u32 inst_offset = inst.control.ds.offset0; + const IR::U32 gds_offset = ir.IAdd(ir.GetM0(), ir.Imm32(inst_offset)); + const IR::U32 prev = ir.DataAppend(gds_offset); + SetDst(inst.dst[0], prev); } -void Translator::DS_ADD_U32(const GcnInst& inst, bool rtn) { - const IR::U32 addr{GetSrc(inst.src[0])}; - const IR::U32 data{GetSrc(inst.src[1])}; - const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); - const IR::U32 addr_offset = ir.IAdd(addr, offset); - IR::VectorReg dst_reg{inst.dst[0].code}; - const IR::Value original_val = ir.SharedAtomicIAdd(addr_offset, data); - if (rtn) { - SetDst(inst.dst[0], IR::U32{original_val}); - } -} - -void Translator::DS_MIN_U32(const GcnInst& inst, bool rtn) { - const IR::U32 addr{GetSrc(inst.src[0])}; - const IR::U32 data{GetSrc(inst.src[1])}; - const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); - const IR::U32 addr_offset = ir.IAdd(addr, offset); - IR::VectorReg dst_reg{inst.dst[0].code}; - const IR::Value original_val = ir.SharedAtomicIMin(addr_offset, data, false); - if (rtn) { - SetDst(inst.dst[0], IR::U32{original_val}); - } -} - -void Translator::DS_MAX_U32(const GcnInst& inst, bool rtn) { - const IR::U32 addr{GetSrc(inst.src[0])}; - const IR::U32 data{GetSrc(inst.src[1])}; - const IR::U32 offset = ir.Imm32(u32(inst.control.ds.offset0)); - const IR::U32 addr_offset = ir.IAdd(addr, offset); - IR::VectorReg dst_reg{inst.dst[0].code}; - const IR::Value original_val = ir.SharedAtomicIMax(addr_offset, data, false); - if (rtn) { - SetDst(inst.dst[0], IR::U32{original_val}); - } -} - -void Translator::S_BARRIER() { - ir.Barrier(); -} - -void Translator::V_READFIRSTLANE_B32(const GcnInst& inst) { - ASSERT(info.stage != Stage::Compute); - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::V_READLANE_B32(const GcnInst& inst) { - ASSERT(info.stage != Stage::Compute); - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::V_WRITELANE_B32(const GcnInst& inst) { - ASSERT(info.stage != Stage::Compute); - SetDst(inst.dst[0], GetSrc(inst.src[0])); +void Translator::DS_CONSUME(const GcnInst& inst) { + const u32 inst_offset = inst.control.ds.offset0; + const IR::U32 gds_offset = ir.IAdd(ir.GetM0(), ir.Imm32(inst_offset)); + const IR::U32 prev = ir.DataConsume(gds_offset); + SetDst(inst.dst[0], prev); } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/export.cpp b/src/shader_recompiler/frontend/translate/export.cpp index 889de21b7..f82f8fc1b 100644 --- a/src/shader_recompiler/frontend/translate/export.cpp +++ b/src/shader_recompiler/frontend/translate/export.cpp @@ -1,14 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" #include "shader_recompiler/frontend/translate/translate.h" +#include "shader_recompiler/runtime_info.h" namespace Shader::Gcn { void Translator::EmitExport(const GcnInst& inst) { if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) { - LOG_WARNING(Render_Recompiler, "An ambiguous export appeared in translation"); ir.Discard(ir.LogicalNot(ir.GetExec())); } @@ -21,12 +20,34 @@ void Translator::EmitExport(const GcnInst& inst) { IR::VectorReg(inst.src[3].code), }; + const auto swizzle = [&](u32 comp) { + if (!IR::IsMrt(attrib)) { + return comp; + } + 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 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, idx * 2); - ir.SetAttribute(attrib, g, idx * 2 + 1); + ir.SetAttribute(attrib, r, swizzle(idx * 2)); + ir.SetAttribute(attrib, g, swizzle(idx * 2 + 1)); }; // Components are float16 packed into a VGPR @@ -47,9 +68,12 @@ void Translator::EmitExport(const GcnInst& inst) { continue; } const IR::F32 comp = ir.GetVectorReg(vsrc[i]); - ir.SetAttribute(attrib, comp, i); + ir.SetAttribute(attrib, comp, swizzle(i)); } } + if (IR::IsMrt(attrib)) { + info.mrt_mask |= 1u << u8(attrib); + } } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 812d93bae..36c1ec85f 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -6,287 +6,190 @@ namespace Shader::Gcn { void Translator::EmitScalarAlu(const GcnInst& inst) { + switch (inst.encoding) { + case InstEncoding::SOPC: { + EmitSOPC(inst); + break; + } + case InstEncoding::SOPK: { + EmitSOPK(inst); + break; + } + default: + switch (inst.opcode) { + // SOP2 + case Opcode::S_ADD_U32: + return S_ADD_U32(inst); + case Opcode::S_SUB_U32: + return S_SUB_U32(inst); + case Opcode::S_ADD_I32: + return S_ADD_I32(inst); + case Opcode::S_SUB_I32: + return S_SUB_U32(inst); + case Opcode::S_ADDC_U32: + return S_ADDC_U32(inst); + case Opcode::S_MIN_I32: + return S_MIN_U32(true, inst); + case Opcode::S_MIN_U32: + return S_MIN_U32(false, inst); + case Opcode::S_MAX_I32: + return S_MAX_U32(true, inst); + case Opcode::S_MAX_U32: + return S_MAX_U32(false, inst); + case Opcode::S_CSELECT_B32: + return S_CSELECT_B32(inst); + case Opcode::S_CSELECT_B64: + return S_CSELECT_B64(inst); + case Opcode::S_AND_B32: + return S_AND_B32(NegateMode::None, inst); + case Opcode::S_AND_B64: + return S_AND_B64(NegateMode::None, inst); + case Opcode::S_OR_B32: + return S_OR_B32(inst); + case Opcode::S_OR_B64: + return S_OR_B64(NegateMode::None, false, inst); + case Opcode::S_XOR_B32: + return S_XOR_B32(inst); + case Opcode::S_XOR_B64: + return S_OR_B64(NegateMode::None, true, inst); + case Opcode::S_ANDN2_B32: + return S_AND_B32(NegateMode::Src1, inst); + case Opcode::S_ANDN2_B64: + return S_AND_B64(NegateMode::Src1, inst); + case Opcode::S_ORN2_B64: + return S_OR_B64(NegateMode::Src1, false, inst); + case Opcode::S_NAND_B32: + return S_AND_B32(NegateMode::Result, inst); + case Opcode::S_NAND_B64: + return S_AND_B64(NegateMode::Result, inst); + case Opcode::S_NOR_B64: + return S_OR_B64(NegateMode::Result, false, inst); + case Opcode::S_XNOR_B64: + return S_OR_B64(NegateMode::Result, true, inst); + case Opcode::S_LSHL_B32: + return S_LSHL_B32(inst); + case Opcode::S_LSHR_B32: + return S_LSHR_B32(inst); + case Opcode::S_ASHR_I32: + return S_ASHR_I32(inst); + case Opcode::S_BFM_B32: + return S_BFM_B32(inst); + case Opcode::S_MUL_I32: + return S_MUL_I32(inst); + case Opcode::S_BFE_U32: + return S_BFE_U32(inst); + case Opcode::S_ABSDIFF_I32: + return S_ABSDIFF_I32(inst); + + // SOP1 + case Opcode::S_MOV_B32: + return S_MOV(inst); + case Opcode::S_MOV_B64: + return S_MOV_B64(inst); + case Opcode::S_NOT_B64: + return S_NOT_B64(inst); + case Opcode::S_WQM_B64: + break; + case Opcode::S_BREV_B32: + return S_BREV_B32(inst); + case Opcode::S_AND_SAVEEXEC_B64: + return S_AND_SAVEEXEC_B64(inst); + default: + LogMissingOpcode(inst); + } + break; + } +} + +void Translator::EmitSOPC(const GcnInst& inst) { switch (inst.opcode) { - case Opcode::S_MOVK_I32: - return S_MOVK(inst); - case Opcode::S_MOV_B32: - return S_MOV(inst); - case Opcode::S_MUL_I32: - return S_MUL_I32(inst); - case Opcode::S_AND_SAVEEXEC_B64: - return S_AND_SAVEEXEC_B64(inst); - case Opcode::S_MOV_B64: - return S_MOV_B64(inst); - case Opcode::S_CMP_LT_U32: - return S_CMP(ConditionOp::LT, false, inst); - case Opcode::S_CMP_LE_U32: - return S_CMP(ConditionOp::LE, false, inst); - case Opcode::S_CMP_LG_U32: - return S_CMP(ConditionOp::LG, false, inst); - case Opcode::S_CMP_LT_I32: - return S_CMP(ConditionOp::LT, true, inst); + case Opcode::S_CMP_EQ_I32: + return S_CMP(ConditionOp::EQ, true, inst); case Opcode::S_CMP_LG_I32: return S_CMP(ConditionOp::LG, true, inst); case Opcode::S_CMP_GT_I32: return S_CMP(ConditionOp::GT, true, inst); - case Opcode::S_CMP_LE_I32: - return S_CMP(ConditionOp::LE, true, inst); case Opcode::S_CMP_GE_I32: return S_CMP(ConditionOp::GE, true, inst); - case Opcode::S_CMP_EQ_I32: - return S_CMP(ConditionOp::EQ, true, inst); + case Opcode::S_CMP_LT_I32: + return S_CMP(ConditionOp::LT, true, inst); + case Opcode::S_CMP_LE_I32: + return S_CMP(ConditionOp::LE, true, inst); + case Opcode::S_CMP_EQ_U32: return S_CMP(ConditionOp::EQ, false, inst); - case Opcode::S_CMP_GE_U32: - return S_CMP(ConditionOp::GE, false, inst); + case Opcode::S_CMP_LG_U32: + return S_CMP(ConditionOp::LG, false, inst); case Opcode::S_CMP_GT_U32: return S_CMP(ConditionOp::GT, false, inst); - case Opcode::S_OR_B64: - return S_OR_B64(NegateMode::None, false, inst); - case Opcode::S_NOR_B64: - return S_OR_B64(NegateMode::Result, false, inst); - case Opcode::S_XOR_B64: - return S_OR_B64(NegateMode::None, true, inst); - case Opcode::S_ORN2_B64: - return S_OR_B64(NegateMode::Src1, false, inst); - case Opcode::S_AND_B64: - return S_AND_B64(NegateMode::None, inst); - case Opcode::S_NAND_B64: - return S_AND_B64(NegateMode::Result, inst); - case Opcode::S_ANDN2_B64: - return S_AND_B64(NegateMode::Src1, inst); - case Opcode::S_NOT_B64: - return S_NOT_B64(inst); - case Opcode::S_ADD_I32: - return S_ADD_I32(inst); - case Opcode::S_AND_B32: - return S_AND_B32(inst); - case Opcode::S_ASHR_I32: - return S_ASHR_I32(inst); - case Opcode::S_OR_B32: - return S_OR_B32(inst); - case Opcode::S_LSHL_B32: - return S_LSHL_B32(inst); - case Opcode::S_LSHR_B32: - return S_LSHR_B32(inst); - case Opcode::S_CSELECT_B32: - return S_CSELECT_B32(inst); - case Opcode::S_CSELECT_B64: - return S_CSELECT_B64(inst); - case Opcode::S_BFE_U32: - return S_BFE_U32(inst); - case Opcode::S_BFM_B32: - return S_BFM_B32(inst); - case Opcode::S_BREV_B32: - return S_BREV_B32(inst); - case Opcode::S_ADD_U32: - return S_ADD_U32(inst); - case Opcode::S_ADDC_U32: - return S_ADDC_U32(inst); - case Opcode::S_ADDK_I32: - return S_ADDK_I32(inst); - case Opcode::S_MULK_I32: - return S_MULK_I32(inst); - case Opcode::S_SUB_U32: - case Opcode::S_SUB_I32: - return S_SUB_U32(inst); - case Opcode::S_MIN_U32: - return S_MIN_U32(inst); - case Opcode::S_MAX_U32: - return S_MAX_U32(inst); - case Opcode::S_WQM_B64: - break; + case Opcode::S_CMP_GE_U32: + return S_CMP(ConditionOp::GE, false, inst); + case Opcode::S_CMP_LT_U32: + return S_CMP(ConditionOp::LT, false, inst); + case Opcode::S_CMP_LE_U32: + return S_CMP(ConditionOp::LE, false, inst); default: LogMissingOpcode(inst); } } -void Translator::S_MOVK(const GcnInst& inst) { - const auto simm16 = inst.control.sopk.simm; - if (simm16 & (1 << 15)) { - // TODO: need to verify the case of imm sign extension - UNREACHABLE(); - } - SetDst(inst.dst[0], ir.Imm32(simm16)); -} +void Translator::EmitSOPK(const GcnInst& inst) { + switch (inst.opcode) { + // SOPK + case Opcode::S_MOVK_I32: + return S_MOVK(inst); -void Translator::S_ADDK_I32(const GcnInst& inst) { - const s32 simm16 = inst.control.sopk.simm; - SetDst(inst.dst[0], ir.IAdd(GetSrc(inst.dst[0]), ir.Imm32(simm16))); -} + case Opcode::S_CMPK_EQ_I32: + return S_CMPK(ConditionOp::EQ, true, inst); + case Opcode::S_CMPK_LG_I32: + return S_CMPK(ConditionOp::LG, true, inst); + case Opcode::S_CMPK_GT_I32: + return S_CMPK(ConditionOp::GT, true, inst); + case Opcode::S_CMPK_GE_I32: + return S_CMPK(ConditionOp::GE, true, inst); + case Opcode::S_CMPK_LT_I32: + return S_CMPK(ConditionOp::LT, true, inst); + case Opcode::S_CMPK_LE_I32: + return S_CMPK(ConditionOp::LE, true, inst); -void Translator::S_MULK_I32(const GcnInst& inst) { - const s32 simm16 = inst.control.sopk.simm; - SetDst(inst.dst[0], ir.IMul(GetSrc(inst.dst[0]), ir.Imm32(simm16))); -} + case Opcode::S_CMPK_EQ_U32: + return S_CMPK(ConditionOp::EQ, false, inst); + case Opcode::S_CMPK_LG_U32: + return S_CMPK(ConditionOp::LG, false, inst); + case Opcode::S_CMPK_GT_U32: + return S_CMPK(ConditionOp::GT, false, inst); + case Opcode::S_CMPK_GE_U32: + return S_CMPK(ConditionOp::GE, false, inst); + case Opcode::S_CMPK_LT_U32: + return S_CMPK(ConditionOp::LT, false, inst); + case Opcode::S_CMPK_LE_U32: + return S_CMPK(ConditionOp::LE, false, inst); -void Translator::S_MOV(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::S_MUL_I32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.IMul(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); -} - -void Translator::S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst) { - const IR::U32 lhs = GetSrc(inst.src[0]); - const IR::U32 rhs = GetSrc(inst.src[1]); - const IR::U1 result = [&] { - switch (cond) { - case ConditionOp::EQ: - return ir.IEqual(lhs, rhs); - case ConditionOp::LG: - return ir.INotEqual(lhs, rhs); - case ConditionOp::GT: - return ir.IGreaterThan(lhs, rhs, is_signed); - case ConditionOp::GE: - return ir.IGreaterThanEqual(lhs, rhs, is_signed); - case ConditionOp::LT: - return ir.ILessThan(lhs, rhs, is_signed); - case ConditionOp::LE: - return ir.ILessThanEqual(lhs, rhs, is_signed); - default: - UNREACHABLE(); - } - }(); - ir.SetScc(result); -} - -void Translator::S_AND_SAVEEXEC_B64(const GcnInst& inst) { - // This instruction normally operates on 64-bit data (EXEC, VCC, SGPRs) - // However here we flatten it to 1-bit EXEC and 1-bit VCC. For the destination - // SGPR we have a special IR opcode for SPGRs that act as thread masks. - const IR::U1 exec{ir.GetExec()}; - const IR::U1 src = [&] { - switch (inst.src[0].field) { - case OperandField::VccLo: - return ir.GetVcc(); - case OperandField::ScalarGPR: - return ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code)); - default: - UNREACHABLE(); - } - }(); - - switch (inst.dst[0].field) { - case OperandField::ScalarGPR: - ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), exec); - break; - case OperandField::VccLo: - ir.SetVcc(exec); - break; + case Opcode::S_ADDK_I32: + return S_ADDK_I32(inst); + case Opcode::S_MULK_I32: + return S_MULK_I32(inst); default: - UNREACHABLE(); - } - - // Update EXEC. - const IR::U1 result = ir.LogicalAnd(exec, src); - ir.SetExec(result); - ir.SetScc(result); -} - -void Translator::S_MOV_B64(const GcnInst& inst) { - const IR::U1 src = [&] { - switch (inst.src[0].field) { - case OperandField::VccLo: - return ir.GetVcc(); - case OperandField::ExecLo: - return ir.GetExec(); - case OperandField::ScalarGPR: - return ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code)); - case OperandField::ConstZero: - return ir.Imm1(false); - default: - UNREACHABLE(); - } - }(); - switch (inst.dst[0].field) { - case OperandField::ScalarGPR: - ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), src); - break; - case OperandField::ExecLo: - ir.SetExec(src); - break; - case OperandField::VccLo: - ir.SetVcc(src); - break; - default: - UNREACHABLE(); + LogMissingOpcode(inst); } } -void Translator::S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst) { - const auto get_src = [&](const InstOperand& operand) { - switch (operand.field) { - case OperandField::ExecLo: - return ir.GetExec(); - case OperandField::VccLo: - return ir.GetVcc(); - case OperandField::ScalarGPR: - return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); - default: - UNREACHABLE(); - } - }; +// SOP2 - const IR::U1 src0{get_src(inst.src[0])}; - IR::U1 src1{get_src(inst.src[1])}; - if (negate == NegateMode::Src1) { - src1 = ir.LogicalNot(src1); - } - IR::U1 result = is_xor ? ir.LogicalXor(src0, src1) : ir.LogicalOr(src0, src1); - if (negate == NegateMode::Result) { - result = ir.LogicalNot(result); - } - ir.SetScc(result); - switch (inst.dst[0].field) { - case OperandField::VccLo: - ir.SetVcc(result); - break; - case OperandField::ScalarGPR: - ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); - break; - default: - UNREACHABLE(); - } +void Translator::S_ADD_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.IAdd(src0, src1)); + // TODO: Carry out + ir.SetScc(ir.Imm1(false)); } -void Translator::S_AND_B64(NegateMode negate, const GcnInst& inst) { - const auto get_src = [&](const InstOperand& operand) { - switch (operand.field) { - case OperandField::VccLo: - return ir.GetVcc(); - case OperandField::ExecLo: - return ir.GetExec(); - case OperandField::ScalarGPR: - return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); - default: - UNREACHABLE(); - } - }; - const IR::U1 src0{get_src(inst.src[0])}; - IR::U1 src1{get_src(inst.src[1])}; - if (negate == NegateMode::Src1) { - src1 = ir.LogicalNot(src1); - } - IR::U1 result = ir.LogicalAnd(src0, src1); - if (negate == NegateMode::Result) { - result = ir.LogicalNot(result); - } - ir.SetScc(result); - switch (inst.dst[0].field) { - case OperandField::VccLo: - ir.SetVcc(result); - break; - case OperandField::ScalarGPR: - ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); - break; - case OperandField::ExecLo: - ir.SetExec(result); - break; - default: - UNREACHABLE(); - } +void Translator::S_SUB_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ISub(src0, src1)); + // TODO: Carry out + ir.SetScc(ir.Imm1(false)); } void Translator::S_ADD_I32(const GcnInst& inst) { @@ -296,36 +199,27 @@ void Translator::S_ADD_I32(const GcnInst& inst) { // TODO: Overflow flag } -void Translator::S_AND_B32(const GcnInst& inst) { +void Translator::S_ADDC_U32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.BitwiseAnd(src0, src1)}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); + const IR::U32 carry{ir.Select(ir.GetScc(), ir.Imm32(1U), ir.Imm32(0U))}; + SetDst(inst.dst[0], ir.IAdd(ir.IAdd(src0, src1), carry)); } -void Translator::S_ASHR_I32(const GcnInst& inst) { +void Translator::S_MIN_U32(bool is_signed, const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.ShiftRightArithmetic(src0, src1)}; + const IR::U32 result = ir.IMin(src0, src1, is_signed); SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); + ir.SetScc(ir.IEqual(result, src0)); } -void Translator::S_OR_B32(const GcnInst& inst) { +void Translator::S_MAX_U32(bool is_signed, const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.BitwiseOr(src0, src1)}; + const IR::U32 result = ir.IMax(src0, src1, is_signed); SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_LSHR_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.ShiftRightLogical(src0, src1)}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); + ir.SetScc(ir.IEqual(result, src0)); } void Translator::S_CSELECT_B32(const GcnInst& inst) { @@ -364,12 +258,112 @@ void Translator::S_CSELECT_B64(const GcnInst& inst) { } } -void Translator::S_BFE_U32(const GcnInst& inst) { +void Translator::S_AND_B32(NegateMode negate, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + IR::U32 src1{GetSrc(inst.src[1])}; + if (negate == NegateMode::Src1) { + src1 = ir.BitwiseNot(src1); + } + IR::U32 result{ir.BitwiseAnd(src0, src1)}; + if (negate == NegateMode::Result) { + result = ir.BitwiseNot(result); + } + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + +void Translator::S_AND_B64(NegateMode negate, const GcnInst& inst) { + const auto get_src = [&](const InstOperand& operand) { + switch (operand.field) { + case OperandField::VccLo: + return ir.GetVcc(); + case OperandField::ExecLo: + return ir.GetExec(); + case OperandField::ScalarGPR: + return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); + case OperandField::ConstZero: + return ir.Imm1(false); + case OperandField::SignedConstIntNeg: + ASSERT_MSG(-s32(operand.code) + SignedConstIntNegMin - 1 == -1, + "SignedConstIntNeg must be -1"); + return ir.Imm1(true); + default: + UNREACHABLE(); + } + }; + const IR::U1 src0{get_src(inst.src[0])}; + IR::U1 src1{get_src(inst.src[1])}; + if (negate == NegateMode::Src1) { + src1 = ir.LogicalNot(src1); + } + IR::U1 result = ir.LogicalAnd(src0, src1); + if (negate == NegateMode::Result) { + result = ir.LogicalNot(result); + } + ir.SetScc(result); + switch (inst.dst[0].field) { + case OperandField::VccLo: + ir.SetVcc(result); + break; + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); + break; + case OperandField::ExecLo: + ir.SetExec(result); + break; + default: + UNREACHABLE(); + } +} + +void Translator::S_OR_B32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 offset{ir.BitwiseAnd(src1, ir.Imm32(0x1F))}; - const IR::U32 count{ir.BitFieldExtract(src1, ir.Imm32(16), ir.Imm32(7))}; - const IR::U32 result{ir.BitFieldExtract(src0, offset, count)}; + const IR::U32 result{ir.BitwiseOr(src0, src1)}; + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + +void Translator::S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst) { + const auto get_src = [&](const InstOperand& operand) { + switch (operand.field) { + case OperandField::ExecLo: + return ir.GetExec(); + case OperandField::VccLo: + return ir.GetVcc(); + case OperandField::ScalarGPR: + return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); + default: + UNREACHABLE(); + } + }; + + const IR::U1 src0{get_src(inst.src[0])}; + IR::U1 src1{get_src(inst.src[1])}; + if (negate == NegateMode::Src1) { + src1 = ir.LogicalNot(src1); + } + IR::U1 result = is_xor ? ir.LogicalXor(src0, src1) : ir.LogicalOr(src0, src1); + if (negate == NegateMode::Result) { + result = ir.LogicalNot(result); + } + ir.SetScc(result); + switch (inst.dst[0].field) { + case OperandField::VccLo: + ir.SetVcc(result); + break; + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); + break; + default: + UNREACHABLE(); + } +} + +void Translator::S_XOR_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.BitwiseXor(src0, src1)}; SetDst(inst.dst[0], result); ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); } @@ -382,6 +376,22 @@ void Translator::S_LSHL_B32(const GcnInst& inst) { ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); } +void Translator::S_LSHR_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.ShiftRightLogical(src0, src1)}; + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + +void Translator::S_ASHR_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.ShiftRightArithmetic(src0, src1)}; + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + void Translator::S_BFM_B32(const GcnInst& inst) { const IR::U32 src0{ir.BitwiseAnd(GetSrc(inst.src[0]), ir.Imm32(0x1F))}; const IR::U32 src1{ir.BitwiseAnd(GetSrc(inst.src[1]), ir.Imm32(0x1F))}; @@ -389,6 +399,110 @@ void Translator::S_BFM_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.ShiftLeftLogical(mask, src1)); } +void Translator::S_MUL_I32(const GcnInst& inst) { + SetDst(inst.dst[0], ir.IMul(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); +} + +void Translator::S_BFE_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 offset{ir.BitwiseAnd(src1, ir.Imm32(0x1F))}; + const IR::U32 count{ir.BitFieldExtract(src1, ir.Imm32(16), ir.Imm32(7))}; + const IR::U32 result{ir.BitFieldExtract(src0, offset, count)}; + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + +void Translator::S_ABSDIFF_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.IAbs(ir.ISub(src0, src1))}; + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + +// SOPK + +void Translator::S_MOVK(const GcnInst& inst) { + const auto simm16 = inst.control.sopk.simm; + if (simm16 & (1 << 15)) { + // TODO: need to verify the case of imm sign extension + UNREACHABLE(); + } + SetDst(inst.dst[0], ir.Imm32(simm16)); +} + +void Translator::S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst) { + const s32 simm16 = inst.control.sopk.simm; + const IR::U32 lhs = GetSrc(inst.dst[0]); + const IR::U32 rhs = ir.Imm32(simm16); + const IR::U1 result = [&] { + switch (cond) { + case ConditionOp::EQ: + return ir.IEqual(lhs, rhs); + case ConditionOp::LG: + return ir.INotEqual(lhs, rhs); + case ConditionOp::GT: + return ir.IGreaterThan(lhs, rhs, is_signed); + case ConditionOp::GE: + return ir.IGreaterThanEqual(lhs, rhs, is_signed); + case ConditionOp::LT: + return ir.ILessThan(lhs, rhs, is_signed); + case ConditionOp::LE: + return ir.ILessThanEqual(lhs, rhs, is_signed); + default: + UNREACHABLE(); + } + }(); + ir.SetScc(result); +} + +void Translator::S_ADDK_I32(const GcnInst& inst) { + const s32 simm16 = inst.control.sopk.simm; + SetDst(inst.dst[0], ir.IAdd(GetSrc(inst.dst[0]), ir.Imm32(simm16))); +} + +void Translator::S_MULK_I32(const GcnInst& inst) { + const s32 simm16 = inst.control.sopk.simm; + SetDst(inst.dst[0], ir.IMul(GetSrc(inst.dst[0]), ir.Imm32(simm16))); +} + +// SOP1 + +void Translator::S_MOV(const GcnInst& inst) { + SetDst(inst.dst[0], GetSrc(inst.src[0])); +} + +void Translator::S_MOV_B64(const GcnInst& inst) { + const IR::U1 src = [&] { + switch (inst.src[0].field) { + case OperandField::VccLo: + return ir.GetVcc(); + case OperandField::ExecLo: + return ir.GetExec(); + case OperandField::ScalarGPR: + return ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code)); + case OperandField::ConstZero: + return ir.Imm1(false); + default: + UNREACHABLE(); + } + }(); + switch (inst.dst[0].field) { + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), src); + break; + case OperandField::ExecLo: + ir.SetExec(src); + break; + case OperandField::VccLo: + ir.SetVcc(src); + break; + default: + UNREACHABLE(); + } +} + void Translator::S_NOT_B64(const GcnInst& inst) { const auto get_src = [&](const InstOperand& operand) { switch (operand.field) { @@ -398,6 +512,8 @@ void Translator::S_NOT_B64(const GcnInst& inst) { return ir.GetExec(); case OperandField::ScalarGPR: return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); + case OperandField::ConstZero: + return ir.Imm1(false); default: UNREACHABLE(); } @@ -412,6 +528,9 @@ void Translator::S_NOT_B64(const GcnInst& inst) { case OperandField::ScalarGPR: ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); break; + case OperandField::ExecLo: + ir.SetExec(result); + break; default: UNREACHABLE(); } @@ -421,48 +540,63 @@ void Translator::S_BREV_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.BitReverse(GetSrc(inst.src[0]))); } -void Translator::S_ADD_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IAdd(src0, src1)); - // TODO: Carry out - ir.SetScc(ir.Imm1(false)); +void Translator::S_AND_SAVEEXEC_B64(const GcnInst& inst) { + // This instruction normally operates on 64-bit data (EXEC, VCC, SGPRs) + // However here we flatten it to 1-bit EXEC and 1-bit VCC. For the destination + // SGPR we have a special IR opcode for SPGRs that act as thread masks. + const IR::U1 exec{ir.GetExec()}; + const IR::U1 src = [&] { + switch (inst.src[0].field) { + case OperandField::VccLo: + return ir.GetVcc(); + case OperandField::ScalarGPR: + return ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[0].code)); + default: + UNREACHABLE(); + } + }(); + + switch (inst.dst[0].field) { + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), exec); + break; + case OperandField::VccLo: + ir.SetVcc(exec); + break; + default: + UNREACHABLE(); + } + + // Update EXEC. + const IR::U1 result = ir.LogicalAnd(exec, src); + ir.SetExec(result); + ir.SetScc(result); } -void Translator::S_SUB_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ISub(src0, src1)); - // TODO: Carry out - ir.SetScc(ir.Imm1(false)); -} +// SOPC -void Translator::S_GETPC_B64(u32 pc, const GcnInst& inst) { - // This only really exists to let resource tracking pass know - // there is an inline cbuf. - SetDst(inst.dst[0], ir.Imm32(pc)); -} - -void Translator::S_ADDC_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IAdd(ir.IAdd(src0, src1), ir.GetSccLo())); -} - -void Translator::S_MAX_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result = ir.UMax(src0, src1); - SetDst(inst.dst[0], result); - ir.SetScc(ir.IEqual(result, src0)); -} - -void Translator::S_MIN_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result = ir.UMin(src0, src1); - SetDst(inst.dst[0], result); - ir.SetScc(ir.IEqual(result, src0)); +void Translator::S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst) { + const IR::U32 lhs = GetSrc(inst.src[0]); + const IR::U32 rhs = GetSrc(inst.src[1]); + const IR::U1 result = [&] { + switch (cond) { + case ConditionOp::EQ: + return ir.IEqual(lhs, rhs); + case ConditionOp::LG: + return ir.INotEqual(lhs, rhs); + case ConditionOp::GT: + return ir.IGreaterThan(lhs, rhs, is_signed); + case ConditionOp::GE: + return ir.IGreaterThanEqual(lhs, rhs, is_signed); + case ConditionOp::LT: + return ir.ILessThan(lhs, rhs, is_signed); + case ConditionOp::LE: + return ir.ILessThanEqual(lhs, rhs, is_signed); + default: + UNREACHABLE(); + } + }(); + ir.SetScc(result); } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/scalar_flow.cpp b/src/shader_recompiler/frontend/translate/scalar_flow.cpp new file mode 100644 index 000000000..ef8bab789 --- /dev/null +++ b/src/shader_recompiler/frontend/translate/scalar_flow.cpp @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "shader_recompiler/frontend/opcodes.h" +#include "shader_recompiler/frontend/translate/translate.h" + +namespace Shader::Gcn { + +void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) { + switch (inst.opcode) { + case Opcode::S_BARRIER: + return S_BARRIER(); + case Opcode::S_TTRACEDATA: + LOG_WARNING(Render_Vulkan, "S_TTRACEDATA instruction!"); + return; + case Opcode::S_GETPC_B64: + return S_GETPC_B64(pc, inst); + case Opcode::S_WAITCNT: + case Opcode::S_NOP: + case Opcode::S_ENDPGM: + case Opcode::S_CBRANCH_EXECZ: + case Opcode::S_CBRANCH_SCC0: + case Opcode::S_CBRANCH_SCC1: + case Opcode::S_CBRANCH_VCCNZ: + case Opcode::S_CBRANCH_VCCZ: + case Opcode::S_CBRANCH_EXECNZ: + case Opcode::S_BRANCH: + return; + case Opcode::S_SENDMSG: + S_SENDMSG(inst); + return; + default: + UNREACHABLE(); + } +} + +void Translator::S_BARRIER() { + ir.Barrier(); +} + +void Translator::S_GETPC_B64(u32 pc, const GcnInst& inst) { + // This only really exists to let resource tracking pass know + // there is an inline cbuf. + const IR::ScalarReg dst{inst.dst[0].code}; + ir.SetScalarReg(dst, ir.Imm32(pc)); + ir.SetScalarReg(dst + 1, ir.Imm32(0)); +} + +void Translator::S_SENDMSG(const GcnInst& inst) { + const auto& simm = reinterpret_cast(inst.control.sopp.simm); + switch (simm.msg) { + case SendMsgSimm::Message::Gs: { + switch (simm.op) { + case SendMsgSimm::GsOp::Nop: + break; + case SendMsgSimm::GsOp::Cut: + ir.EmitPrimitive(); + break; + case SendMsgSimm::GsOp::Emit: + ir.EmitVertex(); + break; + default: + UNREACHABLE(); + } + break; + } + case SendMsgSimm::Message::GsDone: { + break; + } + default: + UNREACHABLE(); + } +} + +} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/scalar_memory.cpp b/src/shader_recompiler/frontend/translate/scalar_memory.cpp index 29f2acc27..a6f8cafd7 100644 --- a/src/shader_recompiler/frontend/translate/scalar_memory.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_memory.cpp @@ -9,6 +9,7 @@ static constexpr u32 SQ_SRC_LITERAL = 0xFF; void Translator::EmitScalarMemory(const GcnInst& inst) { switch (inst.opcode) { + // SMRD case Opcode::S_LOAD_DWORDX4: return S_LOAD_DWORD(4, inst); case Opcode::S_LOAD_DWORDX8: @@ -30,6 +31,8 @@ void Translator::EmitScalarMemory(const GcnInst& inst) { } } +// SMRD + void Translator::S_LOAD_DWORD(int num_dwords, const GcnInst& inst) { const auto& smrd = inst.control.smrd; const u32 dword_offset = [&] -> u32 { diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 4070560ae..bae6681cb 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -7,8 +7,10 @@ #include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/fetch_shader.h" #include "shader_recompiler/frontend/translate/translate.h" +#include "shader_recompiler/info.h" #include "shader_recompiler/runtime_info.h" #include "video_core/amdgpu/resource.h" +#include "video_core/amdgpu/types.h" #define MAGIC_ENUM_RANGE_MIN 0 #define MAGIC_ENUM_RANGE_MAX 1515 @@ -16,8 +18,9 @@ namespace Shader::Gcn { -Translator::Translator(IR::Block* block_, Info& info_, const Profile& profile_) - : ir{*block_, block_->begin()}, info{info_}, profile{profile_} {} +Translator::Translator(IR::Block* block_, Info& info_, const RuntimeInfo& runtime_info_, + const Profile& profile_) + : ir{*block_, block_->begin()}, info{info_}, runtime_info{runtime_info_}, profile{profile_} {} void Translator::EmitPrologue() { ir.Prologue(); @@ -25,7 +28,7 @@ void Translator::EmitPrologue() { // Initialize user data. IR::ScalarReg dst_sreg = IR::ScalarReg::S0; - for (u32 i = 0; i < info.num_user_data; i++) { + for (u32 i = 0; i < runtime_info.num_user_data; i++) { ir.SetScalarReg(dst_sreg, ir.GetUserData(dst_sreg)); ++dst_sreg; } @@ -33,18 +36,19 @@ void Translator::EmitPrologue() { IR::VectorReg dst_vreg = IR::VectorReg::V0; switch (info.stage) { case Stage::Vertex: + case Stage::Export: // v0: vertex ID, always present ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::VertexId)); // v1: instance ID, step rate 0 - if (info.num_input_vgprs > 0) { + if (runtime_info.num_input_vgprs > 0) { ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId0)); } // v2: instance ID, step rate 1 - if (info.num_input_vgprs > 1) { + if (runtime_info.num_input_vgprs > 1) { ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId1)); } // v3: instance ID, plain - if (info.num_input_vgprs > 2) { + if (runtime_info.num_input_vgprs > 2) { ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId)); } break; @@ -64,16 +68,30 @@ void Translator::EmitPrologue() { ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 1)); ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 2)); - if (info.tgid_enable[0]) { + if (runtime_info.cs_info.tgid_enable[0]) { ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::WorkgroupId, 0)); } - if (info.tgid_enable[1]) { + if (runtime_info.cs_info.tgid_enable[1]) { ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::WorkgroupId, 1)); } - if (info.tgid_enable[2]) { + if (runtime_info.cs_info.tgid_enable[2]) { ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::WorkgroupId, 2)); } break; + case Stage::Geometry: + switch (runtime_info.gs_info.out_primitive[0]) { + case AmdGpu::GsOutputPrimitiveType::TriangleStrip: + ir.SetVectorReg(IR::VectorReg::V3, ir.Imm32(2u)); // vertex 2 + [[fallthrough]]; + case AmdGpu::GsOutputPrimitiveType::LineStrip: + ir.SetVectorReg(IR::VectorReg::V1, ir.Imm32(1u)); // vertex 1 + [[fallthrough]]; + default: + ir.SetVectorReg(IR::VectorReg::V0, ir.Imm32(0u)); // vertex 0 + break; + } + ir.SetVectorReg(IR::VectorReg::V2, ir.GetAttributeU32(IR::Attribute::PrimitiveId)); + break; default: throw NotImplementedException("Unknown shader stage"); } @@ -151,10 +169,11 @@ T Translator::GetSrc(const InstOperand& operand) { break; case OperandField::M0: if constexpr (is_float) { - UNREACHABLE(); + value = ir.BitCast(ir.GetM0()); } else { - return m0_value; + value = ir.GetM0(); } + break; default: UNREACHABLE(); } @@ -168,10 +187,10 @@ T Translator::GetSrc(const InstOperand& operand) { } } else { if (operand.input_modifier.abs) { - LOG_WARNING(Render_Vulkan, "Input abs modifier on integer instruction"); + value = ir.IAbs(value); } if (operand.input_modifier.neg) { - UNREACHABLE(); + value = ir.INeg(value); } } return value; @@ -208,7 +227,7 @@ T Translator::GetSrc64(const InstOperand& operand) { const auto value_lo = ir.GetVectorReg(IR::VectorReg(operand.code)); const auto value_hi = ir.GetVectorReg(IR::VectorReg(operand.code + 1)); if constexpr (is_float) { - UNREACHABLE(); + value = ir.PackFloat2x32(ir.CompositeConstruct(value_lo, value_hi)); } else { value = ir.PackUint2x32(ir.CompositeConstruct(value_lo, value_hi)); } @@ -278,12 +297,15 @@ template IR::F64 Translator::GetSrc64(const InstOperand&); void Translator::SetDst(const InstOperand& operand, const IR::U32F32& value) { IR::U32F32 result = value; - if (operand.output_modifier.multiplier != 0.f) { - result = ir.FPMul(result, ir.Imm32(operand.output_modifier.multiplier)); - } - if (operand.output_modifier.clamp) { - result = ir.FPSaturate(value); + if (value.Type() == IR::Type::F32) { + if (operand.output_modifier.multiplier != 0.f) { + result = ir.FPMul(result, ir.Imm32(operand.output_modifier.multiplier)); + } + if (operand.output_modifier.clamp) { + result = ir.FPSaturate(value); + } } + switch (operand.field) { case OperandField::ScalarGPR: return ir.SetScalarReg(IR::ScalarReg(operand.code), result); @@ -294,8 +316,7 @@ void Translator::SetDst(const InstOperand& operand, const IR::U32F32& value) { case OperandField::VccHi: return ir.SetVccHi(result); case OperandField::M0: - m0_value = result; - break; + return ir.SetM0(result); default: UNREACHABLE(); } @@ -346,7 +367,7 @@ void Translator::EmitFetch(const GcnInst& inst) { // Parse the assembly to generate a list of attributes. u32 fetch_size{}; - const auto attribs = ParseFetchShader(code, &fetch_size); + const auto fetch_data = ParseFetchShader(code, &fetch_size); if (Config::dumpShaders()) { using namespace Common::FS; @@ -354,12 +375,15 @@ void Translator::EmitFetch(const GcnInst& inst) { if (!std::filesystem::exists(dump_dir)) { std::filesystem::create_directories(dump_dir); } - const auto filename = fmt::format("vs_fetch_{:#018x}.bin", info.pgm_hash); + const auto filename = fmt::format("vs_{:#018x}.fetch.bin", info.pgm_hash); const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; file.WriteRaw(code, fetch_size); } - for (const auto& attrib : attribs) { + info.vertex_offset_sgpr = fetch_data.vertex_offset_sgpr; + info.instance_offset_sgpr = fetch_data.instance_offset_sgpr; + + for (const auto& attrib : fetch_data.attributes) { const IR::Attribute attr{IR::Attribute::Param0 + attrib.semantic}; IR::VectorReg dst_reg{attrib.dest_vgpr}; @@ -396,9 +420,7 @@ void Translator::EmitFetch(const GcnInst& inst) { info.buffers.push_back({ .sgpr_base = attrib.sgpr_base, .dword_offset = attrib.dword_offset, - .length = buffer.num_records, .used_types = IR::Type::F32, - .is_storage = true, // we may not fit into UBO with large meshes .is_instance_data = true, }); instance_buf_handle = s32(info.buffers.size() - 1); @@ -418,32 +440,7 @@ void Translator::EmitFetch(const GcnInst& inst) { } } -void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) { - switch (inst.opcode) { - case Opcode::S_BARRIER: - return S_BARRIER(); - case Opcode::S_TTRACEDATA: - LOG_WARNING(Render_Vulkan, "S_TTRACEDATA instruction!"); - return; - case Opcode::S_GETPC_B64: - return S_GETPC_B64(pc, inst); - case Opcode::S_WAITCNT: - case Opcode::S_NOP: - case Opcode::S_ENDPGM: - case Opcode::S_CBRANCH_EXECZ: - case Opcode::S_CBRANCH_SCC0: - case Opcode::S_CBRANCH_SCC1: - case Opcode::S_CBRANCH_VCCNZ: - case Opcode::S_CBRANCH_VCCZ: - case Opcode::S_BRANCH: - return; - default: - UNREACHABLE(); - } -} - void Translator::LogMissingOpcode(const GcnInst& inst) { - const u32 opcode = u32(inst.opcode); LOG_ERROR(Render_Recompiler, "Unknown opcode {} ({}, category = {})", magic_enum::enum_name(inst.opcode), u32(inst.opcode), magic_enum::enum_name(inst.category)); @@ -451,17 +448,17 @@ void Translator::LogMissingOpcode(const GcnInst& inst) { } void Translate(IR::Block* block, u32 pc, std::span inst_list, Info& info, - const Profile& profile) { + const RuntimeInfo& runtime_info, const Profile& profile) { if (inst_list.empty()) { return; } - Translator translator{block, info, profile}; + Translator translator{block, info, runtime_info, profile}; for (const auto& inst : inst_list) { pc += inst.length; // Special case for emitting fetch shader. if (inst.opcode == Opcode::S_SWAPPC_B64) { - ASSERT(info.stage == Stage::Vertex); + ASSERT(info.stage == Stage::Vertex || info.stage == Stage::Export); translator.EmitFetch(inst); continue; } diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 009acabdf..b70d4b829 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -5,9 +5,9 @@ #include #include "shader_recompiler/frontend/instruction.h" +#include "shader_recompiler/info.h" #include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/ir_emitter.h" -#include "shader_recompiler/runtime_info.h" namespace Shader { struct Info; @@ -55,164 +55,217 @@ enum class NegateMode : u32 { class Translator { public: - explicit Translator(IR::Block* block_, Info& info, const Profile& profile); + explicit Translator(IR::Block* block_, Info& info, const RuntimeInfo& runtime_info, + const Profile& profile); // Instruction categories void EmitPrologue(); void EmitFetch(const GcnInst& inst); - void EmitDataShare(const GcnInst& inst); - void EmitVectorInterpolation(const GcnInst& inst); - void EmitScalarMemory(const GcnInst& inst); - void EmitVectorMemory(const GcnInst& inst); void EmitExport(const GcnInst& inst); void EmitFlowControl(u32 pc, const GcnInst& inst); void EmitScalarAlu(const GcnInst& inst); + void EmitScalarMemory(const GcnInst& inst); void EmitVectorAlu(const GcnInst& inst); + void EmitVectorInterpolation(const GcnInst& inst); + void EmitDataShare(const GcnInst& inst); + void EmitVectorMemory(const GcnInst& inst); + + // Instruction encodings + void EmitSOPC(const GcnInst& inst); + void EmitSOPK(const GcnInst& inst); // Scalar ALU - void S_MOVK(const GcnInst& inst); - void S_MOV(const GcnInst& inst); - void S_MUL_I32(const GcnInst& inst); - void S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst); - void S_AND_SAVEEXEC_B64(const GcnInst& inst); - void S_MOV_B64(const GcnInst& inst); - void S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst); - void S_AND_B64(NegateMode negate, const GcnInst& inst); - void S_ADD_I32(const GcnInst& inst); - void S_AND_B32(const GcnInst& inst); - void S_ASHR_I32(const GcnInst& inst); - void S_OR_B32(const GcnInst& inst); - void S_LSHR_B32(const GcnInst& inst); - void S_CSELECT_B32(const GcnInst& inst); - void S_CSELECT_B64(const GcnInst& inst); - void S_BFE_U32(const GcnInst& inst); - void S_LSHL_B32(const GcnInst& inst); - void S_BFM_B32(const GcnInst& inst); - void S_NOT_B64(const GcnInst& inst); - void S_BREV_B32(const GcnInst& inst); + // SOP2 void S_ADD_U32(const GcnInst& inst); void S_SUB_U32(const GcnInst& inst); - void S_GETPC_B64(u32 pc, const GcnInst& inst); + void S_ADD_I32(const GcnInst& inst); void S_ADDC_U32(const GcnInst& inst); - void S_MULK_I32(const GcnInst& inst); + void S_MIN_U32(bool is_signed, const GcnInst& inst); + void S_MAX_U32(bool is_signed, const GcnInst& inst); + void S_CSELECT_B32(const GcnInst& inst); + void S_CSELECT_B64(const GcnInst& inst); + void S_AND_B32(NegateMode negate, const GcnInst& inst); + void S_AND_B64(NegateMode negate, const GcnInst& inst); + void S_OR_B32(const GcnInst& inst); + void S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst); + void S_XOR_B32(const GcnInst& inst); + void S_LSHL_B32(const GcnInst& inst); + void S_LSHR_B32(const GcnInst& inst); + void S_ASHR_I32(const GcnInst& inst); + void S_BFM_B32(const GcnInst& inst); + void S_MUL_I32(const GcnInst& inst); + void S_BFE_U32(const GcnInst& inst); + void S_ABSDIFF_I32(const GcnInst& inst); + + // SOPK + void S_MOVK(const GcnInst& inst); + void S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst); void S_ADDK_I32(const GcnInst& inst); - void S_MAX_U32(const GcnInst& inst); - void S_MIN_U32(const GcnInst& inst); + void S_MULK_I32(const GcnInst& inst); + + // SOP1 + void S_MOV(const GcnInst& inst); + void S_MOV_B64(const GcnInst& inst); + void S_NOT_B64(const GcnInst& inst); + void S_BREV_B32(const GcnInst& inst); + void S_GETPC_B64(u32 pc, const GcnInst& inst); + void S_AND_SAVEEXEC_B64(const GcnInst& inst); + + // SOPC + void S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst); + + // SOPP + void S_BARRIER(); + void S_SENDMSG(const GcnInst& inst); // Scalar Memory + // SMRD void S_LOAD_DWORD(int num_dwords, const GcnInst& inst); void S_BUFFER_LOAD_DWORD(int num_dwords, const GcnInst& inst); // Vector ALU - void V_MOV(const GcnInst& inst); - void V_SAD(const GcnInst& inst); - void V_MAC_F32(const GcnInst& inst); - void V_CVT_PKRTZ_F16_F32(const GcnInst& inst); - void V_CVT_F32_F16(const GcnInst& inst); - void V_CVT_F16_F32(const GcnInst& inst); - void V_MUL_F32(const GcnInst& inst); + // VOP2 void V_CNDMASK_B32(const GcnInst& inst); - void V_OR_B32(bool is_xor, const GcnInst& inst); - void V_AND_B32(const GcnInst& inst); - void V_LSHLREV_B32(const GcnInst& inst); + void V_READLANE_B32(const GcnInst& inst); + void V_WRITELANE_B32(const GcnInst& inst); + void V_ADD_F32(const GcnInst& inst); + void V_SUB_F32(const GcnInst& inst); + void V_SUBREV_F32(const GcnInst& inst); + void V_MUL_F32(const GcnInst& inst); + void V_MUL_I32_I24(const GcnInst& inst); + void V_MIN_F32(const GcnInst& inst, bool is_legacy = false); + void V_MAX_F32(const GcnInst& inst, bool is_legacy = false); + void V_MIN_I32(const GcnInst& inst); + void V_MIN_U32(const GcnInst& inst); + void V_MAX_U32(bool is_signed, const GcnInst& inst); + void V_LSHR_B32(const GcnInst& inst); + void V_LSHRREV_B32(const GcnInst& inst); + void V_ASHR_I32(const GcnInst& inst); + void V_ASHRREV_I32(const GcnInst& inst); void V_LSHL_B32(const GcnInst& inst); + void V_LSHLREV_B32(const GcnInst& inst); + void V_AND_B32(const GcnInst& inst); + void V_OR_B32(bool is_xor, const GcnInst& inst); + void V_BFM_B32(const GcnInst& inst); + void V_MAC_F32(const GcnInst& inst); + void V_MADMK_F32(const GcnInst& inst); + void V_BCNT_U32_B32(const GcnInst& inst); + void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst); void V_ADD_I32(const GcnInst& inst); + void V_SUB_I32(const GcnInst& inst); + void V_SUBREV_I32(const GcnInst& inst); void V_ADDC_U32(const GcnInst& inst); + void V_SUBB_U32(const GcnInst& inst); + void V_SUBBREV_U32(const GcnInst& inst); + void V_LDEXP_F32(const GcnInst& inst); + void V_CVT_PKNORM_U16_F32(const GcnInst& inst); + void V_CVT_PKRTZ_F16_F32(const GcnInst& inst); + + // VOP1 + void V_MOV(const GcnInst& inst); + void V_READFIRSTLANE_B32(const GcnInst& inst); + void V_CVT_I32_F64(const GcnInst& inst); + void V_CVT_F64_I32(const GcnInst& inst); void V_CVT_F32_I32(const GcnInst& inst); void V_CVT_F32_U32(const GcnInst& inst); - void V_MAD_F32(const GcnInst& inst); - void V_FRACT_F32(const GcnInst& inst); - void V_ADD_F32(const GcnInst& inst); - void V_CVT_OFF_F32_I4(const GcnInst& inst); - void V_MED3_F32(const GcnInst& inst); - void V_MED3_I32(const GcnInst& inst); - void V_FLOOR_F32(const GcnInst& inst); - void V_SUB_F32(const GcnInst& inst); - void V_RCP_F32(const GcnInst& inst); - void V_FMA_F32(const GcnInst& inst); - void V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst); - void V_MAX_F32(const GcnInst& inst, bool is_legacy = false); - void V_MAX_U32(bool is_signed, const GcnInst& inst); - void V_RSQ_F32(const GcnInst& inst); - void V_SIN_F32(const GcnInst& inst); - void V_LOG_F32(const GcnInst& inst); - void V_EXP_F32(const GcnInst& inst); - void V_SQRT_F32(const GcnInst& inst); - void V_MIN_F32(const GcnInst& inst, bool is_legacy = false); - void V_MIN3_F32(const GcnInst& inst); - void V_MIN3_I32(const GcnInst& inst); - void V_MADMK_F32(const GcnInst& inst); - void V_CUBEMA_F32(const GcnInst& inst); - void V_CUBESC_F32(const GcnInst& inst); - void V_CUBETC_F32(const GcnInst& inst); - void V_CUBEID_F32(const GcnInst& inst); void V_CVT_U32_F32(const GcnInst& inst); - void V_SUBREV_F32(const GcnInst& inst); - void V_SUBREV_I32(const GcnInst& inst); - void V_MAD_U64_U32(const GcnInst& inst); - void V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst); - void V_LSHRREV_B32(const GcnInst& inst); - void V_MUL_HI_U32(bool is_signed, const GcnInst& inst); - void V_SAD_U32(const GcnInst& inst); - void V_BFE_U32(bool is_signed, const GcnInst& inst); - void V_MAD_I32_I24(const GcnInst& inst, bool is_signed = true); - void V_MUL_I32_I24(const GcnInst& inst); - void V_SUB_I32(const GcnInst& inst); - void V_LSHR_B32(const GcnInst& inst); - void V_ASHRREV_I32(const GcnInst& inst); - void V_ASHR_I32(const GcnInst& inst); - void V_MAD_U32_U24(const GcnInst& inst); - void V_RNDNE_F32(const GcnInst& inst); - void V_BCNT_U32_B32(const GcnInst& inst); - void V_COS_F32(const GcnInst& inst); - void V_MAX3_F32(const GcnInst& inst); - void V_MAX3_U32(const GcnInst& inst); void V_CVT_I32_F32(const GcnInst& inst); - void V_MIN_I32(const GcnInst& inst); - void V_MUL_LO_U32(const GcnInst& inst); + void V_CVT_F16_F32(const GcnInst& inst); + void V_CVT_F32_F16(const GcnInst& inst); + void V_CVT_RPI_I32_F32(const GcnInst& inst); + void V_CVT_FLR_I32_F32(const GcnInst& inst); + void V_CVT_OFF_F32_I4(const GcnInst& inst); + void V_CVT_F32_F64(const GcnInst& inst); + void V_CVT_F64_F32(const GcnInst& inst); + void V_CVT_F32_UBYTE(u32 index, const GcnInst& inst); + void V_FRACT_F32(const GcnInst& inst); void V_TRUNC_F32(const GcnInst& inst); void V_CEIL_F32(const GcnInst& inst); - void V_MIN_U32(const GcnInst& inst); - void V_CMP_NE_U64(const GcnInst& inst); - void V_BFI_B32(const GcnInst& inst); + void V_RNDNE_F32(const GcnInst& inst); + void V_FLOOR_F32(const GcnInst& inst); + void V_EXP_F32(const GcnInst& inst); + void V_LOG_F32(const GcnInst& inst); + void V_RCP_F32(const GcnInst& inst); + void V_RCP_F64(const GcnInst& inst); + void V_RSQ_F32(const GcnInst& inst); + void V_SQRT_F32(const GcnInst& inst); + void V_SIN_F32(const GcnInst& inst); + void V_COS_F32(const GcnInst& inst); void V_NOT_B32(const GcnInst& inst); - void V_CVT_F32_UBYTE(u32 index, const GcnInst& inst); void V_BFREV_B32(const GcnInst& inst); - void V_LDEXP_F32(const GcnInst& inst); - void V_CVT_FLR_I32_F32(const GcnInst& inst); - void V_CMP_CLASS_F32(const GcnInst& inst); + void V_FFBH_U32(const GcnInst& inst); void V_FFBL_B32(const GcnInst& inst); - void V_MBCNT_U32_B32(bool is_low, const GcnInst& inst); + void V_MOVRELD_B32(const GcnInst& inst); + void V_MOVRELS_B32(const GcnInst& inst); + void V_MOVRELSD_B32(const GcnInst& inst); - // Vector Memory - void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_format, const GcnInst& inst); - void BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_format, const GcnInst& inst); - void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst); + // VOPC + void V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst); + void V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst); + void V_CMP_NE_U64(const GcnInst& inst); + void V_CMP_CLASS_F32(const GcnInst& inst); + + // VOP3a + void V_MAD_F32(const GcnInst& inst); + void V_MAD_I32_I24(const GcnInst& inst, bool is_signed = false); + void V_MAD_U32_U24(const GcnInst& inst); + void V_CUBEID_F32(const GcnInst& inst); + void V_CUBESC_F32(const GcnInst& inst); + void V_CUBETC_F32(const GcnInst& inst); + void V_CUBEMA_F32(const GcnInst& inst); + void V_BFE_U32(bool is_signed, const GcnInst& inst); + void V_BFI_B32(const GcnInst& inst); + void V_FMA_F32(const GcnInst& inst); + void V_FMA_F64(const GcnInst& inst); + void V_MIN3_F32(const GcnInst& inst); + void V_MIN3_I32(const GcnInst& inst); + void V_MAX3_F32(const GcnInst& inst); + void V_MAX3_U32(bool is_signed, const GcnInst& inst); + void V_MED3_F32(const GcnInst& inst); + void V_MED3_I32(const GcnInst& inst); + void V_SAD(const GcnInst& inst); + void V_SAD_U32(const GcnInst& inst); + void V_CVT_PK_U8_F32(const GcnInst& inst); + void V_LSHL_B64(const GcnInst& inst); + void V_MUL_F64(const GcnInst& inst); + void V_MAX_F64(const GcnInst& inst); + void V_MUL_LO_U32(const GcnInst& inst); + void V_MUL_HI_U32(bool is_signed, const GcnInst& inst); + void V_MAD_U64_U32(const GcnInst& inst); // Vector interpolation + // VINTRP void V_INTERP_P2_F32(const GcnInst& inst); void V_INTERP_MOV_F32(const GcnInst& inst); // Data share - void DS_SWIZZLE_B32(const GcnInst& inst); - void DS_READ(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst); - void DS_WRITE(int bit_size, bool is_signed, bool is_pair, const GcnInst& inst); + // DS void DS_ADD_U32(const GcnInst& inst, bool rtn); - void DS_MIN_U32(const GcnInst& inst, bool rtn); - void DS_MAX_U32(const GcnInst& inst, bool rtn); - void V_READFIRSTLANE_B32(const GcnInst& inst); - void V_READLANE_B32(const GcnInst& inst); - void V_WRITELANE_B32(const GcnInst& inst); - void S_BARRIER(); + void DS_MIN_U32(const GcnInst& inst, bool is_signed, bool rtn); + void DS_MAX_U32(const GcnInst& inst, bool is_signed, bool rtn); + void DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst); + void DS_SWIZZLE_B32(const GcnInst& inst); + void DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst); + void DS_APPEND(const GcnInst& inst); + void DS_CONSUME(const GcnInst& inst); + // Buffer Memory + // MUBUF / MTBUF + void BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst); + void BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst); + void BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst); + void BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst); + void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst); + + // Image Memory // MIMG + void IMAGE_LOAD(bool has_mip, const GcnInst& inst); + void IMAGE_STORE(const GcnInst& inst); void IMAGE_GET_RESINFO(const GcnInst& inst); + void IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst); void IMAGE_SAMPLE(const GcnInst& inst); void IMAGE_GATHER(const GcnInst& inst); - void IMAGE_STORE(const GcnInst& inst); - void IMAGE_LOAD(bool has_mip, const GcnInst& inst); void IMAGE_GET_LOD(const GcnInst& inst); - void IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst); private: template @@ -222,17 +275,23 @@ private: void SetDst(const InstOperand& operand, const IR::U32F32& value); void SetDst64(const InstOperand& operand, const IR::U64F64& value_raw); + // Vector ALU Helpers + IR::U32 GetCarryIn(const GcnInst& inst); + void SetCarryOut(const GcnInst& inst, const IR::U1& carry); + IR::U32 VMovRelSHelper(u32 src_vgprno, const IR::U32 m0); + void VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, const IR::U32 m0); + void LogMissingOpcode(const GcnInst& inst); private: IR::IREmitter ir; Info& info; + const RuntimeInfo& runtime_info; const Profile& profile; - IR::U32 m0_value; bool opcode_missing = false; }; void Translate(IR::Block* block, u32 block_base, std::span inst_list, Info& info, - const Profile& profile); + const RuntimeInfo& runtime_info, const Profile& profile); } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 1bbc3c162..279695461 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -1,59 +1,134 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "shader_recompiler/frontend/opcodes.h" #include "shader_recompiler/frontend/translate/translate.h" namespace Shader::Gcn { void Translator::EmitVectorAlu(const GcnInst& inst) { switch (inst.opcode) { - case Opcode::V_LSHLREV_B32: - return V_LSHLREV_B32(inst); - case Opcode::V_LSHL_B32: - return V_LSHL_B32(inst); - case Opcode::V_BFREV_B32: - return V_BFREV_B32(inst); - case Opcode::V_BFE_U32: - return V_BFE_U32(false, inst); - case Opcode::V_BFE_I32: - return V_BFE_U32(true, inst); - case Opcode::V_BFI_B32: - return V_BFI_B32(inst); + // VOP2 + case Opcode::V_CNDMASK_B32: + return V_CNDMASK_B32(inst); + case Opcode::V_READLANE_B32: + return V_READLANE_B32(inst); + case Opcode::V_WRITELANE_B32: + return V_WRITELANE_B32(inst); + case Opcode::V_ADD_F32: + return V_ADD_F32(inst); + case Opcode::V_SUB_F32: + return V_SUB_F32(inst); + case Opcode::V_SUBREV_F32: + return V_SUBREV_F32(inst); + case Opcode::V_MAC_LEGACY_F32: + return V_MAC_F32(inst); + case Opcode::V_MUL_LEGACY_F32: + return V_MUL_F32(inst); + case Opcode::V_MUL_F32: + return V_MUL_F32(inst); + case Opcode::V_MUL_I32_I24: + return V_MUL_I32_I24(inst); + case Opcode::V_MUL_U32_U24: + return V_MUL_I32_I24(inst); + case Opcode::V_MIN_LEGACY_F32: + return V_MIN_F32(inst, true); + case Opcode::V_MAX_LEGACY_F32: + return V_MAX_F32(inst, true); + case Opcode::V_MIN_F32: + return V_MIN_F32(inst, false); + case Opcode::V_MAX_F32: + return V_MAX_F32(inst); + case Opcode::V_MIN_I32: + return V_MIN_I32(inst); + case Opcode::V_MAX_I32: + return V_MAX_U32(true, inst); + case Opcode::V_MIN_U32: + return V_MIN_U32(inst); + case Opcode::V_MAX_U32: + return V_MAX_U32(false, inst); case Opcode::V_LSHR_B32: return V_LSHR_B32(inst); - case Opcode::V_ASHRREV_I32: - return V_ASHRREV_I32(inst); - case Opcode::V_ASHR_I32: - return V_ASHR_I32(inst); case Opcode::V_LSHRREV_B32: return V_LSHRREV_B32(inst); - case Opcode::V_NOT_B32: - return V_NOT_B32(inst); + case Opcode::V_ASHR_I32: + return V_ASHR_I32(inst); + case Opcode::V_ASHRREV_I32: + return V_ASHRREV_I32(inst); + case Opcode::V_LSHL_B32: + return V_LSHL_B32(inst); + case Opcode::V_LSHLREV_B32: + return V_LSHLREV_B32(inst); case Opcode::V_AND_B32: return V_AND_B32(inst); case Opcode::V_OR_B32: return V_OR_B32(false, inst); case Opcode::V_XOR_B32: return V_OR_B32(true, inst); - case Opcode::V_FFBL_B32: - return V_FFBL_B32(inst); - - case Opcode::V_MOV_B32: - return V_MOV(inst); + case Opcode::V_BFM_B32: + return V_BFM_B32(inst); + case Opcode::V_MAC_F32: + return V_MAC_F32(inst); + case Opcode::V_MADMK_F32: + return V_MADMK_F32(inst); + case Opcode::V_MADAK_F32: + return V_FMA_F32(inst); + case Opcode::V_BCNT_U32_B32: + return V_BCNT_U32_B32(inst); + case Opcode::V_MBCNT_LO_U32_B32: + return V_MBCNT_U32_B32(true, inst); + case Opcode::V_MBCNT_HI_U32_B32: + return V_MBCNT_U32_B32(false, inst); case Opcode::V_ADD_I32: return V_ADD_I32(inst); + case Opcode::V_SUB_I32: + return V_SUB_I32(inst); + case Opcode::V_SUBREV_I32: + return V_SUBREV_I32(inst); case Opcode::V_ADDC_U32: return V_ADDC_U32(inst); + case Opcode::V_SUBB_U32: + return V_SUBB_U32(inst); + case Opcode::V_SUBBREV_U32: + return V_SUBBREV_U32(inst); + case Opcode::V_LDEXP_F32: + return V_LDEXP_F32(inst); + case Opcode::V_CVT_PKNORM_U16_F32: + return V_CVT_PKNORM_U16_F32(inst); + case Opcode::V_CVT_PKRTZ_F16_F32: + return V_CVT_PKRTZ_F16_F32(inst); + + // VOP1 + case Opcode::V_MOV_B32: + return V_MOV(inst); + case Opcode::V_READFIRSTLANE_B32: + return V_READFIRSTLANE_B32(inst); + case Opcode::V_CVT_I32_F64: + return V_CVT_I32_F64(inst); + case Opcode::V_CVT_F64_I32: + return V_CVT_F64_I32(inst); case Opcode::V_CVT_F32_I32: return V_CVT_F32_I32(inst); case Opcode::V_CVT_F32_U32: return V_CVT_F32_U32(inst); - case Opcode::V_CVT_PKRTZ_F16_F32: - return V_CVT_PKRTZ_F16_F32(inst); - case Opcode::V_CVT_F32_F16: - return V_CVT_F32_F16(inst); + case Opcode::V_CVT_U32_F32: + return V_CVT_U32_F32(inst); + case Opcode::V_CVT_I32_F32: + return V_CVT_I32_F32(inst); case Opcode::V_CVT_F16_F32: return V_CVT_F16_F32(inst); + case Opcode::V_CVT_F32_F16: + return V_CVT_F32_F16(inst); + case Opcode::V_CVT_FLR_I32_F32: + return V_CVT_FLR_I32_F32(inst); + case Opcode::V_CVT_F32_F64: + return V_CVT_F32_F64(inst); + case Opcode::V_CVT_F64_F32: + return V_CVT_F64_F32(inst); + case Opcode::V_CVT_RPI_I32_F32: + return V_CVT_RPI_I32_F32(inst); + case Opcode::V_CVT_OFF_F32_I4: + return V_CVT_OFF_F32_I4(inst); case Opcode::V_CVT_F32_UBYTE0: return V_CVT_F32_UBYTE(0, inst); case Opcode::V_CVT_F32_UBYTE1: @@ -62,34 +137,55 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_CVT_F32_UBYTE(2, inst); case Opcode::V_CVT_F32_UBYTE3: return V_CVT_F32_UBYTE(3, inst); - case Opcode::V_CVT_OFF_F32_I4: - return V_CVT_OFF_F32_I4(inst); - case Opcode::V_MAD_U64_U32: - return V_MAD_U64_U32(inst); - case Opcode::V_CMP_GE_I32: - return V_CMP_U32(ConditionOp::GE, true, false, inst); - case Opcode::V_CMP_EQ_I32: - return V_CMP_U32(ConditionOp::EQ, true, false, inst); - case Opcode::V_CMP_LE_I32: - return V_CMP_U32(ConditionOp::LE, true, false, inst); - case Opcode::V_CMP_NE_I32: - return V_CMP_U32(ConditionOp::LG, true, false, inst); - case Opcode::V_CMP_NE_U32: - return V_CMP_U32(ConditionOp::LG, false, false, inst); - case Opcode::V_CMP_EQ_U32: - return V_CMP_U32(ConditionOp::EQ, false, false, inst); - case Opcode::V_CMP_F_U32: - return V_CMP_U32(ConditionOp::F, false, false, inst); - case Opcode::V_CMP_LT_U32: - return V_CMP_U32(ConditionOp::LT, false, false, inst); - case Opcode::V_CMP_GT_U32: - return V_CMP_U32(ConditionOp::GT, false, false, inst); - case Opcode::V_CMP_GE_U32: - return V_CMP_U32(ConditionOp::GE, false, false, inst); - case Opcode::V_CMP_TRU_U32: - return V_CMP_U32(ConditionOp::TRU, false, false, inst); - case Opcode::V_CMP_NEQ_F32: - return V_CMP_F32(ConditionOp::LG, false, inst); + case Opcode::V_FRACT_F32: + return V_FRACT_F32(inst); + case Opcode::V_TRUNC_F32: + return V_TRUNC_F32(inst); + case Opcode::V_CEIL_F32: + return V_CEIL_F32(inst); + case Opcode::V_RNDNE_F32: + return V_RNDNE_F32(inst); + case Opcode::V_FLOOR_F32: + return V_FLOOR_F32(inst); + case Opcode::V_EXP_F32: + return V_EXP_F32(inst); + case Opcode::V_LOG_F32: + return V_LOG_F32(inst); + case Opcode::V_RCP_F32: + return V_RCP_F32(inst); + case Opcode::V_RCP_F64: + return V_RCP_F64(inst); + case Opcode::V_RCP_IFLAG_F32: + return V_RCP_F32(inst); + case Opcode::V_RSQ_CLAMP_F32: + return V_RSQ_F32(inst); + case Opcode::V_RSQ_LEGACY_F32: + return V_RSQ_F32(inst); + case Opcode::V_RSQ_F32: + return V_RSQ_F32(inst); + case Opcode::V_SQRT_F32: + return V_SQRT_F32(inst); + case Opcode::V_SIN_F32: + return V_SIN_F32(inst); + case Opcode::V_COS_F32: + return V_COS_F32(inst); + case Opcode::V_NOT_B32: + return V_NOT_B32(inst); + case Opcode::V_BFREV_B32: + return V_BFREV_B32(inst); + case Opcode::V_FFBH_U32: + return V_FFBH_U32(inst); + case Opcode::V_FFBL_B32: + return V_FFBL_B32(inst); + case Opcode::V_MOVRELD_B32: + return V_MOVRELD_B32(inst); + case Opcode::V_MOVRELS_B32: + return V_MOVRELS_B32(inst); + case Opcode::V_MOVRELSD_B32: + return V_MOVRELSD_B32(inst); + + // VOPC + // V_CMP_{OP16}_F32 case Opcode::V_CMP_F_F32: return V_CMP_F32(ConditionOp::F, false, inst); case Opcode::V_CMP_LT_F32: @@ -104,145 +200,20 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_CMP_F32(ConditionOp::LG, false, inst); case Opcode::V_CMP_GE_F32: return V_CMP_F32(ConditionOp::GE, false, inst); - case Opcode::V_CMP_NLE_F32: - return V_CMP_F32(ConditionOp::GT, false, inst); - case Opcode::V_CMP_NLT_F32: - return V_CMP_F32(ConditionOp::GE, false, inst); - case Opcode::V_CMP_NGT_F32: - return V_CMP_F32(ConditionOp::LE, false, inst); - case Opcode::V_CMP_NGE_F32: - return V_CMP_F32(ConditionOp::LT, false, inst); case Opcode::V_CMP_U_F32: return V_CMP_F32(ConditionOp::U, false, inst); - case Opcode::V_CNDMASK_B32: - return V_CNDMASK_B32(inst); - case Opcode::V_MAX_I32: - return V_MAX_U32(true, inst); - case Opcode::V_MAX_U32: - return V_MAX_U32(false, inst); - case Opcode::V_MIN_I32: - return V_MIN_I32(inst); - case Opcode::V_CUBEMA_F32: - return V_CUBEMA_F32(inst); - case Opcode::V_CUBESC_F32: - return V_CUBESC_F32(inst); - case Opcode::V_CUBETC_F32: - return V_CUBETC_F32(inst); - case Opcode::V_CUBEID_F32: - return V_CUBEID_F32(inst); - case Opcode::V_CVT_U32_F32: - return V_CVT_U32_F32(inst); - case Opcode::V_CVT_I32_F32: - return V_CVT_I32_F32(inst); - case Opcode::V_CVT_FLR_I32_F32: - return V_CVT_FLR_I32_F32(inst); - case Opcode::V_SUBREV_I32: - return V_SUBREV_I32(inst); - case Opcode::V_MUL_HI_U32: - return V_MUL_HI_U32(false, inst); - case Opcode::V_MUL_LO_I32: - return V_MUL_LO_U32(inst); - case Opcode::V_SAD_U32: - return V_SAD_U32(inst); - case Opcode::V_SUB_I32: - return V_SUB_I32(inst); - case Opcode::V_MAD_I32_I24: - return V_MAD_I32_I24(inst); - case Opcode::V_MUL_I32_I24: - case Opcode::V_MUL_U32_U24: - return V_MUL_I32_I24(inst); - case Opcode::V_MAD_U32_U24: - return V_MAD_U32_U24(inst); - case Opcode::V_BCNT_U32_B32: - return V_BCNT_U32_B32(inst); - case Opcode::V_MUL_LO_U32: - return V_MUL_LO_U32(inst); - case Opcode::V_MIN_U32: - return V_MIN_U32(inst); - case Opcode::V_CMP_NE_U64: - return V_CMP_NE_U64(inst); - case Opcode::V_READFIRSTLANE_B32: - return V_READFIRSTLANE_B32(inst); - case Opcode::V_READLANE_B32: - return V_READLANE_B32(inst); - case Opcode::V_WRITELANE_B32: - return V_WRITELANE_B32(inst); - - case Opcode::V_MAD_F32: - return V_MAD_F32(inst); - case Opcode::V_MAC_F32: - return V_MAC_F32(inst); - case Opcode::V_MUL_F32: - return V_MUL_F32(inst); - case Opcode::V_RCP_F32: - return V_RCP_F32(inst); - case Opcode::V_LDEXP_F32: - return V_LDEXP_F32(inst); - case Opcode::V_FRACT_F32: - return V_FRACT_F32(inst); - case Opcode::V_ADD_F32: - return V_ADD_F32(inst); - case Opcode::V_MED3_F32: - return V_MED3_F32(inst); - case Opcode::V_MED3_I32: - return V_MED3_I32(inst); - case Opcode::V_FLOOR_F32: - return V_FLOOR_F32(inst); - case Opcode::V_SUB_F32: - return V_SUB_F32(inst); - case Opcode::V_FMA_F32: - case Opcode::V_MADAK_F32: - return V_FMA_F32(inst); - case Opcode::V_MAX_F32: - return V_MAX_F32(inst); - case Opcode::V_RSQ_F32: - return V_RSQ_F32(inst); - case Opcode::V_SIN_F32: - return V_SIN_F32(inst); - case Opcode::V_COS_F32: - return V_COS_F32(inst); - case Opcode::V_LOG_F32: - return V_LOG_F32(inst); - case Opcode::V_EXP_F32: - return V_EXP_F32(inst); - case Opcode::V_SQRT_F32: - return V_SQRT_F32(inst); - case Opcode::V_MIN_F32: - return V_MIN_F32(inst, false); - case Opcode::V_MIN3_F32: - return V_MIN3_F32(inst); - case Opcode::V_MIN3_I32: - return V_MIN3_I32(inst); - case Opcode::V_MIN_LEGACY_F32: - return V_MIN_F32(inst, true); - case Opcode::V_MADMK_F32: - return V_MADMK_F32(inst); - case Opcode::V_SUBREV_F32: - return V_SUBREV_F32(inst); - case Opcode::V_RNDNE_F32: - return V_RNDNE_F32(inst); - case Opcode::V_MAX3_F32: - return V_MAX3_F32(inst); - case Opcode::V_MAX3_U32: - return V_MAX3_U32(inst); - case Opcode::V_TRUNC_F32: - return V_TRUNC_F32(inst); - case Opcode::V_CEIL_F32: - return V_CEIL_F32(inst); - case Opcode::V_MUL_LEGACY_F32: - return V_MUL_F32(inst); - case Opcode::V_MAC_LEGACY_F32: - return V_MAC_F32(inst); - case Opcode::V_MAD_LEGACY_F32: - return V_MAD_F32(inst); - case Opcode::V_MAX_LEGACY_F32: - return V_MAX_F32(inst, true); - case Opcode::V_RSQ_LEGACY_F32: - case Opcode::V_RSQ_CLAMP_F32: - return V_RSQ_F32(inst); - case Opcode::V_RCP_IFLAG_F32: - return V_RCP_F32(inst); + case Opcode::V_CMP_NGE_F32: + return V_CMP_F32(ConditionOp::LT, false, inst); + case Opcode::V_CMP_NGT_F32: + return V_CMP_F32(ConditionOp::LE, false, inst); + case Opcode::V_CMP_NLE_F32: + return V_CMP_F32(ConditionOp::GT, false, inst); + case Opcode::V_CMP_NEQ_F32: + return V_CMP_F32(ConditionOp::LG, false, inst); + case Opcode::V_CMP_NLT_F32: + return V_CMP_F32(ConditionOp::GE, false, inst); + // V_CMPX_{OP16}_F32 case Opcode::V_CMPX_F_F32: return V_CMP_F32(ConditionOp::F, true, inst); case Opcode::V_CMPX_LT_F32: @@ -271,17 +242,52 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_CMP_F32(ConditionOp::GE, true, inst); case Opcode::V_CMPX_TRU_F32: return V_CMP_F32(ConditionOp::TRU, true, inst); - case Opcode::V_CMP_CLASS_F32: - return V_CMP_CLASS_F32(inst); - case Opcode::V_CMP_LE_U32: - return V_CMP_U32(ConditionOp::LE, false, false, inst); - case Opcode::V_CMP_GT_I32: - return V_CMP_U32(ConditionOp::GT, true, false, inst); + // V_CMP_{OP8}_I32 case Opcode::V_CMP_LT_I32: return V_CMP_U32(ConditionOp::LT, true, false, inst); + case Opcode::V_CMP_EQ_I32: + return V_CMP_U32(ConditionOp::EQ, true, false, inst); + case Opcode::V_CMP_LE_I32: + return V_CMP_U32(ConditionOp::LE, true, false, inst); + case Opcode::V_CMP_GT_I32: + return V_CMP_U32(ConditionOp::GT, true, false, inst); + case Opcode::V_CMP_NE_I32: + return V_CMP_U32(ConditionOp::LG, true, false, inst); + case Opcode::V_CMP_GE_I32: + return V_CMP_U32(ConditionOp::GE, true, false, inst); + case Opcode::V_CMPX_LE_I32: + return V_CMP_U32(ConditionOp::LE, true, true, inst); + + // V_CMPX_{OP8}_I32 case Opcode::V_CMPX_LT_I32: return V_CMP_U32(ConditionOp::LT, true, true, inst); + case Opcode::V_CMPX_EQ_I32: + return V_CMP_U32(ConditionOp::EQ, true, true, inst); + case Opcode::V_CMPX_GT_I32: + return V_CMP_U32(ConditionOp::GT, true, true, inst); + case Opcode::V_CMPX_LG_I32: + return V_CMP_U32(ConditionOp::LG, true, true, inst); + + // V_CMP_{OP8}_U32 + case Opcode::V_CMP_F_U32: + return V_CMP_U32(ConditionOp::F, false, false, inst); + case Opcode::V_CMP_LT_U32: + return V_CMP_U32(ConditionOp::LT, false, false, inst); + case Opcode::V_CMP_EQ_U32: + return V_CMP_U32(ConditionOp::EQ, false, false, inst); + case Opcode::V_CMP_LE_U32: + return V_CMP_U32(ConditionOp::LE, false, false, inst); + case Opcode::V_CMP_GT_U32: + return V_CMP_U32(ConditionOp::GT, false, false, inst); + case Opcode::V_CMP_NE_U32: + return V_CMP_U32(ConditionOp::LG, false, false, inst); + case Opcode::V_CMP_GE_U32: + return V_CMP_U32(ConditionOp::GE, false, false, inst); + case Opcode::V_CMP_TRU_U32: + return V_CMP_U32(ConditionOp::TRU, false, false, inst); + + // V_CMPX_{OP8}_U32 case Opcode::V_CMPX_F_U32: return V_CMP_U32(ConditionOp::F, false, true, inst); case Opcode::V_CMPX_LT_U32: @@ -298,149 +304,90 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_CMP_U32(ConditionOp::GE, false, true, inst); case Opcode::V_CMPX_TRU_U32: return V_CMP_U32(ConditionOp::TRU, false, true, inst); - case Opcode::V_CMPX_LG_I32: - return V_CMP_U32(ConditionOp::LG, true, true, inst); - case Opcode::V_MBCNT_LO_U32_B32: - return V_MBCNT_U32_B32(true, inst); - case Opcode::V_MBCNT_HI_U32_B32: - return V_MBCNT_U32_B32(false, inst); + // V_CMP_{OP8}_U64 + case Opcode::V_CMP_NE_U64: + return V_CMP_NE_U64(inst); + + case Opcode::V_CMP_CLASS_F32: + return V_CMP_CLASS_F32(inst); + + // VOP3a + case Opcode::V_MAD_LEGACY_F32: + return V_MAD_F32(inst); + case Opcode::V_MAD_F32: + return V_MAD_F32(inst); + case Opcode::V_MAD_I32_I24: + return V_MAD_I32_I24(inst); + case Opcode::V_MAD_U32_U24: + return V_MAD_U32_U24(inst); + case Opcode::V_CUBEID_F32: + return V_CUBEID_F32(inst); + case Opcode::V_CUBESC_F32: + return V_CUBESC_F32(inst); + case Opcode::V_CUBETC_F32: + return V_CUBETC_F32(inst); + case Opcode::V_CUBEMA_F32: + return V_CUBEMA_F32(inst); + case Opcode::V_BFE_U32: + return V_BFE_U32(false, inst); + case Opcode::V_BFE_I32: + return V_BFE_U32(true, inst); + case Opcode::V_BFI_B32: + return V_BFI_B32(inst); + case Opcode::V_FMA_F32: + return V_FMA_F32(inst); + case Opcode::V_FMA_F64: + return V_FMA_F64(inst); + case Opcode::V_MIN3_F32: + return V_MIN3_F32(inst); + case Opcode::V_MIN3_I32: + return V_MIN3_I32(inst); + case Opcode::V_MAX3_F32: + return V_MAX3_F32(inst); + case Opcode::V_MAX3_I32: + return V_MAX3_U32(true, inst); + case Opcode::V_MAX3_U32: + return V_MAX3_U32(false, inst); + case Opcode::V_MED3_F32: + return V_MED3_F32(inst); + case Opcode::V_MED3_I32: + return V_MED3_I32(inst); + case Opcode::V_SAD_U32: + return V_SAD_U32(inst); + case Opcode::V_CVT_PK_U8_F32: + return V_CVT_PK_U8_F32(inst); + case Opcode::V_LSHL_B64: + return V_LSHL_B64(inst); + case Opcode::V_MUL_F64: + return V_MUL_F64(inst); + case Opcode::V_MAX_F64: + return V_MAX_F64(inst); + case Opcode::V_MUL_LO_U32: + return V_MUL_LO_U32(inst); + case Opcode::V_MUL_HI_U32: + return V_MUL_HI_U32(false, inst); + case Opcode::V_MUL_LO_I32: + return V_MUL_LO_U32(inst); + case Opcode::V_MAD_U64_U32: + return V_MAD_U64_U32(inst); + case Opcode::V_NOP: + return; default: LogMissingOpcode(inst); } } -void Translator::V_MOV(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::V_SAD(const GcnInst& inst) { - const IR::U32 abs_diff = ir.IAbs(ir.ISub(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); - SetDst(inst.dst[0], ir.IAdd(abs_diff, GetSrc(inst.src[2]))); -} - -void Translator::V_MAC_F32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.FPFma(GetSrc(inst.src[0]), GetSrc(inst.src[1]), - GetSrc(inst.dst[0]))); -} - -void Translator::V_CVT_PKRTZ_F16_F32(const GcnInst& inst) { - const IR::VectorReg dst_reg{inst.dst[0].code}; - const IR::Value vec_f32 = - ir.CompositeConstruct(GetSrc(inst.src[0]), GetSrc(inst.src[1])); - ir.SetVectorReg(dst_reg, ir.PackHalf2x16(vec_f32)); -} - -void Translator::V_CVT_F32_F16(const GcnInst& inst) { - const IR::U32 src0 = GetSrc(inst.src[0]); - const IR::U16 src0l = ir.UConvert(16, src0); - SetDst(inst.dst[0], ir.FPConvert(32, ir.BitCast(src0l))); -} - -void Translator::V_CVT_F16_F32(const GcnInst& inst) { - const IR::F32 src0 = GetSrc(inst.src[0]); - const IR::F16 src0fp16 = ir.FPConvert(16, src0); - SetDst(inst.dst[0], ir.UConvert(32, ir.BitCast(src0fp16))); -} - -void Translator::V_MUL_F32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.FPMul(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); -} +// VOP2 void Translator::V_CNDMASK_B32(const GcnInst& inst) { - const IR::VectorReg dst_reg{inst.dst[0].code}; const IR::ScalarReg flag_reg{inst.src[2].code}; const IR::U1 flag = inst.src[2].field == OperandField::ScalarGPR ? ir.GetThreadBitScalarReg(flag_reg) : ir.GetVcc(); const IR::Value result = ir.Select(flag, GetSrc(inst.src[1]), GetSrc(inst.src[0])); - ir.SetVectorReg(dst_reg, IR::U32F32{result}); -} - -void Translator::V_OR_B32(bool is_xor, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, - is_xor ? ir.BitwiseXor(src0, src1) : IR::U32(ir.BitwiseOr(src0, src1))); -} - -void Translator::V_AND_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.BitwiseAnd(src0, src1)); -} - -void Translator::V_LSHLREV_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.ShiftLeftLogical(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); -} - -void Translator::V_LSHL_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); -} - -void Translator::V_ADD_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.IAdd(src0, src1)); - // TODO: Carry -} - -void Translator::V_ADDC_U32(const GcnInst& inst) { - - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - - IR::U32 scarry; - if (inst.src_count == 3) { // VOP3 - IR::U1 thread_bit{ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[2].code))}; - scarry = IR::U32{ir.Select(thread_bit, ir.Imm32(1), ir.Imm32(0))}; - } else { // VOP2 - scarry = ir.GetVccLo(); - } - - const IR::U32 result = ir.IAdd(ir.IAdd(src0, src1), scarry); - - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, result); - - const IR::U1 less_src0 = ir.ILessThan(result, src0, false); - const IR::U1 less_src1 = ir.ILessThan(result, src1, false); - const IR::U1 did_overflow = ir.LogicalOr(less_src0, less_src1); - ir.SetVcc(did_overflow); -} - -void Translator::V_CVT_F32_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.ConvertSToF(32, 32, src0)); -} - -void Translator::V_CVT_F32_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.ConvertUToF(32, 32, src0)); -} - -void Translator::V_MAD_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPFma(src0, src1, src2)); -} - -void Translator::V_FRACT_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.Fract(src0)); + SetDst(inst.dst[0], IR::U32F32{result}); } void Translator::V_ADD_F32(const GcnInst& inst) { @@ -449,55 +396,449 @@ void Translator::V_ADD_F32(const GcnInst& inst) { SetDst(inst.dst[0], ir.FPAdd(src0, src1)); } -void Translator::V_CVT_OFF_F32_I4(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg( - dst_reg, - ir.FPMul(ir.ConvertUToF(32, 32, ir.ISub(ir.BitwiseAnd(src0, ir.Imm32(0xF)), ir.Imm32(8))), - ir.Imm32(1.f / 16.f))); -} - -void Translator::V_MED3_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - const IR::F32 mmx = ir.FPMin(ir.FPMax(src0, src1), src2); - SetDst(inst.dst[0], ir.FPMax(ir.FPMin(src0, src1), mmx)); -} - -void Translator::V_MED3_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - const IR::U32 mmx = ir.SMin(ir.SMax(src0, src1), src2); - SetDst(inst.dst[0], ir.SMax(ir.SMin(src0, src1), mmx)); -} - -void Translator::V_FLOOR_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::VectorReg dst_reg{inst.dst[0].code}; - ir.SetVectorReg(dst_reg, ir.FPFloor(src0)); -} - void Translator::V_SUB_F32(const GcnInst& inst) { const IR::F32 src0{GetSrc(inst.src[0])}; const IR::F32 src1{GetSrc(inst.src[1])}; SetDst(inst.dst[0], ir.FPSub(src0, src1)); } +void Translator::V_SUBREV_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.FPSub(src1, src0)); +} + +void Translator::V_MUL_F32(const GcnInst& inst) { + SetDst(inst.dst[0], ir.FPMul(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); +} + +void Translator::V_MUL_I32_I24(const GcnInst& inst) { + const IR::U32 src0{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(24), true)}; + const IR::U32 src1{ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(24), true)}; + SetDst(inst.dst[0], ir.IMul(src0, src1)); +} + +void Translator::V_MIN_F32(const GcnInst& inst, bool is_legacy) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.FPMin(src0, src1, is_legacy)); +} + +void Translator::V_MAX_F32(const GcnInst& inst, bool is_legacy) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.FPMax(src0, src1, is_legacy)); +} + +void Translator::V_MIN_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.SMin(src0, src1)); +} + +void Translator::V_MIN_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.IMin(src0, src1, false)); +} + +void Translator::V_MAX_U32(bool is_signed, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.IMax(src0, src1, is_signed)); +} + +void Translator::V_LSHR_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ShiftRightLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); +} + +void Translator::V_LSHRREV_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ShiftRightLogical(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); +} + +void Translator::V_ASHR_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); +} + +void Translator::V_ASHRREV_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ShiftRightArithmetic(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); +} + +void Translator::V_LSHL_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); +} + +void Translator::V_LSHLREV_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.ShiftLeftLogical(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); +} + +void Translator::V_AND_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; + SetDst(inst.dst[0], ir.BitwiseAnd(src0, src1)); +} + +void Translator::V_OR_B32(bool is_xor, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; + SetDst(inst.dst[0], is_xor ? ir.BitwiseXor(src0, src1) : IR::U32(ir.BitwiseOr(src0, src1))); +} + +void Translator::V_BFM_B32(const GcnInst& inst) { + // bitmask width + const IR::U32 src0{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(4))}; + // bitmask offset + const IR::U32 src1{ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(4))}; + const IR::U32 ones = ir.ISub(ir.ShiftLeftLogical(ir.Imm32(1), src0), ir.Imm32(1)); + SetDst(inst.dst[0], ir.ShiftLeftLogical(ones, src1)); +} + +void Translator::V_MAC_F32(const GcnInst& inst) { + SetDst(inst.dst[0], ir.FPFma(GetSrc(inst.src[0]), GetSrc(inst.src[1]), + GetSrc(inst.dst[0]))); +} + +void Translator::V_MADMK_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::F32 k{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.FPFma(src0, k, src1)); +} + +void Translator::V_BCNT_U32_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.IAdd(ir.BitCount(src0), src1)); +} + +void Translator::V_MBCNT_U32_B32(bool is_low, const GcnInst& inst) { + if (!is_low) { + // v_mbcnt_hi_u32_b32 v2, -1, 0 + if (inst.src[0].field == OperandField::SignedConstIntNeg && inst.src[0].code == 193 && + inst.src[1].field == OperandField::ConstZero) { + return; + } + // v_mbcnt_hi_u32_b32 vX, exec_hi, 0 + if (inst.src[0].field == OperandField::ExecHi && + inst.src[1].field == OperandField::ConstZero) { + return; + } + } else { + // v_mbcnt_lo_u32_b32 v2, -1, vX + // used combined with above to fetch lane id in non-compute stages + if (inst.src[0].field == OperandField::SignedConstIntNeg && inst.src[0].code == 193) { + SetDst(inst.dst[0], ir.LaneId()); + } + // v_mbcnt_lo_u32_b32 v20, exec_lo, vX + // used combined in above for append buffer indexing. + if (inst.src[0].field == OperandField::ExecLo) { + SetDst(inst.dst[0], ir.Imm32(0)); + } + } +} + +void Translator::V_ADD_I32(const GcnInst& inst) { + // Signed or unsigned components + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))}; + const IR::U32 result{ir.IAdd(src0, src1)}; + SetDst(inst.dst[0], result); + + // TODO: Carry-out with signed or unsigned components +} + +void Translator::V_SUB_I32(const GcnInst& inst) { + // Unsigned components + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.ISub(src0, src1)}; + SetDst(inst.dst[0], result); + + const IR::U1 did_underflow{ir.IGreaterThan(src1, src0, false)}; + SetCarryOut(inst, did_underflow); +} + +void Translator::V_SUBREV_I32(const GcnInst& inst) { + // Unsigned components + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.ISub(src1, src0)}; + SetDst(inst.dst[0], result); + + const IR::U1 did_underflow{ir.IGreaterThan(src0, src1, false)}; + SetCarryOut(inst, did_underflow); +} + +void Translator::V_ADDC_U32(const GcnInst& inst) { + // Unsigned components + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 carry{GetCarryIn(inst)}; + const IR::U32 result{ir.IAdd(ir.IAdd(src0, src1), carry)}; + SetDst(inst.dst[0], result); + + const IR::U1 less_src0{ir.ILessThan(result, src0, false)}; + const IR::U1 less_src1{ir.ILessThan(result, src1, false)}; + const IR::U1 did_overflow{ir.LogicalOr(less_src0, less_src1)}; + SetCarryOut(inst, did_overflow); +} + +void Translator::V_SUBB_U32(const GcnInst& inst) { + // Signed or unsigned components + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 carry{GetCarryIn(inst)}; + const IR::U32 result{ir.ISub(ir.ISub(src0, src1), carry)}; + SetDst(inst.dst[0], result); + + // TODO: Carry-out with signed or unsigned components +} + +void Translator::V_SUBBREV_U32(const GcnInst& inst) { + // Signed or unsigned components + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 carry{GetCarryIn(inst)}; + const IR::U32 result{ir.ISub(ir.ISub(src1, src0), carry)}; + SetDst(inst.dst[0], result); + + // TODO: Carry-out with signed or unsigned components +} + +void Translator::V_LDEXP_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.FPLdexp(src0, src1)); +} + +void Translator::V_CVT_PKNORM_U16_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::U32 dst0 = ir.ConvertFToU(32, ir.FPMul(src0, ir.Imm32(65535.f))); + const IR::U32 dst1 = ir.ConvertFToU(32, ir.FPMul(src1, ir.Imm32(65535.f))); + const IR::VectorReg dst_reg{inst.dst[0].code}; + ir.SetVectorReg(dst_reg, ir.BitFieldInsert(dst0, dst1, ir.Imm32(16), ir.Imm32(16))); +} + +void Translator::V_CVT_PKRTZ_F16_F32(const GcnInst& inst) { + const IR::Value vec_f32 = + ir.CompositeConstruct(GetSrc(inst.src[0]), GetSrc(inst.src[1])); + SetDst(inst.dst[0], ir.PackHalf2x16(vec_f32)); +} + +// VOP1 + +void Translator::V_MOV(const GcnInst& inst) { + SetDst(inst.dst[0], GetSrc(inst.src[0])); +} + +void Translator::V_CVT_I32_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertFToS(32, src0)); +} + +void Translator::V_CVT_F64_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + SetDst64(inst.dst[0], ir.ConvertSToF(64, 32, src0)); +} + +void Translator::V_CVT_F32_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertSToF(32, 32, src0)); +} + +void Translator::V_CVT_F32_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertUToF(32, 32, src0)); +} + +void Translator::V_CVT_U32_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertFToU(32, src0)); +} + +void Translator::V_CVT_I32_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertFToS(32, src0)); +} + +void Translator::V_CVT_F16_F32(const GcnInst& inst) { + const IR::F32 src0 = GetSrc(inst.src[0]); + const IR::F16 src0fp16 = ir.FPConvert(16, src0); + SetDst(inst.dst[0], ir.UConvert(32, ir.BitCast(src0fp16))); +} + +void Translator::V_CVT_F32_F16(const GcnInst& inst) { + const IR::U32 src0 = GetSrc(inst.src[0]); + const IR::U16 src0l = ir.UConvert(16, src0); + SetDst(inst.dst[0], ir.FPConvert(32, ir.BitCast(src0l))); +} + +void Translator::V_CVT_RPI_I32_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertFToI(32, true, ir.FPFloor(ir.FPAdd(src0, ir.Imm32(0.5f))))); +} + +void Translator::V_CVT_FLR_I32_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.ConvertFToI(32, true, ir.FPFloor(src0))); +} + +void Translator::V_CVT_OFF_F32_I4(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + ASSERT(src0.IsImmediate()); + static constexpr std::array IntToFloat = { + 0.0f, 0.0625f, 0.1250f, 0.1875f, 0.2500f, 0.3125f, 0.3750f, 0.4375f, + -0.5000f, -0.4375f, -0.3750f, -0.3125f, -0.2500f, -0.1875f, -0.1250f, -0.0625f}; + SetDst(inst.dst[0], ir.Imm32(IntToFloat[src0.U32() & 0xF])); +} + +void Translator::V_CVT_F32_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + SetDst(inst.dst[0], ir.FPConvert(32, src0)); +} + +void Translator::V_CVT_F64_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst64(inst.dst[0], ir.FPConvert(64, src0)); +} + +void Translator::V_CVT_F32_UBYTE(u32 index, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 byte = ir.BitFieldExtract(src0, ir.Imm32(8 * index), ir.Imm32(8)); + SetDst(inst.dst[0], ir.ConvertUToF(32, 32, byte)); +} + +void Translator::V_FRACT_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.Fract(src0)); +} + +void Translator::V_TRUNC_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPTrunc(src0)); +} + +void Translator::V_CEIL_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPCeil(src0)); +} + +void Translator::V_RNDNE_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPRoundEven(src0)); +} + +void Translator::V_FLOOR_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPFloor(src0)); +} + +void Translator::V_EXP_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPExp2(src0)); +} + +void Translator::V_LOG_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPLog2(src0)); +} + void Translator::V_RCP_F32(const GcnInst& inst) { const IR::F32 src0{GetSrc(inst.src[0])}; SetDst(inst.dst[0], ir.FPRecip(src0)); } -void Translator::V_FMA_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPFma(src0, src1, src2)); +void Translator::V_RCP_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + SetDst64(inst.dst[0], ir.FPRecip(src0)); } +void Translator::V_RSQ_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPRecipSqrt(src0)); +} + +void Translator::V_SQRT_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPSqrt(src0)); +} + +void Translator::V_SIN_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPSin(src0)); +} + +void Translator::V_COS_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FPCos(src0)); +} + +void Translator::V_NOT_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.BitwiseNot(src0)); +} + +void Translator::V_BFREV_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.BitReverse(src0)); +} + +void Translator::V_FFBH_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) + // position + const IR::U32 msb_pos = ir.FindUMsb(src0); + const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); + // Select 0xFFFFFFFF if src0 was 0 + const IR::U1 cond = ir.INotEqual(src0, ir.Imm32(0)); + SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); +} + +void Translator::V_FFBL_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + SetDst(inst.dst[0], ir.FindILsb(src0)); +} + +void Translator::V_MOVRELD_B32(const GcnInst& inst) { + const IR::U32 src_val{GetSrc(inst.src[0])}; + u32 dst_vgprno = inst.dst[0].code - static_cast(IR::VectorReg::V0); + IR::U32 m0 = ir.GetM0(); + + VMovRelDHelper(dst_vgprno, src_val, m0); +} + +void Translator::V_MOVRELS_B32(const GcnInst& inst) { + u32 src_vgprno = inst.src[0].code - static_cast(IR::VectorReg::V0); + const IR::U32 m0 = ir.GetM0(); + + const IR::U32 src_val = VMovRelSHelper(src_vgprno, m0); + SetDst(inst.dst[0], src_val); +} + +void Translator::V_MOVRELSD_B32(const GcnInst& inst) { + u32 src_vgprno = inst.src[0].code - static_cast(IR::VectorReg::V0); + u32 dst_vgprno = inst.dst[0].code - static_cast(IR::VectorReg::V0); + IR::U32 m0 = ir.GetM0(); + + const IR::U32 src_val = VMovRelSHelper(src_vgprno, m0); + VMovRelDHelper(dst_vgprno, src_val, m0); +} + +// VOPC + void Translator::V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst) { const IR::F32 src0{GetSrc(inst.src[0])}; const IR::F32 src1{GetSrc(inst.src[1])}; @@ -539,122 +880,6 @@ void Translator::V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst) { } } -void Translator::V_MAX_F32(const GcnInst& inst, bool is_legacy) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPMax(src0, src1, is_legacy)); -} - -void Translator::V_MAX_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IMax(src0, src1, is_signed)); -} - -void Translator::V_RSQ_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPRecipSqrt(src0)); -} - -void Translator::V_SIN_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPSin(src0)); -} - -void Translator::V_LOG_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPLog2(src0)); -} - -void Translator::V_EXP_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPExp2(src0)); -} - -void Translator::V_SQRT_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPSqrt(src0)); -} - -void Translator::V_MIN_F32(const GcnInst& inst, bool is_legacy) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPMin(src0, src1, is_legacy)); -} - -void Translator::V_MIN3_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPMin(src0, ir.FPMin(src1, src2))); -} - -void Translator::V_MIN3_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.SMin(src0, ir.SMin(src1, src2))); -} - -void Translator::V_MADMK_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 k{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPFma(src0, k, src1)); -} - -void Translator::V_CUBEMA_F32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.Imm32(1.f)); -} - -void Translator::V_CUBESC_F32(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::V_CUBETC_F32(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[1])); -} - -void Translator::V_CUBEID_F32(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[2])); -} - -void Translator::V_CVT_U32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToU(32, src0)); -} - -void Translator::V_SUBREV_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPSub(src1, src0)); -} - -void Translator::V_SUBREV_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ISub(src1, src0)); - // TODO: Carry-out -} - -void Translator::V_MAD_U64_U32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc64(inst.src[2]); - - // const IR::U64 mul_result = ir.UConvert(64, ir.IMul(src0, src1)); - const IR::U64 mul_result = - ir.PackUint2x32(ir.CompositeConstruct(ir.IMul(src0, src1), ir.Imm32(0U))); - const IR::U64 sum_result = ir.IAdd(mul_result, src2); - - SetDst64(inst.dst[0], sum_result); - - const IR::U1 less_src0 = ir.ILessThan(sum_result, mul_result, false); - const IR::U1 less_src1 = ir.ILessThan(sum_result, src2, false); - const IR::U1 did_overflow = ir.LogicalOr(less_src0, less_src1); - ir.SetVcc(did_overflow); -} - void Translator::V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; @@ -693,149 +918,6 @@ void Translator::V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const } } -void Translator::V_LSHRREV_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightLogical(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); -} - -void Translator::V_MUL_HI_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 hi{ir.CompositeExtract(ir.IMulExt(src0, src1, is_signed), 1)}; - SetDst(inst.dst[0], hi); -} - -void Translator::V_SAD_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - IR::U32 result; - if (src0.IsImmediate() && src0.U32() == 0U) { - result = src1; - } else if (src1.IsImmediate() && src1.U32() == 0U) { - result = src0; - } else { - const IR::U32 max{ir.IMax(src0, src1, false)}; - const IR::U32 min{ir.IMin(src0, src1, false)}; - result = ir.ISub(max, min); - } - SetDst(inst.dst[0], ir.IAdd(result, src2)); -} - -void Translator::V_BFE_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{ir.BitwiseAnd(GetSrc(inst.src[1]), ir.Imm32(0x1F))}; - const IR::U32 src2{ir.BitwiseAnd(GetSrc(inst.src[2]), ir.Imm32(0x1F))}; - SetDst(inst.dst[0], ir.BitFieldExtract(src0, src1, src2, is_signed)); -} - -void Translator::V_MAD_I32_I24(const GcnInst& inst, bool is_signed) { - const IR::U32 src0{ - ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(24), is_signed)}; - const IR::U32 src1{ - ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(24), is_signed)}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.IAdd(ir.IMul(src0, src1), src2)); -} - -void Translator::V_MUL_I32_I24(const GcnInst& inst) { - const IR::U32 src0{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(24), true)}; - const IR::U32 src1{ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(24), true)}; - SetDst(inst.dst[0], ir.IMul(src0, src1)); -} - -void Translator::V_SUB_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ISub(src0, src1)); -} - -void Translator::V_LSHR_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); -} - -void Translator::V_ASHRREV_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightArithmetic(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); -} - -void Translator::V_ASHR_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); -} - -void Translator::V_MAD_U32_U24(const GcnInst& inst) { - V_MAD_I32_I24(inst, false); -} - -void Translator::V_RNDNE_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPRoundEven(src0)); -} - -void Translator::V_BCNT_U32_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IAdd(ir.BitCount(src0), src1)); -} - -void Translator::V_COS_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPCos(src0)); -} - -void Translator::V_MAX3_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPMax(src0, ir.FPMax(src1, src2))); -} - -void Translator::V_MAX3_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.UMax(src0, ir.UMax(src1, src2))); -} - -void Translator::V_CVT_I32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToS(32, src0)); -} - -void Translator::V_MIN_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.SMin(src0, src1)); -} - -void Translator::V_MUL_LO_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IMul(src0, src1)); -} - -void Translator::V_TRUNC_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPTrunc(src0)); -} - -void Translator::V_CEIL_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPCeil(src0)); -} - -void Translator::V_MIN_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IMin(src0, src1, false)); -} - void Translator::V_CMP_NE_U64(const GcnInst& inst) { const auto get_src = [&](const InstOperand& operand) { switch (operand.field) { @@ -865,41 +947,6 @@ void Translator::V_CMP_NE_U64(const GcnInst& inst) { } } -void Translator::V_BFI_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], - ir.BitwiseOr(ir.BitwiseAnd(src0, src1), ir.BitwiseAnd(ir.BitwiseNot(src0), src2))); -} - -void Translator::V_NOT_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.BitwiseNot(src0)); -} - -void Translator::V_CVT_F32_UBYTE(u32 index, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 byte = ir.BitFieldExtract(src0, ir.Imm32(8 * index), ir.Imm32(8)); - SetDst(inst.dst[0], ir.ConvertUToF(32, 32, byte)); -} - -void Translator::V_BFREV_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.BitReverse(src0)); -} - -void Translator::V_LDEXP_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPLdexp(src0, src1)); -} - -void Translator::V_CVT_FLR_I32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToI(32, true, ir.FPFloor(src0))); -} - void Translator::V_CMP_CLASS_F32(const GcnInst& inst) { const IR::F32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; @@ -921,25 +968,266 @@ void Translator::V_CMP_CLASS_F32(const GcnInst& inst) { switch (inst.dst[1].field) { case OperandField::VccLo: return ir.SetVcc(value); + case OperandField::ScalarGPR: + return ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[1].code), value); default: UNREACHABLE(); } } -void Translator::V_FFBL_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FindILsb(src0)); +// VOP3a + +void Translator::V_MAD_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::F32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.FPFma(src0, src1, src2)); } -void Translator::V_MBCNT_U32_B32(bool is_low, const GcnInst& inst) { +void Translator::V_MAD_I32_I24(const GcnInst& inst, bool is_signed) { + const IR::U32 src0{ + ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(24), is_signed)}; + const IR::U32 src1{ + ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(24), is_signed)}; + const IR::U32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.IAdd(ir.IMul(src0, src1), src2)); +} + +void Translator::V_MAD_U32_U24(const GcnInst& inst) { + V_MAD_I32_I24(inst, false); +} + +void Translator::V_CUBEID_F32(const GcnInst& inst) { + SetDst(inst.dst[0], GetSrc(inst.src[2])); +} + +void Translator::V_CUBESC_F32(const GcnInst& inst) { + SetDst(inst.dst[0], GetSrc(inst.src[0])); +} + +void Translator::V_CUBETC_F32(const GcnInst& inst) { + SetDst(inst.dst[0], GetSrc(inst.src[1])); +} + +void Translator::V_CUBEMA_F32(const GcnInst& inst) { + SetDst(inst.dst[0], ir.Imm32(1.f)); +} + +void Translator::V_BFE_U32(bool is_signed, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{ir.BitwiseAnd(GetSrc(inst.src[1]), ir.Imm32(0x1F))}; + const IR::U32 src2{ir.BitwiseAnd(GetSrc(inst.src[2]), ir.Imm32(0x1F))}; + SetDst(inst.dst[0], ir.BitFieldExtract(src0, src1, src2, is_signed)); +} + +void Translator::V_BFI_B32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - if (!is_low) { - ASSERT(src0.IsImmediate() && src0.U32() == ~0U && src1.IsImmediate() && src1.U32() == 0U); + const IR::U32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], + ir.BitwiseOr(ir.BitwiseAnd(src0, src1), ir.BitwiseAnd(ir.BitwiseNot(src0), src2))); +} + +void Translator::V_FMA_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::F32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.FPFma(src0, src1, src2)); +} + +void Translator::V_FMA_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + const IR::F64 src1{GetSrc64(inst.src[1])}; + const IR::F64 src2{GetSrc64(inst.src[2])}; + SetDst64(inst.dst[0], ir.FPFma(src0, src1, src2)); +} + +void Translator::V_MIN3_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::F32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.FPMin(src0, ir.FPMin(src1, src2))); +} + +void Translator::V_MIN3_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.SMin(src0, ir.SMin(src1, src2))); +} + +void Translator::V_MAX3_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::F32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.FPMax(src0, ir.FPMax(src1, src2))); +} + +void Translator::V_MAX3_U32(bool is_signed, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 src2{GetSrc(inst.src[2])}; + SetDst(inst.dst[0], ir.IMax(src0, ir.IMax(src1, src2, is_signed), is_signed)); +} + +void Translator::V_MED3_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::F32 src1{GetSrc(inst.src[1])}; + const IR::F32 src2{GetSrc(inst.src[2])}; + const IR::F32 mmx = ir.FPMin(ir.FPMax(src0, src1), src2); + SetDst(inst.dst[0], ir.FPMax(ir.FPMin(src0, src1), mmx)); +} + +void Translator::V_MED3_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 src2{GetSrc(inst.src[2])}; + const IR::U32 mmx = ir.SMin(ir.SMax(src0, src1), src2); + SetDst(inst.dst[0], ir.SMax(ir.SMin(src0, src1), mmx)); +} + +void Translator::V_SAD(const GcnInst& inst) { + const IR::U32 abs_diff = ir.IAbs(ir.ISub(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); + SetDst(inst.dst[0], ir.IAdd(abs_diff, GetSrc(inst.src[2]))); +} + +void Translator::V_SAD_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 src2{GetSrc(inst.src[2])}; + IR::U32 result; + if (src0.IsImmediate() && src0.U32() == 0U) { + result = src1; + } else if (src1.IsImmediate() && src1.U32() == 0U) { + result = src0; + } else { + const IR::U32 max{ir.IMax(src0, src1, false)}; + const IR::U32 min{ir.IMin(src0, src1, false)}; + result = ir.ISub(max, min); + } + SetDst(inst.dst[0], ir.IAdd(result, src2)); +} + +void Translator::V_CVT_PK_U8_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 src2{GetSrc(inst.src[2])}; + + const IR::U32 value_uint = ir.ConvertFToU(32, src0); + const IR::U32 offset = ir.ShiftLeftLogical(src1, ir.Imm32(3)); + SetDst(inst.dst[0], ir.BitFieldInsert(src2, value_uint, offset, ir.Imm32(8))); +} + +void Translator::V_LSHL_B64(const GcnInst& inst) { + const IR::U64 src0{GetSrc64(inst.src[0])}; + const IR::U64 src1{GetSrc64(inst.src[1])}; + const IR::VectorReg dst_reg{inst.dst[0].code}; + if (src0.IsImmediate() && src0.U64() == -1) { + ir.SetVectorReg(dst_reg, ir.Imm32(0xFFFFFFFF)); + ir.SetVectorReg(dst_reg + 1, ir.Imm32(0xFFFFFFFF)); return; } - ASSERT(src0.IsImmediate() && src0.U32() == ~0U); - SetDst(inst.dst[0], ir.LaneId()); + ASSERT_MSG(src0.IsImmediate() && src0.U64() == 0 && src1.IsImmediate() && src1.U64() == 0, + "V_LSHL_B64 with non-zero src0 or src1 is not supported"); + ir.SetVectorReg(dst_reg, ir.Imm32(0)); + ir.SetVectorReg(dst_reg + 1, ir.Imm32(0)); +} + +void Translator::V_MUL_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + const IR::F64 src1{GetSrc64(inst.src[1])}; + SetDst64(inst.dst[0], ir.FPMul(src0, src1)); +} + +void Translator::V_MAX_F64(const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + const IR::F64 src1{GetSrc64(inst.src[1])}; + SetDst64(inst.dst[0], ir.FPMax(src0, src1)); +} + +void Translator::V_MUL_LO_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.IMul(src0, src1)); +} + +void Translator::V_MUL_HI_U32(bool is_signed, const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 hi{ir.CompositeExtract(ir.IMulExt(src0, src1, is_signed), 1)}; + SetDst(inst.dst[0], hi); +} + +void Translator::V_MAD_U64_U32(const GcnInst& inst) { + const auto src0 = GetSrc(inst.src[0]); + const auto src1 = GetSrc(inst.src[1]); + const auto src2 = GetSrc64(inst.src[2]); + + // const IR::U64 mul_result = ir.UConvert(64, ir.IMul(src0, src1)); + const IR::U64 mul_result = + ir.PackUint2x32(ir.CompositeConstruct(ir.IMul(src0, src1), ir.Imm32(0U))); + const IR::U64 sum_result = ir.IAdd(mul_result, src2); + + SetDst64(inst.dst[0], sum_result); + + const IR::U1 less_src0 = ir.ILessThan(sum_result, mul_result, false); + const IR::U1 less_src1 = ir.ILessThan(sum_result, src2, false); + const IR::U1 did_overflow = ir.LogicalOr(less_src0, less_src1); + ir.SetVcc(did_overflow); +} + +IR::U32 Translator::GetCarryIn(const GcnInst& inst) { + IR::U1 carry; + if (inst.src_count == 3) { // VOP3 + if (inst.src[2].field == OperandField::VccLo) { + carry = ir.GetVcc(); + } else if (inst.src[2].field == OperandField::ScalarGPR) { + carry = ir.GetThreadBitScalarReg(IR::ScalarReg(inst.src[2].code)); + } else { + UNREACHABLE(); + } + } else { // VOP2 + carry = ir.GetVcc(); + } + + return IR::U32{ir.Select(carry, ir.Imm32(1), ir.Imm32(0))}; +} + +void Translator::SetCarryOut(const GcnInst& inst, const IR::U1& carry) { + if (inst.dst_count == 2) { // VOP3 + if (inst.dst[1].field == OperandField::VccLo) { + ir.SetVcc(carry); + } else if (inst.dst[1].field == OperandField::ScalarGPR) { + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[1].code), carry); + } else { + UNREACHABLE(); + } + } else { // VOP2 + ir.SetVcc(carry); + } +} + +// TODO: add range analysis pass to hopefully put an upper bound on m0, and only select one of +// [src_vgprno, src_vgprno + max_m0]. Same for dst regs we may write back to + +IR::U32 Translator::VMovRelSHelper(u32 src_vgprno, const IR::U32 m0) { + // Read from VGPR0 by default when src_vgprno + m0 > num_allocated_vgprs + IR::U32 src_val = ir.GetVectorReg(IR::VectorReg::V0); + for (u32 i = src_vgprno; i < runtime_info.num_allocated_vgprs; i++) { + const IR::U1 cond = ir.IEqual(m0, ir.Imm32(i - src_vgprno)); + src_val = + IR::U32{ir.Select(cond, ir.GetVectorReg(IR::VectorReg::V0 + i), src_val)}; + } + return src_val; +} + +void Translator::VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, const IR::U32 m0) { + for (u32 i = dst_vgprno; i < runtime_info.num_allocated_vgprs; i++) { + const IR::U1 cond = ir.IEqual(m0, ir.Imm32(i - dst_vgprno)); + const IR::U32 dst_val = + IR::U32{ir.Select(cond, src_val, ir.GetVectorReg(IR::VectorReg::V0 + i))}; + ir.SetVectorReg(IR::VectorReg::V0 + i, dst_val); + } } } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/vector_interpolation.cpp b/src/shader_recompiler/frontend/translate/vector_interpolation.cpp index 4ff846cf8..431cb2f04 100644 --- a/src/shader_recompiler/frontend/translate/vector_interpolation.cpp +++ b/src/shader_recompiler/frontend/translate/vector_interpolation.cpp @@ -5,22 +5,9 @@ namespace Shader::Gcn { -void Translator::V_INTERP_P2_F32(const GcnInst& inst) { - const IR::VectorReg dst_reg{inst.dst[0].code}; - auto& attr = info.ps_inputs.at(inst.control.vintrp.attr); - const IR::Attribute attrib{IR::Attribute::Param0 + attr.param_index}; - ir.SetVectorReg(dst_reg, ir.GetAttribute(attrib, inst.control.vintrp.chan)); -} - -void Translator::V_INTERP_MOV_F32(const GcnInst& inst) { - const IR::VectorReg dst_reg{inst.dst[0].code}; - auto& attr = info.ps_inputs.at(inst.control.vintrp.attr); - const IR::Attribute attrib{IR::Attribute::Param0 + attr.param_index}; - ir.SetVectorReg(dst_reg, ir.GetAttribute(attrib, inst.control.vintrp.chan)); -} - void Translator::EmitVectorInterpolation(const GcnInst& inst) { switch (inst.opcode) { + // VINTRP case Opcode::V_INTERP_P1_F32: return; case Opcode::V_INTERP_P2_F32: @@ -32,4 +19,18 @@ void Translator::EmitVectorInterpolation(const GcnInst& inst) { } } +// VINTRP + +void Translator::V_INTERP_P2_F32(const GcnInst& inst) { + auto& attr = runtime_info.fs_info.inputs.at(inst.control.vintrp.attr); + const IR::Attribute attrib{IR::Attribute::Param0 + attr.param_index}; + SetDst(inst.dst[0], ir.GetAttribute(attrib, inst.control.vintrp.chan)); +} + +void Translator::V_INTERP_MOV_F32(const GcnInst& inst) { + auto& attr = runtime_info.fs_info.inputs.at(inst.control.vintrp.attr); + const IR::Attribute attrib{IR::Attribute::Param0 + attr.param_index}; + SetDst(inst.dst[0], ir.GetAttribute(attrib, inst.control.vintrp.chan)); +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 08674fa2d..b7ad3b36b 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -7,285 +7,398 @@ namespace Shader::Gcn { void Translator::EmitVectorMemory(const GcnInst& inst) { switch (inst.opcode) { - case Opcode::IMAGE_SAMPLE_LZ_O: - case Opcode::IMAGE_SAMPLE_O: - case Opcode::IMAGE_SAMPLE_C: - case Opcode::IMAGE_SAMPLE_C_LZ: - case Opcode::IMAGE_SAMPLE_LZ: - case Opcode::IMAGE_SAMPLE: - case Opcode::IMAGE_SAMPLE_L: - case Opcode::IMAGE_SAMPLE_C_O: - case Opcode::IMAGE_SAMPLE_B: - case Opcode::IMAGE_SAMPLE_C_LZ_O: - return IMAGE_SAMPLE(inst); - case Opcode::IMAGE_GATHER4_C: - case Opcode::IMAGE_GATHER4_LZ: - case Opcode::IMAGE_GATHER4_LZ_O: - return IMAGE_GATHER(inst); + // MUBUF / MTBUF + + // Buffer load operations + case Opcode::TBUFFER_LOAD_FORMAT_X: + return BUFFER_LOAD(1, true, inst); + case Opcode::TBUFFER_LOAD_FORMAT_XY: + return BUFFER_LOAD(2, true, inst); + case Opcode::TBUFFER_LOAD_FORMAT_XYZ: + return BUFFER_LOAD(3, true, inst); + case Opcode::TBUFFER_LOAD_FORMAT_XYZW: + return BUFFER_LOAD(4, true, inst); + + case Opcode::BUFFER_LOAD_FORMAT_X: + return BUFFER_LOAD_FORMAT(1, inst); + case Opcode::BUFFER_LOAD_FORMAT_XY: + return BUFFER_LOAD_FORMAT(2, inst); + case Opcode::BUFFER_LOAD_FORMAT_XYZ: + return BUFFER_LOAD_FORMAT(3, inst); + case Opcode::BUFFER_LOAD_FORMAT_XYZW: + return BUFFER_LOAD_FORMAT(4, inst); + + case Opcode::BUFFER_LOAD_DWORD: + return BUFFER_LOAD(1, false, inst); + case Opcode::BUFFER_LOAD_DWORDX2: + return BUFFER_LOAD(2, false, inst); + case Opcode::BUFFER_LOAD_DWORDX3: + return BUFFER_LOAD(3, false, inst); + case Opcode::BUFFER_LOAD_DWORDX4: + return BUFFER_LOAD(4, false, inst); + + // Buffer store operations + case Opcode::BUFFER_STORE_FORMAT_X: + return BUFFER_STORE_FORMAT(1, inst); + case Opcode::BUFFER_STORE_FORMAT_XY: + return BUFFER_STORE_FORMAT(2, inst); + case Opcode::BUFFER_STORE_FORMAT_XYZ: + return BUFFER_STORE_FORMAT(3, inst); + case Opcode::BUFFER_STORE_FORMAT_XYZW: + return BUFFER_STORE_FORMAT(4, inst); + + case Opcode::TBUFFER_STORE_FORMAT_X: + return BUFFER_STORE(1, true, inst); + case Opcode::TBUFFER_STORE_FORMAT_XY: + return BUFFER_STORE(2, true, inst); + case Opcode::TBUFFER_STORE_FORMAT_XYZ: + return BUFFER_STORE(3, true, inst); + case Opcode::TBUFFER_STORE_FORMAT_XYZW: + return BUFFER_STORE(4, true, inst); + + case Opcode::BUFFER_STORE_DWORD: + return BUFFER_STORE(1, false, inst); + case Opcode::BUFFER_STORE_DWORDX2: + return BUFFER_STORE(2, false, inst); + case Opcode::BUFFER_STORE_DWORDX3: + return BUFFER_STORE(3, false, inst); + case Opcode::BUFFER_STORE_DWORDX4: + return BUFFER_STORE(4, false, inst); + + // Buffer atomic operations + case Opcode::BUFFER_ATOMIC_ADD: + return BUFFER_ATOMIC(AtomicOp::Add, inst); + case Opcode::BUFFER_ATOMIC_SWAP: + return BUFFER_ATOMIC(AtomicOp::Swap, inst); + case Opcode::BUFFER_ATOMIC_SMIN: + return BUFFER_ATOMIC(AtomicOp::Smin, inst); + case Opcode::BUFFER_ATOMIC_UMIN: + return BUFFER_ATOMIC(AtomicOp::Umin, inst); + case Opcode::BUFFER_ATOMIC_SMAX: + return BUFFER_ATOMIC(AtomicOp::Smax, inst); + case Opcode::BUFFER_ATOMIC_UMAX: + return BUFFER_ATOMIC(AtomicOp::Umax, inst); + case Opcode::BUFFER_ATOMIC_AND: + return BUFFER_ATOMIC(AtomicOp::And, inst); + case Opcode::BUFFER_ATOMIC_OR: + return BUFFER_ATOMIC(AtomicOp::Or, inst); + case Opcode::BUFFER_ATOMIC_XOR: + return BUFFER_ATOMIC(AtomicOp::Xor, inst); + case Opcode::BUFFER_ATOMIC_INC: + return BUFFER_ATOMIC(AtomicOp::Inc, inst); + case Opcode::BUFFER_ATOMIC_DEC: + return BUFFER_ATOMIC(AtomicOp::Dec, inst); + + // MIMG + // Image load operations + case Opcode::IMAGE_LOAD: + return IMAGE_LOAD(false, inst); + case Opcode::IMAGE_LOAD_MIP: + return IMAGE_LOAD(true, inst); + + // Buffer store operations + case Opcode::IMAGE_STORE: + return IMAGE_STORE(inst); + + // Image misc operations + case Opcode::IMAGE_GET_RESINFO: + return IMAGE_GET_RESINFO(inst); + + // Image atomic operations case Opcode::IMAGE_ATOMIC_ADD: return IMAGE_ATOMIC(AtomicOp::Add, inst); + case Opcode::IMAGE_ATOMIC_SMIN: + return IMAGE_ATOMIC(AtomicOp::Smin, inst); + case Opcode::IMAGE_ATOMIC_UMIN: + return IMAGE_ATOMIC(AtomicOp::Umin, inst); + case Opcode::IMAGE_ATOMIC_SMAX: + return IMAGE_ATOMIC(AtomicOp::Smax, inst); + case Opcode::IMAGE_ATOMIC_UMAX: + return IMAGE_ATOMIC(AtomicOp::Umax, inst); case Opcode::IMAGE_ATOMIC_AND: return IMAGE_ATOMIC(AtomicOp::And, inst); case Opcode::IMAGE_ATOMIC_OR: return IMAGE_ATOMIC(AtomicOp::Or, inst); case Opcode::IMAGE_ATOMIC_XOR: return IMAGE_ATOMIC(AtomicOp::Xor, inst); - case Opcode::IMAGE_ATOMIC_UMAX: - return IMAGE_ATOMIC(AtomicOp::Umax, inst); - case Opcode::IMAGE_ATOMIC_SMAX: - return IMAGE_ATOMIC(AtomicOp::Smax, inst); - case Opcode::IMAGE_ATOMIC_UMIN: - return IMAGE_ATOMIC(AtomicOp::Umin, inst); - case Opcode::IMAGE_ATOMIC_SMIN: - return IMAGE_ATOMIC(AtomicOp::Smin, inst); case Opcode::IMAGE_ATOMIC_INC: return IMAGE_ATOMIC(AtomicOp::Inc, inst); case Opcode::IMAGE_ATOMIC_DEC: return IMAGE_ATOMIC(AtomicOp::Dec, inst); + + case Opcode::IMAGE_SAMPLE: + case Opcode::IMAGE_SAMPLE_D: + case Opcode::IMAGE_SAMPLE_L: + case Opcode::IMAGE_SAMPLE_B: + case Opcode::IMAGE_SAMPLE_LZ: + case Opcode::IMAGE_SAMPLE_C: + case Opcode::IMAGE_SAMPLE_C_LZ: + case Opcode::IMAGE_SAMPLE_O: + case Opcode::IMAGE_SAMPLE_L_O: + case Opcode::IMAGE_SAMPLE_LZ_O: + case Opcode::IMAGE_SAMPLE_C_O: + case Opcode::IMAGE_SAMPLE_C_LZ_O: + case Opcode::IMAGE_SAMPLE_CD: + return IMAGE_SAMPLE(inst); + + // Image gather operations + case Opcode::IMAGE_GATHER4_LZ: + case Opcode::IMAGE_GATHER4_C: + case Opcode::IMAGE_GATHER4_C_O: + case Opcode::IMAGE_GATHER4_C_LZ: + case Opcode::IMAGE_GATHER4_LZ_O: + case Opcode::IMAGE_GATHER4_C_LZ_O: + return IMAGE_GATHER(inst); + + // Image misc operations case Opcode::IMAGE_GET_LOD: return IMAGE_GET_LOD(inst); - case Opcode::IMAGE_STORE: - return IMAGE_STORE(inst); - case Opcode::IMAGE_LOAD_MIP: - return IMAGE_LOAD(true, inst); - case Opcode::IMAGE_LOAD: - return IMAGE_LOAD(false, inst); - case Opcode::IMAGE_GET_RESINFO: - return IMAGE_GET_RESINFO(inst); - // Buffer load operations - case Opcode::TBUFFER_LOAD_FORMAT_X: - return BUFFER_LOAD_FORMAT(1, true, true, inst); - case Opcode::TBUFFER_LOAD_FORMAT_XY: - return BUFFER_LOAD_FORMAT(2, true, true, inst); - case Opcode::TBUFFER_LOAD_FORMAT_XYZ: - return BUFFER_LOAD_FORMAT(3, true, true, inst); - case Opcode::TBUFFER_LOAD_FORMAT_XYZW: - return BUFFER_LOAD_FORMAT(4, true, true, inst); - - case Opcode::BUFFER_LOAD_FORMAT_X: - return BUFFER_LOAD_FORMAT(1, false, true, inst); - case Opcode::BUFFER_LOAD_FORMAT_XY: - return BUFFER_LOAD_FORMAT(2, false, true, inst); - case Opcode::BUFFER_LOAD_FORMAT_XYZ: - return BUFFER_LOAD_FORMAT(3, false, true, inst); - case Opcode::BUFFER_LOAD_FORMAT_XYZW: - return BUFFER_LOAD_FORMAT(4, false, true, inst); - - case Opcode::BUFFER_LOAD_DWORD: - return BUFFER_LOAD_FORMAT(1, false, false, inst); - case Opcode::BUFFER_LOAD_DWORDX2: - return BUFFER_LOAD_FORMAT(2, false, false, inst); - case Opcode::BUFFER_LOAD_DWORDX3: - return BUFFER_LOAD_FORMAT(3, false, false, inst); - case Opcode::BUFFER_LOAD_DWORDX4: - return BUFFER_LOAD_FORMAT(4, false, false, inst); - - // Buffer store operations - case Opcode::BUFFER_STORE_FORMAT_X: - return BUFFER_STORE_FORMAT(1, false, true, inst); - case Opcode::BUFFER_STORE_FORMAT_XY: - return BUFFER_STORE_FORMAT(2, false, true, inst); - case Opcode::BUFFER_STORE_FORMAT_XYZ: - return BUFFER_STORE_FORMAT(3, false, true, inst); - case Opcode::BUFFER_STORE_FORMAT_XYZW: - return BUFFER_STORE_FORMAT(4, false, true, inst); - - case Opcode::TBUFFER_STORE_FORMAT_X: - return BUFFER_STORE_FORMAT(1, true, true, inst); - case Opcode::TBUFFER_STORE_FORMAT_XYZ: - return BUFFER_STORE_FORMAT(3, true, true, inst); - - case Opcode::BUFFER_STORE_DWORD: - return BUFFER_STORE_FORMAT(1, false, false, inst); - case Opcode::BUFFER_STORE_DWORDX2: - return BUFFER_STORE_FORMAT(2, false, false, inst); - case Opcode::BUFFER_STORE_DWORDX3: - return BUFFER_STORE_FORMAT(3, false, false, inst); - case Opcode::BUFFER_STORE_DWORDX4: - return BUFFER_STORE_FORMAT(4, false, false, inst); - - // Buffer atomic operations - case Opcode::BUFFER_ATOMIC_ADD: - return BUFFER_ATOMIC(AtomicOp::Add, inst); default: LogMissingOpcode(inst); } } -void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { - 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)); - - if (flags.test(ImageResComponent::Width)) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)}); - } - if (flags.test(ImageResComponent::Height)) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 1)}); - } - if (flags.test(ImageResComponent::Depth)) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 2)}); - } - if (has_mips) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 3)}); - } -} - -void Translator::IMAGE_SAMPLE(const GcnInst& inst) { - const auto& mimg = inst.control.mimg; - if (mimg.da) { - LOG_WARNING(Render_Vulkan, "Image instruction declares an array"); +void Translator::BUFFER_LOAD(u32 num_dwords, bool is_typed, const GcnInst& inst) { + const auto& mtbuf = inst.control.mtbuf; + const bool is_ring = mtbuf.glc && mtbuf.slc; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::ScalarReg sharp{inst.src[2].code * 4}; + const IR::Value soffset{GetSrc(inst.src[3])}; + if (info.stage != Stage::Geometry) { + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, + "Non immediate offset not supported"); } - IR::VectorReg addr_reg{inst.src[0].code}; - IR::VectorReg dest_reg{inst.dst[0].code}; - const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; - const IR::ScalarReg sampler_reg{inst.src[3].code * 4}; - const auto flags = MimgModifierFlags(mimg.mod); - - // Load first dword of T# and S#. We will use them as the handle that will guide resource - // tracking pass where to read the sharps. This will later also get patched to the SPIRV texture - // binding index. - const IR::Value handle = - ir.CompositeConstruct(ir.GetScalarReg(tsharp_reg), ir.GetScalarReg(sampler_reg)); - - // Load first address components as denoted in 8.2.4 VGPR Usage Sea Islands Series Instruction - // Set Architecture - const IR::U32 offset = - flags.test(MimgModifier::Offset) ? ir.GetVectorReg(addr_reg++) : IR::U32{}; - const IR::F32 bias = - flags.test(MimgModifier::LodBias) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; - const IR::F32 dref = - flags.test(MimgModifier::Pcf) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; - - // Derivatives are tricky because their number depends on the texture type which is located in - // T#. We don't have access to T# though until resource tracking pass. For now assume no - // derivatives are present, otherwise we don't know where coordinates are placed in the address - // stream. - ASSERT_MSG(!flags.test(MimgModifier::Derivative), "Derivative image instruction"); - - // Now we can load body components as noted in Table 8.9 Image Opcodes with Sampler - // Since these are at most 4 dwords, we load them into a single uvec4 and place them - // in coords field of the instruction. Then the resource tracking pass will patch the - // IR instruction to fill in lod_clamp field. - 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 bool explicit_lod = flags.any(MimgModifier::Level0, MimgModifier::Lod); - - IR::TextureInstInfo info{}; - info.is_depth.Assign(flags.test(MimgModifier::Pcf)); - info.has_bias.Assign(flags.test(MimgModifier::LodBias)); - info.has_lod_clamp.Assign(flags.test(MimgModifier::LodClamp)); - info.force_level0.Assign(flags.test(MimgModifier::Level0)); - info.has_offset.Assign(flags.test(MimgModifier::Offset)); - info.explicit_lod.Assign(explicit_lod); - - // Issue IR instruction, leaving unknown fields blank to patch later. - const IR::Value texel = [&]() -> IR::Value { - if (!flags.test(MimgModifier::Pcf)) { - if (explicit_lod) { - return ir.ImageSampleExplicitLod(handle, body, offset, info); - } else { - return ir.ImageSampleImplicitLod(handle, body, bias, offset, info); - } + const IR::Value address = [&] -> IR::Value { + if (is_ring) { + return ir.CompositeConstruct(ir.GetVectorReg(vaddr), soffset); } - if (explicit_lod) { - return ir.ImageSampleDrefExplicitLod(handle, body, dref, offset, info); + if (mtbuf.idxen && mtbuf.offen) { + return ir.CompositeConstruct(ir.GetVectorReg(vaddr), ir.GetVectorReg(vaddr + 1)); } - return ir.ImageSampleDrefImplicitLod(handle, body, dref, bias, offset, info); + if (mtbuf.idxen || mtbuf.offen) { + return ir.GetVectorReg(vaddr); + } + return {}; }(); - for (u32 i = 0; i < 4; i++) { - if (((mimg.dmask >> i) & 1) == 0) { - continue; - } - IR::F32 value; - if (flags.test(MimgModifier::Pcf)) { - value = i < 3 ? IR::F32{texel} : ir.Imm32(1.0f); - } else { - value = IR::F32{ir.CompositeExtract(texel, i)}; - } - ir.SetVectorReg(dest_reg++, value); + IR::BufferInstInfo buffer_info{}; + buffer_info.index_enable.Assign(mtbuf.idxen); + buffer_info.offset_enable.Assign(mtbuf.offen); + buffer_info.inst_offset.Assign(mtbuf.offset); + buffer_info.ring_access.Assign(is_ring); + if (is_typed) { + const auto dmft = static_cast(mtbuf.dfmt); + const auto nfmt = static_cast(mtbuf.nfmt); + ASSERT(nfmt == AmdGpu::NumberFormat::Float && + (dmft == AmdGpu::DataFormat::Format32_32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32)); + } + + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), + ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); + const IR::Value value = ir.LoadBuffer(num_dwords, handle, address, buffer_info); + const IR::VectorReg dst_reg{inst.src[1].code}; + if (num_dwords == 1) { + ir.SetVectorReg(dst_reg, IR::U32{value}); + return; + } + for (u32 i = 0; i < num_dwords; i++) { + ir.SetVectorReg(dst_reg + i, IR::U32{ir.CompositeExtract(value, i)}); } } -void Translator::IMAGE_GATHER(const GcnInst& inst) { - const auto& mimg = inst.control.mimg; - if (mimg.da) { - LOG_WARNING(Render_Vulkan, "Image instruction declares an array"); +void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, const GcnInst& inst) { + const auto& mubuf = inst.control.mubuf; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::ScalarReg sharp{inst.src[2].code * 4}; + ASSERT_MSG(!mubuf.offen && mubuf.offset == 0, "Offsets for image buffers are not supported"); + const IR::Value address = [&] -> IR::Value { + if (mubuf.idxen) { + return ir.GetVectorReg(vaddr); + } + return {}; + }(); + const IR::Value soffset{GetSrc(inst.src[3])}; + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); + + IR::BufferInstInfo info{}; + info.index_enable.Assign(mubuf.idxen); + + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), + ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); + const IR::Value value = ir.LoadBufferFormat(handle, address, info); + const IR::VectorReg dst_reg{inst.src[1].code}; + for (u32 i = 0; i < num_dwords; i++) { + ir.SetVectorReg(dst_reg + i, IR::F32{ir.CompositeExtract(value, i)}); + } +} + +void Translator::BUFFER_STORE(u32 num_dwords, bool is_typed, const GcnInst& inst) { + const auto& mtbuf = inst.control.mtbuf; + const bool is_ring = mtbuf.glc && mtbuf.slc; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::ScalarReg sharp{inst.src[2].code * 4}; + const IR::Value soffset{GetSrc(inst.src[3])}; + + if (info.stage != Stage::Export && info.stage != Stage::Geometry) { + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, + "Non immediate offset not supported"); } - IR::VectorReg addr_reg{inst.src[0].code}; - IR::VectorReg dest_reg{inst.dst[0].code}; - const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; - const IR::ScalarReg sampler_reg{inst.src[3].code * 4}; - const auto flags = MimgModifierFlags(mimg.mod); - - // Load first dword of T# and S#. We will use them as the handle that will guide resource - // tracking pass where to read the sharps. This will later also get patched to the SPIRV texture - // binding index. - const IR::Value handle = - ir.CompositeConstruct(ir.GetScalarReg(tsharp_reg), ir.GetScalarReg(sampler_reg)); - - // Load first address components as denoted in 8.2.4 VGPR Usage Sea Islands Series Instruction - // Set Architecture - const IR::Value offset = - flags.test(MimgModifier::Offset) ? ir.GetVectorReg(addr_reg++) : IR::Value{}; - const IR::F32 bias = - flags.test(MimgModifier::LodBias) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; - const IR::F32 dref = - flags.test(MimgModifier::Pcf) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; - - // Derivatives are tricky because their number depends on the texture type which is located in - // T#. We don't have access to T# though until resource tracking pass. For now assume no - // derivatives are present, otherwise we don't know where coordinates are placed in the address - // stream. - ASSERT_MSG(!flags.test(MimgModifier::Derivative), "Derivative image instruction"); - - // Now we can load body components as noted in Table 8.9 Image Opcodes with Sampler - // Since these are at most 4 dwords, we load them into a single uvec4 and place them - // in coords field of the instruction. Then the resource tracking pass will patch the - // IR instruction to fill in lod_clamp field. - 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 bool explicit_lod = flags.any(MimgModifier::Level0, MimgModifier::Lod); - - IR::TextureInstInfo info{}; - info.is_depth.Assign(flags.test(MimgModifier::Pcf)); - info.has_bias.Assign(flags.test(MimgModifier::LodBias)); - info.has_lod_clamp.Assign(flags.test(MimgModifier::LodClamp)); - info.force_level0.Assign(flags.test(MimgModifier::Level0)); - // info.explicit_lod.Assign(explicit_lod); - info.gather_comp.Assign(std::bit_width(mimg.dmask) - 1); - - // Issue IR instruction, leaving unknown fields blank to patch later. - const IR::Value texel = [&]() -> IR::Value { - const IR::F32 lod = flags.test(MimgModifier::Level0) ? ir.Imm32(0.f) : IR::F32{}; - if (!flags.test(MimgModifier::Pcf)) { - return ir.ImageGather(handle, body, offset, info); + IR::Value address = [&] -> IR::Value { + if (is_ring) { + return ir.CompositeConstruct(ir.GetVectorReg(vaddr), soffset); } - ASSERT(mimg.dmask & 1); // should be always 1st (R) component - return ir.ImageGatherDref(handle, body, offset, dref, info); + if (mtbuf.idxen && mtbuf.offen) { + return ir.CompositeConstruct(ir.GetVectorReg(vaddr), ir.GetVectorReg(vaddr + 1)); + } + if (mtbuf.idxen || mtbuf.offen) { + return ir.GetVectorReg(vaddr); + } + return {}; }(); - // For gather4 instructions dmask selects which component to read and must have - // only one bit set to 1 - ASSERT_MSG(std::popcount(mimg.dmask) == 1, "Unexpected bits in gather dmask"); - for (u32 i = 0; i < 4; i++) { - const IR::F32 value = IR::F32{ir.CompositeExtract(texel, i)}; - ir.SetVectorReg(dest_reg++, value); + IR::BufferInstInfo buffer_info{}; + buffer_info.index_enable.Assign(mtbuf.idxen); + buffer_info.offset_enable.Assign(mtbuf.offen); + buffer_info.inst_offset.Assign(mtbuf.offset); + buffer_info.ring_access.Assign(is_ring); + if (is_typed) { + const auto dmft = static_cast(mtbuf.dfmt); + const auto nfmt = static_cast(mtbuf.nfmt); + ASSERT(nfmt == AmdGpu::NumberFormat::Float && + (dmft == AmdGpu::DataFormat::Format32_32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32_32 || + dmft == AmdGpu::DataFormat::Format32_32 || dmft == AmdGpu::DataFormat::Format32)); + } + + IR::Value value{}; + const IR::VectorReg src_reg{inst.src[1].code}; + switch (num_dwords) { + case 1: + value = ir.GetVectorReg(src_reg); + break; + case 2: + value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), ir.GetVectorReg(src_reg + 1)); + break; + case 3: + value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), ir.GetVectorReg(src_reg + 1), + ir.GetVectorReg(src_reg + 2)); + break; + case 4: + value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), ir.GetVectorReg(src_reg + 1), + ir.GetVectorReg(src_reg + 2), ir.GetVectorReg(src_reg + 3)); + break; + } + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), + ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); + ir.StoreBuffer(num_dwords, handle, address, value, buffer_info); +} + +void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, const GcnInst& inst) { + const auto& mubuf = inst.control.mubuf; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::ScalarReg sharp{inst.src[2].code * 4}; + ASSERT_MSG(!mubuf.offen && mubuf.offset == 0, "Offsets for image buffers are not supported"); + const IR::Value address = [&] -> IR::Value { + if (mubuf.idxen) { + return ir.GetVectorReg(vaddr); + } + return {}; + }(); + const IR::Value soffset{GetSrc(inst.src[3])}; + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); + + IR::BufferInstInfo info{}; + info.index_enable.Assign(mubuf.idxen); + + const IR::VectorReg src_reg{inst.src[1].code}; + + std::array comps{}; + for (u32 i = 0; i < num_dwords; i++) { + comps[i] = ir.GetVectorReg(src_reg + i); + } + for (u32 i = num_dwords; i < 4; i++) { + comps[i] = ir.Imm32(0.f); + } + + const IR::Value value = ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]); + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), + ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); + ir.StoreBufferFormat(handle, address, value, info); +} + +void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) { + const auto& mubuf = inst.control.mubuf; + const IR::VectorReg vaddr{inst.src[0].code}; + const IR::VectorReg vdata{inst.src[1].code}; + const IR::ScalarReg srsrc{inst.src[2].code * 4}; + const IR::Value address = [&] -> IR::Value { + if (mubuf.idxen && mubuf.offen) { + return ir.CompositeConstruct(ir.GetVectorReg(vaddr), ir.GetVectorReg(vaddr + 1)); + } + if (mubuf.idxen || mubuf.offen) { + return ir.GetVectorReg(vaddr); + } + return {}; + }(); + const IR::U32 soffset{GetSrc(inst.src[3])}; + ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); + + IR::BufferInstInfo info{}; + info.index_enable.Assign(mubuf.idxen); + info.inst_offset.Assign(mubuf.offset); + info.offset_enable.Assign(mubuf.offen); + + IR::Value vdata_val = ir.GetVectorReg(vdata); + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(srsrc), ir.GetScalarReg(srsrc + 1), + ir.GetScalarReg(srsrc + 2), ir.GetScalarReg(srsrc + 3)); + + const IR::Value original_val = [&] { + switch (op) { + case AtomicOp::Swap: + return ir.BufferAtomicSwap(handle, address, vdata_val, info); + case AtomicOp::Add: + return ir.BufferAtomicIAdd(handle, address, vdata_val, info); + case AtomicOp::Smin: + return ir.BufferAtomicIMin(handle, address, vdata_val, true, info); + case AtomicOp::Umin: + return ir.BufferAtomicIMin(handle, address, vdata_val, false, info); + case AtomicOp::Smax: + return ir.BufferAtomicIMax(handle, address, vdata_val, true, info); + case AtomicOp::Umax: + return ir.BufferAtomicIMax(handle, address, vdata_val, false, info); + case AtomicOp::And: + return ir.BufferAtomicAnd(handle, address, vdata_val, info); + case AtomicOp::Or: + return ir.BufferAtomicOr(handle, address, vdata_val, info); + case AtomicOp::Xor: + return ir.BufferAtomicXor(handle, address, vdata_val, info); + case AtomicOp::Inc: + return ir.BufferAtomicInc(handle, address, vdata_val, info); + case AtomicOp::Dec: + return ir.BufferAtomicDec(handle, address, vdata_val, info); + default: + UNREACHABLE(); + } + }(); + + if (mubuf.glc) { + ir.SetVectorReg(vdata, IR::U32{original_val}); } } +// Image Memory +// MIMG + void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) { const auto& mimg = inst.control.mimg; IR::VectorReg addr_reg{inst.src[0].code}; @@ -298,7 +411,7 @@ void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) { ir.GetVectorReg(addr_reg + 2), ir.GetVectorReg(addr_reg + 3)); IR::TextureInstInfo info{}; - info.explicit_lod.Assign(has_mip); + info.has_lod.Assign(has_mip); const IR::Value texel = ir.ImageFetch(handle, body, {}, {}, {}, info); for (u32 i = 0; i < 4; i++) { @@ -333,179 +446,27 @@ void Translator::IMAGE_STORE(const GcnInst& inst) { ir.ImageWrite(handle, body, value, {}); } -void Translator::BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, bool is_format, - const GcnInst& inst) { - const auto& mtbuf = inst.control.mtbuf; - const IR::VectorReg vaddr{inst.src[0].code}; - const IR::ScalarReg sharp{inst.src[2].code * 4}; - const IR::Value address = [&] -> IR::Value { - if (mtbuf.idxen && mtbuf.offen) { - return ir.CompositeConstruct(ir.GetVectorReg(vaddr), ir.GetVectorReg(vaddr + 1)); - } - if (mtbuf.idxen || mtbuf.offen) { - return ir.GetVectorReg(vaddr); - } - return {}; - }(); - const IR::Value soffset{GetSrc(inst.src[3])}; - ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); - - IR::BufferInstInfo info{}; - info.index_enable.Assign(mtbuf.idxen); - info.offset_enable.Assign(mtbuf.offen); - info.inst_offset.Assign(mtbuf.offset); - info.is_typed.Assign(is_typed); - if (is_typed) { - info.dmft.Assign(static_cast(mtbuf.dfmt)); - info.nfmt.Assign(static_cast(mtbuf.nfmt)); - ASSERT(info.nfmt == AmdGpu::NumberFormat::Float && - (info.dmft == AmdGpu::DataFormat::Format32_32_32_32 || - info.dmft == AmdGpu::DataFormat::Format32_32_32 || - info.dmft == AmdGpu::DataFormat::Format32_32 || - info.dmft == AmdGpu::DataFormat::Format32)); - } - - const IR::Value handle = - ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), - ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); - const IR::Value value = is_format ? ir.LoadBufferFormat(num_dwords, handle, address, info) - : ir.LoadBuffer(num_dwords, handle, address, info); - const IR::VectorReg dst_reg{inst.src[1].code}; - if (num_dwords == 1) { - ir.SetVectorReg(dst_reg, IR::F32{value}); - return; - } - for (u32 i = 0; i < num_dwords; i++) { - ir.SetVectorReg(dst_reg + i, IR::F32{ir.CompositeExtract(value, i)}); - } -} - -void Translator::BUFFER_STORE_FORMAT(u32 num_dwords, bool is_typed, bool is_format, - const GcnInst& inst) { - const auto& mtbuf = inst.control.mtbuf; - const IR::VectorReg vaddr{inst.src[0].code}; - const IR::ScalarReg sharp{inst.src[2].code * 4}; - const IR::Value address = [&] -> IR::Value { - if (mtbuf.idxen && mtbuf.offen) { - return ir.CompositeConstruct(ir.GetVectorReg(vaddr), ir.GetVectorReg(vaddr + 1)); - } - if (mtbuf.idxen || mtbuf.offen) { - return ir.GetVectorReg(vaddr); - } - return {}; - }(); - const IR::Value soffset{GetSrc(inst.src[3])}; - ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); - - IR::BufferInstInfo info{}; - info.index_enable.Assign(mtbuf.idxen); - info.offset_enable.Assign(mtbuf.offen); - info.inst_offset.Assign(mtbuf.offset); - info.is_typed.Assign(is_typed); - if (is_typed) { - info.dmft.Assign(static_cast(mtbuf.dfmt)); - info.nfmt.Assign(static_cast(mtbuf.nfmt)); - } - - IR::Value value{}; - const IR::VectorReg src_reg{inst.src[1].code}; - switch (num_dwords) { - case 1: - value = ir.GetVectorReg(src_reg); - break; - case 2: - value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), - ir.GetVectorReg(src_reg + 1)); - break; - case 3: - value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), - ir.GetVectorReg(src_reg + 1), - ir.GetVectorReg(src_reg + 2)); - break; - case 4: - value = ir.CompositeConstruct(ir.GetVectorReg(src_reg), - ir.GetVectorReg(src_reg + 1), - ir.GetVectorReg(src_reg + 2), - ir.GetVectorReg(src_reg + 3)); - break; - } - const IR::Value handle = - ir.CompositeConstruct(ir.GetScalarReg(sharp), ir.GetScalarReg(sharp + 1), - ir.GetScalarReg(sharp + 2), ir.GetScalarReg(sharp + 3)); - if (is_format) { - ir.StoreBufferFormat(num_dwords, handle, address, value, info); - } else { - ir.StoreBuffer(num_dwords, handle, address, value, info); - } -} - -// TODO: U64 -void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) { - const auto& mubuf = inst.control.mubuf; - const IR::VectorReg vaddr{inst.src[0].code}; - const IR::VectorReg vdata{inst.src[1].code}; - const IR::ScalarReg srsrc{inst.src[2].code * 4}; - const IR::U32 soffset{GetSrc(inst.src[3])}; - ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0, "Non immediate offset not supported"); - - IR::BufferInstInfo info{}; - info.index_enable.Assign(mubuf.idxen); - info.inst_offset.Assign(mubuf.offset); - info.offset_enable.Assign(mubuf.offen); - - IR::Value vdata_val = ir.GetVectorReg(vdata); - const IR::U32 address = ir.GetVectorReg(vaddr); - const IR::Value handle = - ir.CompositeConstruct(ir.GetScalarReg(srsrc), ir.GetScalarReg(srsrc + 1), - ir.GetScalarReg(srsrc + 2), ir.GetScalarReg(srsrc + 3)); - - const IR::Value original_val = [&] { - switch (op) { - case AtomicOp::Swap: - return ir.BufferAtomicExchange(handle, address, vdata_val, info); - case AtomicOp::Add: - return ir.BufferAtomicIAdd(handle, address, vdata_val, info); - case AtomicOp::Smin: - return ir.BufferAtomicIMin(handle, address, vdata_val, true, info); - case AtomicOp::Umin: - return ir.BufferAtomicIMin(handle, address, vdata_val, false, info); - case AtomicOp::Smax: - return ir.BufferAtomicIMax(handle, address, vdata_val, true, info); - case AtomicOp::Umax: - return ir.BufferAtomicIMax(handle, address, vdata_val, false, info); - case AtomicOp::And: - return ir.BufferAtomicAnd(handle, address, vdata_val, info); - case AtomicOp::Or: - return ir.BufferAtomicOr(handle, address, vdata_val, info); - case AtomicOp::Xor: - return ir.BufferAtomicXor(handle, address, vdata_val, info); - case AtomicOp::Inc: - return ir.BufferAtomicInc(handle, address, vdata_val, info); - case AtomicOp::Dec: - return ir.BufferAtomicDec(handle, address, vdata_val, info); - default: - UNREACHABLE(); - } - }(); - - if (mubuf.glc) { - ir.SetVectorReg(vdata, IR::U32{original_val}); - } -} - -void Translator::IMAGE_GET_LOD(const GcnInst& inst) { - const auto& mimg = inst.control.mimg; +void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { IR::VectorReg dst_reg{inst.dst[0].code}; - IR::VectorReg addr_reg{inst.src[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)); - 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, {}); - ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 0)}); - ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)}); + if (flags.test(ImageResComponent::Width)) { + ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)}); + } + if (flags.test(ImageResComponent::Height)) { + ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 1)}); + } + if (flags.test(ImageResComponent::Depth)) { + ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 2)}); + } + if (has_mips) { + ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 3)}); + } } void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) { @@ -552,4 +513,133 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) { } } +IR::Value EmitImageSample(IR::IREmitter& ir, const GcnInst& inst, const IR::ScalarReg tsharp_reg, + const IR::ScalarReg sampler_reg, const IR::VectorReg addr_reg, + bool gather) { + const auto& mimg = inst.control.mimg; + const auto flags = MimgModifierFlags(mimg.mod); + + IR::TextureInstInfo info{}; + info.is_depth.Assign(flags.test(MimgModifier::Pcf)); + info.has_bias.Assign(flags.test(MimgModifier::LodBias)); + info.has_lod_clamp.Assign(flags.test(MimgModifier::LodClamp)); + info.force_level0.Assign(flags.test(MimgModifier::Level0)); + info.has_offset.Assign(flags.test(MimgModifier::Offset)); + info.has_lod.Assign(flags.any(MimgModifier::Lod)); + info.is_array.Assign(mimg.da); + + if (gather) { + info.gather_comp.Assign(std::bit_width(mimg.dmask) - 1); + info.is_gather.Assign(true); + } else { + info.has_derivatives.Assign(flags.test(MimgModifier::Derivative)); + } + + // Load first dword of T# and S#. We will use them as the handle that will guide resource + // tracking pass where to read the sharps. This will later also get patched to the SPIRV texture + // binding index. + const IR::Value handle = + ir.CompositeConstruct(ir.GetScalarReg(tsharp_reg), ir.GetScalarReg(sampler_reg)); + + // Determine how many address registers need to be passed. + // The image type is unknown, so add all 4 possible base registers and resolve later. + int num_addr_regs = 4; + if (info.has_offset) { + ++num_addr_regs; + } + if (info.has_bias) { + ++num_addr_regs; + } + if (info.is_depth) { + ++num_addr_regs; + } + if (info.has_derivatives) { + // The image type is unknown, so add all 6 possible derivative registers and resolve later. + num_addr_regs += 6; + } + + // Fetch all the address registers to pass in the IR instruction. There can be up to 13 + // registers. + const auto get_addr_reg = [&](int index) -> IR::F32 { + if (index >= num_addr_regs) { + return ir.Imm32(0.f); + } + return ir.GetVectorReg(addr_reg + index); + }; + const IR::Value address1 = + ir.CompositeConstruct(get_addr_reg(0), get_addr_reg(1), get_addr_reg(2), get_addr_reg(3)); + const IR::Value address2 = + ir.CompositeConstruct(get_addr_reg(4), get_addr_reg(5), get_addr_reg(6), get_addr_reg(7)); + const IR::Value address3 = + ir.CompositeConstruct(get_addr_reg(8), get_addr_reg(9), get_addr_reg(10), get_addr_reg(11)); + const IR::Value address4 = get_addr_reg(12); + + // Issue the placeholder IR instruction. + IR::Value texel = ir.ImageSampleRaw(handle, address1, address2, address3, address4, info); + if (info.is_depth && !gather) { + // For non-gather depth sampling, only return a single value. + texel = ir.CompositeExtract(texel, 0); + } + return texel; +} + +void Translator::IMAGE_SAMPLE(const GcnInst& inst) { + const auto& mimg = inst.control.mimg; + IR::VectorReg addr_reg{inst.src[0].code}; + IR::VectorReg dest_reg{inst.dst[0].code}; + const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; + const IR::ScalarReg sampler_reg{inst.src[3].code * 4}; + const auto flags = MimgModifierFlags(mimg.mod); + + const IR::Value texel = EmitImageSample(ir, inst, tsharp_reg, sampler_reg, addr_reg, false); + for (u32 i = 0; i < 4; i++) { + if (((mimg.dmask >> i) & 1) == 0) { + continue; + } + IR::F32 value; + if (flags.test(MimgModifier::Pcf)) { + value = i < 3 ? IR::F32{texel} : ir.Imm32(1.0f); + } else { + value = IR::F32{ir.CompositeExtract(texel, i)}; + } + ir.SetVectorReg(dest_reg++, value); + } +} + +void Translator::IMAGE_GATHER(const GcnInst& inst) { + const auto& mimg = inst.control.mimg; + IR::VectorReg addr_reg{inst.src[0].code}; + IR::VectorReg dest_reg{inst.dst[0].code}; + const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; + const IR::ScalarReg sampler_reg{inst.src[3].code * 4}; + const auto flags = MimgModifierFlags(mimg.mod); + + // For gather4 instructions dmask selects which component to read and must have + // only one bit set to 1 + ASSERT_MSG(std::popcount(mimg.dmask) == 1, "Unexpected bits in gather dmask"); + // should be always 1st (R) component for depth + ASSERT(!flags.test(MimgModifier::Pcf) || mimg.dmask & 1); + + const IR::Value texel = EmitImageSample(ir, inst, tsharp_reg, sampler_reg, addr_reg, true); + for (u32 i = 0; i < 4; i++) { + const IR::F32 value = IR::F32{ir.CompositeExtract(texel, i)}; + ir.SetVectorReg(dest_reg++, value); + } +} + +void Translator::IMAGE_GET_LOD(const GcnInst& inst) { + const auto& mimg = inst.control.mimg; + IR::VectorReg dst_reg{inst.dst[0].code}; + IR::VectorReg addr_reg{inst.src[0].code}; + const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; + + 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, {}); + ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 0)}); + ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)}); +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h new file mode 100644 index 000000000..e727c8a08 --- /dev/null +++ b/src/shader_recompiler/info.h @@ -0,0 +1,277 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include +#include +#include +#include "common/assert.h" +#include "common/types.h" +#include "shader_recompiler/backend/bindings.h" +#include "shader_recompiler/frontend/copy_shader.h" +#include "shader_recompiler/ir/attribute.h" +#include "shader_recompiler/ir/reg.h" +#include "shader_recompiler/ir/type.h" +#include "shader_recompiler/params.h" +#include "shader_recompiler/runtime_info.h" +#include "video_core/amdgpu/resource.h" + +namespace Shader { + +static constexpr size_t NumUserDataRegs = 16; +static constexpr size_t MaxUboSize = 65536; +static constexpr size_t MaxUboDwords = MaxUboSize >> 2; + +enum class TextureType : u32 { + Color1D, + ColorArray1D, + Color2D, + ColorArray2D, + Color3D, + ColorCube, + Buffer, +}; +constexpr u32 NUM_TEXTURE_TYPES = 7; + +struct Info; + +struct BufferResource { + u32 sgpr_base; + u32 dword_offset; + IR::Type used_types; + AmdGpu::Buffer inline_cbuf; + bool is_gds_buffer{}; + bool is_instance_data{}; + bool is_written{}; + + bool IsStorage(AmdGpu::Buffer buffer) const noexcept { + return buffer.GetSize() > MaxUboSize || is_written || is_gds_buffer; + } + + constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; +}; +using BufferResourceList = boost::container::small_vector; + +struct TextureBufferResource { + u32 sgpr_base; + u32 dword_offset; + AmdGpu::NumberFormat nfmt; + bool is_written{}; + + constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; +}; +using TextureBufferResourceList = boost::container::small_vector; + +struct ImageResource { + u32 sgpr_base; + u32 dword_offset; + AmdGpu::ImageType type; + AmdGpu::NumberFormat nfmt; + bool is_storage{}; + bool is_depth{}; + bool is_atomic{}; + bool is_array{}; + + constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; +}; +using ImageResourceList = boost::container::small_vector; + +struct SamplerResource { + u32 sgpr_base; + u32 dword_offset; + AmdGpu::Sampler inline_sampler{}; + u32 associated_image : 4; + u32 disable_aniso : 1; + + constexpr AmdGpu::Sampler GetSharp(const Info& info) const noexcept; +}; +using SamplerResourceList = boost::container::small_vector; + +struct PushData { + static constexpr u32 BufOffsetIndex = 2; + static constexpr u32 UdRegsIndex = 4; + + u32 step0; + u32 step1; + std::array buf_offsets; + std::array ud_regs; + + void AddOffset(u32 binding, u32 offset) { + ASSERT(offset < 256 && binding < buf_offsets.size()); + buf_offsets[binding] = offset; + } +}; +static_assert(sizeof(PushData) <= 128, + "PushData size is greater than minimum size guaranteed by Vulkan spec"); + +/** + * Contains general information generated by the shader recompiler for an input program. + */ +struct Info { + struct VsInput { + enum InstanceIdType : u8 { + None = 0, + OverStepRate0 = 1, + OverStepRate1 = 2, + Plain = 3, + }; + + AmdGpu::NumberFormat fmt; + u16 binding; + u16 num_components; + u8 sgpr_base; + u8 dword_offset; + InstanceIdType instance_step_rate; + s32 instance_data_buf; + }; + boost::container::static_vector vs_inputs{}; + + struct AttributeFlags { + bool Get(IR::Attribute attrib, u32 comp = 0) const { + return flags[Index(attrib)] & (1 << comp); + } + + bool GetAny(IR::Attribute attrib) const { + return flags[Index(attrib)]; + } + + void Set(IR::Attribute attrib, u32 comp = 0) { + flags[Index(attrib)] |= (1 << comp); + } + + u32 NumComponents(IR::Attribute attrib) const { + return 4; + } + + static size_t Index(IR::Attribute attrib) { + return static_cast(attrib); + } + + std::array flags; + }; + AttributeFlags loads{}; + AttributeFlags stores{}; + + struct UserDataMask { + void Set(IR::ScalarReg reg) noexcept { + mask |= 1 << static_cast(reg); + } + + u32 Index(IR::ScalarReg reg) const noexcept { + const u32 reg_mask = (1 << static_cast(reg)) - 1; + return std::popcount(mask & reg_mask); + } + + u32 NumRegs() const noexcept { + return std::popcount(mask); + } + + u32 mask; + }; + UserDataMask ud_mask{}; + + CopyShaderData gs_copy_data; + + s8 vertex_offset_sgpr = -1; + s8 instance_offset_sgpr = -1; + + BufferResourceList buffers; + TextureBufferResourceList texture_buffers; + ImageResourceList images; + SamplerResourceList samplers; + + std::span user_data; + Stage stage; + + u64 pgm_hash{}; + VAddr pgm_base; + bool has_storage_images{}; + bool has_image_buffers{}; + bool has_texel_buffers{}; + bool has_discard{}; + bool has_image_gather{}; + bool has_image_query{}; + bool uses_lane_id{}; + bool uses_group_quad{}; + bool uses_group_ballot{}; + bool uses_shared{}; + bool uses_fp16{}; + bool uses_fp64{}; + bool uses_step_rates{}; + bool translation_failed{}; // indicates that shader has unsupported instructions + u8 mrt_mask{0u}; + + explicit Info(Stage stage_, ShaderParams params) + : stage{stage_}, pgm_hash{params.hash}, pgm_base{params.Base()}, + user_data{params.user_data} {} + + template + T ReadUd(u32 ptr_index, u32 dword_offset) const noexcept { + T data; + const u32* base = user_data.data(); + if (ptr_index != IR::NumScalarRegs) { + std::memcpy(&base, &user_data[ptr_index], sizeof(base)); + base = reinterpret_cast(VAddr(base) & 0xFFFFFFFFFFFFULL); + } + std::memcpy(&data, base + dword_offset, sizeof(T)); + return data; + } + + void PushUd(Backend::Bindings& bnd, PushData& push) const { + u32 mask = ud_mask.mask; + while (mask) { + const u32 index = std::countr_zero(mask); + ASSERT(bnd.user_data < NumUserDataRegs && index < NumUserDataRegs); + mask &= ~(1U << index); + push.ud_regs[bnd.user_data++] = user_data[index]; + } + } + + void AddBindings(Backend::Bindings& bnd) const { + const auto total_buffers = buffers.size() + texture_buffers.size(); + bnd.buffer += total_buffers; + bnd.unified += total_buffers + images.size() + samplers.size(); + bnd.user_data += ud_mask.NumRegs(); + } + + [[nodiscard]] std::pair GetDrawOffsets() const { + u32 vertex_offset = 0; + u32 instance_offset = 0; + if (vertex_offset_sgpr != -1) { + vertex_offset = user_data[vertex_offset_sgpr]; + } + if (instance_offset_sgpr != -1) { + instance_offset = user_data[instance_offset_sgpr]; + } + return {vertex_offset, instance_offset}; + } +}; + +constexpr AmdGpu::Buffer BufferResource::GetSharp(const Info& info) const noexcept { + return inline_cbuf ? inline_cbuf : info.ReadUd(sgpr_base, dword_offset); +} + +constexpr AmdGpu::Buffer TextureBufferResource::GetSharp(const Info& info) const noexcept { + return info.ReadUd(sgpr_base, dword_offset); +} + +constexpr AmdGpu::Image ImageResource::GetSharp(const Info& info) const noexcept { + return info.ReadUd(sgpr_base, dword_offset); +} + +constexpr AmdGpu::Sampler SamplerResource::GetSharp(const Info& info) const noexcept { + return inline_sampler ? inline_sampler : info.ReadUd(sgpr_base, dword_offset); +} + +} // namespace Shader + +template <> +struct fmt::formatter { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + auto format(const Shader::Stage stage, format_context& ctx) const { + constexpr static std::array names = {"fs", "vs", "gs", "es", "hs", "ls", "cs"}; + return fmt::format_to(ctx.out(), "{}", names[static_cast(stage)]); + } +}; diff --git a/src/shader_recompiler/ir/attribute.cpp b/src/shader_recompiler/ir/attribute.cpp index 540cb8afb..e219dfb64 100644 --- a/src/shader_recompiler/ir/attribute.cpp +++ b/src/shader_recompiler/ir/attribute.cpp @@ -6,14 +6,6 @@ namespace Shader::IR { -bool IsParam(Attribute attribute) noexcept { - return attribute >= Attribute::Param0 && attribute <= Attribute::Param31; -} - -bool IsMrt(Attribute attribute) noexcept { - return attribute >= Attribute::RenderTarget0 && attribute <= Attribute::RenderTarget7; -} - std::string NameOf(Attribute attribute) { switch (attribute) { case Attribute::RenderTarget0: diff --git a/src/shader_recompiler/ir/attribute.h b/src/shader_recompiler/ir/attribute.h index 2c67411ff..0890e88f1 100644 --- a/src/shader_recompiler/ir/attribute.h +++ b/src/shader_recompiler/ir/attribute.h @@ -81,9 +81,17 @@ constexpr size_t NumAttributes = static_cast(Attribute::Max); constexpr size_t NumRenderTargets = 8; constexpr size_t NumParams = 32; -[[nodiscard]] bool IsParam(Attribute attribute) noexcept; +constexpr bool IsPosition(Attribute attribute) noexcept { + return attribute >= Attribute::Position0 && attribute <= Attribute::Position3; +} -[[nodiscard]] bool IsMrt(Attribute attribute) noexcept; +constexpr bool IsParam(Attribute attribute) noexcept { + return attribute >= Attribute::Param0 && attribute <= Attribute::Param31; +} + +constexpr bool IsMrt(Attribute attribute) noexcept { + return attribute >= Attribute::RenderTarget0 && attribute <= Attribute::RenderTarget7; +} [[nodiscard]] std::string NameOf(Attribute attribute); diff --git a/src/shader_recompiler/ir/basic_block.h b/src/shader_recompiler/ir/basic_block.h index e9d157aaf..74a7d2c56 100644 --- a/src/shader_recompiler/ir/basic_block.h +++ b/src/shader_recompiler/ir/basic_block.h @@ -147,6 +147,7 @@ public: /// Intrusively store the value of a register in the block. std::array ssa_sreg_values; + std::array ssa_sbit_values; std::array ssa_vreg_values; bool has_multiple_predecessors{false}; diff --git a/src/shader_recompiler/ir/debug_print.h b/src/shader_recompiler/ir/debug_print.h new file mode 100644 index 000000000..1ab1575de --- /dev/null +++ b/src/shader_recompiler/ir/debug_print.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/bit_field.h" +#include "shader_recompiler/ir/opcodes.h" +#include "src/common/types.h" + +#pragma once + +namespace Shader::IR { + +constexpr size_t DEBUGPRINT_NUM_FORMAT_ARGS = NumArgsOf(IR::Opcode::DebugPrint) - 1; + +union DebugPrintFlags { + u32 raw; + // For now, only flag is the number of variadic format args actually used + // So bitfield not really needed + BitField<0, 32, u32> num_args; +}; + +} // namespace Shader::IR \ No newline at end of file diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 3ae068072..cfd044f9e 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1,10 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include +#include +#include "common/assert.h" #include "shader_recompiler/exception.h" +#include "shader_recompiler/ir/debug_print.h" #include "shader_recompiler/ir/ir_emitter.h" +#include "shader_recompiler/ir/opcodes.h" #include "shader_recompiler/ir/value.h" namespace Shader::IR { @@ -125,19 +130,23 @@ void IREmitter::DeviceMemoryBarrier() { } U32 IREmitter::GetUserData(IR::ScalarReg reg) { + ASSERT(static_cast(reg) < IR::NumScalarRegs); return Inst(Opcode::GetUserData, reg); } U1 IREmitter::GetThreadBitScalarReg(IR::ScalarReg reg) { + ASSERT(static_cast(reg) < IR::NumScalarRegs); return Inst(Opcode::GetThreadBitScalarReg, reg); } void IREmitter::SetThreadBitScalarReg(IR::ScalarReg reg, const U1& value) { + ASSERT(static_cast(reg) < IR::NumScalarRegs); Inst(Opcode::SetThreadBitScalarReg, reg, value); } template <> U32 IREmitter::GetScalarReg(IR::ScalarReg reg) { + ASSERT(static_cast(reg) < IR::NumScalarRegs); return Inst(Opcode::GetScalarRegister, reg); } @@ -148,6 +157,7 @@ F32 IREmitter::GetScalarReg(IR::ScalarReg reg) { template <> U32 IREmitter::GetVectorReg(IR::VectorReg reg) { + ASSERT(static_cast(reg) < IR::NumVectorRegs); return Inst(Opcode::GetVectorRegister, reg); } @@ -157,11 +167,13 @@ F32 IREmitter::GetVectorReg(IR::VectorReg reg) { } void IREmitter::SetScalarReg(IR::ScalarReg reg, const U32F32& value) { + ASSERT(static_cast(reg) < IR::NumScalarRegs); const U32 value_typed = value.Type() == Type::F32 ? BitCast(F32{value}) : U32{value}; Inst(Opcode::SetScalarRegister, reg, value_typed); } void IREmitter::SetVectorReg(IR::VectorReg reg, const U32F32& value) { + ASSERT(static_cast(reg) < IR::NumVectorRegs); const U32 value_typed = value.Type() == Type::F32 ? BitCast(F32{value}) : U32{value}; Inst(Opcode::SetVectorRegister, reg, value_typed); } @@ -209,10 +221,6 @@ U1 IREmitter::GetVcc() { return Inst(Opcode::GetVcc); } -U32 IREmitter::GetSccLo() { - return Inst(Opcode::GetSccLo); -} - U32 IREmitter::GetVccLo() { return Inst(Opcode::GetVccLo); } @@ -221,6 +229,10 @@ U32 IREmitter::GetVccHi() { return Inst(Opcode::GetVccHi); } +U32 IREmitter::GetM0() { + return Inst(Opcode::GetM0); +} + void IREmitter::SetScc(const U1& value) { Inst(Opcode::SetScc, value); } @@ -245,8 +257,12 @@ void IREmitter::SetVccHi(const U32& value) { Inst(Opcode::SetVccHi, value); } -F32 IREmitter::GetAttribute(IR::Attribute attribute, u32 comp) { - return Inst(Opcode::GetAttribute, attribute, Imm32(comp)); +void IREmitter::SetM0(const U32& value) { + Inst(Opcode::SetM0, value); +} + +F32 IREmitter::GetAttribute(IR::Attribute attribute, u32 comp, u32 index) { + return Inst(Opcode::GetAttribute, attribute, Imm32(comp), Imm32(index)); } U32 IREmitter::GetAttributeU32(IR::Attribute attribute, u32 comp) { @@ -309,57 +325,44 @@ U32 IREmitter::ReadConst(const Value& base, const U32& offset) { return Inst(Opcode::ReadConst, base, offset); } -F32 IREmitter::ReadConstBuffer(const Value& handle, const U32& index) { - return Inst(Opcode::ReadConstBuffer, handle, index); +U32 IREmitter::ReadConstBuffer(const Value& handle, const U32& index) { + return Inst(Opcode::ReadConstBuffer, handle, index); } Value IREmitter::LoadBuffer(int num_dwords, const Value& handle, const Value& address, BufferInstInfo info) { switch (num_dwords) { case 1: - return Inst(Opcode::LoadBufferF32, Flags{info}, handle, address); + return Inst(Opcode::LoadBufferU32, Flags{info}, handle, address); case 2: - return Inst(Opcode::LoadBufferF32x2, Flags{info}, handle, address); + return Inst(Opcode::LoadBufferU32x2, Flags{info}, handle, address); case 3: - return Inst(Opcode::LoadBufferF32x3, Flags{info}, handle, address); + return Inst(Opcode::LoadBufferU32x3, Flags{info}, handle, address); case 4: - return Inst(Opcode::LoadBufferF32x4, Flags{info}, handle, address); + return Inst(Opcode::LoadBufferU32x4, Flags{info}, handle, address); default: UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); } } -Value IREmitter::LoadBufferFormat(int num_dwords, const Value& handle, const Value& address, - BufferInstInfo info) { - switch (num_dwords) { - case 1: - return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address); - case 2: - return Inst(Opcode::LoadBufferFormatF32x2, Flags{info}, handle, address); - case 3: - return Inst(Opcode::LoadBufferFormatF32x3, Flags{info}, handle, address); - case 4: - return Inst(Opcode::LoadBufferFormatF32x4, Flags{info}, handle, address); - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } +Value IREmitter::LoadBufferFormat(const Value& handle, const Value& address, BufferInstInfo info) { + return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address); } void IREmitter::StoreBuffer(int num_dwords, const Value& handle, const Value& address, const Value& data, BufferInstInfo info) { switch (num_dwords) { case 1: - Inst(data.Type() == Type::F32 ? Opcode::StoreBufferF32 : Opcode::StoreBufferU32, - Flags{info}, handle, address, data); + Inst(Opcode::StoreBufferU32, Flags{info}, handle, address, data); break; case 2: - Inst(Opcode::StoreBufferF32x2, Flags{info}, handle, address, data); + Inst(Opcode::StoreBufferU32x2, Flags{info}, handle, address, data); break; case 3: - Inst(Opcode::StoreBufferF32x3, Flags{info}, handle, address, data); + Inst(Opcode::StoreBufferU32x3, Flags{info}, handle, address, data); break; case 4: - Inst(Opcode::StoreBufferF32x4, Flags{info}, handle, address, data); + Inst(Opcode::StoreBufferU32x4, Flags{info}, handle, address, data); break; default: UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); @@ -408,29 +411,22 @@ Value IREmitter::BufferAtomicXor(const Value& handle, const Value& address, cons return Inst(Opcode::BufferAtomicXor32, Flags{info}, handle, address, value); } -Value IREmitter::BufferAtomicExchange(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicExchange32, Flags{info}, handle, address, value); +Value IREmitter::BufferAtomicSwap(const Value& handle, const Value& address, const Value& value, + BufferInstInfo info) { + return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value); } -void IREmitter::StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info) { - switch (num_dwords) { - case 1: - Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data); - break; - case 2: - Inst(Opcode::StoreBufferFormatF32x2, Flags{info}, handle, address, data); - break; - case 3: - Inst(Opcode::StoreBufferFormatF32x3, Flags{info}, handle, address, data); - break; - case 4: - Inst(Opcode::StoreBufferFormatF32x4, Flags{info}, handle, address, data); - break; - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } +void IREmitter::StoreBufferFormat(const Value& handle, const Value& address, const Value& data, + BufferInstInfo info) { + Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data); +} + +U32 IREmitter::DataAppend(const U32& counter) { + return Inst(Opcode::DataAppend, counter, Imm32(0)); +} + +U32 IREmitter::DataConsume(const U32& counter) { + return Inst(Opcode::DataConsume, counter, Imm32(0)); } U32 IREmitter::LaneId() { @@ -445,6 +441,18 @@ U32 IREmitter::QuadShuffle(const U32& value, const U32& index) { return Inst(Opcode::QuadShuffle, value, index); } +U32 IREmitter::ReadFirstLane(const U32& value) { + return Inst(Opcode::ReadFirstLane, value); +} + +U32 IREmitter::ReadLane(const U32& value, const U32& lane) { + return Inst(Opcode::ReadLane, value, lane); +} + +U32 IREmitter::WriteLane(const U32& value, const U32& write_value, const U32& lane) { + return Inst(Opcode::WriteLane, value, write_value, lane); +} + F32F64 IREmitter::FPAdd(const F32F64& a, const F32F64& b) { if (a.Type() != b.Type()) { UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); @@ -633,6 +641,10 @@ Value IREmitter::UnpackUint2x32(const U64& value) { return Inst(Opcode::UnpackUint2x32, value); } +F64 IREmitter::PackFloat2x32(const Value& vector) { + return Inst(Opcode::PackFloat2x32, vector); +} + U32 IREmitter::PackFloat2x16(const Value& vector) { return Inst(Opcode::PackFloat2x16, vector); } @@ -1059,6 +1071,10 @@ U32 IREmitter::IDiv(const U32& a, const U32& b, bool is_signed) { return Inst(is_signed ? Opcode::SDiv32 : Opcode::UDiv32, a, b); } +U32 IREmitter::IMod(const U32& a, const U32& b, bool is_signed) { + return Inst(is_signed ? Opcode::SMod32 : Opcode::UMod32, a, b); +} + U32U64 IREmitter::INeg(const U32U64& value) { switch (value.Type()) { case Type::U32: @@ -1075,6 +1091,10 @@ U32 IREmitter::IAbs(const U32& value) { } U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { + if (shift.IsImmediate() && shift.U32() == 0) { + return base; + } + switch (base.Type()) { case Type::U32: return Inst(Opcode::ShiftLeftLogical32, base, shift); @@ -1086,6 +1106,10 @@ U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { } U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { + if (shift.IsImmediate() && shift.U32() == 0) { + return base; + } + switch (base.Type()) { case Type::U32: return Inst(Opcode::ShiftRightLogical32, base, shift); @@ -1097,6 +1121,10 @@ U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { } U32U64 IREmitter::ShiftRightArithmetic(const U32U64& base, const U32& shift) { + if (shift.IsImmediate() && shift.U32() == 0) { + return base; + } + switch (base.Type()) { case Type::U32: return Inst(Opcode::ShiftRightArithmetic32, base, shift); @@ -1107,8 +1135,18 @@ U32U64 IREmitter::ShiftRightArithmetic(const U32U64& base, const U32& shift) { } } -U32 IREmitter::BitwiseAnd(const U32& a, const U32& b) { - return Inst(Opcode::BitwiseAnd32, a, b); +U32U64 IREmitter::BitwiseAnd(const U32U64& a, const U32U64& b) { + if (a.Type() != b.Type()) { + UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); + } + switch (a.Type()) { + case Type::U32: + return Inst(Opcode::BitwiseAnd32, a, b); + case Type::U64: + return Inst(Opcode::BitwiseAnd64, a, b); + default: + ThrowInvalidType(a.Type()); + } } U32U64 IREmitter::BitwiseOr(const U32U64& a, const U32U64& b) { @@ -1354,6 +1392,8 @@ U16U32U64 IREmitter::UConvert(size_t result_bitsize, const U16U32U64& value) { switch (value.Type()) { case Type::U16: return Inst(Opcode::ConvertU32U16, value); + default: + break; } default: break; @@ -1374,6 +1414,15 @@ F16F32F64 IREmitter::FPConvert(size_t result_bitsize, const F16F32F64& value) { switch (value.Type()) { case Type::F16: return Inst(Opcode::ConvertF32F16, value); + case Type::F64: + return Inst(Opcode::ConvertF32F64, value); + default: + break; + } + case 64: + switch (value.Type()) { + case Type::F32: + return Inst(Opcode::ConvertF64F32, value); default: break; } @@ -1450,27 +1499,34 @@ Value IREmitter::ImageAtomicExchange(const Value& handle, const Value& coords, c return Inst(Opcode::ImageAtomicExchange32, Flags{info}, handle, coords, value); } -Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& body, const F32& bias, - const U32& offset, TextureInstInfo info) { - return Inst(Opcode::ImageSampleImplicitLod, Flags{info}, handle, body, bias, offset); +Value IREmitter::ImageSampleRaw(const Value& handle, const Value& address1, const Value& address2, + const Value& address3, const Value& address4, + TextureInstInfo info) { + return Inst(Opcode::ImageSampleRaw, Flags{info}, handle, address1, address2, address3, + address4); } -Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& body, const U32& offset, - TextureInstInfo info) { - return Inst(Opcode::ImageSampleExplicitLod, Flags{info}, handle, body, IR::F32{}, offset); +Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& coords, const F32& bias, + const Value& offset, TextureInstInfo info) { + return Inst(Opcode::ImageSampleImplicitLod, Flags{info}, handle, coords, bias, offset); } -F32 IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& body, const F32& dref, - const F32& bias, const U32& offset, - TextureInstInfo info) { - return Inst(Opcode::ImageSampleDrefImplicitLod, Flags{info}, handle, body, dref, bias, - offset); +Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& coords, const F32& lod, + const Value& offset, TextureInstInfo info) { + return Inst(Opcode::ImageSampleExplicitLod, Flags{info}, handle, coords, lod, offset); } -F32 IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& body, const F32& dref, - const U32& offset, TextureInstInfo info) { - return Inst(Opcode::ImageSampleDrefExplicitLod, Flags{info}, handle, body, dref, IR::F32{}, - offset); +Value IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& coords, + const F32& dref, const F32& bias, const Value& offset, + TextureInstInfo info) { + return Inst(Opcode::ImageSampleDrefImplicitLod, Flags{info}, handle, coords, dref, bias, + offset); +} + +Value IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, + const F32& dref, const F32& lod, const Value& offset, + TextureInstInfo info) { + return Inst(Opcode::ImageSampleDrefExplicitLod, Flags{info}, handle, coords, dref, lod, offset); } Value IREmitter::ImageGather(const Value& handle, const Value& coords, const Value& offset, @@ -1502,9 +1558,11 @@ Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, Texture return Inst(Opcode::ImageQueryLod, Flags{info}, handle, coords); } -Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivatives, +Value IREmitter::ImageGradient(const Value& handle, const Value& coords, + const Value& derivatives_dx, const Value& derivatives_dy, const Value& offset, const F32& lod_clamp, TextureInstInfo info) { - return Inst(Opcode::ImageGradient, Flags{info}, handle, coords, derivatives, offset, lod_clamp); + return Inst(Opcode::ImageGradient, Flags{info}, handle, coords, derivatives_dx, derivatives_dy, + offset, lod_clamp); } Value IREmitter::ImageRead(const Value& handle, const Value& coords, TextureInstInfo info) { @@ -1516,4 +1574,44 @@ void IREmitter::ImageWrite(const Value& handle, const Value& coords, const Value Inst(Opcode::ImageWrite, Flags{info}, handle, coords, color); } +// 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: +// https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/debug_printf.md +// +// fmt must be a string literal (pointer is shallow copied into a Value) +// Example usage: +// ir.DebugPrint("invocation xyz: (%u, %u, %u)", +// {ir.GetVectorReg(IR::VectorReg::V0), +// ir.GetVectorReg(IR::VectorReg::V1), +// ir.GetVectorReg(IR::VectorReg::V2)}); +void IREmitter::DebugPrint(const char* fmt, boost::container::small_vector format_args) { + std::array args; + + ASSERT_MSG(format_args.size() < DEBUGPRINT_NUM_FORMAT_ARGS, + "DebugPrint only supports up to {} format args", DEBUGPRINT_NUM_FORMAT_ARGS); + + for (int i = 0; i < format_args.size(); i++) { + args[i] = format_args[i]; + } + + for (int i = format_args.size(); i < DEBUGPRINT_NUM_FORMAT_ARGS; i++) { + args[i] = Inst(Opcode::Void); + } + + IR::Value fmt_val{fmt}; + + DebugPrintFlags flags; + flags.num_args.Assign(format_args.size()); + Inst(Opcode::DebugPrint, Flags{flags}, fmt_val, args[0], args[1], args[2], args[3]); +} + +void IREmitter::EmitVertex() { + Inst(Opcode::EmitVertex); +} + +void IREmitter::EmitPrimitive() { + Inst(Opcode::EmitPrimitive); +} + } // namespace Shader::IR diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index be7f25153..b3f513085 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -6,6 +6,7 @@ #include #include +#include "shader_recompiler/info.h" #include "shader_recompiler/ir/attribute.h" #include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/condition.h" @@ -43,6 +44,7 @@ public: void Epilogue(); void Discard(); void Discard(const U1& cond); + void DebugPrint(const char* fmt, boost::container::small_vector args); void Barrier(); void WorkgroupMemoryBarrier(); @@ -65,19 +67,20 @@ public: [[nodiscard]] U1 GetScc(); [[nodiscard]] U1 GetExec(); [[nodiscard]] U1 GetVcc(); - [[nodiscard]] U32 GetSccLo(); [[nodiscard]] U32 GetVccLo(); [[nodiscard]] U32 GetVccHi(); + [[nodiscard]] U32 GetM0(); void SetScc(const U1& value); void SetExec(const U1& value); void SetVcc(const U1& value); void SetSccLo(const U32& value); void SetVccLo(const U32& value); void SetVccHi(const U32& value); + void SetM0(const U32& value); [[nodiscard]] U1 Condition(IR::Condition cond); - [[nodiscard]] F32 GetAttribute(Attribute attribute, u32 comp = 0); + [[nodiscard]] F32 GetAttribute(Attribute attribute, u32 comp = 0, u32 index = 0); [[nodiscard]] U32 GetAttributeU32(Attribute attribute, u32 comp = 0); void SetAttribute(Attribute attribute, const F32& value, u32 comp = 0); @@ -89,16 +92,16 @@ public: [[nodiscard]] U32 SharedAtomicIMax(const U32& address, const U32& data, bool is_signed); [[nodiscard]] U32 ReadConst(const Value& base, const U32& offset); - [[nodiscard]] F32 ReadConstBuffer(const Value& handle, const U32& index); + [[nodiscard]] U32 ReadConstBuffer(const Value& handle, const U32& index); [[nodiscard]] Value LoadBuffer(int num_dwords, const Value& handle, const Value& address, BufferInstInfo info); - [[nodiscard]] Value LoadBufferFormat(int num_dwords, const Value& handle, const Value& address, + [[nodiscard]] Value LoadBufferFormat(const Value& handle, const Value& address, BufferInstInfo info); void StoreBuffer(int num_dwords, const Value& handle, const Value& address, const Value& data, BufferInstInfo info); - void StoreBufferFormat(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info); + void StoreBufferFormat(const Value& handle, const Value& address, const Value& data, + BufferInstInfo info); [[nodiscard]] Value BufferAtomicIAdd(const Value& handle, const Value& address, const Value& value, BufferInstInfo info); @@ -116,12 +119,17 @@ public: const Value& value, BufferInstInfo info); [[nodiscard]] Value BufferAtomicXor(const Value& handle, const Value& address, const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicExchange(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); + [[nodiscard]] Value BufferAtomicSwap(const Value& handle, const Value& address, + const Value& value, BufferInstInfo info); + [[nodiscard]] U32 DataAppend(const U32& counter); + [[nodiscard]] U32 DataConsume(const U32& counter); [[nodiscard]] U32 LaneId(); [[nodiscard]] U32 WarpId(); [[nodiscard]] U32 QuadShuffle(const U32& value, const U32& index); + [[nodiscard]] U32 ReadFirstLane(const U32& value); + [[nodiscard]] U32 ReadLane(const U32& value, const U32& lane); + [[nodiscard]] U32 WriteLane(const U32& value, const U32& write_value, const U32& lane); [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); @@ -136,6 +144,8 @@ public: [[nodiscard]] U64 PackUint2x32(const Value& vector); [[nodiscard]] Value UnpackUint2x32(const U64& value); + [[nodiscard]] F64 PackFloat2x32(const Value& vector); + [[nodiscard]] U32 PackFloat2x16(const Value& vector); [[nodiscard]] Value UnpackFloat2x16(const U32& value); @@ -188,12 +198,13 @@ public: [[nodiscard]] Value IMulExt(const U32& a, const U32& b, bool is_signed = false); [[nodiscard]] U32U64 IMul(const U32U64& a, const U32U64& b); [[nodiscard]] U32 IDiv(const U32& a, const U32& b, bool is_signed = false); + [[nodiscard]] U32 IMod(const U32& a, const U32& b, bool is_signed = false); [[nodiscard]] U32U64 INeg(const U32U64& value); [[nodiscard]] U32 IAbs(const U32& value); [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift); [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift); - [[nodiscard]] U32 BitwiseAnd(const U32& a, const U32& b); + [[nodiscard]] U32U64 BitwiseAnd(const U32U64& a, const U32U64& b); [[nodiscard]] U32U64 BitwiseOr(const U32U64& a, const U32U64& b); [[nodiscard]] U32 BitwiseXor(const U32& a, const U32& b); [[nodiscard]] U32 BitFieldInsert(const U32& base, const U32& insert, const U32& offset, @@ -266,20 +277,25 @@ public: [[nodiscard]] Value ImageAtomicExchange(const Value& handle, const Value& coords, const Value& value, TextureInstInfo info); + [[nodiscard]] Value ImageSampleRaw(const Value& handle, const Value& address1, + const Value& address2, const Value& address3, + const Value& address4, TextureInstInfo info); + [[nodiscard]] Value ImageSampleImplicitLod(const Value& handle, const Value& body, - const F32& bias, const U32& offset, + const F32& bias, const Value& offset, TextureInstInfo info); [[nodiscard]] Value ImageSampleExplicitLod(const Value& handle, const Value& body, - const U32& offset, TextureInstInfo info); + const F32& lod, const Value& offset, + TextureInstInfo info); - [[nodiscard]] F32 ImageSampleDrefImplicitLod(const Value& handle, const Value& body, - const F32& dref, const F32& bias, - const U32& offset, TextureInstInfo info); + [[nodiscard]] Value ImageSampleDrefImplicitLod(const Value& handle, const Value& body, + const F32& dref, const F32& bias, + const Value& offset, TextureInstInfo info); - [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& body, - const F32& dref, const U32& offset, - TextureInstInfo info); + [[nodiscard]] Value ImageSampleDrefExplicitLod(const Value& handle, const Value& body, + const F32& dref, const F32& lod, + const Value& offset, TextureInstInfo info); [[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod, const U1& skip_mips); @@ -295,12 +311,16 @@ public: [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset, const U32& lod, const U32& multisampling, TextureInstInfo info); [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, - const Value& derivatives, const Value& offset, - const F32& lod_clamp, TextureInstInfo info); + const Value& derivatives_dx, const Value& derivatives_dy, + const Value& offset, const F32& lod_clamp, + TextureInstInfo info); [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); void ImageWrite(const Value& handle, const Value& coords, const Value& color, TextureInstInfo info); + void EmitVertex(); + void EmitPrimitive(); + private: IR::Block::iterator insertion_point; diff --git a/src/shader_recompiler/ir/microinstruction.cpp b/src/shader_recompiler/ir/microinstruction.cpp index e35be8a7f..f0b4882b3 100644 --- a/src/shader_recompiler/ir/microinstruction.cpp +++ b/src/shader_recompiler/ir/microinstruction.cpp @@ -51,15 +51,11 @@ bool Inst::MayHaveSideEffects() const noexcept { case Opcode::Discard: case Opcode::DiscardCond: case Opcode::SetAttribute: - case Opcode::StoreBufferF32: - case Opcode::StoreBufferF32x2: - case Opcode::StoreBufferF32x3: - case Opcode::StoreBufferF32x4: - case Opcode::StoreBufferFormatF32: - case Opcode::StoreBufferFormatF32x2: - case Opcode::StoreBufferFormatF32x3: - case Opcode::StoreBufferFormatF32x4: case Opcode::StoreBufferU32: + case Opcode::StoreBufferU32x2: + case Opcode::StoreBufferU32x3: + case Opcode::StoreBufferU32x4: + case Opcode::StoreBufferFormatF32: case Opcode::BufferAtomicIAdd32: case Opcode::BufferAtomicSMin32: case Opcode::BufferAtomicUMin32: @@ -70,7 +66,9 @@ bool Inst::MayHaveSideEffects() const noexcept { case Opcode::BufferAtomicAnd32: case Opcode::BufferAtomicOr32: case Opcode::BufferAtomicXor32: - case Opcode::BufferAtomicExchange32: + case Opcode::BufferAtomicSwap32: + case Opcode::DataAppend: + case Opcode::DataConsume: case Opcode::WriteSharedU128: case Opcode::WriteSharedU64: case Opcode::WriteSharedU32: @@ -91,6 +89,9 @@ bool Inst::MayHaveSideEffects() const noexcept { case Opcode::ImageAtomicOr32: case Opcode::ImageAtomicXor32: case Opcode::ImageAtomicExchange32: + case Opcode::DebugPrint: + case Opcode::EmitVertex: + case Opcode::EmitPrimitive: return true; default: return false; diff --git a/src/shader_recompiler/ir/opcodes.h b/src/shader_recompiler/ir/opcodes.h index 06f1a6117..200d7f421 100644 --- a/src/shader_recompiler/ir/opcodes.h +++ b/src/shader_recompiler/ir/opcodes.h @@ -21,7 +21,7 @@ namespace Detail { struct OpcodeMeta { std::string_view name; Type type; - std::array arg_types; + std::array arg_types; }; // using enum Type; @@ -51,6 +51,7 @@ constexpr Type F32x4{Type::F32x4}; constexpr Type F64x2{Type::F64x2}; constexpr Type F64x3{Type::F64x3}; constexpr Type F64x4{Type::F64x4}; +constexpr Type StringLiteral{Type::StringLiteral}; constexpr OpcodeMeta META_TABLE[]{ #define OPCODE(name_token, type_token, ...) \ @@ -81,7 +82,7 @@ constexpr u8 NUM_ARGS[]{ } /// Get the number of arguments an opcode accepts -[[nodiscard]] inline size_t NumArgsOf(Opcode op) noexcept { +[[nodiscard]] constexpr inline size_t NumArgsOf(Opcode op) noexcept { return static_cast(Detail::NUM_ARGS[static_cast(op)]); } diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index e9ecd4350..51e10fb38 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -14,17 +14,21 @@ OPCODE(Prologue, Void, OPCODE(Epilogue, Void, ) OPCODE(Discard, Void, ) OPCODE(DiscardCond, Void, U1, ) +OPCODE(DebugPrint, Void, StringLiteral, Opaque, Opaque, Opaque, Opaque, ) // Constant memory operations OPCODE(ReadConst, U32, U32x2, U32, ) -OPCODE(ReadConstBuffer, F32, Opaque, U32, ) -OPCODE(ReadConstBufferU32, U32, Opaque, U32, ) +OPCODE(ReadConstBuffer, U32, Opaque, U32, ) // Barriers OPCODE(Barrier, Void, ) OPCODE(WorkgroupMemoryBarrier, Void, ) OPCODE(DeviceMemoryBarrier, Void, ) +// Geometry shader specific +OPCODE(EmitVertex, Void, ) +OPCODE(EmitPrimitive, Void, ) + // Shared memory operations OPCODE(LoadSharedU32, U32, U32, ) OPCODE(LoadSharedU64, U32x2, U32, ) @@ -35,9 +39,9 @@ OPCODE(WriteSharedU128, Void, U32, // Shared atomic operations OPCODE(SharedAtomicIAdd32, U32, U32, U32, ) -OPCODE(SharedAtomicSMin32, U32, U32, U32, ) +OPCODE(SharedAtomicSMin32, U32, U32, U32, ) OPCODE(SharedAtomicUMin32, U32, U32, U32, ) -OPCODE(SharedAtomicSMax32, U32, U32, U32, ) +OPCODE(SharedAtomicSMax32, U32, U32, U32, ) OPCODE(SharedAtomicUMax32, U32, U32, U32, ) // Context getters/setters @@ -50,23 +54,24 @@ OPCODE(GetVectorRegister, U32, Vect OPCODE(SetVectorRegister, Void, VectorReg, U32, ) OPCODE(GetGotoVariable, U1, U32, ) OPCODE(SetGotoVariable, Void, U32, U1, ) -OPCODE(GetAttribute, F32, Attribute, U32, ) +OPCODE(GetAttribute, F32, Attribute, U32, U32, ) OPCODE(GetAttributeU32, U32, Attribute, U32, ) OPCODE(SetAttribute, Void, Attribute, F32, U32, ) // Flags -OPCODE(GetScc, U1, Void, ) -OPCODE(GetExec, U1, Void, ) -OPCODE(GetVcc, U1, Void, ) -OPCODE(GetSccLo, U32, Void, ) -OPCODE(GetVccLo, U32, Void, ) -OPCODE(GetVccHi, U32, Void, ) -OPCODE(SetScc, Void, U1, ) -OPCODE(SetExec, Void, U1, ) -OPCODE(SetVcc, Void, U1, ) -OPCODE(SetSccLo, Void, U32, ) -OPCODE(SetVccLo, Void, U32, ) -OPCODE(SetVccHi, Void, U32, ) +OPCODE(GetScc, U1, Void, ) +OPCODE(GetExec, U1, Void, ) +OPCODE(GetVcc, U1, Void, ) +OPCODE(GetVccLo, U32, Void, ) +OPCODE(GetVccHi, U32, Void, ) +OPCODE(GetM0, U32, Void, ) +OPCODE(SetScc, Void, U1, ) +OPCODE(SetExec, Void, U1, ) +OPCODE(SetVcc, Void, U1, ) +OPCODE(SetSccLo, Void, U32, ) +OPCODE(SetVccLo, Void, U32, ) +OPCODE(SetVccHi, Void, U32, ) +OPCODE(SetM0, Void, U32, ) // Undefined OPCODE(UndefU1, U1, ) @@ -76,37 +81,29 @@ OPCODE(UndefU32, U32, OPCODE(UndefU64, U64, ) // Buffer operations -OPCODE(LoadBufferF32, F32, Opaque, Opaque, ) -OPCODE(LoadBufferF32x2, F32x2, Opaque, Opaque, ) -OPCODE(LoadBufferF32x3, F32x3, Opaque, Opaque, ) -OPCODE(LoadBufferF32x4, F32x4, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32, F32, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32x2, F32x2, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32x3, F32x3, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32x4, F32x4, Opaque, Opaque, ) OPCODE(LoadBufferU32, U32, Opaque, Opaque, ) -OPCODE(StoreBufferF32, Void, Opaque, Opaque, F32, ) -OPCODE(StoreBufferF32x2, Void, Opaque, Opaque, F32x2, ) -OPCODE(StoreBufferF32x3, Void, Opaque, Opaque, F32x3, ) -OPCODE(StoreBufferF32x4, Void, Opaque, Opaque, F32x4, ) -OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32, ) -OPCODE(StoreBufferFormatF32x2, Void, Opaque, Opaque, F32x2, ) -OPCODE(StoreBufferFormatF32x3, Void, Opaque, Opaque, F32x3, ) -OPCODE(StoreBufferFormatF32x4, Void, Opaque, Opaque, F32x4, ) +OPCODE(LoadBufferU32x2, U32x2, Opaque, Opaque, ) +OPCODE(LoadBufferU32x3, U32x3, Opaque, Opaque, ) +OPCODE(LoadBufferU32x4, U32x4, Opaque, Opaque, ) +OPCODE(LoadBufferFormatF32, F32x4, Opaque, Opaque, ) OPCODE(StoreBufferU32, Void, Opaque, Opaque, U32, ) +OPCODE(StoreBufferU32x2, Void, Opaque, Opaque, U32x2, ) +OPCODE(StoreBufferU32x3, Void, Opaque, Opaque, U32x3, ) +OPCODE(StoreBufferU32x4, Void, Opaque, Opaque, U32x4, ) +OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, U32x4, ) // Buffer atomic operations -OPCODE(BufferAtomicIAdd32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicSMin32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicUMin32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicSMax32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicUMax32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicInc32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicDec32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicAnd32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicOr32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicXor32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicExchange32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicIAdd32, U32, Opaque, Opaque, U32 ) +OPCODE(BufferAtomicSMin32, U32, Opaque, Opaque, U32 ) +OPCODE(BufferAtomicUMin32, U32, Opaque, Opaque, U32 ) +OPCODE(BufferAtomicSMax32, U32, Opaque, Opaque, U32 ) +OPCODE(BufferAtomicUMax32, U32, Opaque, Opaque, U32 ) +OPCODE(BufferAtomicInc32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicDec32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicAnd32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicOr32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicXor32, U32, Opaque, Opaque, U32, ) +OPCODE(BufferAtomicSwap32, U32, Opaque, Opaque, U32, ) // Vector utility OPCODE(CompositeConstructU32x2, U32x2, U32, U32, ) @@ -164,6 +161,7 @@ OPCODE(BitCastF32U32, F32, U32, OPCODE(BitCastF64U64, F64, U64, ) OPCODE(PackUint2x32, U64, U32x2, ) OPCODE(UnpackUint2x32, U32x2, U64, ) +OPCODE(PackFloat2x32, F64, F32x2, ) OPCODE(PackFloat2x16, U32, F16x2, ) OPCODE(UnpackFloat2x16, F16x2, U32, ) OPCODE(PackHalf2x16, U32, F32x2, ) @@ -251,6 +249,8 @@ OPCODE(SMulExt, U32x2, U32, OPCODE(UMulExt, U32x2, U32, U32, ) OPCODE(SDiv32, U32, U32, U32, ) OPCODE(UDiv32, U32, U32, U32, ) +OPCODE(SMod32, U32, U32, U32, ) +OPCODE(UMod32, U32, U32, U32, ) OPCODE(INeg32, U32, U32, ) OPCODE(INeg64, U64, U64, ) OPCODE(IAbs32, U32, U32, ) @@ -261,6 +261,7 @@ OPCODE(ShiftRightLogical64, U64, U64, OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) OPCODE(ShiftRightArithmetic64, U64, U64, U32, ) OPCODE(BitwiseAnd32, U32, U32, U32, ) +OPCODE(BitwiseAnd64, U64, U64, U64, ) OPCODE(BitwiseOr32, U32, U32, U32, ) OPCODE(BitwiseOr64, U64, U64, U64, ) OPCODE(BitwiseXor32, U32, U32, U32, ) @@ -316,33 +317,39 @@ OPCODE(ConvertU16U32, U16, U32, OPCODE(ConvertU32U16, U32, U16, ) // Image operations -OPCODE(ImageSampleImplicitLod, F32x4, Opaque, Opaque, F32, Opaque, ) -OPCODE(ImageSampleExplicitLod, F32x4, Opaque, Opaque, U32, Opaque, ) -OPCODE(ImageSampleDrefImplicitLod, F32, Opaque, Opaque, Opaque, F32, Opaque, ) -OPCODE(ImageSampleDrefExplicitLod, F32, Opaque, Opaque, Opaque, U32, Opaque, ) +OPCODE(ImageSampleRaw, F32x4, Opaque, F32x4, F32x4, F32x4, F32, ) +OPCODE(ImageSampleImplicitLod, F32x4, Opaque, F32x4, F32, Opaque, ) +OPCODE(ImageSampleExplicitLod, F32x4, Opaque, Opaque, F32, Opaque, ) +OPCODE(ImageSampleDrefImplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, ) +OPCODE(ImageSampleDrefExplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, ) OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, ) OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, F32, ) OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, ) OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) -OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, ) +OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, F32, ) OPCODE(ImageRead, U32x4, Opaque, Opaque, ) OPCODE(ImageWrite, Void, Opaque, Opaque, U32x4, ) // Image atomic operations -OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicSMin32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicUMin32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicSMax32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicUMax32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicInc32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicDec32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicAnd32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicSMin32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicUMin32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicSMax32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicUMax32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicInc32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicDec32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicAnd32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) +OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, ) // Warp operations OPCODE(LaneId, U32, ) OPCODE(WarpId, U32, ) OPCODE(QuadShuffle, U32, U32, U32 ) +OPCODE(ReadFirstLane, U32, U32, ) +OPCODE(ReadLane, U32, U32, U32 ) +OPCODE(WriteLane, U32, U32, U32, U32 ) +OPCODE(DataAppend, U32, U32, U32 ) +OPCODE(DataConsume, U32, U32, U32 ) diff --git a/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp similarity index 94% rename from src/shader_recompiler/ir/passes/constant_propogation_pass.cpp rename to src/shader_recompiler/ir/passes/constant_propagation_pass.cpp index 94218b32f..775aed5b3 100644 --- a/src/shader_recompiler/ir/passes/constant_propogation_pass.cpp +++ b/src/shader_recompiler/ir/passes/constant_propagation_pass.cpp @@ -250,6 +250,18 @@ void FoldCmpClass(IR::Inst& inst) { } } +void FoldReadLane(IR::Inst& inst) { + const u32 lane = inst.Arg(1).U32(); + IR::Inst* prod = inst.Arg(0).InstRecursive(); + while (prod->GetOpcode() == IR::Opcode::WriteLane) { + if (prod->Arg(2).U32() == lane) { + inst.ReplaceUsesWith(prod->Arg(1)); + return; + } + prod = prod->Arg(0).InstRecursive(); + } +} + void ConstantPropagation(IR::Block& block, IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::IAdd32: @@ -266,6 +278,12 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { case IR::Opcode::FPCmpClass32: FoldCmpClass(inst); return; + case IR::Opcode::ShiftLeftLogical32: + FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return static_cast(a << b); }); + return; + case IR::Opcode::ShiftRightLogical32: + FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return static_cast(a >> b); }); + return; case IR::Opcode::ShiftRightArithmetic32: FoldWhenAllImmediates(inst, [](s32 a, s32 b) { return static_cast(a >> b); }); return; @@ -289,6 +307,8 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { case IR::Opcode::SelectF32: case IR::Opcode::SelectF64: return FoldSelect(inst); + case IR::Opcode::ReadLane: + return FoldReadLane(inst); case IR::Opcode::FPNeg32: FoldWhenAllImmediates(inst, [](f32 a) { return -a; }); return; @@ -333,14 +353,19 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { return; case IR::Opcode::INotEqual: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a != b; }); - FoldBooleanConvert(inst); return; case IR::Opcode::BitwiseAnd32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a & b; }); return; + case IR::Opcode::BitwiseAnd64: + FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a & b; }); + return; case IR::Opcode::BitwiseOr32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a | b; }); return; + case IR::Opcode::BitwiseOr64: + FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a | b; }); + return; case IR::Opcode::BitwiseXor32: FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a ^ b; }); return; diff --git a/src/shader_recompiler/ir/passes/ir_passes.h b/src/shader_recompiler/ir/passes/ir_passes.h index 7e2b962b5..e6e389d15 100644 --- a/src/shader_recompiler/ir/passes/ir_passes.h +++ b/src/shader_recompiler/ir/passes/ir_passes.h @@ -15,5 +15,7 @@ void ConstantPropagationPass(IR::BlockList& program); void ResourceTrackingPass(IR::Program& program); void CollectShaderInfoPass(IR::Program& program); void LowerSharedMemToRegisters(IR::Program& program); +void RingAccessElimination(const IR::Program& program, const RuntimeInfo& runtime_info, + Stage stage); } // namespace Shader::Optimization diff --git a/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp b/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp index a87cf31b1..76bfcf911 100644 --- a/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp +++ b/src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp @@ -21,8 +21,7 @@ void LowerSharedMemToRegisters(IR::Program& program) { const IR::Inst* prod = inst.Arg(0).InstRecursive(); const auto it = std::ranges::find_if(ds_writes, [&](const IR::Inst* write) { const IR::Inst* write_prod = write->Arg(0).InstRecursive(); - return write_prod->Arg(1).U32() == prod->Arg(1).U32() && - write_prod->Arg(0) == prod->Arg(0); + return write_prod->Arg(1).U32() == prod->Arg(1).U32(); }); ASSERT(it != ds_writes.end()); // Replace data read with value written. diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 20a66ad0c..0d91badda 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -3,11 +3,11 @@ #include #include +#include "shader_recompiler/info.h" #include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/breadth_first_search.h" #include "shader_recompiler/ir/ir_emitter.h" #include "shader_recompiler/ir/program.h" -#include "shader_recompiler/runtime_info.h" #include "video_core/amdgpu/resource.h" namespace Shader::Optimization { @@ -32,7 +32,7 @@ bool IsBufferAtomic(const IR::Inst& inst) { case IR::Opcode::BufferAtomicAnd32: case IR::Opcode::BufferAtomicOr32: case IR::Opcode::BufferAtomicXor32: - case IR::Opcode::BufferAtomicExchange32: + case IR::Opcode::BufferAtomicSwap32: return true; default: return false; @@ -41,15 +41,10 @@ bool IsBufferAtomic(const IR::Inst& inst) { bool IsBufferStore(const IR::Inst& inst) { switch (inst.GetOpcode()) { - case IR::Opcode::StoreBufferF32: - case IR::Opcode::StoreBufferF32x2: - case IR::Opcode::StoreBufferF32x3: - case IR::Opcode::StoreBufferF32x4: - case IR::Opcode::StoreBufferFormatF32: - case IR::Opcode::StoreBufferFormatF32x2: - case IR::Opcode::StoreBufferFormatF32x3: - case IR::Opcode::StoreBufferFormatF32x4: case IR::Opcode::StoreBufferU32: + case IR::Opcode::StoreBufferU32x2: + case IR::Opcode::StoreBufferU32x3: + case IR::Opcode::StoreBufferU32x4: return true; default: return IsBufferAtomic(inst); @@ -58,24 +53,28 @@ bool IsBufferStore(const IR::Inst& inst) { bool IsBufferInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { - case IR::Opcode::LoadBufferF32: - case IR::Opcode::LoadBufferF32x2: - case IR::Opcode::LoadBufferF32x3: - case IR::Opcode::LoadBufferF32x4: - case IR::Opcode::LoadBufferFormatF32: - case IR::Opcode::LoadBufferFormatF32x2: - case IR::Opcode::LoadBufferFormatF32x3: - case IR::Opcode::LoadBufferFormatF32x4: case IR::Opcode::LoadBufferU32: + case IR::Opcode::LoadBufferU32x2: + case IR::Opcode::LoadBufferU32x3: + case IR::Opcode::LoadBufferU32x4: case IR::Opcode::ReadConstBuffer: - case IR::Opcode::ReadConstBufferU32: return true; default: return IsBufferStore(inst); } } -static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { +bool IsDataRingInstruction(const IR::Inst& inst) { + return inst.GetOpcode() == IR::Opcode::DataAppend || + inst.GetOpcode() == IR::Opcode::DataConsume; +} + +bool IsTextureBufferInstruction(const IR::Inst& inst) { + return inst.GetOpcode() == IR::Opcode::LoadBufferFormatF32 || + inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32; +} + +bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { switch (num_format) { case AmdGpu::NumberFormat::Float: switch (data_format) { @@ -99,63 +98,11 @@ static bool UseFP16(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_for } IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) { - switch (inst.GetOpcode()) { - case IR::Opcode::LoadBufferFormatF32: - case IR::Opcode::LoadBufferFormatF32x2: - case IR::Opcode::LoadBufferFormatF32x3: - case IR::Opcode::LoadBufferFormatF32x4: - case IR::Opcode::StoreBufferFormatF32: - case IR::Opcode::StoreBufferFormatF32x2: - case IR::Opcode::StoreBufferFormatF32x3: - case IR::Opcode::StoreBufferFormatF32x4: - switch (num_format) { - case AmdGpu::NumberFormat::Unorm: - case AmdGpu::NumberFormat::Snorm: - case AmdGpu::NumberFormat::Uscaled: - case AmdGpu::NumberFormat::Sscaled: - case AmdGpu::NumberFormat::Uint: - case AmdGpu::NumberFormat::Sint: - case AmdGpu::NumberFormat::SnormNz: - return IR::Type::U32; - case AmdGpu::NumberFormat::Float: - return IR::Type::F32; - default: - UNREACHABLE(); - } - case IR::Opcode::LoadBufferF32: - case IR::Opcode::LoadBufferF32x2: - case IR::Opcode::LoadBufferF32x3: - case IR::Opcode::LoadBufferF32x4: - case IR::Opcode::ReadConstBuffer: - case IR::Opcode::StoreBufferF32: - case IR::Opcode::StoreBufferF32x2: - case IR::Opcode::StoreBufferF32x3: - case IR::Opcode::StoreBufferF32x4: - return IR::Type::F32; - case IR::Opcode::LoadBufferU32: - case IR::Opcode::ReadConstBufferU32: - case IR::Opcode::StoreBufferU32: - case IR::Opcode::BufferAtomicIAdd32: - return IR::Type::U32; - default: - UNREACHABLE(); - } + return IR::Type::U32; } -bool IsImageInstruction(const IR::Inst& inst) { +bool IsImageAtomicInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { - case IR::Opcode::ImageSampleExplicitLod: - case IR::Opcode::ImageSampleImplicitLod: - case IR::Opcode::ImageSampleDrefExplicitLod: - case IR::Opcode::ImageSampleDrefImplicitLod: - case IR::Opcode::ImageFetch: - case IR::Opcode::ImageGather: - case IR::Opcode::ImageGatherDref: - case IR::Opcode::ImageQueryDimensions: - case IR::Opcode::ImageQueryLod: - case IR::Opcode::ImageGradient: - case IR::Opcode::ImageRead: - case IR::Opcode::ImageWrite: case IR::Opcode::ImageAtomicIAdd32: case IR::Opcode::ImageAtomicSMin32: case IR::Opcode::ImageAtomicUMin32: @@ -177,79 +124,71 @@ bool IsImageStorageInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::ImageWrite: case IR::Opcode::ImageRead: - case IR::Opcode::ImageAtomicIAdd32: - case IR::Opcode::ImageAtomicSMin32: - case IR::Opcode::ImageAtomicUMin32: - case IR::Opcode::ImageAtomicSMax32: - case IR::Opcode::ImageAtomicUMax32: - case IR::Opcode::ImageAtomicInc32: - case IR::Opcode::ImageAtomicDec32: - case IR::Opcode::ImageAtomicAnd32: - case IR::Opcode::ImageAtomicOr32: - case IR::Opcode::ImageAtomicXor32: - case IR::Opcode::ImageAtomicExchange32: return true; default: - return false; + return IsImageAtomicInstruction(inst); } } -u32 ImageOffsetArgumentPosition(const IR::Inst& inst) { +bool IsImageInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { - case IR::Opcode::ImageGather: - case IR::Opcode::ImageGatherDref: - return 2; - case IR::Opcode::ImageSampleExplicitLod: - case IR::Opcode::ImageSampleImplicitLod: - return 3; - case IR::Opcode::ImageSampleDrefExplicitLod: - case IR::Opcode::ImageSampleDrefImplicitLod: - return 4; + case IR::Opcode::ImageFetch: + case IR::Opcode::ImageQueryDimensions: + case IR::Opcode::ImageQueryLod: + case IR::Opcode::ImageSampleRaw: + return true; default: - UNREACHABLE(); + return IsImageStorageInstruction(inst); } } class Descriptors { public: explicit Descriptors(Info& info_) - : info{info_}, buffer_resources{info_.buffers}, image_resources{info_.images}, + : info{info_}, buffer_resources{info_.buffers}, + texture_buffer_resources{info_.texture_buffers}, image_resources{info_.images}, sampler_resources{info_.samplers} {} u32 Add(const BufferResource& desc) { const u32 index{Add(buffer_resources, desc, [&desc](const auto& existing) { + // Only one GDS binding can exist. + if (desc.is_gds_buffer && existing.is_gds_buffer) { + return true; + } return desc.sgpr_base == existing.sgpr_base && desc.dword_offset == existing.dword_offset && desc.inline_cbuf == existing.inline_cbuf; })}; auto& buffer = buffer_resources[index]; - ASSERT(buffer.length == desc.length); - buffer.is_storage |= desc.is_storage; buffer.used_types |= desc.used_types; buffer.is_written |= desc.is_written; return index; } + u32 Add(const TextureBufferResource& desc) { + const u32 index{Add(texture_buffer_resources, desc, [&desc](const auto& existing) { + return desc.sgpr_base == existing.sgpr_base && + desc.dword_offset == existing.dword_offset; + })}; + auto& buffer = texture_buffer_resources[index]; + buffer.is_written |= desc.is_written; + return index; + } + u32 Add(const ImageResource& desc) { const u32 index{Add(image_resources, desc, [&desc](const auto& existing) { return desc.sgpr_base == existing.sgpr_base && - desc.dword_offset == existing.dword_offset && desc.type == existing.type && - desc.is_storage == existing.is_storage; + desc.dword_offset == existing.dword_offset; })}; + auto& image = image_resources[index]; + image.is_storage |= desc.is_storage; return index; } u32 Add(const SamplerResource& desc) { const u32 index{Add(sampler_resources, desc, [this, &desc](const auto& existing) { - if (desc.sgpr_base == existing.sgpr_base && - desc.dword_offset == existing.dword_offset) { - return true; - } - // Samplers with different bindings might still be the same. - const auto old_sharp = - info.ReadUd(existing.sgpr_base, existing.dword_offset); - const auto new_sharp = info.ReadUd(desc.sgpr_base, desc.dword_offset); - return old_sharp == new_sharp; + return desc.sgpr_base == existing.sgpr_base && + desc.dword_offset == existing.dword_offset; })}; return index; } @@ -267,6 +206,7 @@ private: const Info& info; BufferResourceList& buffer_resources; + TextureBufferResourceList& texture_buffer_resources; ImageResourceList& image_resources; SamplerResourceList& sampler_resources; }; @@ -295,10 +235,11 @@ std::pair TryDisableAnisoLod0(const IR::Inst* inst) { return not_found; } - // The bits range is for lods + // The bits range is for lods (note that constants are changed after constant propagation pass) const auto* prod0_arg0 = prod0->Arg(0).InstRecursive(); if (prod0_arg0->GetOpcode() != IR::Opcode::BitFieldUExtract || - prod0_arg0->Arg(1).InstRecursive()->Arg(0).U32() != 0x0008000cu) { + !(prod0_arg0->Arg(1).IsIdentity() && prod0_arg0->Arg(1).U32() == 12) || + !(prod0_arg0->Arg(2).IsIdentity() && prod0_arg0->Arg(2).U32() == 8)) { return not_found; } @@ -345,6 +286,7 @@ SharpLocation TrackSharp(const IR::Inst* inst) { // Retrieve SGPR pair that holds sbase const auto pred1 = [](const IR::Inst* inst) -> std::optional { + ASSERT(inst->GetOpcode() != IR::Opcode::ReadConst); if (inst->GetOpcode() == IR::Opcode::GetUserData) { return inst->Arg(0).ScalarReg(); } @@ -361,33 +303,6 @@ SharpLocation TrackSharp(const IR::Inst* inst) { }; } -static constexpr size_t MaxUboSize = 65536; - -static bool IsLoadBufferFormat(const IR::Inst& inst) { - switch (inst.GetOpcode()) { - case IR::Opcode::LoadBufferFormatF32: - case IR::Opcode::LoadBufferFormatF32x2: - case IR::Opcode::LoadBufferFormatF32x3: - case IR::Opcode::LoadBufferFormatF32x4: - return true; - default: - return false; - } -} - -static u32 BufferLength(const AmdGpu::Buffer& buffer) { - const auto stride = buffer.GetStride(); - if (stride < sizeof(f32)) { - ASSERT(sizeof(f32) % stride == 0); - return (((buffer.num_records - 1) / sizeof(f32)) + 1) * stride; - } else if (stride == sizeof(f32)) { - return buffer.num_records; - } else { - ASSERT(stride % sizeof(f32) == 0); - return buffer.num_records * (stride / sizeof(f32)); - } -} - s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, AmdGpu::Buffer& cbuf) { @@ -402,33 +317,20 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, // is used to define an inline constant buffer IR::Inst* handle = inst.Arg(0).InstRecursive(); - IR::Inst* p0 = handle->Arg(0).InstRecursive(); - if (p0->GetOpcode() != IR::Opcode::IAdd32 || !p0->Arg(0).IsImmediate() || - !p0->Arg(1).IsImmediate()) { - return -1; - } - IR::Inst* p1 = handle->Arg(1).InstRecursive(); - if (p1->GetOpcode() != IR::Opcode::IAdd32) { - return -1; - } - if (!handle->Arg(3).IsImmediate() || !handle->Arg(2).IsImmediate()) { + if (!handle->AreAllArgsImmediates()) { return -1; } // We have found this pattern. Build the sharp. - std::array buffer; - buffer[0] = info.pgm_base + p0->Arg(0).U32() + p0->Arg(1).U32(); - buffer[1] = 0; - buffer[2] = handle->Arg(2).U32(); - buffer[3] = handle->Arg(3).U32(); + std::array buffer; + buffer[0] = info.pgm_base + (handle->Arg(0).U32() | u64(handle->Arg(1).U32()) << 32); + buffer[1] = handle->Arg(2).U32() | u64(handle->Arg(3).U32()) << 32; cbuf = std::bit_cast(buffer); // Assign a binding to this sharp. return descriptors.Add(BufferResource{ .sgpr_base = std::numeric_limits::max(), .dword_offset = 0, - .length = BufferLength(cbuf), .used_types = BufferDataType(inst, cbuf.GetNumberFmt()), .inline_cbuf = cbuf, - .is_storage = IsBufferStore(inst) || cbuf.GetSize() > MaxUboSize, }); } @@ -440,121 +342,115 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, IR::Inst* handle = inst.Arg(0).InstRecursive(); IR::Inst* producer = handle->Arg(0).InstRecursive(); const auto sharp = TrackSharp(producer); - const bool is_store = IsBufferStore(inst); buffer = info.ReadUd(sharp.sgpr_base, sharp.dword_offset); binding = descriptors.Add(BufferResource{ .sgpr_base = sharp.sgpr_base, .dword_offset = sharp.dword_offset, - .length = BufferLength(buffer), .used_types = BufferDataType(inst, buffer.GetNumberFmt()), - .is_storage = is_store || buffer.GetSize() > MaxUboSize, - .is_written = is_store, + .is_written = IsBufferStore(inst), }); } // Update buffer descriptor format. const auto inst_info = inst.Flags(); - auto& buffer_desc = info.buffers[binding]; - if (inst_info.is_typed) { - buffer_desc.dfmt = inst_info.dmft; - buffer_desc.nfmt = inst_info.nfmt; - } else { - buffer_desc.dfmt = buffer.GetDataFmt(); - buffer_desc.nfmt = buffer.GetNumberFmt(); - } // Replace handle with binding index in buffer resource list. IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; inst.SetArg(0, ir.Imm32(binding)); - ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable); + ASSERT(!buffer.add_tid_enable); // Address of constant buffer reads can be calculated at IR emittion time. - if (inst.GetOpcode() == IR::Opcode::ReadConstBuffer || - inst.GetOpcode() == IR::Opcode::ReadConstBufferU32) { + if (inst.GetOpcode() == IR::Opcode::ReadConstBuffer) { return; } - if (IsLoadBufferFormat(inst)) { - if (UseFP16(buffer.GetDataFmt(), buffer.GetNumberFmt())) { - info.uses_fp16 = true; - } - } else { - const u32 stride = buffer.GetStride(); - if (stride < 4) { - LOG_WARNING(Render_Vulkan, - "non-formatting load_buffer_* is not implemented for stride {}", stride); - } - } + const IR::U32 index_stride = ir.Imm32(buffer.index_stride); + const IR::U32 element_size = ir.Imm32(buffer.element_size); // Compute address of the buffer using the stride. - // Todo: What if buffer is rebound with different stride? IR::U32 address = ir.Imm32(inst_info.inst_offset.Value()); if (inst_info.index_enable) { const IR::U32 index = inst_info.offset_enable ? IR::U32{ir.CompositeExtract(inst.Arg(1), 0)} : IR::U32{inst.Arg(1)}; - address = ir.IAdd(address, ir.IMul(index, ir.Imm32(buffer.GetStride()))); + if (buffer.swizzle_enable) { + const IR::U32 stride_index_stride = + ir.Imm32(static_cast(buffer.stride * buffer.index_stride)); + const IR::U32 index_msb = ir.IDiv(index, index_stride); + const IR::U32 index_lsb = ir.IMod(index, index_stride); + address = ir.IAdd(address, ir.IAdd(ir.IMul(index_msb, stride_index_stride), + ir.IMul(index_lsb, element_size))); + } else { + address = ir.IAdd(address, ir.IMul(index, ir.Imm32(buffer.GetStride()))); + } } if (inst_info.offset_enable) { const IR::U32 offset = inst_info.index_enable ? IR::U32{ir.CompositeExtract(inst.Arg(1), 1)} : IR::U32{inst.Arg(1)}; - address = ir.IAdd(address, offset); + if (buffer.swizzle_enable) { + const IR::U32 element_size_index_stride = + ir.Imm32(buffer.element_size * buffer.index_stride); + const IR::U32 offset_msb = ir.IDiv(offset, element_size); + const IR::U32 offset_lsb = ir.IMod(offset, element_size); + address = ir.IAdd(address, + ir.IAdd(ir.IMul(offset_msb, element_size_index_stride), offset_lsb)); + } else { + address = ir.IAdd(address, offset); + } } inst.SetArg(1, address); } +void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info, + Descriptors& descriptors) { + const IR::Inst* handle = inst.Arg(0).InstRecursive(); + const IR::Inst* producer = handle->Arg(0).InstRecursive(); + const auto sharp = TrackSharp(producer); + const auto buffer = info.ReadUd(sharp.sgpr_base, sharp.dword_offset); + const s32 binding = descriptors.Add(TextureBufferResource{ + .sgpr_base = sharp.sgpr_base, + .dword_offset = sharp.dword_offset, + .nfmt = buffer.GetNumberFmt(), + .is_written = inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32, + }); + + // Replace handle with binding index in texture buffer resource list. + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + inst.SetArg(0, ir.Imm32(binding)); + ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable); +} + IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t, - const IR::Value& z) { + const IR::Value& z, bool is_storage, bool is_array) { + // When cubemap is written with imageStore it is treated like 2DArray. + if (is_storage) { + 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)); - return ir.CompositeConstruct(x, y, z); + 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 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); - const auto image = info.ReadUd(tsharp.sgpr_base, tsharp.dword_offset); - const auto inst_info = inst.Flags(); - if (!image.Valid()) { - LOG_ERROR(Render_Vulkan, "Shader compiled with unbound image!"); - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - inst.ReplaceUsesWith( - ir.CompositeConstruct(ir.Imm32(0.f), ir.Imm32(0.f), ir.Imm32(0.f), ir.Imm32(0.f))); - return; - } - ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); - u32 image_binding = descriptors.Add(ImageResource{ - .sgpr_base = tsharp.sgpr_base, - .dword_offset = tsharp.dword_offset, - .type = image.GetType(), - .nfmt = static_cast(image.GetNumberFmt()), - .is_storage = IsImageStorageInstruction(inst), - .is_depth = bool(inst_info.is_depth), - }); - +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 u32 sampler_binding = [&] { - if (!has_sampler) { - return 0U; - } + ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2); const IR::Value& handle = producer->Arg(1); // Inline sampler resource. if (handle.IsImmediate()) { @@ -576,7 +472,207 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip .disable_aniso = disable_aniso, }); }(); - image_binding |= (sampler_binding << 16); + + 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); + + IR::Inst* body1 = inst.Arg(1).InstRecursive(); + IR::Inst* body2 = inst.Arg(2).InstRecursive(); + IR::Inst* body3 = inst.Arg(3).InstRecursive(); + IR::F32 body4 = IR::F32{inst.Arg(4)}; + const auto get_addr_reg = [&](u32 index) -> IR::F32 { + if (index <= 3) { + return IR::F32{body1->Arg(index)}; + } + if (index >= 4 && index <= 7) { + return IR::F32{body2->Arg(index - 4)}; + } + if (index >= 8 && index <= 11) { + return IR::F32{body3->Arg(index - 8)}; + } + if (index == 12) { + return body4; + } + UNREACHABLE(); + }; + u32 addr_reg = 0; + + // Load first address components as denoted in 8.2.4 VGPR Usage Sea Islands Series Instruction + // Set Architecture + const IR::Value offset = [&] -> IR::Value { + if (!inst_info.has_offset) { + return IR::U32{}; + } + + // The offsets are six-bit signed integers: X=[5:0], Y=[13:8], and Z=[21:16]. + IR::Value arg = get_addr_reg(addr_reg++); + if (const IR::Inst* offset_inst = arg.TryInstRecursive()) { + ASSERT(offset_inst->GetOpcode() == IR::Opcode::BitCastF32U32); + arg = offset_inst->Arg(0); + } + + const auto read = [&](u32 off) -> IR::U32 { + if (arg.IsImmediate()) { + const u32 imm = + arg.Type() == IR::Type::F32 ? std::bit_cast(arg.F32()) : arg.U32(); + const u16 comp = (imm >> off) & 0x3F; + return ir.Imm32(s32(comp << 26) >> 26); + } + return ir.BitFieldExtract(IR::U32{arg}, ir.Imm32(off), ir.Imm32(6), true); + }; + + switch (image.GetType()) { + case AmdGpu::ImageType::Color1D: + case AmdGpu::ImageType::Color1DArray: + return read(0); + case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Color2DArray: + 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(); + } + }(); + const IR::F32 bias = inst_info.has_bias ? get_addr_reg(addr_reg++) : IR::F32{}; + const IR::F32 dref = inst_info.is_depth ? get_addr_reg(addr_reg++) : IR::F32{}; + const auto [derivatives_dx, derivatives_dy] = [&] -> std::pair { + if (!inst_info.has_derivatives) { + return {}; + } + switch (image.GetType()) { + case AmdGpu::ImageType::Color1D: + case AmdGpu::ImageType::Color1DArray: + // du/dx, du/dy + addr_reg = addr_reg + 2; + return {get_addr_reg(addr_reg - 2), get_addr_reg(addr_reg - 1)}; + case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Color2DArray: + case AmdGpu::ImageType::Color2DMsaa: + // (du/dx, dv/dx), (du/dy, dv/dy) + addr_reg = addr_reg + 4; + 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), + get_addr_reg(addr_reg - 4)), + ir.CompositeConstruct(get_addr_reg(addr_reg - 3), get_addr_reg(addr_reg - 2), + get_addr_reg(addr_reg - 1))}; + default: + UNREACHABLE(); + } + }(); + + // 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()) { + case AmdGpu::ImageType::Color1D: // x + addr_reg = addr_reg + 1; + return get_addr_reg(addr_reg - 1); + case AmdGpu::ImageType::Color1DArray: // x, slice + [[fallthrough]]; + case AmdGpu::ImageType::Color2D: // x, y + addr_reg = addr_reg + 2; + return ir.CompositeConstruct(get_addr_reg(addr_reg - 2), get_addr_reg(addr_reg - 1)); + case AmdGpu::ImageType::Color2DArray: // x, y, slice + [[fallthrough]]; + case AmdGpu::ImageType::Color2DMsaa: // x, y, frag + [[fallthrough]]; + case AmdGpu::ImageType::Color3D: // x, y, z + addr_reg = addr_reg + 3; + return ir.CompositeConstruct(get_addr_reg(addr_reg - 3), get_addr_reg(addr_reg - 2), + get_addr_reg(addr_reg - 1)); + case AmdGpu::ImageType::Cube: // x, y, face + addr_reg = addr_reg + 3; + return PatchCubeCoord(ir, get_addr_reg(addr_reg - 3), get_addr_reg(addr_reg - 2), + get_addr_reg(addr_reg - 1), false, inst_info.is_array); + default: + UNREACHABLE(); + } + }(); + + ASSERT(!inst_info.has_lod || !inst_info.has_lod_clamp); + const bool explicit_lod = inst_info.has_lod || inst_info.force_level0; + const IR::F32 lod = inst_info.has_lod ? get_addr_reg(addr_reg++) + : inst_info.force_level0 ? ir.Imm32(0.0f) + : IR::F32{}; + const IR::F32 lod_clamp = inst_info.has_lod_clamp ? get_addr_reg(addr_reg++) : IR::F32{}; + + const auto new_inst = [&] -> IR::Value { + if (inst_info.is_gather) { + if (inst_info.is_depth) { + return ir.ImageGatherDref(handle, coords, offset, dref, inst_info); + } + return ir.ImageGather(handle, coords, offset, inst_info); + } + if (inst_info.has_derivatives) { + return ir.ImageGradient(handle, coords, derivatives_dx, derivatives_dy, offset, + lod_clamp, inst_info); + } + if (inst_info.is_depth) { + if (explicit_lod) { + return ir.ImageSampleDrefExplicitLod(handle, coords, dref, lod, offset, inst_info); + } + return ir.ImageSampleDrefImplicitLod(handle, coords, dref, bias, offset, inst_info); + } + if (explicit_lod) { + return ir.ImageSampleExplicitLod(handle, coords, lod, offset, inst_info); + } + return ir.ImageSampleImplicitLod(handle, coords, bias, offset, inst_info); + }(); + inst.ReplaceUsesWith(new_inst); +} + +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); + const auto inst_info = inst.Flags(); + auto image = info.ReadUd(tsharp.sgpr_base, tsharp.dword_offset); + 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_storage = IsImageStorageInstruction(inst); + const auto type = image.IsPartialCubemap() ? AmdGpu::ImageType::Color2DArray : image.GetType(); + u32 image_binding = descriptors.Add(ImageResource{ + .sgpr_base = tsharp.sgpr_base, + .dword_offset = tsharp.dword_offset, + .type = type, + .nfmt = image.GetNumberFmt(), + .is_storage = is_storage, + .is_depth = bool(inst_info.is_depth), + .is_atomic = IsImageAtomicInstruction(inst), + .is_array = bool(inst_info.is_array), + }); + + // 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)}; @@ -604,62 +700,64 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip case AmdGpu::ImageType::Color3D: // x, y, z return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; case AmdGpu::ImageType::Cube: // x, y, face - return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; + return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_storage, + inst_info.is_array), + body->Arg(3)}; default: UNREACHABLE_MSG("Unknown image type {}", image.GetType()); } }(); inst.SetArg(1, coords); - if (inst_info.has_offset) { - // The offsets are six-bit signed integers: X=[5:0], Y=[13:8], and Z=[21:16]. - const u32 arg_pos = ImageOffsetArgumentPosition(inst); - const IR::Value arg = inst.Arg(arg_pos); - ASSERT_MSG(arg.Type() == IR::Type::U32, "Unexpected offset type"); + if (inst_info.has_lod) { + ASSERT(inst.GetOpcode() == IR::Opcode::ImageFetch); + inst.SetArg(3, arg); + } +} - const auto read = [&](u32 offset) -> auto { - return ir.BitFieldExtract(IR::U32{arg}, ir.Imm32(offset), ir.Imm32(6), true); - }; +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, + }); - switch (image.GetType()) { - case AmdGpu::ImageType::Color1D: - case AmdGpu::ImageType::Color1DArray: - inst.SetArg(arg_pos, read(0)); - break; - case AmdGpu::ImageType::Color2D: - case AmdGpu::ImageType::Color2DArray: - inst.SetArg(arg_pos, ir.CompositeConstruct(read(0), read(8))); - break; - case AmdGpu::ImageType::Color3D: - inst.SetArg(arg_pos, ir.CompositeConstruct(read(0), read(8), read(16))); - break; - default: - UNREACHABLE(); + const auto pred = [](const IR::Inst* inst) -> std::optional { + if (inst->GetOpcode() == IR::Opcode::GetUserData) { + return inst; } - } + return std::nullopt; + }; - if (inst_info.has_lod_clamp) { - const u32 arg_pos = [&]() -> u32 { - switch (inst.GetOpcode()) { - case IR::Opcode::ImageSampleImplicitLod: - return 2; - case IR::Opcode::ImageSampleDrefImplicitLod: - return 3; - default: - break; - } - return inst_info.is_depth ? 5 : 4; - }(); - inst.SetArg(arg_pos, arg); - } - if (inst_info.explicit_lod) { - ASSERT(inst.GetOpcode() == IR::Opcode::ImageFetch || - inst.GetOpcode() == IR::Opcode::ImageSampleExplicitLod || - inst.GetOpcode() == IR::Opcode::ImageSampleDrefExplicitLod); - const u32 pos = inst.GetOpcode() == IR::Opcode::ImageSampleExplicitLod ? 2 : 3; - const IR::Value value = inst_info.force_level0 ? ir.Imm32(0.f) : arg; - inst.SetArg(pos, value); - } + // 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) { @@ -672,8 +770,16 @@ void ResourceTrackingPass(IR::Program& program) { PatchBufferInstruction(*block, inst, info, descriptors); continue; } + if (IsTextureBufferInstruction(inst)) { + PatchTextureBufferInstruction(*block, inst, info, descriptors); + continue; + } if (IsImageInstruction(inst)) { PatchImageInstruction(*block, inst, info, descriptors); + continue; + } + if (IsDataRingInstruction(inst)) { + PatchDataRingInstruction(*block, inst, info, descriptors); } } } diff --git a/src/shader_recompiler/ir/passes/ring_access_elimination.cpp b/src/shader_recompiler/ir/passes/ring_access_elimination.cpp new file mode 100644 index 000000000..eb1be2967 --- /dev/null +++ b/src/shader_recompiler/ir/passes/ring_access_elimination.cpp @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "shader_recompiler/ir/ir_emitter.h" +#include "shader_recompiler/ir/opcodes.h" +#include "shader_recompiler/ir/program.h" +#include "shader_recompiler/ir/reg.h" +#include "shader_recompiler/recompiler.h" + +namespace Shader::Optimization { + +void RingAccessElimination(const IR::Program& program, const RuntimeInfo& runtime_info, + Stage stage) { + auto& info = program.info; + + const auto& ForEachInstruction = [&](auto func) { + for (IR::Block* block : program.blocks) { + for (IR::Inst& inst : block->Instructions()) { + IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; + func(ir, inst); + } + } + }; + + switch (stage) { + case Stage::Export: { + ForEachInstruction([=](IR::IREmitter& ir, IR::Inst& inst) { + const auto opcode = inst.GetOpcode(); + switch (opcode) { + case IR::Opcode::StoreBufferU32: { + if (!inst.Flags().ring_access) { + break; + } + + const auto offset = inst.Flags().inst_offset.Value(); + ASSERT(offset < runtime_info.es_info.vertex_data_size * 4); + const auto data = ir.BitCast(IR::U32{inst.Arg(2)}); + const auto attrib = + IR::Value{offset < 16 ? IR::Attribute::Position0 + : IR::Attribute::Param0 + (offset / 16 - 1)}; + const auto comp = (offset / 4) % 4; + + inst.ReplaceOpcode(IR::Opcode::SetAttribute); + inst.ClearArgs(); + inst.SetArg(0, attrib); + inst.SetArg(1, data); + inst.SetArg(2, ir.Imm32(comp)); + break; + } + default: + break; + } + }); + break; + } + case Stage::Geometry: { + const auto& gs_info = runtime_info.gs_info; + info.gs_copy_data = Shader::ParseCopyShader(gs_info.vs_copy); + + ForEachInstruction([&](IR::IREmitter& ir, IR::Inst& inst) { + const auto opcode = inst.GetOpcode(); + switch (opcode) { + case IR::Opcode::LoadBufferU32: { + if (!inst.Flags().ring_access) { + break; + } + + const auto shl_inst = inst.Arg(1).TryInstRecursive(); + const auto vertex_id = shl_inst->Arg(0).Resolve().U32() >> 2; + const auto offset = inst.Arg(1).TryInstRecursive()->Arg(1); + const auto bucket = offset.Resolve().U32() / 256u; + const auto attrib = bucket < 4 ? IR::Attribute::Position0 + : IR::Attribute::Param0 + (bucket / 4 - 1); + const auto comp = bucket % 4; + + auto attr_value = ir.GetAttribute(attrib, comp, vertex_id); + inst.ReplaceOpcode(IR::Opcode::BitCastU32F32); + inst.ClearArgs(); + inst.SetArg(0, attr_value); + break; + } + case IR::Opcode::StoreBufferU32: { + if (!inst.Flags().ring_access) { + break; + } + + const auto offset = inst.Flags().inst_offset.Value(); + const auto data = ir.BitCast(IR::U32{inst.Arg(2)}); + const auto comp_ofs = gs_info.output_vertices * 4u; + const auto output_size = comp_ofs * gs_info.out_vertex_data_size; + + const auto vc_read_ofs = (((offset / comp_ofs) * comp_ofs) % output_size) * 16u; + const auto& it = info.gs_copy_data.attr_map.find(vc_read_ofs); + ASSERT(it != info.gs_copy_data.attr_map.cend()); + const auto& [attr, comp] = it->second; + + inst.ReplaceOpcode(IR::Opcode::SetAttribute); + inst.ClearArgs(); + inst.SetArg(0, IR::Value{attr}); + inst.SetArg(1, data); + inst.SetArg(2, ir.Imm32(comp)); + break; + } + default: + break; + } + }); + break; + } + default: + break; + } +} + +} // namespace Shader::Optimization diff --git a/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp b/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp index 52087a653..e995852d5 100644 --- a/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp +++ b/src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp @@ -8,30 +8,46 @@ namespace Shader::Optimization { void Visit(Info& info, IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::GetAttribute: - case IR::Opcode::GetAttributeU32: { + case IR::Opcode::GetAttributeU32: info.loads.Set(inst.Arg(0).Attribute(), inst.Arg(1).U32()); break; - } - case IR::Opcode::SetAttribute: { + case IR::Opcode::SetAttribute: info.stores.Set(inst.Arg(0).Attribute(), inst.Arg(2).U32()); break; - } + case IR::Opcode::GetUserData: + info.ud_mask.Set(inst.Arg(0).ScalarReg()); + break; case IR::Opcode::LoadSharedU32: case IR::Opcode::LoadSharedU64: case IR::Opcode::WriteSharedU32: case IR::Opcode::WriteSharedU64: info.uses_shared = true; break; + case IR::Opcode::ConvertF16F32: case IR::Opcode::ConvertF32F16: case IR::Opcode::BitCastF16U16: info.uses_fp16 = true; break; + case IR::Opcode::BitCastU64F64: + info.uses_fp64 = true; + break; case IR::Opcode::ImageWrite: info.has_storage_images = true; break; + case IR::Opcode::LoadBufferFormatF32: + info.has_texel_buffers = true; + break; + case IR::Opcode::StoreBufferFormatF32: + info.has_image_buffers = true; + break; case IR::Opcode::QuadShuffle: info.uses_group_quad = true; break; + case IR::Opcode::ReadLane: + case IR::Opcode::ReadFirstLane: + case IR::Opcode::WriteLane: + info.uses_group_ballot = true; + break; case IR::Opcode::Discard: case IR::Opcode::DiscardCond: info.has_discard = true; @@ -44,6 +60,9 @@ void Visit(Info& info, IR::Inst& inst) { case IR::Opcode::ImageQueryLod: info.has_image_query = true; break; + case IR::Opcode::LaneId: + info.uses_lane_id = true; + break; default: break; } diff --git a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp index eef73a659..df73c1bc8 100644 --- a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp @@ -32,8 +32,8 @@ struct SccFlagTag : FlagTag {}; struct ExecFlagTag : FlagTag {}; struct VccFlagTag : FlagTag {}; struct VccLoTag : FlagTag {}; -struct SccLoTag : FlagTag {}; struct VccHiTag : FlagTag {}; +struct M0Tag : FlagTag {}; struct GotoVariable : FlagTag { GotoVariable() = default; @@ -44,8 +44,17 @@ struct GotoVariable : FlagTag { u32 index; }; -using Variant = std::variant; +struct ThreadBitScalar : FlagTag { + ThreadBitScalar() = default; + explicit ThreadBitScalar(IR::ScalarReg sgpr_) : sgpr{sgpr_} {} + + auto operator<=>(const ThreadBitScalar&) const noexcept = default; + + IR::ScalarReg sgpr; +}; + +using Variant = std::variant; using ValueMap = std::unordered_map; struct DefTable { @@ -70,6 +79,13 @@ struct DefTable { goto_vars[variable.index].insert_or_assign(block, value); } + const IR::Value& Def(IR::Block* block, ThreadBitScalar variable) { + return block->ssa_sbit_values[RegIndex(variable.sgpr)]; + } + void SetDef(IR::Block* block, ThreadBitScalar variable, const IR::Value& value) { + block->ssa_sbit_values[RegIndex(variable.sgpr)] = value; + } + const IR::Value& Def(IR::Block* block, SccFlagTag) { return scc_flag[block]; } @@ -84,13 +100,6 @@ struct DefTable { exec_flag.insert_or_assign(block, value); } - const IR::Value& Def(IR::Block* block, SccLoTag) { - return scc_lo_flag[block]; - } - void SetDef(IR::Block* block, SccLoTag, const IR::Value& value) { - scc_lo_flag.insert_or_assign(block, value); - } - const IR::Value& Def(IR::Block* block, VccLoTag) { return vcc_lo_flag[block]; } @@ -111,6 +120,12 @@ struct DefTable { void SetDef(IR::Block* block, VccFlagTag, const IR::Value& value) { vcc_flag.insert_or_assign(block, value); } + const IR::Value& Def(IR::Block* block, M0Tag) { + return m0_flag[block]; + } + void SetDef(IR::Block* block, M0Tag, const IR::Value& value) { + m0_flag.insert_or_assign(block, value); + } std::unordered_map goto_vars; ValueMap scc_flag; @@ -119,6 +134,7 @@ struct DefTable { ValueMap scc_lo_flag; ValueMap vcc_lo_flag; ValueMap vcc_hi_flag; + ValueMap m0_flag; }; IR::Opcode UndefOpcode(IR::ScalarReg) noexcept { @@ -133,11 +149,11 @@ IR::Opcode UndefOpcode(const VccLoTag) noexcept { return IR::Opcode::UndefU32; } -IR::Opcode UndefOpcode(const SccLoTag) noexcept { +IR::Opcode UndefOpcode(const VccHiTag) noexcept { return IR::Opcode::UndefU32; } -IR::Opcode UndefOpcode(const VccHiTag) noexcept { +IR::Opcode UndefOpcode(const M0Tag) noexcept { return IR::Opcode::UndefU32; } @@ -173,7 +189,7 @@ public: } template - IR::Value ReadVariable(Type variable, IR::Block* root_block, bool is_thread_bit = false) { + IR::Value ReadVariable(Type variable, IR::Block* root_block) { boost::container::small_vector, 64> stack{ ReadState(nullptr), ReadState(root_block), @@ -201,7 +217,7 @@ public: } else if (!block->IsSsaSealed()) { // Incomplete CFG IR::Inst* phi{&*block->PrependNewInst(block->begin(), IR::Opcode::Phi)}; - phi->SetFlags(is_thread_bit ? IR::Type::U1 : IR::TypeOf(UndefOpcode(variable))); + phi->SetFlags(IR::TypeOf(UndefOpcode(variable))); incomplete_phis[block].insert_or_assign(variable, phi); stack.back().result = IR::Value{&*phi}; @@ -214,7 +230,7 @@ public: } else { // Break potential cycles with operandless phi IR::Inst* const phi{&*block->PrependNewInst(block->begin(), IR::Opcode::Phi)}; - phi->SetFlags(is_thread_bit ? IR::Type::U1 : IR::TypeOf(UndefOpcode(variable))); + phi->SetFlags(IR::TypeOf(UndefOpcode(variable))); WriteVariable(variable, block, IR::Value{phi}); @@ -263,9 +279,7 @@ private: template IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) { for (IR::Block* const imm_pred : block->ImmPredecessors()) { - const bool is_thread_bit = - std::is_same_v && phi.Flags() == IR::Type::U1; - phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred, is_thread_bit)); + phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred)); } return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable)); } @@ -313,7 +327,11 @@ private: void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { const IR::Opcode opcode{inst.GetOpcode()}; switch (opcode) { - case IR::Opcode::SetThreadBitScalarReg: + case IR::Opcode::SetThreadBitScalarReg: { + const IR::ScalarReg reg{inst.Arg(0).ScalarReg()}; + pass.WriteVariable(ThreadBitScalar{reg}, block, inst.Arg(1)); + break; + } case IR::Opcode::SetScalarRegister: { const IR::ScalarReg reg{inst.Arg(0).ScalarReg()}; pass.WriteVariable(reg, block, inst.Arg(1)); @@ -336,20 +354,24 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::SetVcc: pass.WriteVariable(VccFlagTag{}, block, inst.Arg(0)); break; - case IR::Opcode::SetSccLo: - pass.WriteVariable(SccLoTag{}, block, inst.Arg(0)); - break; case IR::Opcode::SetVccLo: pass.WriteVariable(VccLoTag{}, block, inst.Arg(0)); break; case IR::Opcode::SetVccHi: pass.WriteVariable(VccHiTag{}, block, inst.Arg(0)); break; - case IR::Opcode::GetThreadBitScalarReg: + case IR::Opcode::SetM0: + pass.WriteVariable(M0Tag{}, block, inst.Arg(0)); + break; + case IR::Opcode::GetThreadBitScalarReg: { + const IR::ScalarReg reg{inst.Arg(0).ScalarReg()}; + const IR::Value value = pass.ReadVariable(ThreadBitScalar{reg}, block); + inst.ReplaceUsesWith(value); + break; + } case IR::Opcode::GetScalarRegister: { const IR::ScalarReg reg{inst.Arg(0).ScalarReg()}; - const bool thread_bit = opcode == IR::Opcode::GetThreadBitScalarReg; - const IR::Value value = pass.ReadVariable(reg, block, thread_bit); + const IR::Value value = pass.ReadVariable(reg, block); inst.ReplaceUsesWith(value); break; } @@ -371,15 +393,15 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::GetVcc: inst.ReplaceUsesWith(pass.ReadVariable(VccFlagTag{}, block)); break; - case IR::Opcode::GetSccLo: - inst.ReplaceUsesWith(pass.ReadVariable(SccLoTag{}, block)); - break; case IR::Opcode::GetVccLo: inst.ReplaceUsesWith(pass.ReadVariable(VccLoTag{}, block)); break; case IR::Opcode::GetVccHi: inst.ReplaceUsesWith(pass.ReadVariable(VccHiTag{}, block)); break; + case IR::Opcode::GetM0: + inst.ReplaceUsesWith(pass.ReadVariable(M0Tag{}, block)); + break; default: break; } diff --git a/src/shader_recompiler/ir/program.h b/src/shader_recompiler/ir/program.h index eff933f28..84a1a2d40 100644 --- a/src/shader_recompiler/ir/program.h +++ b/src/shader_recompiler/ir/program.h @@ -5,18 +5,20 @@ #include #include "shader_recompiler/frontend/instruction.h" +#include "shader_recompiler/info.h" #include "shader_recompiler/ir/abstract_syntax_list.h" #include "shader_recompiler/ir/basic_block.h" -#include "shader_recompiler/runtime_info.h" namespace Shader::IR { struct Program { + explicit Program(Info& info_) : info{info_} {} + AbstractSyntaxList syntax_list; BlockList blocks; BlockList post_order_blocks; std::vector ins_list; - Info info; + Info& info; }; [[nodiscard]] std::string DumpProgram(const Program& program); diff --git a/src/shader_recompiler/ir/reg.h b/src/shader_recompiler/ir/reg.h index e3d04260b..d7c0b1db5 100644 --- a/src/shader_recompiler/ir/reg.h +++ b/src/shader_recompiler/ir/reg.h @@ -7,24 +7,9 @@ #include "common/bit_field.h" #include "common/enum.h" #include "common/types.h" -#include "video_core/amdgpu/pixel_format.h" namespace Shader::IR { -enum class FpRoundMode : u32 { - NearestEven = 0, - PlusInf = 1, - MinInf = 2, - ToZero = 3, -}; - -enum class FpDenormMode : u32 { - InOutFlush = 0, - InAllowOutFlush = 1, - InFlushOutAllow = 2, - InOutAllow = 3, -}; - enum class FloatClassFunc : u32 { SignalingNan = 1 << 0, QuietNan = 1 << 1, @@ -42,22 +27,18 @@ enum class FloatClassFunc : u32 { }; DECLARE_ENUM_FLAG_OPERATORS(FloatClassFunc) -union Mode { - BitField<0, 4, FpRoundMode> fp_round; - BitField<4, 2, FpDenormMode> fp_denorm_single; - BitField<6, 2, FpDenormMode> fp_denorm_double; - BitField<8, 1, u32> dx10_clamp; -}; - union TextureInstInfo { u32 raw; BitField<0, 1, u32> is_depth; BitField<1, 1, u32> has_bias; BitField<2, 1, u32> has_lod_clamp; BitField<3, 1, u32> force_level0; - BitField<4, 1, u32> explicit_lod; + BitField<4, 1, u32> has_lod; BitField<5, 1, u32> has_offset; BitField<6, 2, u32> gather_comp; + BitField<8, 1, u32> has_derivatives; + BitField<9, 1, u32> is_array; + BitField<10, 1, u32> is_gather; }; union BufferInstInfo { @@ -65,9 +46,7 @@ union BufferInstInfo { BitField<0, 1, u32> index_enable; BitField<1, 1, u32> offset_enable; BitField<2, 12, u32> inst_offset; - BitField<14, 4, AmdGpu::DataFormat> dmft; - BitField<18, 3, AmdGpu::NumberFormat> nfmt; - BitField<21, 1, u32> is_typed; + BitField<14, 1, u32> ring_access; // global + system coherency }; enum class ScalarReg : u32 { diff --git a/src/shader_recompiler/ir/type.cpp b/src/shader_recompiler/ir/type.cpp index 9d303b4db..08157f108 100644 --- a/src/shader_recompiler/ir/type.cpp +++ b/src/shader_recompiler/ir/type.cpp @@ -9,10 +9,9 @@ namespace Shader::IR { std::string NameOf(Type type) { static constexpr std::array names{ - "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", - "U64", "F16", "F32", "F64", "U32x2", "U32x3", "U32x4", "F16x2", "F16x3", - "F16x4", "F32x2", "F32x3", "F32x4", "F64x2", "F64x3", "F64x4", - }; + "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", + "U64", "F16", "F32", "F64", "U32x2", "U32x3", "U32x4", "F16x2", "F16x3", + "F16x4", "F32x2", "F32x3", "F32x4", "F64x2", "F64x3", "F64x4", "StringLiteral"}; const size_t bits{static_cast(type)}; if (bits == 0) { return "Void"; diff --git a/src/shader_recompiler/ir/type.h b/src/shader_recompiler/ir/type.h index d7f47e1de..ec855a77e 100644 --- a/src/shader_recompiler/ir/type.h +++ b/src/shader_recompiler/ir/type.h @@ -36,6 +36,7 @@ enum class Type { F64x2 = 1 << 22, F64x3 = 1 << 23, F64x4 = 1 << 24, + StringLiteral = 1 << 25, }; DECLARE_ENUM_FLAG_OPERATORS(Type) diff --git a/src/shader_recompiler/ir/value.cpp b/src/shader_recompiler/ir/value.cpp index 9cbb9e7cf..cf7a70f76 100644 --- a/src/shader_recompiler/ir/value.cpp +++ b/src/shader_recompiler/ir/value.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "shader_recompiler/ir/value.h" namespace Shader::IR { @@ -27,6 +28,8 @@ Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {} Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {} +Value::Value(const char* value) noexcept : type{Type::StringLiteral}, string_literal{value} {} + IR::Type Value::Type() const noexcept { if (IsPhi()) { // The type of a phi node is stored in its flags @@ -69,6 +72,8 @@ bool Value::operator==(const Value& other) const { case Type::U64: case Type::F64: return imm_u64 == other.imm_u64; + case Type::StringLiteral: + return std::string_view(string_literal) == other.string_literal; case Type::U32x2: case Type::U32x3: case Type::U32x4: @@ -81,6 +86,7 @@ bool Value::operator==(const Value& other) const { case Type::F64x2: case Type::F64x3: case Type::F64x4: + default: break; } UNREACHABLE_MSG("Invalid type {}", type); diff --git a/src/shader_recompiler/ir/value.h b/src/shader_recompiler/ir/value.h index db939eaa5..a282b9168 100644 --- a/src/shader_recompiler/ir/value.h +++ b/src/shader_recompiler/ir/value.h @@ -39,6 +39,7 @@ public: explicit Value(f32 value) noexcept; explicit Value(u64 value) noexcept; explicit Value(f64 value) noexcept; + explicit Value(const char* value) noexcept; [[nodiscard]] bool IsIdentity() const noexcept; [[nodiscard]] bool IsPhi() const noexcept; @@ -60,6 +61,7 @@ public: [[nodiscard]] f32 F32() const; [[nodiscard]] u64 U64() const; [[nodiscard]] f64 F64() const; + [[nodiscard]] const char* StringLiteral() const; [[nodiscard]] bool operator==(const Value& other) const; [[nodiscard]] bool operator!=(const Value& other) const; @@ -78,6 +80,7 @@ private: f32 imm_f32; u64 imm_u64; f64 imm_f64; + const char* string_literal; }; }; static_assert(static_cast(IR::Type::Void) == 0, "memset relies on IR::Type being zero"); @@ -206,7 +209,7 @@ private: union { NonTriviallyDummy dummy{}; boost::container::small_vector, 2> phi_args; - std::array args; + std::array args; }; }; static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased"); @@ -348,6 +351,14 @@ inline f64 Value::F64() const { return imm_f64; } +inline const char* Value::StringLiteral() const { + if (IsIdentity()) { + return inst->Arg(0).StringLiteral(); + } + DEBUG_ASSERT(type == Type::StringLiteral); + return string_literal; +} + [[nodiscard]] inline bool IsPhi(const Inst& inst) { return inst.GetOpcode() == Opcode::Phi; } diff --git a/src/shader_recompiler/params.h b/src/shader_recompiler/params.h new file mode 100644 index 000000000..0dce9a0f3 --- /dev/null +++ b/src/shader_recompiler/params.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/types.h" + +namespace Shader { + +/** + * Compilation parameters used to identify and locate a guest shader program. + */ +struct ShaderParams { + static constexpr u32 NumShaderUserData = 16; + + std::span user_data; + std::span code; + u64 hash; + + VAddr Base() const noexcept { + return reinterpret_cast(code.data()); + } +}; + +} // namespace Shader diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index badd54554..bbda731e0 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -19,13 +19,8 @@ struct Profile { bool support_float_controls{}; bool support_separate_denorm_behavior{}; bool support_separate_rounding_mode{}; - bool support_fp16_denorm_preserve{}; bool support_fp32_denorm_preserve{}; - bool support_fp16_denorm_flush{}; bool support_fp32_denorm_flush{}; - bool support_fp16_signed_zero_nan_preserve{}; - bool support_fp32_signed_zero_nan_preserve{}; - bool support_fp64_signed_zero_nan_preserve{}; bool support_explicit_workgroup_layout{}; bool has_broken_spirv_clamp{}; bool lower_left_origin_mode{}; diff --git a/src/shader_recompiler/recompiler.cpp b/src/shader_recompiler/recompiler.cpp index 0f9fd6d41..e13e5d009 100644 --- a/src/shader_recompiler/recompiler.cpp +++ b/src/shader_recompiler/recompiler.cpp @@ -6,6 +6,7 @@ #include "shader_recompiler/frontend/structured_control_flow.h" #include "shader_recompiler/ir/passes/ir_passes.h" #include "shader_recompiler/ir/post_order.h" +#include "shader_recompiler/recompiler.h" namespace Shader { @@ -27,44 +28,46 @@ IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { return blocks; } -IR::Program TranslateProgram(Common::ObjectPool& inst_pool, - Common::ObjectPool& block_pool, std::span token, - const Info&& info, const Profile& profile) { +IR::Program TranslateProgram(std::span code, Pools& pools, Info& info, + const RuntimeInfo& runtime_info, const Profile& profile) { // Ensure first instruction is expected. constexpr u32 token_mov_vcchi = 0xBEEB03FF; - ASSERT_MSG(token[0] == token_mov_vcchi, "First instruction is not s_mov_b32 vcc_hi, #imm"); + ASSERT_MSG(code[0] == token_mov_vcchi, "First instruction is not s_mov_b32 vcc_hi, #imm"); - Gcn::GcnCodeSlice slice(token.data(), token.data() + token.size()); + Gcn::GcnCodeSlice slice(code.data(), code.data() + code.size()); Gcn::GcnDecodeContext decoder; // Decode and save instructions - IR::Program program; - program.ins_list.reserve(token.size()); + IR::Program program{info}; + program.ins_list.reserve(code.size()); while (!slice.atEnd()) { program.ins_list.emplace_back(decoder.decodeInstruction(slice)); } + // Clear any previous pooled data. + pools.ReleaseContents(); + // Create control flow graph Common::ObjectPool gcn_block_pool{64}; Gcn::CFG cfg{gcn_block_pool, program.ins_list}; // Structurize control flow graph and create program. - program.info = std::move(info); - program.syntax_list = Shader::Gcn::BuildASL(inst_pool, block_pool, cfg, program.info, profile); + program.syntax_list = Shader::Gcn::BuildASL(pools.inst_pool, pools.block_pool, cfg, + program.info, runtime_info, profile); program.blocks = GenerateBlocks(program.syntax_list); program.post_order_blocks = Shader::IR::PostOrder(program.syntax_list.front()); // Run optimization passes Shader::Optimization::SsaRewritePass(program.post_order_blocks); - Shader::Optimization::ResourceTrackingPass(program); Shader::Optimization::ConstantPropagationPass(program.post_order_blocks); if (program.info.stage != Stage::Compute) { Shader::Optimization::LowerSharedMemToRegisters(program); } + Shader::Optimization::RingAccessElimination(program, runtime_info, program.info.stage); + Shader::Optimization::ResourceTrackingPass(program); Shader::Optimization::IdentityRemovalPass(program.blocks); Shader::Optimization::DeadCodeEliminationPass(program); Shader::Optimization::CollectShaderInfoPass(program); - LOG_DEBUG(Render_Vulkan, "{}", Shader::IR::DumpProgram(program)); return program; } diff --git a/src/shader_recompiler/recompiler.h b/src/shader_recompiler/recompiler.h index 34e958a15..f8acf6c9e 100644 --- a/src/shader_recompiler/recompiler.h +++ b/src/shader_recompiler/recompiler.h @@ -10,10 +10,24 @@ namespace Shader { struct Profile; +struct RuntimeInfo; -[[nodiscard]] IR::Program TranslateProgram(Common::ObjectPool& inst_pool, - Common::ObjectPool& block_pool, - std::span code, const Info&& info, - const Profile& profile); +struct Pools { + static constexpr u32 InstPoolSize = 8192; + static constexpr u32 BlockPoolSize = 32; + + Common::ObjectPool inst_pool; + Common::ObjectPool block_pool; + + explicit Pools() : inst_pool{InstPoolSize}, block_pool{BlockPoolSize} {} + + void ReleaseContents() { + inst_pool.ReleaseContents(); + block_pool.ReleaseContents(); + } +}; + +[[nodiscard]] IR::Program TranslateProgram(std::span code, Pools& pools, Info& info, + const RuntimeInfo& runtime_info, const Profile& profile); } // namespace Shader diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index b1eb6aea7..03936f3a8 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -3,19 +3,14 @@ #pragma once +#include #include #include -#include "common/assert.h" #include "common/types.h" -#include "shader_recompiler/ir/attribute.h" -#include "shader_recompiler/ir/reg.h" -#include "shader_recompiler/ir/type.h" -#include "video_core/amdgpu/resource.h" +#include "video_core/amdgpu/types.h" namespace Shader { -static constexpr size_t NumUserDataRegs = 16; - enum class Stage : u32 { Fragment, Vertex, @@ -28,21 +23,16 @@ enum class Stage : u32 { constexpr u32 MaxStageTypes = 6; [[nodiscard]] constexpr Stage StageFromIndex(size_t index) noexcept { - return static_cast(static_cast(Stage::Vertex) + index); + return static_cast(index); } -enum class TextureType : u32 { - Color1D, - ColorArray1D, - Color2D, - ColorArray2D, - Color3D, - ColorCube, - Buffer, -}; -constexpr u32 NUM_TEXTURE_TYPES = 7; +struct ExportRuntimeInfo { + u32 vertex_data_size; -enum class VsOutput : u32 { + auto operator<=>(const ExportRuntimeInfo&) const noexcept = default; +}; + +enum class VsOutput : u8 { None, PointSprite, EdgeFlag, @@ -69,166 +59,121 @@ enum class VsOutput : u32 { }; using VsOutputMap = std::array; -struct Info; +struct VertexRuntimeInfo { + u32 num_outputs; + std::array outputs; + bool emulate_depth_negative_one_to_one{}; -struct BufferResource { - u32 sgpr_base; - u32 dword_offset; - u32 length; - IR::Type used_types; - AmdGpu::Buffer inline_cbuf; - AmdGpu::DataFormat dfmt; - AmdGpu::NumberFormat nfmt; - bool is_storage{}; - bool is_instance_data{}; - bool is_written{}; - - constexpr AmdGpu::Buffer GetVsharp(const Info& info) const noexcept; -}; -using BufferResourceList = boost::container::static_vector; - -struct ImageResource { - u32 sgpr_base; - u32 dword_offset; - AmdGpu::ImageType type; - AmdGpu::NumberFormat nfmt; - bool is_storage; - bool is_depth; -}; -using ImageResourceList = boost::container::static_vector; - -struct SamplerResource { - u32 sgpr_base; - u32 dword_offset; - AmdGpu::Sampler inline_sampler{}; - u32 associated_image : 4; - u32 disable_aniso : 1; - - constexpr AmdGpu::Sampler GetSsharp(const Info& info) const noexcept; -}; -using SamplerResourceList = boost::container::static_vector; - -struct PushData { - static constexpr size_t BufOffsetIndex = 2; - - u32 step0; - u32 step1; - std::array buf_offsets; - - void AddOffset(u32 binding, u32 offset) { - ASSERT(offset < 256 && binding < buf_offsets.size()); - buf_offsets[binding] = offset; + bool operator==(const VertexRuntimeInfo& other) const noexcept { + return emulate_depth_negative_one_to_one == other.emulate_depth_negative_one_to_one; } }; -struct Info { - struct VsInput { - enum InstanceIdType : u8 { - None = 0, - OverStepRate0 = 1, - OverStepRate1 = 2, - Plain = 3, - }; +static constexpr auto GsMaxOutputStreams = 4u; +using GsOutputPrimTypes = std::array; +struct GeometryRuntimeInfo { + u32 num_invocations{}; + u32 output_vertices{}; + u32 in_vertex_data_size{}; + u32 out_vertex_data_size{}; + AmdGpu::PrimitiveType in_primitive; + GsOutputPrimTypes out_primitive; + std::span vs_copy; + u64 vs_copy_hash; - AmdGpu::NumberFormat fmt; - u16 binding; - u16 num_components; - u8 sgpr_base; - u8 dword_offset; - InstanceIdType instance_step_rate; - s32 instance_data_buf; - }; - boost::container::static_vector vs_inputs{}; + bool operator==(const GeometryRuntimeInfo& other) const noexcept { + return num_invocations && other.num_invocations && + output_vertices == other.output_vertices && in_primitive == other.in_primitive && + std::ranges::equal(out_primitive, other.out_primitive); + } +}; +enum class MrtSwizzle : u8 { + Identity = 0, + Alt = 1, + Reverse = 2, + ReverseAlt = 3, +}; +static constexpr u32 MaxColorBuffers = 8; + +struct FragmentRuntimeInfo { struct PsInput { - u32 param_index; + u8 param_index; bool is_default; bool is_flat; - u32 default_value; + u8 default_value; + + auto operator<=>(const PsInput&) const noexcept = default; }; - boost::container::static_vector ps_inputs{}; + u32 num_inputs; + std::array inputs; + struct PsColorBuffer { + AmdGpu::NumberFormat num_format; + MrtSwizzle mrt_swizzle; - struct AttributeFlags { - bool Get(IR::Attribute attrib, u32 comp = 0) const { - return flags[Index(attrib)] & (1 << comp); - } - - bool GetAny(IR::Attribute attrib) const { - return flags[Index(attrib)]; - } - - void Set(IR::Attribute attrib, u32 comp = 0) { - flags[Index(attrib)] |= (1 << comp); - } - - u32 NumComponents(IR::Attribute attrib) const { - return 4; - } - - static size_t Index(IR::Attribute attrib) { - return static_cast(attrib); - } - - std::array flags; + auto operator<=>(const PsColorBuffer&) const noexcept = default; }; - AttributeFlags loads{}; - AttributeFlags stores{}; - boost::container::static_vector vs_outputs; + std::array color_buffers; - BufferResourceList buffers; - ImageResourceList images; - SamplerResourceList samplers; + bool operator==(const FragmentRuntimeInfo& other) const noexcept { + return std::ranges::equal(color_buffers, other.color_buffers) && + num_inputs == other.num_inputs && + std::ranges::equal(inputs.begin(), inputs.begin() + num_inputs, other.inputs.begin(), + other.inputs.begin() + num_inputs); + } +}; - std::array workgroup_size{}; +struct ComputeRuntimeInfo { + u32 shared_memory_size; + std::array workgroup_size; std::array tgid_enable; + bool operator==(const ComputeRuntimeInfo& other) const noexcept { + return workgroup_size == other.workgroup_size && tgid_enable == other.tgid_enable; + } +}; + +/** + * Stores information relevant to shader compilation sourced from liverpool registers. + * It may potentially differ with the same shader module so must be checked. + * It's also possible to store any other custom information that needs to be part of shader key. + */ +struct RuntimeInfo { + Stage stage; u32 num_user_data; u32 num_input_vgprs; - std::span user_data; - Stage stage; + u32 num_allocated_vgprs; + AmdGpu::FpDenormMode fp_denorm_mode32; + AmdGpu::FpRoundMode fp_round_mode32; + union { + ExportRuntimeInfo es_info; + VertexRuntimeInfo vs_info; + GeometryRuntimeInfo gs_info; + FragmentRuntimeInfo fs_info; + ComputeRuntimeInfo cs_info; + }; - uintptr_t pgm_base{}; - u64 pgm_hash{}; - u32 shared_memory_size{}; - bool has_storage_images{}; - bool has_discard{}; - bool has_image_gather{}; - bool has_image_query{}; - bool uses_group_quad{}; - bool uses_shared{}; - bool uses_fp16{}; - bool uses_step_rates{}; - bool translation_failed{}; // indicates that shader has unsupported instructions + RuntimeInfo(Stage stage_) { + memset(this, 0, sizeof(*this)); + stage = stage_; + } - template - T ReadUd(u32 ptr_index, u32 dword_offset) const noexcept { - T data; - const u32* base = user_data.data(); - if (ptr_index != IR::NumScalarRegs) { - std::memcpy(&base, &user_data[ptr_index], sizeof(base)); + bool operator==(const RuntimeInfo& other) const noexcept { + switch (stage) { + case Stage::Fragment: + return fs_info == other.fs_info; + case Stage::Vertex: + return vs_info == other.vs_info; + case Stage::Compute: + return cs_info == other.cs_info; + case Stage::Export: + return es_info == other.es_info; + case Stage::Geometry: + return gs_info == other.gs_info; + default: + return true; } - std::memcpy(&data, base + dword_offset, sizeof(T)); - return data; } }; -constexpr AmdGpu::Buffer BufferResource::GetVsharp(const Info& info) const noexcept { - return inline_cbuf ? inline_cbuf : info.ReadUd(sgpr_base, dword_offset); -} - -constexpr AmdGpu::Sampler SamplerResource::GetSsharp(const Info& info) const noexcept { - return inline_sampler ? inline_sampler : info.ReadUd(sgpr_base, dword_offset); -} - } // namespace Shader - -template <> -struct fmt::formatter { - constexpr auto parse(format_parse_context& ctx) { - return ctx.begin(); - } - auto format(const Shader::Stage stage, format_context& ctx) const { - constexpr static std::array names = {"fs", "vs", "gs", "es", "hs", "ls", "cs"}; - return fmt::format_to(ctx.out(), "{}", names[static_cast(stage)]); - } -}; diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h new file mode 100644 index 000000000..0a3a696bc --- /dev/null +++ b/src/shader_recompiler/specialization.h @@ -0,0 +1,112 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/types.h" +#include "shader_recompiler/backend/bindings.h" +#include "shader_recompiler/info.h" + +namespace Shader { + +struct BufferSpecialization { + u16 stride : 14; + u16 is_storage : 1; + + auto operator<=>(const BufferSpecialization&) const = default; +}; + +struct TextureBufferSpecialization { + bool is_integer = false; + + auto operator<=>(const TextureBufferSpecialization&) const = default; +}; + +struct ImageSpecialization { + AmdGpu::ImageType type = AmdGpu::ImageType::Color2D; + bool is_integer = false; + + auto operator<=>(const ImageSpecialization&) const = default; +}; + +/** + * Alongside runtime information, this structure also checks bound resources + * for compatibility. Can be used as a key for storing shader permutations. + * Is separate from runtime information, because resource layout can only be deduced + * after the first compilation of a module. + */ +struct StageSpecialization { + static constexpr size_t MaxStageResources = 64; + + const Shader::Info* info; + RuntimeInfo runtime_info; + std::bitset bitset{}; + boost::container::small_vector buffers; + boost::container::small_vector tex_buffers; + boost::container::small_vector images; + Backend::Bindings start{}; + + explicit StageSpecialization(const Shader::Info& info_, RuntimeInfo runtime_info_, + Backend::Bindings start_) + : info{&info_}, runtime_info{runtime_info_}, start{start_} { + u32 binding{}; + ForEachSharp(binding, buffers, info->buffers, + [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { + spec.stride = sharp.GetStride(); + spec.is_storage = desc.IsStorage(sharp); + }); + ForEachSharp(binding, tex_buffers, info->texture_buffers, + [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { + spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); + }); + ForEachSharp(binding, images, info->images, + [](auto& spec, const auto& desc, AmdGpu::Image sharp) { + spec.type = sharp.IsPartialCubemap() ? AmdGpu::ImageType::Color2DArray + : sharp.GetType(); + spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); + }); + } + + void ForEachSharp(u32& binding, auto& spec_list, auto& desc_list, auto&& func) { + for (const auto& desc : desc_list) { + auto& spec = spec_list.emplace_back(); + const auto sharp = desc.GetSharp(*info); + if (!sharp) { + binding++; + continue; + } + bitset.set(binding++); + func(spec, desc, sharp); + } + } + + bool operator==(const StageSpecialization& other) const { + if (start != other.start) { + return false; + } + if (runtime_info != other.runtime_info) { + return false; + } + u32 binding{}; + for (u32 i = 0; i < buffers.size(); i++) { + if (other.bitset[binding++] && buffers[i] != other.buffers[i]) { + return false; + } + } + for (u32 i = 0; i < tex_buffers.size(); i++) { + if (other.bitset[binding++] && tex_buffers[i] != other.tex_buffers[i]) { + return false; + } + } + for (u32 i = 0; i < images.size(); i++) { + if (other.bitset[binding++] && images[i] != other.images[i]) { + return false; + } + } + return true; + } +}; + +} // namespace Shader diff --git a/src/shadps4.qrc b/src/shadps4.qrc index c22b837bd..a59cb0621 100644 --- a/src/shadps4.qrc +++ b/src/shadps4.qrc @@ -2,6 +2,7 @@ images/shadps4.ico images/about_icon.png + images/dump_icon.png images/play_icon.png images/pause_icon.png images/stop_icon.png @@ -15,6 +16,7 @@ images/settings_icon.png images/controller_icon.png images/refresh_icon.png + images/update_icon.png images/list_mode_icon.png images/flag_jp.png images/flag_eu.png diff --git a/src/video_core/amdgpu/default_context.cpp b/src/video_core/amdgpu/default_context.cpp new file mode 100644 index 000000000..01229e7b1 --- /dev/null +++ b/src/video_core/amdgpu/default_context.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/types.h" +#include "video_core/amdgpu/liverpool.h" + +#include + +namespace AmdGpu { + +// The following values are taken from fpPS4: +// https://github.com/red-prig/fpPS4/blob/436b43064be4c78229500f3d3c054fc76639247d/chip/pm4_pfp.pas#L410 +// +static constexpr std::array reg_array_default{ + 0x00000000u, 0x80000000u, 0x40004000u, 0xdeadbeefu, 0x00000000u, 0x40004000u, 0x00000000u, + 0x40004000u, 0x00000000u, 0x40004000u, 0x00000000u, 0x40004000u, 0xaa99aaaau, 0x00000000u, + 0xdeadbeefu, 0xdeadbeefu, 0x80000000u, 0x40004000u, 0x00000000u, 0x00000000u, 0x80000000u, + 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, + 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, + 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, + 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, 0x40004000u, 0x80000000u, + 0x40004000u, 0x80000000u, 0x40004000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, + 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, + 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, + 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, + 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, 0x00000000u, 0x3f800000u, + 0x2a00161au, +}; + +void Liverpool::Regs::SetDefaults() { + std::memset(reg_array.data(), 0, reg_array.size() * sizeof(u32)); + + std::memcpy(®_array[ContextRegWordOffset + 0x80], reg_array_default.data(), + reg_array_default.size() * sizeof(u32)); + + // Individual context regs values + reg_array[ContextRegWordOffset + 0x000d] = 0x40004000u; + reg_array[ContextRegWordOffset + 0x01b6] = 0x00000002u; + reg_array[ContextRegWordOffset + 0x0204] = 0x00090000u; + reg_array[ContextRegWordOffset + 0x0205] = 0x00000004u; + reg_array[ContextRegWordOffset + 0x0295] = 0x00000100u; + reg_array[ContextRegWordOffset + 0x0296] = 0x00000080u; + reg_array[ContextRegWordOffset + 0x0297] = 0x00000002u; + reg_array[ContextRegWordOffset + 0x02aa] = 0x00001000u; + reg_array[ContextRegWordOffset + 0x02f7] = 0x00001000u; + reg_array[ContextRegWordOffset + 0x02f9] = 0x00000005u; + reg_array[ContextRegWordOffset + 0x02fa] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x02fb] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x02fc] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x02fd] = 0x3f800000u; + reg_array[ContextRegWordOffset + 0x0316] = 0x0000000eu; + reg_array[ContextRegWordOffset + 0x0317] = 0x00000010u; +} + +} // namespace AmdGpu diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index dce2d4b42..7b4727088 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -2,9 +2,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "common/config.h" #include "common/debug.h" #include "common/polyfill_thread.h" #include "common/thread.h" +#include "core/debug_state.h" #include "core/libraries/videoout/driver.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/pm4_cmds.h" @@ -19,6 +21,20 @@ static const char* acb_task_name{"ACB_TASK"}; std::array Liverpool::ConstantEngine::constants_heap; +static std::span NextPacket(std::span span, size_t offset) { + if (offset > span.size()) { + LOG_ERROR( + Lib_GnmDriver, + ": packet length exceeds remaining submission size. Packet dword count={}, remaining " + "submission dwords={}", + offset, span.size()); + // Return empty subspan so check for next packet bails out + return {}; + } + + return span.subspan(offset); +} + Liverpool::Liverpool() { process_thread = std::jthread{std::bind_front(&Liverpool::Process, this)}; } @@ -29,7 +45,7 @@ Liverpool::~Liverpool() { } void Liverpool::Process(std::stop_token stoken) { - Common::SetCurrentThreadName("GPU_CommandProcessor"); + Common::SetCurrentThreadName("shadPS4:GPU_CommandProcessor"); while (!stoken.stop_requested()) { { @@ -149,7 +165,7 @@ Liverpool::Task Liverpool::ProcessCeUpdate(std::span ccb) { UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", static_cast(opcode), count); } - ccb = ccb.subspan(header->type3.NumWords() + 1); + ccb = NextPacket(ccb, header->type3.NumWords() + 1); } TracyFiberLeave; @@ -172,293 +188,406 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(dcb.data()); while (!dcb.empty()) { const auto* header = reinterpret_cast(dcb.data()); const u32 type = header->type; - if (type != 3) { - // No other types of packets were spotted so far - UNREACHABLE_MSG("Invalid PM4 type {}", type); - } - const u32 count = header->type3.NumWords(); - const PM4ItOpcode opcode = header->type3.opcode; - switch (opcode) { - case PM4ItOpcode::Nop: { - const auto* nop = reinterpret_cast(header); - if (nop->header.count.Value() == 0) { - break; - } - - switch (nop->data_block[0]) { - case PM4CmdNop::PayloadType::PatchedFlip: { - // There is no evidence that GPU CP drives flip events by parsing - // special NOP packets. For convenience lets assume that it does. - Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxFlip); - break; - } - case PM4CmdNop::PayloadType::DebugMarkerPush: { - const auto marker_sz = nop->header.count.Value() * 2; - const std::string_view label{reinterpret_cast(&nop->data_block[1]), - marker_sz}; - rasterizer->ScopeMarkerBegin(label); - break; - } - case PM4CmdNop::PayloadType::DebugMarkerPop: { - rasterizer->ScopeMarkerEnd(); - break; - } - default: - break; - } + switch (type) { + case 0: + case 1: + UNREACHABLE_MSG("Unsupported PM4 type {}", type); break; - } - case PM4ItOpcode::ContextControl: { - break; - } - case PM4ItOpcode::ClearState: { - break; - } - case PM4ItOpcode::SetConfigReg: { - const auto* set_data = reinterpret_cast(header); - const auto reg_addr = ConfigRegWordOffset + set_data->reg_offset; - const auto* payload = reinterpret_cast(header + 2); - std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); - break; - } - case PM4ItOpcode::SetContextReg: { - const auto* set_data = reinterpret_cast(header); - const auto reg_addr = ContextRegWordOffset + set_data->reg_offset; - const auto* payload = reinterpret_cast(header + 2); + case 2: + // Type-2 packet are used for padding purposes + dcb = NextPacket(dcb, 1); + continue; + case 3: + const u32 count = header->type3.NumWords(); + const PM4ItOpcode opcode = header->type3.opcode; + switch (opcode) { + case PM4ItOpcode::Nop: { + const auto* nop = reinterpret_cast(header); + if (nop->header.count.Value() == 0) { + break; + } - std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); - - // In the case of HW, render target memory has alignment as color block operates on - // tiles. There is no information of actual resource extents stored in CB context - // regs, so any deduction of it from slices/pitch will lead to a larger surface created. - // The same applies to the depth targets. Fortunately, the guest always sends - // a trailing NOP packet right after the context regs setup, so we can use the heuristic - // below and extract the hint to determine actual resource dims. - - switch (reg_addr) { - case ContextRegs::CbColor0Base: - case ContextRegs::CbColor1Base: - case ContextRegs::CbColor2Base: - case ContextRegs::CbColor3Base: - case ContextRegs::CbColor4Base: - case ContextRegs::CbColor5Base: - case ContextRegs::CbColor6Base: - case ContextRegs::CbColor7Base: { - const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Base) / - (ContextRegs::CbColor1Base - ContextRegs::CbColor0Base); - ASSERT(col_buf_id < NumColorBuffers); - - const auto nop_offset = header->type3.count; - if (nop_offset == 0x0e || nop_offset == 0x0d || nop_offset == 0x0b) { - ASSERT_MSG(payload[nop_offset] == 0xc0001000, - "NOP hint is missing in CB setup sequence"); - last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; - } else { - last_cb_extent[col_buf_id].raw = 0; + switch (nop->data_block[0]) { + case PM4CmdNop::PayloadType::PatchedFlip: { + // There is no evidence that GPU CP drives flip events by parsing + // special NOP packets. For convenience lets assume that it does. + Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxFlip); + break; + } + case PM4CmdNop::PayloadType::DebugMarkerPush: { + const auto marker_sz = nop->header.count.Value() * 2; + const std::string_view label{reinterpret_cast(&nop->data_block[1]), + marker_sz}; + if (rasterizer) { + rasterizer->ScopeMarkerBegin(label); + } + break; + } + case PM4CmdNop::PayloadType::DebugColorMarkerPush: { + const auto marker_sz = nop->header.count.Value() * 2; + const std::string_view label{reinterpret_cast(&nop->data_block[1]), + marker_sz}; + const u32 color = *reinterpret_cast( + reinterpret_cast(&nop->data_block[1]) + marker_sz); + if (rasterizer) { + rasterizer->ScopedMarkerInsertColor(label, color); + } + break; + } + case PM4CmdNop::PayloadType::DebugMarkerPop: { + if (rasterizer) { + rasterizer->ScopeMarkerEnd(); + } + break; + } + default: + break; } break; } - case ContextRegs::CbColor0Cmask: - case ContextRegs::CbColor1Cmask: - case ContextRegs::CbColor2Cmask: - case ContextRegs::CbColor3Cmask: - case ContextRegs::CbColor4Cmask: - case ContextRegs::CbColor5Cmask: - case ContextRegs::CbColor6Cmask: - case ContextRegs::CbColor7Cmask: { - const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Cmask) / - (ContextRegs::CbColor1Cmask - ContextRegs::CbColor0Cmask); - ASSERT(col_buf_id < NumColorBuffers); + case PM4ItOpcode::ContextControl: { + break; + } + case PM4ItOpcode::ClearState: { + regs.SetDefaults(); + break; + } + case PM4ItOpcode::SetConfigReg: { + const auto* set_data = reinterpret_cast(header); + const auto reg_addr = ConfigRegWordOffset + set_data->reg_offset; + const auto* payload = reinterpret_cast(header + 2); + std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); + break; + } + case PM4ItOpcode::SetContextReg: { + const auto* set_data = reinterpret_cast(header); + const auto reg_addr = ContextRegWordOffset + set_data->reg_offset; + const auto* payload = reinterpret_cast(header + 2); - const auto nop_offset = header->type3.count; - if (nop_offset == 0x04) { - ASSERT_MSG(payload[nop_offset] == 0xc0001000, - "NOP hint is missing in CB setup sequence"); - last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; + std::memcpy(®s.reg_array[reg_addr], payload, (count - 1) * sizeof(u32)); + + // In the case of HW, render target memory has alignment as color block operates on + // tiles. There is no information of actual resource extents stored in CB context + // regs, so any deduction of it from slices/pitch will lead to a larger surface + // created. The same applies to the depth targets. Fortunately, the guest always + // sends a trailing NOP packet right after the context regs setup, so we can use the + // heuristic below and extract the hint to determine actual resource dims. + + switch (reg_addr) { + case ContextRegs::CbColor0Base: + case ContextRegs::CbColor1Base: + case ContextRegs::CbColor2Base: + case ContextRegs::CbColor3Base: + case ContextRegs::CbColor4Base: + case ContextRegs::CbColor5Base: + case ContextRegs::CbColor6Base: + case ContextRegs::CbColor7Base: { + const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Base) / + (ContextRegs::CbColor1Base - ContextRegs::CbColor0Base); + ASSERT(col_buf_id < NumColorBuffers); + + const auto nop_offset = header->type3.count; + if (nop_offset == 0x0e || nop_offset == 0x0d || nop_offset == 0x0b) { + ASSERT_MSG(payload[nop_offset] == 0xc0001000, + "NOP hint is missing in CB setup sequence"); + last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; + } else { + last_cb_extent[col_buf_id].raw = 0; + } + break; + } + case ContextRegs::CbColor0Cmask: + case ContextRegs::CbColor1Cmask: + case ContextRegs::CbColor2Cmask: + case ContextRegs::CbColor3Cmask: + case ContextRegs::CbColor4Cmask: + case ContextRegs::CbColor5Cmask: + case ContextRegs::CbColor6Cmask: + case ContextRegs::CbColor7Cmask: { + const auto col_buf_id = + (reg_addr - ContextRegs::CbColor0Cmask) / + (ContextRegs::CbColor1Cmask - ContextRegs::CbColor0Cmask); + ASSERT(col_buf_id < NumColorBuffers); + + const auto nop_offset = header->type3.count; + if (nop_offset == 0x04) { + ASSERT_MSG(payload[nop_offset] == 0xc0001000, + "NOP hint is missing in CB setup sequence"); + last_cb_extent[col_buf_id].raw = payload[nop_offset + 1]; + } + break; + } + case ContextRegs::DbZInfo: { + if (header->type3.count == 8) { + ASSERT_MSG(payload[20] == 0xc0001000, + "NOP hint is missing in DB setup sequence"); + last_db_extent.raw = payload[21]; + } else { + last_db_extent.raw = 0; + } + break; + } + default: + break; } break; } - case ContextRegs::DbZInfo: { - if (header->type3.count == 8) { - ASSERT_MSG(payload[20] == 0xc0001000, - "NOP hint is missing in DB setup sequence"); - last_db_extent.raw = payload[21]; + case PM4ItOpcode::SetShReg: { + const auto* set_data = reinterpret_cast(header); + std::memcpy(®s.reg_array[ShRegWordOffset + set_data->reg_offset], header + 2, + (count - 1) * sizeof(u32)); + break; + } + case PM4ItOpcode::SetUconfigReg: { + const auto* set_data = reinterpret_cast(header); + std::memcpy(®s.reg_array[UconfigRegWordOffset + set_data->reg_offset], + header + 2, (count - 1) * sizeof(u32)); + break; + } + case PM4ItOpcode::IndexType: { + const auto* index_type = reinterpret_cast(header); + regs.index_buffer_type.raw = index_type->raw; + break; + } + case PM4ItOpcode::DrawIndex2: { + const auto* draw_index = reinterpret_cast(header); + regs.max_index_size = draw_index->max_size; + regs.index_base_address.base_addr_lo = draw_index->index_base_lo; + regs.index_base_address.base_addr_hi.Assign(draw_index->index_base_hi); + regs.num_indices = draw_index->index_count; + regs.draw_initiator = draw_index->draw_initiator; + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + } + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndex2", cmd_address)); + rasterizer->Draw(true); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndexOffset2: { + const auto* draw_index_off = + reinterpret_cast(header); + regs.max_index_size = draw_index_off->max_size; + regs.num_indices = draw_index_off->index_count; + regs.draw_initiator = draw_index_off->draw_initiator; + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + } + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin( + fmt::format("dcb:{}:DrawIndexOffset2", cmd_address)); + rasterizer->Draw(true, draw_index_off->index_offset); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndexAuto: { + const auto* draw_index = reinterpret_cast(header); + regs.num_indices = draw_index->index_count; + regs.draw_initiator = draw_index->draw_initiator; + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + } + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexAuto", cmd_address)); + rasterizer->Draw(false); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndirect: { + const auto* draw_indirect = reinterpret_cast(header); + const auto offset = draw_indirect->data_offset; + const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; + const auto size = sizeof(PM4CmdDrawIndirect::DrawInstancedArgs); + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + } + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndirect", cmd_address)); + rasterizer->DrawIndirect(false, ib_address, offset, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DrawIndexIndirect: { + const auto* draw_index_indirect = + reinterpret_cast(header); + const auto offset = draw_index_indirect->data_offset; + const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; + const auto size = sizeof(PM4CmdDrawIndexIndirect::DrawIndexInstancedArgs); + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + } + if (rasterizer) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin( + fmt::format("dcb:{}:DrawIndexIndirect", cmd_address)); + rasterizer->DrawIndirect(true, ib_address, offset, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DispatchDirect: { + const auto* dispatch_direct = reinterpret_cast(header); + regs.cs_program.dim_x = dispatch_direct->dim_x; + regs.cs_program.dim_y = dispatch_direct->dim_y; + regs.cs_program.dim_z = dispatch_direct->dim_z; + regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs, + true); + } + if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:Dispatch", cmd_address)); + rasterizer->DispatchDirect(); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::DispatchIndirect: { + const auto* dispatch_indirect = + reinterpret_cast(header); + const auto offset = dispatch_indirect->data_offset; + const auto ib_address = mapped_queues[GfxQueueId].indirect_args_addr; + const auto size = sizeof(PM4CmdDispatchIndirect::GroupDimensions); + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs, + true); + } + if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarkerBegin( + fmt::format("dcb:{}:DispatchIndirect", cmd_address)); + rasterizer->DispatchIndirect(ib_address, offset, size); + rasterizer->ScopeMarkerEnd(); + } + break; + } + case PM4ItOpcode::NumInstances: { + const auto* num_instances = reinterpret_cast(header); + regs.num_instances.num_instances = num_instances->num_instances; + break; + } + case PM4ItOpcode::IndexBase: { + const auto* index_base = reinterpret_cast(header); + regs.index_base_address.base_addr_lo = index_base->addr_lo; + regs.index_base_address.base_addr_hi.Assign(index_base->addr_hi); + break; + } + case PM4ItOpcode::IndexBufferSize: { + const auto* index_size = reinterpret_cast(header); + regs.num_indices = index_size->num_indices; + break; + } + case PM4ItOpcode::SetBase: { + const auto* set_base = reinterpret_cast(header); + ASSERT(set_base->base_index == PM4CmdSetBase::BaseIndex::DrawIndexIndirPatchTable); + mapped_queues[GfxQueueId].indirect_args_addr = set_base->Address(); + break; + } + case PM4ItOpcode::EventWrite: { + // const auto* event = reinterpret_cast(header); + break; + } + case PM4ItOpcode::EventWriteEos: { + const auto* event_eos = reinterpret_cast(header); + event_eos->SignalFence(); + if (event_eos->command == PM4CmdEventWriteEos::Command::GdsStore) { + ASSERT(event_eos->size == 1); + if (rasterizer) { + rasterizer->Finish(); + const u32 value = rasterizer->ReadDataFromGds(event_eos->gds_index); + *event_eos->Address() = value; + } + } + break; + } + case PM4ItOpcode::EventWriteEop: { + const auto* event_eop = reinterpret_cast(header); + event_eop->SignalFence(); + break; + } + case PM4ItOpcode::DmaData: { + const auto* dma_data = reinterpret_cast(header); + if (dma_data->src_sel == DmaDataSrc::Data && dma_data->dst_sel == DmaDataDst::Gds) { + rasterizer->InlineDataToGds(dma_data->dst_addr_lo, dma_data->data); + } + break; + } + case PM4ItOpcode::WriteData: { + const auto* write_data = reinterpret_cast(header); + ASSERT(write_data->dst_sel.Value() == 2 || write_data->dst_sel.Value() == 5); + const u32 data_size = (header->type3.count.Value() - 2) * 4; + u64* address = write_data->Address(); + if (!write_data->wr_one_addr.Value()) { + std::memcpy(address, write_data->data, data_size); } else { - last_db_extent.raw = 0; + UNREACHABLE(); + } + break; + } + case PM4ItOpcode::AcquireMem: { + // const auto* acquire_mem = reinterpret_cast(header); + break; + } + case PM4ItOpcode::WaitRegMem: { + const auto* wait_reg_mem = reinterpret_cast(header); + // ASSERT(wait_reg_mem->engine.Value() == PM4CmdWaitRegMem::Engine::Me); + // Optimization: VO label waits are special because the emulator + // will write to the label when presentation is finished. So if + // there are no other submits to yield to we can sleep the thread + // instead and allow other tasks to run. + const u64* wait_addr = wait_reg_mem->Address(); + if (vo_port->IsVoLabel(wait_addr) && num_submits == 1) { + vo_port->WaitVoLabel([&] { return wait_reg_mem->Test(); }); + } + while (!wait_reg_mem->Test()) { + mapped_queues[GfxQueueId].cs_state = regs.cs_program; + TracyFiberLeave; + co_yield {}; + TracyFiberEnter(dcb_task_name); + regs.cs_program = mapped_queues[GfxQueueId].cs_state; + } + break; + } + case PM4ItOpcode::IncrementDeCounter: { + ++cblock.de_count; + break; + } + case PM4ItOpcode::WaitOnCeCounter: { + while (cblock.ce_count <= cblock.de_count) { + TracyFiberLeave; + ce_task.handle.resume(); + TracyFiberEnter(dcb_task_name); + } + break; + } + case PM4ItOpcode::PfpSyncMe: { + if (rasterizer) { + rasterizer->CpSync(); } break; } default: - break; + UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", + static_cast(opcode), count); } + dcb = NextPacket(dcb, header->type3.NumWords() + 1); break; } - case PM4ItOpcode::SetShReg: { - const auto* set_data = reinterpret_cast(header); - std::memcpy(®s.reg_array[ShRegWordOffset + set_data->reg_offset], header + 2, - (count - 1) * sizeof(u32)); - break; - } - case PM4ItOpcode::SetUconfigReg: { - const auto* set_data = reinterpret_cast(header); - std::memcpy(®s.reg_array[UconfigRegWordOffset + set_data->reg_offset], header + 2, - (count - 1) * sizeof(u32)); - break; - } - case PM4ItOpcode::IndexType: { - const auto* index_type = reinterpret_cast(header); - regs.index_buffer_type.raw = index_type->raw; - break; - } - case PM4ItOpcode::DrawIndex2: { - const auto* draw_index = reinterpret_cast(header); - regs.max_index_size = draw_index->max_size; - regs.index_base_address.base_addr_lo = draw_index->index_base_lo; - regs.index_base_address.base_addr_hi.Assign(draw_index->index_base_hi); - regs.num_indices = draw_index->index_count; - regs.draw_initiator = draw_index->draw_initiator; - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndex2", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->Draw(true); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::DrawIndexOffset2: { - const auto* draw_index_off = reinterpret_cast(header); - regs.max_index_size = draw_index_off->max_size; - regs.num_indices = draw_index_off->index_count; - regs.draw_initiator = draw_index_off->draw_initiator; - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexOffset2", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->Draw(true, draw_index_off->index_offset); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::DrawIndexAuto: { - const auto* draw_index = reinterpret_cast(header); - regs.num_indices = draw_index->index_count; - regs.draw_initiator = draw_index->draw_initiator; - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexAuto", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->Draw(false); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::DispatchDirect: { - const auto* dispatch_direct = reinterpret_cast(header); - regs.cs_program.dim_x = dispatch_direct->dim_x; - regs.cs_program.dim_y = dispatch_direct->dim_y; - regs.cs_program.dim_z = dispatch_direct->dim_z; - regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; - if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { - const auto cmd_address = reinterpret_cast(header); - rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:Dispatch", cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); - rasterizer->DispatchDirect(); - rasterizer->ScopeMarkerEnd(); - } - break; - } - case PM4ItOpcode::NumInstances: { - const auto* num_instances = reinterpret_cast(header); - regs.num_instances.num_instances = num_instances->num_instances; - break; - } - case PM4ItOpcode::IndexBase: { - const auto* index_base = reinterpret_cast(header); - regs.index_base_address.base_addr_lo = index_base->addr_lo; - regs.index_base_address.base_addr_hi.Assign(index_base->addr_hi); - break; - } - case PM4ItOpcode::IndexBufferSize: { - const auto* index_size = reinterpret_cast(header); - regs.num_indices = index_size->num_indices; - break; - } - case PM4ItOpcode::EventWrite: { - // const auto* event = reinterpret_cast(header); - break; - } - case PM4ItOpcode::EventWriteEos: { - const auto* event_eos = reinterpret_cast(header); - event_eos->SignalFence(); - break; - } - case PM4ItOpcode::EventWriteEop: { - const auto* event_eop = reinterpret_cast(header); - event_eop->SignalFence(); - break; - } - case PM4ItOpcode::DmaData: { - const auto* dma_data = reinterpret_cast(header); - break; - } - case PM4ItOpcode::WriteData: { - const auto* write_data = reinterpret_cast(header); - ASSERT(write_data->dst_sel.Value() == 2 || write_data->dst_sel.Value() == 5); - const u32 data_size = (header->type3.count.Value() - 2) * 4; - u64* address = write_data->Address(); - if (!write_data->wr_one_addr.Value()) { - std::memcpy(address, write_data->data, data_size); - } else { - UNREACHABLE(); - } - break; - } - case PM4ItOpcode::AcquireMem: { - // const auto* acquire_mem = reinterpret_cast(header); - break; - } - case PM4ItOpcode::WaitRegMem: { - const auto* wait_reg_mem = reinterpret_cast(header); - // ASSERT(wait_reg_mem->engine.Value() == PM4CmdWaitRegMem::Engine::Me); - // Optimization: VO label waits are special because the emulator - // will write to the label when presentation is finished. So if - // there are no other submits to yield to we can sleep the thread - // instead and allow other tasks to run. - const u64* wait_addr = wait_reg_mem->Address(); - if (vo_port->IsVoLabel(wait_addr) && num_submits == 1) { - vo_port->WaitVoLabel([&] { return wait_reg_mem->Test(); }); - } - while (!wait_reg_mem->Test()) { - mapped_queues[GfxQueueId].cs_state = regs.cs_program; - TracyFiberLeave; - co_yield {}; - TracyFiberEnter(dcb_task_name); - regs.cs_program = mapped_queues[GfxQueueId].cs_state; - } - break; - } - case PM4ItOpcode::IncrementDeCounter: { - ++cblock.de_count; - break; - } - case PM4ItOpcode::WaitOnCeCounter: { - while (cblock.ce_count <= cblock.de_count) { - TracyFiberLeave; - ce_task.handle.resume(); - TracyFiberEnter(dcb_task_name); - } - break; - } - default: - UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", - static_cast(opcode), count); - } - dcb = dcb.subspan(header->type3.NumWords() + 1); } if (ce_task.handle) { @@ -472,6 +601,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span acb, int vqid) { TracyFiberEnter(acb_task_name); + auto base_addr = reinterpret_cast(acb.data()); while (!acb.empty()) { const auto* header = reinterpret_cast(acb.data()); const u32 type = header->type; @@ -516,10 +646,12 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { regs.cs_program.dim_y = dispatch_direct->dim_y; regs.cs_program.dim_z = dispatch_direct->dim_z; regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; + if (DebugState.DumpingCurrentReg()) { + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs, true); + } if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { const auto cmd_address = reinterpret_cast(header); rasterizer->ScopeMarkerBegin(fmt::format("acb[{}]:{}:Dispatch", vqid, cmd_address)); - rasterizer->Breadcrumb(u64(cmd_address)); rasterizer->DispatchDirect(); rasterizer->ScopeMarkerEnd(); } @@ -558,15 +690,55 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { static_cast(opcode), count); } - acb = acb.subspan(header->type3.NumWords() + 1); + acb = NextPacket(acb, header->type3.NumWords() + 1); } TracyFiberLeave; } +std::pair, std::span> Liverpool::CopyCmdBuffers( + std::span dcb, std::span ccb) { + auto& queue = mapped_queues[GfxQueueId]; + + // std::vector resize can invalidate spans for commands in flight + ASSERT_MSG(queue.dcb_buffer.capacity() >= queue.dcb_buffer_offset + dcb.size(), + "dcb copy buffer out of reserved space"); + ASSERT_MSG(queue.ccb_buffer.capacity() >= queue.ccb_buffer_offset + ccb.size(), + "ccb copy buffer out of reserved space"); + + queue.dcb_buffer.resize( + std::max(queue.dcb_buffer.size(), queue.dcb_buffer_offset + dcb.size())); + queue.ccb_buffer.resize( + std::max(queue.ccb_buffer.size(), queue.ccb_buffer_offset + ccb.size())); + + u32 prev_dcb_buffer_offset = queue.dcb_buffer_offset; + u32 prev_ccb_buffer_offset = queue.ccb_buffer_offset; + if (!dcb.empty()) { + std::memcpy(queue.dcb_buffer.data() + queue.dcb_buffer_offset, dcb.data(), + dcb.size_bytes()); + queue.dcb_buffer_offset += dcb.size(); + dcb = std::span{queue.dcb_buffer.begin() + prev_dcb_buffer_offset, + queue.dcb_buffer.begin() + queue.dcb_buffer_offset}; + } + + if (!ccb.empty()) { + std::memcpy(queue.ccb_buffer.data() + queue.ccb_buffer_offset, ccb.data(), + ccb.size_bytes()); + queue.ccb_buffer_offset += ccb.size(); + ccb = std::span{queue.ccb_buffer.begin() + prev_ccb_buffer_offset, + queue.ccb_buffer.begin() + queue.ccb_buffer_offset}; + } + + return std::make_pair(dcb, ccb); +} + void Liverpool::SubmitGfx(std::span dcb, std::span ccb) { auto& queue = mapped_queues[GfxQueueId]; + if (Config::copyGPUCmdBuffers()) { + std::tie(dcb, ccb) = CopyCmdBuffers(dcb, ccb); + } + auto task = ProcessGraphics(dcb, ccb); { std::scoped_lock lock{queue.m_access}; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 595c98f56..a4cf79334 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "common/assert.h" @@ -17,6 +18,8 @@ #include "common/polyfill_thread.h" #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" @@ -89,6 +92,12 @@ struct Liverpool { union { BitField<0, 6, u64> num_vgprs; BitField<6, 4, u64> num_sgprs; + BitField<10, 2, u64> priority; + BitField<12, 2, FpRoundMode> fp_round_mode32; + BitField<14, 2, FpRoundMode> fp_round_mode64; + BitField<16, 2, FpDenormMode> fp_denorm_mode32; + BitField<18, 2, FpDenormMode> fp_denorm_mode64; + BitField<12, 8, u64> float_mode; BitField<24, 2, u64> vgpr_comp_cnt; // SPI provided per-thread inputs BitField<33, 5, u64> num_user_regs; } settings; @@ -166,10 +175,19 @@ struct Liverpool { static constexpr auto* GetBinaryInfo(const Shader& sh) { const auto* code = sh.template Address(); const auto* bininfo = std::bit_cast(code + (code[1] + 1) * 2); - ASSERT_MSG(bininfo->Valid(), "Invalid shader binary header"); + // ASSERT_MSG(bininfo->Valid(), "Invalid shader binary header"); return bininfo; } + static constexpr Shader::ShaderParams GetParams(const auto& sh) { + auto* bininfo = GetBinaryInfo(sh); + return { + .user_data = sh.user_data, + .code = sh.Code(), + .hash = bininfo->shader_hash, + }; + } + union PsInputControl { u32 raw; BitField<0, 5, u32> input_offset; @@ -242,6 +260,13 @@ struct Liverpool { } }; + struct ModeControl { + s32 msaa_enable : 1; + s32 vport_scissor_enable : 1; + s32 line_stripple_enable : 1; + s32 send_unlit_stiles_to_pkr : 1; + }; + enum class ZOrder : u32 { LateZ = 0, EarlyZLateZ = 1, @@ -345,13 +370,16 @@ struct Liverpool { Stencil8 = 1, }; - union { + union ZInfo { BitField<0, 2, ZFormat> format; BitField<2, 2, u32> num_samples; BitField<13, 3, u32> tile_split; + BitField<20, 3, u32> tile_mode_index; + BitField<23, 4, u32> decompress_on_n_zplanes; BitField<27, 1, u32> allow_expclear; BitField<28, 1, u32> read_size; BitField<29, 1, u32> tile_surface_en; + BitField<30, 1, u32> clear_disallowed; BitField<31, 1, u32> zrange_precision; } z_info; union { @@ -454,6 +482,8 @@ struct Liverpool { BitField<13, 1, u32> enable_polygon_offset_para; BitField<16, 1, u32> enable_window_offset; BitField<19, 1, ProvokingVtxLast> provoking_vtx_last; + BitField<20, 1, u32> persp_corr_dis; + BitField<21, 1, u32> multi_prim_ib_ena; PolygonMode PolyMode() const { return enable_polygon_mode ? polygon_mode_front.Value() : PolygonMode::Fill; @@ -462,6 +492,11 @@ struct Liverpool { CullMode CullingMode() const { return static_cast(cull_front | cull_back << 1); } + + bool NeedsBias() const { + return enable_polygon_offset_back || enable_polygon_offset_front || + enable_polygon_offset_para; + } }; union VsOutputConfig { @@ -495,6 +530,11 @@ struct Liverpool { u32 GetMask(int buf_id) const { return (raw >> (buf_id * 4)) & 0xfu; } + + void SetMask(int buf_id, u32 mask) { + raw &= ~(0xf << (buf_id * 4)); + raw |= (mask << (buf_id * 4)); + } }; struct IndexBufferBase { @@ -538,29 +578,39 @@ struct Liverpool { s16 top_left_x; s16 top_left_y; }; - union { - BitField<0, 15, u32> bottom_right_x; - BitField<16, 15, u32> bottom_right_y; + struct { + s16 bottom_right_x; + s16 bottom_right_y; }; + // From AMD spec: 'Negative numbers clamped to 0' + static s16 Clamp(s16 value) { + return std::max(s16(0), value); + } + u32 GetWidth() const { - return static_cast(bottom_right_x - top_left_x); + return static_cast(Clamp(bottom_right_x) - Clamp(top_left_x)); } u32 GetHeight() const { - return static_cast(bottom_right_y - top_left_y); + return static_cast(Clamp(bottom_right_y) - Clamp(top_left_y)); } }; + struct WindowOffset { + s32 window_x_offset : 16; + s32 window_y_offset : 16; + }; + struct ViewportScissor { union { BitField<0, 15, s32> top_left_x; - BitField<15, 15, s32> top_left_y; - BitField<30, 1, s32> window_offset_disble; + BitField<16, 15, s32> top_left_y; + BitField<31, 1, s32> window_offset_disable; }; - union { - BitField<0, 15, s32> bottom_right_x; - BitField<15, 15, s32> bottom_right_y; + struct { + s16 bottom_right_x; + s16 bottom_right_y; }; u32 GetWidth() const { @@ -596,6 +646,7 @@ struct Liverpool { BitField<8, 1, u32> xy_transformed; BitField<9, 1, u32> z_transformed; BitField<10, 1, u32> w_transformed; + BitField<11, 1, u32> perfcounter_ref; }; struct ClipUserData { @@ -651,6 +702,7 @@ struct Liverpool { BitField<24, 5, BlendFactor> alpha_dst_factor; BitField<29, 1, u32> separate_alpha_blend; BitField<30, 1, u32> enable; + BitField<31, 1, u32> disable_rop3; }; union ColorControl { @@ -659,9 +711,11 @@ struct Liverpool { Normal = 1u, EliminateFastClear = 2u, Resolve = 3u, + Err = 4u, FmaskDecompress = 5u, }; + BitField<0, 1, u32> disable_dual_quad; BitField<3, 1, u32> degamma_enable; BitField<4, 3, OperationMode> mode; BitField<16, 8, u32> rop3; @@ -699,7 +753,7 @@ struct Liverpool { BitField<0, 11, u32> slice_start; BitField<13, 11, u32> slice_max; } view; - union { + union Color0Info { BitField<0, 2, EndianSwap> endian; BitField<2, 5, DataFormat> format; BitField<7, 1, u32> linear_general; @@ -712,13 +766,24 @@ struct Liverpool { BitField<17, 1, u32> simple_float; BitField<18, 1, RoundMode> round_mode; BitField<19, 1, u32> cmask_is_linear; + BitField<20, 3, u32> blend_opt_dont_rd_dst; + BitField<23, 3, u32> blend_opt_discard_pixel; + 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; + + u32 u32all; } info; - union { + union Color0Attrib { BitField<0, 5, TilingMode> tile_mode_index; BitField<5, 5, u32> fmask_tile_mode_index; + BitField<10, 2, u32> fmask_bank_height; BitField<12, 3, u32> num_samples_log2; BitField<15, 2, u32> num_fragments_log2; BitField<17, 1, u32> force_dst_alpha_1; + + u32 u32all; } attrib; INSERT_PADDING_WORDS(1); u32 cmask_base_address; @@ -788,26 +853,6 @@ struct Liverpool { } }; - enum class PrimitiveType : u32 { - None = 0, - PointList = 1, - LineList = 2, - LineStrip = 3, - TriangleList = 4, - TriangleFan = 5, - TriangleStrip = 6, - PatchPrimitive = 9, - AdjLineList = 10, - AdjLineStrip = 11, - AdjTriangleList = 12, - AdjTriangleStrip = 13, - RectList = 17, - LineLoop = 18, - QuadList = 19, - QuadStrip = 20, - Polygon = 21, - }; - enum ContextRegs : u32 { DbZInfo = 0xA010, CbColor0Base = 0xA318, @@ -848,8 +893,14 @@ struct Liverpool { u32 raw; BitField<0, 1, u32> depth_clear_enable; BitField<1, 1, u32> stencil_clear_enable; + BitField<2, 1, u32> depth_copy; + BitField<3, 1, u32> stencil_copy; + BitField<4, 1, u32> resummarize_enable; BitField<5, 1, u32> stencil_compress_disable; BitField<6, 1, u32> depth_compress_disable; + BitField<7, 1, u32> copy_centroid; + BitField<8, 1, u32> copy_sample; + BitField<9, 1, u32> decompress_enable; }; union DepthView { @@ -876,14 +927,19 @@ struct Liverpool { }; union ShaderStageEnable { - u32 raw; + enum VgtStages : u32 { + Vs = 0u, // always enabled + EsGs = 0xB0u, + }; + + VgtStages raw; BitField<0, 2, u32> ls_en; BitField<2, 1, u32> hs_en; BitField<3, 2, u32> es_en; BitField<5, 1, u32> gs_en; BitField<6, 1, u32> vs_en; - bool IsStageEnabled(u32 stage) { + bool IsStageEnabled(u32 stage) const { switch (stage) { case 0: case 1: @@ -902,6 +958,97 @@ struct Liverpool { } }; + union GsInstances { + u32 raw; + struct { + u32 enable : 2; + u32 count : 6; + }; + + bool IsEnabled() const { + return enable && count > 0; + } + }; + + union GsOutPrimitiveType { + u32 raw; + struct { + GsOutputPrimitiveType outprim_type : 6; + GsOutputPrimitiveType outprim_type1 : 6; + GsOutputPrimitiveType outprim_type2 : 6; + GsOutputPrimitiveType outprim_type3 : 6; + u32 reserved : 3; + u32 unique_type_per_stream : 1; + }; + + GsOutputPrimitiveType GetPrimitiveType(u32 stream) const { + if (unique_type_per_stream == 0) { + return outprim_type; + } + + switch (stream) { + case 0: + return outprim_type; + case 1: + return outprim_type1; + case 2: + return outprim_type2; + case 3: + return outprim_type3; + default: + UNREACHABLE(); + } + } + }; + + union GsMode { + u32 raw; + BitField<0, 3, u32> mode; + BitField<3, 2, u32> cut_mode; + BitField<22, 2, u32> onchip; + }; + + union StreamOutConfig { + u32 raw; + struct { + u32 streamout_0_en : 1; + u32 streamout_1_en : 1; + u32 streamout_2_en : 1; + u32 streamout_3_en : 1; + u32 rast_stream : 3; + u32 : 1; + u32 rast_stream_mask : 4; + u32 : 19; + u32 use_rast_stream_mask : 1; + }; + }; + + union StreamOutBufferConfig { + u32 raw; + struct { + u32 stream_0_buf_en : 4; + u32 stream_1_buf_en : 4; + u32 stream_2_buf_en : 4; + u32 stream_3_buf_en : 4; + }; + }; + + union Eqaa { + u32 raw; + BitField<0, 1, u32> max_anchor_samples; + BitField<4, 3, u32> ps_iter_samples; + BitField<8, 3, u32> mask_export_num_samples; + BitField<12, 3, u32> alpha_to_mask_num_samples; + BitField<16, 1, u32> high_quality_intersections; + BitField<17, 1, u32> incoherent_eqaa_reads; + BitField<18, 1, u32> interpolate_comp_z; + BitField<19, 1, u32> interpolate_src_z; + BitField<20, 1, u32> static_anchor_associations; + BitField<21, 1, u32> alpha_to_mask_eqaa_disable; + BitField<24, 3, u32> overrasterization_amount; + BitField<27, 1, u32> enable_postz_overrasterization; + }; + union Regs { struct { INSERT_PADDING_WORDS(0x2C08); @@ -932,10 +1079,14 @@ struct Liverpool { Scissor screen_scissor; INSERT_PADDING_WORDS(0xA010 - 0xA00C - 2); DepthBuffer depth_buffer; - INSERT_PADDING_WORDS(0xA08E - 0xA018); + INSERT_PADDING_WORDS(0xA080 - 0xA018); + WindowOffset window_offset; + ViewportScissor window_scissor; + INSERT_PADDING_WORDS(0xA08E - 0xA081 - 2); ColorBufferMask color_target_mask; ColorBufferMask color_shader_mask; - INSERT_PADDING_WORDS(0xA094 - 0xA08E - 2); + ViewportScissor generic_scissor; + INSERT_PADDING_WORDS(2); std::array viewport_scissors; std::array viewport_depths; INSERT_PADDING_WORDS(0xA103 - 0xA0D4); @@ -973,7 +1124,13 @@ struct Liverpool { PolygonControl polygon_control; ViewportControl viewport_control; VsOutputControl vs_output_control; - INSERT_PADDING_WORDS(0xA29E - 0xA207 - 2); + INSERT_PADDING_WORDS(0xA290 - 0xA207 - 1); + GsMode vgt_gs_mode; + INSERT_PADDING_WORDS(1); + ModeControl mode_control; + INSERT_PADDING_WORDS(8); + GsOutPrimitiveType vgt_gs_out_prim_type; + INSERT_PADDING_WORDS(1); u32 index_size; u32 max_index_size; IndexBufferType index_buffer_type; @@ -984,11 +1141,21 @@ struct Liverpool { INSERT_PADDING_WORDS(0xA2A8 - 0xA2A5 - 1); u32 vgt_instance_step_rate_0; u32 vgt_instance_step_rate_1; - INSERT_PADDING_WORDS(0xA2D5 - 0xA2A9 - 1); + INSERT_PADDING_WORDS(0xA2AB - 0xA2A9 - 1); + u32 vgt_esgs_ring_itemsize; + u32 vgt_gsvs_ring_itemsize; + INSERT_PADDING_WORDS(0xA2CE - 0xA2AC - 1); + BitField<0, 11, u32> vgt_gs_max_vert_out; + INSERT_PADDING_WORDS(0xA2D5 - 0xA2CE - 1); ShaderStageEnable stage_enable; - INSERT_PADDING_WORDS(9); + INSERT_PADDING_WORDS(1); + u32 vgt_gs_vert_itemsize[4]; + INSERT_PADDING_WORDS(4); PolygonOffset poly_offset; - INSERT_PADDING_WORDS(0xA2F8 - 0xA2DF - 5); + GsInstances vgt_gs_instance_cnt; + StreamOutConfig vgt_strmout_config; + StreamOutBufferConfig vgt_strmout_buffer_config; + INSERT_PADDING_WORDS(0xA2F8 - 0xA2E6 - 1); AaConfig aa_config; INSERT_PADDING_WORDS(0xA318 - 0xA2F8 - 1); ColorBuffer color_buffers[NumColorBuffers]; @@ -1017,6 +1184,8 @@ struct Liverpool { } return nullptr; } + + void SetDefaults(); }; Regs regs{}; @@ -1045,6 +1214,8 @@ public: void SubmitDone() noexcept { std::scoped_lock lk{submit_mutex}; + mapped_queues[GfxQueueId].ccb_buffer_offset = 0; + mapped_queues[GfxQueueId].dcb_buffer_offset = 0; submit_done = true; submit_cv.notify_one(); } @@ -1073,6 +1244,15 @@ public: submit_cv.notify_one(); } + void reserveCopyBufferSpace() { + GpuQueue& gfx_queue = mapped_queues[GfxQueueId]; + std::scoped_lock lk(gfx_queue.m_access); + + constexpr size_t GfxReservedSize = 2_MB >> 2; + gfx_queue.ccb_buffer.reserve(GfxReservedSize); + gfx_queue.dcb_buffer.reserve(GfxReservedSize); + } + private: struct Task { struct promise_type { @@ -1106,6 +1286,8 @@ private: Handle handle; }; + std::pair, std::span> CopyCmdBuffers(std::span dcb, + std::span ccb); Task ProcessGraphics(std::span dcb, std::span ccb); Task ProcessCeUpdate(std::span ccb); Task ProcessCompute(std::span acb, int vqid); @@ -1114,8 +1296,13 @@ private: struct GpuQueue { std::mutex m_access{}; + std::atomic dcb_buffer_offset; + std::atomic ccb_buffer_offset; + std::vector dcb_buffer; + std::vector ccb_buffer; std::queue submits{}; ComputeProgram cs_state{}; + VAddr indirect_args_addr{}; }; std::array mapped_queues{}; @@ -1165,8 +1352,11 @@ static_assert(GFX6_3D_REG_INDEX(depth_htile_data_base) == 0xA005); static_assert(GFX6_3D_REG_INDEX(screen_scissor) == 0xA00C); static_assert(GFX6_3D_REG_INDEX(depth_buffer.z_info) == 0xA010); static_assert(GFX6_3D_REG_INDEX(depth_buffer.depth_slice) == 0xA017); +static_assert(GFX6_3D_REG_INDEX(window_offset) == 0xA080); +static_assert(GFX6_3D_REG_INDEX(window_scissor) == 0xA081); static_assert(GFX6_3D_REG_INDEX(color_target_mask) == 0xA08E); static_assert(GFX6_3D_REG_INDEX(color_shader_mask) == 0xA08F); +static_assert(GFX6_3D_REG_INDEX(generic_scissor) == 0xA090); static_assert(GFX6_3D_REG_INDEX(viewport_scissors) == 0xA094); static_assert(GFX6_3D_REG_INDEX(primitive_restart_index) == 0xA103); static_assert(GFX6_3D_REG_INDEX(stencil_control) == 0xA10B); @@ -1186,14 +1376,24 @@ static_assert(GFX6_3D_REG_INDEX(color_control) == 0xA202); static_assert(GFX6_3D_REG_INDEX(clipper_control) == 0xA204); static_assert(GFX6_3D_REG_INDEX(viewport_control) == 0xA206); static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207); +static_assert(GFX6_3D_REG_INDEX(vgt_gs_mode) == 0xA290); +static_assert(GFX6_3D_REG_INDEX(mode_control) == 0xA292); +static_assert(GFX6_3D_REG_INDEX(vgt_gs_out_prim_type) == 0xA29B); static_assert(GFX6_3D_REG_INDEX(index_size) == 0xA29D); static_assert(GFX6_3D_REG_INDEX(index_buffer_type) == 0xA29F); static_assert(GFX6_3D_REG_INDEX(enable_primitive_id) == 0xA2A1); static_assert(GFX6_3D_REG_INDEX(enable_primitive_restart) == 0xA2A5); static_assert(GFX6_3D_REG_INDEX(vgt_instance_step_rate_0) == 0xA2A8); static_assert(GFX6_3D_REG_INDEX(vgt_instance_step_rate_1) == 0xA2A9); +static_assert(GFX6_3D_REG_INDEX(vgt_esgs_ring_itemsize) == 0xA2AB); +static_assert(GFX6_3D_REG_INDEX(vgt_gsvs_ring_itemsize) == 0xA2AC); +static_assert(GFX6_3D_REG_INDEX(vgt_gs_max_vert_out) == 0xA2CE); static_assert(GFX6_3D_REG_INDEX(stage_enable) == 0xA2D5); +static_assert(GFX6_3D_REG_INDEX(vgt_gs_vert_itemsize[0]) == 0xA2D7); static_assert(GFX6_3D_REG_INDEX(poly_offset) == 0xA2DF); +static_assert(GFX6_3D_REG_INDEX(vgt_gs_instance_cnt) == 0xA2E4); +static_assert(GFX6_3D_REG_INDEX(vgt_strmout_config) == 0xA2E5); +static_assert(GFX6_3D_REG_INDEX(vgt_strmout_buffer_config) == 0xA2E6); static_assert(GFX6_3D_REG_INDEX(aa_config) == 0xA2F8); static_assert(GFX6_3D_REG_INDEX(color_buffers[0].base_address) == 0xA318); static_assert(GFX6_3D_REG_INDEX(color_buffers[0].pitch) == 0xA319); diff --git a/src/video_core/amdgpu/pixel_format.cpp b/src/video_core/amdgpu/pixel_format.cpp index 6744891a6..b13fc2d11 100644 --- a/src/video_core/amdgpu/pixel_format.cpp +++ b/src/video_core/amdgpu/pixel_format.cpp @@ -144,10 +144,10 @@ static constexpr std::array component_bits = { std::array{8, 8, 0, 0}, // 3 Format8_8 std::array{32, 0, 0, 0}, // 4 Format32 std::array{16, 16, 0, 0}, // 5 Format16_16 - std::array{10, 11, 11, 0}, // 6 Format10_11_11 - std::array{11, 11, 10, 0}, // 7 Format11_11_10 - std::array{10, 10, 10, 2}, // 8 Format10_10_10_2 - std::array{2, 10, 10, 10}, // 9 Format2_10_10_10 + std::array{11, 11, 10, 0}, // 6 Format10_11_11 + std::array{10, 11, 11, 0}, // 7 Format11_11_10 + std::array{2, 10, 10, 10}, // 8 Format10_10_10_2 + std::array{10, 10, 10, 2}, // 9 Format2_10_10_10 std::array{8, 8, 8, 8}, // 10 Format8_8_8_8 std::array{32, 32, 0, 0}, // 11 Format32_32 std::array{16, 16, 16, 16}, // 12 Format16_16_16_16 @@ -155,12 +155,12 @@ static constexpr std::array component_bits = { std::array{32, 32, 32, 32}, // 14 Format32_32_32_32 std::array{0, 0, 0, 0}, // 15 std::array{5, 6, 5, 0}, // 16 Format5_6_5 - std::array{1, 5, 5, 5}, // 17 Format1_5_5_5 - std::array{5, 5, 5, 1}, // 18 Format5_5_5_1 + std::array{5, 5, 5, 1}, // 17 Format1_5_5_5 + std::array{1, 5, 5, 5}, // 18 Format5_5_5_1 std::array{4, 4, 4, 4}, // 19 Format4_4_4_4 - std::array{8, 24, 0, 0}, // 20 Format8_24 - std::array{24, 8, 0, 0}, // 21 Format24_8 - std::array{24, 8, 0, 0}, // 22 FormatX24_8_32 + std::array{24, 8, 0, 0}, // 20 Format8_24 + std::array{8, 24, 0, 0}, // 21 Format24_8 + std::array{8, 24, 0, 0}, // 22 FormatX24_8_32 std::array{0, 0, 0, 0}, // 23 std::array{0, 0, 0, 0}, // 24 std::array{0, 0, 0, 0}, // 25 @@ -197,10 +197,10 @@ static constexpr std::array component_offset = { std::array{0, 8, -1, -1}, // 3 Format8_8 std::array{0, -1, -1, -1}, // 4 Format32 std::array{0, 16, -1, -1}, // 5 Format16_16 - std::array{0, 10, 21, -1}, // 6 Format10_11_11 - std::array{0, 11, 22, -1}, // 7 Format11_11_10 - std::array{0, 10, 20, 30}, // 8 Format10_10_10_2 - std::array{0, 2, 12, 22}, // 9 Format2_10_10_10 + std::array{0, 11, 22, -1}, // 6 Format10_11_11 + std::array{0, 10, 21, -1}, // 7 Format11_11_10 + std::array{0, 2, 12, 22}, // 8 Format10_10_10_2 + std::array{0, 10, 20, 30}, // 9 Format2_10_10_10 std::array{0, 8, 16, 24}, // 10 Format8_8_8_8 std::array{0, 32, -1, -1}, // 11 Format32_32 std::array{0, 16, 32, 48}, // 12 Format16_16_16_16 @@ -208,12 +208,12 @@ static constexpr std::array component_offset = { std::array{0, 32, 64, 96}, // 14 Format32_32_32_32 std::array{-1, -1, -1, -1}, // 15 std::array{0, 5, 11, -1}, // 16 Format5_6_5 - std::array{0, 1, 6, 11}, // 17 Format1_5_5_5 - std::array{0, 5, 10, 15}, // 18 Format5_5_5_1 + std::array{0, 5, 10, 15}, // 17 Format1_5_5_5 + std::array{0, 1, 6, 11}, // 18 Format5_5_5_1 std::array{0, 4, 8, 12}, // 19 Format4_4_4_4 - std::array{0, 8, -1, -1}, // 20 Format8_24 - std::array{0, 24, -1, -1}, // 21 Format24_8 - std::array{0, 24, -1, -1}, // 22 FormatX24_8_32 + std::array{0, 24, -1, -1}, // 20 Format8_24 + std::array{0, 8, -1, -1}, // 21 Format24_8 + std::array{0, 8, -1, -1}, // 22 FormatX24_8_32 std::array{-1, -1, -1, -1}, // 23 std::array{-1, -1, -1, -1}, // 24 std::array{-1, -1, -1, -1}, // 25 diff --git a/src/video_core/amdgpu/pixel_format.h b/src/video_core/amdgpu/pixel_format.h index 1004ed7d2..e83313ea4 100644 --- a/src/video_core/amdgpu/pixel_format.h +++ b/src/video_core/amdgpu/pixel_format.h @@ -6,60 +6,13 @@ #include #include #include "common/types.h" +#include "video_core/amdgpu/types.h" namespace AmdGpu { -// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] -enum class DataFormat : u32 { - FormatInvalid = 0, - Format8 = 1, - Format16 = 2, - Format8_8 = 3, - Format32 = 4, - Format16_16 = 5, - Format10_11_11 = 6, - Format11_11_10 = 7, - Format10_10_10_2 = 8, - Format2_10_10_10 = 9, - Format8_8_8_8 = 10, - Format32_32 = 11, - Format16_16_16_16 = 12, - Format32_32_32 = 13, - Format32_32_32_32 = 14, - Format5_6_5 = 16, - Format1_5_5_5 = 17, - Format5_5_5_1 = 18, - Format4_4_4_4 = 19, - Format8_24 = 20, - Format24_8 = 21, - FormatX24_8_32 = 22, - FormatGB_GR = 32, - FormatBG_RG = 33, - Format5_9_9_9 = 34, - FormatBc1 = 35, - FormatBc2 = 36, - FormatBc3 = 37, - FormatBc4 = 38, - FormatBc5 = 39, - FormatBc6 = 40, - FormatBc7 = 41, -}; - -enum class NumberFormat : u32 { - Unorm = 0, - Snorm = 1, - Uscaled = 2, - Sscaled = 3, - Uint = 4, - Sint = 5, - SnormNz = 6, - Float = 7, - Srgb = 9, - Ubnorm = 10, - UbnromNz = 11, - Ubint = 12, - Ubscaled = 13, -}; +[[nodiscard]] constexpr bool IsInteger(NumberFormat nfmt) { + return nfmt == AmdGpu::NumberFormat::Sint || nfmt == AmdGpu::NumberFormat::Uint; +} [[nodiscard]] std::string_view NameOf(DataFormat fmt); [[nodiscard]] std::string_view NameOf(NumberFormat fmt); diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 5ab233fdc..a7a862ea3 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -36,6 +36,8 @@ union PM4Type0Header { }; union PM4Type3Header { + static constexpr u32 TYPE = 3; + constexpr PM4Type3Header(PM4ItOpcode code, u32 num_words_min_one, PM4ShaderType stype = PM4ShaderType::ShaderGraphics, PM4Predicate pred = PM4Predicate::PredDisable) { @@ -187,6 +189,11 @@ struct PM4CmdSetData { BitField<28, 4, u32> index; ///< Index for UCONFIG/CONTEXT on CI+ ///< Program to zero for other opcodes and on SI }; + u32 data[0]; + + [[nodiscard]] u32 Size() const { + return header.count << 2u; + } template static constexpr u32* SetContextReg(u32* cmdbuf, Args... data) { @@ -206,6 +213,7 @@ struct PM4CmdNop { enum PayloadType : u32 { DebugMarkerPush = 0x68750001u, ///< Begin of GPU event scope DebugMarkerPop = 0x68750002u, ///< End of GPU event scope + DebugSetMarker = 0x68750003u, ///< Set GPU event marker SetVsharpInUdata = 0x68750004u, ///< Indicates that V# will be set in the next packet SetTsharpInUdata = 0x68750005u, ///< Indicates that T# will be set in the next packet SetSsharpInUdata = 0x68750006u, ///< Indicates that S# will be set in the next packet @@ -253,20 +261,6 @@ struct PM4CmdDrawIndexAuto { u32 draw_initiator; }; -struct PM4CmdDrawIndirect { - PM4Type3Header header; ///< header - u32 data_offset; ///< DWORD aligned offset - union { - u32 dw2; - BitField<0, 16, u32> base_vtx_loc; ///< base vertex location - }; - union { - u32 dw3; - BitField<0, 16, u32> start_inst_loc; ///< start instance location - }; - u32 draw_initiator; ///< Draw Initiator Register -}; - enum class DataSelect : u32 { None = 0, Data32Low = 1, @@ -364,6 +358,27 @@ struct PM4CmdEventWriteEop { } }; +struct PM4CmdAcquireMem { + PM4Type3Header header; + u32 cp_coher_cntl; + u32 cp_coher_size_lo; + u32 cp_coher_size_hi; + u32 cp_coher_base_lo; + u32 cp_coher_base_hi; + u32 poll_interval; +}; + +enum class DmaDataDst : u32 { + Memory = 0, + Gds = 1, +}; + +enum class DmaDataSrc : u32 { + Memory = 0, + Gds = 1, + Data = 2, +}; + struct PM4DmaData { PM4Type3Header header; union { @@ -371,11 +386,11 @@ struct PM4DmaData { BitField<12, 1, u32> src_atc; BitField<13, 2, u32> src_cache_policy; BitField<15, 1, u32> src_volatile; - BitField<20, 2, u32> dst_sel; + BitField<20, 2, DmaDataDst> dst_sel; BitField<24, 1, u32> dst_atc; BitField<25, 2, u32> dst_cache_policy; BitField<27, 1, u32> dst_volatile; - BitField<29, 2, u32> src_sel; + BitField<29, 2, DmaDataSrc> src_sel; BitField<31, 1, u32> cp_sync; }; union { @@ -470,6 +485,10 @@ struct PM4CmdWriteData { }; u32 data[0]; + u32 Size() const { + return (header.count.Value() - 2) * 4; + } + template void Address(T addr) { addr64 = static_cast(addr); @@ -484,7 +503,7 @@ struct PM4CmdWriteData { struct PM4CmdEventWriteEos { enum class Command : u32 { GdsStore = 1u, - SingalFence = 2u, + SignalFence = 2u, }; PM4Type3Header header; @@ -516,13 +535,17 @@ struct PM4CmdEventWriteEos { } void SignalFence() const { - switch (command.Value()) { - case Command::SingalFence: { + const auto cmd = command.Value(); + switch (cmd) { + case Command::SignalFence: { *Address() = DataDWord(); break; } + case Command::GdsStore: { + break; + } default: { - UNREACHABLE(); + UNREACHABLE_MSG("Unknown command {}", u32(cmd)); } } } @@ -704,4 +727,87 @@ struct PM4CmdReleaseMem { } }; +struct PM4CmdSetBase { + enum class BaseIndex : u32 { + DisplayListPatchTable = 0b0000, + DrawIndexIndirPatchTable = 0b0001, + GdsPartition = 0b0010, + CePartition = 0b0011, + }; + + PM4Type3Header header; + union { + BitField<0, 4, BaseIndex> base_index; + u32 dw1; + }; + u32 address0; + u32 address1; + + template + T Address() const { + ASSERT(base_index == BaseIndex::DisplayListPatchTable || + base_index == BaseIndex::DrawIndexIndirPatchTable); + return reinterpret_cast(address0 | (u64(address1 & 0xffff) << 32u)); + } +}; + +struct PM4CmdDispatchIndirect { + struct GroupDimensions { + u32 dim_x; + u32 dim_y; + u32 dim_z; + }; + + PM4Type3Header header; + u32 data_offset; ///< Byte aligned offset where the required data structure starts + u32 dispatch_initiator; ///< Dispatch Initiator Register +}; + +struct PM4CmdDrawIndirect { + struct DrawInstancedArgs { + u32 vertex_count_per_instance; + u32 instance_count; + u32 start_vertex_location; + u32 start_instance_location; + }; + + PM4Type3Header header; ///< header + u32 data_offset; ///< Byte aligned offset where the required data structure starts + union { + u32 dw2; + BitField<0, 16, u32> base_vtx_loc; ///< Offset where the CP will write the + ///< BaseVertexLocation it fetched from memory + }; + union { + u32 dw3; + BitField<0, 16, u32> start_inst_loc; ///< Offset where the CP will write the + ///< StartInstanceLocation it fetched from memory + }; + u32 draw_initiator; ///< Draw Initiator Register +}; + +struct PM4CmdDrawIndexIndirect { + struct DrawIndexInstancedArgs { + u32 index_count_per_instance; + u32 instance_count; + u32 start_index_location; + u32 base_vertex_location; + u32 start_instance_location; + }; + + PM4Type3Header header; ///< header + u32 data_offset; ///< Byte aligned offset where the required data structure starts + union { + u32 dw2; + BitField<0, 16, u32> base_vtx_loc; ///< Offset where the CP will write the + ///< BaseVertexLocation it fetched from memory + }; + union { // NOTE: this one is undocumented in AMD spec, but Gnm driver writes this field + u32 dw3; + BitField<0, 16, u32> start_inst_loc; ///< Offset where the CP will write the + ///< StartInstanceLocation it fetched from memory + }; + u32 draw_initiator; ///< Draw Initiator Register +}; + } // namespace AmdGpu diff --git a/src/video_core/amdgpu/pm4_opcodes.h b/src/video_core/amdgpu/pm4_opcodes.h index fba0cbb9f..4b853138b 100644 --- a/src/video_core/amdgpu/pm4_opcodes.h +++ b/src/video_core/amdgpu/pm4_opcodes.h @@ -32,6 +32,7 @@ enum class PM4ItOpcode : u32 { NumInstances = 0x2F, DrawIndexMultiAuto = 0x30, IndirectBufferConst = 0x33, + StrmoutBufferUpdate = 0x34, DrawIndexOffset2 = 0x35, WriteData = 0x37, DrawIndexIndirectMulti = 0x38, @@ -48,10 +49,11 @@ enum class PM4ItOpcode : u32 { EventWriteEop = 0x47, EventWriteEos = 0x48, ReleaseMem = 0x49, - PremableCntl = 0x4A, + PreambleCntl = 0x4A, DmaData = 0x50, ContextRegRmw = 0x51, AcquireMem = 0x58, + Rewind = 0x59, LoadShReg = 0x5F, LoadConfigReg = 0x60, LoadContextReg = 0x61, @@ -60,7 +62,9 @@ enum class PM4ItOpcode : u32 { SetContextRegIndirect = 0x73, SetShReg = 0x76, SetShRegOffset = 0x77, + SetQueueReg = 0x78, SetUconfigReg = 0x79, + LoadConstRam = 0x80, WriteConstRam = 0x81, DumpConstRam = 0x83, IncrementCeCounter = 0x84, diff --git a/src/video_core/amdgpu/resource.h b/src/video_core/amdgpu/resource.h index ef5bf1b66..97df40a0d 100644 --- a/src/video_core/amdgpu/resource.h +++ b/src/video_core/amdgpu/resource.h @@ -3,6 +3,7 @@ #pragma once +#include "common/alignment.h" #include "common/assert.h" #include "common/bit_field.h" #include "common/types.h" @@ -22,7 +23,7 @@ enum class CompSwizzle : u32 { // Table 8.5 Buffer Resource Descriptor [Sea Islands Series Instruction Set Architecture] struct Buffer { u64 base_address : 44; - u64 : 4; + u64 _padding0 : 4; u64 stride : 14; u64 cache_swizzle : 1; u64 swizzle_enable : 1; @@ -36,7 +37,7 @@ struct Buffer { u32 element_size : 2; u32 index_stride : 2; u32 add_tid_enable : 1; - u32 : 6; + u32 _padding1 : 6; u32 type : 2; // overlaps with T# type, so should be 0 for buffer bool Valid() const { @@ -65,11 +66,15 @@ struct Buffer { } u32 GetStride() const noexcept { - return stride == 0 ? 1U : stride; + return stride; + } + + u32 NumDwords() const noexcept { + return Common::AlignUp(GetSize(), sizeof(u32)) >> 2; } u32 GetSize() const noexcept { - return GetStride() * num_records; + return stride == 0 ? num_records : (stride * num_records); } }; static_assert(sizeof(Buffer) == 16); // 128bits @@ -171,6 +176,18 @@ struct Image { u64 lod_hw_cnt_en : 1; u64 : 43; + 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.tiling_index = u64(TilingMode::Texture_MicroTiled); + image.type = u64(ImageType::Color2D); + return image; + } + bool Valid() const { return (type & 0x8u) != 0; } @@ -179,6 +196,10 @@ struct Image { return base_address << 8; } + operator bool() const noexcept { + return base_address != 0; + } + u32 DstSelect() const { return dst_sel_x | (dst_sel_y << 3) | (dst_sel_z << 6) | (dst_sel_w << 9); } @@ -217,10 +238,15 @@ struct Image { return pitch + 1; } - u32 NumLayers() const { + u32 NumLayers(bool is_array) const { u32 slices = GetType() == ImageType::Color3D ? 1 : depth + 1; if (GetType() == ImageType::Cube) { - slices *= 6; + if (is_array) { + slices = last_array + 1; + ASSERT(slices % 6 == 0); + } else { + slices = 6; + } } if (pow2pad) { slices = std::bit_ceil(slices); @@ -261,6 +287,11 @@ struct Image { bool IsTiled() const { return GetTilingMode() != TilingMode::Display_Linear; } + + bool IsPartialCubemap() const { + const auto viewed_slice = last_array - base_array + 1; + return GetType() == ImageType::Cube && viewed_slice < 6; + } }; static_assert(sizeof(Image) == 32); // 256bits diff --git a/src/video_core/amdgpu/types.h b/src/video_core/amdgpu/types.h new file mode 100644 index 000000000..6b95ed910 --- /dev/null +++ b/src/video_core/amdgpu/types.h @@ -0,0 +1,120 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace AmdGpu { + +enum class FpRoundMode : u32 { + NearestEven = 0, + PlusInf = 1, + MinInf = 2, + ToZero = 3, +}; + +enum class FpDenormMode : u32 { + InOutFlush = 0, + InAllowOutFlush = 1, + InFlushOutAllow = 2, + InOutAllow = 3, +}; + +// See `VGT_PRIMITIVE_TYPE` description in [Radeon Sea Islands 3D/Compute Register Reference Guide] +enum class PrimitiveType : u32 { + None = 0, + PointList = 1, + LineList = 2, + LineStrip = 3, + TriangleList = 4, + TriangleFan = 5, + TriangleStrip = 6, + PatchPrimitive = 9, + AdjLineList = 10, + AdjLineStrip = 11, + AdjTriangleList = 12, + AdjTriangleStrip = 13, + RectList = 17, + LineLoop = 18, + QuadList = 19, + QuadStrip = 20, + Polygon = 21, +}; + +enum class GsOutputPrimitiveType : u32 { + PointList = 0, + LineStrip = 1, + TriangleStrip = 2, +}; + +// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] +enum class DataFormat : u32 { + FormatInvalid = 0, + Format8 = 1, + Format16 = 2, + Format8_8 = 3, + Format32 = 4, + Format16_16 = 5, + Format10_11_11 = 6, + Format11_11_10 = 7, + Format10_10_10_2 = 8, + Format2_10_10_10 = 9, + Format8_8_8_8 = 10, + Format32_32 = 11, + Format16_16_16_16 = 12, + Format32_32_32 = 13, + Format32_32_32_32 = 14, + Format5_6_5 = 16, + Format1_5_5_5 = 17, + Format5_5_5_1 = 18, + Format4_4_4_4 = 19, + Format8_24 = 20, + Format24_8 = 21, + FormatX24_8_32 = 22, + FormatGB_GR = 32, + FormatBG_RG = 33, + Format5_9_9_9 = 34, + FormatBc1 = 35, + FormatBc2 = 36, + FormatBc3 = 37, + FormatBc4 = 38, + FormatBc5 = 39, + FormatBc6 = 40, + FormatBc7 = 41, + FormatFmask8_1 = 47, + FormatFmask8_2 = 48, + FormatFmask8_4 = 49, + FormatFmask16_1 = 50, + FormatFmask16_2 = 51, + FormatFmask32_2 = 52, + FormatFmask32_4 = 53, + FormatFmask32_8 = 54, + FormatFmask64_4 = 55, + FormatFmask64_8 = 56, + Format4_4 = 57, + Format6_5_5 = 58, + Format1 = 59, + Format1_Reversed = 60, + Format32_As_8 = 61, + Format32_As_8_8 = 62, + Format32_As_32_32_32_32 = 63, +}; + +enum class NumberFormat : u32 { + Unorm = 0, + Snorm = 1, + Uscaled = 2, + Sscaled = 3, + Uint = 4, + Sint = 5, + SnormNz = 6, + Float = 7, + Srgb = 9, + Ubnorm = 10, + UbnromNz = 11, + Ubint = 12, + Ubscaled = 13, +}; + +} // namespace AmdGpu diff --git a/src/video_core/buffer_cache/buffer.cpp b/src/video_core/buffer_cache/buffer.cpp index d112864d5..5a049c185 100644 --- a/src/video_core/buffer_cache/buffer.cpp +++ b/src/video_core/buffer_cache/buffer.cpp @@ -13,12 +13,6 @@ namespace VideoCore { -constexpr vk::BufferUsageFlags AllFlags = - vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst | - vk::BufferUsageFlagBits::eUniformTexelBuffer | vk::BufferUsageFlagBits::eStorageTexelBuffer | - vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eStorageBuffer | - vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eVertexBuffer; - std::string_view BufferTypeName(MemoryUsage type) { switch (type) { case MemoryUsage::Upload: @@ -94,14 +88,15 @@ void UniqueBuffer::Create(const vk::BufferCreateInfo& buffer_ci, MemoryUsage usa buffer = vk::Buffer{unsafe_buffer}; } -Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_addr_, - u64 size_bytes_) - : cpu_addr{cpu_addr_}, size_bytes{size_bytes_}, instance{&instance_}, usage{usage_}, - buffer{instance->GetDevice(), instance->GetAllocator()} { +Buffer::Buffer(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, MemoryUsage usage_, + VAddr cpu_addr_, vk::BufferUsageFlags flags, u64 size_bytes_) + : cpu_addr{cpu_addr_}, size_bytes{size_bytes_}, instance{&instance_}, scheduler{&scheduler_}, + usage{usage_}, buffer{instance->GetDevice(), instance->GetAllocator()} { // Create buffer object. const vk::BufferCreateInfo buffer_ci = { .size = size_bytes, - .usage = AllFlags, + // When maintenance5 is not supported, use all flags since we can't add flags to views. + .usage = instance->IsMaintenance5Supported() ? flags : AllFlags, }; VmaAllocationInfo alloc_info{}; buffer.Create(buffer_ci, usage, &alloc_info); @@ -118,35 +113,33 @@ Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_ is_coherent = property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; } -vk::BufferView Buffer::View(u32 offset, u32 size, AmdGpu::DataFormat dfmt, +vk::BufferView Buffer::View(u32 offset, u32 size, bool is_written, AmdGpu::DataFormat dfmt, AmdGpu::NumberFormat nfmt) { - const auto it{std::ranges::find_if(views, [offset, size, dfmt, nfmt](const BufferView& view) { - return offset == view.offset && size == view.size && dfmt == view.dfmt && nfmt == view.nfmt; - })}; - if (it != views.end()) { - return it->handle; - } - views.push_back({ + const vk::BufferUsageFlags2CreateInfoKHR usage_flags = { + .usage = is_written ? vk::BufferUsageFlagBits2KHR::eStorageTexelBuffer + : vk::BufferUsageFlagBits2KHR::eUniformTexelBuffer, + }; + const vk::BufferViewCreateInfo view_ci = { + .pNext = instance->IsMaintenance5Supported() ? &usage_flags : nullptr, + .buffer = buffer.buffer, + .format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt), .offset = offset, - .size = size, - .dfmt = dfmt, - .nfmt = nfmt, - .handle = instance->GetDevice().createBufferView({ - .buffer = buffer.buffer, - .format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt), - .offset = offset, - .range = size, - }), - }); - return views.back().handle; + .range = size, + }; + const auto [view_result, view] = instance->GetDevice().createBufferView(view_ci); + ASSERT_MSG(view_result == vk::Result::eSuccess, "Failed to create buffer view: {}", + vk::to_string(view_result)); + scheduler->DeferOperation( + [view, device = instance->GetDevice()] { device.destroyBufferView(view); }); + return view; } constexpr u64 WATCHES_INITIAL_RESERVE = 0x4000; constexpr u64 WATCHES_RESERVE_CHUNK = 0x1000; -StreamBuffer::StreamBuffer(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler_, +StreamBuffer::StreamBuffer(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler, MemoryUsage usage, u64 size_bytes) - : Buffer{instance, usage, 0, size_bytes}, scheduler{scheduler_} { + : Buffer{instance, scheduler, usage, 0, AllFlags, size_bytes} { ReserveWatches(current_watches, WATCHES_INITIAL_RESERVE); ReserveWatches(previous_watches, WATCHES_INITIAL_RESERVE); const auto device = instance.GetDevice(); @@ -201,7 +194,7 @@ void StreamBuffer::Commit() { auto& watch = current_watches[current_watch_cursor++]; watch.upper_bound = offset; - watch.tick = scheduler.CurrentTick(); + watch.tick = scheduler->CurrentTick(); } void StreamBuffer::ReserveWatches(std::vector& watches, std::size_t grow_size) { @@ -215,7 +208,7 @@ void StreamBuffer::WaitPendingOperations(u64 requested_upper_bound) { while (requested_upper_bound > wait_bound && wait_cursor < *invalidation_mark) { auto& watch = previous_watches[wait_cursor]; wait_bound = watch.upper_bound; - scheduler.Wait(watch.tick); + scheduler->Wait(watch.tick); ++wait_cursor; } } diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index d373fbffb..403d4ed85 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include #include "common/types.h" @@ -30,6 +31,15 @@ enum class MemoryUsage { Stream, ///< Requests device local host visible buffer, falling back host memory. }; +constexpr vk::BufferUsageFlags ReadFlags = + vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eUniformTexelBuffer | + vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eIndexBuffer | + vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eIndirectBuffer; + +constexpr vk::BufferUsageFlags AllFlags = ReadFlags | vk::BufferUsageFlagBits::eTransferDst | + vk::BufferUsageFlagBits::eStorageTexelBuffer | + vk::BufferUsageFlagBits::eStorageBuffer; + struct UniqueBuffer { explicit UniqueBuffer(vk::Device device, VmaAllocator allocator); ~UniqueBuffer(); @@ -38,9 +48,9 @@ struct UniqueBuffer { UniqueBuffer& operator=(const UniqueBuffer&) = delete; UniqueBuffer(UniqueBuffer&& other) - : buffer{std::exchange(other.buffer, VK_NULL_HANDLE)}, - allocator{std::exchange(other.allocator, VK_NULL_HANDLE)}, - allocation{std::exchange(other.allocation, VK_NULL_HANDLE)} {} + : allocator{std::exchange(other.allocator, VK_NULL_HANDLE)}, + allocation{std::exchange(other.allocation, VK_NULL_HANDLE)}, + buffer{std::exchange(other.buffer, VK_NULL_HANDLE)} {} UniqueBuffer& operator=(UniqueBuffer&& other) { buffer = std::exchange(other.buffer, VK_NULL_HANDLE); allocator = std::exchange(other.allocator, VK_NULL_HANDLE); @@ -63,7 +73,8 @@ struct UniqueBuffer { class Buffer { public: - explicit Buffer(const Vulkan::Instance& instance, MemoryUsage usage, VAddr cpu_addr_, + explicit Buffer(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler, + MemoryUsage usage, VAddr cpu_addr_, vk::BufferUsageFlags flags, u64 size_bytes_); Buffer& operator=(const Buffer&) = delete; @@ -72,7 +83,8 @@ public: Buffer& operator=(Buffer&&) = default; Buffer(Buffer&&) = default; - vk::BufferView View(u32 offset, u32 size, AmdGpu::DataFormat dfmt, AmdGpu::NumberFormat nfmt); + vk::BufferView View(u32 offset, u32 size, bool is_written, AmdGpu::DataFormat dfmt, + AmdGpu::NumberFormat nfmt); /// Increases the likeliness of this being a stream buffer void IncreaseStreamScore(int score) noexcept { @@ -107,6 +119,25 @@ public: return buffer; } + std::optional GetBarrier(vk::AccessFlagBits2 dst_acess_mask, + vk::PipelineStageFlagBits2 dst_stage) { + if (dst_acess_mask == access_mask && stage == dst_stage) { + return {}; + } + + auto barrier = vk::BufferMemoryBarrier2{ + .srcStageMask = stage, + .srcAccessMask = access_mask, + .dstStageMask = dst_stage, + .dstAccessMask = dst_acess_mask, + .buffer = buffer.buffer, + .size = size_bytes, + }; + access_mask = dst_acess_mask; + stage = dst_stage; + return barrier; + } + public: VAddr cpu_addr = 0; bool is_picked{}; @@ -114,17 +145,12 @@ public: int stream_score = 0; size_t size_bytes = 0; std::span mapped_data; - const Vulkan::Instance* instance{}; + const Vulkan::Instance* instance; + Vulkan::Scheduler* scheduler; MemoryUsage usage; UniqueBuffer buffer; - struct BufferView { - u32 offset; - u32 size; - AmdGpu::DataFormat dfmt; - AmdGpu::NumberFormat nfmt; - vk::BufferView handle; - }; - std::vector views; + vk::AccessFlagBits2 access_mask{vk::AccessFlagBits2::eNone}; + vk::PipelineStageFlagBits2 stage{vk::PipelineStageFlagBits2::eNone}; }; class StreamBuffer : public Buffer { @@ -163,7 +189,6 @@ private: void WaitPendingOperations(u64 requested_upper_bound); private: - Vulkan::Scheduler& scheduler; u64 offset{}; u64 mapped_size{}; std::vector current_watches; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 02d6b2ce4..c2993f3d1 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -4,26 +4,49 @@ #include #include "common/alignment.h" #include "common/scope_exit.h" -#include "shader_recompiler/runtime_info.h" +#include "shader_recompiler/info.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/texture_cache/texture_cache.h" namespace VideoCore { -static constexpr size_t StagingBufferSize = 512_MB; +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; BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, - const AmdGpu::Liverpool* liverpool_, PageManager& tracker_) - : instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, tracker{tracker_}, + const AmdGpu::Liverpool* liverpool_, TextureCache& texture_cache_, + PageManager& tracker_) + : instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, + texture_cache{texture_cache_}, tracker{tracker_}, staging_buffer{instance, scheduler, MemoryUsage::Upload, StagingBufferSize}, stream_buffer{instance, scheduler, MemoryUsage::Stream, UboStreamBufferSize}, + gds_buffer{instance, scheduler, MemoryUsage::Stream, 0, AllFlags, GdsBufferSize}, memory_tracker{&tracker} { + Vulkan::SetObjectName(instance.GetDevice(), gds_buffer.Handle(), "GDS Buffer"); + // Ensure the first slot is used for the null buffer - void(slot_buffers.insert(instance, MemoryUsage::DeviceLocal, 0, 1)); + const auto null_id = + slot_buffers.insert(instance, scheduler, MemoryUsage::DeviceLocal, 0, ReadFlags, 1); + 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; @@ -93,6 +116,15 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { 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); } }; @@ -100,9 +132,11 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { return false; } - std::array host_buffers; - std::array host_offsets; - boost::container::static_vector guest_buffers; + std::array host_buffers; + std::array host_offsets; + std::array host_sizes; + std::array host_strides; + boost::container::static_vector guest_buffers; struct BufferRange { VAddr base_address; @@ -117,7 +151,7 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { // Calculate buffers memory overlaps bool has_step_rate = false; - boost::container::static_vector ranges{}; + boost::container::static_vector ranges{}; for (const auto& input : vs_info.vs_inputs) { if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { @@ -152,7 +186,7 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { return lhv.base_address < rhv.base_address; }); - boost::container::static_vector ranges_merged{ranges[0]}; + 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) { @@ -181,11 +215,18 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { 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(); - cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data()); + 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()); + } } return has_step_rate; @@ -194,7 +235,7 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { // Emulate QuadList primitive type with CPU made index buffer. const auto& regs = liverpool->regs; - if (regs.primitive_type == AmdGpu::Liverpool::PrimitiveType::QuadList) { + if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList) { is_indexed = true; // Emit indices. @@ -228,11 +269,32 @@ u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { return regs.num_indices; } -std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, bool is_written) { - std::scoped_lock lk{mutex}; +void BufferCache::InlineDataToGds(u32 gds_offset, u32 value) { + ASSERT_MSG(gds_offset % 4 == 0, "GDS offset must be dword aligned"); + scheduler.EndRendering(); + const auto cmdbuf = scheduler.CommandBuffer(); + const vk::BufferMemoryBarrier2 buf_barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, + .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .dstAccessMask = vk::AccessFlagBits2::eMemoryRead, + .buffer = gds_buffer.Handle(), + .offset = gds_offset, + .size = sizeof(u32), + }; + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &buf_barrier, + }); + cmdbuf.updateBuffer(gds_buffer.Handle(), gds_offset, sizeof(u32), &value); +} + +std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, bool is_written, + bool is_texel_buffer) { static constexpr u64 StreamThreshold = CACHING_PAGESIZE; const bool is_gpu_dirty = memory_tracker.IsRegionGpuModified(device_addr, size); - if (!is_written && size < StreamThreshold && !is_gpu_dirty) { + if (!is_written && size <= StreamThreshold && !is_gpu_dirty) { // For small uniform buffers that have not been modified by gpu // use device local stream buffer to reduce renderpass breaks. const u64 offset = stream_buffer.Copy(device_addr, size, instance.UniformMinAlignment()); @@ -241,19 +303,20 @@ std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, b const BufferId buffer_id = FindBuffer(device_addr, size); Buffer& buffer = slot_buffers[buffer_id]; - SynchronizeBuffer(buffer, device_addr, size); + SynchronizeBuffer(buffer, device_addr, size, is_texel_buffer); if (is_written) { memory_tracker.MarkRegionAsGpuModified(device_addr, size); } return {&buffer, buffer.Offset(device_addr)}; } -std::pair BufferCache::ObtainTempBuffer(VAddr gpu_addr, u32 size) { +std::pair BufferCache::ObtainTempBuffer(VAddr gpu_addr, u32 size) { const u64 page = gpu_addr >> CACHING_PAGEBITS; const BufferId buffer_id = page_table[page]; if (buffer_id) { - const Buffer& buffer = slot_buffers[buffer_id]; + Buffer& buffer = slot_buffers[buffer_id]; if (buffer.IsInBounds(gpu_addr, size)) { + SynchronizeBuffer(buffer, gpu_addr, size, false); return {&buffer, buffer.Offset(gpu_addr)}; } } @@ -420,8 +483,8 @@ 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, MemoryUsage::DeviceLocal, overlap.begin, size); + const BufferId new_buffer_id = 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(); @@ -459,7 +522,9 @@ void BufferCache::ChangeRegister(BufferId buffer_id) { } } -bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size) { +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; @@ -478,8 +543,13 @@ bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size) // Prevent uploading to gpu modified regions. // gpu_modified_ranges.ForEachNotInRange(device_addr_out, range_size, add_copy); }); + SCOPE_EXIT { + if (is_texel_buffer) { + SynchronizeBufferFromImage(buffer, device_addr, size); + } + }; if (total_size_bytes == 0) { - return true; + return; } vk::Buffer src_buffer = staging_buffer.Handle(); if (total_size_bytes < StagingBufferSize) { @@ -495,7 +565,12 @@ bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size) } else { // For large one time transfers use a temporary host buffer. // RenderDoc can lag quite a bit if the stream buffer is too large. - Buffer temp_buffer{instance, MemoryUsage::Upload, 0, total_size_bytes}; + Buffer temp_buffer{instance, + scheduler, + MemoryUsage::Upload, + 0, + vk::BufferUsageFlagBits::eTransferSrc, + total_size_bytes}; src_buffer = temp_buffer.Handle(); u8* const staging = temp_buffer.mapped_data.data(); for (auto& copy : copies) { @@ -522,7 +597,61 @@ bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size) cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAllCommands, vk::DependencyFlagBits::eByRegion, WRITE_BARRIER, {}, {}); - return false; +} + +bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, u32 size) { + static constexpr FindFlags find_flags = + FindFlags::NoCreate | FindFlags::RelaxDim | FindFlags::RelaxFmt | FindFlags::RelaxSize; + ImageInfo info{}; + info.guest_address = device_addr; + info.guest_size_bytes = size; + const ImageId image_id = texture_cache.FindImage(info, find_flags); + if (!image_id) { + return false; + } + Image& image = texture_cache.GetImage(image_id); + if (False(image.flags & ImageFlagBits::GpuModified)) { + return false; + } + ASSERT_MSG(device_addr == image.info.guest_address, + "Texel buffer aliases image subresources {:x} : {:x}", device_addr, + image.info.guest_address); + boost::container::small_vector copies; + u32 offset = buffer.Offset(image.cpu_addr); + const u32 num_layers = image.info.resources.layers; + const u32 max_offset = offset + size; + for (u32 m = 0; m < image.info.resources.levels; m++) { + const u32 width = std::max(image.info.size.width >> m, 1u); + const u32 height = std::max(image.info.size.height >> m, 1u); + const u32 depth = + image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u; + const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m]; + offset += mip_ofs * num_layers; + if (offset + (mip_size * num_layers) > max_offset) { + break; + } + copies.push_back({ + .bufferOffset = offset, + .bufferRowLength = static_cast(mip_pitch), + .bufferImageHeight = static_cast(mip_height), + .imageSubresource{ + .aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil, + .mipLevel = m, + .baseArrayLayer = 0, + .layerCount = num_layers, + }, + .imageOffset = {0, 0, 0}, + .imageExtent = {width, height, depth}, + }); + } + if (!copies.empty()) { + scheduler.EndRendering(); + image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {}); + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.buffer, + copies); + } + return true; } void BufferCache::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 2bcc4f0e8..76309363a 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -28,7 +28,7 @@ using BufferId = Common::SlotId; static constexpr BufferId NULL_BUFFER_ID{0}; -static constexpr u32 NUM_VERTEX_BUFFERS = 32; +class TextureCache; class BufferCache { public: @@ -53,9 +53,24 @@ public: public: explicit BufferCache(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler, - const AmdGpu::Liverpool* liverpool, PageManager& tracker); + const AmdGpu::Liverpool* liverpool, TextureCache& texture_cache, + PageManager& tracker); ~BufferCache(); + /// Returns a pointer to GDS device local buffer. + [[nodiscard]] const Buffer* GetGdsBuffer() const noexcept { + return &gds_buffer; + } + + /// Retrieves the buffer with the specified id. + [[nodiscard]] Buffer& GetBuffer(BufferId id) { + 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); @@ -65,11 +80,15 @@ public: /// Bind host index buffer for the current draw. u32 BindIndexBuffer(bool& is_indexed, u32 index_offset); + /// Writes a value to GDS buffer. + void InlineDataToGds(u32 gds_offset, u32 value); + /// Obtains a buffer for the specified region. - [[nodiscard]] std::pair ObtainBuffer(VAddr gpu_addr, u32 size, bool is_written); + [[nodiscard]] std::pair ObtainBuffer(VAddr gpu_addr, u32 size, bool is_written, + bool is_texel_buffer = false); /// Obtains a temporary buffer for usage in texture cache. - [[nodiscard]] std::pair ObtainTempBuffer(VAddr gpu_addr, u32 size); + [[nodiscard]] std::pair ObtainTempBuffer(VAddr gpu_addr, u32 size); /// Return true when a region is registered on the cache [[nodiscard]] bool IsRegionRegistered(VAddr addr, size_t size); @@ -115,18 +134,23 @@ private: template void ChangeRegister(BufferId buffer_id); - bool SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size); + void SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, bool is_texel_buffer); + + bool SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, u32 size); void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false); const Vulkan::Instance& instance; Vulkan::Scheduler& scheduler; const AmdGpu::Liverpool* liverpool; + TextureCache& texture_cache; PageManager& tracker; StreamBuffer staging_buffer; StreamBuffer stream_buffer; - std::recursive_mutex mutex; + Buffer gds_buffer; + std::mutex mutex; Common::SlotVector slot_buffers; + vk::BufferView null_buffer_view; MemoryTracker memory_tracker; PageTable page_table; }; diff --git a/src/video_core/host_shaders/detile_m8x1.comp b/src/video_core/host_shaders/detile_m8x1.comp index 5ec48fae2..3ca2e64bd 100644 --- a/src/video_core/host_shaders/detile_m8x1.comp +++ b/src/video_core/host_shaders/detile_m8x1.comp @@ -4,7 +4,7 @@ #version 450 #extension GL_KHR_shader_subgroup_shuffle : require -// NOTE: Current subgroup utilization is subotimal on most GPUs, so +// NOTE: Current subgroup utilization is suboptimal on most GPUs, so // it will be nice to process two tiles at once here. layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in; diff --git a/src/video_core/host_shaders/detile_m8x2.comp b/src/video_core/host_shaders/detile_m8x2.comp index d27bc6e2d..ee9b72810 100644 --- a/src/video_core/host_shaders/detile_m8x2.comp +++ b/src/video_core/host_shaders/detile_m8x2.comp @@ -3,7 +3,7 @@ #version 450 -// NOTE: Current subgroup utilization is subotimal on most GPUs, so +// NOTE: Current subgroup utilization is suboptimal on most GPUs, so // it will be nice to process two tiles at once here. layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in; diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index 6225f11ba..a49fff43a 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -2,20 +2,22 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "common/alignment.h" #include "common/assert.h" #include "common/error.h" +#include "common/signal_context.h" +#include "core/signals.h" #include "video_core/page_manager.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" #ifndef _WIN64 -#include -#include -#include -#include #include #ifdef ENABLE_USERFAULTFD +#include #include +#include +#include #endif #else #include @@ -26,44 +28,7 @@ namespace VideoCore { constexpr size_t PAGESIZE = 4_KB; constexpr size_t PAGEBITS = 12; -#ifdef _WIN64 -struct PageManager::Impl { - Impl(Vulkan::Rasterizer* rasterizer_) { - rasterizer = rasterizer_; - - veh_handle = AddVectoredExceptionHandler(0, GuestFaultSignalHandler); - ASSERT_MSG(veh_handle, "Failed to register an exception handler"); - } - - void OnMap(VAddr address, size_t size) {} - - void OnUnmap(VAddr address, size_t size) {} - - void Protect(VAddr address, size_t size, bool allow_write) { - DWORD prot = allow_write ? PAGE_READWRITE : PAGE_READONLY; - DWORD old_prot{}; - BOOL result = VirtualProtect(std::bit_cast(address), size, prot, &old_prot); - ASSERT_MSG(result != 0, "Region protection failed"); - } - - static LONG WINAPI GuestFaultSignalHandler(EXCEPTION_POINTERS* pExp) noexcept { - const u32 ec = pExp->ExceptionRecord->ExceptionCode; - if (ec == EXCEPTION_ACCESS_VIOLATION) { - const auto info = pExp->ExceptionRecord->ExceptionInformation; - if (info[0] == 1) { // Write violation - rasterizer->InvalidateMemory(info[1], sizeof(u64)); - return EXCEPTION_CONTINUE_EXECUTION; - } /* else { - UNREACHABLE(); - }*/ - } - return EXCEPTION_CONTINUE_SEARCH; // pass further - } - - inline static Vulkan::Rasterizer* rasterizer; - void* veh_handle{}; -}; -#elif ENABLE_USERFAULTFD +#if ENABLE_USERFAULTFD struct PageManager::Impl { Impl(Vulkan::Rasterizer* rasterizer_) : rasterizer{rasterizer_} { uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); @@ -162,51 +127,48 @@ struct PageManager::Impl { Impl(Vulkan::Rasterizer* rasterizer_) { rasterizer = rasterizer_; -#ifdef __APPLE__ - // Read-only memory write results in SIGBUS on Apple. - static constexpr int SignalType = SIGBUS; -#else - static constexpr int SignalType = SIGSEGV; -#endif - sigset_t signal_mask; - sigemptyset(&signal_mask); - sigaddset(&signal_mask, SignalType); - - using HandlerType = decltype(sigaction::sa_sigaction); - - struct sigaction guest_access_fault {}; - guest_access_fault.sa_flags = SA_SIGINFO | SA_ONSTACK; - guest_access_fault.sa_sigaction = &GuestFaultSignalHandler; - guest_access_fault.sa_mask = signal_mask; - sigaction(SignalType, &guest_access_fault, nullptr); + // Should be called first. + constexpr auto priority = std::numeric_limits::min(); + Core::Signals::Instance()->RegisterAccessViolationHandler(GuestFaultSignalHandler, + priority); } - void OnMap(VAddr address, size_t size) {} + void OnMap(VAddr address, size_t size) { + owned_ranges += boost::icl::interval::right_open(address, address + size); + } - void OnUnmap(VAddr address, size_t size) {} + void OnUnmap(VAddr address, size_t size) { + owned_ranges -= boost::icl::interval::right_open(address, address + size); + } void Protect(VAddr address, size_t size, bool allow_write) { + ASSERT_MSG(owned_ranges.find(address) != owned_ranges.end(), + "Attempted to track non-GPU memory at address {:#x}, size {:#x}.", address, + size); +#ifdef _WIN32 + DWORD prot = allow_write ? PAGE_READWRITE : PAGE_READONLY; + DWORD old_prot{}; + BOOL result = VirtualProtect(std::bit_cast(address), size, prot, &old_prot); + ASSERT_MSG(result != 0, "Region protection failed"); +#else mprotect(reinterpret_cast(address), size, PROT_READ | (allow_write ? PROT_WRITE : 0)); +#endif } - static void GuestFaultSignalHandler(int sig, siginfo_t* info, void* raw_context) { - ucontext_t* ctx = reinterpret_cast(raw_context); - const VAddr address = reinterpret_cast(info->si_addr); -#ifdef __APPLE__ - const u32 err = ctx->uc_mcontext->__es.__err; -#else - const greg_t err = ctx->uc_mcontext.gregs[REG_ERR]; -#endif - if (err & 0x2) { - rasterizer->InvalidateMemory(address, sizeof(u64)); - } else { - // Read not supported! - UNREACHABLE(); + static bool GuestFaultSignalHandler(void* context, void* fault_address) { + const auto addr = reinterpret_cast(fault_address); + const bool is_write = Common::IsWriteError(context); + if (is_write && owned_ranges.find(addr) != owned_ranges.end()) { + const VAddr addr_aligned = Common::AlignDown(addr, PAGESIZE); + rasterizer->InvalidateMemory(addr_aligned, PAGESIZE); + return true; } + return false; } inline static Vulkan::Rasterizer* rasterizer; + inline static boost::icl::interval_set owned_ranges; }; #endif diff --git a/src/video_core/renderdoc.cpp b/src/video_core/renderdoc.cpp index 7f88e1264..7e0994992 100644 --- a/src/video_core/renderdoc.cpp +++ b/src/video_core/renderdoc.cpp @@ -110,11 +110,11 @@ void TriggerCapture() { } } -void SetOutputDir(const std::string& path, const std::string& prefix) { +void SetOutputDir(const std::filesystem::path& path, const std::string& prefix) { if (!rdoc_api) { return; } - rdoc_api->SetCaptureFilePathTemplate((path + '\\' + prefix).c_str()); + rdoc_api->SetCaptureFilePathTemplate(fmt::UTF((path / prefix).u8string()).data.data()); } } // namespace VideoCore diff --git a/src/video_core/renderdoc.h b/src/video_core/renderdoc.h index febf6fbc1..91e242d04 100644 --- a/src/video_core/renderdoc.h +++ b/src/video_core/renderdoc.h @@ -20,6 +20,6 @@ void EndCapture(); void TriggerCapture(); /// Sets output directory for captures -void SetOutputDir(const std::string& path, const std::string& prefix); +void SetOutputDir(const std::filesystem::path& path, const std::string& prefix); } // namespace VideoCore diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index daf64a4d3..3e43c50e5 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -2,11 +2,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "common/number_utils.h" #include "video_core/amdgpu/pixel_format.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include +#define INVALID_NUMBER_FORMAT_COMBO \ + LOG_ERROR(Render_Vulkan, "Unsupported number type {} for format {}", number_type, format); + namespace Vulkan::LiverpoolToVK { using DepthBuffer = Liverpool::DepthBuffer; @@ -61,34 +65,34 @@ vk::CompareOp CompareOp(Liverpool::CompareFunc func) { } } -vk::PrimitiveTopology PrimitiveType(Liverpool::PrimitiveType type) { +vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type) { switch (type) { - case Liverpool::PrimitiveType::PointList: + case AmdGpu::PrimitiveType::PointList: return vk::PrimitiveTopology::ePointList; - case Liverpool::PrimitiveType::LineList: + case AmdGpu::PrimitiveType::LineList: return vk::PrimitiveTopology::eLineList; - case Liverpool::PrimitiveType::LineStrip: + case AmdGpu::PrimitiveType::LineStrip: return vk::PrimitiveTopology::eLineStrip; - case Liverpool::PrimitiveType::TriangleList: + case AmdGpu::PrimitiveType::TriangleList: return vk::PrimitiveTopology::eTriangleList; - case Liverpool::PrimitiveType::TriangleFan: + case AmdGpu::PrimitiveType::TriangleFan: return vk::PrimitiveTopology::eTriangleFan; - case Liverpool::PrimitiveType::TriangleStrip: + case AmdGpu::PrimitiveType::TriangleStrip: return vk::PrimitiveTopology::eTriangleStrip; - case Liverpool::PrimitiveType::AdjLineList: + case AmdGpu::PrimitiveType::AdjLineList: return vk::PrimitiveTopology::eLineListWithAdjacency; - case Liverpool::PrimitiveType::AdjLineStrip: + case AmdGpu::PrimitiveType::AdjLineStrip: return vk::PrimitiveTopology::eLineStripWithAdjacency; - case Liverpool::PrimitiveType::AdjTriangleList: + case AmdGpu::PrimitiveType::AdjTriangleList: return vk::PrimitiveTopology::eTriangleListWithAdjacency; - case Liverpool::PrimitiveType::AdjTriangleStrip: + case AmdGpu::PrimitiveType::AdjTriangleStrip: return vk::PrimitiveTopology::eTriangleStripWithAdjacency; - case Liverpool::PrimitiveType::PatchPrimitive: + case AmdGpu::PrimitiveType::PatchPrimitive: return vk::PrimitiveTopology::ePatchList; - case Liverpool::PrimitiveType::QuadList: + case AmdGpu::PrimitiveType::QuadList: // Needs to generate index buffer on the fly. return vk::PrimitiveTopology::eTriangleList; - case Liverpool::PrimitiveType::RectList: + case AmdGpu::PrimitiveType::RectList: return vk::PrimitiveTopology::eTriangleStrip; default: UNREACHABLE(); @@ -199,8 +203,17 @@ vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode) { return vk::SamplerAddressMode::eMirroredRepeat; case AmdGpu::ClampMode::ClampLastTexel: return vk::SamplerAddressMode::eClampToEdge; + case AmdGpu::ClampMode::MirrorOnceHalfBorder: + case AmdGpu::ClampMode::MirrorOnceBorder: + LOG_WARNING(Render_Vulkan, "Unimplemented clamp mode {}, using closest equivalent.", + static_cast(mode)); + [[fallthrough]]; case AmdGpu::ClampMode::MirrorOnceLastTexel: return vk::SamplerAddressMode::eMirrorClampToEdge; + case AmdGpu::ClampMode::ClampHalfBorder: + LOG_WARNING(Render_Vulkan, "Unimplemented clamp mode {}, using closest equivalent.", + static_cast(mode)); + [[fallthrough]]; case AmdGpu::ClampMode::ClampBorder: return vk::SamplerAddressMode::eClampToBorder; default: @@ -285,301 +298,345 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) { } } -std::span GetAllFormats() { +static constexpr vk::FormatFeatureFlags2 BufferRead = + vk::FormatFeatureFlagBits2::eUniformTexelBuffer | vk::FormatFeatureFlagBits2::eVertexBuffer; +static constexpr vk::FormatFeatureFlags2 BufferWrite = + vk::FormatFeatureFlagBits2::eStorageTexelBuffer | + vk::FormatFeatureFlagBits2::eStorageReadWithoutFormat | + vk::FormatFeatureFlagBits2::eStorageWriteWithoutFormat; +static constexpr vk::FormatFeatureFlags2 ImageRead = vk::FormatFeatureFlagBits2::eTransferSrc | + vk::FormatFeatureFlagBits2::eTransferDst | + vk::FormatFeatureFlagBits2::eSampledImage; +static constexpr vk::FormatFeatureFlags2 ImageWrite = + vk::FormatFeatureFlagBits2::eStorageImage | + vk::FormatFeatureFlagBits2::eStorageReadWithoutFormat | + vk::FormatFeatureFlagBits2::eStorageWriteWithoutFormat; +static constexpr vk::FormatFeatureFlags2 Mrt = vk::FormatFeatureFlagBits2::eColorAttachment; + +// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] +static constexpr vk::FormatFeatureFlags2 GetDataFormatFeatureFlags( + const AmdGpu::DataFormat data_format) { + switch (data_format) { + case AmdGpu::DataFormat::FormatInvalid: + case AmdGpu::DataFormat::Format8: + case AmdGpu::DataFormat::Format16: + case AmdGpu::DataFormat::Format8_8: + case AmdGpu::DataFormat::Format32: + case AmdGpu::DataFormat::Format16_16: + case AmdGpu::DataFormat::Format10_11_11: + case AmdGpu::DataFormat::Format11_11_10: + case AmdGpu::DataFormat::Format10_10_10_2: + case AmdGpu::DataFormat::Format2_10_10_10: + case AmdGpu::DataFormat::Format8_8_8_8: + case AmdGpu::DataFormat::Format32_32: + case AmdGpu::DataFormat::Format16_16_16_16: + case AmdGpu::DataFormat::Format32_32_32_32: + return BufferRead | BufferWrite | ImageRead | ImageWrite | Mrt; + case AmdGpu::DataFormat::Format32_32_32: + return BufferRead | BufferWrite | ImageRead; + case AmdGpu::DataFormat::Format5_6_5: + case AmdGpu::DataFormat::Format1_5_5_5: + case AmdGpu::DataFormat::Format5_5_5_1: + case AmdGpu::DataFormat::Format4_4_4_4: + return ImageRead | ImageWrite | Mrt; + case AmdGpu::DataFormat::Format8_24: + case AmdGpu::DataFormat::Format24_8: + case AmdGpu::DataFormat::FormatX24_8_32: + return ImageRead | Mrt; + case AmdGpu::DataFormat::FormatGB_GR: + case AmdGpu::DataFormat::FormatBG_RG: + case AmdGpu::DataFormat::Format5_9_9_9: + case AmdGpu::DataFormat::FormatBc1: + case AmdGpu::DataFormat::FormatBc2: + case AmdGpu::DataFormat::FormatBc3: + case AmdGpu::DataFormat::FormatBc4: + case AmdGpu::DataFormat::FormatBc5: + case AmdGpu::DataFormat::FormatBc6: + case AmdGpu::DataFormat::FormatBc7: + case AmdGpu::DataFormat::Format4_4: + case AmdGpu::DataFormat::Format6_5_5: + case AmdGpu::DataFormat::Format1: + case AmdGpu::DataFormat::Format1_Reversed: + case AmdGpu::DataFormat::Format32_As_8: + case AmdGpu::DataFormat::Format32_As_8_8: + case AmdGpu::DataFormat::Format32_As_32_32_32_32: + return ImageRead; + case AmdGpu::DataFormat::FormatFmask8_1: + case AmdGpu::DataFormat::FormatFmask8_2: + case AmdGpu::DataFormat::FormatFmask8_4: + case AmdGpu::DataFormat::FormatFmask16_1: + case AmdGpu::DataFormat::FormatFmask16_2: + case AmdGpu::DataFormat::FormatFmask32_2: + case AmdGpu::DataFormat::FormatFmask32_4: + case AmdGpu::DataFormat::FormatFmask32_8: + case AmdGpu::DataFormat::FormatFmask64_4: + case AmdGpu::DataFormat::FormatFmask64_8: + return ImageRead | ImageWrite; + } + UNREACHABLE_MSG("Missing feature flags for data format {}", static_cast(data_format)); +} + +// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] +static constexpr vk::FormatFeatureFlags2 GetNumberFormatFeatureFlags( + const AmdGpu::NumberFormat number_format) { + switch (number_format) { + case AmdGpu::NumberFormat::Unorm: + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + case AmdGpu::NumberFormat::Float: + return BufferRead | BufferWrite | ImageRead | ImageWrite | Mrt; + case AmdGpu::NumberFormat::Uscaled: + case AmdGpu::NumberFormat::Sscaled: + case AmdGpu::NumberFormat::SnormNz: + return BufferRead | ImageRead; + case AmdGpu::NumberFormat::Srgb: + return ImageRead | Mrt; + case AmdGpu::NumberFormat::Ubnorm: + case AmdGpu::NumberFormat::UbnromNz: + case AmdGpu::NumberFormat::Ubint: + case AmdGpu::NumberFormat::Ubscaled: + return ImageRead; + } + UNREACHABLE_MSG("Missing feature flags for number format {}", static_cast(number_format)); +} + +static constexpr SurfaceFormatInfo CreateSurfaceFormatInfo(const AmdGpu::DataFormat data_format, + const AmdGpu::NumberFormat number_format, + const vk::Format vk_format) { + return { + .data_format = data_format, + .number_format = number_format, + .vk_format = vk_format, + .flags = + GetDataFormatFeatureFlags(data_format) & GetNumberFormatFeatureFlags(number_format), + }; +} + +std::span SurfaceFormats() { static constexpr std::array formats{ - vk::Format::eA2B10G10R10UnormPack32, - vk::Format::eA2R10G10B10SnormPack32, - vk::Format::eA2R10G10B10UnormPack32, - vk::Format::eB5G6R5UnormPack16, - vk::Format::eB8G8R8A8Srgb, - vk::Format::eB8G8R8A8Unorm, - vk::Format::eB10G11R11UfloatPack32, - vk::Format::eBc1RgbaSrgbBlock, - vk::Format::eBc1RgbaUnormBlock, - vk::Format::eBc2UnormBlock, - vk::Format::eBc3SrgbBlock, - vk::Format::eBc3UnormBlock, - vk::Format::eBc4UnormBlock, - vk::Format::eBc5UnormBlock, - vk::Format::eBc5SnormBlock, - vk::Format::eBc7SrgbBlock, - vk::Format::eBc7UnormBlock, - vk::Format::eD16Unorm, - vk::Format::eD16UnormS8Uint, - vk::Format::eD32Sfloat, - vk::Format::eD32SfloatS8Uint, - vk::Format::eR4G4B4A4UnormPack16, - vk::Format::eR5G6B5UnormPack16, - vk::Format::eR8G8B8A8Srgb, - vk::Format::eR8G8B8A8Uint, - vk::Format::eR8G8B8A8Unorm, - vk::Format::eR8G8B8A8Snorm, - vk::Format::eR8G8B8A8Uscaled, - vk::Format::eR8G8Snorm, - vk::Format::eR8G8Uint, - vk::Format::eR8G8Unorm, - vk::Format::eR8Sint, - vk::Format::eR8Uint, - vk::Format::eR8Unorm, - vk::Format::eR8Srgb, - vk::Format::eR16G16B16A16Sfloat, - vk::Format::eR16G16B16A16Sint, - vk::Format::eR16G16B16A16Snorm, - vk::Format::eR16G16B16A16Uint, - vk::Format::eR16G16B16A16Unorm, - vk::Format::eR16G16Sfloat, - vk::Format::eR16G16Sint, - vk::Format::eR16G16Snorm, - vk::Format::eR16Sfloat, - vk::Format::eR16Uint, - vk::Format::eR16Unorm, - vk::Format::eR32G32B32A32Sfloat, - vk::Format::eR32G32B32A32Sint, - vk::Format::eR32G32B32A32Uint, - vk::Format::eR32G32B32Sfloat, - vk::Format::eR32G32B32Uint, - vk::Format::eR32G32Sfloat, - vk::Format::eR32G32Uint, - vk::Format::eR32Sfloat, - vk::Format::eR32Sint, - vk::Format::eR32Uint, - vk::Format::eBc6HUfloatBlock, - vk::Format::eBc6HSfloatBlock, - vk::Format::eR16G16Unorm, - vk::Format::eR16G16B16A16Sscaled, - vk::Format::eR16G16Sscaled, - vk::Format::eE5B9G9R9UfloatPack32, + // Invalid + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Unorm, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Snorm, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Uscaled, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Sscaled, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Uint, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Sint, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::SnormNz, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Float, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Srgb, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubnorm, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::UbnromNz, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubint, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubscaled, + vk::Format::eUndefined), + // 8 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Unorm, + vk::Format::eR8Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Snorm, + vk::Format::eR8Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Uint, + vk::Format::eR8Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Sint, + vk::Format::eR8Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Srgb, + vk::Format::eR8Srgb), + // 16 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Unorm, + vk::Format::eR16Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Snorm, + vk::Format::eR16Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Uint, + vk::Format::eR16Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Sint, + vk::Format::eR16Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Float, + vk::Format::eR16Sfloat), + // 8_8 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Unorm, + vk::Format::eR8G8Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Snorm, + vk::Format::eR8G8Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Uint, + vk::Format::eR8G8Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Sint, + vk::Format::eR8G8Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Srgb, + vk::Format::eR8G8Srgb), + // 32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32, AmdGpu::NumberFormat::Float, + vk::Format::eR32Sfloat), + // 16_16 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Unorm, + 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, + vk::Format::eR16G16Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Float, + vk::Format::eR16G16Sfloat), + // 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 + // 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), + // 8_8_8_8 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Unorm, + 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, + vk::Format::eR8G8B8A8Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Srgb, + vk::Format::eR8G8B8A8Srgb), + // 32_32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32G32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32G32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32, AmdGpu::NumberFormat::Float, + vk::Format::eR32G32Sfloat), + // 16_16_16_16 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Unorm, + 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, + vk::Format::eR16G16B16A16Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, + AmdGpu::NumberFormat::SnormNz, vk::Format::eR16G16B16A16Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Float, + vk::Format::eR16G16B16A16Sfloat), + // 32_32_32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32G32B32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32G32B32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32, AmdGpu::NumberFormat::Float, + vk::Format::eR32G32B32Sfloat), + // 32_32_32_32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32_32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32G32B32A32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32_32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32G32B32A32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32_32, AmdGpu::NumberFormat::Float, + vk::Format::eR32G32B32A32Sfloat), + // 5_6_5 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_6_5, AmdGpu::NumberFormat::Unorm, + vk::Format::eB5G6R5UnormPack16), + // 1_5_5_5 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm, + vk::Format::eR5G5B5A1UnormPack16), + // 5_5_5_1 + // 4_4_4_4 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format4_4_4_4, AmdGpu::NumberFormat::Unorm, + vk::Format::eR4G4B4A4UnormPack16), + // 8_24 + // 24_8 + // X24_8_32 + // GB_GR + // BG_RG + // 5_9_9_9 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_9_9_9, AmdGpu::NumberFormat::Float, + vk::Format::eE5B9G9R9UfloatPack32), + // BC1 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc1, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc1RgbaUnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc1, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc1RgbaSrgbBlock), + // BC2 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc2, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc2UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc2, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc2SrgbBlock), + // BC3 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc3, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc3UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc3, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc3SrgbBlock), + // BC4 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc4, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc4UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc4, AmdGpu::NumberFormat::Snorm, + vk::Format::eBc4SnormBlock), + // BC5 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc5, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc5UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc5, AmdGpu::NumberFormat::Snorm, + vk::Format::eBc5SnormBlock), + // BC6 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc6, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc6HUfloatBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc6, AmdGpu::NumberFormat::Snorm, + vk::Format::eBc6HSfloatBlock), + // BC7 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc7, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc7UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc7, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc7SrgbBlock), }; return formats; } vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { - - if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32G32B32A32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32G32B32Uint; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR8G8B8A8Unorm; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eR8G8B8A8Srgb; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32G32B32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32_32 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32G32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format5_6_5 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eB5G6R5UnormPack16; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR8Unorm; - } - if (data_format == AmdGpu::DataFormat::FormatBc3 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc3SrgbBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc3 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc3UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc4 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc4UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc5 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc5UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc5 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eBc5SnormBlock; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR16G16B16A16Sint; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Sscaled) { - return vk::Format::eR16G16B16A16Sscaled; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16G16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR16G16Unorm; - } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eA2B10G10R10UnormPack32; - } - if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc7SrgbBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc1 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc1RgbaUnormBlock; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR8G8B8A8Uint; - } - if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16G16B16A16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32Uint; - } - if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR32Sint; - } - if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR8G8Unorm; - } - if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR8G8Snorm; - } - if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc7UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc2UnormBlock; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR16G16Snorm; - } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eA2R10G10B10UnormPack32; - } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eA2R10G10B10SnormPack32; - } - if (data_format == AmdGpu::DataFormat::Format10_11_11 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eB10G11R11UfloatPack32; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16G16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR16G16B16A16Snorm; - } - if (data_format == AmdGpu::DataFormat::Format32_32 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32G32Uint; - } - if (data_format == AmdGpu::DataFormat::Format4_4_4_4 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR4G4B4A4UnormPack16; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR16G16B16A16Uint; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32G32B32A32Uint; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR32G32B32A32Sint; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR8Sint; - } - if (data_format == AmdGpu::DataFormat::FormatBc1 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc1RgbaSrgbBlock; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR16G16Sint; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Sscaled) { - return vk::Format::eR16G16Sscaled; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Uscaled) { - return vk::Format::eR8G8B8A8Uscaled; - } - if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR16Unorm; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR16G16B16A16Unorm; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR16G16Uint; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR8Uint; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::SnormNz) { - return vk::Format::eR16G16B16A16Snorm; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR8G8B8A8Snorm; - } - if (data_format == AmdGpu::DataFormat::FormatBc6 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc6HUfloatBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc6 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eBc6HSfloatBlock; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR8G8B8A8Sint; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eR8Srgb; - } - if (data_format == AmdGpu::DataFormat::Format11_11_10 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eB10G11R11UfloatPack32; - } - if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR16Uint; - } - if (data_format == AmdGpu::DataFormat::Format5_9_9_9 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eE5B9G9R9UfloatPack32; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR8Snorm; - } - UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(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; } vk::Format AdjustColorBufferFormat(vk::Format base_format, Liverpool::ColorBuffer::SwapMode comp_swap, bool is_vo_surface) { - ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard || - comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate, - "Unsupported component swap mode {}", static_cast(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: @@ -590,9 +647,23 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, return is_vo_surface ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb; case vk::Format::eB8G8R8A8Srgb: return is_vo_surface ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb; + case vk::Format::eA2B10G10R10UnormPack32: + return vk::Format::eA2R10G10B10UnormPack32; default: break; } + } else if (comp_swap_reverse) { + switch (base_format) { + case vk::Format::eR8G8B8A8Unorm: + return vk::Format::eA8B8G8R8UnormPack32; + case vk::Format::eR8G8B8A8Srgb: + return is_vo_surface ? vk::Format::eA8B8G8R8UnormPack32 + : vk::Format::eA8B8G8R8SrgbPack32; + default: + break; + } + } else if (comp_swap_alt_reverse) { + return base_format; } else { if (is_vo_surface && base_format == vk::Format::eR8G8B8A8Srgb) { return vk::Format::eR8G8B8A8Unorm; @@ -604,30 +675,45 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, return base_format; } -vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) { +static constexpr DepthFormatInfo CreateDepthFormatInfo( + const DepthBuffer::ZFormat z_format, const DepthBuffer::StencilFormat stencil_format, + const vk::Format vk_format) { + return { + .z_format = z_format, + .stencil_format = stencil_format, + .vk_format = vk_format, + .flags = vk::FormatFeatureFlagBits2::eDepthStencilAttachment, + }; +} + +std::span DepthFormats() { using ZFormat = DepthBuffer::ZFormat; using StencilFormat = DepthBuffer::StencilFormat; + static constexpr std::array formats{ + // Invalid + CreateDepthFormatInfo(ZFormat::Invalid, StencilFormat::Invalid, vk::Format::eUndefined), + CreateDepthFormatInfo(ZFormat::Invalid, StencilFormat::Stencil8, + vk::Format::eD32SfloatS8Uint), + // 16 + CreateDepthFormatInfo(ZFormat::Z16, StencilFormat::Invalid, vk::Format::eD16Unorm), + CreateDepthFormatInfo(ZFormat::Z16, StencilFormat::Stencil8, vk::Format::eD16UnormS8Uint), + // 32_Float + CreateDepthFormatInfo(ZFormat::Z32Float, StencilFormat::Invalid, vk::Format::eD32Sfloat), + CreateDepthFormatInfo(ZFormat::Z32Float, StencilFormat::Stencil8, + vk::Format::eD32SfloatS8Uint), + }; + return formats; +} - if (z_format == ZFormat::Z32Float && stencil_format == StencilFormat::Stencil8) { - return vk::Format::eD32SfloatS8Uint; - } - if (z_format == ZFormat::Z32Float && stencil_format == StencilFormat::Invalid) { - return vk::Format::eD32Sfloat; - } - if (z_format == ZFormat::Z16 && stencil_format == StencilFormat::Invalid) { - return vk::Format::eD16Unorm; - } - if (z_format == ZFormat::Z16 && stencil_format == StencilFormat::Stencil8) { - return vk::Format::eD16UnormS8Uint; - } - if (z_format == ZFormat::Invalid && stencil_format == StencilFormat::Stencil8) { - return vk::Format::eD32SfloatS8Uint; - } - if (z_format == ZFormat::Invalid && stencil_format == StencilFormat::Invalid) { - return vk::Format::eUndefined; - } - UNREACHABLE_MSG("Unsupported depth/stencil format. depth = {} stencil = {}", - magic_enum::enum_name(z_format), magic_enum::enum_name(stencil_format)); +vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) { + const auto& formats = DepthFormats(); + const auto format = + std::find_if(formats.begin(), formats.end(), [&](const DepthFormatInfo& format_info) { + return format_info.z_format == z_format && format_info.stencil_format == stencil_format; + }); + ASSERT_MSG(format != formats.end(), "Unknown z_format={} and stencil_format={}", + static_cast(z_format), static_cast(stencil_format)); + return format->vk_format; } void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { @@ -637,65 +723,372 @@ void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { *out_data++ = i; *out_data++ = i + 1; *out_data++ = i + 2; - *out_data++ = i + 2; *out_data++ = i; + *out_data++ = i + 2; *out_data++ = i + 3; } } -static constexpr float U8ToUnorm(u8 v) { - static constexpr auto c = 1.0f / 255.0f; - return float(v * c); -} - vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) { const auto comp_swap = color_buffer.info.comp_swap.Value(); - ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard || - comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate, - "Unsupported component swap mode {}", static_cast(comp_swap)); - - const bool comp_swap_alt = comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate; + const auto format = color_buffer.info.format.Value(); + const auto number_type = color_buffer.info.number_type.Value(); 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{}; - switch (color_buffer.info.number_type) { - case AmdGpu::NumberFormat::Snorm: - [[fallthrough]]; - case AmdGpu::NumberFormat::SnormNz: - [[fallthrough]]; - case AmdGpu::NumberFormat::Unorm: - [[fallthrough]]; - case AmdGpu::NumberFormat::Srgb: { - switch (num_bits) { - case 32: { - color.float32 = std::array{ - U8ToUnorm((c0 >> (comp_swap_alt ? 16 : 0)) & 0xff), - U8ToUnorm((c0 >> 8) & 0xff), - U8ToUnorm((c0 >> (comp_swap_alt ? 0 : 16)) & 0xff), - U8ToUnorm((c0 >> 24) & 0xff), - }; - break; - } - default: { - LOG_ERROR(Render_Vulkan, "Missing clear color conversion for bits {}", num_bits); - break; - } - } + + switch (number_type) { + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[3] = 1; + break; + default: + color.float32[3] = 1.0f; break; } - default: { - LOG_ERROR(Render_Vulkan, "Missing clear color conversion for type {}", - color_buffer.info.number_type.Value()); + + switch (format) { + case AmdGpu::DataFormat::Format8: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + case AmdGpu::NumberFormat::Srgb: // Should we handle gamma correction here? + color.float32[0] = NumberUtils::U8ToUnorm(c0 & 0xff); + break; + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S8ToSnorm(c0 & 0xff); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0; + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format16: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + color.float32[0] = NumberUtils::U16ToUnorm(c0 & 0xffff); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S16ToSnorm(c0 & 0xffff); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0; + break; + case AmdGpu::NumberFormat::Float: + color.float32[0] = NumberUtils::Uf16ToF32(c0 & 0xffff); + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format8_8: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + case AmdGpu::NumberFormat::Srgb: // Should we handle gamma correction here? + color.float32[0] = NumberUtils::U8ToUnorm(c0 & 0xff); + color.float32[1] = NumberUtils::U8ToUnorm((c0 >> 8) & 0xff); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S8ToSnorm(c0 & 0xff); + color.float32[1] = NumberUtils::S8ToSnorm((c0 >> 8) & 0xff); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0 & 0xff; + color.uint32[1] = (c0 >> 8) & 0xff; + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format32: + switch (number_type) { + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0; + break; + case AmdGpu::NumberFormat::Float: + color.float32[0] = *(reinterpret_cast(&c0)); + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format16_16: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + color.float32[0] = NumberUtils::U16ToUnorm(c0 & 0xffff); + color.float32[1] = NumberUtils::U16ToUnorm((c0 >> 16) & 0xffff); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S16ToSnorm(c0 & 0xffff); + color.float32[1] = NumberUtils::S16ToSnorm((c0 >> 16) & 0xffff); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0 & 0xffff; + color.uint32[1] = (c0 >> 16) & 0xffff; + break; + case AmdGpu::NumberFormat::Float: + color.float32[0] = NumberUtils::Uf16ToF32(c0 & 0xffff); + color.float32[1] = NumberUtils::Uf16ToF32((c0 >> 16) & 0xffff); + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format10_11_11: + color.float32[0] = NumberUtils::Uf11ToF32(c0 & 0x7ff); + color.float32[1] = NumberUtils::Uf11ToF32((c0 >> 11) & 0x7ff); + color.float32[2] = NumberUtils::Uf10ToF32((c0 >> 22) & 0x3ff); + break; + case AmdGpu::DataFormat::Format11_11_10: + color.float32[0] = NumberUtils::Uf10ToF32(c0 & 0x3ff); + color.float32[1] = NumberUtils::Uf11ToF32((c0 >> 10) & 0x7ff); + color.float32[2] = NumberUtils::Uf11ToF32((c0 >> 21) & 0x7ff); + break; + case AmdGpu::DataFormat::Format5_9_9_9: { + int exponent; + union { + float f; + u32 u; + } scale; + + exponent = (c0 >> 27) - 10; + scale.u = (exponent + 127) << 23; + + color.float32[0] = (c0 & 0x1ff) * scale.f; + color.float32[1] = ((c0 >> 9) & 0x1ff) * scale.f; + color.float32[2] = ((c0 >> 18) & 0x1ff) * scale.f; break; } + case AmdGpu::DataFormat::Format10_10_10_2: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + color.float32[0] = NumberUtils::U2ToUnorm(c0 & 0x3); + color.float32[1] = NumberUtils::U10ToUnorm((c0 >> 2) & 0x3ff); + color.float32[2] = NumberUtils::U10ToUnorm((c0 >> 12) & 0x3ff); + color.float32[3] = NumberUtils::U10ToUnorm(c0 >> 22); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S2ToSnorm(c0 & 0x3); + color.float32[1] = NumberUtils::S10ToSnorm((c0 >> 2) & 0x3ff); + color.float32[2] = NumberUtils::S10ToSnorm((c0 >> 12) & 0x3ff); + color.float32[3] = NumberUtils::S2ToSnorm(c0 >> 22); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0 & 0x3; + color.uint32[1] = (c0 >> 2) & 0x3ff; + color.uint32[2] = (c0 >> 12) & 0x3ff; + color.uint32[3] = c0 >> 22; + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format2_10_10_10: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + color.float32[0] = NumberUtils::U10ToUnorm(c0 & 0x3ff); + color.float32[1] = NumberUtils::U10ToUnorm((c0 >> 10) & 0x3ff); + color.float32[2] = NumberUtils::U10ToUnorm((c0 >> 20) & 0x3ff); + color.float32[3] = NumberUtils::U2ToUnorm(c0 >> 30); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S10ToSnorm(c0 & 0x3ff); + color.float32[1] = NumberUtils::S10ToSnorm((c0 >> 10) & 0x3ff); + color.float32[2] = NumberUtils::S10ToSnorm((c0 >> 20) & 0x3ff); + color.float32[3] = NumberUtils::S2ToSnorm(c0 >> 30); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0 & 0x3ff; + color.uint32[1] = (c0 >> 10) & 0x3ff; + color.uint32[2] = (c0 >> 20) & 0x3ff; + color.uint32[3] = c0 >> 30; + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format8_8_8_8: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + case AmdGpu::NumberFormat::Srgb: // Should we handle gamma correction here? + color.float32[0] = NumberUtils::U8ToUnorm(c0 & 0xff); + color.float32[1] = NumberUtils::U8ToUnorm((c0 >> 8) & 0xff); + color.float32[2] = NumberUtils::U8ToUnorm((c0 >> 16) & 0xff); + color.float32[3] = NumberUtils::U8ToUnorm(c0 >> 24); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S8ToSnorm(c0 & 0xff); + color.float32[1] = NumberUtils::S8ToSnorm((c0 >> 8) & 0xff); + color.float32[2] = NumberUtils::S8ToSnorm((c0 >> 16) & 0xff); + color.float32[3] = NumberUtils::S8ToSnorm(c0 >> 24); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0 & 0xff; + color.uint32[1] = (c0 >> 8) & 0xff; + color.uint32[2] = (c0 >> 16) & 0xff; + color.uint32[3] = c0 >> 24; + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format32_32: + switch (number_type) { + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0; + color.uint32[1] = c1; + break; + case AmdGpu::NumberFormat::Float: + color.float32[0] = *(reinterpret_cast(&c0)); + color.float32[1] = *(reinterpret_cast(&c1)); + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format16_16_16_16: + switch (number_type) { + case AmdGpu::NumberFormat::Unorm: + color.float32[0] = NumberUtils::U16ToUnorm(c0 & 0xffff); + color.float32[1] = NumberUtils::U16ToUnorm((c0 >> 16) & 0xffff); + color.float32[2] = NumberUtils::U16ToUnorm(c1 & 0xffff); + color.float32[3] = NumberUtils::U16ToUnorm((c1 >> 16) & 0xffff); + break; + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::SnormNz: + color.float32[0] = NumberUtils::S16ToSnorm(c0 & 0xffff); + color.float32[1] = NumberUtils::S16ToSnorm((c0 >> 16) & 0xffff); + color.float32[2] = NumberUtils::S16ToSnorm(c1 & 0xffff); + color.float32[3] = NumberUtils::S16ToSnorm((c1 >> 16) & 0xffff); + break; + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0 & 0xffff; + color.uint32[1] = (c0 >> 16) & 0xffff; + color.uint32[2] = c1 & 0xffff; + color.uint32[3] = (c1 >> 16) & 0xffff; + break; + case AmdGpu::NumberFormat::Float: + color.float32[0] = NumberUtils::Uf16ToF32(c0 & 0xffff); + color.float32[1] = NumberUtils::Uf16ToF32((c0 >> 16) & 0xffff); + color.float32[2] = NumberUtils::Uf16ToF32(c1 & 0xffff); + color.float32[3] = NumberUtils::Uf16ToF32((c1 >> 16) & 0xffff); + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format32_32_32_32: + switch (number_type) { + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + color.uint32[0] = c0; + color.uint32[1] = c0; + color.uint32[2] = c0; + color.uint32[3] = c1; + break; + case AmdGpu::NumberFormat::Float: + color.float32[0] = *(reinterpret_cast(&c0)); + color.float32[1] = *(reinterpret_cast(&c0)); + color.float32[2] = *(reinterpret_cast(&c0)); + color.float32[3] = *(reinterpret_cast(&c1)); + break; + default: + INVALID_NUMBER_FORMAT_COMBO; + break; + } + break; + case AmdGpu::DataFormat::Format5_6_5: + color.float32[0] = NumberUtils::U5ToUnorm(c0 & 0x1f); + color.float32[1] = NumberUtils::U6ToUnorm((c0 >> 5) & 0x3f); + color.float32[2] = NumberUtils::U5ToUnorm(c0 >> 11); + break; + case AmdGpu::DataFormat::Format1_5_5_5: + color.float32[0] = NumberUtils::U5ToUnorm(c0 & 0x1f); + color.float32[1] = NumberUtils::U5ToUnorm((c0 >> 5) & 0x1f); + color.float32[2] = NumberUtils::U5ToUnorm((c0 >> 10) & 0x1f); + color.float32[3] = (c0 >> 15) ? 1.0f : 0.0f; + break; + case AmdGpu::DataFormat::Format5_5_5_1: + color.float32[0] = (c0 & 0x1) ? 1.0f : 0.0f; + color.float32[1] = NumberUtils::U5ToUnorm((c0 >> 1) & 0x1f); + color.float32[2] = NumberUtils::U5ToUnorm((c0 >> 6) & 0x1f); + color.float32[3] = NumberUtils::U5ToUnorm((c0 >> 11) & 0x1f); + break; + case AmdGpu::DataFormat::Format4_4_4_4: + color.float32[0] = NumberUtils::U4ToUnorm(c0 & 0xf); + color.float32[1] = NumberUtils::U4ToUnorm((c0 >> 4) & 0xf); + color.float32[2] = NumberUtils::U4ToUnorm((c0 >> 8) & 0xf); + color.float32[3] = NumberUtils::U4ToUnorm(c0 >> 12); + break; + default: + LOG_ERROR(Render_Vulkan, "Unsupported color buffer format: {}", format); + 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; + } + } + return {.color = color}; } -vk::SampleCountFlagBits NumSamples(u32 num_samples) { +vk::SampleCountFlagBits RawNumSamples(u32 num_samples) { switch (num_samples) { case 1: return vk::SampleCountFlagBits::e1; @@ -712,4 +1105,14 @@ vk::SampleCountFlagBits NumSamples(u32 num_samples) { } } +vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags) { + vk::SampleCountFlagBits flags = RawNumSamples(num_samples); + // Half sample counts until supported, with a minimum of 1. + while (!(supported_flags & flags) && num_samples > 1) { + num_samples /= 2; + flags = RawNumSamples(num_samples); + } + return flags; +} + } // namespace Vulkan::LiverpoolToVK diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index 94f9073de..5fb04e5f5 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -4,6 +4,7 @@ #pragma once #include +#include "common/assert.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/pixel_format.h" #include "video_core/amdgpu/resource.h" @@ -17,7 +18,7 @@ vk::StencilOp StencilOp(Liverpool::StencilFunc op); vk::CompareOp CompareOp(Liverpool::CompareFunc func); -vk::PrimitiveTopology PrimitiveType(Liverpool::PrimitiveType type); +vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type); vk::PolygonMode PolygonMode(Liverpool::PolygonMode mode); @@ -39,20 +40,43 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter); vk::BorderColor BorderColor(AmdGpu::BorderColor color); -std::span GetAllFormats(); +struct SurfaceFormatInfo { + AmdGpu::DataFormat data_format; + AmdGpu::NumberFormat number_format; + vk::Format vk_format; + vk::FormatFeatureFlags2 flags; +}; +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, bool is_vo_surface); +struct DepthFormatInfo { + Liverpool::DepthBuffer::ZFormat z_format; + Liverpool::DepthBuffer::StencilFormat stencil_format; + vk::Format vk_format; + vk::FormatFeatureFlags2 flags; +}; +std::span DepthFormats(); + vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format, Liverpool::DepthBuffer::StencilFormat stencil_format); vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer); -vk::SampleCountFlagBits NumSamples(u32 num_samples); +vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags); void EmitQuadToTriangleListIndices(u8* out_indices, u32 num_vertices); +static inline vk::Format PromoteFormatToDepth(vk::Format fmt) { + if (fmt == vk::Format::eR32Sfloat) { + return vk::Format::eD32Sfloat; + } else if (fmt == vk::Format::eR16Unorm) { + return vk::Format::eD16Unorm; + } + UNREACHABLE(); +} + } // namespace Vulkan::LiverpoolToVK diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index c78d629e4..64a483654 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -6,6 +6,7 @@ #include "common/singleton.h" #include "core/file_format/splash.h" #include "core/libraries/system/systemservice.h" +#include "imgui/renderer/imgui_core.h" #include "sdl_window.h" #include "video_core/renderer_vulkan/renderer_vulkan.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" @@ -13,6 +14,9 @@ #include +#include "core/debug_state.h" +#include "core/devtools/layer.h" + namespace Vulkan { bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format format) { @@ -29,8 +33,8 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for }; } -[[nodiscard]] vk::ImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 swapchain_width, - s32 swapchain_height) { +[[nodiscard]] vk::ImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 dst_width, + s32 dst_height, s32 offset_x, s32 offset_y) { return vk::ImageBlit{ .srcSubresource = MakeImageSubresourceLayers(), .srcOffsets = @@ -50,23 +54,50 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for .dstOffsets = std::array{ vk::Offset3D{ - .x = 0, - .y = 0, + .x = offset_x, + .y = offset_y, .z = 0, }, vk::Offset3D{ - .x = swapchain_width, - .y = swapchain_height, + .x = offset_x + dst_width, + .y = offset_y + dst_height, .z = 1, }, }, }; } +[[nodiscard]] vk::ImageBlit MakeImageBlitStretch(s32 frame_width, s32 frame_height, + s32 swapchain_width, s32 swapchain_height) { + return MakeImageBlit(frame_width, frame_height, swapchain_width, swapchain_height, 0, 0); +} + +[[nodiscard]] vk::ImageBlit MakeImageBlitFit(s32 frame_width, s32 frame_height, s32 swapchain_width, + s32 swapchain_height) { + float frame_aspect = static_cast(frame_width) / frame_height; + float swapchain_aspect = static_cast(swapchain_width) / swapchain_height; + + s32 dst_width = swapchain_width; + s32 dst_height = swapchain_height; + + if (frame_aspect > swapchain_aspect) { + dst_height = static_cast(swapchain_width / frame_aspect); + } else { + dst_width = static_cast(swapchain_height * frame_aspect); + } + + s32 offset_x = (swapchain_width - dst_width) / 2; + s32 offset_y = (swapchain_height - dst_height) / 2; + + return MakeImageBlit(frame_width, frame_height, dst_width, dst_height, offset_x, offset_y); +} + RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_) : window{window_}, liverpool{liverpool_}, - instance{window, Config::getGpuId(), Config::vkValidationEnabled()}, draw_scheduler{instance}, - present_scheduler{instance}, flip_scheduler{instance}, swapchain{instance, window}, + instance{window, Config::getGpuId(), Config::vkValidationEnabled(), + Config::vkCrashDiagnosticEnabled()}, + draw_scheduler{instance}, present_scheduler{instance}, flip_scheduler{instance}, + swapchain{instance, window}, rasterizer{std::make_unique(instance, draw_scheduler, liverpool)}, texture_cache{rasterizer->GetTextureCache()} { const u32 num_images = swapchain.GetImageCount(); @@ -76,12 +107,21 @@ RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* present_frames.resize(num_images); for (u32 i = 0; i < num_images; i++) { Frame& frame = present_frames[i]; - frame.present_done = device.createFence({.flags = vk::FenceCreateFlagBits::eSignaled}); + auto [fence_result, fence] = + device.createFence({.flags = vk::FenceCreateFlagBits::eSignaled}); + ASSERT_MSG(fence_result == vk::Result::eSuccess, "Failed to create present done fence: {}", + vk::to_string(fence_result)); + frame.present_done = fence; free_queue.push(&frame); } + + // Setup ImGui + ImGui::Core::Initialize(instance, window, num_images, swapchain.GetSurfaceFormat().format); + ImGui::Layer::AddLayer(Common::Singleton::Instance()); } RendererVulkan::~RendererVulkan() { + ImGui::Layer::RemoveLayer(Common::Singleton::Instance()); draw_scheduler.Finish(); const vk::Device device = instance.GetDevice(); for (auto& frame : present_frames) { @@ -89,6 +129,7 @@ RendererVulkan::~RendererVulkan() { device.destroyImageView(frame.image_view); device.destroyFence(frame.present_done); } + ImGui::Core::Shutdown(device); } void RendererVulkan::RecreateFrame(Frame* frame, u32 width, u32 height) { @@ -145,7 +186,10 @@ void RendererVulkan::RecreateFrame(Frame* frame, u32 width, u32 height) { .layerCount = 1, }, }; - frame->image_view = device.createImageView(view_info); + auto [view_result, view] = device.createImageView(view_info); + ASSERT_MSG(view_result == vk::Result::eSuccess, "Failed to create frame image view: {}", + vk::to_string(view_result)); + frame->image_view = view; frame->width = width; frame->height = height; } @@ -190,8 +234,16 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop scheduler.EndRendering(); const auto cmdbuf = scheduler.CommandBuffer(); - image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead, cmdbuf); + image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {}, + cmdbuf); + const auto frame_subresources = vk::ImageSubresourceRange{ + .aspectMask = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }; const std::array pre_barrier{ vk::ImageMemoryBarrier{ .srcAccessMask = vk::AccessFlagBits::eTransferRead, @@ -201,24 +253,39 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = frame->image, - .subresourceRange{ - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, + .subresourceRange{frame_subresources}, }, }; cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier); + // Clear the frame image before blitting to avoid artifacts. + const vk::ClearColorValue clear_color{std::array{0.0f, 0.0f, 0.0f, 1.0f}}; + cmdbuf.clearColorImage(frame->image, vk::ImageLayout::eTransferDstOptimal, clear_color, + frame_subresources); + + const auto blitBarrier = + vk::ImageMemoryBarrier2{.srcStageMask = vk::PipelineStageFlagBits2::eTransfer, + .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, + .dstAccessMask = vk::AccessFlagBits2::eTransferWrite, + .oldLayout = vk::ImageLayout::eTransferDstOptimal, + .newLayout = vk::ImageLayout::eTransferDstOptimal, + .image = frame->image, + .subresourceRange{frame_subresources}}; + + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &blitBarrier, + }); + // Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image. - cmdbuf.blitImage( - image.image, image.layout, frame->image, vk::ImageLayout::eTransferDstOptimal, - MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height), - vk::Filter::eLinear); + cmdbuf.blitImage(image.image, image.last_state.layout, frame->image, + vk::ImageLayout::eTransferDstOptimal, + MakeImageBlitFit(image.info.size.width, image.info.size.height, frame->width, + frame->height), + vk::Filter::eLinear); const vk::ImageMemoryBarrier post_barrier{ .srcAccessMask = vk::AccessFlagBits::eTransferWrite, @@ -228,13 +295,7 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = frame->image, - .subresourceRange{ - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, + .subresourceRange{frame_subresources}, }; cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, @@ -249,16 +310,27 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop } void RendererVulkan::Present(Frame* frame) { + // Recreate the swapchain if the window was resized. + if (window.getWidth() != swapchain.GetExtent().width || + window.getHeight() != swapchain.GetExtent().height) { + swapchain.Recreate(window.getWidth(), window.getHeight()); + } + + ImGui::Core::NewFrame(); + swapchain.AcquireNextImage(); const vk::Image swapchain_image = swapchain.Image(); auto& scheduler = present_scheduler; const auto cmdbuf = scheduler.CommandBuffer(); + + ImGui::Core::Render(cmdbuf, frame); + { auto* profiler_ctx = instance.GetProfilerContext(); TracyVkNamedZoneC(profiler_ctx, renderer_gpu_zone, cmdbuf, "Host frame", - MarkersPallete::GpuMarkerColor, profiler_ctx != nullptr); + MarkersPalette::GpuMarkerColor, profiler_ctx != nullptr); const vk::Extent2D extent = swapchain.GetExtent(); const std::array pre_barriers{ @@ -316,10 +388,11 @@ void RendererVulkan::Present(Frame* frame) { vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers); - cmdbuf.blitImage(frame->image, vk::ImageLayout::eTransferSrcOptimal, swapchain_image, - vk::ImageLayout::eTransferDstOptimal, - MakeImageBlit(frame->width, frame->height, extent.width, extent.height), - vk::Filter::eLinear); + cmdbuf.blitImage( + frame->image, vk::ImageLayout::eTransferSrcOptimal, swapchain_image, + vk::ImageLayout::eTransferDstOptimal, + MakeImageBlitStretch(frame->width, frame->height, extent.width, extent.height), + vk::Filter::eLinear); cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, @@ -346,6 +419,8 @@ void RendererVulkan::Present(Frame* frame) { std::scoped_lock fl{free_mutex}; free_queue.push(frame); free_cv.notify_one(); + + DebugState.IncFlipFrameNum(); } Frame* RendererVulkan::GetRenderFrame() { @@ -354,7 +429,7 @@ Frame* RendererVulkan::GetRenderFrame() { { std::unique_lock lock{free_mutex}; free_cv.wait(lock, [this] { return !free_queue.empty(); }); - LOG_INFO(Render_Vulkan, "Got render frame, remaining {}", free_queue.size() - 1); + LOG_DEBUG(Render_Vulkan, "Got render frame, remaining {}", free_queue.size() - 1); // Take the frame from the queue frame = free_queue.front(); @@ -371,6 +446,8 @@ Frame* RendererVulkan::GetRenderFrame() { // Wait for the presentation to be finished so all frame resources are free while (wait() != vk::Result::eSuccess) { + ASSERT_MSG(result != vk::Result::eErrorDeviceLost, + "Device lost during waiting for a frame"); // Retry if the waiting times out if (result == vk::Result::eTimeout) { continue; @@ -380,7 +457,7 @@ Frame* RendererVulkan::GetRenderFrame() { // Reset fence for next queue submission. device.resetFences(frame->present_done); - // If the window dimentions changed, recreate this frame + // If the window dimensions changed, recreate this frame if (frame->width != window.getWidth() || frame->height != window.getHeight()) { RecreateFrame(frame, window.getWidth(), window.getHeight()); } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index ee5e35c67..a663622fc 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -4,6 +4,7 @@ #pragma once #include + #include "video_core/amdgpu/liverpool.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" diff --git a/src/video_core/renderer_vulkan/vk_common.cpp b/src/video_core/renderer_vulkan/vk_common.cpp index e9265ea9c..b19567808 100644 --- a/src/video_core/renderer_vulkan/vk_common.cpp +++ b/src/video_core/renderer_vulkan/vk_common.cpp @@ -5,7 +5,10 @@ // Implement vma functions #define VMA_IMPLEMENTATION +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnullability-completeness" #include +#pragma clang diagnostic pop // Store the dispatch loader here VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE diff --git a/src/video_core/renderer_vulkan/vk_common.h b/src/video_core/renderer_vulkan/vk_common.h index 7db6fb06d..9178aeb65 100644 --- a/src/video_core/renderer_vulkan/vk_common.h +++ b/src/video_core/renderer_vulkan/vk_common.h @@ -3,13 +3,25 @@ #pragma once +#if defined(__APPLE__) && !USE_SYSTEM_VULKAN_LOADER +#define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 0 +#endif + // Include vulkan-hpp header #define VK_ENABLE_BETA_EXTENSIONS #define VK_NO_PROTOTYPES #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_NO_CONSTRUCTORS #define VULKAN_HPP_NO_STRUCT_SETTERS +#define VULKAN_HPP_HAS_SPACESHIP_OPERATOR +#define VULKAN_HPP_NO_EXCEPTIONS +// Define assert-on-result to nothing to instead return the result for our handling. +#define VULKAN_HPP_ASSERT_ON_RESULT + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-value" #include +#pragma clang diagnostic pop #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 81cf9c02a..37a44ddac 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "common/alignment.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" @@ -12,23 +13,34 @@ namespace Vulkan { ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler_, - vk::PipelineCache pipeline_cache, u64 compute_key_, - const Program* program) - : instance{instance_}, scheduler{scheduler_}, compute_key{compute_key_}, - info{&program->pgm.info} { + DescriptorHeap& desc_heap_, vk::PipelineCache pipeline_cache, + u64 compute_key_, const Shader::Info& info_, + vk::ShaderModule module) + : Pipeline{instance_, scheduler_, desc_heap_, pipeline_cache}, compute_key{compute_key_}, + info{&info_} { const vk::PipelineShaderStageCreateInfo shader_ci = { .stage = vk::ShaderStageFlagBits::eCompute, - .module = program->module, + .module = module, .pName = "main", }; u32 binding{}; boost::container::small_vector bindings; for (const auto& buffer : info->buffers) { + const auto sharp = buffer.GetSharp(*info); bindings.push_back({ .binding = binding++, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = buffer.IsStorage(sharp) ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, + .descriptorCount = 1, + .stageFlags = vk::ShaderStageFlagBits::eCompute, + }); + } + for (const auto& tex_buffer : info->texture_buffers) { + bindings.push_back({ + .binding = binding++, + .descriptorType = tex_buffer.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, .descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute, }); @@ -57,12 +69,21 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler .size = sizeof(Shader::PushData), }; + uses_push_descriptors = binding < instance.MaxPushDescriptors(); + const auto flags = uses_push_descriptors + ? vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR + : vk::DescriptorSetLayoutCreateFlagBits{}; const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = { - .flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR, + .flags = flags, .bindingCount = static_cast(bindings.size()), .pBindings = bindings.data(), }; - desc_layout = instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci); + auto [descriptor_set_result, descriptor_set] = + instance.GetDevice().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)); + desc_layout = std::move(descriptor_set); const vk::DescriptorSetLayout set_layout = *desc_layout; const vk::PipelineLayoutCreateInfo layout_info = { @@ -71,19 +92,20 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler .pushConstantRangeCount = 1U, .pPushConstantRanges = &push_constants, }; - pipeline_layout = instance.GetDevice().createPipelineLayoutUnique(layout_info); + auto [layout_result, layout] = instance.GetDevice().createPipelineLayoutUnique(layout_info); + ASSERT_MSG(layout_result == vk::Result::eSuccess, + "Failed to create compute pipeline layout: {}", vk::to_string(layout_result)); + pipeline_layout = std::move(layout); const vk::ComputePipelineCreateInfo compute_pipeline_ci = { .stage = shader_ci, .layout = *pipeline_layout, }; - auto result = + auto [pipeline_result, pipe] = instance.GetDevice().createComputePipelineUnique(pipeline_cache, compute_pipeline_ci); - if (result.result == vk::Result::eSuccess) { - pipeline = std::move(result.value); - } else { - UNREACHABLE_MSG("Graphics pipeline creation failed!"); - } + ASSERT_MSG(pipeline_result == vk::Result::eSuccess, "Failed to create compute pipeline: {}", + vk::to_string(pipeline_result)); + pipeline = std::move(pipe); } ComputePipeline::~ComputePipeline() = default; @@ -91,84 +113,127 @@ ComputePipeline::~ComputePipeline() = default; bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, VideoCore::TextureCache& texture_cache) const { // Bind resource buffers and textures. - boost::container::static_vector buffer_infos; - boost::container::static_vector image_infos; + boost::container::static_vector buffer_views; + boost::container::static_vector buffer_infos; boost::container::small_vector set_writes; + boost::container::small_vector buffer_barriers; Shader::PushData push_data{}; - u32 binding{}; + Shader::Backend::Bindings binding{}; - for (const auto& buffer : info->buffers) { - const auto vsharp = buffer.GetVsharp(*info); - const VAddr address = vsharp.base_address; - // Most of the time when a metadata is updated with a shader it gets cleared. It means we - // can skip the whole dispatch and update the tracked state instead. Also, it is not - // intended to be consumed and in such rare cases (e.g. HTile introspection, CRAA) we will - // need its full emulation anyways. For cases of metadata read a warning will be logged. - if (buffer.is_storage) { - if (texture_cache.TouchMeta(address, true)) { - LOG_WARNING(Render_Vulkan, "Metadata update skipped"); - return false; - } + image_infos.clear(); + + info->PushUd(binding, push_data); + for (const auto& desc : info->buffers) { + bool is_storage = true; + if (desc.is_gds_buffer) { + auto* vk_buffer = buffer_cache.GetGdsBuffer(); + buffer_infos.emplace_back(vk_buffer->Handle(), 0, vk_buffer->SizeBytes()); } else { - if (texture_cache.IsMeta(address)) { - LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (buffer)"); + const auto vsharp = desc.GetSharp(*info); + is_storage = desc.IsStorage(vsharp); + const VAddr address = vsharp.base_address; + // Most of the time when a metadata is updated with a shader it gets cleared. It means + // we can skip the whole dispatch and update the tracked state instead. Also, it is not + // intended to be consumed and in such rare cases (e.g. HTile introspection, CRAA) we + // will need its full emulation anyways. For cases of metadata read a warning will be + // logged. + if (desc.is_written) { + if (texture_cache.TouchMeta(address, true)) { + LOG_TRACE(Render_Vulkan, "Metadata update skipped"); + return false; + } + } else { + if (texture_cache.IsMeta(address)) { + LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (buffer)"); + } } - } - const u32 size = vsharp.GetSize(); - if (buffer.is_written) { - texture_cache.InvalidateMemory(address, size, true); - } - const u32 alignment = - buffer.is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); - const auto [vk_buffer, offset] = - buffer_cache.ObtainBuffer(address, size, buffer.is_written); - const u32 offset_aligned = Common::AlignDown(offset, alignment); - const u32 adjust = offset - offset_aligned; - if (adjust != 0) { + const u32 size = vsharp.GetSize(); + const u32 alignment = + is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); + const auto [vk_buffer, offset] = + buffer_cache.ObtainBuffer(address, size, desc.is_written); + const u32 offset_aligned = Common::AlignDown(offset, alignment); + const u32 adjust = offset - offset_aligned; ASSERT(adjust % 4 == 0); - push_data.AddOffset(binding, adjust); + push_data.AddOffset(binding.buffer, adjust); + buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust); } - buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust); set_writes.push_back({ .dstSet = VK_NULL_HANDLE, - .dstBinding = binding++, + .dstBinding = binding.unified++, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, .pBufferInfo = &buffer_infos.back(), }); + ++binding.buffer; } - for (const auto& image_desc : info->images) { - const auto tsharp = - info->ReadUd(image_desc.sgpr_base, image_desc.dword_offset); - VideoCore::ImageInfo image_info{tsharp}; - VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; - const auto& image_view = texture_cache.FindTexture(image_info, view_info); - const auto& image = texture_cache.GetImage(image_view.image_id); - image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); + const auto null_buffer_view = + instance.IsNullDescriptorSupported() ? VK_NULL_HANDLE : buffer_cache.NullBufferView(); + for (const auto& desc : info->texture_buffers) { + const auto vsharp = desc.GetSharp(*info); + vk::BufferView& buffer_view = buffer_views.emplace_back(null_buffer_view); + const u32 size = vsharp.GetSize(); + if (vsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid && size != 0) { + const VAddr address = vsharp.base_address; + if (desc.is_written) { + if (texture_cache.TouchMeta(address, true)) { + LOG_TRACE(Render_Vulkan, "Metadata update skipped"); + return false; + } + } else { + if (texture_cache.IsMeta(address)) { + LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (buffer)"); + } + } + const u32 alignment = instance.TexelBufferMinAlignment(); + const auto [vk_buffer, offset] = + buffer_cache.ObtainBuffer(address, size, desc.is_written, true); + const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; + ASSERT_MSG(fmt_stride == vsharp.GetStride(), + "Texel buffer stride must match format stride"); + const u32 offset_aligned = Common::AlignDown(offset, alignment); + const u32 adjust = offset - offset_aligned; + ASSERT(adjust % fmt_stride == 0); + push_data.AddOffset(binding.buffer, adjust / fmt_stride); + buffer_view = vk_buffer->View(offset_aligned, size + adjust, desc.is_written, + vsharp.GetDataFmt(), vsharp.GetNumberFmt()); + if (auto barrier = + vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite + : vk::AccessFlagBits2::eShaderRead, + vk::PipelineStageFlagBits2::eComputeShader)) { + buffer_barriers.emplace_back(*barrier); + } + if (desc.is_written) { + texture_cache.InvalidateMemoryFromGPU(address, size); + } + } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, - .dstBinding = binding++, + .dstBinding = binding.unified++, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = image_desc.is_storage ? vk::DescriptorType::eStorageImage - : vk::DescriptorType::eSampledImage, - .pImageInfo = &image_infos.back(), + .descriptorType = desc.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, + .pTexelBufferView = &buffer_view, }); - - if (texture_cache.IsMeta(tsharp.Address())) { - LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (texture)"); - } + ++binding.buffer; } + + BindTextures(texture_cache, *info, binding, set_writes); + for (const auto& sampler : info->samplers) { - const auto ssharp = sampler.GetSsharp(*info); + const auto ssharp = sampler.GetSharp(*info); + if (ssharp.force_degamma) { + LOG_WARNING(Render_Vulkan, "Texture requires gamma correction"); + } const auto vk_sampler = texture_cache.GetSampler(ssharp); image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); set_writes.push_back({ .dstSet = VK_NULL_HANDLE, - .dstBinding = binding++, + .dstBinding = binding.unified++, .dstArrayElement = 0, .descriptorCount = 1, .descriptorType = vk::DescriptorType::eSampler, @@ -181,9 +246,32 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } const auto cmdbuf = scheduler.CommandBuffer(); + + if (!buffer_barriers.empty()) { + const auto dependencies = vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = u32(buffer_barriers.size()), + .pBufferMemoryBarriers = buffer_barriers.data(), + }; + scheduler.EndRendering(); + cmdbuf.pipelineBarrier2(dependencies); + } + + if (uses_push_descriptors) { + cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, + set_writes); + } else { + const auto desc_set = desc_heap.Commit(*desc_layout); + for (auto& set_write : set_writes) { + set_write.dstSet = desc_set; + } + instance.GetDevice().updateDescriptorSets(set_writes, {}); + cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, desc_set, + {}); + } + cmdbuf.pushConstants(*pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0u, sizeof(push_data), &push_data); - cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, set_writes); return true; } diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 5da9dc7e7..f1bc7285a 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h @@ -3,9 +3,8 @@ #pragma once -#include "shader_recompiler/ir/program.h" -#include "shader_recompiler/runtime_info.h" #include "video_core/renderer_vulkan/vk_common.h" +#include "video_core/renderer_vulkan/vk_pipeline_common.h" namespace VideoCore { class BufferCache; @@ -16,36 +15,22 @@ namespace Vulkan { class Instance; class Scheduler; +class DescriptorHeap; -struct Program { - Shader::IR::Program pgm; - std::vector spv; - vk::ShaderModule module; - u32 end_binding; -}; - -class ComputePipeline { +class ComputePipeline : public Pipeline { public: - explicit ComputePipeline(const Instance& instance, Scheduler& scheduler, - vk::PipelineCache pipeline_cache, u64 compute_key, - const Program* program); + ComputePipeline(const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap, + vk::PipelineCache pipeline_cache, u64 compute_key, const Shader::Info& info, + vk::ShaderModule module); ~ComputePipeline(); - [[nodiscard]] vk::Pipeline Handle() const noexcept { - return *pipeline; - } - bool BindResources(VideoCore::BufferCache& buffer_cache, VideoCore::TextureCache& texture_cache) const; private: - const Instance& instance; - Scheduler& scheduler; - vk::UniquePipeline pipeline; - vk::UniquePipelineLayout pipeline_layout; - vk::UniqueDescriptorSetLayout desc_layout; u64 compute_key; const Shader::Info* info; + bool uses_push_descriptors{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index c2649b96c..cbc0fc5ec 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -16,22 +16,22 @@ namespace Vulkan { +static constexpr auto gp_stage_flags = vk::ShaderStageFlagBits::eVertex | + vk::ShaderStageFlagBits::eGeometry | + vk::ShaderStageFlagBits::eFragment; + GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& scheduler_, - const GraphicsPipelineKey& key_, + DescriptorHeap& desc_heap_, const GraphicsPipelineKey& key_, vk::PipelineCache pipeline_cache, - std::span programs) - : instance{instance_}, scheduler{scheduler_}, key{key_} { + std::span infos, + std::span modules) + : Pipeline{instance_, scheduler_, desc_heap_, pipeline_cache}, key{key_} { const vk::Device device = instance.GetDevice(); - for (u32 i = 0; i < MaxShaderStages; i++) { - if (!programs[i]) { - continue; - } - stages[i] = &programs[i]->pgm.info; - } + std::ranges::copy(infos, stages.begin()); BuildDescSetLayout(); const vk::PushConstantRange push_constants = { - .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, + .stageFlags = gp_stage_flags, .offset = 0, .size = sizeof(Shader::PushData), }; @@ -43,70 +43,84 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul .pushConstantRangeCount = 1, .pPushConstantRanges = &push_constants, }; - pipeline_layout = instance.GetDevice().createPipelineLayoutUnique(layout_info); + auto [layout_result, layout] = instance.GetDevice().createPipelineLayoutUnique(layout_info); + ASSERT_MSG(layout_result == vk::Result::eSuccess, + "Failed to create graphics pipeline layout: {}", vk::to_string(layout_result)); + pipeline_layout = std::move(layout); - boost::container::static_vector bindings; - boost::container::static_vector attributes; - const auto& vs_info = stages[u32(Shader::Stage::Vertex)]; - for (const auto& input : vs_info->vs_inputs) { - if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || - input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { - // Skip attribute binding as the data will be pulled by shader - continue; + boost::container::static_vector vertex_bindings; + boost::container::static_vector vertex_attributes; + if (!instance.IsVertexInputDynamicState()) { + const auto& vs_info = stages[u32(Shader::Stage::Vertex)]; + for (const auto& input : vs_info->vs_inputs) { + if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || + input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { + // Skip attribute binding as the data will be pulled by shader + continue; + } + + const auto buffer = + vs_info->ReadUd(input.sgpr_base, input.dword_offset); + if (buffer.GetSize() == 0) { + continue; + } + vertex_attributes.push_back({ + .location = input.binding, + .binding = input.binding, + .format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()), + .offset = 0, + }); + vertex_bindings.push_back({ + .binding = input.binding, + .stride = buffer.GetStride(), + .inputRate = input.instance_step_rate == Shader::Info::VsInput::None + ? vk::VertexInputRate::eVertex + : vk::VertexInputRate::eInstance, + }); } - - const auto buffer = vs_info->ReadUd(input.sgpr_base, input.dword_offset); - attributes.push_back({ - .location = input.binding, - .binding = input.binding, - .format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()), - .offset = 0, - }); - bindings.push_back({ - .binding = input.binding, - .stride = buffer.GetStride(), - .inputRate = input.instance_step_rate == Shader::Info::VsInput::None - ? vk::VertexInputRate::eVertex - : vk::VertexInputRate::eInstance, - }); } const vk::PipelineVertexInputStateCreateInfo vertex_input_info = { - .vertexBindingDescriptionCount = static_cast(bindings.size()), - .pVertexBindingDescriptions = bindings.data(), - .vertexAttributeDescriptionCount = static_cast(attributes.size()), - .pVertexAttributeDescriptions = attributes.data(), + .vertexBindingDescriptionCount = static_cast(vertex_bindings.size()), + .pVertexBindingDescriptions = vertex_bindings.data(), + .vertexAttributeDescriptionCount = static_cast(vertex_attributes.size()), + .pVertexAttributeDescriptions = vertex_attributes.data(), }; - if (key.prim_type == Liverpool::PrimitiveType::RectList && !IsEmbeddedVs()) { + if (key.prim_type == AmdGpu::PrimitiveType::RectList && !IsEmbeddedVs()) { LOG_WARNING(Render_Vulkan, "Rectangle List primitive type is only supported for embedded VS"); } + auto prim_restart = key.enable_primitive_restart != 0; + if (prim_restart && IsPrimitiveListTopology() && !instance.IsListRestartSupported()) { + LOG_WARNING(Render_Vulkan, + "Primitive restart is enabled for list topology but not supported by driver."); + prim_restart = false; + } const vk::PipelineInputAssemblyStateCreateInfo input_assembly = { .topology = LiverpoolToVK::PrimitiveType(key.prim_type), - .primitiveRestartEnable = key.enable_primitive_restart != 0, + .primitiveRestartEnable = prim_restart, }; - ASSERT_MSG(!key.enable_primitive_restart || key.primitive_restart_index == 0xFFFF, - "Primitive restart index other than 0xFFFF is not supported yet"); + ASSERT_MSG(!prim_restart || key.primitive_restart_index == 0xFFFF || + key.primitive_restart_index == 0xFFFFFFFF, + "Primitive restart index other than -1 is not supported yet"); const vk::PipelineRasterizationStateCreateInfo raster_state = { .depthClampEnable = false, .rasterizerDiscardEnable = false, .polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode), - .cullMode = vk::CullModeFlagBits::eNone /*LiverpoolToVK::CullMode(key.cull_mode)*/, + .cullMode = LiverpoolToVK::CullMode(key.cull_mode), .frontFace = key.front_face == Liverpool::FrontFace::Clockwise ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise, .depthBiasEnable = bool(key.depth_bias_enable), - .depthBiasConstantFactor = key.depth_bias_const_factor, - .depthBiasClamp = key.depth_bias_clamp, - .depthBiasSlopeFactor = key.depth_bias_slope_factor, .lineWidth = 1.0f, }; const vk::PipelineMultisampleStateCreateInfo multisampling = { - .rasterizationSamples = LiverpoolToVK::NumSamples(key.num_samples), + .rasterizationSamples = + LiverpoolToVK::NumSamples(key.num_samples, instance.GetFramebufferSampleCounts()), .sampleShadingEnable = false, }; @@ -129,7 +143,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul }; const vk::PipelineViewportStateCreateInfo viewport_info = { - .pNext = &clip_control, + .pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr, .viewportCount = 1, .pViewports = &viewport, .scissorCount = 1, @@ -137,9 +151,10 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul }; boost::container::static_vector dynamic_states = { - vk::DynamicState::eViewport, - vk::DynamicState::eScissor, - vk::DynamicState::eBlendConstants, + vk::DynamicState::eViewport, vk::DynamicState::eScissor, + vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthBounds, + vk::DynamicState::eDepthBias, vk::DynamicState::eStencilReference, + vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask, }; if (instance.IsColorWriteEnableSupported()) { @@ -148,6 +163,8 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul } if (instance.IsVertexInputDynamicState()) { dynamic_states.push_back(vk::DynamicState::eVertexInputEXT); + } else { + dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT); } const vk::PipelineDynamicStateCreateInfo dynamic_info = { @@ -156,54 +173,56 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul }; const vk::PipelineDepthStencilStateCreateInfo depth_info = { - .depthTestEnable = key.depth.depth_enable, - .depthWriteEnable = key.depth.depth_write_enable, - .depthCompareOp = LiverpoolToVK::CompareOp(key.depth.depth_func), - .depthBoundsTestEnable = key.depth.depth_bounds_enable, - .stencilTestEnable = key.depth.stencil_enable, + .depthTestEnable = key.depth_stencil.depth_enable, + .depthWriteEnable = key.depth_stencil.depth_write_enable, + .depthCompareOp = LiverpoolToVK::CompareOp(key.depth_stencil.depth_func), + .depthBoundsTestEnable = key.depth_stencil.depth_bounds_enable, + .stencilTestEnable = key.depth_stencil.stencil_enable, .front{ .failOp = LiverpoolToVK::StencilOp(key.stencil.stencil_fail_front), .passOp = LiverpoolToVK::StencilOp(key.stencil.stencil_zpass_front), .depthFailOp = LiverpoolToVK::StencilOp(key.stencil.stencil_zfail_front), - .compareOp = LiverpoolToVK::CompareOp(key.depth.stencil_ref_func), - .compareMask = key.stencil_ref_front.stencil_mask, - .writeMask = key.stencil_ref_front.stencil_write_mask, - .reference = key.stencil_ref_front.stencil_test_val, + .compareOp = LiverpoolToVK::CompareOp(key.depth_stencil.stencil_ref_func), }, .back{ - .failOp = LiverpoolToVK::StencilOp(key.depth.backface_enable + .failOp = LiverpoolToVK::StencilOp(key.depth_stencil.backface_enable ? key.stencil.stencil_fail_back.Value() : key.stencil.stencil_fail_front.Value()), - .passOp = LiverpoolToVK::StencilOp(key.depth.backface_enable + .passOp = LiverpoolToVK::StencilOp(key.depth_stencil.backface_enable ? key.stencil.stencil_zpass_back.Value() : key.stencil.stencil_zpass_front.Value()), - .depthFailOp = LiverpoolToVK::StencilOp(key.depth.backface_enable + .depthFailOp = LiverpoolToVK::StencilOp(key.depth_stencil.backface_enable ? key.stencil.stencil_zfail_back.Value() : key.stencil.stencil_zfail_front.Value()), - .compareOp = LiverpoolToVK::CompareOp(key.depth.backface_enable - ? key.depth.stencil_bf_func.Value() - : key.depth.stencil_ref_func.Value()), - .compareMask = key.stencil_ref_back.stencil_mask, - .writeMask = key.stencil_ref_back.stencil_write_mask, - .reference = key.stencil_ref_back.stencil_test_val, + .compareOp = LiverpoolToVK::CompareOp(key.depth_stencil.backface_enable + ? key.depth_stencil.stencil_bf_func.Value() + : key.depth_stencil.stencil_ref_func.Value()), }, - .minDepthBounds = key.depth_bounds_min, - .maxDepthBounds = key.depth_bounds_max, }; - auto stage = u32(Shader::Stage::Vertex); boost::container::static_vector shader_stages; - shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ - .stage = vk::ShaderStageFlagBits::eVertex, - .module = programs[stage]->module, - .pName = "main", - }); + auto stage = u32(Shader::Stage::Vertex); + if (infos[stage]) { + shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ + .stage = vk::ShaderStageFlagBits::eVertex, + .module = modules[stage], + .pName = "main", + }); + } + stage = u32(Shader::Stage::Geometry); + if (infos[stage]) { + shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ + .stage = vk::ShaderStageFlagBits::eGeometry, + .module = modules[stage], + .pName = "main", + }); + } stage = u32(Shader::Stage::Fragment); - if (programs[stage]) { + if (infos[stage]) { shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{ .stage = vk::ShaderStageFlagBits::eFragment, - .module = programs[stage]->module, + .module = modules[stage], .pName = "main", }); } @@ -280,7 +299,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul .pNext = &pipeline_rendering_ci, .stageCount = static_cast(shader_stages.size()), .pStages = shader_stages.data(), - .pVertexInputState = &vertex_input_info, + .pVertexInputState = !instance.IsVertexInputDynamicState() ? &vertex_input_info : nullptr, .pInputAssemblyState = &input_assembly, .pViewportState = &viewport_info, .pRasterizationState = &raster_state, @@ -291,30 +310,40 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul .layout = *pipeline_layout, }; - auto result = device.createGraphicsPipelineUnique(pipeline_cache, pipeline_info); - if (result.result == vk::Result::eSuccess) { - pipeline = std::move(result.value); - } else { - UNREACHABLE_MSG("Graphics pipeline creation failed!"); - } + auto [pipeline_result, pipe] = + device.createGraphicsPipelineUnique(pipeline_cache, pipeline_info); + ASSERT_MSG(pipeline_result == vk::Result::eSuccess, "Failed to create graphics pipeline: {}", + vk::to_string(pipeline_result)); + pipeline = std::move(pipe); } GraphicsPipeline::~GraphicsPipeline() = default; void GraphicsPipeline::BuildDescSetLayout() { - u32 binding{}; boost::container::small_vector bindings; + u32 binding{}; + for (const auto* stage : stages) { if (!stage) { continue; } for (const auto& buffer : stage->buffers) { + const auto sharp = buffer.GetSharp(*stage); bindings.push_back({ .binding = binding++, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = buffer.IsStorage(sharp) ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, + .stageFlags = gp_stage_flags, + }); + } + for (const auto& tex_buffer : stage->texture_buffers) { + bindings.push_back({ + .binding = binding++, + .descriptorType = tex_buffer.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, + .descriptorCount = 1, + .stageFlags = gp_stage_flags, }); } for (const auto& image : stage->images) { @@ -323,7 +352,7 @@ void GraphicsPipeline::BuildDescSetLayout() { .descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage : vk::DescriptorType::eSampledImage, .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, + .stageFlags = gp_stage_flags, }); } for (const auto& sampler : stage->samplers) { @@ -331,27 +360,38 @@ void GraphicsPipeline::BuildDescSetLayout() { .binding = binding++, .descriptorType = vk::DescriptorType::eSampler, .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, + .stageFlags = gp_stage_flags, }); } } + uses_push_descriptors = binding < instance.MaxPushDescriptors(); + const auto flags = uses_push_descriptors + ? vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR + : vk::DescriptorSetLayoutCreateFlagBits{}; const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = { - .flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR, + .flags = flags, .bindingCount = static_cast(bindings.size()), .pBindings = bindings.data(), }; - desc_layout = instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci); + auto [layout_result, layout] = + instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci); + ASSERT_MSG(layout_result == vk::Result::eSuccess, + "Failed to create graphics descriptor set layout: {}", vk::to_string(layout_result)); + desc_layout = std::move(layout); } void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, VideoCore::BufferCache& buffer_cache, VideoCore::TextureCache& texture_cache) const { // Bind resource buffers and textures. - boost::container::static_vector buffer_infos; - boost::container::static_vector image_infos; + boost::container::static_vector buffer_views; + boost::container::static_vector buffer_infos; boost::container::small_vector set_writes; + boost::container::small_vector buffer_barriers; Shader::PushData push_data{}; - u32 binding{}; + Shader::Backend::Bindings binding{}; + + image_infos.clear(); for (const auto* stage : stages) { if (!stage) { @@ -361,66 +401,94 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, push_data.step0 = regs.vgt_instance_step_rate_0; push_data.step1 = regs.vgt_instance_step_rate_1; } + stage->PushUd(binding, push_data); for (const auto& buffer : stage->buffers) { - const auto vsharp = buffer.GetVsharp(*stage); - if (vsharp) { + const auto vsharp = buffer.GetSharp(*stage); + const bool is_storage = buffer.IsStorage(vsharp); + if (vsharp && vsharp.GetSize() > 0) { const VAddr address = vsharp.base_address; if (texture_cache.IsMeta(address)) { LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (buffer)"); } const u32 size = vsharp.GetSize(); - const u32 alignment = buffer.is_storage ? instance.StorageMinAlignment() - : instance.UniformMinAlignment(); + const u32 alignment = + is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment(); const auto [vk_buffer, offset] = buffer_cache.ObtainBuffer(address, size, buffer.is_written); const u32 offset_aligned = Common::AlignDown(offset, alignment); const u32 adjust = offset - offset_aligned; - if (adjust != 0) { - ASSERT(adjust % 4 == 0); - push_data.AddOffset(binding, adjust); - } + ASSERT(adjust % 4 == 0); + push_data.AddOffset(binding.buffer, adjust); buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust); - } else { + } 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); } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, - .dstBinding = binding++, + .dstBinding = binding.unified++, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer - : vk::DescriptorType::eUniformBuffer, + .descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer + : vk::DescriptorType::eUniformBuffer, .pBufferInfo = &buffer_infos.back(), }); + ++binding.buffer; } - boost::container::static_vector tsharps; - for (const auto& image_desc : stage->images) { - const auto& tsharp = tsharps.emplace_back( - stage->ReadUd(image_desc.sgpr_base, image_desc.dword_offset)); - VideoCore::ImageInfo image_info{tsharp}; - VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage}; - const auto& image_view = texture_cache.FindTexture(image_info, view_info); - const auto& image = texture_cache.GetImage(image_view.image_id); - image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); + const auto null_buffer_view = + instance.IsNullDescriptorSupported() ? VK_NULL_HANDLE : buffer_cache.NullBufferView(); + for (const auto& desc : stage->texture_buffers) { + const auto vsharp = desc.GetSharp(*stage); + vk::BufferView& buffer_view = buffer_views.emplace_back(null_buffer_view); + const u32 size = vsharp.GetSize(); + if (vsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid && size != 0) { + const VAddr address = vsharp.base_address; + const u32 alignment = instance.TexelBufferMinAlignment(); + const auto [vk_buffer, offset] = + buffer_cache.ObtainBuffer(address, size, desc.is_written, true); + const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; + ASSERT_MSG(fmt_stride == vsharp.GetStride(), + "Texel buffer stride must match format stride"); + const u32 offset_aligned = Common::AlignDown(offset, alignment); + const u32 adjust = offset - offset_aligned; + ASSERT(adjust % fmt_stride == 0); + push_data.AddOffset(binding.buffer, adjust / fmt_stride); + buffer_view = vk_buffer->View(offset_aligned, size + adjust, desc.is_written, + vsharp.GetDataFmt(), vsharp.GetNumberFmt()); + const auto dst_access = desc.is_written ? vk::AccessFlagBits2::eShaderWrite + : vk::AccessFlagBits2::eShaderRead; + if (auto barrier = vk_buffer->GetBarrier( + dst_access, vk::PipelineStageFlagBits2::eVertexShader)) { + buffer_barriers.emplace_back(*barrier); + } + if (desc.is_written) { + texture_cache.InvalidateMemoryFromGPU(address, size); + } + } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, - .dstBinding = binding++, + .dstBinding = binding.unified++, .dstArrayElement = 0, .descriptorCount = 1, - .descriptorType = image_desc.is_storage ? vk::DescriptorType::eStorageImage - : vk::DescriptorType::eSampledImage, - .pImageInfo = &image_infos.back(), + .descriptorType = desc.is_written ? vk::DescriptorType::eStorageTexelBuffer + : vk::DescriptorType::eUniformTexelBuffer, + .pTexelBufferView = &buffer_view, }); - - if (texture_cache.IsMeta(tsharp.Address())) { - LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (texture)"); - } + ++binding.buffer; } + + BindTextures(texture_cache, *stage, binding, set_writes); + for (const auto& sampler : stage->samplers) { - auto ssharp = sampler.GetSsharp(*stage); + auto ssharp = sampler.GetSharp(*stage); + if (ssharp.force_degamma) { + LOG_WARNING(Render_Vulkan, "Texture requires gamma correction"); + } if (sampler.disable_aniso) { - const auto& tsharp = tsharps[sampler.associated_image]; + const auto& tsharp = stage->images[sampler.associated_image].GetSharp(*stage); if (tsharp.base_level == 0 && tsharp.last_level == 0) { ssharp.max_aniso.Assign(AmdGpu::AnisoRatio::One); } @@ -429,7 +497,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); set_writes.push_back({ .dstSet = VK_NULL_HANDLE, - .dstBinding = binding++, + .dstBinding = binding.unified++, .dstArrayElement = 0, .descriptorCount = 1, .descriptorType = vk::DescriptorType::eSampler, @@ -439,13 +507,32 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, } const auto cmdbuf = scheduler.CommandBuffer(); - if (!set_writes.empty()) { - cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0, - set_writes); + + if (!buffer_barriers.empty()) { + const auto dependencies = vk::DependencyInfo{ + .dependencyFlags = vk::DependencyFlagBits::eByRegion, + .bufferMemoryBarrierCount = u32(buffer_barriers.size()), + .pBufferMemoryBarriers = buffer_barriers.data(), + }; + scheduler.EndRendering(); + cmdbuf.pipelineBarrier2(dependencies); } - cmdbuf.pushConstants(*pipeline_layout, - vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, 0U, - sizeof(push_data), &push_data); + + if (!set_writes.empty()) { + if (uses_push_descriptors) { + cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0, + set_writes); + } else { + const auto desc_set = desc_heap.Commit(*desc_layout); + for (auto& set_write : set_writes) { + set_write.dstSet = desc_set; + } + instance.GetDevice().updateDescriptorSets(set_writes, {}); + cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0, + desc_set, {}); + } + } + cmdbuf.pushConstants(*pipeline_layout, gp_stage_flags, 0U, sizeof(push_data), &push_data); cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, Handle()); } diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 548e7d451..f7762eb12 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -5,7 +5,7 @@ #include "common/types.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_common.h" -#include "video_core/renderer_vulkan/vk_compute_pipeline.h" +#include "video_core/renderer_vulkan/vk_pipeline_common.h" namespace VideoCore { class BufferCache; @@ -19,60 +19,51 @@ static constexpr u32 MaxShaderStages = 5; class Instance; class Scheduler; +class DescriptorHeap; using Liverpool = AmdGpu::Liverpool; struct GraphicsPipelineKey { std::array stage_hashes; std::array color_formats; + std::array color_num_formats; + std::array mrt_swizzles; vk::Format depth_format; vk::Format stencil_format; - Liverpool::DepthControl depth; - float depth_bounds_min; - float depth_bounds_max; - float depth_bias_const_factor; - float depth_bias_slope_factor; - float depth_bias_clamp; + Liverpool::DepthControl depth_stencil; u32 depth_bias_enable; - u32 num_samples = 1; + u32 num_samples; + u32 mrt_mask; Liverpool::StencilControl stencil; - Liverpool::StencilRefMask stencil_ref_front; - Liverpool::StencilRefMask stencil_ref_back; - Liverpool::PrimitiveType prim_type; + AmdGpu::PrimitiveType prim_type; u32 enable_primitive_restart; u32 primitive_restart_index; Liverpool::PolygonMode polygon_mode; Liverpool::CullMode cull_mode; Liverpool::FrontFace front_face; Liverpool::ClipSpace clip_space; - Liverpool::ColorBufferMask cb_shader_mask{}; + Liverpool::ColorBufferMask cb_shader_mask; std::array blend_controls; std::array write_masks; + std::array vertex_buffer_formats; bool operator==(const GraphicsPipelineKey& key) const noexcept { return std::memcmp(this, &key, sizeof(key)) == 0; } }; -class GraphicsPipeline { +class GraphicsPipeline : public Pipeline { public: - explicit GraphicsPipeline(const Instance& instance, Scheduler& scheduler, - const GraphicsPipelineKey& key, vk::PipelineCache pipeline_cache, - std::span programs); + GraphicsPipeline(const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap, + const GraphicsPipelineKey& key, vk::PipelineCache pipeline_cache, + std::span stages, + std::span modules); ~GraphicsPipeline(); void BindResources(const Liverpool::Regs& regs, VideoCore::BufferCache& buffer_cache, VideoCore::TextureCache& texture_cache) const; - vk::Pipeline Handle() const noexcept { - return *pipeline; - } - - vk::PipelineLayout GetLayout() const { - return *pipeline_layout; - } - const Shader::Info& GetStage(Shader::Stage stage) const noexcept { return *stages[u32(stage)]; } @@ -86,21 +77,31 @@ public: return key.write_masks; } + auto GetMrtMask() const { + return key.mrt_mask; + } + bool IsDepthEnabled() const { - return key.depth.depth_enable.Value(); + return key.depth_stencil.depth_enable.Value(); + } + + [[nodiscard]] bool IsPrimitiveListTopology() const { + return key.prim_type == AmdGpu::PrimitiveType::PointList || + key.prim_type == AmdGpu::PrimitiveType::LineList || + key.prim_type == AmdGpu::PrimitiveType::TriangleList || + key.prim_type == AmdGpu::PrimitiveType::AdjLineList || + key.prim_type == AmdGpu::PrimitiveType::AdjTriangleList || + key.prim_type == AmdGpu::PrimitiveType::RectList || + key.prim_type == AmdGpu::PrimitiveType::QuadList; } private: void BuildDescSetLayout(); private: - const Instance& instance; - Scheduler& scheduler; - vk::UniquePipeline pipeline; - vk::UniquePipelineLayout pipeline_layout; - vk::UniqueDescriptorSetLayout desc_layout; std::array stages{}; GraphicsPipelineKey key; + bool uses_push_descriptors{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 66da030f1..dda4e0d9f 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -20,8 +20,20 @@ namespace Vulkan { namespace { +std::vector EnumeratePhysicalDevices(vk::UniqueInstance& instance) { + auto [devices_result, devices] = instance->enumeratePhysicalDevices(); + ASSERT_MSG(devices_result == vk::Result::eSuccess, "Failed to enumerate physical devices: {}", + vk::to_string(devices_result)); + return std::move(devices); +} + std::vector GetSupportedExtensions(vk::PhysicalDevice physical) { - const std::vector extensions = physical.enumerateDeviceExtensionProperties(); + const auto [extensions_result, extensions] = physical.enumerateDeviceExtensionProperties(); + if (extensions_result != vk::Result::eSuccess) { + LOG_ERROR(Render_Vulkan, "Could not query supported extensions: {}", + vk::to_string(extensions_result)); + return {}; + } std::vector supported_extensions; supported_extensions.reserve(extensions.size()); for (const auto& extension : extensions) { @@ -30,11 +42,41 @@ std::vector GetSupportedExtensions(vk::PhysicalDevice physical) { return supported_extensions; } -std::unordered_map GetFormatProperties( +vk::FormatProperties3 GetFormatProperties(vk::PhysicalDevice physical, vk::Format format) { + vk::FormatProperties3 properties3{}; + vk::FormatProperties2 properties2 = { + .pNext = &properties3, + }; + physical.getFormatProperties2(format, &properties2); + return properties3; +} + +std::unordered_map GetFormatProperties( vk::PhysicalDevice physical) { - std::unordered_map format_properties; - for (const auto& format : LiverpoolToVK::GetAllFormats()) { - format_properties.emplace(format, physical.getFormatProperties(format)); + std::unordered_map format_properties; + for (const auto& format_info : LiverpoolToVK::SurfaceFormats()) { + const auto format = format_info.vk_format; + if (!format_properties.contains(format)) { + format_properties.emplace(format, GetFormatProperties(physical, format)); + } + } + for (const auto& format_info : LiverpoolToVK::DepthFormats()) { + const auto format = format_info.vk_format; + if (!format_properties.contains(format)) { + format_properties.emplace(format, GetFormatProperties(physical, format)); + } + } + // Other miscellaneous formats, e.g. for color buffers, swizzles, or compatibility + static constexpr std::array misc_formats = { + vk::Format::eA2R10G10B10UnormPack32, vk::Format::eA8B8G8R8UnormPack32, + vk::Format::eA8B8G8R8SrgbPack32, vk::Format::eB8G8R8A8Unorm, + vk::Format::eB8G8R8A8Srgb, vk::Format::eR5G6B5UnormPack16, + vk::Format::eD24UnormS8Uint, + }; + for (const auto& format : misc_formats) { + if (!format_properties.contains(format)) { + format_properties.emplace(format, GetFormatProperties(physical, format)); + } } return format_properties; } @@ -46,15 +88,16 @@ std::string GetReadableVersion(u32 version) { } // Anonymous namespace -Instance::Instance(bool enable_validation, bool dump_command_buffers) - : instance{CreateInstance(dl, Frontend::WindowSystemType::Headless, enable_validation, - dump_command_buffers)}, - physical_devices{instance->enumeratePhysicalDevices()} {} +Instance::Instance(bool enable_validation, bool enable_crash_diagnostic) + : instance{CreateInstance(Frontend::WindowSystemType::Headless, enable_validation, + enable_crash_diagnostic)}, + physical_devices{EnumeratePhysicalDevices(instance)} {} Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index, - bool enable_validation /*= false*/) - : instance{CreateInstance(dl, window.getWindowInfo().type, enable_validation, false)}, - physical_devices{instance->enumeratePhysicalDevices()} { + bool enable_validation /*= false*/, bool enable_crash_diagnostic /*= false*/) + : instance{CreateInstance(window.getWindowInfo().type, enable_validation, + enable_crash_diagnostic)}, + physical_devices{EnumeratePhysicalDevices(instance)} { if (enable_validation) { debug_callback = CreateDebugCallback(*instance); } @@ -116,18 +159,23 @@ Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index, CollectToolingInfo(); // Check and log format support details. - for (const auto& key : format_properties | std::views::keys) { - const auto format = key; - if (!IsFormatSupported(format)) { - const auto alternative = GetAlternativeFormat(format); - if (IsFormatSupported(alternative)) { - LOG_WARNING(Render_Vulkan, "Format {} is not supported, falling back to {}", - vk::to_string(format), vk::to_string(alternative)); - } else { - LOG_ERROR(Render_Vulkan, - "Format {} is not supported and no suitable alternative is supported.", - vk::to_string(format)); - } + for (const auto& format : LiverpoolToVK::SurfaceFormats()) { + if (!IsFormatSupported(GetSupportedFormat(format.vk_format, format.flags), format.flags)) { + LOG_WARNING(Render_Vulkan, + "Surface format data_format={}, number_format={} is not fully supported " + "(vk_format={}, requested flags={})", + static_cast(format.data_format), + static_cast(format.number_format), vk::to_string(format.vk_format), + vk::to_string(format.flags)); + } + } + for (const auto& format : LiverpoolToVK::DepthFormats()) { + if (!IsFormatSupported(GetSupportedFormat(format.vk_format, format.flags), format.flags)) { + LOG_WARNING(Render_Vulkan, + "Depth format z_format={}, stencil_format={} is not fully supported " + "(vk_format={}, requested flags={})", + static_cast(format.z_format), static_cast(format.stencil_format), + vk::to_string(format.vk_format), vk::to_string(format.flags)); } } } @@ -168,8 +216,11 @@ bool Instance::CreateDevice() { vk::PhysicalDevicePortabilitySubsetFeaturesKHR>(); const vk::StructureChain properties_chain = physical_device.getProperties2< vk::PhysicalDeviceProperties2, vk::PhysicalDevicePortabilitySubsetPropertiesKHR, - vk::PhysicalDeviceExternalMemoryHostPropertiesEXT, vk::PhysicalDeviceVulkan11Properties>(); + vk::PhysicalDeviceExternalMemoryHostPropertiesEXT, vk::PhysicalDeviceVulkan11Properties, + vk::PhysicalDevicePushDescriptorPropertiesKHR, vk::PhysicalDeviceVulkan12Properties>(); subgroup_size = properties_chain.get().subgroupSize; + push_descriptor_props = properties_chain.get(); + vk12_props = properties_chain.get(); LOG_INFO(Render_Vulkan, "Physical device subgroup size {}", subgroup_size); features = feature_chain.get().features; @@ -178,7 +229,7 @@ bool Instance::CreateDevice() { return false; } - boost::container::static_vector enabled_extensions; + boost::container::static_vector enabled_extensions; const auto add_extension = [&](std::string_view extension) -> bool { const auto result = std::find_if(available_extensions.begin(), available_extensions.end(), @@ -199,7 +250,7 @@ bool Instance::CreateDevice() { external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - const bool depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); + depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); workgroup_memory_explicit_layout = add_extension(VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); @@ -210,20 +261,20 @@ bool Instance::CreateDevice() { color_write_en &= add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); const bool calibrated_timestamps = add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME); const bool robustness = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); + list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME); + maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 // with extensions. - tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); + if (Config::vkValidationEnabled() || Config::isRdocEnabled()) { + tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); + } const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); + add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME); add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); - const bool has_sync2 = add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); - - if (has_sync2) { - has_nv_checkpoints = Config::isMarkersEnabled() - ? add_extension(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME) - : false; - } + add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); + add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); #ifdef __APPLE__ // Required by Vulkan spec if supported. @@ -269,16 +320,21 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceFeatures2{ .features{ .robustBufferAccess = features.robustBufferAccess, + .imageCubeArray = features.imageCubeArray, .independentBlend = features.independentBlend, .geometryShader = features.geometryShader, .logicOp = features.logicOp, + .depthBiasClamp = features.depthBiasClamp, + .fillModeNonSolid = features.fillModeNonSolid, .multiViewport = features.multiViewport, .samplerAnisotropy = features.samplerAnisotropy, + .vertexPipelineStoresAndAtomics = features.vertexPipelineStoresAndAtomics, .fragmentStoresAndAtomics = features.fragmentStoresAndAtomics, .shaderImageGatherExtended = features.shaderImageGatherExtended, .shaderStorageImageExtendedFormats = features.shaderStorageImageExtendedFormats, .shaderStorageImageMultisample = features.shaderStorageImageMultisample, .shaderClipDistance = features.shaderClipDistance, + .shaderFloat64 = features.shaderFloat64, .shaderInt64 = features.shaderInt64, .shaderInt16 = features.shaderInt16, }, @@ -287,15 +343,20 @@ bool Instance::CreateDevice() { .shaderDrawParameters = true, }, vk::PhysicalDeviceVulkan12Features{ + .samplerMirrorClampToEdge = vk12_features.samplerMirrorClampToEdge, .shaderFloat16 = vk12_features.shaderFloat16, .scalarBlockLayout = vk12_features.scalarBlockLayout, .uniformBufferStandardLayout = vk12_features.uniformBufferStandardLayout, + .separateDepthStencilLayouts = vk12_features.separateDepthStencilLayouts, .hostQueryReset = vk12_features.hostQueryReset, .timelineSemaphore = vk12_features.timelineSemaphore, }, vk::PhysicalDeviceMaintenance4FeaturesKHR{ .maintenance4 = true, }, + vk::PhysicalDeviceMaintenance5FeaturesKHR{ + .maintenance5 = true, + }, vk::PhysicalDeviceDynamicRenderingFeaturesKHR{ .dynamicRendering = true, }, @@ -309,6 +370,9 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceColorWriteEnableFeaturesEXT{ .colorWriteEnable = true, }, + vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{ + .extendedDynamicState = true, + }, vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{ .extendedDynamicState3ColorWriteMask = true, }, @@ -330,6 +394,9 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{ .vertexInputDynamicState = true, }, + vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT{ + .primitiveTopologyListRestart = true, + }, #ifdef __APPLE__ feature_chain.get(), #endif @@ -338,6 +405,9 @@ bool Instance::CreateDevice() { if (!maintenance4) { device_chain.unlink(); } + if (!maintenance5) { + device_chain.unlink(); + } if (!custom_border_color) { device_chain.unlink(); } @@ -351,25 +421,28 @@ bool Instance::CreateDevice() { if (!workgroup_memory_explicit_layout) { device_chain.unlink(); } + if (!list_restart) { + device_chain.unlink(); + } if (robustness) { - device_chain.get().nullDescriptor = + null_descriptor = feature_chain.get().nullDescriptor; + device_chain.get().nullDescriptor = + null_descriptor; } else { + null_descriptor = false; device_chain.unlink(); } if (!vertex_input_dynamic_state) { device_chain.unlink(); } - try { - device = physical_device.createDeviceUnique(device_chain.get()); - } catch (vk::ExtensionNotPresentError& err) { - LOG_CRITICAL(Render_Vulkan, "Some required extensions are not available {}", err.what()); - return false; - } catch (vk::FeatureNotPresentError& err) { - LOG_CRITICAL(Render_Vulkan, "Some required features are not available {}", err.what()); + auto [device_result, dev] = physical_device.createDeviceUnique(device_chain.get()); + if (device_result != vk::Result::eSuccess) { + LOG_CRITICAL(Render_Vulkan, "Failed to create device: {}", vk::to_string(device_result)); return false; } + device = std::move(dev); VULKAN_HPP_DEFAULT_DISPATCHER.init(*device); @@ -377,27 +450,33 @@ bool Instance::CreateDevice() { present_queue = device->getQueue(queue_family_index, 0); if (calibrated_timestamps) { - const auto& time_domains = physical_device.getCalibrateableTimeDomainsEXT(); + const auto [time_domains_result, time_domains] = + physical_device.getCalibrateableTimeDomainsEXT(); + if (time_domains_result == vk::Result::eSuccess) { #if _WIN64 - const bool has_host_time_domain = - std::find(time_domains.cbegin(), time_domains.cend(), - vk::TimeDomainEXT::eQueryPerformanceCounter) != time_domains.cend(); + const bool has_host_time_domain = + std::find(time_domains.cbegin(), time_domains.cend(), + vk::TimeDomainEXT::eQueryPerformanceCounter) != time_domains.cend(); #elif __linux__ - const bool has_host_time_domain = - std::find(time_domains.cbegin(), time_domains.cend(), - vk::TimeDomainEXT::eClockMonotonicRaw) != time_domains.cend(); + const bool has_host_time_domain = + std::find(time_domains.cbegin(), time_domains.cend(), + vk::TimeDomainEXT::eClockMonotonicRaw) != time_domains.cend(); #else - // Tracy limitation means only Windows and Linux can use host time domain. - // https://github.com/shadps4-emu/tracy/blob/c6d779d78508514102fbe1b8eb28bda10d95bb2a/public/tracy/TracyVulkan.hpp#L384-L389 - const bool has_host_time_domain = false; + // Tracy limitation means only Windows and Linux can use host time domain. + // https://github.com/shadps4-emu/tracy/blob/c6d779d78508514102fbe1b8eb28bda10d95bb2a/public/tracy/TracyVulkan.hpp#L384-L389 + const bool has_host_time_domain = false; #endif - if (has_host_time_domain) { - static constexpr std::string_view context_name{"vk_rasterizer"}; - profiler_context = - TracyVkContextHostCalibrated(*instance, physical_device, *device, - VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr, - VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr); - TracyVkContextName(profiler_context, context_name.data(), context_name.size()); + if (has_host_time_domain) { + static constexpr std::string_view context_name{"vk_rasterizer"}; + profiler_context = TracyVkContextHostCalibrated( + *instance, physical_device, *device, + VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr, + VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr); + TracyVkContextName(profiler_context, context_name.data(), context_name.size()); + } + } else { + LOG_WARNING(Render_Vulkan, "Could not query calibrated time domains for profiling: {}", + vk::to_string(time_domains_result)); } } @@ -453,7 +532,12 @@ void Instance::CollectToolingInfo() { if (!tooling_info) { return; } - const auto tools = physical_device.getToolPropertiesEXT(); + const auto [tools_result, tools] = physical_device.getToolPropertiesEXT(); + if (tools_result != vk::Result::eSuccess) { + LOG_ERROR(Render_Vulkan, "Could not get Vulkan tool properties: {}", + vk::to_string(tools_result)); + return; + } for (const vk::PhysicalDeviceToolProperties& tool : tools) { const std::string_view name = tool.name; LOG_INFO(Render_Vulkan, "Attached debugging tool: {}", name); @@ -462,7 +546,8 @@ void Instance::CollectToolingInfo() { } } -bool Instance::IsFormatSupported(const vk::Format format) const { +bool Instance::IsFormatSupported(const vk::Format format, + const vk::FormatFeatureFlags2 flags) const { if (format == vk::Format::eUndefined) [[unlikely]] { return true; } @@ -472,33 +557,36 @@ bool Instance::IsFormatSupported(const vk::Format format) const { UNIMPLEMENTED_MSG("Properties of format {} have not been queried.", vk::to_string(format)); } - constexpr vk::FormatFeatureFlags optimal_flags = vk::FormatFeatureFlagBits::eTransferSrc | - vk::FormatFeatureFlagBits::eTransferDst | - vk::FormatFeatureFlagBits::eSampledImage; - return (it->second.optimalTilingFeatures & optimal_flags) == optimal_flags; + return ((it->second.optimalTilingFeatures | it->second.bufferFeatures) & flags) == flags; } -vk::Format Instance::GetAlternativeFormat(const vk::Format format) const { - if (format == vk::Format::eB5G6R5UnormPack16) { +static vk::Format GetAlternativeFormat(const vk::Format format) { + switch (format) { + case vk::Format::eB5G6R5UnormPack16: return vk::Format::eR5G6B5UnormPack16; + case vk::Format::eD16UnormS8Uint: + return vk::Format::eD24UnormS8Uint; + default: + return format; } - return format; } -vk::Format Instance::GetSupportedFormat(const vk::Format format) const { - if (IsFormatSupported(format)) [[likely]] { +vk::Format Instance::GetSupportedFormat(const vk::Format format, + const vk::FormatFeatureFlags2 flags) const { + if (IsFormatSupported(format, flags)) [[likely]] { return format; } const vk::Format alternative = GetAlternativeFormat(format); - if (IsFormatSupported(alternative)) [[likely]] { + if (IsFormatSupported(alternative, flags)) [[likely]] { return alternative; } return format; } -vk::ComponentMapping Instance::GetSupportedComponentSwizzle(vk::Format format, - vk::ComponentMapping swizzle) const { - if (IsFormatSupported(format)) [[likely]] { +vk::ComponentMapping Instance::GetSupportedComponentSwizzle( + const vk::Format format, const vk::ComponentMapping swizzle, + const vk::FormatFeatureFlags2 flags) const { + if (IsFormatSupported(format, flags)) [[likely]] { return swizzle; } diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 4cb4741a5..474b86e9a 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -17,30 +17,25 @@ class WindowSDL; VK_DEFINE_HANDLE(VmaAllocator) -#ifdef __APPLE__ -#define VULKAN_LIBRARY_NAME "libMoltenVK.dylib" -#else -#define VULKAN_LIBRARY_NAME -#endif - namespace Vulkan { class Instance { public: - explicit Instance(bool validation = false, bool dump_command_buffers = false); + explicit Instance(bool validation = false, bool crash_diagnostic = false); explicit Instance(Frontend::WindowSDL& window, s32 physical_device_index, - bool enable_validation = false); + bool enable_validation = false, bool enable_crash_diagnostic = false); ~Instance(); /// Returns a formatted string for the driver version std::string GetDriverVersionName(); /// Gets a compatibility format if the format is not supported. - [[nodiscard]] vk::Format GetSupportedFormat(vk::Format format) const; + [[nodiscard]] vk::Format GetSupportedFormat(vk::Format format, + vk::FormatFeatureFlags2 flags) const; /// Re-orders a component swizzle for format compatibility, if needed. [[nodiscard]] vk::ComponentMapping GetSupportedComponentSwizzle( - vk::Format format, vk::ComponentMapping swizzle) const; + vk::Format format, vk::ComponentMapping swizzle, vk::FormatFeatureFlags2 flags) const; /// Returns the Vulkan instance vk::Instance GetInstance() const { @@ -88,10 +83,6 @@ public: return profiler_context; } - bool HasNvCheckpoints() const { - return has_nv_checkpoints; - } - /// Returns true when a known debugging tool is attached. bool HasDebuggingToolAttached() const { return has_renderdoc || has_nsight_graphics; @@ -127,6 +118,11 @@ public: return external_memory_host; } + /// Returns true when VK_EXT_depth_clip_control is supported + bool IsDepthClipControlSupported() const { + return depth_clip_control; + } + /// Returns true when VK_EXT_color_write_enable is supported bool IsColorWriteEnableSupported() const { return color_write_en; @@ -137,6 +133,30 @@ public: return vertex_input_dynamic_state; } + /// Returns true when the nullDescriptor feature of VK_EXT_robustness2 is supported. + bool IsNullDescriptorSupported() const { + return null_descriptor; + } + + /// Returns true when VK_KHR_maintenance5 is supported. + bool IsMaintenance5Supported() const { + return maintenance5; + } + + bool IsListRestartSupported() const { + return list_restart; + } + + /// Returns true when geometry shaders are supported by the device + bool IsGeometryStageSupported() const { + return features.geometryShader; + } + + /// Returns true when tessellation is supported by the device + bool IsTessellationSupported() const { + return features.tessellationShader; + } + /// Returns the vendor ID of the physical device u32 GetVendorID() const { return properties.vendorID; @@ -192,6 +212,11 @@ public: return properties.limits.minStorageBufferOffsetAlignment; } + /// Returns the minimum required alignment for texel buffers + vk::DeviceSize TexelBufferMinAlignment() const { + return properties.limits.minTexelBufferOffsetAlignment; + } + /// Returns the minimum alignemt required for accessing host-mapped device memory vk::DeviceSize NonCoherentAtomSize() const { return properties.limits.nonCoherentAtomSize; @@ -207,6 +232,21 @@ public: return properties.limits.maxTexelBufferElements; } + /// Returns the maximum sampler LOD bias. + float MaxSamplerLodBias() const { + return properties.limits.maxSamplerLodBias; + } + + /// Returns the maximum number of push descriptors. + u32 MaxPushDescriptors() const { + return push_descriptor_props.maxPushDescriptors; + } + + /// Returns the vulkan 1.2 physical device properties. + const vk::PhysicalDeviceVulkan12Properties& GetVk12Properties() const noexcept { + return vk12_props; + } + /// Returns true if shaders can declare the ClipDistance attribute bool IsShaderClipDistanceSupported() const { return features.shaderClipDistance; @@ -217,6 +257,13 @@ public: return min_imported_host_pointer_alignment; } + /// Returns the sample count flags supported by framebuffers. + vk::SampleCountFlags GetFramebufferSampleCounts() const { + return properties.limits.framebufferColorSampleCounts & + properties.limits.framebufferDepthSampleCounts & + properties.limits.framebufferStencilSampleCounts; + } + private: /// Creates the logical device opportunistically enabling extensions bool CreateDevice(); @@ -228,18 +275,16 @@ private: void CollectDeviceParameters(); void CollectToolingInfo(); - /// Determines if a format is supported. - [[nodiscard]] bool IsFormatSupported(vk::Format format) const; - - /// Gets a commonly available alternative for an unsupported pixel format. - vk::Format GetAlternativeFormat(const vk::Format format) const; + /// Determines if a format is supported for a set of feature flags. + [[nodiscard]] bool IsFormatSupported(vk::Format format, vk::FormatFeatureFlags2 flags) const; private: - vk::DynamicLoader dl{VULKAN_LIBRARY_NAME}; vk::UniqueInstance instance; vk::PhysicalDevice physical_device; vk::UniqueDevice device; vk::PhysicalDeviceProperties properties; + vk::PhysicalDevicePushDescriptorPropertiesKHR push_descriptor_props; + vk::PhysicalDeviceVulkan12Properties vk12_props; vk::PhysicalDeviceFeatures features; vk::DriverIdKHR driver_id; vk::UniqueDebugUtilsMessengerEXT debug_callback{}; @@ -249,7 +294,7 @@ private: vk::Queue graphics_queue; std::vector physical_devices; std::vector available_extensions; - std::unordered_map format_properties; + std::unordered_map format_properties; TracyVkCtx profiler_context{}; u32 queue_family_index{0}; bool image_view_reinterpretation{true}; @@ -260,16 +305,19 @@ private: bool fragment_shader_barycentric{}; bool shader_stencil_export{}; bool external_memory_host{}; + bool depth_clip_control{}; bool workgroup_memory_explicit_layout{}; bool color_write_en{}; bool vertex_input_dynamic_state{}; + bool null_descriptor{}; + bool maintenance5{}; + bool list_restart{}; u64 min_imported_host_pointer_alignment{}; u32 subgroup_size{}; bool tooling_info{}; bool debug_utils_supported{}; bool has_nsight_graphics{}; bool has_renderdoc{}; - bool has_nv_checkpoints{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index 753f2bbdf..00f63681e 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp @@ -5,6 +5,8 @@ #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_master_semaphore.h" +#include "common/assert.h" + namespace Vulkan { constexpr u64 WAIT_TIMEOUT = std::numeric_limits::max(); @@ -17,7 +19,11 @@ MasterSemaphore::MasterSemaphore(const Instance& instance_) : instance{instance_ .initialValue = 0, }, }; - semaphore = instance.GetDevice().createSemaphoreUnique(semaphore_chain.get()); + auto [semaphore_result, sem] = + instance.GetDevice().createSemaphoreUnique(semaphore_chain.get()); + ASSERT_MSG(semaphore_result == vk::Result::eSuccess, "Failed to create master semaphore: {}", + vk::to_string(semaphore_result)); + semaphore = std::move(sem); } MasterSemaphore::~MasterSemaphore() = default; @@ -27,7 +33,10 @@ void MasterSemaphore::Refresh() { u64 counter{}; do { this_tick = gpu_tick.load(std::memory_order_acquire); - counter = instance.GetDevice().getSemaphoreCounterValue(*semaphore); + auto [counter_result, cntr] = instance.GetDevice().getSemaphoreCounterValue(*semaphore); + ASSERT_MSG(counter_result == vk::Result::eSuccess, + "Failed to get master semaphore value: {}", vk::to_string(counter_result)); + counter = cntr; if (counter < this_tick) { return; } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 55f04bac4..a06d82eb3 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -1,11 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include + #include "common/config.h" #include "common/io_file.h" #include "common/path_util.h" #include "shader_recompiler/backend/spirv/emit_spirv.h" -#include "shader_recompiler/exception.h" +#include "shader_recompiler/info.h" #include "shader_recompiler/recompiler.h" #include "shader_recompiler/runtime_info.h" #include "video_core/renderer_vulkan/renderer_vulkan.h" @@ -24,11 +26,21 @@ using Shader::VsOutput; return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)); } -void BuildVsOutputs(Shader::Info& info, const AmdGpu::Liverpool::VsOutputControl& ctl) { +constexpr static std::array DescriptorHeapSizes = { + vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 8192}, + vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer, 1024}, + vk::DescriptorPoolSize{vk::DescriptorType::eUniformTexelBuffer, 128}, + vk::DescriptorPoolSize{vk::DescriptorType::eStorageTexelBuffer, 128}, + vk::DescriptorPoolSize{vk::DescriptorType::eSampledImage, 8192}, + vk::DescriptorPoolSize{vk::DescriptorType::eSampler, 1024}, +}; + +void GatherVertexOutputs(Shader::VertexRuntimeInfo& info, + const AmdGpu::Liverpool::VsOutputControl& ctl) { const auto add_output = [&](VsOutput x, VsOutput y, VsOutput z, VsOutput w) { if (x != VsOutput::None || y != VsOutput::None || z != VsOutput::None || w != VsOutput::None) { - info.vs_outputs.emplace_back(Shader::VsOutputMap{x, y, z, w}); + info.outputs[info.num_outputs++] = Shader::VsOutputMap{x, y, z, w}; } }; // VS_OUT_MISC_VEC @@ -68,38 +80,78 @@ void BuildVsOutputs(Shader::Info& info, const AmdGpu::Liverpool::VsOutputControl : (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None)); } -Shader::Info MakeShaderInfo(Shader::Stage stage, std::span user_data, - const AmdGpu::Liverpool::Regs& regs) { - Shader::Info info{}; - info.user_data = user_data; - info.stage = stage; +Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) { + auto info = Shader::RuntimeInfo{stage}; + const auto& regs = liverpool->regs; + const auto BuildCommon = [&](const auto& program) { + info.num_user_data = program.settings.num_user_regs; + info.num_input_vgprs = program.settings.vgpr_comp_cnt; + info.num_allocated_vgprs = program.settings.num_vgprs * 4; + info.fp_denorm_mode32 = program.settings.fp_denorm_mode32; + info.fp_round_mode32 = program.settings.fp_round_mode32; + }; switch (stage) { + case Shader::Stage::Export: { + BuildCommon(regs.es_program); + info.es_info.vertex_data_size = regs.vgt_esgs_ring_itemsize; + break; + } case Shader::Stage::Vertex: { - info.num_user_data = regs.vs_program.settings.num_user_regs; - info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt; - BuildVsOutputs(info, regs.vs_output_control); + BuildCommon(regs.vs_program); + GatherVertexOutputs(info.vs_info, regs.vs_output_control); + info.vs_info.emulate_depth_negative_one_to_one = + !instance.IsDepthClipControlSupported() && + regs.clipper_control.clip_space == Liverpool::ClipSpace::MinusWToW; + break; + } + case Shader::Stage::Geometry: { + BuildCommon(regs.gs_program); + auto& gs_info = info.gs_info; + gs_info.output_vertices = regs.vgt_gs_max_vert_out; + gs_info.num_invocations = + regs.vgt_gs_instance_cnt.IsEnabled() ? regs.vgt_gs_instance_cnt.count : 1; + gs_info.in_primitive = regs.primitive_type; + for (u32 stream_id = 0; stream_id < Shader::GsMaxOutputStreams; ++stream_id) { + gs_info.out_primitive[stream_id] = + regs.vgt_gs_out_prim_type.GetPrimitiveType(stream_id); + } + gs_info.in_vertex_data_size = regs.vgt_esgs_ring_itemsize; + gs_info.out_vertex_data_size = regs.vgt_gs_vert_itemsize[0]; + const auto params_vc = Liverpool::GetParams(regs.vs_program); + gs_info.vs_copy = params_vc.code; + gs_info.vs_copy_hash = params_vc.hash; + DumpShader(gs_info.vs_copy, gs_info.vs_copy_hash, Shader::Stage::Vertex, 0, "copy.bin"); break; } case Shader::Stage::Fragment: { - info.num_user_data = regs.ps_program.settings.num_user_regs; + BuildCommon(regs.ps_program); + const auto& ps_inputs = regs.ps_inputs; + info.fs_info.num_inputs = regs.num_interp; for (u32 i = 0; i < regs.num_interp; i++) { - info.ps_inputs.push_back({ - .param_index = regs.ps_inputs[i].input_offset.Value(), - .is_default = bool(regs.ps_inputs[i].use_default), - .is_flat = bool(regs.ps_inputs[i].flat_shade), - .default_value = regs.ps_inputs[i].default_value, - }); + info.fs_info.inputs[i] = { + .param_index = u8(ps_inputs[i].input_offset.Value()), + .is_default = bool(ps_inputs[i].use_default), + .is_flat = bool(ps_inputs[i].flat_shade), + .default_value = u8(ps_inputs[i].default_value), + }; + } + 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]), + }; } break; } case Shader::Stage::Compute: { const auto& cs_pgm = regs.cs_program; info.num_user_data = cs_pgm.settings.num_user_regs; - info.workgroup_size = {cs_pgm.num_thread_x.full, cs_pgm.num_thread_y.full, - cs_pgm.num_thread_z.full}; - info.tgid_enable = {cs_pgm.IsTgidEnabled(0), cs_pgm.IsTgidEnabled(1), - cs_pgm.IsTgidEnabled(2)}; - info.shared_memory_size = cs_pgm.SharedMemSize(); + info.num_allocated_vgprs = regs.cs_program.settings.num_vgprs * 4; + info.cs_info.workgroup_size = {cs_pgm.num_thread_x.full, cs_pgm.num_thread_y.full, + cs_pgm.num_thread_z.full}; + info.cs_info.tgid_enable = {cs_pgm.IsTgidEnabled(0), cs_pgm.IsTgidEnabled(1), + cs_pgm.IsTgidEnabled(2)}; + info.cs_info.shared_memory_size = cs_pgm.SharedMemSize(); break; } default: @@ -110,66 +162,101 @@ Shader::Info MakeShaderInfo(Shader::Stage stage, std::span user_d PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, AmdGpu::Liverpool* liverpool_) - : instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, inst_pool{8192}, - block_pool{512} { - pipeline_cache = instance.GetDevice().createPipelineCacheUnique({}); + : instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, + desc_heap{instance, scheduler.GetMasterSemaphore(), DescriptorHeapSizes} { + const auto& vk12_props = instance.GetVk12Properties(); profile = Shader::Profile{ - .supported_spirv = 0x00010600U, + .supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U, .subgroup_size = instance.SubgroupSize(), + .support_fp32_denorm_preserve = bool(vk12_props.shaderDenormPreserveFloat32), + .support_fp32_denorm_flush = bool(vk12_props.shaderDenormFlushToZeroFloat32), .support_explicit_workgroup_layout = true, }; + auto [cache_result, cache] = instance.GetDevice().createPipelineCacheUnique({}); + ASSERT_MSG(cache_result == vk::Result::eSuccess, "Failed to create pipeline cache: {}", + vk::to_string(cache_result)); + pipeline_cache = std::move(cache); } +PipelineCache::~PipelineCache() = default; + const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() { + const auto& regs = liverpool->regs; // Tessellation is unsupported so skip the draw to avoid locking up the driver. - if (liverpool->regs.primitive_type == Liverpool::PrimitiveType::PatchPrimitive) { + if (regs.primitive_type == AmdGpu::PrimitiveType::PatchPrimitive) { + return nullptr; + } + // There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an + // actual draw hence can skip pipeline creation. + if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) { + LOG_TRACE(Render_Vulkan, "FCE pass skipped"); + return nullptr; + } + if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) { + // TODO: check for a valid MRT1 to promote the draw to the resolve pass. + LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped"); + return nullptr; + } + if (regs.primitive_type == AmdGpu::PrimitiveType::None) { + LOG_TRACE(Render_Vulkan, "Primitive type 'None' skipped"); + return nullptr; + } + if (!RefreshGraphicsKey()) { return nullptr; } - RefreshGraphicsKey(); const auto [it, is_new] = graphics_pipelines.try_emplace(graphics_key); if (is_new) { - it.value() = CreateGraphicsPipeline(); + it.value() = graphics_pipeline_pool.Create(instance, scheduler, desc_heap, graphics_key, + *pipeline_cache, infos, modules); } - const GraphicsPipeline* pipeline = it->second.get(); - return pipeline; + return it->second; } const ComputePipeline* PipelineCache::GetComputePipeline() { - const auto& cs_pgm = liverpool->regs.cs_program; - ASSERT(cs_pgm.Address() != nullptr); - const auto* bininfo = Liverpool::GetBinaryInfo(cs_pgm); - compute_key = bininfo->shader_hash; + if (!RefreshComputeKey()) { + return nullptr; + } const auto [it, is_new] = compute_pipelines.try_emplace(compute_key); if (is_new) { - it.value() = CreateComputePipeline(); + it.value() = compute_pipeline_pool.Create(instance, scheduler, desc_heap, *pipeline_cache, + compute_key, *infos[0], modules[0]); } - const ComputePipeline* pipeline = it->second.get(); - return pipeline; + return it->second; } -void PipelineCache::RefreshGraphicsKey() { +bool PipelineCache::RefreshGraphicsKey() { + std::memset(&graphics_key, 0, sizeof(GraphicsPipelineKey)); + auto& regs = liverpool->regs; auto& key = graphics_key; - key.depth = regs.depth_control; - key.depth.depth_write_enable.Assign(regs.depth_control.depth_write_enable.Value() && - !regs.depth_render_control.depth_clear_enable); - key.depth_bounds_min = regs.depth_bounds_min; - key.depth_bounds_max = regs.depth_bounds_max; - key.depth_bias_enable = regs.polygon_control.enable_polygon_offset_back || - regs.polygon_control.enable_polygon_offset_front || - regs.polygon_control.enable_polygon_offset_para; - if (regs.polygon_control.enable_polygon_offset_front) { - key.depth_bias_const_factor = regs.poly_offset.front_offset; - key.depth_bias_slope_factor = regs.poly_offset.front_scale; + key.depth_stencil = regs.depth_control; + key.depth_stencil.depth_write_enable.Assign(regs.depth_control.depth_write_enable.Value() && + !regs.depth_render_control.depth_clear_enable); + key.depth_bias_enable = regs.polygon_control.NeedsBias(); + + const auto& db = regs.depth_buffer; + const auto ds_format = instance.GetSupportedFormat( + LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format), + vk::FormatFeatureFlagBits2::eDepthStencilAttachment); + if (db.z_info.format != AmdGpu::Liverpool::DepthBuffer::ZFormat::Invalid) { + key.depth_format = ds_format; } else { - key.depth_bias_const_factor = regs.poly_offset.back_offset; - key.depth_bias_slope_factor = regs.poly_offset.back_scale; + key.depth_format = vk::Format::eUndefined; + } + if (regs.depth_control.depth_enable) { + key.depth_stencil.depth_enable.Assign(key.depth_format != vk::Format::eUndefined); } - key.depth_bias_clamp = regs.poly_offset.depth_bias; key.stencil = regs.stencil_control; - key.stencil_ref_front = regs.stencil_ref_front; - key.stencil_ref_back = regs.stencil_ref_back; + + if (db.stencil_info.format != AmdGpu::Liverpool::DepthBuffer::StencilFormat::Invalid) { + key.stencil_format = key.depth_format; + } else { + key.stencil_format = vk::Format::eUndefined; + } + if (key.depth_stencil.stencil_enable) { + key.depth_stencil.stencil_enable.Assign(key.stencil_format != vk::Format::eUndefined); + } key.prim_type = regs.primitive_type; key.enable_primitive_restart = regs.enable_primitive_restart & 1; key.primitive_restart_index = regs.primitive_restart_index; @@ -179,215 +266,214 @@ void PipelineCache::RefreshGraphicsKey() { key.front_face = regs.polygon_control.front_face; key.num_samples = regs.aa_config.NumSamples(); - const auto& db = regs.depth_buffer; - const auto ds_format = LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format); - - if (db.z_info.format != AmdGpu::Liverpool::DepthBuffer::ZFormat::Invalid) { - key.depth_format = ds_format; - } else { - key.depth_format = vk::Format::eUndefined; - } - if (key.depth.depth_enable) { - key.depth.depth_enable.Assign(key.depth_format != vk::Format::eUndefined); - } - - if (db.stencil_info.format != AmdGpu::Liverpool::DepthBuffer::StencilFormat::Invalid) { - key.stencil_format = key.depth_format; - } else { - key.stencil_format = vk::Format::eUndefined; - } - if (key.depth.stencil_enable) { - key.depth.stencil_enable.Assign(key.stencil_format != vk::Format::eUndefined); - } - - const auto skip_cb_binding = + const bool skip_cb_binding = regs.color_control.mode == AmdGpu::Liverpool::ColorControl::OperationMode::Disable; // `RenderingInfo` is assumed to be initialized with a contiguous array of valid color - // attachments. This might be not a case as HW color buffers can be bound in an arbitrary order. - // We need to do some arrays compaction at this stage + // attachments. This might be not a case as HW color buffers can be bound in an arbitrary + // order. We need to do some arrays compaction at this stage key.color_formats.fill(vk::Format::eUndefined); + key.color_num_formats.fill(AmdGpu::NumberFormat::Unorm); key.blend_controls.fill({}); key.write_masks.fill({}); - int remapped_cb{}; - for (auto cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) { + key.mrt_swizzles.fill(Liverpool::ColorBuffer::SwapMode::Standard); + key.vertex_buffer_formats.fill(vk::Format::eUndefined); + + // First pass of bindings check to idenitfy formats and swizzles and pass them to rhe shader + // recompiler. + for (auto cb = 0u, remapped_cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) { auto const& col_buf = regs.color_buffers[cb]; if (skip_cb_binding || !col_buf || !regs.color_target_mask.GetMask(cb)) { continue; } const auto base_format = LiverpoolToVK::SurfaceFormat(col_buf.info.format, col_buf.NumFormat()); - const auto is_vo_surface = renderer->IsVideoOutSurface(col_buf); + const bool is_vo_surface = renderer->IsVideoOutSurface(col_buf); key.color_formats[remapped_cb] = LiverpoolToVK::AdjustColorBufferFormat( base_format, col_buf.info.comp_swap.Value(), false /*is_vo_surface*/); - key.blend_controls[remapped_cb] = regs.blend_control[cb]; - key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable && - !col_buf.info.blend_bypass); - key.write_masks[remapped_cb] = vk::ColorComponentFlags{regs.color_target_mask.GetMask(cb)}; - key.cb_shader_mask = regs.color_shader_mask; + 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(); + } ++remapped_cb; } - for (u32 i = 0; i < MaxShaderStages; i++) { - if (!regs.stage_enable.IsStageEnabled(i)) { - key.stage_hashes[i] = 0; - continue; + Shader::Backend::Bindings binding{}; + const auto& TryBindStageRemap = [&](Shader::Stage stage_in, Shader::Stage stage_out) -> bool { + const auto stage_in_idx = static_cast(stage_in); + const auto stage_out_idx = static_cast(stage_out); + if (!regs.stage_enable.IsStageEnabled(stage_in_idx)) { + key.stage_hashes[stage_out_idx] = 0; + infos[stage_out_idx] = nullptr; + return false; } - auto* pgm = regs.ProgramForStage(i); + + const auto* pgm = regs.ProgramForStage(stage_in_idx); if (!pgm || !pgm->Address()) { - key.stage_hashes[i] = 0; - continue; + key.stage_hashes[stage_out_idx] = 0; + infos[stage_out_idx] = nullptr; + return false; } + const auto* bininfo = Liverpool::GetBinaryInfo(*pgm); if (!bininfo->Valid()) { - key.stage_hashes[i] = 0; - continue; + LOG_WARNING(Render_Vulkan, "Invalid binary info structure!"); + key.stage_hashes[stage_out_idx] = 0; + infos[stage_out_idx] = nullptr; + return false; } - key.stage_hashes[i] = bininfo->shader_hash; + + auto params = Liverpool::GetParams(*pgm); + std::tie(infos[stage_out_idx], modules[stage_out_idx], key.stage_hashes[stage_out_idx]) = + GetProgram(stage_in, params, binding); + return true; + }; + + const auto& TryBindStage = [&](Shader::Stage stage) { return TryBindStageRemap(stage, stage); }; + + const auto& IsGsFeaturesSupported = [&]() -> bool { + // These checks are temporary until all functionality is implemented. + return !regs.vgt_gs_mode.onchip && !regs.vgt_strmout_config.raw; + }; + + TryBindStage(Shader::Stage::Fragment); + + const auto* fs_info = infos[static_cast(Shader::Stage::Fragment)]; + key.mrt_mask = fs_info ? fs_info->mrt_mask : 0u; + + switch (regs.stage_enable.raw) { + case Liverpool::ShaderStageEnable::VgtStages::EsGs: { + if (!instance.IsGeometryStageSupported() || !IsGsFeaturesSupported()) { + break; + } + if (!TryBindStageRemap(Shader::Stage::Export, Shader::Stage::Vertex)) { + return false; + } + if (!TryBindStage(Shader::Stage::Geometry)) { + return false; + } + break; + } + default: { + TryBindStage(Shader::Stage::Vertex); + infos[static_cast(Shader::Stage::Geometry)] = nullptr; + break; } -} - -std::unique_ptr PipelineCache::CreateGraphicsPipeline() { - const auto& regs = liverpool->regs; - - // There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an - // actual draw hence can skip pipeline creation. - if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) { - LOG_TRACE(Render_Vulkan, "FCE pass skipped"); - return {}; } - if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) { - // TODO: check for a valid MRT1 to promote the draw to the resolve pass. - LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped"); - return {}; - } - - u32 binding{}; - for (u32 i = 0; i < MaxShaderStages; i++) { - if (!graphics_key.stage_hashes[i]) { - programs[i] = nullptr; - continue; - } - auto* pgm = regs.ProgramForStage(i); - const auto code = pgm->Code(); - - // Dump shader code if requested. - const auto stage = Shader::Stage{i}; - const u64 hash = graphics_key.stage_hashes[i]; - if (Config::dumpShaders()) { - DumpShader(code, hash, stage, "bin"); - } - - block_pool.ReleaseContents(); - inst_pool.ReleaseContents(); - - if (stage != Shader::Stage::Fragment && stage != Shader::Stage::Vertex) { - LOG_ERROR(Render_Vulkan, "Unsupported shader stage {}. PL creation skipped.", stage); - return {}; - } - - const u64 lookup_hash = HashCombine(hash, binding); - auto it = program_cache.find(lookup_hash); - if (it != program_cache.end()) { - const Program* program = it.value().get(); - ASSERT(program->pgm.info.stage == stage); - programs[i] = program; - binding = program->end_binding; - continue; - } - - // Recompile shader to IR. - try { - auto program = std::make_unique(); - block_pool.ReleaseContents(); - inst_pool.ReleaseContents(); - - LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x}", stage, hash); - Shader::Info info = MakeShaderInfo(stage, pgm->user_data, regs); - info.pgm_base = pgm->Address(); - info.pgm_hash = hash; - program->pgm = - Shader::TranslateProgram(inst_pool, block_pool, code, std::move(info), profile); - - // Compile IR to SPIR-V - program->spv = Shader::Backend::SPIRV::EmitSPIRV(profile, program->pgm, binding); - if (Config::dumpShaders()) { - DumpShader(program->spv, hash, stage, "spv"); + const auto* vs_info = infos[static_cast(Shader::Stage::Vertex)]; + if (vs_info && !instance.IsVertexInputDynamicState()) { + u32 vertex_binding = 0; + for (const auto& input : vs_info->vs_inputs) { + if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || + input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { + continue; } - - // Compile module and set name to hash in renderdoc - program->end_binding = binding; - program->module = CompileSPV(program->spv, instance.GetDevice()); - const auto name = fmt::format("{}_{:#x}", stage, hash); - Vulkan::SetObjectName(instance.GetDevice(), program->module, name); - - // Cache program - const auto [it, _] = program_cache.emplace(lookup_hash, std::move(program)); - programs[i] = it.value().get(); - } catch (const Shader::Exception& e) { - UNREACHABLE_MSG("{}", e.what()); + const auto& buffer = + vs_info->ReadUd(input.sgpr_base, input.dword_offset); + if (buffer.GetSize() == 0) { + continue; + } + ASSERT(vertex_binding < MaxVertexBufferCount); + key.vertex_buffer_formats[vertex_binding++] = + Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()); } } - return std::make_unique(instance, scheduler, graphics_key, *pipeline_cache, - programs); + // Second pass to fill remain CB pipeline key data + for (auto cb = 0u, remapped_cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) { + auto const& col_buf = regs.color_buffers[cb]; + if (skip_cb_binding || !col_buf || !regs.color_target_mask.GetMask(cb) || + (key.mrt_mask & (1u << cb)) == 0) { + key.color_formats[cb] = vk::Format::eUndefined; + key.mrt_swizzles[cb] = Liverpool::ColorBuffer::SwapMode::Standard; + continue; + } + + key.blend_controls[remapped_cb] = regs.blend_control[cb]; + key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable && + !col_buf.info.blend_bypass); + key.write_masks[remapped_cb] = vk::ColorComponentFlags{regs.color_target_mask.GetMask(cb)}; + key.cb_shader_mask.SetMask(remapped_cb, regs.color_shader_mask.GetMask(cb)); + + ++remapped_cb; + } + return true; } -std::unique_ptr PipelineCache::CreateComputePipeline() { - const auto& cs_pgm = liverpool->regs.cs_program; - const auto code = cs_pgm.Code(); +bool PipelineCache::RefreshComputeKey() { + Shader::Backend::Bindings binding{}; + const auto* cs_pgm = &liverpool->regs.cs_program; + const auto cs_params = Liverpool::GetParams(*cs_pgm); + std::tie(infos[0], modules[0], compute_key) = + GetProgram(Shader::Stage::Compute, cs_params, binding); + return true; +} - // Dump shader code if requested. - if (Config::dumpShaders()) { - DumpShader(code, compute_key, Shader::Stage::Compute, "bin"); +vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, + const Shader::RuntimeInfo& runtime_info, + std::span code, size_t perm_idx, + Shader::Backend::Bindings& binding) { + LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x} {}", info.stage, info.pgm_hash, + perm_idx != 0 ? "(permutation)" : ""); + DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); + + const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); + const auto spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); + DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); + + const auto module = CompileSPV(spv, instance.GetDevice()); + const auto name = fmt::format("{}_{:#x}_{}", info.stage, info.pgm_hash, perm_idx); + Vulkan::SetObjectName(instance.GetDevice(), module, name); + return module; +} + +std::tuple PipelineCache::GetProgram( + Shader::Stage stage, Shader::ShaderParams params, Shader::Backend::Bindings& binding) { + const auto runtime_info = BuildRuntimeInfo(stage); + auto [it_pgm, new_program] = program_cache.try_emplace(params.hash); + if (new_program) { + Program* program = program_pool.Create(stage, params); + auto start = binding; + const auto module = CompileModule(program->info, runtime_info, params.code, 0, binding); + const auto spec = Shader::StageSpecialization(program->info, runtime_info, start); + program->AddPermut(module, std::move(spec)); + it_pgm.value() = program; + return std::make_tuple(&program->info, module, HashCombine(params.hash, 0)); } - block_pool.ReleaseContents(); - inst_pool.ReleaseContents(); + Program* program = it_pgm->second; + const auto& info = program->info; + const auto spec = Shader::StageSpecialization(info, runtime_info, binding); + size_t perm_idx = program->modules.size(); + vk::ShaderModule module{}; - // Recompile shader to IR. - try { - auto program = std::make_unique(); - LOG_INFO(Render_Vulkan, "Compiling cs shader {:#x}", compute_key); - Shader::Info info = - MakeShaderInfo(Shader::Stage::Compute, cs_pgm.user_data, liverpool->regs); - info.pgm_base = cs_pgm.Address(); - info.pgm_hash = compute_key; - program->pgm = - Shader::TranslateProgram(inst_pool, block_pool, code, std::move(info), profile); - - // Compile IR to SPIR-V - u32 binding{}; - program->spv = Shader::Backend::SPIRV::EmitSPIRV(profile, program->pgm, binding); - if (Config::dumpShaders()) { - DumpShader(program->spv, compute_key, Shader::Stage::Compute, "spv"); - } - - // Compile module and set name to hash in renderdoc - program->module = CompileSPV(program->spv, instance.GetDevice()); - const auto name = fmt::format("cs_{:#x}", compute_key); - Vulkan::SetObjectName(instance.GetDevice(), program->module, name); - - // Cache program - const auto [it, _] = program_cache.emplace(compute_key, std::move(program)); - return std::make_unique(instance, scheduler, *pipeline_cache, compute_key, - it.value().get()); - } catch (const Shader::Exception& e) { - UNREACHABLE_MSG("{}", e.what()); - return nullptr; + const auto it = std::ranges::find(program->modules, spec, &Program::Module::spec); + if (it == program->modules.end()) { + auto new_info = Shader::Info(stage, params); + module = CompileModule(new_info, runtime_info, params.code, perm_idx, binding); + program->AddPermut(module, std::move(spec)); + } else { + info.AddBindings(binding); + module = it->module; + perm_idx = std::distance(program->modules.begin(), it); } + return std::make_tuple(&info, module, HashCombine(params.hash, perm_idx)); } void PipelineCache::DumpShader(std::span code, u64 hash, Shader::Stage stage, - std::string_view ext) { + size_t perm_idx, std::string_view ext) { + if (!Config::dumpShaders()) { + return; + } + using namespace Common::FS; const auto dump_dir = GetUserPath(PathType::ShaderDir) / "dumps"; if (!std::filesystem::exists(dump_dir)) { std::filesystem::create_directories(dump_dir); } - const auto filename = fmt::format("{}_{:#018x}.{}", stage, hash, ext); + const auto filename = fmt::format("{}_{:#018x}_{}.{}", stage, hash, perm_idx, ext); const auto file = IOFile{dump_dir / filename, FileAccessMode::Write}; file.WriteSpan(code); } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 8f3b806cb..7e44bbf09 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -4,11 +4,12 @@ #pragma once #include -#include "shader_recompiler/ir/basic_block.h" -#include "shader_recompiler/ir/program.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/recompiler.h" +#include "shader_recompiler/specialization.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" +#include "video_core/renderer_vulkan/vk_resource_pool.h" namespace Shader { struct Info; @@ -18,6 +19,23 @@ namespace Vulkan { class Instance; class Scheduler; +class ShaderCache; + +struct Program { + struct Module { + vk::ShaderModule module; + Shader::StageSpecialization spec; + }; + + Shader::Info info; + boost::container::small_vector modules; + + explicit Program(Shader::Stage stage, Shader::ShaderParams params) : info{stage, params} {} + + void AddPermut(vk::ShaderModule module, const Shader::StageSpecialization&& spec) { + modules.emplace_back(module, std::move(spec)); + } +}; class PipelineCache { static constexpr size_t MaxShaderStages = 5; @@ -25,34 +43,45 @@ class PipelineCache { public: explicit PipelineCache(const Instance& instance, Scheduler& scheduler, AmdGpu::Liverpool* liverpool); - ~PipelineCache() = default; + ~PipelineCache(); const GraphicsPipeline* GetGraphicsPipeline(); const ComputePipeline* GetComputePipeline(); -private: - void RefreshGraphicsKey(); - void DumpShader(std::span code, u64 hash, Shader::Stage stage, std::string_view ext); + std::tuple GetProgram( + Shader::Stage stage, Shader::ShaderParams params, Shader::Backend::Bindings& binding); - std::unique_ptr CreateGraphicsPipeline(); - std::unique_ptr CreateComputePipeline(); +private: + bool RefreshGraphicsKey(); + bool RefreshComputeKey(); + + void DumpShader(std::span code, u64 hash, Shader::Stage stage, size_t perm_idx, + std::string_view ext); + vk::ShaderModule CompileModule(Shader::Info& info, const Shader::RuntimeInfo& runtime_info, + std::span code, size_t perm_idx, + Shader::Backend::Bindings& binding); + Shader::RuntimeInfo BuildRuntimeInfo(Shader::Stage stage); private: const Instance& instance; Scheduler& scheduler; AmdGpu::Liverpool* liverpool; + DescriptorHeap desc_heap; vk::UniquePipelineCache pipeline_cache; vk::UniquePipelineLayout pipeline_layout; - tsl::robin_map> program_cache; - tsl::robin_map> compute_pipelines; - tsl::robin_map> graphics_pipelines; - std::array programs{}; Shader::Profile profile{}; + Shader::Pools pools; + tsl::robin_map program_cache; + Common::ObjectPool program_pool; + Common::ObjectPool graphics_pipeline_pool; + Common::ObjectPool compute_pipeline_pool; + tsl::robin_map compute_pipelines; + tsl::robin_map graphics_pipelines; + std::array infos{}; + std::array modules{}; GraphicsPipelineKey graphics_key{}; u64 compute_key{}; - Common::ObjectPool inst_pool; - Common::ObjectPool block_pool; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_common.cpp b/src/video_core/renderer_vulkan/vk_pipeline_common.cpp new file mode 100644 index 000000000..61e564150 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_pipeline_common.cpp @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "shader_recompiler/info.h" +#include "video_core/renderer_vulkan/vk_instance.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" + +namespace Vulkan { + +boost::container::static_vector Pipeline::image_infos; + +Pipeline::Pipeline(const Instance& instance_, Scheduler& scheduler_, DescriptorHeap& desc_heap_, + vk::PipelineCache pipeline_cache) + : instance{instance_}, scheduler{scheduler_}, desc_heap{desc_heap_} {} + +Pipeline::~Pipeline() = default; + +void Pipeline::BindTextures(VideoCore::TextureCache& texture_cache, const Shader::Info& stage, + Shader::Backend::Bindings& binding, + DescriptorWrites& set_writes) const { + + using ImageBindingInfo = std::tuple; + boost::container::static_vector image_bindings; + + for (const auto& image_desc : stage.images) { + const auto tsharp = image_desc.GetSharp(stage); + if (tsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) { + VideoCore::ImageInfo image_info{tsharp, image_desc}; + const auto image_id = texture_cache.FindImage(image_info); + auto& image = texture_cache.GetImage(image_id); + image.flags |= VideoCore::ImageFlagBits::Bound; + image_bindings.emplace_back(image_id, tsharp, image_desc); + } else { + image_bindings.emplace_back(VideoCore::ImageId{}, tsharp, image_desc); + } + + if (texture_cache.IsMeta(tsharp.Address())) { + LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (texture)"); + } + } + + // Second pass to re-bind images that were updated after binding + for (auto [image_id, tsharp, desc] : image_bindings) { + if (!image_id) { + if (instance.IsNullDescriptorSupported()) { + image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); + } else { + auto& null_image = texture_cache.GetImageView(VideoCore::NULL_IMAGE_VIEW_ID); + image_infos.emplace_back(VK_NULL_HANDLE, *null_image.image_view, + vk::ImageLayout::eGeneral); + } + } else { + auto& image = texture_cache.GetImage(image_id); + if (True(image.flags & VideoCore::ImageFlagBits::NeedsRebind)) { + image_id = texture_cache.FindImage(image.info); + } + VideoCore::ImageViewInfo view_info{tsharp, desc}; + auto& image_view = texture_cache.FindTexture(image_id, view_info); + image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, + texture_cache.GetImage(image_id).last_state.layout); + image.flags &= + ~(VideoCore::ImageFlagBits::NeedsRebind | VideoCore::ImageFlagBits::Bound); + } + + set_writes.push_back({ + .dstSet = VK_NULL_HANDLE, + .dstBinding = binding.unified++, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = desc.is_storage ? vk::DescriptorType::eStorageImage + : vk::DescriptorType::eSampledImage, + .pImageInfo = &image_infos.back(), + }); + } +} + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_common.h b/src/video_core/renderer_vulkan/vk_pipeline_common.h new file mode 100644 index 000000000..ab99e7b33 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_pipeline_common.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "shader_recompiler/backend/bindings.h" +#include "shader_recompiler/info.h" +#include "video_core/renderer_vulkan/vk_common.h" + +namespace VideoCore { +class BufferCache; +class TextureCache; +} // namespace VideoCore + +namespace Vulkan { + +class Instance; +class Scheduler; +class DescriptorHeap; + +class Pipeline { +public: + Pipeline(const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap, + vk::PipelineCache pipeline_cache); + virtual ~Pipeline(); + + vk::Pipeline Handle() const noexcept { + return *pipeline; + } + + vk::PipelineLayout GetLayout() const noexcept { + return *pipeline_layout; + } + + using DescriptorWrites = boost::container::small_vector; + void BindTextures(VideoCore::TextureCache& texture_cache, const Shader::Info& stage, + Shader::Backend::Bindings& binding, DescriptorWrites& set_writes) const; + +protected: + const Instance& instance; + Scheduler& scheduler; + DescriptorHeap& desc_heap; + vk::UniquePipeline pipeline; + vk::UniquePipelineLayout pipeline_layout; + vk::UniqueDescriptorSetLayout desc_layout; + static boost::container::static_vector image_infos; +}; + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index c73a8139d..0eb7e0759 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -17,13 +17,23 @@ #include "common/assert.h" #include "common/config.h" #include "common/logging/log.h" +#include "common/path_util.h" #include "sdl_window.h" #include "video_core/renderer_vulkan/vk_platform.h" +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL +static vk::DynamicLoader dl; +#else +extern "C" { +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, + const char* pName); +} +#endif + namespace Vulkan { static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; -static const char* const API_DUMP_LAYER_NAME = "VK_LAYER_LUNARG_api_dump"; +static const char* const CRASH_DIAGNOSTIC_LAYER_NAME = "VK_LAYER_LUNARG_crash_diagnostic"; static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback( VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, @@ -32,7 +42,8 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback( switch (static_cast(callback_data->messageIdNumber)) { case 0x609a13b: // Vertex attribute at location not consumed by shader case 0xc81ad50e: - case 0x92d66fc1: // `pMultisampleState is NULL` for depth only passes (confirmed VL error) + case 0xb7c39078: + case 0x32868fde: // vkCreateBufferView(): pCreateInfo->range does not equal VK_WHOLE_SIZE return VK_FALSE; default: break; @@ -123,9 +134,10 @@ vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& e std::vector GetInstanceExtensions(Frontend::WindowSystemType window_type, bool enable_debug_utils) { - const auto properties = vk::enumerateInstanceExtensionProperties(); - if (properties.empty()) { - LOG_ERROR(Render_Vulkan, "Failed to query extension properties"); + const auto [properties_result, properties] = vk::enumerateInstanceExtensionProperties(); + if (properties_result != vk::Result::eSuccess || properties.empty()) { + LOG_ERROR(Render_Vulkan, "Failed to query extension properties: {}", + vk::to_string(properties_result)); return {}; } @@ -186,18 +198,22 @@ std::vector GetInstanceExtensions(Frontend::WindowSystemType window return extensions; } -vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemType window_type, - bool enable_validation, bool dump_command_buffers) { +vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool enable_validation, + bool enable_crash_diagnostic) { LOG_INFO(Render_Vulkan, "Creating vulkan instance"); +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL auto vkGetInstanceProcAddr = dl.getProcAddress("vkGetInstanceProcAddr"); +#endif VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); - const u32 available_version = VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion - ? vk::enumerateInstanceVersion() - : VK_API_VERSION_1_0; - + const auto [available_version_result, available_version] = + VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion + ? vk::enumerateInstanceVersion() + : vk::ResultValue(vk::Result::eSuccess, VK_API_VERSION_1_0); + ASSERT_MSG(available_version_result == vk::Result::eSuccess, + "Failed to query Vulkan API version: {}", vk::to_string(available_version_result)); ASSERT_MSG(available_version >= TargetVulkanApiVersion, "Vulkan {}.{} is required, but only {}.{} is supported by instance!", VK_VERSION_MAJOR(TargetVulkanApiVersion), VK_VERSION_MINOR(TargetVulkanApiVersion), @@ -216,12 +232,27 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT u32 num_layers = 0; std::array layers; + vk::Bool32 enable_force_barriers = vk::False; + const char* log_path{}; + +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL if (enable_validation) { layers[num_layers++] = VALIDATION_LAYER_NAME; } - if (dump_command_buffers) { - layers[num_layers++] = API_DUMP_LAYER_NAME; + + if (enable_crash_diagnostic) { + layers[num_layers++] = CRASH_DIAGNOSTIC_LAYER_NAME; + static const auto crash_diagnostic_path = + Common::FS::GetUserPathString(Common::FS::PathType::LogDir); + log_path = crash_diagnostic_path.c_str(); + enable_force_barriers = vk::True; } +#else + if (enable_validation || enable_crash_diagnostic) { + LOG_WARNING(Render_Vulkan, + "Skipping loading Vulkan layers as dynamic loading is not enabled."); + } +#endif vk::Bool32 enable_sync = enable_validation && Config::vkValidationSyncEnabled() ? vk::True : vk::False; @@ -240,7 +271,7 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT }, vk::LayerSettingEXT{ .pLayerName = VALIDATION_LAYER_NAME, - .pSettingName = "sync_queue_submit", + .pSettingName = "syncval_submit_time_validation", .type = vk::LayerSettingTypeEXT::eBool32, .valueCount = 1, .pValues = &enable_sync, @@ -280,6 +311,20 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT .valueCount = 1, .pValues = &enable_gpuav, }, + vk::LayerSettingEXT{ + .pLayerName = "lunarg_crash_diagnostic", + .pSettingName = "output_path", + .type = vk::LayerSettingTypeEXT::eString, + .valueCount = 1, + .pValues = &log_path, + }, + vk::LayerSettingEXT{ + .pLayerName = "lunarg_crash_diagnostic", + .pSettingName = "sync_after_commands", + .type = vk::LayerSettingTypeEXT::eBool32, + .valueCount = 1, + .pValues = &enable_force_barriers, + }, }; vk::StructureChain instance_ci_chain = { @@ -299,11 +344,13 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT }, }; - auto instance = vk::createInstanceUnique(instance_ci_chain.get()); + auto [instance_result, instance] = vk::createInstanceUnique(instance_ci_chain.get()); + ASSERT_MSG(instance_result == vk::Result::eSuccess, "Failed to create instance: {}", + vk::to_string(instance_result)); VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance); - return instance; + return std::move(instance); } vk::UniqueDebugUtilsMessengerEXT CreateDebugCallback(vk::Instance instance) { @@ -317,7 +364,10 @@ vk::UniqueDebugUtilsMessengerEXT CreateDebugCallback(vk::Instance instance) { vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, .pfnUserCallback = DebugUtilsCallback, }; - return instance.createDebugUtilsMessengerEXTUnique(msg_ci); + auto [messenger_result, messenger] = instance.createDebugUtilsMessengerEXTUnique(msg_ci); + ASSERT_MSG(messenger_result == vk::Result::eSuccess, "Failed to create debug callback: {}", + vk::to_string(messenger_result)); + return std::move(messenger); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_platform.h b/src/video_core/renderer_vulkan/vk_platform.h index 582de3831..6b425b6d8 100644 --- a/src/video_core/renderer_vulkan/vk_platform.h +++ b/src/video_core/renderer_vulkan/vk_platform.h @@ -7,6 +7,7 @@ #include #include +#include "common/logging/log.h" #include "common/types.h" #include "video_core/renderer_vulkan/vk_common.h" @@ -21,8 +22,8 @@ constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_2; vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& emu_window); -vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemType window_type, - bool enable_validation, bool dump_command_buffers); +vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool enable_validation, + bool enable_crash_diagnostic); vk::UniqueDebugUtilsMessengerEXT CreateDebugCallback(vk::Instance instance); @@ -36,7 +37,10 @@ void SetObjectName(vk::Device device, const HandleType& handle, std::string_view .objectHandle = reinterpret_cast(static_cast(handle)), .pObjectName = debug_name.data(), }; - device.setDebugUtilsObjectNameEXT(name_info); + auto result = device.setDebugUtilsObjectNameEXT(name_info); + if (result != vk::Result::eSuccess) { + LOG_DEBUG(Render_Vulkan, "Could not set object debug name: {}", vk::to_string(result)); + } } template diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 6cd803934..b3c42fcb6 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -17,18 +17,30 @@ namespace Vulkan { Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_, AmdGpu::Liverpool* liverpool_) : instance{instance_}, scheduler{scheduler_}, page_manager{this}, - buffer_cache{instance, scheduler, liverpool_, page_manager}, + buffer_cache{instance, scheduler, liverpool_, texture_cache, page_manager}, texture_cache{instance, scheduler, buffer_cache, page_manager}, liverpool{liverpool_}, memory{Core::Memory::Instance()}, pipeline_cache{instance, scheduler, liverpool} { if (!Config::nullGpu()) { liverpool->BindRasterizer(this); } memory->SetRasterizer(this); - wfi_event = instance.GetDevice().createEventUnique({}); } Rasterizer::~Rasterizer() = default; +void Rasterizer::CpSync() { + scheduler.EndRendering(); + auto cmdbuf = scheduler.CommandBuffer(); + + const vk::MemoryBarrier ib_barrier{ + .srcAccessMask = vk::AccessFlagBits::eShaderWrite, + .dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead, + }; + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, + vk::PipelineStageFlagBits::eDrawIndirect, + vk::DependencyFlagBits::eByRegion, ib_barrier, {}, {}); +} + void Rasterizer::Draw(bool is_indexed, u32 index_offset) { RENDERER_TRACE; @@ -49,16 +61,58 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { buffer_cache.BindVertexBuffers(vs_info); const u32 num_indices = buffer_cache.BindIndexBuffer(is_indexed, index_offset); - BeginRendering(); + BeginRendering(*pipeline); UpdateDynamicState(*pipeline); + const auto [vertex_offset, instance_offset] = vs_info.GetDrawOffsets(); + if (is_indexed) { - cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, 0, 0); + cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, s32(vertex_offset), + instance_offset); } else { - const u32 num_vertices = regs.primitive_type == AmdGpu::Liverpool::PrimitiveType::RectList - ? 4 - : regs.num_indices; - cmdbuf.draw(num_vertices, regs.num_instances.NumInstances(), 0, 0); + const u32 num_vertices = + regs.primitive_type == AmdGpu::PrimitiveType::RectList ? 4 : regs.num_indices; + cmdbuf.draw(num_vertices, regs.num_instances.NumInstances(), vertex_offset, + instance_offset); + } +} + +void Rasterizer::DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size) { + RENDERER_TRACE; + + const auto cmdbuf = scheduler.CommandBuffer(); + const auto& regs = liverpool->regs; + const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline(); + if (!pipeline) { + return; + } + + ASSERT_MSG(regs.primitive_type != AmdGpu::PrimitiveType::RectList, + "Unsupported primitive type for indirect draw"); + + try { + pipeline->BindResources(regs, buffer_cache, texture_cache); + } catch (...) { + UNREACHABLE(); + } + + const auto& vs_info = pipeline->GetStage(Shader::Stage::Vertex); + buffer_cache.BindVertexBuffers(vs_info); + const u32 num_indices = buffer_cache.BindIndexBuffer(is_indexed, 0); + + const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true); + const auto total_offset = base + offset; + + BeginRendering(*pipeline); + UpdateDynamicState(*pipeline); + + // We can safely ignore both SGPR UD indices and results of fetch shader parsing, as vertex and + // instance offsets will be automatically applied by Vulkan from indirect args buffer. + + if (is_indexed) { + cmdbuf.drawIndexedIndirect(buffer->Handle(), total_offset, 1, 0); + } else { + cmdbuf.drawIndirect(buffer->Handle(), total_offset, 1, 0); } } @@ -86,6 +140,32 @@ void Rasterizer::DispatchDirect() { cmdbuf.dispatch(cs_program.dim_x, cs_program.dim_y, cs_program.dim_z); } +void Rasterizer::DispatchIndirect(VAddr address, u32 offset, u32 size) { + RENDERER_TRACE; + + const auto cmdbuf = scheduler.CommandBuffer(); + const auto& cs_program = liverpool->regs.cs_program; + const ComputePipeline* pipeline = pipeline_cache.GetComputePipeline(); + if (!pipeline) { + return; + } + + try { + const auto has_resources = pipeline->BindResources(buffer_cache, texture_cache); + if (!has_resources) { + return; + } + } catch (...) { + UNREACHABLE(); + } + + scheduler.EndRendering(); + cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle()); + const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true); + const auto total_offset = base + offset; + cmdbuf.dispatchIndirect(buffer->Handle(), total_offset); +} + u64 Rasterizer::Flush() { const u64 current_tick = scheduler.CurrentTick(); SubmitInfo info{}; @@ -93,10 +173,18 @@ u64 Rasterizer::Flush() { return current_tick; } -void Rasterizer::BeginRendering() { +void Rasterizer::Finish() { + scheduler.Finish(); +} + +void Rasterizer::BeginRendering(const GraphicsPipeline& pipeline) { const auto& regs = liverpool->regs; RenderState state; + if (regs.color_control.degamma_enable) { + LOG_WARNING(Render_Vulkan, "Color buffers require gamma correction"); + } + for (auto col_buf_id = 0u; col_buf_id < Liverpool::NumColorBuffers; ++col_buf_id) { const auto& col_buf = regs.color_buffers[col_buf_id]; if (!col_buf) { @@ -109,6 +197,13 @@ void Rasterizer::BeginRendering() { continue; } + // Skip stale color buffers if shader doesn't output to them. Otherwise it will perform + // an unnecessary transition and may result in state conflict if the resource is already + // bound for reading. + if ((pipeline.GetMrtMask() & (1 << col_buf_id)) == 0) { + continue; + } + const auto& hint = liverpool->last_cb_extent[col_buf_id]; VideoCore::ImageInfo image_info{col_buf, hint}; VideoCore::ImageViewInfo view_info{col_buf, false /*!!image.info.usage.vo_buffer*/}; @@ -134,8 +229,8 @@ void Rasterizer::BeginRendering() { using StencilFormat = AmdGpu::Liverpool::DepthBuffer::StencilFormat; if (regs.depth_buffer.Address() != 0 && ((regs.depth_control.depth_enable && regs.depth_buffer.z_info.format != ZFormat::Invalid) || - regs.depth_control.stencil_enable && - regs.depth_buffer.stencil_info.format != StencilFormat::Invalid)) { + (regs.depth_control.stencil_enable && + regs.depth_buffer.stencil_info.format != StencilFormat::Invalid))) { const auto htile_address = regs.depth_htile_data_base.GetAddress(); const bool is_clear = regs.depth_render_control.depth_clear_enable || texture_cache.IsMetaCleared(htile_address); @@ -150,7 +245,7 @@ void Rasterizer::BeginRendering() { state.depth_image = image.image; state.depth_attachment = { .imageView = *image_view.image_view, - .imageLayout = image.layout, + .imageLayout = image.last_state.layout, .loadOp = is_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, .storeOp = is_clear ? vk::AttachmentStoreOp::eNone : vk::AttachmentStoreOp::eStore, .clearValue = vk::ClearValue{.depthStencil = {.depth = regs.depth_clear, @@ -165,6 +260,17 @@ void Rasterizer::BeginRendering() { scheduler.BeginRendering(state); } +void Rasterizer::InlineDataToGds(u32 gds_offset, u32 value) { + buffer_cache.InlineDataToGds(gds_offset, value); +} + +u32 Rasterizer::ReadDataFromGds(u32 gds_offset) { + auto* gds_buf = buffer_cache.GetGdsBuffer(); + u32 value; + std::memcpy(&value, gds_buf->mapped_data.data() + gds_offset, sizeof(u32)); + return value; +} + void Rasterizer::InvalidateMemory(VAddr addr, u64 size) { buffer_cache.InvalidateMemory(addr, size); texture_cache.InvalidateMemory(addr, size); @@ -196,6 +302,43 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) { cmdbuf.setColorWriteEnableEXT(write_ens); cmdbuf.setColorWriteMaskEXT(0, write_masks); } + if (regs.depth_control.depth_bounds_enable) { + cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max); + } + if (regs.polygon_control.NeedsBias()) { + if (regs.polygon_control.enable_polygon_offset_front) { + cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias, + regs.poly_offset.front_scale); + } else { + cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias, + regs.poly_offset.back_scale); + } + } + if (regs.depth_control.stencil_enable) { + const auto front = regs.stencil_ref_front; + const auto back = regs.stencil_ref_back; + if (front.stencil_test_val == back.stencil_test_val) { + cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, + front.stencil_test_val); + } else { + cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront, front.stencil_test_val); + cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, back.stencil_test_val); + } + if (front.stencil_write_mask == back.stencil_write_mask) { + cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack, + front.stencil_write_mask); + } else { + cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront, front.stencil_write_mask); + cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, back.stencil_write_mask); + } + if (front.stencil_mask == back.stencil_mask) { + cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack, + front.stencil_mask); + } else { + cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront, front.stencil_mask); + cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack, back.stencil_mask); + } + } } void Rasterizer::UpdateViewportScissorState() { @@ -205,7 +348,10 @@ void Rasterizer::UpdateViewportScissorState() { boost::container::static_vector scissors; const float reduce_z = - regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW ? 1.0f : 0.0f; + instance.IsDepthClipControlSupported() && + regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW + ? 1.0f + : 0.0f; for (u32 i = 0; i < Liverpool::NumViewports; i++) { const auto& vp = regs.viewports[i]; const auto& vp_d = regs.viewport_depths[i]; @@ -221,11 +367,55 @@ void Rasterizer::UpdateViewportScissorState() { .maxDepth = vp.zscale + vp.zoffset, }); } - const auto& sc = regs.screen_scissor; - scissors.push_back({ - .offset = {sc.top_left_x, sc.top_left_y}, - .extent = {sc.GetWidth(), sc.GetHeight()}, - }); + + const bool enable_offset = !regs.window_scissor.window_offset_disable.Value(); + Liverpool::Scissor scsr{}; + const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) { + return std::max({scr, s16(win + win_offset), s16(gen + win_offset)}); + }; + + scsr.top_left_x = combined_scissor_value_tl( + regs.screen_scissor.top_left_x, s16(regs.window_scissor.top_left_x.Value()), + s16(regs.generic_scissor.top_left_x.Value()), + enable_offset ? regs.window_offset.window_x_offset : 0); + + scsr.top_left_y = combined_scissor_value_tl( + regs.screen_scissor.top_left_y, s16(regs.window_scissor.top_left_y.Value()), + s16(regs.generic_scissor.top_left_y.Value()), + enable_offset ? regs.window_offset.window_y_offset : 0); + + const auto combined_scissor_value_br = [](s16 scr, s16 win, s16 gen, s16 win_offset) { + return std::min({scr, s16(win + win_offset), s16(gen + win_offset)}); + }; + + scsr.bottom_right_x = combined_scissor_value_br( + regs.screen_scissor.bottom_right_x, regs.window_scissor.bottom_right_x, + regs.generic_scissor.bottom_right_x, + enable_offset ? regs.window_offset.window_x_offset : 0); + + scsr.bottom_right_y = combined_scissor_value_br( + regs.screen_scissor.bottom_right_y, regs.window_scissor.bottom_right_y, + regs.generic_scissor.bottom_right_y, + enable_offset ? regs.window_offset.window_y_offset : 0); + + for (u32 idx = 0; idx < Liverpool::NumViewports; idx++) { + auto vp_scsr = scsr; + if (regs.mode_control.vport_scissor_enable) { + vp_scsr.top_left_x = + std::max(vp_scsr.top_left_x, s16(regs.viewport_scissors[idx].top_left_x.Value())); + vp_scsr.top_left_y = + std::max(vp_scsr.top_left_y, s16(regs.viewport_scissors[idx].top_left_y.Value())); + vp_scsr.bottom_right_x = + std::min(vp_scsr.bottom_right_x, regs.viewport_scissors[idx].bottom_right_x); + vp_scsr.bottom_right_y = + std::min(vp_scsr.bottom_right_y, regs.viewport_scissors[idx].bottom_right_y); + } + scissors.push_back({ + .offset = {vp_scsr.top_left_x, vp_scsr.top_left_y}, + .extent = {vp_scsr.GetWidth(), vp_scsr.GetHeight()}, + }); + } + const auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.setViewport(0, viewports); cmdbuf.setScissor(0, scissors); @@ -239,7 +429,7 @@ void Rasterizer::UpdateDepthStencilState() { } void Rasterizer::ScopeMarkerBegin(const std::string_view& str) { - if (!Config::isMarkersEnabled()) { + if (Config::nullGpu() || !Config::vkMarkersEnabled()) { return; } @@ -250,7 +440,7 @@ void Rasterizer::ScopeMarkerBegin(const std::string_view& str) { } void Rasterizer::ScopeMarkerEnd() { - if (!Config::isMarkersEnabled()) { + if (Config::nullGpu() || !Config::vkMarkersEnabled()) { return; } @@ -259,7 +449,7 @@ void Rasterizer::ScopeMarkerEnd() { } void Rasterizer::ScopedMarkerInsert(const std::string_view& str) { - if (!Config::isMarkersEnabled()) { + if (Config::nullGpu() || !Config::vkMarkersEnabled()) { return; } @@ -269,11 +459,17 @@ void Rasterizer::ScopedMarkerInsert(const std::string_view& str) { }); } -void Rasterizer::Breadcrumb(u64 id) { - if (!instance.HasNvCheckpoints()) { +void Rasterizer::ScopedMarkerInsertColor(const std::string_view& str, const u32 color) { + if (Config::nullGpu() || !Config::vkMarkersEnabled()) { return; } - scheduler.CommandBuffer().setCheckpointNV(id); + + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.insertDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{ + .pLabelName = str.data(), + .color = std::array( + {(f32)((color >> 16) & 0xff) / 255.0f, (f32)((color >> 8) & 0xff) / 255.0f, + (f32)(color & 0xff) / 255.0f, (f32)((color >> 24) & 0xff) / 255.0f})}); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index a151ebc27..bc14f39a4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -32,22 +32,28 @@ public: } void Draw(bool is_indexed, u32 index_offset = 0); + void DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size); void DispatchDirect(); + void DispatchIndirect(VAddr address, u32 offset, u32 size); void ScopeMarkerBegin(const std::string_view& str); void ScopeMarkerEnd(); void ScopedMarkerInsert(const std::string_view& str); - void Breadcrumb(u64 id); + void ScopedMarkerInsertColor(const std::string_view& str, const u32 color); + void InlineDataToGds(u32 gds_offset, u32 value); + u32 ReadDataFromGds(u32 gsd_offset); void InvalidateMemory(VAddr addr, u64 size); void MapMemory(VAddr addr, u64 size); void UnmapMemory(VAddr addr, u64 size); + void CpSync(); u64 Flush(); + void Finish(); private: - void BeginRendering(); + void BeginRendering(const GraphicsPipeline& pipeline); void UpdateDynamicState(const GraphicsPipeline& pipeline); void UpdateViewportScissorState(); @@ -62,7 +68,6 @@ private: AmdGpu::Liverpool* liverpool; Core::MemoryManager* memory; PipelineCache pipeline_cache; - vk::UniqueEvent wfi_event; }; } // 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 f9f2ae0a0..25a134528 100644 --- a/src/video_core/renderer_vulkan/vk_resource_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_resource_pool.cpp @@ -3,8 +3,8 @@ #include #include -#include #include "common/assert.h" +#include "common/scope_exit.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_master_semaphore.h" #include "video_core/renderer_vulkan/vk_resource_pool.h" @@ -69,7 +69,10 @@ CommandPool::CommandPool(const Instance& instance, MasterSemaphore* master_semap .queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex(), }; const vk::Device device = instance.GetDevice(); - cmd_pool = device.createCommandPoolUnique(pool_create_info); + auto [pool_result, pool] = device.createCommandPoolUnique(pool_create_info); + ASSERT_MSG(pool_result == vk::Result::eSuccess, "Failed to create command pool: {}", + vk::to_string(pool_result)); + cmd_pool = std::move(pool); if (instance.HasDebuggingToolAttached()) { SetObjectName(device, *cmd_pool, "CommandPool"); } @@ -103,88 +106,89 @@ vk::CommandBuffer CommandPool::Commit() { return cmd_buffers[index]; } -constexpr u32 DESCRIPTOR_SET_BATCH = 32; - -DescriptorHeap::DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore, - std::span bindings, +DescriptorHeap::DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore_, + std::span pool_sizes_, u32 descriptor_heap_count_) - : ResourcePool{master_semaphore, DESCRIPTOR_SET_BATCH}, device{instance.GetDevice()}, - descriptor_heap_count{descriptor_heap_count_} { - // Create descriptor set layout. - const vk::DescriptorSetLayoutCreateInfo layout_ci = { - .bindingCount = static_cast(bindings.size()), - .pBindings = bindings.data(), - }; - descriptor_set_layout = device.createDescriptorSetLayoutUnique(layout_ci); - if (instance.HasDebuggingToolAttached()) { - SetObjectName(device, *descriptor_set_layout, "DescriptorSetLayout"); - } - - // Build descriptor set pool counts. - std::unordered_map descriptor_type_counts; - for (const auto& binding : bindings) { - descriptor_type_counts[binding.descriptorType] += binding.descriptorCount; - } - for (const auto& [type, count] : descriptor_type_counts) { - auto& pool_size = pool_sizes.emplace_back(); - pool_size.descriptorCount = count * descriptor_heap_count; - pool_size.type = type; - } - - // Create descriptor pool - AppendDescriptorPool(); + : device{instance.GetDevice()}, master_semaphore{master_semaphore_}, + descriptor_heap_count{descriptor_heap_count_}, pool_sizes{pool_sizes_} { + CreateDescriptorPool(); } -DescriptorHeap::~DescriptorHeap() = default; +DescriptorHeap::~DescriptorHeap() { + device.destroyDescriptorPool(curr_pool); + for (const auto [pool, tick] : pending_pools) { + master_semaphore->Wait(tick); + device.destroyDescriptorPool(pool); + } +} -void DescriptorHeap::Allocate(std::size_t begin, std::size_t end) { - ASSERT(end - begin == DESCRIPTOR_SET_BATCH); - descriptor_sets.resize(end); - hashes.resize(end); +vk::DescriptorSet DescriptorHeap::Commit(vk::DescriptorSetLayout set_layout) { + const u64 set_key = std::bit_cast(set_layout); + const auto [it, _] = descriptor_sets.try_emplace(set_key); - std::array layouts; - layouts.fill(*descriptor_set_layout); + // Check if allocated sets exist and pick one. + if (!it->second.empty()) { + const auto desc_set = it->second.back(); + it.value().pop_back(); + return desc_set; + } + + DescSetBatch desc_sets(DescriptorSetBatch); + std::array layouts; + layouts.fill(set_layout); - u32 current_pool = 0; vk::DescriptorSetAllocateInfo alloc_info = { - .descriptorPool = *pools[current_pool], - .descriptorSetCount = DESCRIPTOR_SET_BATCH, + .descriptorPool = curr_pool, + .descriptorSetCount = DescriptorSetBatch, .pSetLayouts = layouts.data(), }; - // Attempt to allocate the descriptor set batch. If the pool has run out of space, use a new - // one. - while (true) { - const auto result = - device.allocateDescriptorSets(&alloc_info, descriptor_sets.data() + begin); - if (result == vk::Result::eSuccess) { - break; - } - if (result == vk::Result::eErrorOutOfPoolMemory) { - current_pool++; - if (current_pool == pools.size()) { - LOG_INFO(Render_Vulkan, "Run out of pools, creating new one!"); - AppendDescriptorPool(); - } - alloc_info.descriptorPool = *pools[current_pool]; - } + // Attempt to allocate the descriptor set batch. + auto result = device.allocateDescriptorSets(&alloc_info, desc_sets.data()); + if (result == vk::Result::eSuccess) { + const auto desc_set = desc_sets.back(); + desc_sets.pop_back(); + it.value() = std::move(desc_sets); + return desc_set; } + + // The pool has run out. Record current tick and place it in pending list. + ASSERT_MSG(result == vk::Result::eErrorOutOfPoolMemory, + "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)) { + curr_pool = pool; + pending_pools.pop_front(); + device.resetDescriptorPool(curr_pool); + } else { + CreateDescriptorPool(); + } + + // Attempt to allocate again with fresh pool. + alloc_info.descriptorPool = curr_pool; + result = device.allocateDescriptorSets(&alloc_info, desc_sets.data()); + ASSERT_MSG(result == vk::Result::eSuccess, + "Unexpected error during descriptor set allocation {}", vk::to_string(result)); + + // We've changed pool so also reset descriptor batch cache. + descriptor_sets.clear(); + const auto desc_set = desc_sets.back(); + desc_sets.pop_back(); + descriptor_sets[set_key] = std::move(desc_sets); + return desc_set; } -vk::DescriptorSet DescriptorHeap::Commit() { - const std::size_t index = CommitResource(); - return descriptor_sets[index]; -} - -void DescriptorHeap::AppendDescriptorPool() { +void DescriptorHeap::CreateDescriptorPool() { const vk::DescriptorPoolCreateInfo pool_info = { .flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind, .maxSets = descriptor_heap_count, .poolSizeCount = static_cast(pool_sizes.size()), .pPoolSizes = pool_sizes.data(), }; - auto& pool = pools.emplace_back(); - pool = device.createDescriptorPoolUnique(pool_info); + auto [pool_result, pool] = device.createDescriptorPool(pool_info); + ASSERT_MSG(pool_result == vk::Result::eSuccess, "Failed to create descriptor pool: {}", + vk::to_string(pool_result)); + curr_pool = pool; } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_resource_pool.h b/src/video_core/renderer_vulkan/vk_resource_pool.h index b138b9693..98c2ddb8c 100644 --- a/src/video_core/renderer_vulkan/vk_resource_pool.h +++ b/src/video_core/renderer_vulkan/vk_resource_pool.h @@ -3,7 +3,9 @@ #pragma once +#include #include +#include #include #include "common/types.h" @@ -62,32 +64,29 @@ private: std::vector cmd_buffers; }; -class DescriptorHeap final : public ResourcePool { +class DescriptorHeap final { + static constexpr u32 DescriptorSetBatch = 32; + public: explicit DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore, - std::span bindings, + std::span pool_sizes, u32 descriptor_heap_count = 1024); - ~DescriptorHeap() override; + ~DescriptorHeap(); - const vk::DescriptorSetLayout& Layout() const { - return *descriptor_set_layout; - } - - void Allocate(std::size_t begin, std::size_t end) override; - - vk::DescriptorSet Commit(); + vk::DescriptorSet Commit(vk::DescriptorSetLayout set_layout); private: - void AppendDescriptorPool(); + void CreateDescriptorPool(); private: vk::Device device; - vk::UniqueDescriptorSetLayout descriptor_set_layout; + MasterSemaphore* master_semaphore; u32 descriptor_heap_count; - std::vector pool_sizes; - std::vector pools; - std::vector descriptor_sets; - std::vector hashes; + std::span pool_sizes; + vk::DescriptorPool curr_pool; + std::deque> pending_pools; + using DescSetBatch = boost::container::static_vector; + tsl::robin_map descriptor_sets; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index ef0307efd..2c4e7a3c6 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -4,6 +4,7 @@ #include #include "common/assert.h" #include "common/debug.h" +#include "imgui/renderer/texture_manager.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" @@ -58,58 +59,6 @@ void Scheduler::EndRendering() { } is_rendering = false; current_cmdbuf.endRendering(); - - boost::container::static_vector barriers; - for (size_t i = 0; i < render_state.num_color_attachments; ++i) { - barriers.push_back(vk::ImageMemoryBarrier{ - .srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, - .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, - .oldLayout = vk::ImageLayout::eColorAttachmentOptimal, - .newLayout = vk::ImageLayout::eColorAttachmentOptimal, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = render_state.color_images[i], - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }); - } - if (render_state.has_depth || render_state.has_stencil) { - barriers.push_back(vk::ImageMemoryBarrier{ - .srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite, - .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, - .oldLayout = render_state.depth_attachment.imageLayout, - .newLayout = render_state.depth_attachment.imageLayout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = render_state.depth_image, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eDepth | - (render_state.has_stencil ? vk::ImageAspectFlagBits::eStencil - : vk::ImageAspectFlagBits::eNone), - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }); - } - - if (!barriers.empty()) { - const auto src_stages = - vk::PipelineStageFlagBits::eColorAttachmentOutput | - (render_state.has_depth ? vk::PipelineStageFlagBits::eLateFragmentTests | - vk::PipelineStageFlagBits::eEarlyFragmentTests - : vk::PipelineStageFlagBits::eNone); - current_cmdbuf.pipelineBarrier(src_stages, vk::PipelineStageFlagBits::eFragmentShader, - vk::DependencyFlagBits::eByRegion, {}, {}, barriers); - } } void Scheduler::Flush(SubmitInfo& info) { @@ -140,12 +89,14 @@ void Scheduler::AllocateWorkerCommandBuffers() { }; current_cmdbuf = command_pool.Commit(); - current_cmdbuf.begin(begin_info); + auto begin_result = current_cmdbuf.begin(begin_info); + ASSERT_MSG(begin_result == vk::Result::eSuccess, "Failed to begin command buffer: {}", + vk::to_string(begin_result)); auto* profiler_ctx = instance.GetProfilerContext(); if (profiler_ctx) { static const auto scope_loc = - GPU_SCOPE_LOCATION("Guest Frame", MarkersPallete::GpuMarkerColor); + GPU_SCOPE_LOCATION("Guest Frame", MarkersPalette::GpuMarkerColor); new (profiler_scope) tracy::VkCtxScope{profiler_ctx, &scope_loc, current_cmdbuf, true}; } } @@ -161,7 +112,9 @@ void Scheduler::SubmitExecution(SubmitInfo& info) { } EndRendering(); - current_cmdbuf.end(); + auto end_result = current_cmdbuf.end(); + ASSERT_MSG(end_result == vk::Result::eSuccess, "Failed to end command buffer: {}", + vk::to_string(end_result)); const vk::Semaphore timeline = master_semaphore.Handle(); info.AddSignal(timeline, signal_value); @@ -189,18 +142,9 @@ void Scheduler::SubmitExecution(SubmitInfo& info) { .pSignalSemaphores = info.signal_semas.data(), }; - try { - instance.GetGraphicsQueue().submit(submit_info, info.fence); - } catch (vk::DeviceLostError& err) { - if (instance.HasNvCheckpoints()) { - const auto checkpoint_data = instance.GetGraphicsQueue().getCheckpointData2NV(); - for (const auto& cp : checkpoint_data) { - LOG_CRITICAL(Render_Vulkan, "{}: {:#x}", vk::to_string(cp.stage), - reinterpret_cast(cp.pCheckpointMarker)); - } - } - UNREACHABLE_MSG("Device lost during submit: {}", err.what()); - } + ImGui::Core::TextureManager::Submit(); + auto submit_result = instance.GetGraphicsQueue().submit(submit_info, info.fence); + ASSERT_MSG(submit_result != vk::Result::eErrorDeviceLost, "Device lost during submit"); master_semaphore.Refresh(); AllocateWorkerCommandBuffers(); diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp index 687760110..f9347d6e6 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp @@ -218,13 +218,10 @@ vk::ShaderModule CompileSPV(std::span code, vk::Device device) { .pCode = code.data(), }; - try { - return device.createShaderModule(shader_info); - } catch (vk::SystemError& err) { - UNREACHABLE_MSG("{}", err.what()); - } - - return {}; + auto [module_result, module] = device.createShaderModule(shader_info); + ASSERT_MSG(module_result == vk::Result::eSuccess, "Failed to compile SPIR-V shader: {}", + vk::to_string(module_result)); + return module; } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 701272b16..86d7d5063 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -37,8 +37,12 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) { instance.GetPresentQueueFamilyIndex(), }; - const auto modes = instance.GetPhysicalDevice().getSurfacePresentModesKHR(surface); - const auto find_mode = [&modes](vk::PresentModeKHR requested) { + const auto [modes_result, modes] = + instance.GetPhysicalDevice().getSurfacePresentModesKHR(surface); + const auto find_mode = [&modes_result, &modes](vk::PresentModeKHR requested) { + if (modes_result != vk::Result::eSuccess) { + return false; + } const auto it = std::find_if(modes.begin(), modes.end(), [&requested](vk::PresentModeKHR mode) { return mode == requested; }); @@ -70,17 +74,19 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) { .oldSwapchain = nullptr, }; - try { - swapchain = instance.GetDevice().createSwapchainKHR(swapchain_info); - } catch (vk::SystemError& err) { - LOG_CRITICAL(Render_Vulkan, "{}", err.what()); - UNREACHABLE(); - } + auto [swapchain_result, chain] = instance.GetDevice().createSwapchainKHR(swapchain_info); + ASSERT_MSG(swapchain_result == vk::Result::eSuccess, "Failed to create swapchain: {}", + vk::to_string(swapchain_result)); + swapchain = chain; SetupImages(); RefreshSemaphores(); } +void Swapchain::Recreate(u32 width_, u32 height_) { + Create(width_, height_, surface); +} + bool Swapchain::AcquireNextImage() { vk::Device device = instance.GetDevice(); vk::Result result = @@ -107,9 +113,6 @@ bool Swapchain::AcquireNextImage() { } void Swapchain::Present() { - if (needs_recreation) { - return; - } const vk::PresentInfoKHR present_info = { .waitSemaphoreCount = 1, @@ -119,20 +122,22 @@ void Swapchain::Present() { .pImageIndices = &image_index, }; - try { - [[maybe_unused]] vk::Result result = instance.GetPresentQueue().presentKHR(present_info); - } catch (vk::OutOfDateKHRError&) { + auto result = instance.GetPresentQueue().presentKHR(present_info); + if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR) { needs_recreation = true; - } catch (const vk::SystemError& err) { - LOG_CRITICAL(Render_Vulkan, "Swapchain presentation failed {}", err.what()); - UNREACHABLE(); + } else { + ASSERT_MSG(result == vk::Result::eSuccess, "Swapchain presentation failed: {}", + vk::to_string(result)); } frame_index = (frame_index + 1) % image_count; } void Swapchain::FindPresentFormat() { - const auto formats = instance.GetPhysicalDevice().getSurfaceFormatsKHR(surface); + const auto [formats_result, formats] = + instance.GetPhysicalDevice().getSurfaceFormatsKHR(surface); + ASSERT_MSG(formats_result == vk::Result::eSuccess, "Failed to query surface formats: {}", + vk::to_string(formats_result)); // If there is a single undefined surface format, the device doesn't care, so we'll just use // RGBA sRGB. @@ -158,8 +163,10 @@ void Swapchain::FindPresentFormat() { } void Swapchain::SetSurfaceProperties() { - const vk::SurfaceCapabilitiesKHR capabilities = + const auto [capabilities_result, capabilities] = instance.GetPhysicalDevice().getSurfaceCapabilitiesKHR(surface); + ASSERT_MSG(capabilities_result == vk::Result::eSuccess, + "Failed to query surface capabilities: {}", vk::to_string(capabilities_result)); extent = capabilities.currentExtent; if (capabilities.currentExtent.width == std::numeric_limits::max()) { @@ -190,6 +197,11 @@ void Swapchain::SetSurfaceProperties() { void Swapchain::Destroy() { vk::Device device = instance.GetDevice(); + const auto wait_result = device.waitIdle(); + if (wait_result != vk::Result::eSuccess) { + LOG_WARNING(Render_Vulkan, "Failed to wait for device to become idle: {}", + vk::to_string(wait_result)); + } if (swapchain) { device.destroySwapchainKHR(swapchain); } @@ -207,10 +219,17 @@ void Swapchain::RefreshSemaphores() { present_ready.resize(image_count); for (vk::Semaphore& semaphore : image_acquired) { - semaphore = device.createSemaphore({}); + auto [semaphore_result, sem] = device.createSemaphore({}); + ASSERT_MSG(semaphore_result == vk::Result::eSuccess, + "Failed to create image acquired semaphore: {}", + vk::to_string(semaphore_result)); + semaphore = sem; } for (vk::Semaphore& semaphore : present_ready) { - semaphore = device.createSemaphore({}); + auto [semaphore_result, sem] = device.createSemaphore({}); + ASSERT_MSG(semaphore_result == vk::Result::eSuccess, + "Failed to create present ready semaphore: {}", vk::to_string(semaphore_result)); + semaphore = sem; } if (instance.HasDebuggingToolAttached()) { @@ -223,7 +242,10 @@ void Swapchain::RefreshSemaphores() { void Swapchain::SetupImages() { vk::Device device = instance.GetDevice(); - images = device.getSwapchainImagesKHR(swapchain); + auto [images_result, imgs] = device.getSwapchainImagesKHR(swapchain); + ASSERT_MSG(images_result == vk::Result::eSuccess, "Failed to create swapchain images: {}", + vk::to_string(images_result)); + images = std::move(imgs); image_count = static_cast(images.size()); if (instance.HasDebuggingToolAttached()) { diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 28ac3a9c5..a41b3ca76 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -25,6 +25,9 @@ public: /// Creates (or recreates) the swapchain with a given size. void Create(u32 width, u32 height, vk::SurfaceKHR surface); + /// Recreates the swapchain with a given size and current surface. + void Recreate(u32 width, u32 height); + /// Acquires the next image in the swapchain. bool AcquireNextImage(); diff --git a/src/video_core/texture_cache/host_compatibility.h b/src/video_core/texture_cache/host_compatibility.h new file mode 100644 index 000000000..a73f7e6be --- /dev/null +++ b/src/video_core/texture_cache/host_compatibility.h @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright © 2023 Skyline Team and Contributors (https://github.com/skyline-emu/) +// Copyright © 2015-2023 The Khronos Group Inc. +// Copyright © 2015-2023 Valve Corporation +// Copyright © 2015-2023 LunarG, Inc. + +#pragma once + +#include +#include "video_core/renderer_vulkan/vk_common.h" + +namespace VideoCore { +/** + * @brief All classes of format compatibility according to the Vulkan specification + * @url + * https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/d37c676f75f545a3e5a98d7dfb89864391a1db1e/layers/generated/vk_format_utils.h#L47-L131 + * @note This is copied directly from Vulkan Validation Layers and doesn't follow the Skyline naming + * conventions + */ +enum class FORMAT_COMPATIBILITY_CLASS { + NONE = 0, + _10BIT_2PLANE_420, + _10BIT_2PLANE_422, + _10BIT_2PLANE_444, + _10BIT_3PLANE_420, + _10BIT_3PLANE_422, + _10BIT_3PLANE_444, + _12BIT_2PLANE_420, + _12BIT_2PLANE_422, + _12BIT_2PLANE_444, + _12BIT_3PLANE_420, + _12BIT_3PLANE_422, + _12BIT_3PLANE_444, + _128BIT, + _16BIT, + _16BIT_2PLANE_420, + _16BIT_2PLANE_422, + _16BIT_2PLANE_444, + _16BIT_3PLANE_420, + _16BIT_3PLANE_422, + _16BIT_3PLANE_444, + _192BIT, + _24BIT, + _256BIT, + _32BIT, + _32BIT_B8G8R8G8, + _32BIT_G8B8G8R8, + _48BIT, + _64BIT, + _64BIT_B10G10R10G10, + _64BIT_B12G12R12G12, + _64BIT_B16G16R16G16, + _64BIT_G10B10G10R10, + _64BIT_G12B12G12R12, + _64BIT_G16B16G16R16, + _64BIT_R10G10B10A10, + _64BIT_R12G12B12A12, + _8BIT, + _8BIT_2PLANE_420, + _8BIT_2PLANE_422, + _8BIT_2PLANE_444, + _8BIT_3PLANE_420, + _8BIT_3PLANE_422, + _8BIT_3PLANE_444, + _96BIT, + ASTC_10X10, + ASTC_10X5, + ASTC_10X6, + ASTC_10X8, + ASTC_12X10, + ASTC_12X12, + ASTC_4X4, + ASTC_5X4, + ASTC_5X5, + ASTC_6X5, + ASTC_6X6, + ASTC_8X5, + ASTC_8X6, + ASTC_8X8, + BC1_RGB, + BC1_RGBA, + BC2, + BC3, + BC4, + BC5, + BC6H, + BC7, + D16, + D16S8, + D24, + D24S8, + D32, + D32S8, + EAC_R, + EAC_RG, + ETC2_EAC_RGBA, + ETC2_RGB, + ETC2_RGBA, + PVRTC1_2BPP, + PVRTC1_4BPP, + PVRTC2_2BPP, + PVRTC2_4BPP, + S8 +}; + +/** + * @brief The format compatibility class according to the Vulkan specification + * @url + * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#formats-compatibility-classes + * @url + * https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/d37c676f75f545a3e5a98d7dfb89864391a1db1e/layers/generated/vk_format_utils.cpp#L70-L812 + * @note This is copied directly from Vulkan Validation Layers and doesn't follow the Skyline naming + * conventions + */ +static const std::unordered_map vkFormatClassTable{ + {VK_FORMAT_A1R5G5B5_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_A2B10G10R10_SINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2B10G10R10_SNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2B10G10R10_SSCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2B10G10R10_UINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2B10G10R10_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2B10G10R10_USCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2R10G10B10_SINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2R10G10B10_SNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2R10G10B10_SSCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2R10G10B10_UINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2R10G10B10_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A2R10G10B10_USCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_A8B8G8R8_SINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A8B8G8R8_SNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A8B8G8R8_SRGB_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A8B8G8R8_SSCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A8B8G8R8_UINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A8B8G8R8_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_A8B8G8R8_USCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X10}, + {VK_FORMAT_ASTC_10x10_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X10}, + {VK_FORMAT_ASTC_10x10_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X10}, + {VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X5}, + {VK_FORMAT_ASTC_10x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X5}, + {VK_FORMAT_ASTC_10x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X5}, + {VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X6}, + {VK_FORMAT_ASTC_10x6_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X6}, + {VK_FORMAT_ASTC_10x6_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X6}, + {VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X8}, + {VK_FORMAT_ASTC_10x8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X8}, + {VK_FORMAT_ASTC_10x8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X8}, + {VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_12X10}, + {VK_FORMAT_ASTC_12x10_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X10}, + {VK_FORMAT_ASTC_12x10_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X10}, + {VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_12X12}, + {VK_FORMAT_ASTC_12x12_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X12}, + {VK_FORMAT_ASTC_12x12_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X12}, + {VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_4X4}, + {VK_FORMAT_ASTC_4x4_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_4X4}, + {VK_FORMAT_ASTC_4x4_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_4X4}, + {VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_5X4}, + {VK_FORMAT_ASTC_5x4_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X4}, + {VK_FORMAT_ASTC_5x4_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X4}, + {VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_5X5}, + {VK_FORMAT_ASTC_5x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X5}, + {VK_FORMAT_ASTC_5x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X5}, + {VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_6X5}, + {VK_FORMAT_ASTC_6x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X5}, + {VK_FORMAT_ASTC_6x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X5}, + {VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_6X6}, + {VK_FORMAT_ASTC_6x6_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X6}, + {VK_FORMAT_ASTC_6x6_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X6}, + {VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_8X5}, + {VK_FORMAT_ASTC_8x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X5}, + {VK_FORMAT_ASTC_8x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X5}, + {VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_8X6}, + {VK_FORMAT_ASTC_8x6_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X6}, + {VK_FORMAT_ASTC_8x6_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X6}, + {VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_8X8}, + {VK_FORMAT_ASTC_8x8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X8}, + {VK_FORMAT_ASTC_8x8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X8}, + {VK_FORMAT_B10G11R11_UFLOAT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + FORMAT_COMPATIBILITY_CLASS::_64BIT_B10G10R10G10}, + {VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + FORMAT_COMPATIBILITY_CLASS::_64BIT_B12G12R12G12}, + {VK_FORMAT_B16G16R16G16_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT_B16G16R16G16}, + {VK_FORMAT_B4G4R4A4_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_B5G5R5A1_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_B5G6R5_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_B8G8R8A8_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8A8_SNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8A8_SRGB, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8A8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8A8_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8A8_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8A8_USCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_B8G8R8G8_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT_B8G8R8G8}, + {VK_FORMAT_B8G8R8_SINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_B8G8R8_SNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_B8G8R8_SRGB, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_B8G8R8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_B8G8R8_UINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_B8G8R8_UNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_B8G8R8_USCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_BC1_RGBA_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGBA}, + {VK_FORMAT_BC1_RGBA_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGBA}, + {VK_FORMAT_BC1_RGB_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGB}, + {VK_FORMAT_BC1_RGB_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGB}, + {VK_FORMAT_BC2_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC2}, + {VK_FORMAT_BC2_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC2}, + {VK_FORMAT_BC3_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC3}, + {VK_FORMAT_BC3_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC3}, + {VK_FORMAT_BC4_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC4}, + {VK_FORMAT_BC4_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC4}, + {VK_FORMAT_BC5_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC5}, + {VK_FORMAT_BC5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC5}, + {VK_FORMAT_BC6H_SFLOAT_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC6H}, + {VK_FORMAT_BC6H_UFLOAT_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC6H}, + {VK_FORMAT_BC7_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC7}, + {VK_FORMAT_BC7_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC7}, + {VK_FORMAT_D16_UNORM, FORMAT_COMPATIBILITY_CLASS::D16}, + {VK_FORMAT_D16_UNORM_S8_UINT, FORMAT_COMPATIBILITY_CLASS::D16S8}, + {VK_FORMAT_D24_UNORM_S8_UINT, FORMAT_COMPATIBILITY_CLASS::D24S8}, + {VK_FORMAT_D32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::D32}, + {VK_FORMAT_D32_SFLOAT_S8_UINT, FORMAT_COMPATIBILITY_CLASS::D32S8}, + {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_EAC_R11G11_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_RG}, + {VK_FORMAT_EAC_R11G11_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_RG}, + {VK_FORMAT_EAC_R11_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_R}, + {VK_FORMAT_EAC_R11_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_R}, + {VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGBA}, + {VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGBA}, + {VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_EAC_RGBA}, + {VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_EAC_RGBA}, + {VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGB}, + {VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGB}, + {VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + FORMAT_COMPATIBILITY_CLASS::_64BIT_G10B10G10R10}, + {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_10BIT_2PLANE_420}, + {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_10BIT_2PLANE_422}, + {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT, + FORMAT_COMPATIBILITY_CLASS::_10BIT_2PLANE_444}, + {VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_10BIT_3PLANE_420}, + {VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_10BIT_3PLANE_422}, + {VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_10BIT_3PLANE_444}, + {VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + FORMAT_COMPATIBILITY_CLASS::_64BIT_G12B12G12R12}, + {VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_12BIT_2PLANE_420}, + {VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_12BIT_2PLANE_422}, + {VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT, + FORMAT_COMPATIBILITY_CLASS::_12BIT_2PLANE_444}, + {VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_12BIT_3PLANE_420}, + {VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_12BIT_3PLANE_422}, + {VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + FORMAT_COMPATIBILITY_CLASS::_12BIT_3PLANE_444}, + {VK_FORMAT_G16B16G16R16_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT_G16B16G16R16}, + {VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_2PLANE_420}, + {VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_2PLANE_422}, + {VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT, FORMAT_COMPATIBILITY_CLASS::_16BIT_2PLANE_444}, + {VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_3PLANE_420}, + {VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_3PLANE_422}, + {VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_3PLANE_444}, + {VK_FORMAT_G8B8G8R8_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT_G8B8G8R8}, + {VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_2PLANE_420}, + {VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_2PLANE_422}, + {VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, FORMAT_COMPATIBILITY_CLASS::_8BIT_2PLANE_444}, + {VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_3PLANE_420}, + {VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_3PLANE_422}, + {VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_3PLANE_444}, + {VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_2BPP}, + {VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_2BPP}, + {VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_4BPP}, + {VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_4BPP}, + {VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_2BPP}, + {VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_2BPP}, + {VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_4BPP}, + {VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_4BPP}, + {VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, FORMAT_COMPATIBILITY_CLASS::_64BIT_R10G10B10A10}, + {VK_FORMAT_R10X6G10X6_UNORM_2PACK16, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R10X6_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, FORMAT_COMPATIBILITY_CLASS::_64BIT_R12G12B12A12}, + {VK_FORMAT_R12X4G12X4_UNORM_2PACK16, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R12X4_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16G16B16A16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16A16_SINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16A16_SNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16A16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16A16_UINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16A16_UNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16A16_USCALED, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R16G16B16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16B16_SINT, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16B16_SNORM, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16B16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16B16_UINT, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16B16_UNORM, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16B16_USCALED, FORMAT_COMPATIBILITY_CLASS::_48BIT}, + {VK_FORMAT_R16G16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16G16_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16G16_SNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16G16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16G16_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16G16_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16G16_USCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16_SINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16_SNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16_UINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R16_USCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R32G32B32A32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, + {VK_FORMAT_R32G32B32A32_SINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, + {VK_FORMAT_R32G32B32A32_UINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, + {VK_FORMAT_R32G32B32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_96BIT}, + {VK_FORMAT_R32G32B32_SINT, FORMAT_COMPATIBILITY_CLASS::_96BIT}, + {VK_FORMAT_R32G32B32_UINT, FORMAT_COMPATIBILITY_CLASS::_96BIT}, + {VK_FORMAT_R32G32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R32G32_SINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R32G32_UINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R32_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R32_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R4G4B4A4_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R4G4_UNORM_PACK8, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R5G5B5A1_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R5G6B5_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R64G64B64A64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_256BIT}, + {VK_FORMAT_R64G64B64A64_SINT, FORMAT_COMPATIBILITY_CLASS::_256BIT}, + {VK_FORMAT_R64G64B64A64_UINT, FORMAT_COMPATIBILITY_CLASS::_256BIT}, + {VK_FORMAT_R64G64B64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_192BIT}, + {VK_FORMAT_R64G64B64_SINT, FORMAT_COMPATIBILITY_CLASS::_192BIT}, + {VK_FORMAT_R64G64B64_UINT, FORMAT_COMPATIBILITY_CLASS::_192BIT}, + {VK_FORMAT_R64G64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, + {VK_FORMAT_R64G64_SINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, + {VK_FORMAT_R64G64_UINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, + {VK_FORMAT_R64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R64_SINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R64_UINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, + {VK_FORMAT_R8G8B8A8_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8A8_SNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8A8_SRGB, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8A8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8A8_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8A8_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8A8_USCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, + {VK_FORMAT_R8G8B8_SINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8B8_SNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8B8_SRGB, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8B8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8B8_UINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8B8_UNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8B8_USCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, + {VK_FORMAT_R8G8_SINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8G8_SNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8G8_SRGB, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8G8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8G8_UINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8G8_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8G8_USCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, + {VK_FORMAT_R8_SINT, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R8_SNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R8_SRGB, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R8_UINT, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R8_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_R8_USCALED, FORMAT_COMPATIBILITY_CLASS::_8BIT}, + {VK_FORMAT_S8_UINT, FORMAT_COMPATIBILITY_CLASS::S8}, + {VK_FORMAT_X8_D24_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::D24}, + {VK_FORMAT_UNDEFINED, FORMAT_COMPATIBILITY_CLASS::NONE}, +}; + +/** + * @return If the two formats are compatible according to Vulkan's format compatibility rules + * @url + * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#formats-compatibility + */ +static bool IsVulkanFormatCompatible(vk::Format lhs, vk::Format rhs) { + if (lhs == rhs) { + return true; + } + return vkFormatClassTable.at(VkFormat(lhs)) == vkFormatClassTable.at(VkFormat(rhs)); +} +} // namespace VideoCore diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 528dda55c..bea2ce4ff 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -1,20 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "common/assert.h" -#include "common/config.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/texture_cache/image.h" -#include "video_core/texture_cache/tile_manager.h" #include namespace VideoCore { using namespace Vulkan; -using Libraries::VideoOut::TilingMode; bool ImageInfo::IsBlockCoded() const { switch (pixel_format) { @@ -73,17 +71,39 @@ static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) { if (!info.IsBlockCoded() && !info.IsPacked()) { usage |= vk::ImageUsageFlagBits::eColorAttachment; } + // In cases where an image is created as a render/depth target and cleared with compute, + // we cannot predict whether it will be used as a storage image. A proper solution would + // involve re-creating the resource with a new configuration and copying previous content + // into it. However, for now, we will set storage usage for all images (if the format + // allows), sacrificing a bit of performance. Note use of ExtendedUsage flag set by default. + usage |= vk::ImageUsageFlagBits::eStorage; } - // In cases where an image is created as a render/depth target and cleared with compute, - // we cannot predict whether it will be used as a storage image. A proper solution would - // involve re-creating the resource with a new configuration and copying previous content into - // it. However, for now, we will set storage usage for all images (if the format allows), - // sacrificing a bit of performance. Note use of ExtendedUsage flag set by default. - usage |= vk::ImageUsageFlagBits::eStorage; return usage; } +static vk::FormatFeatureFlags2 FormatFeatureFlags(const vk::ImageUsageFlags usage_flags) { + vk::FormatFeatureFlags2 feature_flags{}; + if (usage_flags & vk::ImageUsageFlagBits::eTransferSrc) { + feature_flags |= vk::FormatFeatureFlagBits2::eTransferSrc; + } + if (usage_flags & vk::ImageUsageFlagBits::eTransferDst) { + feature_flags |= vk::FormatFeatureFlagBits2::eTransferDst; + } + if (usage_flags & vk::ImageUsageFlagBits::eSampled) { + feature_flags |= vk::FormatFeatureFlagBits2::eSampledImage; + } + if (usage_flags & vk::ImageUsageFlagBits::eColorAttachment) { + feature_flags |= vk::FormatFeatureFlagBits2::eColorAttachment; + } + if (usage_flags & vk::ImageUsageFlagBits::eDepthStencilAttachment) { + feature_flags |= vk::FormatFeatureFlagBits2::eDepthStencilAttachment; + } + // Note: StorageImage is intentionally ignored for now since it is always set, and can mess up + // compatibility checks. + return feature_flags; +} + UniqueImage::UniqueImage(vk::Device device_, VmaAllocator allocator_) : device{device_}, allocator{allocator_} {} @@ -123,13 +143,14 @@ 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}; - if (info.props.is_cube) { + if (info.props.is_cube || (info.type == vk::ImageType::e2D && info.resources.layers >= 6)) { flags |= vk::ImageCreateFlagBits::eCubeCompatible; } else if (info.props.is_volume) { flags |= vk::ImageCreateFlagBits::e2DArrayCompatible; } usage = ImageUsageFlags(info); + format_features = FormatFeatureFlags(usage); switch (info.pixel_format) { case vk::Format::eD16Unorm: @@ -146,10 +167,18 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, break; } + constexpr auto tiling = vk::ImageTiling::eOptimal; + const auto supported_format = instance->GetSupportedFormat(info.pixel_format, format_features); + const auto properties = instance->GetPhysicalDevice().getImageFormatProperties( + supported_format, info.type, tiling, usage, flags); + const auto supported_samples = properties.result == vk::Result::eSuccess + ? properties.value.sampleCounts + : vk::SampleCountFlagBits::e1; + const vk::ImageCreateInfo image_ci = { .flags = flags, .imageType = info.type, - .format = instance->GetSupportedFormat(info.pixel_format), + .format = supported_format, .extent{ .width = info.size.width, .height = info.size.height, @@ -157,64 +186,145 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, }, .mipLevels = static_cast(info.resources.levels), .arrayLayers = static_cast(info.resources.layers), - .samples = LiverpoolToVK::NumSamples(info.num_samples), - .tiling = vk::ImageTiling::eOptimal, + .samples = LiverpoolToVK::NumSamples(info.num_samples, supported_samples), + .tiling = tiling, .usage = usage, .initialLayout = vk::ImageLayout::eUndefined, }; image.Create(image_ci); - Vulkan::SetObjectName(instance->GetDevice(), (vk::Image)image, "Image {:#x}:{:#x}", - info.guest_address, info.guest_size_bytes); + 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); } -void Image::Transit(vk::ImageLayout dst_layout, vk::Flags dst_mask, - vk::CommandBuffer cmdbuf) { - if (dst_layout == layout && dst_mask == access_mask) { - return; +boost::container::small_vector Image::GetBarriers( + vk::ImageLayout dst_layout, vk::Flags dst_mask, + vk::PipelineStageFlags2 dst_stage, std::optional subres_range) { + const bool needs_partial_transition = + subres_range && + (subres_range->base != SubresourceBase{} || subres_range->extent != info.resources); + const bool partially_transited = !subresource_states.empty(); + + boost::container::small_vector barriers{}; + if (needs_partial_transition || partially_transited) { + if (!partially_transited) { + subresource_states.resize(info.resources.levels * info.resources.layers); + std::fill(subresource_states.begin(), subresource_states.end(), last_state); + } + + // In case of partial transition, we need to change the specified subresources only. + // Otherwise all subresources need to be set to the same state so we can use a full + // resource transition for the next time. + const auto mips = + needs_partial_transition + ? std::ranges::views::iota(subres_range->base.level, + subres_range->base.level + subres_range->extent.levels) + : std::views::iota(0u, info.resources.levels); + const auto layers = + needs_partial_transition + ? std::ranges::views::iota(subres_range->base.layer, + subres_range->base.layer + subres_range->extent.layers) + : std::views::iota(0u, info.resources.layers); + + for (u32 mip : mips) { + for (u32 layer : layers) { + // NOTE: these loops may produce a lot of small barriers. + // If this becomes a problem, we can optimize it by merging adjacent barriers. + const auto subres_idx = mip * info.resources.layers + layer; + ASSERT(subres_idx < subresource_states.size()); + auto& state = subresource_states[subres_idx]; + + if (state.layout != dst_layout || state.access_mask != dst_mask) { + barriers.emplace_back(vk::ImageMemoryBarrier2{ + .srcStageMask = state.pl_stage, + .srcAccessMask = state.access_mask, + .dstStageMask = dst_stage, + .dstAccessMask = dst_mask, + .oldLayout = state.layout, + .newLayout = dst_layout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = mip, + .levelCount = 1, + .baseArrayLayer = layer, + .layerCount = 1, + }, + }); + state.layout = dst_layout; + state.access_mask = dst_mask; + state.pl_stage = dst_stage; + } + } + } + + if (!needs_partial_transition) { + subresource_states.clear(); + } + } else { // Full resource transition + if (last_state.layout == dst_layout && last_state.access_mask == dst_mask) { + return {}; + } + + barriers.emplace_back(vk::ImageMemoryBarrier2{ + .srcStageMask = last_state.pl_stage, + .srcAccessMask = last_state.access_mask, + .dstStageMask = dst_stage, + .dstAccessMask = dst_mask, + .oldLayout = last_state.layout, + .newLayout = dst_layout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }); } - const vk::ImageMemoryBarrier barrier = { - .srcAccessMask = access_mask, - .dstAccessMask = dst_mask, - .oldLayout = layout, - .newLayout = dst_layout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange{ - .aspectMask = aspect_mask, - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }; + last_state.layout = dst_layout; + last_state.access_mask = dst_mask; + last_state.pl_stage = dst_stage; + return barriers; +} + +void Image::Transit(vk::ImageLayout dst_layout, vk::Flags dst_mask, + std::optional range, vk::CommandBuffer cmdbuf /*= {}*/) { // Adjust pipieline stage - const vk::PipelineStageFlags dst_pl_stage = - (dst_mask == vk::AccessFlagBits::eTransferRead || - dst_mask == vk::AccessFlagBits::eTransferWrite) - ? vk::PipelineStageFlagBits::eTransfer - : vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader; + const vk::PipelineStageFlags2 dst_pl_stage = + (dst_mask == vk::AccessFlagBits2::eTransferRead || + dst_mask == vk::AccessFlagBits2::eTransferWrite) + ? vk::PipelineStageFlagBits2::eTransfer + : vk::PipelineStageFlagBits2::eAllGraphics | vk::PipelineStageFlagBits2::eComputeShader; + + const auto barriers = GetBarriers(dst_layout, dst_mask, dst_pl_stage, range); + if (barriers.empty()) { + return; + } if (!cmdbuf) { // When using external cmdbuf you are responsible for ending rp. scheduler->EndRendering(); cmdbuf = scheduler->CommandBuffer(); } - cmdbuf.pipelineBarrier(pl_stage, dst_pl_stage, vk::DependencyFlagBits::eByRegion, {}, {}, - barrier); - - layout = dst_layout; - access_mask = dst_mask; - pl_stage = dst_pl_stage; + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .imageMemoryBarrierCount = static_cast(barriers.size()), + .pImageMemoryBarriers = barriers.data(), + }); } void Image::Upload(vk::Buffer buffer, u64 offset) { scheduler->EndRendering(); - Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits::eTransferWrite); + Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {}); // Copy to the image. const auto aspect = aspect_mask & vk::ImageAspectFlagBits::eStencil @@ -238,7 +348,77 @@ void Image::Upload(vk::Buffer buffer, u64 offset) { cmdbuf.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, image_copy); Transit(vk::ImageLayout::eGeneral, - vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead); + vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eTransferRead, {}); +} + +void Image::CopyImage(const Image& image) { + scheduler->EndRendering(); + Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {}); + + auto cmdbuf = scheduler->CommandBuffer(); + + boost::container::small_vector image_copy{}; + for (u32 m = 0; m < image.info.resources.levels; ++m) { + const auto mip_w = std::max(info.size.width >> m, 1u); + const auto mip_h = std::max(info.size.height >> m, 1u); + const auto mip_d = std::max(info.size.depth >> m, 1u); + + image_copy.emplace_back(vk::ImageCopy{ + .srcSubresource{ + .aspectMask = image.aspect_mask, + .mipLevel = m, + .baseArrayLayer = 0, + .layerCount = image.info.resources.layers, + }, + .dstSubresource{ + .aspectMask = image.aspect_mask, + .mipLevel = m, + .baseArrayLayer = 0, + .layerCount = image.info.resources.layers, + }, + .extent = {mip_w, mip_h, mip_d}, + }); + } + cmdbuf.copyImage(image.image, image.last_state.layout, this->image, this->last_state.layout, + image_copy); + + Transit(vk::ImageLayout::eGeneral, + vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eTransferRead, {}); +} + +void Image::CopyMip(const Image& image, u32 mip) { + scheduler->EndRendering(); + Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {}); + + auto cmdbuf = scheduler->CommandBuffer(); + + const auto mip_w = std::max(info.size.width >> mip, 1u); + const auto mip_h = std::max(info.size.height >> mip, 1u); + const auto mip_d = std::max(info.size.depth >> mip, 1u); + + ASSERT(mip_w == image.info.size.width); + ASSERT(mip_h == image.info.size.height); + + const vk::ImageCopy image_copy{ + .srcSubresource{ + .aspectMask = image.aspect_mask, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = image.info.resources.layers, + }, + .dstSubresource{ + .aspectMask = image.aspect_mask, + .mipLevel = mip, + .baseArrayLayer = 0, + .layerCount = info.resources.layers, + }, + .extent = {mip_w, mip_h, mip_d}, + }; + cmdbuf.copyImage(image.image, image.last_state.layout, this->image, this->last_state.layout, + image_copy); + + Transit(vk::ImageLayout::eGeneral, + vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eTransferRead, {}); } Image::~Image() = default; diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index 5a888346f..312ff97e8 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -5,13 +5,9 @@ #include "common/enum.h" #include "common/types.h" -#include "core/libraries/videoout/buffer.h" -#include "video_core/amdgpu/liverpool.h" -#include "video_core/amdgpu/resource.h" #include "video_core/renderer_vulkan/vk_common.h" #include "video_core/texture_cache/image_info.h" #include "video_core/texture_cache/image_view.h" -#include "video_core/texture_cache/types.h" #include @@ -26,12 +22,16 @@ VK_DEFINE_HANDLE(VmaAllocator) namespace VideoCore { enum ImageFlagBits : u32 { - CpuModified = 1 << 2, ///< Contents have been modified from the CPU + CpuDirty = 1 << 1, ///< Contents have been modified from the CPU + GpuDirty = 1 << 2, ///< Contents have been modified from the GPU (valid data in buffer cache) + Dirty = CpuDirty | GpuDirty, GpuModified = 1 << 3, ///< Contents have been modified from the GPU Tracked = 1 << 4, ///< Writes and reads are being hooked from the CPU Registered = 1 << 6, ///< True when the image is registered Picked = 1 << 7, ///< Temporary flag to mark the image as picked MetaRegistered = 1 << 8, ///< True when metadata for this surface is known and registered + Bound = 1 << 9, ///< True when the image is bound to a descriptor set + NeedsRebind = 1 << 10, ///< True when the image needs to be rebound }; DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) @@ -43,9 +43,9 @@ struct UniqueImage { UniqueImage& operator=(const UniqueImage&) = delete; UniqueImage(UniqueImage&& other) - : image{std::exchange(other.image, VK_NULL_HANDLE)}, - allocator{std::exchange(other.allocator, VK_NULL_HANDLE)}, - allocation{std::exchange(other.allocation, VK_NULL_HANDLE)} {} + : allocator{std::exchange(other.allocator, VK_NULL_HANDLE)}, + allocation{std::exchange(other.allocation, VK_NULL_HANDLE)}, + image{std::exchange(other.image, VK_NULL_HANDLE)} {} UniqueImage& operator=(UniqueImage&& other) { image = std::exchange(other.image, VK_NULL_HANDLE); allocator = std::exchange(other.allocator, VK_NULL_HANDLE); @@ -91,16 +91,22 @@ struct Image { return image_view_ids[std::distance(image_view_infos.begin(), it)]; } - void Transit(vk::ImageLayout dst_layout, vk::Flags dst_mask, - vk::CommandBuffer cmdbuf = {}); + boost::container::small_vector GetBarriers( + vk::ImageLayout dst_layout, vk::Flags dst_mask, + vk::PipelineStageFlags2 dst_stage, std::optional subres_range); + void Transit(vk::ImageLayout dst_layout, vk::Flags dst_mask, + std::optional range, vk::CommandBuffer cmdbuf = {}); void Upload(vk::Buffer buffer, u64 offset); + void CopyImage(const Image& image); + void CopyMip(const Image& image, u32 mip); + const Vulkan::Instance* instance; Vulkan::Scheduler* scheduler; ImageInfo info; UniqueImage image; vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor; - ImageFlagBits flags = ImageFlagBits::CpuModified; + ImageFlagBits flags = ImageFlagBits::Dirty; VAddr cpu_addr = 0; VAddr cpu_addr_end = 0; std::vector image_view_infos; @@ -108,10 +114,16 @@ struct Image { // Resource state tracking vk::ImageUsageFlags usage; - vk::Flags pl_stage = vk::PipelineStageFlagBits::eAllCommands; - vk::Flags access_mask = vk::AccessFlagBits::eNone; - vk::ImageLayout layout = vk::ImageLayout::eUndefined; - boost::container::small_vector mip_hashes; + vk::FormatFeatureFlags2 format_features; + struct State { + vk::Flags pl_stage = vk::PipelineStageFlagBits2::eAllCommands; + vk::Flags access_mask = vk::AccessFlagBits2::eNone; + vk::ImageLayout layout = vk::ImageLayout::eUndefined; + }; + State last_state{}; + std::vector subresource_states{}; + boost::container::small_vector mip_hashes{}; + u64 tick_accessed_last{0}; }; } // namespace VideoCore diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 17b78a6d5..efb74ffae 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -34,6 +34,7 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { case AmdGpu::ImageType::Color1DArray: return vk::ImageType::e1D; case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Color2DMsaa: case AmdGpu::ImageType::Cube: case AmdGpu::ImageType::Color2DArray: return vk::ImageType::e2D; @@ -173,6 +174,7 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, const auto color_slice_sz = buffer.GetColorSliceSize(); guest_size_bytes = color_slice_sz * buffer.NumSlices(); mips_layout.emplace_back(color_slice_sz, pitch, 0); + tiling_idx = static_cast(buffer.attrib.tile_mode_index.Value()); } ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slices, @@ -185,7 +187,7 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slice size.width = hint.Valid() ? hint.width : buffer.Pitch(); size.height = hint.Valid() ? hint.height : buffer.Height(); size.depth = 1; - pitch = size.width; + pitch = buffer.Pitch(); resources.layers = num_slices; meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0; usage.depth_target = true; @@ -198,9 +200,13 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slice mips_layout.emplace_back(depth_slice_sz, pitch, 0); } -ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { +ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept { tiling_mode = image.GetTilingMode(); pixel_format = LiverpoolToVK::SurfaceFormat(image.GetDataFmt(), image.GetNumberFmt()); + // Override format if image is forced to be a depth target + if (desc.is_depth) { + pixel_format = LiverpoolToVK::PromoteFormatToDepth(pixel_format); + } type = ConvertImageType(image.GetType()); props.is_tiled = image.IsTiled(); props.is_cube = image.GetType() == AmdGpu::ImageType::Cube; @@ -212,14 +218,19 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { size.depth = props.is_volume ? image.depth + 1 : 1; pitch = image.Pitch(); resources.levels = image.NumLevels(); - resources.layers = image.NumLayers(); + resources.layers = image.NumLayers(desc.is_array); num_bits = NumBits(image.GetDataFmt()); usage.texture = true; guest_address = image.Address(); mips_layout.reserve(resources.levels); + tiling_idx = image.tiling_index; + UpdateSize(); +} +void ImageInfo::UpdateSize() { + mips_layout.clear(); MipInfo mip_info{}; guest_size_bytes = 0; for (auto mip = 0u; mip < resources.levels; ++mip) { @@ -243,7 +254,6 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { switch (tiling_mode) { case AmdGpu::TilingMode::Display_Linear: { - ASSERT(!props.is_cube); std::tie(mip_info.pitch, mip_info.size) = ImageSizeLinearAligned(mip_w, mip_h, bpp, num_samples); mip_info.height = mip_h; @@ -265,7 +275,7 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { ASSERT(!props.is_block); ASSERT(num_samples == 1); std::tie(mip_info.pitch, mip_info.size) = - ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, image.tiling_index); + ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, tiling_idx); break; } default: { @@ -281,4 +291,79 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { guest_size_bytes *= resources.layers; } +bool ImageInfo::IsMipOf(const ImageInfo& info) const { + if (!IsCompatible(info)) { + return false; + } + + // Currently we expect only on level to be copied. + if (resources.levels != 1) { + return false; + } + + const int mip = info.resources.levels - resources.levels; + if (mip < 1) { + return false; + } + + const auto mip_w = std::max(info.size.width >> mip, 1u); + const auto mip_h = std::max(info.size.height >> mip, 1u); + if ((size.width != mip_w) || (size.height != mip_h)) { + return false; + } + + const auto mip_d = std::max(info.size.depth >> mip, 1u); + if (info.type == vk::ImageType::e3D && type == vk::ImageType::e2D) { + // In case of 2D array to 3D copy, make sure we have proper number of layers. + if (resources.layers != mip_d) { + return false; + } + } else { + if (type != info.type) { + return false; + } + } + + // Check if the mip has correct size. + if (info.mips_layout.size() <= mip || info.mips_layout[mip].size != guest_size_bytes) { + return false; + } + + // Ensure that address matches too. + if ((info.guest_address + info.mips_layout[mip].offset) != guest_address) { + return false; + } + + return true; +} + +bool ImageInfo::IsSliceOf(const ImageInfo& info) const { + if (!IsCompatible(info)) { + return false; + } + + // Array slices should be of the same type. + if (type != info.type) { + return false; + } + + // 2D dimensions of both images should be the same. + if ((size.width != info.size.width) || (size.height != info.size.height)) { + return false; + } + + // Check for size alignment. + const bool slice_size = info.guest_size_bytes / info.resources.layers; + if (guest_size_bytes % slice_size != 0) { + return false; + } + + // Ensure that address is aligned too. + if (((info.guest_address - guest_address) % guest_size_bytes) != 0) { + return false; + } + + return true; +} + } // namespace VideoCore diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 9dad0dd67..2ae2547f7 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -3,9 +3,9 @@ #pragma once -#include "common/enum.h" #include "common/types.h" #include "core/libraries/videoout/buffer.h" +#include "shader_recompiler/info.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/texture_cache/types.h" @@ -20,7 +20,7 @@ struct ImageInfo { const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slices, VAddr htile_address, const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; - ImageInfo(const AmdGpu::Image& image) noexcept; + ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept; bool IsTiled() const { return tiling_mode != AmdGpu::TilingMode::Display_Linear; @@ -29,6 +29,17 @@ struct ImageInfo { bool IsPacked() const; bool IsDepthStencil() const; + bool IsMipOf(const ImageInfo& info) const; + bool IsSliceOf(const ImageInfo& info) const; + + /// Verifies if images are compatible for subresource merging. + bool IsCompatible(const ImageInfo& info) const { + return (pixel_format == info.pixel_format && tiling_idx == info.tiling_idx && + num_samples == info.num_samples && num_bits == info.num_bits); + } + + void UpdateSize(); + struct { VAddr cmask_addr; VAddr fmask_addr; @@ -69,6 +80,7 @@ struct ImageInfo { boost::container::small_vector mips_layout; VAddr guest_address{0}; u32 guest_size_bytes{0}; + u32 tiling_idx{0}; // TODO: merge with existing! }; } // namespace VideoCore diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index cbf77f2d8..db8113499 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" +#include "shader_recompiler/info.h" +#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/image.h" @@ -16,6 +18,7 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) { case AmdGpu::ImageType::Color1DArray: return vk::ImageViewType::e1DArray; case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Color2DMsaa: return vk::ImageViewType::e2D; case AmdGpu::ImageType::Cube: return vk::ImageViewType::eCube; @@ -48,9 +51,9 @@ vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) { } bool IsIdentityMapping(u32 dst_sel, u32 num_components) { - return (num_components == 1 && dst_sel == 0b100) || - (num_components == 2 && dst_sel == 0b101'100) || - (num_components == 3 && dst_sel == 0b110'101'100) || + return (num_components == 1 && dst_sel == 0b001'000'000'100) || + (num_components == 2 && dst_sel == 0b001'000'101'100) || + (num_components == 3 && dst_sel == 0b001'110'101'100) || (num_components == 4 && dst_sel == 0b111'110'101'100); } @@ -58,17 +61,46 @@ vk::Format TrySwizzleFormat(vk::Format format, u32 dst_sel) { if (format == vk::Format::eR8G8B8A8Unorm && dst_sel == 0b111100101110) { return vk::Format::eB8G8R8A8Unorm; } + if (format == vk::Format::eR8G8B8A8Srgb && dst_sel == 0b111100101110) { + return vk::Format::eB8G8R8A8Srgb; + } return format; } -ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, bool is_storage_) noexcept - : is_storage{is_storage_} { - type = ConvertImageViewType(image.GetType()); - format = Vulkan::LiverpoolToVK::SurfaceFormat(image.GetDataFmt(), image.GetNumberFmt()); +ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept + : is_storage{desc.is_storage} { + const auto dfmt = image.GetDataFmt(); + auto nfmt = image.GetNumberFmt(); + if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) { + nfmt = AmdGpu::NumberFormat::Unorm; + } + format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt); + if (desc.is_depth) { + format = Vulkan::LiverpoolToVK::PromoteFormatToDepth(format); + } range.base.level = image.base_level; range.base.layer = image.base_array; - range.extent.levels = image.last_level + 1; - range.extent.layers = image.last_array + 1; + range.extent.levels = image.last_level - image.base_level + 1; + range.extent.layers = image.last_array - image.base_array + 1; + type = ConvertImageViewType(image.GetType()); + + // Adjust view type for partial cubemaps and arrays + if (image.IsPartialCubemap()) { + type = vk::ImageViewType::e2DArray; + } + 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; + } + if (!is_storage) { mapping.r = ConvertComponentSwizzle(image.dst_sel_x); mapping.g = ConvertComponentSwizzle(image.dst_sel_y); @@ -93,7 +125,7 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer, 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.extent.layers = col_buffer.NumSlices() - range.base.layer; format = Vulkan::LiverpoolToVK::AdjustColorBufferFormat( base_format, col_buffer.info.comp_swap.Value(), is_vo_surface); } @@ -105,39 +137,48 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::DepthBuffer& depth_buffer, depth_buffer.stencil_info.format); is_storage = ctl.depth_write_enable; range.base.layer = view.slice_start; - range.extent.layers = view.NumSlices(); + range.extent.layers = view.NumSlices() - range.base.layer; } ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info_, Image& image, - ImageId image_id_, std::optional usage_override /*= {}*/) - : info{info_}, image_id{image_id_} { - vk::ImageViewUsageCreateInfo usage_ci{}; - if (usage_override) { - usage_ci.usage = usage_override.value(); + ImageId image_id_) + : image_id{image_id_}, info{info_} { + vk::ImageViewUsageCreateInfo usage_ci{.usage = image.usage}; + if (!info.is_storage) { + usage_ci.usage &= ~vk::ImageUsageFlagBits::eStorage; } // When sampling D32 texture from shader, the T# specifies R32 Float format so adjust it. vk::Format format = info.format; vk::ImageAspectFlags aspect = image.aspect_mask; - if (image.aspect_mask & vk::ImageAspectFlagBits::eDepth && format == vk::Format::eR32Sfloat) { + if (image.aspect_mask & vk::ImageAspectFlagBits::eDepth && + (format == vk::Format::eR32Sfloat || format == vk::Format::eD32Sfloat)) { format = image.info.pixel_format; aspect = vk::ImageAspectFlagBits::eDepth; } + if (image.aspect_mask & vk::ImageAspectFlagBits::eStencil && format == vk::Format::eR8Unorm) { + format = image.info.pixel_format; + aspect = vk::ImageAspectFlagBits::eStencil; + } const vk::ImageViewCreateInfo image_view_ci = { - .pNext = usage_override ? &usage_ci : nullptr, + .pNext = &usage_ci, .image = image.image, .viewType = info.type, - .format = instance.GetSupportedFormat(format), - .components = instance.GetSupportedComponentSwizzle(format, info.mapping), + .format = instance.GetSupportedFormat(format, image.format_features), + .components = + instance.GetSupportedComponentSwizzle(format, info.mapping, image.format_features), .subresourceRange{ .aspectMask = aspect, .baseMipLevel = info.range.base.level, - .levelCount = info.range.extent.levels - info.range.base.level, - .baseArrayLayer = info_.range.base.layer, - .layerCount = info.range.extent.layers - info.range.base.layer, + .levelCount = info.range.extent.levels, + .baseArrayLayer = info.range.base.layer, + .layerCount = info.range.extent.layers, }, }; - image_view = instance.GetDevice().createImageViewUnique(image_view_ci); + auto [view_result, view] = instance.GetDevice().createImageViewUnique(image_view_ci); + ASSERT_MSG(view_result == vk::Result::eSuccess, "Failed to create image view: {}", + vk::to_string(view_result)); + image_view = std::move(view); } ImageView::~ImageView() = default; diff --git a/src/video_core/texture_cache/image_view.h b/src/video_core/texture_cache/image_view.h index fbc62db36..ba8d2c72b 100644 --- a/src/video_core/texture_cache/image_view.h +++ b/src/video_core/texture_cache/image_view.h @@ -3,13 +3,12 @@ #pragma once +#include "shader_recompiler/info.h" #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/resource.h" #include "video_core/renderer_vulkan/vk_common.h" #include "video_core/texture_cache/types.h" -#include - namespace Vulkan { class Instance; class Scheduler; @@ -19,7 +18,7 @@ namespace VideoCore { struct ImageViewInfo { ImageViewInfo() = default; - ImageViewInfo(const AmdGpu::Image& image, bool is_storage) noexcept; + ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept; ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer, bool is_vo_surface) noexcept; ImageViewInfo(const AmdGpu::Liverpool::DepthBuffer& depth_buffer, AmdGpu::Liverpool::DepthView view, AmdGpu::Liverpool::DepthControl ctl); @@ -28,7 +27,7 @@ struct ImageViewInfo { vk::Format format = vk::Format::eR8G8B8A8Unorm; SubresourceRange range; vk::ComponentMapping mapping{}; - bool is_storage; + bool is_storage = false; auto operator<=>(const ImageViewInfo&) const = default; }; @@ -38,8 +37,8 @@ struct Image; constexpr Common::SlotId NULL_IMAGE_VIEW_ID{0}; struct ImageView { - explicit ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info, Image& image, - ImageId image_id, std::optional usage_override = {}); + ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info, Image& image, + ImageId image_id); ~ImageView(); ImageView(const ImageView&) = delete; diff --git a/src/video_core/texture_cache/sampler.cpp b/src/video_core/texture_cache/sampler.cpp index 19c92712c..179dd6646 100644 --- a/src/video_core/texture_cache/sampler.cpp +++ b/src/video_core/texture_cache/sampler.cpp @@ -16,7 +16,7 @@ Sampler::Sampler(const Vulkan::Instance& instance, const AmdGpu::Sampler& sample .addressModeU = LiverpoolToVK::ClampMode(sampler.clamp_x), .addressModeV = LiverpoolToVK::ClampMode(sampler.clamp_y), .addressModeW = LiverpoolToVK::ClampMode(sampler.clamp_z), - .mipLodBias = sampler.LodBias(), + .mipLodBias = std::min(sampler.LodBias(), instance.MaxSamplerLodBias()), .compareEnable = sampler.depth_compare_func != AmdGpu::DepthCompare::Never, .compareOp = LiverpoolToVK::DepthCompare(sampler.depth_compare_func), .minLod = sampler.MinLod(), @@ -24,7 +24,10 @@ Sampler::Sampler(const Vulkan::Instance& instance, const AmdGpu::Sampler& sample .borderColor = LiverpoolToVK::BorderColor(sampler.border_color_type), .unnormalizedCoordinates = bool(sampler.force_unnormalized), }; - handle = instance.GetDevice().createSamplerUnique(sampler_ci); + auto [sampler_result, smplr] = instance.GetDevice().createSamplerUnique(sampler_ci); + ASSERT_MSG(sampler_result == vk::Result::eSuccess, "Failed to create sampler: {}", + vk::to_string(sampler_result)); + handle = std::move(smplr); } Sampler::~Sampler() = default; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 6bc893b09..00e6bea82 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -1,45 +1,68 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include "common/assert.h" #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/page_manager.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/texture_cache/host_compatibility.h" #include "video_core/texture_cache/texture_cache.h" #include "video_core/texture_cache/tile_manager.h" namespace VideoCore { static constexpr u64 PageShift = 12; +static constexpr u64 NumFramesBeforeRemoval = 32; TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, BufferCache& buffer_cache_, PageManager& tracker_) : instance{instance_}, scheduler{scheduler_}, buffer_cache{buffer_cache_}, tracker{tracker_}, tile_manager{instance, scheduler} { - ImageInfo info; + ImageInfo info{}; info.pixel_format = vk::Format::eR8G8B8A8Unorm; info.type = vk::ImageType::e2D; + info.tiling_idx = u32(AmdGpu::TilingMode::Texture_MicroTiled); + info.num_bits = 32; + info.UpdateSize(); const ImageId null_id = slot_images.insert(instance, scheduler, info); ASSERT(null_id.index == 0); + const vk::Image& null_image = slot_images[null_id].image; + Vulkan::SetObjectName(instance.GetDevice(), null_image, "Null Image"); + slot_images[null_id].flags = ImageFlagBits::Tracked; ImageViewInfo view_info; - void(slot_image_views.insert(instance, view_info, slot_images[null_id], null_id)); + const auto null_view_id = + slot_image_views.insert(instance, view_info, slot_images[null_id], null_id); + ASSERT(null_view_id.index == 0); + const vk::ImageView& null_image_view = slot_image_views[null_view_id].image_view.get(); + Vulkan::SetObjectName(instance.GetDevice(), null_image_view, "Null Image View"); } TextureCache::~TextureCache() = default; -void TextureCache::InvalidateMemory(VAddr address, size_t size, bool from_compute) { - std::unique_lock lock{mutex}; +void TextureCache::InvalidateMemory(VAddr address, size_t size) { + std::scoped_lock lock{mutex}; ForEachImageInRegion(address, size, [&](ImageId image_id, Image& image) { - if (from_compute && !image.Overlaps(address, size)) { + // Ensure image is reuploaded when accessed again. + image.flags |= ImageFlagBits::CpuDirty; + // Untrack image, so the range is unprotected and the guest can write freely. + UntrackImage(image_id); + }); +} + +void TextureCache::InvalidateMemoryFromGPU(VAddr address, size_t max_size) { + std::scoped_lock lock{mutex}; + ForEachImageInRegion(address, max_size, [&](ImageId image_id, Image& image) { + // Only consider images that match base address. + // TODO: Maybe also consider subresources + if (image.info.guest_address != address) { return; } // Ensure image is reuploaded when accessed again. - image.flags |= ImageFlagBits::CpuModified; - // Untrack image, so the range is unprotected and the guest can write freely. - UntrackImage(image, image_id); + image.flags |= ImageFlagBits::GpuDirty; }); } @@ -49,46 +72,190 @@ void TextureCache::UnmapMemory(VAddr cpu_addr, size_t size) { boost::container::small_vector deleted_images; ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); for (const ImageId id : deleted_images) { - Image& image = slot_images[id]; - if (True(image.flags & ImageFlagBits::Tracked)) { - UntrackImage(image, id); - } // TODO: Download image data back to host. - UnregisterImage(id); - DeleteImage(id); + FreeImage(id); } } -ImageId TextureCache::FindImage(const ImageInfo& info) { +ImageId TextureCache::ResolveDepthOverlap(const ImageInfo& requested_info, ImageId cache_image_id) { + const auto& cache_info = slot_images[cache_image_id].info; + + const bool was_bound_as_texture = + !cache_info.usage.depth_target && (cache_info.usage.texture || cache_info.usage.storage); + if (requested_info.usage.depth_target && was_bound_as_texture) { + auto new_image_id = slot_images.insert(instance, scheduler, requested_info); + RegisterImage(new_image_id); + + // TODO: perform a depth copy here + + FreeImage(cache_image_id); + return new_image_id; + } + + const bool should_bind_as_texture = + !requested_info.usage.depth_target && + (requested_info.usage.texture || requested_info.usage.storage); + if (cache_info.usage.depth_target && should_bind_as_texture) { + if (cache_info.resources == requested_info.resources) { + return cache_image_id; + } else { + UNREACHABLE(); + } + } + + return {}; +} + +ImageId TextureCache::ResolveOverlap(const ImageInfo& image_info, ImageId cache_image_id, + ImageId merged_image_id) { + auto& tex_cache_image = slot_images[cache_image_id]; + + if (image_info.guest_address == tex_cache_image.info.guest_address) { // Equal address + if (image_info.size != tex_cache_image.info.size) { + // Very likely this kind of overlap is caused by allocation from a pool. We can assume + // it is safe to delete the image if it wasn't accessed in some amount of frames. + if (scheduler.CurrentTick() - tex_cache_image.tick_accessed_last > + NumFramesBeforeRemoval) { + + FreeImage(cache_image_id); + } + return merged_image_id; + } + + if (auto depth_image_id = ResolveDepthOverlap(image_info, cache_image_id)) { + return depth_image_id; + } + + if (image_info.pixel_format != tex_cache_image.info.pixel_format || + image_info.guest_size_bytes <= tex_cache_image.info.guest_size_bytes) { + auto result_id = merged_image_id ? merged_image_id : cache_image_id; + const auto& result_image = slot_images[result_id]; + return IsVulkanFormatCompatible(image_info.pixel_format, result_image.info.pixel_format) + ? result_id + : ImageId{}; + } + + ImageId new_image_id{}; + if (image_info.type == tex_cache_image.info.type) { + new_image_id = ExpandImage(image_info, cache_image_id); + } else { + UNREACHABLE(); + } + return new_image_id; + } + + // Right overlap, the image requested is a possible subresource of the image from cache. + if (image_info.guest_address > tex_cache_image.info.guest_address) { + // Should be handled by view. No additional actions needed. + } else { + // Left overlap, the image from cache is a possible subresource of the image requested + if (!merged_image_id) { + // We need to have a larger, already allocated image to copy this one into + return {}; + } + + if (tex_cache_image.info.IsMipOf(image_info)) { + tex_cache_image.Transit(vk::ImageLayout::eTransferSrcOptimal, + vk::AccessFlagBits2::eTransferRead, {}); + + const auto num_mips_to_copy = tex_cache_image.info.resources.levels; + ASSERT(num_mips_to_copy == 1); + + auto& merged_image = slot_images[merged_image_id]; + merged_image.CopyMip(tex_cache_image, image_info.resources.levels - 1); + + FreeImage(cache_image_id); + } + } + + return merged_image_id; +} + +ImageId TextureCache::ExpandImage(const ImageInfo& info, ImageId image_id) { + const auto new_image_id = slot_images.insert(instance, scheduler, info); + RegisterImage(new_image_id); + + auto& src_image = slot_images[image_id]; + auto& new_image = slot_images[new_image_id]; + + src_image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {}); + new_image.CopyImage(src_image); + + if (True(src_image.flags & ImageFlagBits::Bound)) { + src_image.flags |= ImageFlagBits::NeedsRebind; + } + + FreeImage(image_id); + + TrackImage(new_image_id); + new_image.flags &= ~ImageFlagBits::Dirty; + return new_image_id; +} + +ImageId TextureCache::FindImage(const ImageInfo& info, FindFlags flags) { if (info.guest_address == 0) [[unlikely]] { return NULL_IMAGE_VIEW_ID; } - std::unique_lock lock{mutex}; - boost::container::small_vector image_ids; - ForEachImageInRegion( - info.guest_address, info.guest_size_bytes, [&](ImageId image_id, Image& image) { - // Address and width must match. - if (image.cpu_addr != info.guest_address || image.info.size.width != info.size.width) { - return; - } - if (info.IsDepthStencil() != image.info.IsDepthStencil() && - info.pixel_format != vk::Format::eR32Sfloat) { - return; - } - image_ids.push_back(image_id); - }); - - // ASSERT_MSG(image_ids.size() <= 1, "Overlapping images not allowed!"); + std::scoped_lock lock{mutex}; + boost::container::small_vector image_ids; + ForEachImageInRegion(info.guest_address, info.guest_size_bytes, + [&](ImageId image_id, Image& image) { image_ids.push_back(image_id); }); ImageId image_id{}; - if (image_ids.empty()) { + + // Check for a perfect match first + for (const auto& cache_id : image_ids) { + auto& cache_image = slot_images[cache_id]; + 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) { + continue; + } + if (False(flags & FindFlags::RelaxDim) && cache_image.info.size != info.size) { + continue; + } + if (False(flags & FindFlags::RelaxFmt) && + !IsVulkanFormatCompatible(info.pixel_format, cache_image.info.pixel_format)) { + continue; + } + ASSERT(cache_image.info.type == info.type || True(flags & FindFlags::RelaxFmt)); + image_id = cache_id; + } + + if (True(flags & FindFlags::NoCreate) && !image_id) { + return {}; + } + + // Try to resolve overlaps (if any) + if (!image_id) { + for (const auto& cache_id : image_ids) { + const auto& merged_info = image_id ? slot_images[image_id].info : info; + image_id = ResolveOverlap(merged_info, cache_id, image_id); + } + } + + if (image_id) { + Image& image_resoved = slot_images[image_id]; + + if (image_resoved.info.resources < info.resources) { + // The image was clearly picked up wrong. + FreeImage(image_id); + image_id = {}; + LOG_WARNING(Render_Vulkan, "Image overlap resolve failed"); + } + } + // Create and register a new image + if (!image_id) { image_id = slot_images.insert(instance, scheduler, info); RegisterImage(image_id); - } else { - image_id = image_ids[image_ids.size() > 1 ? 1 : 0]; } + Image& image = slot_images[image_id]; + image.tick_accessed_last = scheduler.CurrentTick(); + return image_id; } @@ -98,64 +265,31 @@ ImageView& TextureCache::RegisterImageView(ImageId image_id, const ImageViewInfo return slot_image_views[view_id]; } - // All tiled images are created with storage usage flag. This makes set of formats (e.g. sRGB) - // impossible to use. However, during view creation, if an image isn't used as storage we can - // temporary remove its storage bit. - std::optional usage_override; - if (!image.info.usage.storage) { - usage_override = image.usage & ~vk::ImageUsageFlagBits::eStorage; - } - - const ImageViewId view_id = - slot_image_views.insert(instance, view_info, image, image_id, usage_override); + const ImageViewId view_id = slot_image_views.insert(instance, view_info, image, image_id); image.image_view_infos.emplace_back(view_info); image.image_view_ids.emplace_back(view_id); return slot_image_views[view_id]; } -ImageView& TextureCache::FindTexture(const ImageInfo& info, const ImageViewInfo& view_info) { - const ImageId image_id = FindImage(info); - UpdateImage(image_id); +ImageView& TextureCache::FindTexture(ImageId image_id, const ImageViewInfo& view_info) { Image& image = slot_images[image_id]; + UpdateImage(image_id); auto& usage = image.info.usage; if (view_info.is_storage) { image.Transit(vk::ImageLayout::eGeneral, - vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite); + vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eShaderWrite, + view_info.range); usage.storage = true; } else { const auto new_layout = image.info.IsDepthStencil() ? vk::ImageLayout::eDepthStencilReadOnlyOptimal : vk::ImageLayout::eShaderReadOnlyOptimal; - image.Transit(new_layout, vk::AccessFlagBits::eShaderRead); + image.Transit(new_layout, vk::AccessFlagBits2::eShaderRead, view_info.range); usage.texture = true; } - // These changes are temporary and should be removed once texture cache will handle subresources - // merging - auto view_info_tmp = view_info; - if (view_info_tmp.range.base.level > image.info.resources.levels - 1 || - view_info_tmp.range.base.layer > image.info.resources.layers - 1 || - view_info_tmp.range.extent.levels > image.info.resources.levels || - view_info_tmp.range.extent.layers > image.info.resources.layers) { - - LOG_DEBUG(Render_Vulkan, - "Subresource range ({}~{},{}~{}) exceeds base image extents ({},{})", - view_info_tmp.range.base.level, view_info_tmp.range.extent.levels, - view_info_tmp.range.base.layer, view_info_tmp.range.extent.layers, - image.info.resources.levels, image.info.resources.layers); - - view_info_tmp.range.base.level = - std::min(view_info_tmp.range.base.level, image.info.resources.levels - 1); - view_info_tmp.range.base.layer = - std::min(view_info_tmp.range.base.layer, image.info.resources.layers - 1); - view_info_tmp.range.extent.levels = - std::min(view_info_tmp.range.extent.levels, image.info.resources.levels); - view_info_tmp.range.extent.layers = - std::min(view_info_tmp.range.extent.layers, image.info.resources.layers); - } - - return RegisterImageView(image_id, view_info_tmp); + return RegisterImageView(image_id, view_info); } ImageView& TextureCache::FindRenderTarget(const ImageInfo& image_info, @@ -166,8 +300,9 @@ ImageView& TextureCache::FindRenderTarget(const ImageInfo& image_info, UpdateImage(image_id); image.Transit(vk::ImageLayout::eColorAttachmentOptimal, - vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eColorAttachmentRead); + vk::AccessFlagBits2::eColorAttachmentWrite | + vk::AccessFlagBits2::eColorAttachmentRead, + view_info.range); // Register meta data for this color buffer if (!(image.flags & ImageFlagBits::MetaRegistered)) { @@ -199,12 +334,23 @@ ImageView& TextureCache::FindDepthTarget(const ImageInfo& image_info, const ImageId image_id = FindImage(image_info); Image& image = slot_images[image_id]; image.flags |= ImageFlagBits::GpuModified; - image.flags &= ~ImageFlagBits::CpuModified; + image.flags &= ~ImageFlagBits::Dirty; + image.aspect_mask = vk::ImageAspectFlagBits::eDepth; - const auto new_layout = view_info.is_storage ? vk::ImageLayout::eDepthStencilAttachmentOptimal - : vk::ImageLayout::eDepthStencilReadOnlyOptimal; - image.Transit(new_layout, vk::AccessFlagBits::eDepthStencilAttachmentWrite | - vk::AccessFlagBits::eDepthStencilAttachmentRead); + const bool has_stencil = image_info.usage.stencil; + if (has_stencil) { + image.aspect_mask |= vk::ImageAspectFlagBits::eStencil; + } + + const auto new_layout = view_info.is_storage + ? has_stencil ? vk::ImageLayout::eDepthStencilAttachmentOptimal + : vk::ImageLayout::eDepthAttachmentOptimal + : has_stencil ? vk::ImageLayout::eDepthStencilReadOnlyOptimal + : vk::ImageLayout::eDepthReadOnlyOptimal; + image.Transit(new_layout, + vk::AccessFlagBits2::eDepthStencilAttachmentWrite | + vk::AccessFlagBits2::eDepthStencilAttachmentRead, + view_info.range); // Register meta data for this depth buffer if (!(image.flags & ImageFlagBits::MetaRegistered)) { @@ -219,13 +365,15 @@ ImageView& TextureCache::FindDepthTarget(const ImageInfo& image_info, // Update tracked image usage image.info.usage.depth_target = true; + image.info.usage.stencil = has_stencil; return RegisterImageView(image_id, view_info); } void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_scheduler /*= nullptr*/) { - // Mark image as validated. - image.flags &= ~ImageFlagBits::CpuModified; + if (False(image.flags & ImageFlagBits::Dirty)) { + return; + } const auto& num_layers = image.info.resources.layers; const auto& num_mips = image.info.resources.levels; @@ -239,9 +387,10 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u; const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m]; - // Protect GPU modified resources from accidental reuploads. - if (True(image.flags & ImageFlagBits::GpuModified) && - !buffer_cache.IsRegionGpuModified(image.info.guest_address + mip_ofs, mip_size)) { + // Protect GPU modified resources from accidental CPU reuploads. + const bool is_gpu_modified = True(image.flags & ImageFlagBits::GpuModified); + const bool is_gpu_dirty = True(image.flags & ImageFlagBits::GpuDirty); + if (is_gpu_modified && !is_gpu_dirty) { const u8* addr = std::bit_cast(image.info.guest_address); const u64 hash = XXH3_64bits(addr + mip_ofs, mip_size); if (image.mip_hashes[m] == hash) { @@ -255,7 +404,7 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule .bufferRowLength = static_cast(mip_pitch), .bufferImageHeight = static_cast(mip_height), .imageSubresource{ - .aspectMask = vk::ImageAspectFlagBits::eColor, + .aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil, .mipLevel = m, .baseArrayLayer = 0, .layerCount = num_layers, @@ -273,25 +422,31 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule sched_ptr->EndRendering(); const auto cmdbuf = sched_ptr->CommandBuffer(); - image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits::eTransferWrite, cmdbuf); + 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; - vk::Buffer buffer{}; - u32 offset{}; - if (auto upload_buffer = tile_manager.TryDetile(image); upload_buffer) { - buffer = *upload_buffer; - } else { - const auto [vk_buffer, buf_offset] = buffer_cache.ObtainTempBuffer(image_addr, image_size); - buffer = vk_buffer->Handle(); - offset = buf_offset; + const auto [vk_buffer, buf_offset] = buffer_cache.ObtainTempBuffer(image_addr, image_size); + // 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{ + .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); for (auto& copy : image_copy) { copy.bufferOffset += offset; } cmdbuf.copyBufferToImage(buffer, image.image, vk::ImageLayout::eTransferDstOptimal, image_copy); + image.flags &= ~ImageFlagBits::Dirty; } vk::Sampler TextureCache::GetSampler(const AmdGpu::Sampler& sampler) { @@ -328,10 +483,10 @@ void TextureCache::UnregisterImage(ImageId image_id) { } image_ids.erase(vector_it); }); - slot_images.erase(image_id); } -void TextureCache::TrackImage(Image& image, ImageId image_id) { +void TextureCache::TrackImage(ImageId image_id) { + auto& image = slot_images[image_id]; if (True(image.flags & ImageFlagBits::Tracked)) { return; } @@ -339,7 +494,8 @@ void TextureCache::TrackImage(Image& image, ImageId image_id) { tracker.UpdatePagesCachedCount(image.cpu_addr, image.info.guest_size_bytes, 1); } -void TextureCache::UntrackImage(Image& image, ImageId image_id) { +void TextureCache::UntrackImage(ImageId image_id) { + auto& image = slot_images[image_id]; if (False(image.flags & ImageFlagBits::Tracked)) { return; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 137b60141..3bbfd952c 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -23,12 +23,22 @@ namespace VideoCore { class BufferCache; class PageManager; +enum class FindFlags { + NoCreate = 1 << 0, ///< Do not create an image if searching for one fails. + RelaxDim = 1 << 1, ///< Do not check the dimentions of image, only address. + RelaxSize = 1 << 2, ///< Do not check that the size matches exactly. + RelaxFmt = 1 << 3, ///< Do not check that format is compatible. +}; +DECLARE_ENUM_FLAG_OPERATORS(FindFlags) + +static constexpr u32 MaxInvalidateDist = 12_MB; + class TextureCache { struct Traits { using Entry = boost::container::small_vector; static constexpr size_t AddressSpaceBits = 39; static constexpr size_t FirstLevelBits = 9; - static constexpr size_t PageBits = 22; + static constexpr size_t PageBits = 20; }; using PageTable = MultiLevelPageTable; @@ -38,17 +48,19 @@ public: ~TextureCache(); /// Invalidates any image in the logical page range. - void InvalidateMemory(VAddr address, size_t size, bool from_compute = false); + void InvalidateMemory(VAddr address, size_t size); + + /// Marks an image as dirty if it exists at the provided address. + void InvalidateMemoryFromGPU(VAddr address, size_t max_size); /// Evicts any images that overlap the unmapped range. void UnmapMemory(VAddr cpu_addr, size_t size); /// Retrieves the image handle of the image with the provided attributes. - [[nodiscard]] ImageId FindImage(const ImageInfo& info); + [[nodiscard]] ImageId FindImage(const ImageInfo& info, FindFlags flags = {}); - /// Retrieves an image view with the properties of the specified image descriptor. - [[nodiscard]] ImageView& FindTexture(const ImageInfo& image_info, - const ImageViewInfo& view_info); + /// Retrieves an image view with the properties of the specified image id. + [[nodiscard]] ImageView& FindTexture(ImageId image_id, const ImageViewInfo& view_info); /// Retrieves the render target with specified properties [[nodiscard]] ImageView& FindRenderTarget(const ImageInfo& image_info, @@ -61,13 +73,19 @@ public: /// Updates image contents if it was modified by CPU. void UpdateImage(ImageId image_id, Vulkan::Scheduler* custom_scheduler = nullptr) { Image& image = slot_images[image_id]; - if (False(image.flags & ImageFlagBits::CpuModified)) { - return; - } + TrackImage(image_id); RefreshImage(image, custom_scheduler); - TrackImage(image, image_id); } + [[nodiscard]] ImageId ResolveOverlap(const ImageInfo& info, ImageId cache_img_id, + ImageId merged_image_id); + + /// Resolves depth overlap and either re-creates the image or returns existing one + [[nodiscard]] ImageId ResolveDepthOverlap(const ImageInfo& requested_info, + ImageId cache_img_id); + + [[nodiscard]] ImageId ExpandImage(const ImageInfo& info, ImageId image_id); + /// Reuploads image contents. void RefreshImage(Image& image, Vulkan::Scheduler* custom_scheduler = nullptr); @@ -79,6 +97,11 @@ public: return slot_images[id]; } + /// Retrieves the image view with the specified id. + [[nodiscard]] ImageView& GetImageView(ImageId id) { + return slot_image_views[id]; + } + bool IsMeta(VAddr address) const { return surface_metas.contains(address); } @@ -100,25 +123,6 @@ public: return false; } -private: - ImageView& RegisterImageView(ImageId image_id, const ImageViewInfo& view_info); - - /// Iterate over all page indices in a range - template - static void ForEachPage(PAddr addr, size_t size, Func&& func) { - static constexpr bool RETURNS_BOOL = std::is_same_v, bool>; - const u64 page_end = (addr + size - 1) >> Traits::PageBits; - for (u64 page = addr >> Traits::PageBits; page <= page_end; ++page) { - if constexpr (RETURNS_BOOL) { - if (func(page)) { - break; - } - } else { - func(page); - } - } - } - template void ForEachImageInRegion(VAddr cpu_addr, size_t size, Func&& func) { using FuncReturn = typename std::invoke_result::type; @@ -138,6 +142,9 @@ private: if (image.flags & ImageFlagBits::Picked) { continue; } + if (!image.Overlaps(cpu_addr, size)) { + continue; + } image.flags |= ImageFlagBits::Picked; images.push_back(image_id); if constexpr (BOOL_BREAK) { @@ -157,6 +164,26 @@ private: } } +private: + /// Iterate over all page indices in a range + template + static void ForEachPage(PAddr addr, size_t size, Func&& func) { + static constexpr bool RETURNS_BOOL = std::is_same_v, bool>; + const u64 page_end = (addr + size - 1) >> Traits::PageBits; + for (u64 page = addr >> Traits::PageBits; page <= page_end; ++page) { + if constexpr (RETURNS_BOOL) { + if (func(page)) { + break; + } + } else { + func(page); + } + } + } + + /// Registers an image view for provided image + ImageView& RegisterImageView(ImageId image_id, const ImageViewInfo& view_info); + /// Create an image from the given parameters [[nodiscard]] ImageId InsertImage(const ImageInfo& info, VAddr cpu_addr); @@ -167,14 +194,20 @@ private: void UnregisterImage(ImageId image); /// Track CPU reads and writes for image - void TrackImage(Image& image, ImageId image_id); + void TrackImage(ImageId image_id); /// Stop tracking CPU reads and writes for image - void UntrackImage(Image& image, ImageId image_id); + void UntrackImage(ImageId image_id); /// Removes the image and any views/surface metas that reference it. void DeleteImage(ImageId image_id); + void FreeImage(ImageId image_id) { + UntrackImage(image_id); + UnregisterImage(image_id); + DeleteImage(image_id); + } + private: const Vulkan::Instance& instance; Vulkan::Scheduler& scheduler; diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index 6bb104a66..c4f24420d 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -187,6 +187,7 @@ vk::Format DemoteImageFormatForDetiling(vk::Format format) { case vk::Format::eR32Uint: case vk::Format::eR16G16Sfloat: case vk::Format::eR16G16Unorm: + case vk::Format::eB10G11R11UfloatPack32: return vk::Format::eR32Uint; case vk::Format::eBc1RgbaSrgbBlock: case vk::Format::eBc1RgbaUnormBlock: @@ -202,6 +203,7 @@ vk::Format DemoteImageFormatForDetiling(vk::Format format) { case vk::Format::eBc3SrgbBlock: case vk::Format::eBc3UnormBlock: case vk::Format::eBc5UnormBlock: + case vk::Format::eBc5SnormBlock: case vk::Format::eBc7SrgbBlock: case vk::Format::eBc7UnormBlock: case vk::Format::eBc6HUfloatBlock: @@ -249,17 +251,46 @@ struct DetilerParams { u32 sizes[14]; }; -static constexpr size_t StreamBufferSize = 1_GB; - TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler) - : instance{instance}, scheduler{scheduler}, - stream_buffer{instance, scheduler, MemoryUsage::Upload, StreamBufferSize} { + : 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, }; + boost::container::static_vector bindings{ + { + .binding = 0, + .descriptorType = vk::DescriptorType::eStorageBuffer, + .descriptorCount = 1, + .stageFlags = vk::ShaderStageFlagBits::eCompute, + }, + { + .binding = 1, + .descriptorType = vk::DescriptorType::eStorageBuffer, + .descriptorCount = 1, + .stageFlags = vk::ShaderStageFlagBits::eCompute, + }, + }; + + const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = { + .flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR, + .bindingCount = static_cast(bindings.size()), + .pBindings = bindings.data(), + }; + auto desc_layout_result = instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci); + ASSERT_MSG(desc_layout_result.result == vk::Result::eSuccess, + "Failed to create descriptor set layout: {}", + vk::to_string(desc_layout_result.result)); + desc_layout = std::move(desc_layout_result.value); + + const vk::PushConstantRange push_constants = { + .stageFlags = vk::ShaderStageFlagBits::eCompute, + .offset = 0, + .size = sizeof(DetilerParams), + }; + for (int pl_id = 0; pl_id < DetilerType::Max; ++pl_id) { auto& ctx = detilers[pl_id]; @@ -276,35 +307,6 @@ TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& sc .pName = "main", }; - boost::container::static_vector bindings{ - { - .binding = 0, - .descriptorType = vk::DescriptorType::eStorageBuffer, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eCompute, - }, - { - .binding = 1, - .descriptorType = vk::DescriptorType::eStorageBuffer, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eCompute, - }, - }; - - const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = { - .flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR, - .bindingCount = static_cast(bindings.size()), - .pBindings = bindings.data(), - }; - static auto desc_layout = - instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci); - - const vk::PushConstantRange push_constants = { - .stageFlags = vk::ShaderStageFlagBits::eCompute, - .offset = 0, - .size = sizeof(DetilerParams), - }; - const vk::DescriptorSetLayout set_layout = *desc_layout; const vk::PipelineLayoutCreateInfo layout_info = { .setLayoutCount = 1U, @@ -312,7 +314,10 @@ TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& sc .pushConstantRangeCount = 1, .pPushConstantRanges = &push_constants, }; - ctx.pl_layout = instance.GetDevice().createPipelineLayoutUnique(layout_info); + auto [layout_result, layout] = instance.GetDevice().createPipelineLayoutUnique(layout_info); + ASSERT_MSG(layout_result == vk::Result::eSuccess, "Failed to create pipeline layout: {}", + vk::to_string(layout_result)); + ctx.pl_layout = std::move(layout); const vk::ComputePipelineCreateInfo compute_pipeline_ci = { .stage = shader_ci, @@ -342,12 +347,6 @@ TileManager::ScratchBuffer TileManager::AllocBuffer(u32 size, bool is_storage /* .usage = usage, }; -#ifdef __APPLE__ - // Fix for detiler artifacts on macOS - const bool is_large_buffer = true; -#else - const bool is_large_buffer = size > 128_MB; -#endif VmaAllocationCreateInfo alloc_info{ .flags = !is_storage ? VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT @@ -381,35 +380,23 @@ void TileManager::FreeBuffer(ScratchBuffer buffer) { vmaDestroyBuffer(instance.GetAllocator(), buffer.first, buffer.second); } -std::optional TileManager::TryDetile(Image& image) { +std::pair TileManager::TryDetile(vk::Buffer in_buffer, u32 in_offset, + Image& image) { if (!image.info.props.is_tiled) { - return std::nullopt; + return {in_buffer, in_offset}; } const auto* detiler = GetDetiler(image); if (!detiler) { - if (image.info.tiling_mode != AmdGpu::TilingMode::Texture_MacroTiled) { + if (image.info.tiling_mode != AmdGpu::TilingMode::Texture_MacroTiled && + image.info.tiling_mode != AmdGpu::TilingMode::Display_MacroTiled) { LOG_ERROR(Render_Vulkan, "Unsupported tiled image: {} ({})", vk::to_string(image.info.pixel_format), NameOf(image.info.tiling_mode)); } - return std::nullopt; + return {in_buffer, in_offset}; } - // Prepare input buffer const u32 image_size = image.info.guest_size_bytes; - const auto [in_buffer, in_offset] = [&] -> std::pair { - // Use stream buffer for smaller textures. - if (image_size <= stream_buffer.GetFreeSize()) { - u32 offset = stream_buffer.Copy(image.info.guest_address, image_size); - return {stream_buffer.Handle(), offset}; - } - // Request temporary host buffer for larger sizes. - auto in_buffer = AllocBuffer(image_size); - const auto addr = reinterpret_cast(image.info.guest_address); - Upload(in_buffer, addr, image_size); - scheduler.DeferOperation([=, this]() { FreeBuffer(in_buffer); }); - return {in_buffer.first, 0}; - }(); // Prepare output buffer auto out_buffer = AllocBuffer(image_size, true); @@ -462,7 +449,6 @@ std::optional TileManager::TryDetile(Image& image) { (m > 0 ? params.sizes[m - 1] : 0); } - auto pitch = image.info.pitch; cmdbuf.pushConstants(*detiler->pl_layout, vk::ShaderStageFlagBits::eCompute, 0u, sizeof(params), ¶ms); @@ -481,7 +467,7 @@ std::optional TileManager::TryDetile(Image& image) { vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, {}, post_barrier, {}); - return {out_buffer.first}; + return {out_buffer.first, 0}; } } // namespace VideoCore diff --git a/src/video_core/texture_cache/tile_manager.h b/src/video_core/texture_cache/tile_manager.h index 00765b1f8..ed7e32c44 100644 --- a/src/video_core/texture_cache/tile_manager.h +++ b/src/video_core/texture_cache/tile_manager.h @@ -39,7 +39,7 @@ public: TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler); ~TileManager(); - std::optional TryDetile(Image& image); + std::pair TryDetile(vk::Buffer in_buffer, u32 in_offset, Image& image); ScratchBuffer AllocBuffer(u32 size, bool is_storage = false); void Upload(ScratchBuffer buffer, const void* data, size_t size); @@ -51,7 +51,7 @@ private: private: const Vulkan::Instance& instance; Vulkan::Scheduler& scheduler; - StreamBuffer stream_buffer; + vk::UniqueDescriptorSetLayout desc_layout; std::array detilers; }; diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 45ffe2511..bcef19355 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h @@ -36,6 +36,8 @@ struct Extent3D { u32 width; u32 height; u32 depth; + + auto operator<=>(const Extent3D&) const = default; }; struct SubresourceLayers {