From bdea21923622a7828dc1a4a0eda57abc7b51d3c6 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 15:53:38 -0700 Subject: [PATCH 01/68] ci: Pin actions to commit hash --- .../workflows/build-xemu-win64-toolchain.yml | 10 ++--- .github/workflows/build.yml | 42 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build-xemu-win64-toolchain.yml b/.github/workflows/build-xemu-win64-toolchain.yml index deefd9c070..972382d5d7 100644 --- a/.github/workflows/build-xemu-win64-toolchain.yml +++ b/.github/workflows/build-xemu-win64-toolchain.yml @@ -21,10 +21,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone tree - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Extract image metadata (tags, labels) id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} labels: | @@ -35,16 +35,16 @@ jobs: type=ref,event=branch type=sha - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3 - name: Login to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: context: ubuntu-win64-cross push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ef3537790..79876dd479 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone tree - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 - name: Install dependencies @@ -50,7 +50,7 @@ jobs: ./scripts/archive-source.sh src.tar gzip -1 src.tar - name: Upload source package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: src.tar.gz path: src.tar.gz @@ -83,14 +83,14 @@ jobs: steps: - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package run: tar xf src.tar.gz - name: Initialize compiler cache id: cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: /tmp/xemu-ccache key: cache-wincross-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }} @@ -111,7 +111,7 @@ jobs: $DOCKER_IMAGE_NAME \ bash -c "ccache -z; ./build.sh -p win64-cross ${{ matrix.build_param }} && ccache -s" - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }} path: dist @@ -140,7 +140,7 @@ jobs: arch: aarch64 steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_name }} @@ -157,7 +157,7 @@ jobs: 7z a -tzip ../dist/${{ matrix.artifact_name }}.zip * "-xr!*.pdb" 7z a -tzip ../dist/${{ matrix.artifact_name }}-pdb.zip "-ir!*.pdb" - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }}-pdb path: dist @@ -196,13 +196,13 @@ jobs: steps: - name: Initialize compiler cache id: cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: /tmp/xemu-ccache key: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }} restore-keys: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}- - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package @@ -266,7 +266,7 @@ jobs: run: | tar -czvf ${{ matrix.artifact_filename }} --transform "s#^dist#xemu#" dist - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_filename }} @@ -300,7 +300,7 @@ jobs: artifact_filename: xemu-macos-arm64-release.zip steps: - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package @@ -319,7 +319,7 @@ jobs: pip install pyyaml requests - name: Initialize compiler, library cache id: cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: | xemu-ccache @@ -339,7 +339,7 @@ jobs: zip -r ../${{ matrix.artifact_filename }} * popd - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_filename }} @@ -353,12 +353,12 @@ jobs: configuration: ["debug", "release"] steps: - name: Download x86_64 build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: xemu-macos-x86_64-${{ matrix.configuration }} path: xemu-macos-x86_64-${{ matrix.configuration }} - name: Download arm64 build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: xemu-macos-arm64-${{ matrix.configuration }} path: xemu-macos-arm64-${{ matrix.configuration }} @@ -382,7 +382,7 @@ jobs: zip -r ../xemu-macos-universal-${{ matrix.configuration }}.zip * popd - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: xemu-macos-universal-${{ matrix.configuration }} path: xemu-macos-universal-${{ matrix.configuration }}.zip @@ -393,7 +393,7 @@ jobs: needs: [Ubuntu, macOSUniversal, Windows, WindowsPdb] steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: path: dist - name: Extract source package @@ -415,7 +415,7 @@ jobs: run: | cp dist/xemu-win-x86_64-release-pdb/xemu-win-x86_64-release.zip dist/xemu-win-x86_64-release-pdb/xemu-win-release.zip - name: Publish release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 with: tag_name: v${{ env.XEMU_VERSION }} name: v${{ env.XEMU_VERSION }} @@ -439,7 +439,7 @@ jobs: dist/xemu-ubuntu-aarch64-debug/xemu/xemu-v${{ env.XEMU_VERSION }}-dbg-aarch64.AppImage dist/xemu-ubuntu-aarch64-release/xemu/xemu-v${{ env.XEMU_VERSION }}-aarch64.AppImage - name: Trigger website update - uses: benc-uk/workflow-dispatch@v1.2.2 + uses: benc-uk/workflow-dispatch@798e70c97009500150087d30d9f11c5444830385 # v1.2.2 with: workflow: build.yml repo: xemu-project/xemu-website @@ -457,7 +457,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package @@ -476,7 +476,7 @@ jobs: -- Matt Borgerson $(date -R)" > debian/changelog popd - name: Deploy source archive to branch - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./src From 9cf1483cd3c0c7b158d926c25935cf8c9b99f8f0 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 15:54:21 -0700 Subject: [PATCH 02/68] ci: Add dependabot config for GH actions update --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..5ace4600a1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" From 8a2bd21bcb6d55493ba5ccd8a75fc16529d5db67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:02:14 -0700 Subject: [PATCH 03/68] ci: bump benc-uk/workflow-dispatch from 1.2.2 to 1.2.4 Bumps [benc-uk/workflow-dispatch](https://github.com/benc-uk/workflow-dispatch) from 1.2.2 to 1.2.4. - [Release notes](https://github.com/benc-uk/workflow-dispatch/releases) - [Commits](https://github.com/benc-uk/workflow-dispatch/compare/798e70c97009500150087d30d9f11c5444830385...e2e5e9a103e331dad343f381a29e654aea3cf8fc) --- updated-dependencies: - dependency-name: benc-uk/workflow-dispatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79876dd479..57ac4664be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -439,7 +439,7 @@ jobs: dist/xemu-ubuntu-aarch64-debug/xemu/xemu-v${{ env.XEMU_VERSION }}-dbg-aarch64.AppImage dist/xemu-ubuntu-aarch64-release/xemu/xemu-v${{ env.XEMU_VERSION }}-aarch64.AppImage - name: Trigger website update - uses: benc-uk/workflow-dispatch@798e70c97009500150087d30d9f11c5444830385 # v1.2.2 + uses: benc-uk/workflow-dispatch@e2e5e9a103e331dad343f381a29e654aea3cf8fc # v1.2.4 with: workflow: build.yml repo: xemu-project/xemu-website From ce7e228afa598653af4e038335730ac2a33aecfa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:02:50 -0700 Subject: [PATCH 04/68] ci: bump actions/setup-python from 5.1.0 to 5.5.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.1.0 to 5.5.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5.1.0...v5.5.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57ac4664be..e844798886 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -305,7 +305,7 @@ jobs: name: src.tar.gz - name: Extract source package run: tar xf src.tar.gz - - uses: actions/setup-python@v5.1.0 + - uses: actions/setup-python@v5.5.0 with: python-version: '3.12' - name: Install dependencies From 56d643ff2660c2568d87ef0bfaeb773ae51c7f1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:23:09 -0700 Subject: [PATCH 05/68] ci: bump softprops/action-gh-release from 1 to 2 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/de2c0eb89ae2a093876385947365aca7b0e5f844...c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e844798886..7c14ad126d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -415,7 +415,7 @@ jobs: run: | cp dist/xemu-win-x86_64-release-pdb/xemu-win-x86_64-release.zip dist/xemu-win-x86_64-release-pdb/xemu-win-release.zip - name: Publish release - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 + uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 with: tag_name: v${{ env.XEMU_VERSION }} name: v${{ env.XEMU_VERSION }} From 5eeee7cd5c85e9fa412d33c9bac1c458e189a079 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:23:35 -0700 Subject: [PATCH 06/68] ci: bump docker/build-push-action from 5.4.0 to 6.15.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.4.0 to 6.15.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/ca052bb54ab0790a636c9b5f226502c73d547a25...471d1dc4e07e5cdedd4c2171150001c434f0b7a4) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-xemu-win64-toolchain.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-xemu-win64-toolchain.yml b/.github/workflows/build-xemu-win64-toolchain.yml index 972382d5d7..7a521389a5 100644 --- a/.github/workflows/build-xemu-win64-toolchain.yml +++ b/.github/workflows/build-xemu-win64-toolchain.yml @@ -44,7 +44,7 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v5 with: context: ubuntu-win64-cross push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} From a6fbb4957b6fe4f8636c70a5892a87db1a450cb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:25:32 -0700 Subject: [PATCH 07/68] ci: bump peaceiris/actions-gh-pages from 3.9.3 to 4.0.0 Bumps [peaceiris/actions-gh-pages](https://github.com/peaceiris/actions-gh-pages) from 3.9.3 to 4.0.0. - [Release notes](https://github.com/peaceiris/actions-gh-pages/releases) - [Changelog](https://github.com/peaceiris/actions-gh-pages/blob/main/CHANGELOG.md) - [Commits](https://github.com/peaceiris/actions-gh-pages/compare/373f7f263a76c20808c831209c920827a82a2847...4f9cc6602d3f66b9c108549d475ec49e8ef4d45e) --- updated-dependencies: - dependency-name: peaceiris/actions-gh-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c14ad126d..71a2d9a500 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -476,7 +476,7 @@ jobs: -- Matt Borgerson $(date -R)" > debian/changelog popd - name: Deploy source archive to branch - uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # v3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./src From 48c454e1b620ee53a393a5aef311cf9130ab4bc5 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 16:38:17 -0700 Subject: [PATCH 08/68] ci: Add 'ci: ' prefix for dependabot updates --- .github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5ace4600a1..4c39a334be 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,5 @@ updates: directory: "/" schedule: interval: "weekly" + commit-message: + prefix: "ci" From ee5c556ae9306b0e59b26e62be8cbe0a0375645d Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 16:28:20 -0700 Subject: [PATCH 09/68] ubuntu-win64-cross: Bump Vulkan headers --- ubuntu-win64-cross/vulkan-headers.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubuntu-win64-cross/vulkan-headers.mk b/ubuntu-win64-cross/vulkan-headers.mk index 01594d6c3a..3ea0f9d679 100644 --- a/ubuntu-win64-cross/vulkan-headers.mk +++ b/ubuntu-win64-cross/vulkan-headers.mk @@ -2,10 +2,10 @@ PKG := vulkan-headers $(PKG)_WEBSITE := https://github.com/KhronosGroup/Vulkan-Headers $(PKG)_DESCR := Vulkan-Headers $(PKG)_IGNORE := -$(PKG)_VERSION := vulkan-sdk-1.4.304.0 +$(PKG)_VERSION := vulkan-sdk-1.4.309.0 $(PKG)_SUBDIR := Vulkan-Headers-$($(PKG)_VERSION) $(PKG)_FILE := vulkan-headers-$($(PKG)_VERSION).tar.gz -$(PKG)_CHECKSUM := 46f8f5b6384a36c688e0c40d28d534df41d22de406493dfb5c9b7bcc29672613 +$(PKG)_CHECKSUM := 2bc1b4127950badc80212abf1edfa5c3b5032f3425edf37255863ba7592c1969 $(PKG)_URL := https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/$($(PKG)_VERSION).tar.gz $(PKG)_DEPS := cc From 9764c90b21967b8c195ba554a9ea44769768e82a Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 16:31:48 -0700 Subject: [PATCH 10/68] ubuntu-win64-cross: Bump mxe/build-win64-mxe --- ubuntu-win64-cross/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubuntu-win64-cross/Dockerfile b/ubuntu-win64-cross/Dockerfile index 8741b629de..a3aeb78329 100644 --- a/ubuntu-win64-cross/Dockerfile +++ b/ubuntu-win64-cross/Dockerfile @@ -6,10 +6,10 @@ FROM ubuntu:24.04 ENV MXE_PATH=/opt/mxe ENV MXE_REPO=https://github.com/mxe/mxe.git -ENV MXE_VERSION=866492387740cc6580ef516c8a746402be645453 +ENV MXE_VERSION=db7f5247eaab700f28bb9b9433d279e5958f5f01 ENV MXE_LLVM_MINGW_REPO=https://github.com/libvips/build-win64-mxe -ENV MXE_LLVM_MINGW_VERSION=32a2d0ecdfd3ea16bb4a99e333a8d5a3d63be491 +ENV MXE_LLVM_MINGW_VERSION=51fc5884d0c4a3be43a2f09fa36a464885918d3d ENV MXE_LLVM_MINGW_PATH=/opt/build-win64-mxe ARG PLUGIN_DIRS="${MXE_LLVM_MINGW_PATH} ${MXE_LLVM_MINGW_PATH}/build/plugins/llvm-mingw" From cc857adb6cebc8e4a04ba0fe3ac7b4659b71b4d1 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 16:32:05 -0700 Subject: [PATCH 11/68] meson: Bump SPIRV-Reflect --- subprojects/SPIRV-Reflect.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/SPIRV-Reflect.wrap b/subprojects/SPIRV-Reflect.wrap index dded924d1d..bdc1486c5c 100644 --- a/subprojects/SPIRV-Reflect.wrap +++ b/subprojects/SPIRV-Reflect.wrap @@ -1,4 +1,4 @@ [wrap-git] url=https://github.com/KhronosGroup/SPIRV-Reflect -revision=vulkan-sdk-1.4.304.0 +revision=vulkan-sdk-1.4.309.0 depth=1 From 0d06ce860379dfacfdf796d9e011427ded7e8302 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 16:32:13 -0700 Subject: [PATCH 12/68] meson: Bump glslang --- subprojects/glslang.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/glslang.wrap b/subprojects/glslang.wrap index 29b74d8249..9aa182135a 100644 --- a/subprojects/glslang.wrap +++ b/subprojects/glslang.wrap @@ -1,4 +1,4 @@ [wrap-git] url=https://github.com/KhronosGroup/glslang -revision=vulkan-sdk-1.4.304.0 +revision=vulkan-sdk-1.4.309.0 depth=1 From 68b3683f77a109f7e561c8577dc8421758d8ab2a Mon Sep 17 00:00:00 2001 From: antangelo Date: Thu, 27 Mar 2025 21:35:52 -0400 Subject: [PATCH 13/68] ci: Add clang-format lint check Co-authored-by: Matt Borgerson --- .github/workflows/lint.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..20757708b5 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,36 @@ +name: Lint + +on: + pull_request: + paths-ignore: + - '.github/**' + - '!.github/workflows/lint.yml' + - 'README.md' + - 'ubuntu-win64-cross/**' + +jobs: + Check: + name: Check formatting and lints + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Clone tree + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + - name: Check formatting/lints + uses: cpp-linter/cpp-linter-action@832a609fe16e1c98ea764641f07dec5d39db5a56 # v2.13.4 + id: linter + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + version: '16' + style: file + lines-changed-only: true + format-review: true + - name: Report result + if: steps.linter.outputs.checks-failed > 0 + run: exit 1 + From d6a285e173215d4141c238a17ceaa6ed0b28da14 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 19:07:31 -0700 Subject: [PATCH 14/68] ci: Migrate lint to build.yml --- .github/workflows/build.yml | 13 +++++++++++++ .github/workflows/lint.yml | 36 ------------------------------------ 2 files changed, 13 insertions(+), 36 deletions(-) delete mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71a2d9a500..ec0d7f1c5c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -270,6 +270,19 @@ jobs: with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_filename }} + - name: Lint + if: matrix.configuration == 'Debug' && matrix.arch == 'x86_64' + uses: cpp-linter/cpp-linter-action@8ae6cfaea8cc035c6155b5fe79d7991a9bf638af # v2.14.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + version: '18' # clang-format version + repo-root: ${{ github.workspace }}/src + style: file:${{ github.workspace }}/src/.clang-format + database: ${{ github.workspace }}/src/build/compile_commands.json + lines-changed-only: true + format-review: true + passive-reviews: true macOS: name: Build for macOS (${{ matrix.arch }}, ${{ matrix.configuration }}) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 20757708b5..0000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Lint - -on: - pull_request: - paths-ignore: - - '.github/**' - - '!.github/workflows/lint.yml' - - 'README.md' - - 'ubuntu-win64-cross/**' - -jobs: - Check: - name: Check formatting and lints - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - name: Clone tree - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - name: Check formatting/lints - uses: cpp-linter/cpp-linter-action@832a609fe16e1c98ea764641f07dec5d39db5a56 # v2.13.4 - id: linter - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - version: '16' - style: file - lines-changed-only: true - format-review: true - - name: Report result - if: steps.linter.outputs.checks-failed > 0 - run: exit 1 - From 0fe76b531f3394ab857ce7d656ca65caba194b49 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 22:01:25 -0700 Subject: [PATCH 15/68] .gitignore: Unignore .clang-format --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index bfac196fad..e1927ae154 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ .sdk .stgit-* .git-submodule-status -.clang-format .gdb_history cscope.* tags From a830cc45261a936a6dcd84e4cb408d03337758ac Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 20:27:33 -0700 Subject: [PATCH 16/68] xbox: Disable clang-format for deliberately aligned reg defs --- hw/xbox/mcpx/apu_regs.h | 4 ++++ hw/xbox/nv2a/nv2a_regs.h | 4 ++++ hw/xbox/nvnet_regs.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/hw/xbox/mcpx/apu_regs.h b/hw/xbox/mcpx/apu_regs.h index 7488c2e267..2fa71593ae 100644 --- a/hw/xbox/mcpx/apu_regs.h +++ b/hw/xbox/mcpx/apu_regs.h @@ -22,6 +22,8 @@ #ifndef MCPX_APU_REGS_H #define MCPX_APU_REGS_H +// clang-format off + #define NV_PAPU_ISTS 0x00001000 # define NV_PAPU_ISTS_GINTSTS (1 << 0) # define NV_PAPU_ISTS_FETINTSTS (1 << 4) @@ -343,4 +345,6 @@ enum MCPX_HW_NOTIFIER { #define NV1BA0_NOTIFICATION_STATUS_DONE_SUCCESS 0x01 #define NV1BA0_NOTIFICATION_STATUS_IN_PROGRESS 0x80 +// clang-format on + #endif diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 78a9091eb5..fa657bf271 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -32,6 +32,8 @@ (v) |= ((__val) << ctz32(__mask)) & (__mask); \ }) +// clang-format off + #define NV_NUM_BLOCKS 21 #define NV_PMC 0 /* card master control */ #define NV_PBUS 1 /* bus control */ @@ -1463,4 +1465,6 @@ #define NV2A_CUBEMAP_FACE_ALIGNMENT 128 +// clang-format on + #endif diff --git a/hw/xbox/nvnet_regs.h b/hw/xbox/nvnet_regs.h index 992f609937..7a1744f7bc 100644 --- a/hw/xbox/nvnet_regs.h +++ b/hw/xbox/nvnet_regs.h @@ -68,6 +68,8 @@ #ifndef HW_NVNET_REGS_H #define HW_NVNET_REGS_H +// clang-format on + #define DEV_NEED_LASTPACKET1 0x0001 #define DEV_IRQMASK_1 0x0002 #define DEV_IRQMASK_2 0x0004 @@ -291,4 +293,6 @@ enum { #define LPA_LPACK 0x4000 /* Link partner acked us */ #define LPA_NPAGE 0x8000 /* Next page bit */ +// clang-format off + #endif /* HW_NVNET_REGS_H */ From 0e18d11d90d01b78cd6211daffc2abbe264b61b7 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 19:48:08 -0700 Subject: [PATCH 17/68] nv2a: Rename methods.h -> methods.h.inc --- hw/xbox/nv2a/pgraph/{methods.h => methods.h.inc} | 0 hw/xbox/nv2a/pgraph/pgraph.c | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename hw/xbox/nv2a/pgraph/{methods.h => methods.h.inc} (100%) diff --git a/hw/xbox/nv2a/pgraph/methods.h b/hw/xbox/nv2a/pgraph/methods.h.inc similarity index 100% rename from hw/xbox/nv2a/pgraph/methods.h rename to hw/xbox/nv2a/pgraph/methods.h.inc diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index 9db475796e..9d133db139 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -431,7 +431,7 @@ unsigned int nv2a_get_surface_scale_factor(void) #define DEF_METHOD_CASE_4_OFFSET(gclass, name, offset, stride) /* Drop */ #define DEF_METHOD_CASE_4(gclass, name, stride) \ DEF_METHOD_PROTO(gclass, name); -#include "methods.h" +#include "methods.h.inc" #undef DEF_METHOD #undef DEF_METHOD_RANGE #undef DEF_METHOD_CASE_4_OFFSET @@ -485,7 +485,7 @@ static const struct { }, #define DEF_METHOD_CASE_4(gclass, name, stride) \ DEF_METHOD_CASE_4_OFFSET(gclass, name, 0, stride) -#include "methods.h" +#include "methods.h.inc" #undef DEF_METHOD #undef DEF_METHOD_RANGE #undef DEF_METHOD_CASE_4_OFFSET @@ -504,7 +504,7 @@ static const struct { #define DEF_METHOD_CASE_4(gclass, name, stride) \ static const size_t METHOD_RANGE_END_NAME(gclass, name) = \ METHOD_ADDR(gclass, name) + 4*stride; -#include "methods.h" +#include "methods.h.inc" #undef DEF_METHOD #undef DEF_METHOD_RANGE #undef DEF_METHOD_CASE_4_OFFSET From 2d73e8aafe838782649d7f59d6107b9087a6fa78 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 20:33:33 -0700 Subject: [PATCH 18/68] nv2a: Use root-relative paths to reference parent dir headers --- hw/xbox/nv2a/pgraph/pgraph.c | 2 +- hw/xbox/nv2a/pgraph/profile.c | 2 +- hw/xbox/nv2a/pgraph/rdi.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index 9d133db139..5b0bc982d1 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -19,7 +19,7 @@ * License along with this library; if not, see . */ -#include "../nv2a_int.h" +#include "hw/xbox/nv2a/nv2a_int.h" #include "ui/xemu-notifications.h" #include "ui/xemu-settings.h" #include "util.h" diff --git a/hw/xbox/nv2a/pgraph/profile.c b/hw/xbox/nv2a/pgraph/profile.c index 69a1b5bfbd..295042010d 100644 --- a/hw/xbox/nv2a/pgraph/profile.c +++ b/hw/xbox/nv2a/pgraph/profile.c @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ -#include "../nv2a_int.h" +#include "hw/xbox/nv2a/nv2a_int.h" NV2AStats g_nv2a_stats; diff --git a/hw/xbox/nv2a/pgraph/rdi.c b/hw/xbox/nv2a/pgraph/rdi.c index 297c7a67c0..f540b240c6 100644 --- a/hw/xbox/nv2a/pgraph/rdi.c +++ b/hw/xbox/nv2a/pgraph/rdi.c @@ -19,7 +19,7 @@ * License along with this library; if not, see . */ -#include "../nv2a_int.h" +#include "hw/xbox/nv2a/nv2a_int.h" uint32_t pgraph_rdi_read(PGRAPHState *pg, unsigned int select, unsigned int address) From 312bd9457301a12204ce341649bec44bf74dc140 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 22:47:27 -0700 Subject: [PATCH 19/68] mcpx: Move voice_list_regs to apu.c --- hw/xbox/mcpx/apu.c | 8 ++++++++ hw/xbox/mcpx/apu_regs.h | 9 --------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/xbox/mcpx/apu.c b/hw/xbox/mcpx/apu.c index ecace96ce3..d5eec18f40 100644 --- a/hw/xbox/mcpx/apu.c +++ b/hw/xbox/mcpx/apu.c @@ -154,6 +154,14 @@ typedef struct MCPXAPUState { int16_t apu_fifo_output[256][2]; // 1 EP frame (0x400 bytes), 8 buffered } MCPXAPUState; +static const struct { + hwaddr top, current, next; +} voice_list_regs[] = { + { NV_PAPU_TVL2D, NV_PAPU_CVL2D, NV_PAPU_NVL2D }, // 2D + { NV_PAPU_TVL3D, NV_PAPU_CVL3D, NV_PAPU_NVL3D }, // 3D + { NV_PAPU_TVLMP, NV_PAPU_CVLMP, NV_PAPU_NVLMP }, // MP +}; + static MCPXAPUState *g_state; // Used via debug handlers static struct McpxApuDebug g_dbg, g_dbg_cache; static int g_dbg_voice_monitor = -1; diff --git a/hw/xbox/mcpx/apu_regs.h b/hw/xbox/mcpx/apu_regs.h index 2fa71593ae..d745a69354 100644 --- a/hw/xbox/mcpx/apu_regs.h +++ b/hw/xbox/mcpx/apu_regs.h @@ -124,15 +124,6 @@ #define NV_PAPU_EPPMEM 0x0000A000 #define NV_PAPU_EPRST 0x0000FFFC -static const struct { - hwaddr top, current, next; -} voice_list_regs[] = { - {NV_PAPU_TVL2D, NV_PAPU_CVL2D, NV_PAPU_NVL2D}, //2D - {NV_PAPU_TVL3D, NV_PAPU_CVL3D, NV_PAPU_NVL3D}, //3D - {NV_PAPU_TVLMP, NV_PAPU_CVLMP, NV_PAPU_NVLMP}, //MP -}; - - /* audio processor object / front-end messages */ #define NV1BA0_PIO_FREE 0x00000010 #define NV1BA0_PIO_SET_ANTECEDENT_VOICE 0x00000120 From 1586b40b11c8bf5ee561d8fc4dba20f49112b0c4 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 27 Mar 2025 23:35:21 -0700 Subject: [PATCH 20/68] ci: Bump Windows build container --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ec0d7f1c5c..bbe0335c33 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,7 +79,7 @@ jobs: artifact_name: xemu-win-aarch64-release arch: aarch64 env: - DOCKER_IMAGE_NAME: ghcr.io/xemu-project/xemu-win64-toolchain:sha-3bdb9e7 + DOCKER_IMAGE_NAME: ghcr.io/xemu-project/xemu-win64-toolchain:sha-0d06ce8 steps: - name: Download source package From 48d1195c27e09f83f5fb7098ef9dfdb3369f8dac Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Fri, 28 Mar 2025 02:15:00 -0700 Subject: [PATCH 21/68] ci: Drop lint action for now --- .github/workflows/build.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbe0335c33..576d3adf89 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -270,19 +270,6 @@ jobs: with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_filename }} - - name: Lint - if: matrix.configuration == 'Debug' && matrix.arch == 'x86_64' - uses: cpp-linter/cpp-linter-action@8ae6cfaea8cc035c6155b5fe79d7991a9bf638af # v2.14.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - version: '18' # clang-format version - repo-root: ${{ github.workspace }}/src - style: file:${{ github.workspace }}/src/.clang-format - database: ${{ github.workspace }}/src/build/compile_commands.json - lines-changed-only: true - format-review: true - passive-reviews: true macOS: name: Build for macOS (${{ matrix.arch }}, ${{ matrix.configuration }}) From 672e9cd553df9fa4629ecdc49efacf310d9994b0 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Mon, 10 Mar 2025 19:15:03 -0700 Subject: [PATCH 22/68] nv2a: Handle SET_SPECULAR_ENABLE --- hw/xbox/nv2a/nv2a_regs.h | 2 ++ hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 5 +++++ hw/xbox/nv2a/pgraph/glsl/vsh.c | 15 ++++++++++++--- hw/xbox/nv2a/pgraph/methods.h.inc | 1 + hw/xbox/nv2a/pgraph/pgraph.c | 6 +++++- hw/xbox/nv2a/pgraph/shaders.c | 2 ++ hw/xbox/nv2a/pgraph/shaders.h | 1 + 7 files changed, 28 insertions(+), 4 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index fa657bf271..fa62536181 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -314,6 +314,7 @@ # define NV_PGRAPH_CSV0_D_SKIN_4 6 #define NV_PGRAPH_CSV0_C 0x00000FB8 # define NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START 0x0000FF00 +# define NV_PGRAPH_CSV0_C_SPECULAR_ENABLE (1 << 16) # define NV_PGRAPH_CSV0_C_SPECULAR (3 << 19) # define NV_PGRAPH_CSV0_C_DIFFUSE (3 << 21) # define NV_PGRAPH_CSV0_C_AMBIENT (3 << 23) @@ -1015,6 +1016,7 @@ # define NV097_SET_NORMALIZATION_ENABLE 0x000003A4 # define NV097_SET_MATERIAL_EMISSION 0x000003A8 # define NV097_SET_MATERIAL_ALPHA 0x000003B4 +# define NV097_SET_SPECULAR_ENABLE 0x000003B8 # define NV097_SET_LIGHT_ENABLE_MASK 0x000003BC # define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_OFF 0 # define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_INFINITE 1 diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 2412826647..445ce73066 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -383,6 +383,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, " oD0 = diffuse;\n"); mstring_append(body, " oD1 = specular;\n"); } + + if (!state->specular_enable) { + mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); + } + mstring_append(body, " oB0 = backDiffuse;\n"); mstring_append(body, " oB1 = backSpecular;\n"); diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh.c b/hw/xbox/nv2a/pgraph/glsl/vsh.c index d92c8b2fb3..5fff5cf410 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh.c @@ -34,7 +34,6 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) mstring_append_fmt(output, "#version %d\n\n", state->vulkan ? 450 : 400); MString *header = mstring_from_str(""); - MString *uniforms = mstring_from_str(""); const char *u = state->vulkan ? "" : "uniform "; // FIXME: Remove @@ -243,9 +242,7 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) /* Set outputs */ mstring_append(body, "\n" " vtxD0 = clamp(oD0, 0.0, 1.0);\n" - " vtxD1 = clamp(oD1, 0.0, 1.0);\n" " vtxB0 = clamp(oB0, 0.0, 1.0);\n" - " vtxB1 = clamp(oB1, 0.0, 1.0);\n" " vtxFog = oFog.x;\n" " vtxT0 = oT0;\n" " vtxT1 = oT1;\n" @@ -254,6 +251,18 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) " gl_PointSize = oPts.x;\n" ); + if (state->specular_enable) { + mstring_append(body, + " vtxD1 = clamp(oD1, 0.0, 1.0);\n" + " vtxB1 = clamp(oB1, 0.0, 1.0);\n" + ); + } else { + mstring_append(body, + " vtxD1 = vec4(0.0, 0.0, 0.0, 1.0);\n" + " vtxB1 = vec4(0.0, 0.0, 0.0, 1.0);\n" + ); + } + if (state->vulkan) { mstring_append(body, " gl_Position = oPos;\n" diff --git a/hw/xbox/nv2a/pgraph/methods.h.inc b/hw/xbox/nv2a/pgraph/methods.h.inc index 380df07ea5..fd6184426e 100644 --- a/hw/xbox/nv2a/pgraph/methods.h.inc +++ b/hw/xbox/nv2a/pgraph/methods.h.inc @@ -78,6 +78,7 @@ DEF_METHOD(NV097, SET_FRONT_FACE) DEF_METHOD(NV097, SET_NORMALIZATION_ENABLE) DEF_METHOD_RANGE(NV097, SET_MATERIAL_EMISSION, 3) DEF_METHOD(NV097, SET_MATERIAL_ALPHA) +DEF_METHOD(NV097, SET_SPECULAR_ENABLE) DEF_METHOD(NV097, SET_LIGHT_ENABLE_MASK) DEF_METHOD_CASE_4(NV097, SET_TEXGEN_S, 16) DEF_METHOD_CASE_4(NV097, SET_TEXGEN_T, 16) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index 5b0bc982d1..0f17fde184 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -1619,6 +1619,11 @@ DEF_METHOD(NV097, SET_MATERIAL_ALPHA) pg->material_alpha = *(float*)¶meter; } +DEF_METHOD(NV097, SET_SPECULAR_ENABLE) +{ + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_SPECULAR_ENABLE, parameter); +} + DEF_METHOD(NV097, SET_LIGHT_ENABLE_MASK) { PG_SET_MASK(NV_PGRAPH_CSV0_D, NV_PGRAPH_CSV0_D_LIGHTS, parameter); @@ -3022,4 +3027,3 @@ void pgraph_pre_shutdown_wait(NV2AState *d) PGRAPHState *pg = &d->pgraph; pg->renderer->ops.pre_shutdown_wait(d); } - diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c index 6e13f2084c..dce6d05bb3 100644 --- a/hw/xbox/nv2a/pgraph/shaders.c +++ b/hw/xbox/nv2a/pgraph/shaders.c @@ -69,6 +69,8 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg) pgraph_reg_r(pg, NV_PGRAPH_SHADOWCTL), NV_PGRAPH_SHADOWCTL_SHADOW_ZFUNC); state.fixed_function = fixed_function; + state.specular_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), + NV_PGRAPH_CSV0_C_SPECULAR_ENABLE); /* fixed function stuff */ if (fixed_function) { diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/shaders.h index 71febe2e2f..7ff93a6302 100644 --- a/hw/xbox/nv2a/pgraph/shaders.h +++ b/hw/xbox/nv2a/pgraph/shaders.h @@ -83,6 +83,7 @@ typedef struct ShaderState { enum VshLight light[NV2A_MAX_LIGHTS]; bool fixed_function; + bool specular_enable; /* vertex program */ bool vertex_program; From bf51af891d5976b4ad3814d9f54d2733cbe9d121 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:28 -0700 Subject: [PATCH 23/68] mcpx/dsp: Move to a library --- hw/xbox/mcpx/dsp/meson.build | 2 ++ hw/xbox/mcpx/meson.build | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 hw/xbox/mcpx/dsp/meson.build diff --git a/hw/xbox/mcpx/dsp/meson.build b/hw/xbox/mcpx/dsp/meson.build new file mode 100644 index 0000000000..b94537f97c --- /dev/null +++ b/hw/xbox/mcpx/dsp/meson.build @@ -0,0 +1,2 @@ +libdsp = static_library('dsp', files(['dsp.c', 'dsp_cpu.c', 'dsp_dma.c']) + genh) +dsp = declare_dependency(objects: libdsp.extract_all_objects(recursive: false)) diff --git a/hw/xbox/mcpx/meson.build b/hw/xbox/mcpx/meson.build index fd87ef118e..5f6807337d 100644 --- a/hw/xbox/mcpx/meson.build +++ b/hw/xbox/mcpx/meson.build @@ -1,10 +1,9 @@ +subdir('dsp') + mcpx_ss = ss.source_set() -mcpx_ss.add(sdl, libsamplerate, files( +mcpx_ss.add(sdl, libsamplerate, dsp, files( 'apu.c', 'aci.c', - 'dsp/dsp.c', - 'dsp/dsp_cpu.c', - 'dsp/dsp_dma.c', )) specific_ss.add_all(mcpx_ss) \ No newline at end of file From d6a4b4e36a95333d83e0aefcdb0336a3cfa5ab1f Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:28 -0700 Subject: [PATCH 24/68] tests/mcpx/dsp: Add basic test --- tests/meson.build | 1 + tests/xbox/dsp/data/Makefile | 4 ++ tests/xbox/dsp/data/basic | 12 +++++ tests/xbox/dsp/data/basic.a56 | 12 +++++ tests/xbox/dsp/meson.build | 13 ++++++ tests/xbox/dsp/test-dsp.c | 84 +++++++++++++++++++++++++++++++++++ tests/xbox/meson.build | 1 + 7 files changed, 127 insertions(+) create mode 100644 tests/xbox/dsp/data/Makefile create mode 100644 tests/xbox/dsp/data/basic create mode 100644 tests/xbox/dsp/data/basic.a56 create mode 100644 tests/xbox/dsp/meson.build create mode 100644 tests/xbox/dsp/test-dsp.c create mode 100644 tests/xbox/meson.build diff --git a/tests/meson.build b/tests/meson.build index 907a4c1c98..febbe02806 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -86,3 +86,4 @@ subdir('qapi-schema') subdir('qtest') subdir('migration') subdir('functional') +subdir('xbox') diff --git a/tests/xbox/dsp/data/Makefile b/tests/xbox/dsp/data/Makefile new file mode 100644 index 0000000000..8bd271a422 --- /dev/null +++ b/tests/xbox/dsp/data/Makefile @@ -0,0 +1,4 @@ +all: basic + +%: %.a56 + a56 -o $@ $< diff --git a/tests/xbox/dsp/data/basic b/tests/xbox/dsp/data/basic new file mode 100644 index 0000000000..7b11e507ea --- /dev/null +++ b/tests/xbox/dsp/data/basic @@ -0,0 +1,12 @@ +P 0000 0C0040 +P 0040 0AF080 +P 0041 000042 +P 0042 56F400 +P 0043 123456 +P 0044 567000 +P 0045 000003 +P 0046 08F484 +P 0047 000001 +P 0048 0C0042 +I 000040 start +I 000042 mainloop diff --git a/tests/xbox/dsp/data/basic.a56 b/tests/xbox/dsp/data/basic.a56 new file mode 100644 index 0000000000..0be7483dba --- /dev/null +++ b/tests/xbox/dsp/data/basic.a56 @@ -0,0 +1,12 @@ + org p:$0000 + jmp . + */ + +#include "qemu/osdep.h" +#include "hw/xbox/mcpx/dsp/dsp.h" + +static void scratch_rw(void *opaque, uint8_t *ptr, uint32_t addr, size_t len, bool dir) +{ + assert(!"Not implemented"); +} + +static void fifo_rw(void *opaque, uint8_t *ptr, unsigned int index, size_t len, bool dir) +{ + assert(!"Not implemented"); +} + +static void load_prog(DSPState *s, const char *path) +{ + FILE *file = fopen(path, "r"); + assert(file && "Error opening file"); + + char type, line[100], arg1[20], arg2[20]; + int addr, value; + + while (fgets(line, sizeof(line), file)) { + if (sscanf(line, "%c %s %s", &type, arg1, arg2) >= 2) { + switch (type) { + case 'P': + case 'X': + case 'Y': { + assert(sscanf(arg1, "%x", &addr) == 1); + assert(sscanf(arg2, "%x", &value) == 1); + dsp_write_memory(s, type, addr, value); + break; + } + } + } else { + printf("Invalid line: %s\n", line); + assert(0); + } + } + + fclose(file); +} + +static void test_dsp_basic(void) +{ + g_autofree gchar *path = g_test_build_filename(G_TEST_DIST, "data", "basic", NULL); + + DSPState *s = dsp_init(NULL, scratch_rw, fifo_rw); + + load_prog(s, path); + dsp_run(s, 1000); + + uint32_t v = dsp_read_memory(s, 'X', 3); + g_assert_cmphex(v, ==, 0x123456); + + dsp_destroy(s); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/basic", test_dsp_basic); + + return g_test_run(); +} diff --git a/tests/xbox/meson.build b/tests/xbox/meson.build new file mode 100644 index 0000000000..e836218210 --- /dev/null +++ b/tests/xbox/meson.build @@ -0,0 +1 @@ +subdir('dsp') From 9af3c1a0057cfc0507374a3434ae8cf6e5373d9d Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:28 -0700 Subject: [PATCH 25/68] mcpx/dsp: Add missing copyright --- hw/xbox/mcpx/dsp/dsp.c | 1 + hw/xbox/mcpx/dsp/dsp_cpu.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index d1e3b2a9b3..a86d9f314b 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -2,6 +2,7 @@ * MCPX DSP emulator * * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson * * Adapted from Hatari DSP M56001 emulation * (C) 2001-2008 ARAnyM developer team diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 874dd494ce..b31172fd60 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -2,6 +2,7 @@ * DSP56300 emulator * * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson * * Adapted from Hatari DSP M56001 emulation * (C) 2003-2008 ARAnyM developer team From 89f98947f62cdc476cf1a48197013959e316f090 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:28 -0700 Subject: [PATCH 26/68] mcpx/dsp: Fix dprintf use --- hw/xbox/mcpx/dsp/dsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index a86d9f314b..09d39e2a14 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -202,7 +202,7 @@ void dsp_bootstrap(DSPState* dsp) (uint8_t*)dsp->core.pram, 0, 0x800*4, false); for (int i = 0; i < 0x800; i++) { if (dsp->core.pram[i] & 0xff000000) { - DPRINTF(stderr, "Bootstrap %04x: %08x\n", i, dsp->core.pram[i]); + DPRINTF("Bootstrap %04x: %08x\n", i, dsp->core.pram[i]); dsp->core.pram[i] &= 0x00ffffff; } } From 115456f2557d964213e3953e8d3b5d378b4bc37e Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:28 -0700 Subject: [PATCH 27/68] mcpx/dsp: Bring back disassembly --- hw/xbox/mcpx/dsp/dsp_cpu.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index b31172fd60..89a3555899 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -595,25 +595,16 @@ static void disasm_reg_compare(dsp_core_t* dsp) static const char* disasm_get_instruction_text(dsp_core_t* dsp) { - // const int len = sizeof(dsp->disasm_str_instr); - // uint64_t count, cycles; - // uint16_t cycle_diff; - // float percentage; - // int offset; + const int len = sizeof(dsp->disasm_str_instr); if (dsp->disasm_is_looping) { dsp->disasm_str_instr2[0] = 0; } - // if (dsp->disasm_cur_inst_len == 1) { - // offset = sprintf(dsp->disasm_str_instr2, "p:%04x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, dsp->instr_cycle, len, dsp->disasm_str_instr); - // } else { - // offset = sprintf(dsp->disasm_str_instr2, "p:%04x %06x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, read_memory_p(dsp, dsp->disasm_prev_inst_pc + 1), dsp->instr_cycle, len, dsp->disasm_str_instr); - // } - // if (offset > 2 && Profile_DspAddressData(dsp->disasm_prev_inst_pc, &percentage, &count, &cycles, &cycle_diff)) { - // offset -= 2; - // sprintf(str_instr2+offset, "%5.2f%% (%"PRId64", %"PRId64", %d)\n", - // percentage, count, cycles, cycle_diff); - // } + if (dsp->disasm_cur_inst_len == 1) { + snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, dsp->instr_cycle, len, dsp->disasm_str_instr); + } else { + snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, read_memory_p(dsp, dsp->disasm_prev_inst_pc + 1), dsp->instr_cycle, len, dsp->disasm_str_instr); + } return dsp->disasm_str_instr2; } From 148f04e1c789dfc19695faa04ef93b03a3cf6b70 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 28/68] mcpx/dsp: Replace printf -> DPRINTF --- hw/xbox/mcpx/dsp/dsp.c | 6 ++++-- hw/xbox/mcpx/dsp/dsp_cpu.c | 43 ++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index 09d39e2a14..d304c0ebe0 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -43,9 +43,11 @@ #define INTERRUPT_START_FRAME (1 << 1) #define INTERRUPT_DMA_EOL (1 << 7) -// #define DEBUG_DSP +#ifndef DEBUG_DSP +#define DEBUG_DSP 0 +#endif -#ifdef DEBUG_DSP +#if DEBUG_DSP #define DPRINTF(fmt, ...) \ do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) #else diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 89a3555899..d40d2eafe4 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -33,11 +33,18 @@ #include "dsp_cpu.h" +#ifndef DEBUG_DSP +#define DEBUG_DSP 0 +#endif + #define TRACE_DSP_DISASM 0 #define TRACE_DSP_DISASM_REG 0 #define TRACE_DSP_DISASM_MEM 0 -#define DPRINTF(s, ...) printf(s, ## __VA_ARGS__) +#define DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_DSP) fprintf(stderr, fmt, ## __VA_ARGS__); \ + } while (0) #define BITMASK(x) ((1<<(x))-1) @@ -463,7 +470,7 @@ static uint16_t disasm_instruction(dsp_core_t* dsp, dsp_trace_disasm_t mode) if (mode == DSP_TRACE_MODE) { if (dsp->disasm_prev_inst_pc == dsp->pc) { if (!dsp->disasm_is_looping) { - printf( "Looping on DSP instruction at PC = $%04x\n", dsp->disasm_prev_inst_pc); + DPRINTF("Looping on DSP instruction at PC = $%04x\n", dsp->disasm_prev_inst_pc); dsp->disasm_is_looping = true; } return 0; @@ -521,7 +528,7 @@ static void disasm_reg_compare(dsp_core_t* dsp) case DSP_REG_X1: case DSP_REG_Y0: case DSP_REG_Y1: - printf("\tReg: %s $%06x -> $%06x\n", + DPRINTF("\tReg: %s $%06x -> $%06x\n", registers_name[i], dsp->disasm_registers_save[i], dsp->registers[i]); break; case DSP_REG_R0: @@ -551,21 +558,21 @@ static void disasm_reg_compare(dsp_core_t* dsp) case DSP_REG_SR: case DSP_REG_LA: case DSP_REG_LC: - printf("\tReg: %s $%04x -> $%04x\n", + DPRINTF("\tReg: %s $%04x -> $%04x\n", registers_name[i], dsp->disasm_registers_save[i], dsp->registers[i]); break; case DSP_REG_OMR: case DSP_REG_SP: case DSP_REG_SSH: case DSP_REG_SSL: - printf("\tReg: %s $%02x -> $%02x\n", + DPRINTF("\tReg: %s $%02x -> $%02x\n", registers_name[i], dsp->disasm_registers_save[i], dsp->registers[i]); break; case DSP_REG_A0: case DSP_REG_A1: case DSP_REG_A2: if (bRegA == false) { - printf("\tReg: a $%02x:%06x:%06x -> $%02x:%06x:%06x\n", + DPRINTF("\tReg: a $%02x:%06x:%06x -> $%02x:%06x:%06x\n", dsp->disasm_registers_save[DSP_REG_A2], dsp->disasm_registers_save[DSP_REG_A1], dsp->disasm_registers_save[DSP_REG_A0], dsp->registers[DSP_REG_A2], dsp->registers[DSP_REG_A1], dsp->registers[DSP_REG_A0] ); @@ -576,7 +583,7 @@ static void disasm_reg_compare(dsp_core_t* dsp) case DSP_REG_B1: case DSP_REG_B2: if (bRegB == false) { - printf("\tReg: b $%02x:%06x:%06x -> $%02x:%06x:%06x\n", + DPRINTF("\tReg: b $%02x:%06x:%06x -> $%02x:%06x:%06x\n", dsp->disasm_registers_save[DSP_REG_B2], dsp->disasm_registers_save[DSP_REG_B1], dsp->disasm_registers_save[DSP_REG_B0], dsp->registers[DSP_REG_B2], dsp->registers[DSP_REG_B1], dsp->registers[DSP_REG_B0] ); @@ -588,7 +595,7 @@ static void disasm_reg_compare(dsp_core_t* dsp) #ifdef DSP_DISASM_REG_PC if (pc_save != dsp->pc) { - printf("\tReg: pc $%04x -> $%04x\n", pc_save, dsp->pc); + DPRINTF("\tReg: pc $%04x -> $%04x\n", pc_save, dsp->pc); } #endif } @@ -660,7 +667,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) disasm_return = disasm_instruction(dsp, DSP_TRACE_MODE); if (disasm_return) { - printf( "%s", disasm_get_instruction_text(dsp)); + DPRINTF("%s", disasm_get_instruction_text(dsp)); } if (disasm_return != 0 && TRACE_DSP_DISASM_REG) { /* DSP regs trace enabled only if DSP DISASM is enabled */ @@ -678,7 +685,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) if (op->emu_func) { op->emu_func(dsp); } else { - printf("%x - %s\n", dsp->cur_inst, op->name); + DPRINTF("%x - %s\n", dsp->cur_inst, op->name); emu_undefined(dsp); } } else { @@ -691,7 +698,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) /* Display only when DSP is called in trace mode */ if (!dsp->executing_for_disasm) { if (disasm_return != 0) { - // printf( "%s", disasm_get_instruction_text(dsp)); + // DPRINTF("%s", disasm_get_instruction_text(dsp)); /* DSP regs trace enabled only if DSP DISASM is enabled */ if (TRACE_DSP_DISASM_REG) @@ -700,11 +707,11 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) if (TRACE_DSP_DISASM_MEM) { /* 1 memory change to display ? */ if (dsp->disasm_memory_ptr == 1) - printf( "\t%s\n", dsp->str_disasm_memory[0]); + DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); /* 2 memory changes to display ? */ else if (dsp->disasm_memory_ptr == 2) { - printf( "\t%s\n", dsp->str_disasm_memory[0]); - printf( "\t%s\n", dsp->str_disasm_memory[1]); + DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); + DPRINTF("\t%s\n", dsp->str_disasm_memory[1]); } } } @@ -726,7 +733,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) /* Evaluate time after instructions have been executed to avoid asking too frequently */ uint32_t cur_time = SDL_GetTicks(); if (cur_time-start_time>1000) { - printf( "Dsp: %d i/s\n", (dsp->num_inst*1000)/(cur_time-start_time)); + DPRINTF("Dsp: %d i/s\n", (dsp->num_inst*1000)/(cur_time-start_time)); start_time=cur_time; dsp->num_inst=0; } @@ -1115,7 +1122,7 @@ static void dsp_write_reg(dsp_core_t* dsp, uint32_t numreg, uint32_t value) dsp56k_add_interrupt(dsp, DSP_INTER_STACK_ERROR); dsp->registers[DSP_REG_SP] = value & (3<executing_for_disasm) { - printf( "Dsp: Stack Overflow or Underflow\n"); + DPRINTF("Dsp: Stack Overflow or Underflow\n"); } if (dsp->exception_debugging) { assert(false); @@ -1160,7 +1167,7 @@ static void dsp_stack_push(dsp_core_t* dsp, uint32_t curpc, uint32_t cursr, uint /* Stack full, raise interrupt */ dsp56k_add_interrupt(dsp, DSP_INTER_STACK_ERROR); if (!dsp->executing_for_disasm) - printf("Dsp: Stack Overflow\n"); + DPRINTF("Dsp: Stack Overflow\n"); if (dsp->exception_debugging) assert(false); } @@ -1197,7 +1204,7 @@ static void dsp_stack_pop(dsp_core_t* dsp, uint32_t *newpc, uint32_t *newsr) /* Stack empty*/ dsp56k_add_interrupt(dsp, DSP_INTER_STACK_ERROR); if (!dsp->executing_for_disasm) - printf("Dsp: Stack underflow\n"); + DPRINTF("Dsp: Stack underflow\n"); if (dsp->exception_debugging) assert(false); } From 5ba2ef790c5f5e7803d1738f681d886229b13e29 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 29/68] mcpx/dsp: Factor out debug bits to a header --- hw/xbox/mcpx/dsp/debug.h | 37 +++++++++++++++++++++++++++++++++++++ hw/xbox/mcpx/dsp/dsp.c | 13 +------------ hw/xbox/mcpx/dsp/dsp_cpu.c | 14 +------------- 3 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 hw/xbox/mcpx/dsp/debug.h diff --git a/hw/xbox/mcpx/dsp/debug.h b/hw/xbox/mcpx/dsp/debug.h new file mode 100644 index 0000000000..befef229b1 --- /dev/null +++ b/hw/xbox/mcpx/dsp/debug.h @@ -0,0 +1,37 @@ +/* + * MCPX DSP emulator + + * Copyright (c) 2025 Matt Borgerson + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef HW_XBOX_MCPX_DSP_DEBUG_H +#define HW_XBOX_MCPX_DSP_DEBUG_H + +#ifndef DEBUG_DSP +#define DEBUG_DSP 0 +#endif + +#define TRACE_DSP_DISASM 0 +#define TRACE_DSP_DISASM_REG 0 +#define TRACE_DSP_DISASM_MEM 0 + +#define DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_DSP) fprintf(stderr, fmt, ## __VA_ARGS__); \ + } while (0) + +#endif diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index d304c0ebe0..29d8d67ea3 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -35,6 +35,7 @@ #include "dsp_state.h" #include "dsp.h" +#include "debug.h" /* Defines */ #define BITMASK(x) ((1<<(x))-1) @@ -43,18 +44,6 @@ #define INTERRUPT_START_FRAME (1 << 1) #define INTERRUPT_DMA_EOL (1 << 7) -#ifndef DEBUG_DSP -#define DEBUG_DSP 0 -#endif - -#if DEBUG_DSP -#define DPRINTF(fmt, ...) \ - do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ - do { } while (0) -#endif - static uint32_t read_peripheral(dsp_core_t* core, uint32_t address); static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value); diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index d40d2eafe4..f89a8ea1b8 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -32,19 +32,7 @@ #include "qemu/bswap.h" #include "dsp_cpu.h" - -#ifndef DEBUG_DSP -#define DEBUG_DSP 0 -#endif - -#define TRACE_DSP_DISASM 0 -#define TRACE_DSP_DISASM_REG 0 -#define TRACE_DSP_DISASM_MEM 0 - -#define DPRINTF(fmt, ...) \ - do { \ - if (DEBUG_DSP) fprintf(stderr, fmt, ## __VA_ARGS__); \ - } while (0) +#include "debug.h" #define BITMASK(x) ((1<<(x))-1) From 31c491a7026ee3a8ae2739b1ffe8937908e0d82f Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 30/68] mcpx/dsp: Move cpu reg defs to a header --- hw/xbox/mcpx/dsp/dsp_cpu.h | 110 +------------------------ hw/xbox/mcpx/dsp/dsp_cpu_regs.h | 138 ++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 109 deletions(-) create mode 100644 hw/xbox/mcpx/dsp/dsp_cpu_regs.h diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.h b/hw/xbox/mcpx/dsp/dsp_cpu.h index 6876b4d20a..4a87868139 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.h +++ b/hw/xbox/mcpx/dsp/dsp_cpu.h @@ -29,115 +29,7 @@ #include #include -#define DSP_OMR_MA 0x00 -#define DSP_OMR_MB 0x01 -#define DSP_OMR_DE 0x02 -#define DSP_OMR_SD 0x06 -#define DSP_OMR_EA 0x07 - -#define DSP_SR_C 0x00 -#define DSP_SR_V 0x01 -#define DSP_SR_Z 0x02 -#define DSP_SR_N 0x03 -#define DSP_SR_U 0x04 -#define DSP_SR_E 0x05 -#define DSP_SR_L 0x06 - -#define DSP_SR_I0 0x08 -#define DSP_SR_I1 0x09 -#define DSP_SR_S0 0x0a -#define DSP_SR_S1 0x0b -#define DSP_SR_T 0x0d -#define DSP_SR_LF 0x0f - -#define DSP_SP_SE 0x04 -#define DSP_SP_UF 0x05 - -/* Registers numbers in dsp.registers[] */ -#define DSP_REG_X0 0x04 -#define DSP_REG_X1 0x05 -#define DSP_REG_Y0 0x06 -#define DSP_REG_Y1 0x07 -#define DSP_REG_A0 0x08 -#define DSP_REG_B0 0x09 -#define DSP_REG_A2 0x0a -#define DSP_REG_B2 0x0b -#define DSP_REG_A1 0x0c -#define DSP_REG_B1 0x0d -#define DSP_REG_A 0x0e -#define DSP_REG_B 0x0f - -#define DSP_REG_R0 0x10 -#define DSP_REG_R1 0x11 -#define DSP_REG_R2 0x12 -#define DSP_REG_R3 0x13 -#define DSP_REG_R4 0x14 -#define DSP_REG_R5 0x15 -#define DSP_REG_R6 0x16 -#define DSP_REG_R7 0x17 - -#define DSP_REG_N0 0x18 -#define DSP_REG_N1 0x19 -#define DSP_REG_N2 0x1a -#define DSP_REG_N3 0x1b -#define DSP_REG_N4 0x1c -#define DSP_REG_N5 0x1d -#define DSP_REG_N6 0x1e -#define DSP_REG_N7 0x1f - -#define DSP_REG_M0 0x20 -#define DSP_REG_M1 0x21 -#define DSP_REG_M2 0x22 -#define DSP_REG_M3 0x23 -#define DSP_REG_M4 0x24 -#define DSP_REG_M5 0x25 -#define DSP_REG_M6 0x26 -#define DSP_REG_M7 0x27 - -#define DSP_REG_SR 0x39 -#define DSP_REG_OMR 0x3a -#define DSP_REG_SP 0x3b -#define DSP_REG_SSH 0x3c -#define DSP_REG_SSL 0x3d -#define DSP_REG_LA 0x3e -#define DSP_REG_LC 0x3f - -#define DSP_REG_NULL 0x00 -#define DSP_REG_LCSAVE 0x30 - -#define DSP_REG_MAX 0x40 - -/* Memory spaces for dsp.ram[], dsp.rom[] */ -#define DSP_SPACE_X 0x00 -#define DSP_SPACE_Y 0x01 -#define DSP_SPACE_P 0x02 - -#define DSP_XRAM_SIZE 4096 -#define DSP_YRAM_SIZE 2048 -#define DSP_PRAM_SIZE 4096 - -#define DSP_MIXBUFFER_BASE 0x001400 -#define DSP_MIXBUFFER_SIZE 1024 - -#define DSP_PERIPH_BASE 0xFFFF80 -#define DSP_PERIPH_SIZE 128 - -#define DSP_INTERRUPT_NONE 0x0 -#define DSP_INTERRUPT_DISABLED 0x1 -#define DSP_INTERRUPT_LONG 0x2 - -#define DSP_INTER_RESET 0x0 -#define DSP_INTER_ILLEGAL 0x1 -#define DSP_INTER_STACK_ERROR 0x2 -#define DSP_INTER_TRACE 0x3 -#define DSP_INTER_SWI 0x4 -#define DSP_INTER_HOST_COMMAND 0x5 -#define DSP_INTER_HOST_RCV_DATA 0x6 -#define DSP_INTER_HOST_TRX_DATA 0x7 -#define DSP_INTER_SSI_RCV_DATA_E 0x8 -#define DSP_INTER_SSI_RCV_DATA 0x9 -#define DSP_INTER_SSI_TRX_DATA_E 0xa -#define DSP_INTER_SSI_TRX_DATA 0xb +#include "dsp_cpu_regs.h" typedef enum { DSP_TRACE_MODE, diff --git a/hw/xbox/mcpx/dsp/dsp_cpu_regs.h b/hw/xbox/mcpx/dsp/dsp_cpu_regs.h new file mode 100644 index 0000000000..75b2009b2f --- /dev/null +++ b/hw/xbox/mcpx/dsp/dsp_cpu_regs.h @@ -0,0 +1,138 @@ +/* + * DSP56300 emulator + * + * Copyright (c) 2015 espes + * + * Adapted from Hatari DSP M56001 emulation + * (C) 2003-2008 ARAnyM developer team + * Adaption to Hatari (C) 2008 by Thomas Huth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef HW_XBOX_MCPX_DSP_DSP_CPU_REGS_H +#define HW_XBOX_MCPX_DSP_DSP_CPU_REGS_H + +#define DSP_OMR_MA 0x00 +#define DSP_OMR_MB 0x01 +#define DSP_OMR_DE 0x02 +#define DSP_OMR_SD 0x06 +#define DSP_OMR_EA 0x07 + +#define DSP_SR_C 0x00 +#define DSP_SR_V 0x01 +#define DSP_SR_Z 0x02 +#define DSP_SR_N 0x03 +#define DSP_SR_U 0x04 +#define DSP_SR_E 0x05 +#define DSP_SR_L 0x06 + +#define DSP_SR_I0 0x08 +#define DSP_SR_I1 0x09 +#define DSP_SR_S0 0x0a +#define DSP_SR_S1 0x0b +#define DSP_SR_T 0x0d +#define DSP_SR_LF 0x0f + +#define DSP_SP_SE 0x04 +#define DSP_SP_UF 0x05 + +/* Registers numbers in dsp.registers[] */ +#define DSP_REG_X0 0x04 +#define DSP_REG_X1 0x05 +#define DSP_REG_Y0 0x06 +#define DSP_REG_Y1 0x07 +#define DSP_REG_A0 0x08 +#define DSP_REG_B0 0x09 +#define DSP_REG_A2 0x0a +#define DSP_REG_B2 0x0b +#define DSP_REG_A1 0x0c +#define DSP_REG_B1 0x0d +#define DSP_REG_A 0x0e +#define DSP_REG_B 0x0f + +#define DSP_REG_R0 0x10 +#define DSP_REG_R1 0x11 +#define DSP_REG_R2 0x12 +#define DSP_REG_R3 0x13 +#define DSP_REG_R4 0x14 +#define DSP_REG_R5 0x15 +#define DSP_REG_R6 0x16 +#define DSP_REG_R7 0x17 + +#define DSP_REG_N0 0x18 +#define DSP_REG_N1 0x19 +#define DSP_REG_N2 0x1a +#define DSP_REG_N3 0x1b +#define DSP_REG_N4 0x1c +#define DSP_REG_N5 0x1d +#define DSP_REG_N6 0x1e +#define DSP_REG_N7 0x1f + +#define DSP_REG_M0 0x20 +#define DSP_REG_M1 0x21 +#define DSP_REG_M2 0x22 +#define DSP_REG_M3 0x23 +#define DSP_REG_M4 0x24 +#define DSP_REG_M5 0x25 +#define DSP_REG_M6 0x26 +#define DSP_REG_M7 0x27 + +#define DSP_REG_SR 0x39 +#define DSP_REG_OMR 0x3a +#define DSP_REG_SP 0x3b +#define DSP_REG_SSH 0x3c +#define DSP_REG_SSL 0x3d +#define DSP_REG_LA 0x3e +#define DSP_REG_LC 0x3f + +#define DSP_REG_NULL 0x00 +#define DSP_REG_LCSAVE 0x30 + +#define DSP_REG_MAX 0x40 + +/* Memory spaces for dsp.ram[], dsp.rom[] */ +#define DSP_SPACE_X 0x00 +#define DSP_SPACE_Y 0x01 +#define DSP_SPACE_P 0x02 + +#define DSP_XRAM_SIZE 4096 +#define DSP_YRAM_SIZE 2048 +#define DSP_PRAM_SIZE 4096 + +#define DSP_MIXBUFFER_BASE 0x001400 +#define DSP_MIXBUFFER_SIZE 1024 + +#define DSP_PERIPH_BASE 0xFFFF80 +#define DSP_PERIPH_SIZE 128 + +#define DSP_INTERRUPT_NONE 0x0 +#define DSP_INTERRUPT_DISABLED 0x1 +#define DSP_INTERRUPT_LONG 0x2 + +#define DSP_INTER_RESET 0x0 +#define DSP_INTER_ILLEGAL 0x1 +#define DSP_INTER_STACK_ERROR 0x2 +#define DSP_INTER_TRACE 0x3 +#define DSP_INTER_SWI 0x4 +#define DSP_INTER_HOST_COMMAND 0x5 +#define DSP_INTER_HOST_RCV_DATA 0x6 +#define DSP_INTER_HOST_TRX_DATA 0x7 +#define DSP_INTER_SSI_RCV_DATA_E 0x8 +#define DSP_INTER_SSI_RCV_DATA 0x9 +#define DSP_INTER_SSI_TRX_DATA_E 0xa +#define DSP_INTER_SSI_TRX_DATA 0xb + +#endif From c68cdd9479c38bede20028e8c046ebba69d018c8 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 31/68] mcpx/dsp: Fix minor header issues --- hw/xbox/mcpx/dsp/dsp.c | 7 ------- hw/xbox/mcpx/dsp/dsp_cpu.c | 6 ------ hw/xbox/mcpx/dsp/dsp_dma.c | 9 +-------- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index 29d8d67ea3..c2327a73be 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -24,16 +24,9 @@ */ #include "qemu/osdep.h" - -#include -#include -#include -#include - #include "dsp_cpu.h" #include "dsp_dma.h" #include "dsp_state.h" - #include "dsp.h" #include "debug.h" diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index f89a8ea1b8..8d786bcd69 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -24,13 +24,7 @@ */ #include "qemu/osdep.h" - -#include -#include -#include - #include "qemu/bswap.h" - #include "dsp_cpu.h" #include "debug.h" diff --git a/hw/xbox/mcpx/dsp/dsp_dma.c b/hw/xbox/mcpx/dsp/dsp_dma.c index 377475fb76..50a7a9f01d 100644 --- a/hw/xbox/mcpx/dsp/dsp_dma.c +++ b/hw/xbox/mcpx/dsp/dsp_dma.c @@ -18,12 +18,7 @@ * License along with this library; if not, see . */ -#include -#include -#include -#include - -#include +#include "qemu/osdep.h" #include "qemu/compiler.h" #include "dsp_dma.h" #include "dsp_state.h" @@ -98,8 +93,6 @@ const char *space_names[] = { #endif -#define MIN(a,b) (((a)<(b))?(a):(b)) - static void scratch_circular_copy( DSPDMAState *s, uint32_t scratch_base, From f8cbcbadaa07adf243b0e967ce58f93142624c45 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 32/68] mcpx/dsp: Move dma reg defs to a header --- hw/xbox/mcpx/dsp/dsp_dma.c | 25 +----------------- hw/xbox/mcpx/dsp/dsp_dma_regs.h | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 hw/xbox/mcpx/dsp/dsp_dma_regs.h diff --git a/hw/xbox/mcpx/dsp/dsp_dma.c b/hw/xbox/mcpx/dsp/dsp_dma.c index 50a7a9f01d..80cf5a9747 100644 --- a/hw/xbox/mcpx/dsp/dsp_dma.c +++ b/hw/xbox/mcpx/dsp/dsp_dma.c @@ -21,32 +21,9 @@ #include "qemu/osdep.h" #include "qemu/compiler.h" #include "dsp_dma.h" +#include "dsp_dma_regs.h" #include "dsp_state.h" - -#define DMA_CONFIGURATION_AUTOSTART (1 << 0) -#define DMA_CONFIGURATION_AUTOREADY (1 << 1) -#define DMA_CONFIGURATION_IOC_CLEAR (1 << 2) -#define DMA_CONFIGURATION_EOL_CLEAR (1 << 3) -#define DMA_CONFIGURATION_ERR_CLEAR (1 << 4) - -#define DMA_CONTROL_ACTION 0x7 -#define DMA_CONTROL_ACTION_NOP 0 -#define DMA_CONTROL_ACTION_START 1 -#define DMA_CONTROL_ACTION_STOP 2 -#define DMA_CONTROL_ACTION_FREEZE 3 -#define DMA_CONTROL_ACTION_UNFREEZE 4 -#define DMA_CONTROL_ACTION_ABORT 5 -#define DMA_CONTROL_FROZEN (1 << 3) -#define DMA_CONTROL_RUNNING (1 << 4) -#define DMA_CONTROL_STOPPED (1 << 5) - -#define NODE_POINTER_VAL 0x3fff -#define NODE_POINTER_EOL (1 << 14) - -#define NODE_CONTROL_DIRECTION (1 << 1) - - // #define DEBUG #ifdef DEBUG # define DPRINTF(s, ...) printf(s, ## __VA_ARGS__) diff --git a/hw/xbox/mcpx/dsp/dsp_dma_regs.h b/hw/xbox/mcpx/dsp/dsp_dma_regs.h new file mode 100644 index 0000000000..a373cb7c14 --- /dev/null +++ b/hw/xbox/mcpx/dsp/dsp_dma_regs.h @@ -0,0 +1,46 @@ +/* + * MCPX DSP DMA + * + * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_XBOX_MCPX_DSP_DSP_DMA_REGS_H +#define HW_XBOX_MCPX_DSP_DSP_DMA_REGS_H + +#define DMA_CONFIGURATION_AUTOSTART (1 << 0) +#define DMA_CONFIGURATION_AUTOREADY (1 << 1) +#define DMA_CONFIGURATION_IOC_CLEAR (1 << 2) +#define DMA_CONFIGURATION_EOL_CLEAR (1 << 3) +#define DMA_CONFIGURATION_ERR_CLEAR (1 << 4) + +#define DMA_CONTROL_ACTION 0x7 +#define DMA_CONTROL_ACTION_NOP 0 +#define DMA_CONTROL_ACTION_START 1 +#define DMA_CONTROL_ACTION_STOP 2 +#define DMA_CONTROL_ACTION_FREEZE 3 +#define DMA_CONTROL_ACTION_UNFREEZE 4 +#define DMA_CONTROL_ACTION_ABORT 5 +#define DMA_CONTROL_FROZEN (1 << 3) +#define DMA_CONTROL_RUNNING (1 << 4) +#define DMA_CONTROL_STOPPED (1 << 5) + +#define NODE_POINTER_VAL 0x3fff +#define NODE_POINTER_EOL (1 << 14) + +#define NODE_CONTROL_DIRECTION (1 << 1) + +#endif From d18125994c3d1c20cf78173b5f45fb2cada29924 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 33/68] mcpx/dsp: Drop some dead code --- hw/xbox/mcpx/dsp/dsp_dma.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/hw/xbox/mcpx/dsp/dsp_dma.c b/hw/xbox/mcpx/dsp/dsp_dma.c index 80cf5a9747..98f7bc3cb7 100644 --- a/hw/xbox/mcpx/dsp/dsp_dma.c +++ b/hw/xbox/mcpx/dsp/dsp_dma.c @@ -24,14 +24,8 @@ #include "dsp_dma_regs.h" #include "dsp_state.h" -// #define DEBUG #ifdef DEBUG -# define DPRINTF(s, ...) printf(s, ## __VA_ARGS__) -#else -# define DPRINTF(s, ...) do { } while (0) -#endif -#ifdef DEBUG const char *buffer_names[] = { "fifo0", /* 0x0 */ "fifo1", /* 0x1 */ @@ -112,8 +106,6 @@ static void dsp_dma_run(DSPDMAState *s) return; } - // DSPState *dsp = container_of(s, DSPState, dma); - while (!(s->next_block & NODE_POINTER_EOL)) { uint32_t addr = s->next_block & NODE_POINTER_VAL; uint32_t block_addr = 0; From 8dafd513b90fe711cbe4be6857430022165bef77 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 34/68] mcpx/dsp: Move some debug functions out to debug.c --- hw/xbox/mcpx/dsp/debug.c | 312 +++++++++++++++++++++++++++++++++++ hw/xbox/mcpx/dsp/dsp.c | 269 ------------------------------ hw/xbox/mcpx/dsp/dsp.h | 9 +- hw/xbox/mcpx/dsp/dsp_cpu.c | 2 - hw/xbox/mcpx/dsp/meson.build | 2 +- 5 files changed, 316 insertions(+), 278 deletions(-) create mode 100644 hw/xbox/mcpx/dsp/debug.c diff --git a/hw/xbox/mcpx/dsp/debug.c b/hw/xbox/mcpx/dsp/debug.c new file mode 100644 index 0000000000..e678acb3d3 --- /dev/null +++ b/hw/xbox/mcpx/dsp/debug.c @@ -0,0 +1,312 @@ +/* + * MCPX DSP emulator + * + * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson + * + * Adapted from Hatari DSP M56001 emulation + * (C) 2001-2008 ARAnyM developer team + * Adaption to Hatari (C) 2008 by Thomas Huth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "qemu/osdep.h" + +#include +#include +#include +#include + +#include "dsp_cpu.h" +#include "dsp_dma.h" +#include "dsp_state.h" + +#include "dsp.h" +#include "debug.h" + +#if DEBUG_DSP +#define BITMASK(x) ((1<<(x))-1) + +/** + * Disassemble DSP code between given addresses, return next PC address + */ +uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr) +{ + uint32_t dsp_pc; + + for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { + dsp_pc += dsp56k_execute_one_disasm_instruction(&dsp->core, out, dsp_pc); + } + return dsp_pc; +} + +/** + * Output memory values between given addresses in given DSP address space. + * Return next DSP address value. + */ +uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space) +{ + uint32_t mem, value; + + for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { + value = dsp_read_memory(dsp, space, mem); + printf("%04x %06x\n", mem, value); + } + return dsp_memdump_upper+1; +} + +/** + * Show information on DSP core state which isn't + * shown by any of the other commands (dd, dm, dr). + */ +void dsp_info(DSPState* dsp) +{ + int i, j; + const char *stackname[] = { "SSH", "SSL" }; + + printf("DSP core information:\n"); + + for (i = 0; i < ARRAY_SIZE(stackname); i++) { + printf("- %s stack:", stackname[i]); + for (j = 0; j < ARRAY_SIZE(dsp->core.stack[0]); j++) { + printf(" %04x", dsp->core.stack[i][j]); + } + printf("\n"); + } + + printf("- Interrupt IPL:"); + for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_ipl); i++) { + printf(" %04x", dsp->core.interrupt_ipl[i]); + } + printf("\n"); + + printf("- Pending ints: "); + for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_is_pending); i++) { + printf(" %04hx", dsp->core.interrupt_is_pending[i]); + } + printf("\n"); +} + +/** + * Show DSP register contents + */ +void dsp_print_registers(DSPState* dsp) +{ + uint32_t i; + + printf("A: A2: %02x A1: %06x A0: %06x\n", + dsp->core.registers[DSP_REG_A2], dsp->core.registers[DSP_REG_A1], dsp->core.registers[DSP_REG_A0]); + printf("B: B2: %02x B1: %06x B0: %06x\n", + dsp->core.registers[DSP_REG_B2], dsp->core.registers[DSP_REG_B1], dsp->core.registers[DSP_REG_B0]); + + printf("X: X1: %06x X0: %06x\n", dsp->core.registers[DSP_REG_X1], dsp->core.registers[DSP_REG_X0]); + printf("Y: Y1: %06x Y0: %06x\n", dsp->core.registers[DSP_REG_Y1], dsp->core.registers[DSP_REG_Y0]); + + for (i=0; i<8; i++) { + printf("R%01x: %04x N%01x: %04x M%01x: %04x\n", + i, dsp->core.registers[DSP_REG_R0+i], + i, dsp->core.registers[DSP_REG_N0+i], + i, dsp->core.registers[DSP_REG_M0+i]); + } + + printf("LA: %04x LC: %04x PC: %04x\n", dsp->core.registers[DSP_REG_LA], dsp->core.registers[DSP_REG_LC], dsp->core.pc); + printf("SR: %04x OMR: %02x\n", dsp->core.registers[DSP_REG_SR], dsp->core.registers[DSP_REG_OMR]); + printf("SP: %02x SSH: %04x SSL: %04x\n", + dsp->core.registers[DSP_REG_SP], dsp->core.registers[DSP_REG_SSH], dsp->core.registers[DSP_REG_SSL]); +} + + +/** + * Get given DSP register address and required bit mask. + * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP, + * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers + * need special handling (in DSP*SetRegister()) when they are set. + * Return the register width in bits or zero for an error. + */ +int dsp_get_register_address(DSPState* dsp, const char *regname, uint32_t **addr, uint32_t *mask) +{ +#define MAX_REGNAME_LEN 4 + typedef struct { + const char name[MAX_REGNAME_LEN]; + uint32_t *addr; + size_t bits; + uint32_t mask; + } reg_addr_t; + + /* sorted by name so that this can be bisected */ + const reg_addr_t registers[] = { + + /* 56-bit A register */ + { "A0", &dsp->core.registers[DSP_REG_A0], 32, BITMASK(24) }, + { "A1", &dsp->core.registers[DSP_REG_A1], 32, BITMASK(24) }, + { "A2", &dsp->core.registers[DSP_REG_A2], 32, BITMASK(8) }, + + /* 56-bit B register */ + { "B0", &dsp->core.registers[DSP_REG_B0], 32, BITMASK(24) }, + { "B1", &dsp->core.registers[DSP_REG_B1], 32, BITMASK(24) }, + { "B2", &dsp->core.registers[DSP_REG_B2], 32, BITMASK(8) }, + + /* 16-bit LA & LC registers */ + { "LA", &dsp->core.registers[DSP_REG_LA], 32, BITMASK(16) }, + { "LC", &dsp->core.registers[DSP_REG_LC], 32, BITMASK(16) }, + + /* 16-bit M registers */ + { "M0", &dsp->core.registers[DSP_REG_M0], 32, BITMASK(16) }, + { "M1", &dsp->core.registers[DSP_REG_M1], 32, BITMASK(16) }, + { "M2", &dsp->core.registers[DSP_REG_M2], 32, BITMASK(16) }, + { "M3", &dsp->core.registers[DSP_REG_M3], 32, BITMASK(16) }, + { "M4", &dsp->core.registers[DSP_REG_M4], 32, BITMASK(16) }, + { "M5", &dsp->core.registers[DSP_REG_M5], 32, BITMASK(16) }, + { "M6", &dsp->core.registers[DSP_REG_M6], 32, BITMASK(16) }, + { "M7", &dsp->core.registers[DSP_REG_M7], 32, BITMASK(16) }, + + /* 16-bit N registers */ + { "N0", &dsp->core.registers[DSP_REG_N0], 32, BITMASK(16) }, + { "N1", &dsp->core.registers[DSP_REG_N1], 32, BITMASK(16) }, + { "N2", &dsp->core.registers[DSP_REG_N2], 32, BITMASK(16) }, + { "N3", &dsp->core.registers[DSP_REG_N3], 32, BITMASK(16) }, + { "N4", &dsp->core.registers[DSP_REG_N4], 32, BITMASK(16) }, + { "N5", &dsp->core.registers[DSP_REG_N5], 32, BITMASK(16) }, + { "N6", &dsp->core.registers[DSP_REG_N6], 32, BITMASK(16) }, + { "N7", &dsp->core.registers[DSP_REG_N7], 32, BITMASK(16) }, + + { "OMR", &dsp->core.registers[DSP_REG_OMR], 32, 0x5f }, + + /* 16-bit program counter */ + { "PC", (uint32_t*)(&dsp->core.pc), 24, BITMASK(24) }, + + /* 16-bit DSP R (address) registers */ + { "R0", &dsp->core.registers[DSP_REG_R0], 32, BITMASK(16) }, + { "R1", &dsp->core.registers[DSP_REG_R1], 32, BITMASK(16) }, + { "R2", &dsp->core.registers[DSP_REG_R2], 32, BITMASK(16) }, + { "R3", &dsp->core.registers[DSP_REG_R3], 32, BITMASK(16) }, + { "R4", &dsp->core.registers[DSP_REG_R4], 32, BITMASK(16) }, + { "R5", &dsp->core.registers[DSP_REG_R5], 32, BITMASK(16) }, + { "R6", &dsp->core.registers[DSP_REG_R6], 32, BITMASK(16) }, + { "R7", &dsp->core.registers[DSP_REG_R7], 32, BITMASK(16) }, + + { "SSH", &dsp->core.registers[DSP_REG_SSH], 32, BITMASK(16) }, + { "SSL", &dsp->core.registers[DSP_REG_SSL], 32, BITMASK(16) }, + { "SP", &dsp->core.registers[DSP_REG_SP], 32, BITMASK(6) }, + + /* 16-bit status register */ + { "SR", &dsp->core.registers[DSP_REG_SR], 32, 0xefff }, + + /* 48-bit X register */ + { "X0", &dsp->core.registers[DSP_REG_X0], 32, BITMASK(24) }, + { "X1", &dsp->core.registers[DSP_REG_X1], 32, BITMASK(24) }, + + /* 48-bit Y register */ + { "Y0", &dsp->core.registers[DSP_REG_Y0], 32, BITMASK(24) }, + { "Y1", &dsp->core.registers[DSP_REG_Y1], 32, BITMASK(24) } + }; + /* left, right, middle, direction */ + int l, r, m, dir = 0; + unsigned int i, len; + char reg[MAX_REGNAME_LEN]; + + for (i = 0; i < sizeof(reg) && regname[i]; i++) { + reg[i] = toupper(regname[i]); + } + if (i < 2 || regname[i]) { + /* too short or longer than any of the names */ + return 0; + } + len = i; + + /* bisect */ + l = 0; + r = ARRAY_SIZE(registers) - 1; + do { + m = (l+r) >> 1; + for (i = 0; i < len; i++) { + dir = (int)reg[i] - registers[m].name[i]; + if (dir) { + break; + } + } + if (dir == 0) { + *addr = registers[m].addr; + *mask = registers[m].mask; + return registers[m].bits; + } + if (dir < 0) { + r = m-1; + } else { + l = m+1; + } + } while (l <= r); +#undef MAX_REGNAME_LEN + return 0; +} + + +/** + * Set given DSP register value, return false if unknown register given + */ +bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value) +{ + uint32_t *addr, mask, sp_value; + int bits; + + /* first check registers needing special handling... */ + if (arg[0]=='S' || arg[0]=='s') { + if (arg[1]=='P' || arg[1]=='p') { + dsp->core.registers[DSP_REG_SP] = value & BITMASK(6); + value &= BITMASK(4); + dsp->core.registers[DSP_REG_SSH] = dsp->core.stack[0][value]; + dsp->core.registers[DSP_REG_SSL] = dsp->core.stack[1][value]; + return true; + } + if (arg[1]=='S' || arg[1]=='s') { + sp_value = dsp->core.registers[DSP_REG_SP] & BITMASK(4); + if (arg[2]=='H' || arg[2]=='h') { + if (sp_value == 0) { + dsp->core.registers[DSP_REG_SSH] = 0; + dsp->core.stack[0][sp_value] = 0; + } else { + dsp->core.registers[DSP_REG_SSH] = value & BITMASK(16); + dsp->core.stack[0][sp_value] = value & BITMASK(16); + } + return true; + } + if (arg[2]=='L' || arg[2]=='l') { + if (sp_value == 0) { + dsp->core.registers[DSP_REG_SSL] = 0; + dsp->core.stack[1][sp_value] = 0; + } else { + dsp->core.registers[DSP_REG_SSL] = value & BITMASK(16); + dsp->core.stack[1][sp_value] = value & BITMASK(16); + } + return true; + } + } + } + + /* ...then registers where address & mask are enough */ + bits = dsp_get_register_address(dsp, arg, &addr, &mask); + switch (bits) { + case 32: + *addr = value & mask; + return true; + case 16: + *(uint16_t*)addr = value & mask; + return true; + } + return false; +} + +#endif diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index c2327a73be..dda5f829e1 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -198,19 +198,6 @@ void dsp_start_frame(DSPState* dsp) dsp->interrupts |= INTERRUPT_START_FRAME; } -/** - * Disassemble DSP code between given addresses, return next PC address - */ -uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr) -{ - uint32_t dsp_pc; - - for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { - dsp_pc += dsp56k_execute_one_disasm_instruction(&dsp->core, out, dsp_pc); - } - return dsp_pc; -} - uint32_t dsp_read_memory(DSPState* dsp, char space, uint32_t address) { int space_id; @@ -254,259 +241,3 @@ void dsp_write_memory(DSPState* dsp, char space, uint32_t address, uint32_t valu dsp56k_write_memory(&dsp->core, space_id, address, value); } - -/** - * Output memory values between given addresses in given DSP address space. - * Return next DSP address value. - */ -uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space) -{ - uint32_t mem, value; - - for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { - value = dsp_read_memory(dsp, space, mem); - printf("%04x %06x\n", mem, value); - } - return dsp_memdump_upper+1; -} - -/** - * Show information on DSP core state which isn't - * shown by any of the other commands (dd, dm, dr). - */ -void dsp_info(DSPState* dsp) -{ - int i, j; - const char *stackname[] = { "SSH", "SSL" }; - - printf("DSP core information:\n"); - - for (i = 0; i < ARRAY_SIZE(stackname); i++) { - printf("- %s stack:", stackname[i]); - for (j = 0; j < ARRAY_SIZE(dsp->core.stack[0]); j++) { - printf(" %04x", dsp->core.stack[i][j]); - } - printf("\n"); - } - - printf("- Interrupt IPL:"); - for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_ipl); i++) { - printf(" %04x", dsp->core.interrupt_ipl[i]); - } - printf("\n"); - - printf("- Pending ints: "); - for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_is_pending); i++) { - printf(" %04hx", dsp->core.interrupt_is_pending[i]); - } - printf("\n"); -} - -/** - * Show DSP register contents - */ -void dsp_print_registers(DSPState* dsp) -{ - uint32_t i; - - printf("A: A2: %02x A1: %06x A0: %06x\n", - dsp->core.registers[DSP_REG_A2], dsp->core.registers[DSP_REG_A1], dsp->core.registers[DSP_REG_A0]); - printf("B: B2: %02x B1: %06x B0: %06x\n", - dsp->core.registers[DSP_REG_B2], dsp->core.registers[DSP_REG_B1], dsp->core.registers[DSP_REG_B0]); - - printf("X: X1: %06x X0: %06x\n", dsp->core.registers[DSP_REG_X1], dsp->core.registers[DSP_REG_X0]); - printf("Y: Y1: %06x Y0: %06x\n", dsp->core.registers[DSP_REG_Y1], dsp->core.registers[DSP_REG_Y0]); - - for (i=0; i<8; i++) { - printf("R%01x: %04x N%01x: %04x M%01x: %04x\n", - i, dsp->core.registers[DSP_REG_R0+i], - i, dsp->core.registers[DSP_REG_N0+i], - i, dsp->core.registers[DSP_REG_M0+i]); - } - - printf("LA: %04x LC: %04x PC: %04x\n", dsp->core.registers[DSP_REG_LA], dsp->core.registers[DSP_REG_LC], dsp->core.pc); - printf("SR: %04x OMR: %02x\n", dsp->core.registers[DSP_REG_SR], dsp->core.registers[DSP_REG_OMR]); - printf("SP: %02x SSH: %04x SSL: %04x\n", - dsp->core.registers[DSP_REG_SP], dsp->core.registers[DSP_REG_SSH], dsp->core.registers[DSP_REG_SSL]); -} - - -/** - * Get given DSP register address and required bit mask. - * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP, - * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers - * need special handling (in DSP*SetRegister()) when they are set. - * Return the register width in bits or zero for an error. - */ -int dsp_get_register_address(DSPState* dsp, const char *regname, uint32_t **addr, uint32_t *mask) -{ -#define MAX_REGNAME_LEN 4 - typedef struct { - const char name[MAX_REGNAME_LEN]; - uint32_t *addr; - size_t bits; - uint32_t mask; - } reg_addr_t; - - /* sorted by name so that this can be bisected */ - const reg_addr_t registers[] = { - - /* 56-bit A register */ - { "A0", &dsp->core.registers[DSP_REG_A0], 32, BITMASK(24) }, - { "A1", &dsp->core.registers[DSP_REG_A1], 32, BITMASK(24) }, - { "A2", &dsp->core.registers[DSP_REG_A2], 32, BITMASK(8) }, - - /* 56-bit B register */ - { "B0", &dsp->core.registers[DSP_REG_B0], 32, BITMASK(24) }, - { "B1", &dsp->core.registers[DSP_REG_B1], 32, BITMASK(24) }, - { "B2", &dsp->core.registers[DSP_REG_B2], 32, BITMASK(8) }, - - /* 16-bit LA & LC registers */ - { "LA", &dsp->core.registers[DSP_REG_LA], 32, BITMASK(16) }, - { "LC", &dsp->core.registers[DSP_REG_LC], 32, BITMASK(16) }, - - /* 16-bit M registers */ - { "M0", &dsp->core.registers[DSP_REG_M0], 32, BITMASK(16) }, - { "M1", &dsp->core.registers[DSP_REG_M1], 32, BITMASK(16) }, - { "M2", &dsp->core.registers[DSP_REG_M2], 32, BITMASK(16) }, - { "M3", &dsp->core.registers[DSP_REG_M3], 32, BITMASK(16) }, - { "M4", &dsp->core.registers[DSP_REG_M4], 32, BITMASK(16) }, - { "M5", &dsp->core.registers[DSP_REG_M5], 32, BITMASK(16) }, - { "M6", &dsp->core.registers[DSP_REG_M6], 32, BITMASK(16) }, - { "M7", &dsp->core.registers[DSP_REG_M7], 32, BITMASK(16) }, - - /* 16-bit N registers */ - { "N0", &dsp->core.registers[DSP_REG_N0], 32, BITMASK(16) }, - { "N1", &dsp->core.registers[DSP_REG_N1], 32, BITMASK(16) }, - { "N2", &dsp->core.registers[DSP_REG_N2], 32, BITMASK(16) }, - { "N3", &dsp->core.registers[DSP_REG_N3], 32, BITMASK(16) }, - { "N4", &dsp->core.registers[DSP_REG_N4], 32, BITMASK(16) }, - { "N5", &dsp->core.registers[DSP_REG_N5], 32, BITMASK(16) }, - { "N6", &dsp->core.registers[DSP_REG_N6], 32, BITMASK(16) }, - { "N7", &dsp->core.registers[DSP_REG_N7], 32, BITMASK(16) }, - - { "OMR", &dsp->core.registers[DSP_REG_OMR], 32, 0x5f }, - - /* 16-bit program counter */ - { "PC", (uint32_t*)(&dsp->core.pc), 24, BITMASK(24) }, - - /* 16-bit DSP R (address) registers */ - { "R0", &dsp->core.registers[DSP_REG_R0], 32, BITMASK(16) }, - { "R1", &dsp->core.registers[DSP_REG_R1], 32, BITMASK(16) }, - { "R2", &dsp->core.registers[DSP_REG_R2], 32, BITMASK(16) }, - { "R3", &dsp->core.registers[DSP_REG_R3], 32, BITMASK(16) }, - { "R4", &dsp->core.registers[DSP_REG_R4], 32, BITMASK(16) }, - { "R5", &dsp->core.registers[DSP_REG_R5], 32, BITMASK(16) }, - { "R6", &dsp->core.registers[DSP_REG_R6], 32, BITMASK(16) }, - { "R7", &dsp->core.registers[DSP_REG_R7], 32, BITMASK(16) }, - - { "SSH", &dsp->core.registers[DSP_REG_SSH], 32, BITMASK(16) }, - { "SSL", &dsp->core.registers[DSP_REG_SSL], 32, BITMASK(16) }, - { "SP", &dsp->core.registers[DSP_REG_SP], 32, BITMASK(6) }, - - /* 16-bit status register */ - { "SR", &dsp->core.registers[DSP_REG_SR], 32, 0xefff }, - - /* 48-bit X register */ - { "X0", &dsp->core.registers[DSP_REG_X0], 32, BITMASK(24) }, - { "X1", &dsp->core.registers[DSP_REG_X1], 32, BITMASK(24) }, - - /* 48-bit Y register */ - { "Y0", &dsp->core.registers[DSP_REG_Y0], 32, BITMASK(24) }, - { "Y1", &dsp->core.registers[DSP_REG_Y1], 32, BITMASK(24) } - }; - /* left, right, middle, direction */ - int l, r, m, dir = 0; - unsigned int i, len; - char reg[MAX_REGNAME_LEN]; - - for (i = 0; i < sizeof(reg) && regname[i]; i++) { - reg[i] = toupper(regname[i]); - } - if (i < 2 || regname[i]) { - /* too short or longer than any of the names */ - return 0; - } - len = i; - - /* bisect */ - l = 0; - r = ARRAY_SIZE(registers) - 1; - do { - m = (l+r) >> 1; - for (i = 0; i < len; i++) { - dir = (int)reg[i] - registers[m].name[i]; - if (dir) { - break; - } - } - if (dir == 0) { - *addr = registers[m].addr; - *mask = registers[m].mask; - return registers[m].bits; - } - if (dir < 0) { - r = m-1; - } else { - l = m+1; - } - } while (l <= r); -#undef MAX_REGNAME_LEN - return 0; -} - - -/** - * Set given DSP register value, return false if unknown register given - */ -bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value) -{ - uint32_t *addr, mask, sp_value; - int bits; - - /* first check registers needing special handling... */ - if (arg[0]=='S' || arg[0]=='s') { - if (arg[1]=='P' || arg[1]=='p') { - dsp->core.registers[DSP_REG_SP] = value & BITMASK(6); - value &= BITMASK(4); - dsp->core.registers[DSP_REG_SSH] = dsp->core.stack[0][value]; - dsp->core.registers[DSP_REG_SSL] = dsp->core.stack[1][value]; - return true; - } - if (arg[1]=='S' || arg[1]=='s') { - sp_value = dsp->core.registers[DSP_REG_SP] & BITMASK(4); - if (arg[2]=='H' || arg[2]=='h') { - if (sp_value == 0) { - dsp->core.registers[DSP_REG_SSH] = 0; - dsp->core.stack[0][sp_value] = 0; - } else { - dsp->core.registers[DSP_REG_SSH] = value & BITMASK(16); - dsp->core.stack[0][sp_value] = value & BITMASK(16); - } - return true; - } - if (arg[2]=='L' || arg[2]=='l') { - if (sp_value == 0) { - dsp->core.registers[DSP_REG_SSL] = 0; - dsp->core.stack[1][sp_value] = 0; - } else { - dsp->core.registers[DSP_REG_SSL] = value & BITMASK(16); - dsp->core.stack[1][sp_value] = value & BITMASK(16); - } - return true; - } - } - } - - /* ...then registers where address & mask are enough */ - bits = dsp_get_register_address(dsp, arg, &addr, &mask); - switch (bits) { - case 32: - *addr = value & mask; - return true; - case 16: - *(uint16_t*)addr = value & mask; - return true; - } - return false; -} diff --git a/hw/xbox/mcpx/dsp/dsp.h b/hw/xbox/mcpx/dsp/dsp.h index 0b18fa0c45..d85e03d55e 100644 --- a/hw/xbox/mcpx/dsp/dsp.h +++ b/hw/xbox/mcpx/dsp/dsp.h @@ -36,7 +36,6 @@ typedef void (*dsp_scratch_rw_func)( typedef void (*dsp_fifo_rw_func)( void *opaque, uint8_t *ptr, unsigned int index, size_t len, bool dir); -/* Dsp commands */ DSPState *dsp_init(void *rw_opaque, dsp_scratch_rw_func scratch_rw, dsp_fifo_rw_func fifo_rw); @@ -49,16 +48,14 @@ void dsp_run(DSPState* dsp, int cycles); void dsp_bootstrap(DSPState* dsp); void dsp_start_frame(DSPState* dsp); - -/* Dsp Debugger commands */ uint32_t dsp_read_memory(DSPState* dsp, char space, uint32_t addr); void dsp_write_memory(DSPState* dsp, char space, uint32_t address, uint32_t value); -uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space); -uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr); + void dsp_info(DSPState* dsp); void dsp_print_registers(DSPState* dsp); int dsp_get_register_address(DSPState* dsp, const char *arg, uint32_t **addr, uint32_t *mask); +uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space); +uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr); bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value); - #endif /* DSP_H */ diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 8d786bcd69..ba6fd7e057 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -1439,5 +1439,3 @@ static uint32_t dsp_signextend(int bits, uint32_t v) { assert(shift > 0); return (uint32_t)(((int32_t)v << shift) >> shift); } - - diff --git a/hw/xbox/mcpx/dsp/meson.build b/hw/xbox/mcpx/dsp/meson.build index b94537f97c..4e06c59496 100644 --- a/hw/xbox/mcpx/dsp/meson.build +++ b/hw/xbox/mcpx/dsp/meson.build @@ -1,2 +1,2 @@ -libdsp = static_library('dsp', files(['dsp.c', 'dsp_cpu.c', 'dsp_dma.c']) + genh) +libdsp = static_library('dsp', files(['debug.c', 'dsp.c', 'dsp_cpu.c', 'dsp_dma.c']) + genh) dsp = declare_dependency(objects: libdsp.extract_all_objects(recursive: false)) From 31d8237ee3c1ed4d6cc98bf0acc40992627eec54 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 35/68] mcpx/dsp: Remove dsp56k_execute_one_disasm_instruction --- hw/xbox/mcpx/apu.c | 2 +- hw/xbox/mcpx/dsp/debug.c | 13 ------ hw/xbox/mcpx/dsp/dsp_cpu.c | 89 ++++++++---------------------------- hw/xbox/mcpx/dsp/dsp_cpu.h | 5 -- hw/xbox/mcpx/dsp/dsp_emu.inl | 13 ++---- 5 files changed, 24 insertions(+), 98 deletions(-) diff --git a/hw/xbox/mcpx/apu.c b/hw/xbox/mcpx/apu.c index d5eec18f40..338e132956 100644 --- a/hw/xbox/mcpx/apu.c +++ b/hw/xbox/mcpx/apu.c @@ -2579,7 +2579,7 @@ const VMStateDescription vmstate_vp_dsp_core_state = { VMSTATE_UINT32(num_inst, dsp_core_t), VMSTATE_UINT32(cur_inst_len, dsp_core_t), VMSTATE_UINT32(cur_inst, dsp_core_t), - VMSTATE_BOOL(executing_for_disasm, dsp_core_t), + VMSTATE_UNUSED(1), VMSTATE_UINT32(disasm_memory_ptr, dsp_core_t), VMSTATE_BOOL(exception_debugging, dsp_core_t), VMSTATE_UINT32(disasm_prev_inst_pc, dsp_core_t), diff --git a/hw/xbox/mcpx/dsp/debug.c b/hw/xbox/mcpx/dsp/debug.c index e678acb3d3..e41a222bf9 100644 --- a/hw/xbox/mcpx/dsp/debug.c +++ b/hw/xbox/mcpx/dsp/debug.c @@ -40,19 +40,6 @@ #if DEBUG_DSP #define BITMASK(x) ((1<<(x))-1) -/** - * Disassemble DSP code between given addresses, return next PC address - */ -uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr) -{ - uint32_t dsp_pc; - - for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { - dsp_pc += dsp56k_execute_one_disasm_instruction(&dsp->core, out, dsp_pc); - } - return dsp_pc; -} - /** * Output memory values between given addresses in given DSP address space. * Return next DSP address value. diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index ba6fd7e057..06d4b82ab2 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -405,7 +405,6 @@ void dsp56k_reset_cpu(dsp_core_t* dsp) /* runtime shit */ - dsp->executing_for_disasm = false; // start_time = SDL_GetTicks(); dsp->num_inst = 0; @@ -597,39 +596,6 @@ static const char* disasm_get_instruction_text(dsp_core_t* dsp) return dsp->disasm_str_instr2; } -/** - * Execute one instruction in trace mode at a given PC address. - * */ -uint16_t dsp56k_execute_one_disasm_instruction(dsp_core_t* dsp, FILE *out, uint32_t pc) -{ - dsp_core_t dsp_core_save; - - /* Set DSP in disasm mode */ - dsp->executing_for_disasm = true; - - /* Save DSP context before executing instruction */ - memcpy(&dsp_core_save, dsp, sizeof(dsp_core_t)); - - /* execute and disasm instruction */ - dsp->pc = pc; - - /* Disasm instruction */ - uint16_t instruction_length = disasm_instruction(dsp, DSP_DISASM_MODE) - 1; - - /* Execute instruction at address given in parameter to get the number of cycles it takes */ - dsp56k_execute_instruction(dsp); - - fprintf(out, "%s", disasm_get_instruction_text(dsp)); - - /* Restore DSP context after executing instruction */ - memcpy(dsp, &dsp_core_save, sizeof(dsp_core_t)); - - /* Unset DSP in disasm mode */ - dsp->executing_for_disasm = false; - - return instruction_length; -} - void dsp56k_execute_instruction(dsp_core_t* dsp) { uint32_t disasm_return = 0; @@ -644,15 +610,10 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) /* Disasm current instruction ? (trace mode only) */ if (TRACE_DSP_DISASM) { - /* Call disasm_instruction only when DSP is called in trace mode */ - if (!dsp->executing_for_disasm) { - disasm_return = disasm_instruction(dsp, DSP_TRACE_MODE); - - if (disasm_return) { - DPRINTF("%s", disasm_get_instruction_text(dsp)); - } - if (disasm_return != 0 && TRACE_DSP_DISASM_REG) { - /* DSP regs trace enabled only if DSP DISASM is enabled */ + disasm_return = disasm_instruction(dsp, DSP_TRACE_MODE); + if (disasm_return) { + DPRINTF("%s", disasm_get_instruction_text(dsp)); + if (TRACE_DSP_DISASM_REG) { disasm_reg_save(dsp); } } @@ -676,26 +637,18 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) } /* Disasm current instruction ? (trace mode only) */ - if (TRACE_DSP_DISASM) { - /* Display only when DSP is called in trace mode */ - if (!dsp->executing_for_disasm) { - if (disasm_return != 0) { - // DPRINTF("%s", disasm_get_instruction_text(dsp)); - - /* DSP regs trace enabled only if DSP DISASM is enabled */ - if (TRACE_DSP_DISASM_REG) - disasm_reg_compare(dsp); - - if (TRACE_DSP_DISASM_MEM) { - /* 1 memory change to display ? */ - if (dsp->disasm_memory_ptr == 1) - DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); - /* 2 memory changes to display ? */ - else if (dsp->disasm_memory_ptr == 2) { - DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); - DPRINTF("\t%s\n", dsp->str_disasm_memory[1]); - } - } + if (TRACE_DSP_DISASM && disasm_return) { + if (TRACE_DSP_DISASM_REG) { + disasm_reg_compare(dsp); + } + if (TRACE_DSP_DISASM_MEM) { + /* 1 memory change to display ? */ + if (dsp->disasm_memory_ptr == 1) + DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); + /* 2 memory changes to display ? */ + else if (dsp->disasm_memory_ptr == 2) { + DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); + DPRINTF("\t%s\n", dsp->str_disasm_memory[1]); } } } @@ -1103,9 +1056,7 @@ static void dsp_write_reg(dsp_core_t* dsp, uint32_t numreg, uint32_t value) /* Stack underflow or overflow detected, raise interrupt */ dsp56k_add_interrupt(dsp, DSP_INTER_STACK_ERROR); dsp->registers[DSP_REG_SP] = value & (3<executing_for_disasm) { - DPRINTF("Dsp: Stack Overflow or Underflow\n"); - } + DPRINTF("Dsp: Stack Overflow or Underflow\n"); if (dsp->exception_debugging) { assert(false); } @@ -1148,8 +1099,7 @@ static void dsp_stack_push(dsp_core_t* dsp, uint32_t curpc, uint32_t cursr, uint if ((stack_error==0) && (stack & (1<executing_for_disasm) - DPRINTF("Dsp: Stack Overflow\n"); + DPRINTF("Dsp: Stack Overflow\n"); if (dsp->exception_debugging) assert(false); } @@ -1185,8 +1135,7 @@ static void dsp_stack_pop(dsp_core_t* dsp, uint32_t *newpc, uint32_t *newsr) if ((stack_error==0) && (stack & (1<executing_for_disasm) - DPRINTF("Dsp: Stack underflow\n"); + DPRINTF("Dsp: Stack underflow\n"); if (dsp->exception_debugging) assert(false); } diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.h b/hw/xbox/mcpx/dsp/dsp_cpu.h index 4a87868139..4cffd2631d 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.h +++ b/hw/xbox/mcpx/dsp/dsp_cpu.h @@ -101,10 +101,6 @@ struct dsp_core_s { /* Current instruction */ uint32_t cur_inst; - /* DSP is in disasm mode ? */ - /* If yes, stack overflow, underflow and illegal instructions messages are not displayed */ - bool executing_for_disasm; - char str_disasm_memory[2][50]; /* Buffer for memory change text in disasm mode */ uint32_t disasm_memory_ptr; /* Pointer for memory change in disasm mode */ @@ -142,7 +138,6 @@ struct dsp_core_s { /* Functions */ void dsp56k_reset_cpu(dsp_core_t* dsp); /* Set dsp_core to use */ void dsp56k_execute_instruction(dsp_core_t* dsp); /* Execute 1 instruction */ -uint16_t dsp56k_execute_one_disasm_instruction(dsp_core_t* dsp, FILE *out, uint32_t pc); /* Execute 1 instruction in disasm mode */ uint32_t dsp56k_read_memory(dsp_core_t* dsp, int space, uint32_t address); void dsp56k_write_memory(dsp_core_t* dsp, int space, uint32_t address, uint32_t value); diff --git a/hw/xbox/mcpx/dsp/dsp_emu.inl b/hw/xbox/mcpx/dsp/dsp_emu.inl index e509baa2d7..b67ea13398 100644 --- a/hw/xbox/mcpx/dsp/dsp_emu.inl +++ b/hw/xbox/mcpx/dsp/dsp_emu.inl @@ -27,15 +27,10 @@ typedef void (*emu_func_t)(dsp_core_t* dsp); static void emu_undefined(dsp_core_t* dsp) { - if (!dsp->executing_for_disasm) { - dsp->cur_inst_len = 0; - printf("Dsp: 0x%04x: 0x%06x Illegal instruction\n",dsp->pc, dsp->cur_inst); - /* Add some artificial CPU cycles to avoid being stuck in an infinite loop */ - dsp->instr_cycle += 100; - } else { - dsp->cur_inst_len = 1; - dsp->instr_cycle = 0; - } + dsp->cur_inst_len = 0; + printf("Dsp: 0x%04x: 0x%06x Illegal instruction\n",dsp->pc, dsp->cur_inst); + /* Add some artificial CPU cycles to avoid being stuck in an infinite loop */ + dsp->instr_cycle += 100; if (dsp->exception_debugging) { assert(false); } From 4b81c289011d2e085573bc3351cb9425a80856de Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 17 Feb 2025 01:49:29 -0700 Subject: [PATCH 36/68] mcpx/dsp: Migrate some DPRINTFs to trace events --- hw/xbox/mcpx/dsp/dsp.c | 9 ++++----- hw/xbox/mcpx/dsp/dsp_cpu.c | 21 ++++++++++++++------- hw/xbox/mcpx/dsp/trace-events | 9 +++++++++ hw/xbox/mcpx/dsp/trace.h | 1 + meson.build | 1 + 5 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 hw/xbox/mcpx/dsp/trace-events create mode 100644 hw/xbox/mcpx/dsp/trace.h diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index dda5f829e1..32b9c12d40 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -29,6 +29,7 @@ #include "dsp_state.h" #include "dsp.h" #include "debug.h" +#include "trace.h" /* Defines */ #define BITMASK(x) ((1<<(x))-1) @@ -76,8 +77,6 @@ void dsp_destroy(DSPState* dsp) static uint32_t read_peripheral(dsp_core_t* core, uint32_t address) { DSPState* dsp = container_of(core, DSPState, core); - DPRINTF("read_peripheral 0x%06x", address); - uint32_t v = 0xababa; switch(address) { case 0xFFFFB3: @@ -103,15 +102,13 @@ static uint32_t read_peripheral(dsp_core_t* core, uint32_t address) { break; } - DPRINTF(" -> 0x%06x\n", v); + trace_dsp_read_peripheral(address, v); return v; } static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value) { DSPState* dsp = container_of(core, DSPState, core); - DPRINTF("write_peripheral [0x%06x] = 0x%06x\n", address, value); - switch(address) { case 0xFFFFC4: if (value & 1) { @@ -137,6 +134,8 @@ static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value) dsp_dma_write(&dsp->dma, DMA_CONFIGURATION, value); break; } + + trace_dsp_write_peripheral(address, value); } diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 06d4b82ab2..61cce8cf41 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -27,6 +27,7 @@ #include "qemu/bswap.h" #include "dsp_cpu.h" #include "debug.h" +#include "trace.h" #define BITMASK(x) ((1<<(x))-1) @@ -583,21 +584,21 @@ static void disasm_reg_compare(dsp_core_t* dsp) static const char* disasm_get_instruction_text(dsp_core_t* dsp) { - const int len = sizeof(dsp->disasm_str_instr); - if (dsp->disasm_is_looping) { dsp->disasm_str_instr2[0] = 0; } if (dsp->disasm_cur_inst_len == 1) { - snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, dsp->instr_cycle, len, dsp->disasm_str_instr); + snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x (%02d cyc) %s", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, dsp->instr_cycle, dsp->disasm_str_instr); } else { - snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, read_memory_p(dsp, dsp->disasm_prev_inst_pc + 1), dsp->instr_cycle, len, dsp->disasm_str_instr); + snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x %06x (%02d cyc) %s", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, read_memory_p(dsp, dsp->disasm_prev_inst_pc + 1), dsp->instr_cycle, dsp->disasm_str_instr); } return dsp->disasm_str_instr2; } void dsp56k_execute_instruction(dsp_core_t* dsp) { + trace_dsp56k_execute_instruction(dsp->is_gp, dsp->pc); + uint32_t disasm_return = 0; dsp->disasm_memory_ptr = 0; @@ -608,11 +609,17 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) dsp->cur_inst_len = 1; dsp->instr_cycle = 2; + bool tracing = TRACE_DSP_DISASM || trace_event_get_state(TRACE_DSP56K_EXECUTE_INSTRUCTION_DISASM); + /* Disasm current instruction ? (trace mode only) */ - if (TRACE_DSP_DISASM) { + if (tracing) { disasm_return = disasm_instruction(dsp, DSP_TRACE_MODE); if (disasm_return) { - DPRINTF("%s", disasm_get_instruction_text(dsp)); + const char *text = disasm_get_instruction_text(dsp); + trace_dsp56k_execute_instruction_disasm(text); + if (TRACE_DSP_DISASM) { + DPRINTF("%s\n", text); + } if (TRACE_DSP_DISASM_REG) { disasm_reg_save(dsp); } @@ -637,7 +644,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) } /* Disasm current instruction ? (trace mode only) */ - if (TRACE_DSP_DISASM && disasm_return) { + if (tracing && disasm_return) { if (TRACE_DSP_DISASM_REG) { disasm_reg_compare(dsp); } diff --git a/hw/xbox/mcpx/dsp/trace-events b/hw/xbox/mcpx/dsp/trace-events new file mode 100644 index 0000000000..82f10a3f92 --- /dev/null +++ b/hw/xbox/mcpx/dsp/trace-events @@ -0,0 +1,9 @@ +# See docs/devel/tracing.rst for syntax documentation. + +# dsp.c +dsp_read_peripheral(uint32_t addr, uint32_t val) "addr 0x%"PRIx32" val 0x%"PRIx32 +dsp_write_peripheral(uint32_t addr, uint32_t val) "addr 0x%"PRIx32" val 0x%"PRIx32 + +# dsp_cpu.c +dsp56k_execute_instruction(uint32_t id, uint32_t pc) "[gp=%d]: pc=0x%"PRIx32 +dsp56k_execute_instruction_disasm(const char *disasm) "%s" diff --git a/hw/xbox/mcpx/dsp/trace.h b/hw/xbox/mcpx/dsp/trace.h new file mode 100644 index 0000000000..6ab110fe5b --- /dev/null +++ b/hw/xbox/mcpx/dsp/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_xbox_mcpx_dsp.h" diff --git a/meson.build b/meson.build index 72e7049e02..c1e9612bbf 100644 --- a/meson.build +++ b/meson.build @@ -3772,6 +3772,7 @@ if have_system 'hw/remote', 'hw/xbox/nv2a', 'hw/xbox/mcpx', + 'hw/xbox/mcpx/dsp', 'hw/xbox', ] endif From 4a5c91397f7fb00bfa9647204543a14778f74d9b Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 29 Mar 2025 16:03:14 -0700 Subject: [PATCH 37/68] ci: Run xbox tests --- .github/workflows/build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 576d3adf89..fb2a6cc123 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -245,6 +245,11 @@ jobs: echo -e "\n\nCompiler Cache Stats:" ccache -s + - name: Test + run: | + pushd src/build + ./pyvenv/bin/meson test --suite xbox + popd - name: Generate AppImage run: | wget --no-verbose https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-${{ matrix.arch }}.AppImage From e08011b77201920fabd95df9ad2241d1b8883ad5 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 29 Mar 2025 16:10:41 -0700 Subject: [PATCH 38/68] mcpx/dsp: Rename *.inl -> *.c.inc --- hw/xbox/mcpx/dsp/dsp_cpu.c | 5 ++--- hw/xbox/mcpx/dsp/{dsp_dis.inl => dsp_dis.c.inc} | 0 hw/xbox/mcpx/dsp/{dsp_emu.inl => dsp_emu.c.inc} | 0 3 files changed, 2 insertions(+), 3 deletions(-) rename hw/xbox/mcpx/dsp/{dsp_dis.inl => dsp_dis.c.inc} (100%) rename hw/xbox/mcpx/dsp/{dsp_emu.inl => dsp_emu.c.inc} (100%) diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 61cce8cf41..a5b2d64630 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -129,9 +129,8 @@ static const int registers_mask[64] = { 16, 16, 16, 16 }; -#include "dsp_emu.inl" - -#include "dsp_dis.inl" +#include "dsp_emu.c.inc" +#include "dsp_dis.c.inc" typedef bool (*match_func_t)(uint32_t op); diff --git a/hw/xbox/mcpx/dsp/dsp_dis.inl b/hw/xbox/mcpx/dsp/dsp_dis.c.inc similarity index 100% rename from hw/xbox/mcpx/dsp/dsp_dis.inl rename to hw/xbox/mcpx/dsp/dsp_dis.c.inc diff --git a/hw/xbox/mcpx/dsp/dsp_emu.inl b/hw/xbox/mcpx/dsp/dsp_emu.c.inc similarity index 100% rename from hw/xbox/mcpx/dsp/dsp_emu.inl rename to hw/xbox/mcpx/dsp/dsp_emu.c.inc From 9439f605a89e1af0b34a4123a1f79571f105c285 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 29 Mar 2025 17:07:50 -0700 Subject: [PATCH 39/68] mcpx/dsp: Drop redundant value/address assertions --- hw/xbox/mcpx/dsp/dsp_cpu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index a5b2d64630..09cbb7c180 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -961,9 +961,6 @@ uint32_t dsp56k_read_memory(dsp_core_t* dsp, int space, uint32_t address) void dsp56k_write_memory(dsp_core_t* dsp, int space, uint32_t address, uint32_t value) { - assert((value & 0xFF000000) == 0); - assert((address & 0xFF000000) == 0); - if (TRACE_DSP_DISASM_MEM) write_memory_disasm(dsp, space, address, value); else From 57cdee770e228409f1755b636d7075135e046f12 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 29 Mar 2025 17:23:55 -0700 Subject: [PATCH 40/68] mcpx/dsp: Fix some formatting/spelling nits --- hw/xbox/mcpx/dsp/dsp_cpu.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 09cbb7c180..380c07e1bb 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -71,18 +71,18 @@ static void dsp_rnd56(dsp_core_t* dsp, uint32_t *dest); static uint32_t dsp_signextend(int bits, uint32_t v); static const dsp_interrupt_t dsp_interrupt[12] = { - {DSP_INTER_RESET , 0x00, 0, "Reset"}, - {DSP_INTER_ILLEGAL , 0x3e, 0, "Illegal"}, - {DSP_INTER_STACK_ERROR , 0x02, 0, "Stack Error"}, - {DSP_INTER_TRACE , 0x04, 0, "Trace"}, - {DSP_INTER_SWI , 0x06, 0, "Swi"}, - {DSP_INTER_HOST_COMMAND , 0xff, 1, "Host Command"}, - {DSP_INTER_HOST_RCV_DATA, 0x20, 1, "Host receive"}, - {DSP_INTER_HOST_TRX_DATA, 0x22, 1, "Host transmit"}, - {DSP_INTER_SSI_RCV_DATA_E, 0x0e, 2, "SSI receive with exception"}, - {DSP_INTER_SSI_RCV_DATA , 0x0c, 2, "SSI receive"}, - {DSP_INTER_SSI_TRX_DATA_E, 0x12, 2, "SSI transmit with exception"}, - {DSP_INTER_SSI_TRX_DATA , 0x10, 2, "SSI tramsmit"} + { DSP_INTER_RESET, 0x00, 0, "Reset" }, + { DSP_INTER_ILLEGAL, 0x3e, 0, "Illegal" }, + { DSP_INTER_STACK_ERROR, 0x02, 0, "Stack Error" }, + { DSP_INTER_TRACE, 0x04, 0, "Trace" }, + { DSP_INTER_SWI, 0x06, 0, "Swi" }, + { DSP_INTER_HOST_COMMAND, 0xff, 1, "Host Command" }, + { DSP_INTER_HOST_RCV_DATA, 0x20, 1, "Host receive" }, + { DSP_INTER_HOST_TRX_DATA, 0x22, 1, "Host transmit" }, + { DSP_INTER_SSI_RCV_DATA_E, 0x0e, 2, "SSI receive with exception" }, + { DSP_INTER_SSI_RCV_DATA, 0x0c, 2, "SSI receive" }, + { DSP_INTER_SSI_TRX_DATA_E, 0x12, 2, "SSI transmit with exception" }, + { DSP_INTER_SSI_TRX_DATA, 0x10, 2, "SSI transmit" } }; static const int registers_tcc[16][2] = { From f82c6865fc27a07f52470e0a1da30151b130b4a2 Mon Sep 17 00:00:00 2001 From: Mason Thompson <72317541+MasonT8198@users.noreply.github.com> Date: Mon, 31 Mar 2025 18:03:28 -0400 Subject: [PATCH 41/68] control: Add python3-tomli/python3-pip --- debian/control | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/control b/debian/control index eb495ec081..7f5871bbd7 100644 --- a/debian/control +++ b/debian/control @@ -6,6 +6,8 @@ Build-Depends: debhelper (>= 11), cmake, git, python3:any, + python3-pip, + python3-tomli, python3-yaml, python3-venv, ninja-build, From ebec5e30284a6ef2c55fe4f1d1c123eb88c19a74 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Tue, 8 Apr 2025 11:03:00 -0700 Subject: [PATCH 42/68] nv2a: Fix assert when setting fog gen mode to fog_x --- hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 2 +- hw/xbox/nv2a/pgraph/vsh.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 445ce73066..19ebf12f3b 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -414,7 +414,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, " float fogDistance = fogCoord;\n"); break; default: - assert(false); + assert(!"Invalid foggen mode"); break; } diff --git a/hw/xbox/nv2a/pgraph/vsh.h b/hw/xbox/nv2a/pgraph/vsh.h index 405b6c9aa6..36cac16edf 100644 --- a/hw/xbox/nv2a/pgraph/vsh.h +++ b/hw/xbox/nv2a/pgraph/vsh.h @@ -55,8 +55,6 @@ enum VshFoggen { FOGGEN_RADIAL, FOGGEN_PLANAR, FOGGEN_ABS_PLANAR, - FOGGEN_ERROR4, - FOGGEN_ERROR5, FOGGEN_FOG_X }; From 2cc926588b9fea2aa5bd5b4882cb7440c6553991 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Fri, 11 Apr 2025 03:52:24 -0700 Subject: [PATCH 43/68] nv2a/gl: Fix COLOR_LE_G8B8 GL surface format type --- hw/xbox/nv2a/pgraph/gl/constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/nv2a/pgraph/gl/constants.h b/hw/xbox/nv2a/pgraph/gl/constants.h index d78b0054e3..e3e78df8d1 100644 --- a/hw/xbox/nv2a/pgraph/gl/constants.h +++ b/hw/xbox/nv2a/pgraph/gl/constants.h @@ -298,7 +298,7 @@ static const SurfaceFormatInfo kelvin_surface_color_format_gl_map[] = { [NV097_SET_SURFACE_FORMAT_COLOR_LE_B8] = {1, GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_COLOR_ATTACHMENT0}, [NV097_SET_SURFACE_FORMAT_COLOR_LE_G8B8] = - {2, GL_RG8, GL_RG, GL_UNSIGNED_SHORT, GL_COLOR_ATTACHMENT0}, + {2, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, GL_COLOR_ATTACHMENT0}, }; static const SurfaceFormatInfo kelvin_surface_zeta_float_format_gl_map[] = { From 1f876ce0da6e1b6b2396db494e10b8c0b5db8bb0 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Wed, 16 Apr 2025 09:22:56 -0700 Subject: [PATCH 44/68] build.sh: Add xemu_version fallback to macOS builds --- build.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index d84b67ee4b..81fca2fb59 100755 --- a/build.sh +++ b/build.sh @@ -66,8 +66,14 @@ package_macos() { cp Info.plist dist/xemu.app/Contents/ - plutil -replace CFBundleShortVersionString -string $(cat ${project_source_dir}/XEMU_VERSION | cut -f1 -d-) dist/xemu.app/Contents/Info.plist - plutil -replace CFBundleVersion -string $(cat ${project_source_dir}/XEMU_VERSION | cut -f1 -d-) dist/xemu.app/Contents/Info.plist + if [[ -e "${project_source_dir}/XEMU_VERSION" ]]; then + xemu_version="$(cat ${project_source_dir}/XEMU_VERSION | cut -f1 -d-)" + else + xemu_version="0.0.0" + fi + + plutil -replace CFBundleShortVersionString -string "${xemu_version}" dist/xemu.app/Contents/Info.plist + plutil -replace CFBundleVersion -string "${xemu_version}" dist/xemu.app/Contents/Info.plist codesign --force --deep --preserve-metadata=entitlements,requirements,flags,runtime --sign - "${exe_path}" python3 ./scripts/gen-license.py --version-file=macos-libs/$target_arch/INSTALLED > dist/LICENSE.txt From 86c85023e6f970a20c559f717a21dc263ed69dd6 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Wed, 16 Apr 2025 08:15:07 -0700 Subject: [PATCH 45/68] nv2a: Handle SET_FOG_COORD and SET_WEIGHT* commands --- hw/xbox/nv2a/nv2a_regs.h | 5 ++++ hw/xbox/nv2a/pgraph/methods.h.inc | 5 ++++ hw/xbox/nv2a/pgraph/pgraph.c | 47 ++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index fa62536181..99fd3ee526 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -1099,6 +1099,11 @@ # define NV097_SET_TEXCOORD3_4F 0x00001620 # define NV097_SET_TEXCOORD3_2S 0x00001610 # define NV097_SET_TEXCOORD3_4S 0x00001630 +# define NV097_SET_FOG_COORD 0x00001698 +# define NV097_SET_WEIGHT1F 0x0000169C +# define NV097_SET_WEIGHT2F 0x000016A0 +# define NV097_SET_WEIGHT3F 0x000016B0 +# define NV097_SET_WEIGHT4F 0x000016C0 # define NV097_SET_VERTEX_DATA_ARRAY_OFFSET 0x00001720 # define NV097_SET_VERTEX_DATA_ARRAY_FORMAT 0x00001760 # define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE 0x0000000F diff --git a/hw/xbox/nv2a/pgraph/methods.h.inc b/hw/xbox/nv2a/pgraph/methods.h.inc index fd6184426e..d2892c5501 100644 --- a/hw/xbox/nv2a/pgraph/methods.h.inc +++ b/hw/xbox/nv2a/pgraph/methods.h.inc @@ -134,6 +134,11 @@ DEF_METHOD_RANGE(NV097, SET_TEXCOORD3_2F, 2) DEF_METHOD_RANGE(NV097, SET_TEXCOORD3_4F, 4) DEF_METHOD_RANGE(NV097, SET_TEXCOORD3_2S, 1) DEF_METHOD_RANGE(NV097, SET_TEXCOORD3_4S, 2) +DEF_METHOD(NV097, SET_FOG_COORD) +DEF_METHOD(NV097, SET_WEIGHT1F) +DEF_METHOD_RANGE(NV097, SET_WEIGHT2F, 2) +DEF_METHOD_RANGE(NV097, SET_WEIGHT3F, 3) +DEF_METHOD_RANGE(NV097, SET_WEIGHT4F, 4) DEF_METHOD_RANGE(NV097, SET_VERTEX_DATA_ARRAY_FORMAT, 16) DEF_METHOD_RANGE(NV097, SET_VERTEX_DATA_ARRAY_OFFSET, 16) DEF_METHOD(NV097, SET_LOGIC_OP_ENABLE) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index 0f17fde184..14de8a78ff 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -2010,6 +2010,26 @@ DEF_METHOD_INC(NV097, SET_VERTEX4F) } } +DEF_METHOD(NV097, SET_FOG_COORD) +{ + VertexAttribute *attribute = &pg->vertex_attributes[NV2A_VERTEX_ATTR_FOG]; + pgraph_allocate_inline_buffer_vertices(pg, NV2A_VERTEX_ATTR_FOG); + attribute->inline_value[0] = *(float*)¶meter; + attribute->inline_value[1] = attribute->inline_value[0]; + attribute->inline_value[2] = attribute->inline_value[0]; + attribute->inline_value[3] = attribute->inline_value[0]; +} + +DEF_METHOD(NV097, SET_WEIGHT1F) +{ + VertexAttribute *attribute = &pg->vertex_attributes[NV2A_VERTEX_ATTR_WEIGHT]; + pgraph_allocate_inline_buffer_vertices(pg, NV2A_VERTEX_ATTR_WEIGHT); + attribute->inline_value[0] = *(float*)¶meter; + attribute->inline_value[1] = 0.f; + attribute->inline_value[2] = 0.f; + attribute->inline_value[3] = 1.f; +} + DEF_METHOD_INC(NV097, SET_NORMAL3S) { int slot = (method - NV097_SET_NORMAL3S) / 4; @@ -2144,7 +2164,6 @@ DEF_METHOD_INC(NV097, SET_TEXCOORD1_4F) SET_VERTEX_ATTRIBUTE_F(NV097_SET_TEXCOORD1_4F, NV2A_VERTEX_ATTR_TEXTURE1); } - DEF_METHOD_INC(NV097, SET_TEXCOORD2_4F) { SET_VERTEX_ATTRIBUTE_F(NV097_SET_TEXCOORD2_4F, NV2A_VERTEX_ATTR_TEXTURE2); @@ -2155,8 +2174,34 @@ DEF_METHOD_INC(NV097, SET_TEXCOORD3_4F) SET_VERTEX_ATTRIBUTE_F(NV097_SET_TEXCOORD3_4F, NV2A_VERTEX_ATTR_TEXTURE3); } +DEF_METHOD_INC(NV097, SET_WEIGHT4F) +{ + SET_VERTEX_ATTRIBUTE_F(NV097_SET_WEIGHT4F, NV2A_VERTEX_ATTR_WEIGHT); +} + #undef SET_VERTEX_ATTRIBUTE_F +DEF_METHOD_INC(NV097, SET_WEIGHT2F) +{ + int slot = (method - NV097_SET_WEIGHT2F) / 4; + VertexAttribute *attribute = + &pg->vertex_attributes[NV2A_VERTEX_ATTR_WEIGHT]; + pgraph_allocate_inline_buffer_vertices(pg, NV2A_VERTEX_ATTR_WEIGHT); + attribute->inline_value[slot] = *(float*)¶meter; + attribute->inline_value[2] = 0.0f; + attribute->inline_value[3] = 1.0f; +} + +DEF_METHOD_INC(NV097, SET_WEIGHT3F) +{ + int slot = (method - NV097_SET_WEIGHT3F) / 4; + VertexAttribute *attribute = + &pg->vertex_attributes[NV2A_VERTEX_ATTR_WEIGHT]; + pgraph_allocate_inline_buffer_vertices(pg, NV2A_VERTEX_ATTR_WEIGHT); + attribute->inline_value[slot] = *(float*)¶meter; + attribute->inline_value[3] = 1.0f; +} + #define SET_VERTEX_ATRIBUTE_TEX_2F(command, attr_index) \ do { \ int slot = (method - (command)) / 4; \ From 7a34eedd6fe699dc7d55686e005d1d4205e8ad8c Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Wed, 26 Mar 2025 14:10:06 -0700 Subject: [PATCH 46/68] nv2a: Partially handle SET_LIGHT_CONTROL --- hw/xbox/nv2a/nv2a_regs.h | 7 +++++++ hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 20 ++++++++++++++++---- hw/xbox/nv2a/pgraph/glsl/vsh.c | 7 +++++++ hw/xbox/nv2a/pgraph/methods.h.inc | 1 + hw/xbox/nv2a/pgraph/pgraph.c | 12 ++++++++++++ hw/xbox/nv2a/pgraph/shaders.c | 5 +++++ hw/xbox/nv2a/pgraph/shaders.h | 3 +++ 7 files changed, 51 insertions(+), 4 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 99fd3ee526..0990d635fe 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -315,11 +315,14 @@ #define NV_PGRAPH_CSV0_C 0x00000FB8 # define NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START 0x0000FF00 # define NV_PGRAPH_CSV0_C_SPECULAR_ENABLE (1 << 16) +# define NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR (1 << 17) +# define NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR (1 << 18) # define NV_PGRAPH_CSV0_C_SPECULAR (3 << 19) # define NV_PGRAPH_CSV0_C_DIFFUSE (3 << 21) # define NV_PGRAPH_CSV0_C_AMBIENT (3 << 23) # define NV_PGRAPH_CSV0_C_EMISSION (3 << 25) # define NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE (1 << 27) +# define NV_PGRAPH_CSV0_C_LOCALEYE (1 << 30) # define NV_PGRAPH_CSV0_C_LIGHTING (1 << 31) #define NV_PGRAPH_CSV1_B 0x00000FBC #define NV_PGRAPH_CSV1_A 0x00000FC0 @@ -882,6 +885,10 @@ # define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0) # define NV097_SET_CONTROL0_Z_FORMAT (1 << 12) # define NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE (1 << 16) +# define NV097_SET_LIGHT_CONTROL 0x00000294 +# define NV097_SET_LIGHT_CONTROL_SEPARATE_SPECULAR 1 +# define NV097_SET_LIGHT_CONTROL_LOCALEYE (1 << 16) +# define NV097_SET_LIGHT_CONTROL_ALPHA_FROM_MATERIAL_SPECULAR (1 << 17) # define NV097_SET_COLOR_MATERIAL 0x00000298 # define NV097_SET_FOG_MODE 0x0000029C # define NV097_SET_FOG_MODE_V_LINEAR 0x2601 diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 19ebf12f3b..52e6296791 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -384,13 +384,25 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, " oD1 = specular;\n"); } - if (!state->specular_enable) { - mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); - } - mstring_append(body, " oB0 = backDiffuse;\n"); mstring_append(body, " oB1 = backSpecular;\n"); + if (!state->specular_enable) { + mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); + mstring_append(body, " oB1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); + } else { + if (!state->separate_specular) { + mstring_append(body, " oD1 = specular;\n"); + mstring_append(body, " oB1 = backSpecular;\n"); + } + if (state->ignore_specular_alpha) { + mstring_append(body, + " oD1.w = 1.0;\n" + " oB1.a = 1.0;\n" + ); + } + } + /* Fog */ if (state->fog_enable) { diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh.c b/hw/xbox/nv2a/pgraph/glsl/vsh.c index 5fff5cf410..25c846bbde 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh.c @@ -256,6 +256,13 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) " vtxD1 = clamp(oD1, 0.0, 1.0);\n" " vtxB1 = clamp(oB1, 0.0, 1.0);\n" ); + + if (state->ignore_specular_alpha) { + mstring_append(body, + " vtxD1.w = 1.0;\n" + " vtxB1.w = 1.0;\n" + ); + } } else { mstring_append(body, " vtxD1 = vec4(0.0, 0.0, 0.0, 1.0);\n" diff --git a/hw/xbox/nv2a/pgraph/methods.h.inc b/hw/xbox/nv2a/pgraph/methods.h.inc index d2892c5501..0b3c014e7d 100644 --- a/hw/xbox/nv2a/pgraph/methods.h.inc +++ b/hw/xbox/nv2a/pgraph/methods.h.inc @@ -27,6 +27,7 @@ DEF_METHOD(NV097, SET_COMBINER_SPECULAR_FOG_CW0) DEF_METHOD(NV097, SET_COMBINER_SPECULAR_FOG_CW1) DEF_METHOD_CASE_4(NV097, SET_TEXTURE_ADDRESS, 64) DEF_METHOD(NV097, SET_CONTROL0) +DEF_METHOD(NV097, SET_LIGHT_CONTROL) DEF_METHOD(NV097, SET_COLOR_MATERIAL) DEF_METHOD(NV097, SET_FOG_MODE) DEF_METHOD(NV097, SET_FOG_GEN_MODE) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index 14de8a78ff..fa6d734405 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -1075,6 +1075,18 @@ DEF_METHOD(NV097, SET_CONTROL0) z_perspective); } +DEF_METHOD(NV097, SET_LIGHT_CONTROL) +{ + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR, + (parameter & NV097_SET_LIGHT_CONTROL_SEPARATE_SPECULAR) != 0); + + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_LOCALEYE, + (parameter & NV097_SET_LIGHT_CONTROL_LOCALEYE) != 0); + + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR, + (parameter & NV097_SET_LIGHT_CONTROL_ALPHA_FROM_MATERIAL_SPECULAR) != 0); +} + DEF_METHOD(NV097, SET_COLOR_MATERIAL) { PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_EMISSION, diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c index dce6d05bb3..ce80dc127a 100644 --- a/hw/xbox/nv2a/pgraph/shaders.c +++ b/hw/xbox/nv2a/pgraph/shaders.c @@ -92,6 +92,11 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg) pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SPECULAR); } + state.separate_specular = GET_MASK( + pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR); + state.ignore_specular_alpha = !GET_MASK( + pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR); + /* vertex program stuff */ state.vertex_program = vertex_program, state.z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) & diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/shaders.h index 7ff93a6302..9496cbbea2 100644 --- a/hw/xbox/nv2a/pgraph/shaders.h +++ b/hw/xbox/nv2a/pgraph/shaders.h @@ -79,6 +79,9 @@ typedef struct ShaderState { enum MaterialColorSource diffuse_src; enum MaterialColorSource specular_src; + bool separate_specular; + bool ignore_specular_alpha; + bool lighting; enum VshLight light[NV2A_MAX_LIGHTS]; From 69c8df2a3e3e342e3ef99c817638b6c7793bd6fb Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Sat, 29 Mar 2025 11:40:57 -0700 Subject: [PATCH 47/68] nv2a: Partial implementation of SET_SPECULAR_PARAMS --- hw/xbox/nv2a/nv2a_regs.h | 2 + hw/xbox/nv2a/pgraph/gl/renderer.h | 1 + hw/xbox/nv2a/pgraph/gl/shaders.c | 7 ++ hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 66 ++++++++++------- hw/xbox/nv2a/pgraph/methods.h.inc | 2 + hw/xbox/nv2a/pgraph/pgraph.c | 118 ++++++++++++++++++++++++++++++ hw/xbox/nv2a/pgraph/pgraph.h | 5 ++ hw/xbox/nv2a/pgraph/shaders.c | 3 + hw/xbox/nv2a/pgraph/shaders.h | 2 + hw/xbox/nv2a/pgraph/vk/renderer.h | 1 + 10 files changed, 181 insertions(+), 26 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 0990d635fe..0c0fb70eef 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -1056,6 +1056,7 @@ # define NV097_SET_TEXGEN_VIEW_MODEL_LOCAL_VIEWER 0 # define NV097_SET_TEXGEN_VIEW_MODEL_INFINITE_VIEWER 1 # define NV097_SET_FOG_PLANE 0x000009D0 +# define NV097_SET_SPECULAR_PARAMS 0x000009E0 # define NV097_SET_SCENE_AMBIENT_COLOR 0x00000A10 # define NV097_SET_VIEWPORT_OFFSET 0x00000A20 # define NV097_SET_POINT_PARAMS 0x00000A30 @@ -1264,6 +1265,7 @@ # define NV097_SET_CLEAR_RECT_HORIZONTAL 0x00001D98 # define NV097_SET_CLEAR_RECT_VERTICAL 0x00001D9C # define NV097_SET_SPECULAR_FOG_FACTOR 0x00001E20 +# define NV097_SET_SPECULAR_PARAMS_BACK 0x00001E28 # define NV097_SET_COMBINER_COLOR_OCW 0x00001E40 # define NV097_SET_COMBINER_CONTROL 0x00001E60 # define NV097_SET_SHADOW_ZSLOPE_THRESHOLD 0x00001E68 diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.h b/hw/xbox/nv2a/pgraph/gl/renderer.h index 3529006898..89ed6ecfd3 100644 --- a/hw/xbox/nv2a/pgraph/gl/renderer.h +++ b/hw/xbox/nv2a/pgraph/gl/renderer.h @@ -122,6 +122,7 @@ typedef struct ShaderBinding { GLint light_infinite_direction_loc[NV2A_MAX_LIGHTS]; GLint light_local_position_loc[NV2A_MAX_LIGHTS]; GLint light_local_attenuation_loc[NV2A_MAX_LIGHTS]; + int specular_power_loc; GLint clip_region_loc[8]; diff --git a/hw/xbox/nv2a/pgraph/gl/shaders.c b/hw/xbox/nv2a/pgraph/gl/shaders.c index ad1c21f4a2..ad2f3e1b9b 100644 --- a/hw/xbox/nv2a/pgraph/gl/shaders.c +++ b/hw/xbox/nv2a/pgraph/gl/shaders.c @@ -193,8 +193,11 @@ static void update_shader_constant_locations(ShaderBinding *binding) if (binding->state.fixed_function) { binding->material_alpha_loc = glGetUniformLocation(binding->gl_program, "material_alpha"); + binding->specular_power_loc = + glGetUniformLocation(binding->gl_program, "specularPower"); } else { binding->material_alpha_loc = -1; + binding->specular_power_loc = -1; } } @@ -836,6 +839,10 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding, } } + if (binding->specular_power_loc != -1) { + glUniform1f(binding->specular_power_loc, pg->specular_power); + } + /* estimate the viewport by assuming it matches the surface ... */ unsigned int aa_width = 1, aa_height = 1; pgraph_apply_anti_aliasing_factor(pg, &aa_width, &aa_height); diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 52e6296791..a26c1fa17f 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -230,10 +230,16 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz } /* Lighting */ - if (state->lighting) { - + if (!state->lighting) { + mstring_append(body, " oD0 = diffuse;\n"); + mstring_append(body, " oD1 = specular;\n"); + mstring_append(body, " oB0 = backDiffuse;\n"); + mstring_append(body, " oB1 = backSpecular;\n"); + } else { //FIXME: Do 2 passes if we want 2 sided-lighting? + mstring_append_fmt(uniforms, "%sfloat specularPower;\n", u); + static char alpha_source_diffuse[] = "diffuse.a"; static char alpha_source_specular[] = "specular.a"; static char alpha_source_material[] = "material_alpha"; @@ -269,12 +275,6 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz continue; } - /* FIXME: It seems that we only have to handle the surface colors if - * they are not part of the material [= vertex colors]. - * If they are material the cpu will premultiply light - * colors - */ - mstring_append_fmt(body, "/* Light %d */ {\n", i); if (state->light[i] == LIGHT_LOCAL @@ -310,14 +310,10 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz u, i, u, i); mstring_append_fmt(body, " float attenuation = 1.0;\n" - " float nDotVP = max(0.0, dot(tNormal, normalize(vec3(lightInfiniteDirection%d))));\n" - " float nDotHV = max(0.0, dot(tNormal, vec3(lightInfiniteHalfVector%d)));\n", + " float nDotVP = max(0.0, dot(tNormal, normalize(lightInfiniteDirection%d)));\n" + " float nDotHV = max(0.0, dot(tNormal, lightInfiniteHalfVector%d));\n", i, i); - /* FIXME: Do specular */ - - /* FIXME: tBackDiffuse */ - break; case LIGHT_LOCAL: /* Everything done already */ @@ -349,11 +345,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz " if (nDotVP == 0.0) {\n" " pf = 0.0;\n" " } else {\n" - " pf = pow(nDotHV, /* specular(l, m, n, l1, m1, n1) */ 0.001);\n" + " pf = pow(nDotHV, specularPower);\n" " }\n" " vec3 lightAmbient = lightAmbientColor(%d) * attenuation;\n" " vec3 lightDiffuse = lightDiffuseColor(%d) * attenuation * nDotVP;\n" - " vec3 lightSpecular = lightSpecularColor(%d) * pf;\n", + " vec3 lightSpecular = lightSpecularColor(%d) * attenuation * pf;\n", i, i, i); mstring_append(body, @@ -374,26 +370,44 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz break; } - mstring_append(body, - " oD1.xyz += specular.xyz * lightSpecular;\n"); + switch (state->specular_src) { + case MATERIAL_COLOR_SRC_MATERIAL: + mstring_append(body, + " oD1.xyz += lightSpecular;\n"); + break; + case MATERIAL_COLOR_SRC_DIFFUSE: + mstring_append(body, + " oD1.xyz += diffuse.xyz * lightSpecular;\n"); + break; + case MATERIAL_COLOR_SRC_SPECULAR: + mstring_append(body, + " oD1.xyz += specular.xyz * lightSpecular;\n"); + break; + } mstring_append(body, "}\n"); } - } else { - mstring_append(body, " oD0 = diffuse;\n"); - mstring_append(body, " oD1 = specular;\n"); - } - mstring_append(body, " oB0 = backDiffuse;\n"); - mstring_append(body, " oB1 = backSpecular;\n"); + /* TODO: Implement two-sided lighting */ + mstring_append(body, " oB0 = backDiffuse;\n"); + mstring_append(body, " oB1 = backSpecular;\n"); + } if (!state->specular_enable) { mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); mstring_append(body, " oB1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); } else { if (!state->separate_specular) { - mstring_append(body, " oD1 = specular;\n"); - mstring_append(body, " oB1 = backSpecular;\n"); + if (state->lighting) { + mstring_append(body, + " oD0.xyz += oD1.xyz;\n" + " oB0.xyz += oB1.xyz;\n" + ); + } + mstring_append(body, + " oD1 = specular;\n" + " oB1 = backSpecular;\n" + ); } if (state->ignore_specular_alpha) { mstring_append(body, diff --git a/hw/xbox/nv2a/pgraph/methods.h.inc b/hw/xbox/nv2a/pgraph/methods.h.inc index 0b3c014e7d..2f7b7b4198 100644 --- a/hw/xbox/nv2a/pgraph/methods.h.inc +++ b/hw/xbox/nv2a/pgraph/methods.h.inc @@ -96,6 +96,7 @@ DEF_METHOD_RANGE(NV097, SET_FOG_PARAMS, 3) DEF_METHOD_RANGE(NV097, SET_TEXGEN_PLANE_S, 4*4*4) DEF_METHOD(NV097, SET_TEXGEN_VIEW_MODEL) DEF_METHOD_RANGE(NV097, SET_FOG_PLANE, 4) +DEF_METHOD_RANGE(NV097, SET_SPECULAR_PARAMS, 6) DEF_METHOD_RANGE(NV097, SET_SCENE_AMBIENT_COLOR, 3) DEF_METHOD_RANGE(NV097, SET_VIEWPORT_OFFSET, 4) DEF_METHOD_RANGE(NV097, SET_POINT_PARAMS, 8) @@ -183,6 +184,7 @@ DEF_METHOD(NV097, CLEAR_SURFACE) DEF_METHOD(NV097, SET_CLEAR_RECT_HORIZONTAL) DEF_METHOD(NV097, SET_CLEAR_RECT_VERTICAL) DEF_METHOD_RANGE(NV097, SET_SPECULAR_FOG_FACTOR, 2) +DEF_METHOD_RANGE(NV097, SET_SPECULAR_PARAMS_BACK, 6) DEF_METHOD(NV097, SET_SHADER_CLIP_PLANE_MODE) DEF_METHOD_RANGE(NV097, SET_COMBINER_COLOR_OCW, 8) DEF_METHOD(NV097, SET_COMBINER_CONTROL) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index fa6d734405..feb5f858ca 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -19,6 +19,8 @@ * License along with this library; if not, see . */ +#include + #include "hw/xbox/nv2a/nv2a_int.h" #include "ui/xemu-notifications.h" #include "ui/xemu-settings.h" @@ -1803,6 +1805,113 @@ DEF_METHOD_INC(NV097, SET_FOG_PLANE) pg->vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_FOG] = true; } +struct CurveCoefficients { + float a; + float b; + float c; +}; + +static const struct CurveCoefficients curve_coefficients[] = { + {1.000108475163, -9.838607076280, 54.829089549713}, + {1.199164441703, -3.292603784852, 7.799987995214}, + {8.653441252033, 29.189473787191, 43.586027561823}, + {-531.307758450301, 117.398468683934, 113.155490738338}, + {-4.662713151292, 1.221108944572, 1.217360986939}, + {-124.435242105211, 35.401219563514, 35.408114377045}, + {10672560.259502287954, 21565843.555823743343, 10894794.336297152564}, + {-51973801.463933646679, -104199997.554352939129, -52225454.356278456748}, + {972270.324080004124, 2025882.096547174733, 1054898.052467488218}, +}; + +static const float kCoefficient0StepPoints[] = { + -0.022553957999, // power = 1.25 + -0.421539008617, // power = 4.00 + -0.678715527058, // power = 9.00 + -0.838916420937, // power = 20.00 + -0.961754500866, // power = 90.00 + -0.990773200989, // power = 375.00 + -0.994858562946, // power = 650.00 + -0.996561050415, // power = 1000.00 + -0.999547004700, // power = 1250.00 +}; + +static float reconstruct_quadratic(float c0, const struct CurveCoefficients *coefficients) { + return coefficients->a + coefficients->b * c0 + coefficients->c * c0 * c0; +} + +static float reconstruct_saturation_growth_rate(float c0, const struct CurveCoefficients *coefficients) { + return (coefficients->a * c0) / (coefficients->b + coefficients->c * c0); +} + +static float (* const reconstruct_func_map[])(float, const struct CurveCoefficients *) = { + reconstruct_quadratic, // 1.0..1.25 max error 0.01 % + reconstruct_quadratic, // 1.25..4.0 max error 2.2 % + reconstruct_quadratic, // 4.0..9.0 max error 2.3 % + reconstruct_saturation_growth_rate, // 9.0..20.0 max error 1.4 % + reconstruct_saturation_growth_rate, // 20.0..90.0 max error 2.1 % + reconstruct_saturation_growth_rate, // 90.0..375.0 max error 2.8% + reconstruct_quadratic, // 375..650 max error 1.0 % + reconstruct_quadratic, // 650..1000 max error 1.7% + reconstruct_quadratic, // 1000..1250 max error 1.0% +}; + +static float reconstruct_specular_power(const float *params) { + // See https://github.com/dracc/xgu/blob/db3172d8c983629f0dc971092981846da22438ae/xgux.h#L279 + + // Values < 1.0 will result in a positive c1 and (c2 - c0 * 2) will be very + // close to the original value. + if (params[1] > 0.0f && params[2] < 1.0f) { + return params[2] - (params[0] * 2.0f); + } + + float c0 = params[0]; + float c3 = params[3]; + // FIXME: This handling is not correct, but is distinct without crashing. + // It does not appear possible for a DirectX-generated value to be positive, + // so while this differs from hardware behavior, it may be irrelevant in + // practice. + if (c0 > 0.0f || c3 > 0.0f) { + return 0.0001f; + } + + float reconstructed_power = 0.f; + for (uint32_t i = 0; i < sizeof(kCoefficient0StepPoints) / sizeof(kCoefficient0StepPoints[0]); ++i) { + if (c0 > kCoefficient0StepPoints[i]) { + reconstructed_power = reconstruct_func_map[i](c0, &curve_coefficients[i]); + break; + } + } + + float reconstructed_half_power = 0.f; + for (uint32_t i = 0; i < sizeof(kCoefficient0StepPoints) / sizeof(kCoefficient0StepPoints[0]); ++i) { + if (c3 > kCoefficient0StepPoints[i]) { + reconstructed_half_power = reconstruct_func_map[i](c3, &curve_coefficients[i]); + break; + } + } + + // The range can be extended beyond 1250 by using the half power params. This + // will only work for DirectX generated values, arbitrary params could + // erroneously trigger this. + // + // There are some very low power (~1) values that have inverted powers, but + // they are easily identified by comparatively high c0 parameters. + if (reconstructed_power == 0.f || (reconstructed_half_power > reconstructed_power && c0 < -0.1f)) { + return reconstructed_half_power * 2.f; + } + + return reconstructed_power; +} + +DEF_METHOD_INC(NV097, SET_SPECULAR_PARAMS) +{ + int slot = (method - NV097_SET_SPECULAR_PARAMS) / 4; + pg->specular_params[slot] = *(float *)¶meter; + if (slot == 5) { + pg->specular_power = reconstruct_specular_power(pg->specular_params); + } +} + DEF_METHOD_INC(NV097, SET_SCENE_AMBIENT_COLOR) { int slot = (method - NV097_SET_SCENE_AMBIENT_COLOR) / 4; @@ -2785,6 +2894,15 @@ DEF_METHOD_INC(NV097, SET_SPECULAR_FOG_FACTOR) pgraph_reg_w(pg, NV_PGRAPH_SPECFOGFACTOR0 + slot*4, parameter); } +DEF_METHOD_INC(NV097, SET_SPECULAR_PARAMS_BACK) +{ + int slot = (method - NV097_SET_SPECULAR_PARAMS_BACK) / 4; + pg->specular_params_back[slot] = *(float *)¶meter; + if (slot == 5) { + pg->specular_power_back = reconstruct_specular_power(pg->specular_params_back); + } +} + DEF_METHOD(NV097, SET_SHADER_CLIP_PLANE_MODE) { pgraph_reg_w(pg, NV_PGRAPH_SHADERCLIPMODE, parameter); diff --git a/hw/xbox/nv2a/pgraph/pgraph.h b/hw/xbox/nv2a/pgraph/pgraph.h index 64b671e71d..c74e370bba 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.h +++ b/hw/xbox/nv2a/pgraph/pgraph.h @@ -197,6 +197,11 @@ typedef struct PGRAPHState { float light_local_position[NV2A_MAX_LIGHTS][3]; float light_local_attenuation[NV2A_MAX_LIGHTS][3]; + float specular_params[6]; + float specular_power; + float specular_params_back[6]; + float specular_power_back; + float point_params[8]; VertexAttribute vertex_attributes[NV2A_VERTEXSHADER_ATTRIBUTES]; diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c index ce80dc127a..79f66026d9 100644 --- a/hw/xbox/nv2a/pgraph/shaders.c +++ b/hw/xbox/nv2a/pgraph/shaders.c @@ -97,6 +97,9 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg) state.ignore_specular_alpha = !GET_MASK( pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR); + state.specular_power = pg->specular_power; + state.specular_power_back = pg->specular_power_back; + /* vertex program stuff */ state.vertex_program = vertex_program, state.z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) & diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/shaders.h index 9496cbbea2..b384b679bf 100644 --- a/hw/xbox/nv2a/pgraph/shaders.h +++ b/hw/xbox/nv2a/pgraph/shaders.h @@ -81,6 +81,8 @@ typedef struct ShaderState { bool separate_specular; bool ignore_specular_alpha; + float specular_power; + float specular_power_back; bool lighting; enum VshLight light[NV2A_MAX_LIGHTS]; diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.h b/hw/xbox/nv2a/pgraph/vk/renderer.h index eb0726ac2f..d728805475 100644 --- a/hw/xbox/nv2a/pgraph/vk/renderer.h +++ b/hw/xbox/nv2a/pgraph/vk/renderer.h @@ -190,6 +190,7 @@ typedef struct ShaderBinding { int light_infinite_direction_loc[NV2A_MAX_LIGHTS]; int light_local_position_loc[NV2A_MAX_LIGHTS]; int light_local_attenuation_loc[NV2A_MAX_LIGHTS]; + int specular_power_loc; int clip_region_loc; From 34ed0f75dea71a4479bacb4ae73207dee5d41e83 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Sun, 30 Mar 2025 18:08:02 -0700 Subject: [PATCH 48/68] nv2a: Handle LOCAL_RANGE --- hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 84 ++++++++++++++++--------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index a26c1fa17f..74ee67c4ad 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -287,15 +287,15 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append_fmt(body, " vec3 VP = lightLocalPosition%d - tPosition.xyz/tPosition.w;\n" " float d = length(VP);\n" -//FIXME: if (d > lightLocalRange) { .. don't process this light .. } /* inclusive?! */ - what about directional lights? - " VP = normalize(VP);\n" - " float attenuation = 1.0 / (lightLocalAttenuation%d.x\n" - " + lightLocalAttenuation%d.y * d\n" - " + lightLocalAttenuation%d.z * d * d);\n" - " vec3 halfVector = normalize(VP + eyePosition.xyz / eyePosition.w);\n" /* FIXME: Not sure if eyePosition is correct */ - " float nDotVP = max(0.0, dot(tNormal, VP));\n" - " float nDotHV = max(0.0, dot(tNormal, halfVector));\n", - i, i, i, i); + " if (d <= lightLocalRange(%d)) {\n" /* FIXME: Double check that range is inclusive */ + " VP = normalize(VP);\n" + " float attenuation = 1.0 / (lightLocalAttenuation%d.x\n" + " + lightLocalAttenuation%d.y * d\n" + " + lightLocalAttenuation%d.z * d * d);\n" + " vec3 halfVector = normalize(VP + eyePosition.xyz / eyePosition.w);\n" /* FIXME: Not sure if eyePosition is correct */ + " float nDotVP = max(0.0, dot(tNormal, VP));\n" + " float nDotHV = max(0.0, dot(tNormal, halfVector));\n", + i, i, i, i, i); } @@ -309,9 +309,10 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz "%svec3 lightInfiniteDirection%d;\n", u, i, u, i); mstring_append_fmt(body, - " float attenuation = 1.0;\n" - " float nDotVP = max(0.0, dot(tNormal, normalize(lightInfiniteDirection%d)));\n" - " float nDotHV = max(0.0, dot(tNormal, lightInfiniteHalfVector%d));\n", + " {\n" + " float attenuation = 1.0;\n" + " float nDotVP = max(0.0, dot(tNormal, normalize(lightInfiniteDirection%d)));\n" + " float nDotHV = max(0.0, dot(tNormal, lightInfiniteHalfVector%d));\n", i, i); break; @@ -321,18 +322,18 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz case LIGHT_SPOT: /* https://docs.microsoft.com/en-us/windows/win32/direct3d9/attenuation-and-spotlight-factor#spotlight-factor */ mstring_append_fmt(body, - " vec4 spotDir = lightSpotDirection(%d);\n" - " float invScale = 1/length(spotDir.xyz);\n" - " float cosHalfPhi = -invScale*spotDir.w;\n" - " float cosHalfTheta = invScale + cosHalfPhi;\n" - " float spotDirDotVP = dot(spotDir.xyz, VP);\n" - " float rho = invScale*spotDirDotVP;\n" - " if (rho > cosHalfTheta) {\n" - " } else if (rho <= cosHalfPhi) {\n" - " attenuation = 0.0;\n" - " } else {\n" - " attenuation *= spotDirDotVP + spotDir.w;\n" /* FIXME: lightSpotFalloff */ - " }\n", + " vec4 spotDir = lightSpotDirection(%d);\n" + " float invScale = 1/length(spotDir.xyz);\n" + " float cosHalfPhi = -invScale*spotDir.w;\n" + " float cosHalfTheta = invScale + cosHalfPhi;\n" + " float spotDirDotVP = dot(spotDir.xyz, VP);\n" + " float rho = invScale*spotDirDotVP;\n" + " if (rho > cosHalfTheta) {\n" + " } else if (rho <= cosHalfPhi) {\n" + " attenuation = 0.0;\n" + " } else {\n" + " attenuation *= spotDirDotVP + spotDir.w;\n" /* FIXME: lightSpotFalloff */ + " }\n", i); break; default: @@ -341,51 +342,52 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz } mstring_append_fmt(body, - " float pf;\n" - " if (nDotVP == 0.0) {\n" - " pf = 0.0;\n" - " } else {\n" - " pf = pow(nDotHV, specularPower);\n" - " }\n" - " vec3 lightAmbient = lightAmbientColor(%d) * attenuation;\n" - " vec3 lightDiffuse = lightDiffuseColor(%d) * attenuation * nDotVP;\n" - " vec3 lightSpecular = lightSpecularColor(%d) * attenuation * pf;\n", + " float pf;\n" + " if (nDotVP == 0.0) {\n" + " pf = 0.0;\n" + " } else {\n" + " pf = pow(nDotHV, specularPower);\n" + " }\n" + " vec3 lightAmbient = lightAmbientColor(%d) * attenuation;\n" + " vec3 lightDiffuse = lightDiffuseColor(%d) * attenuation * nDotVP;\n" + " vec3 lightSpecular = lightSpecularColor(%d) * attenuation * pf;\n", i, i, i); mstring_append(body, - " oD0.xyz += lightAmbient;\n"); + " oD0.xyz += lightAmbient;\n"); switch (state->diffuse_src) { case MATERIAL_COLOR_SRC_MATERIAL: mstring_append(body, - " oD0.xyz += lightDiffuse;\n"); + " oD0.xyz += lightDiffuse;\n"); break; case MATERIAL_COLOR_SRC_DIFFUSE: mstring_append(body, - " oD0.xyz += diffuse.xyz * lightDiffuse;\n"); + " oD0.xyz += diffuse.xyz * lightDiffuse;\n"); break; case MATERIAL_COLOR_SRC_SPECULAR: mstring_append(body, - " oD0.xyz += specular.xyz * lightDiffuse;\n"); + " oD0.xyz += specular.xyz * lightDiffuse;\n"); break; } switch (state->specular_src) { case MATERIAL_COLOR_SRC_MATERIAL: mstring_append(body, - " oD1.xyz += lightSpecular;\n"); + " oD1.xyz += lightSpecular;\n"); break; case MATERIAL_COLOR_SRC_DIFFUSE: mstring_append(body, - " oD1.xyz += diffuse.xyz * lightSpecular;\n"); + " oD1.xyz += diffuse.xyz * lightSpecular;\n"); break; case MATERIAL_COLOR_SRC_SPECULAR: mstring_append(body, - " oD1.xyz += specular.xyz * lightSpecular;\n"); + " oD1.xyz += specular.xyz * lightSpecular;\n"); break; } - mstring_append(body, "}\n"); + mstring_append(body, " }\n" + "}\n"); } /* TODO: Implement two-sided lighting */ From 679f6d06bd61ef8cb5c09c663c63bab36e76b899 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Sun, 30 Mar 2025 21:20:18 -0700 Subject: [PATCH 49/68] nv2a: Handle LOCALEYE light control --- hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 35 +++++++++++++++++++++++-------- hw/xbox/nv2a/pgraph/shaders.c | 2 ++ hw/xbox/nv2a/pgraph/shaders.h | 1 + 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 74ee67c4ad..f1a2956ca0 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -270,6 +270,12 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n"); + if (state->local_eye) { + mstring_append(body, + "vec3 VPeye = normalize(eyePosition.xyz / eyePosition.w - tPosition.xyz / tPosition.w);\n" + ); + } + for (i = 0; i < NV2A_MAX_LIGHTS; i++) { if (state->light[i] == LIGHT_OFF) { continue; @@ -285,18 +291,20 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz "%svec3 lightLocalAttenuation%d;\n", u, i, u, i); mstring_append_fmt(body, - " vec3 VP = lightLocalPosition%d - tPosition.xyz/tPosition.w;\n" + " vec3 tPos = tPosition.xyz/tPosition.w;\n" + " vec3 VP = lightLocalPosition%d - tPos;\n" " float d = length(VP);\n" " if (d <= lightLocalRange(%d)) {\n" /* FIXME: Double check that range is inclusive */ " VP = normalize(VP);\n" " float attenuation = 1.0 / (lightLocalAttenuation%d.x\n" " + lightLocalAttenuation%d.y * d\n" " + lightLocalAttenuation%d.z * d * d);\n" - " vec3 halfVector = normalize(VP + eyePosition.xyz / eyePosition.w);\n" /* FIXME: Not sure if eyePosition is correct */ + " vec3 halfVector = normalize(VP + %s);\n" " float nDotVP = max(0.0, dot(tNormal, VP));\n" " float nDotHV = max(0.0, dot(tNormal, halfVector));\n", - i, i, i, i, i); - + i, i, i, i, i, + state->local_eye ? "VPeye" : "vec3(0.0, 0.0, 0.0)" + ); } switch(state->light[i]) { @@ -311,10 +319,19 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append_fmt(body, " {\n" " float attenuation = 1.0;\n" - " float nDotVP = max(0.0, dot(tNormal, normalize(lightInfiniteDirection%d)));\n" - " float nDotHV = max(0.0, dot(tNormal, lightInfiniteHalfVector%d));\n", - i, i); - + " vec3 lightDirection = normalize(lightInfiniteDirection%d);\n" + " float nDotVP = max(0.0, dot(tNormal, lightDirection));\n", + i); + if (state->local_eye) { + mstring_append(body, + " float nDotHV = max(0.0, dot(tNormal, normalize(lightDirection + VPeye)));\n" + ); + } else { + mstring_append_fmt(body, + " float nDotHV = max(0.0, dot(tNormal, lightInfiniteHalfVector%d));\n", + i + ); + } break; case LIGHT_LOCAL: /* Everything done already */ @@ -413,7 +430,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz } if (state->ignore_specular_alpha) { mstring_append(body, - " oD1.w = 1.0;\n" + " oD1.a = 1.0;\n" " oB1.a = 1.0;\n" ); } diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c index 79f66026d9..cddbf450f0 100644 --- a/hw/xbox/nv2a/pgraph/shaders.c +++ b/hw/xbox/nv2a/pgraph/shaders.c @@ -96,6 +96,8 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg) pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR); state.ignore_specular_alpha = !GET_MASK( pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR); + state.local_eye = GET_MASK( + pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LOCALEYE); state.specular_power = pg->specular_power; state.specular_power_back = pg->specular_power_back; diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/shaders.h index b384b679bf..4cc07e3a9d 100644 --- a/hw/xbox/nv2a/pgraph/shaders.h +++ b/hw/xbox/nv2a/pgraph/shaders.h @@ -81,6 +81,7 @@ typedef struct ShaderState { bool separate_specular; bool ignore_specular_alpha; + bool local_eye; float specular_power; float specular_power_back; From 5685a6290cfbf7b022ec5e58a8ffb09f664c04e8 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 16 Apr 2025 20:15:16 -0700 Subject: [PATCH 50/68] nv2a/vk: Set specular power uniform --- hw/xbox/nv2a/pgraph/vk/shaders.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/xbox/nv2a/pgraph/vk/shaders.c b/hw/xbox/nv2a/pgraph/vk/shaders.c index 421a81ba60..5d6e345ffb 100644 --- a/hw/xbox/nv2a/pgraph/vk/shaders.c +++ b/hw/xbox/nv2a/pgraph/vk/shaders.c @@ -313,6 +313,9 @@ static void update_shader_constant_locations(ShaderBinding *binding) binding->uniform_attrs_loc = uniform_index(&binding->vertex->uniforms, "inlineValue"); + + binding->specular_power_loc = + uniform_index(&binding->vertex->uniforms, "specularPower"); } static void shader_cache_entry_init(Lru *lru, LruNode *node, void *state) @@ -607,6 +610,11 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding, } } + if (binding->specular_power_loc != -1) { + uniform1f(&binding->vertex->uniforms, binding->specular_power_loc, + pg->specular_power); + } + /* estimate the viewport by assuming it matches the surface ... */ unsigned int aa_width = 1, aa_height = 1; pgraph_apply_anti_aliasing_factor(pg, &aa_width, &aa_height); From 270dbe01ea6b36c38f8cf2bc6a66449caa719a01 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Thu, 17 Apr 2025 22:22:19 -0700 Subject: [PATCH 51/68] nv2a: Increase MAX_BATCH_LENGTH beyond highest known retail use --- hw/xbox/nv2a/nv2a_regs.h | 13 ++++++++++++- hw/xbox/nv2a/pgraph/pgraph.c | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 0c0fb70eef..2bdac1d93f 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -1467,7 +1467,18 @@ #define NV2A_NUM_SUBCHANNELS 8 #define NV2A_CACHE1_SIZE 128 -#define NV2A_MAX_BATCH_LENGTH 0x1FFFF +/* This is a multi-use limit. Testing on an Xbox 1.0, it is possible to send + * arrays of at least 0x0FFFFF elements without issue, however sending + * NV097_DRAW_ARRAYS with a start value > 0xFFFF raises an exception implying + * that there may be a vertex limit. Since xemu uses batch length for vertex + * elements in NV097_INLINE_ARRAY the size should ideally be high enough to + * accommodate 0xFFFF vertices with maximum attributes specified. + * + * Retail games are known to send at least 0x410FA elements in a single draw, so + * a somewhat larger value is selected to balance memory use with real-world + * limits. + */ +#define NV2A_MAX_BATCH_LENGTH 0x07FFFF #define NV2A_VERTEXSHADER_ATTRIBUTES 16 #define NV2A_MAX_TEXTURES 4 diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index feb5f858ca..fc6420fff0 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -2692,7 +2692,11 @@ DEF_METHOD(NV097, DRAW_ARRAYS) int32_t count = GET_MASK(parameter, NV097_DRAW_ARRAYS_COUNT) + 1; if (pg->inline_elements_length) { - /* FIXME: Determine HW behavior for overflow case. */ + /* FIXME: HW throws an exception if the start index is > 0xFFFF. This + * would prevent this assert from firing for any reasonable choice of + * NV2A_MAX_BATCH_LENGTH (which must be larger to accommodate + * NV097_INLINE_ARRAY anyway) + */ assert((pg->inline_elements_length + count) < NV2A_MAX_BATCH_LENGTH); assert(!pg->draw_arrays_prevent_connect); From fee1e58204949b91800772590e6cbb191442f32f Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Fri, 18 Apr 2025 11:21:27 -0700 Subject: [PATCH 52/68] vmstate: Add VMSTATE_UINT32_SUB_ARRAY_V --- include/migration/vmstate.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index f313f2f408..eee7359f2d 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -1085,6 +1085,9 @@ extern const VMStateInfo vmstate_info_qlist; #define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \ VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t) +#define VMSTATE_UINT32_SUB_ARRAY_V(_f, _s, _start, _num, _v) \ + VMSTATE_SUB_ARRAY(_f, _s, _start, _num, _v, vmstate_info_uint32, uint32_t) + #define VMSTATE_UINT32_2DARRAY(_f, _s, _n1, _n2) \ VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, 0) From 0c2a6178192043db8b30c4d61a96129b442102f5 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Fri, 18 Apr 2025 11:22:25 -0700 Subject: [PATCH 53/68] nv2a: Bump vmstate version for new NV2A_MAX_BATCH_LENGTH --- hw/xbox/nv2a/nv2a.c | 8 +++++--- hw/xbox/nv2a/nv2a_regs.h | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/xbox/nv2a/nv2a.c b/hw/xbox/nv2a/nv2a.c index 0124a0d451..02cfbca3e9 100644 --- a/hw/xbox/nv2a/nv2a.c +++ b/hw/xbox/nv2a/nv2a.c @@ -423,7 +423,7 @@ const VMStateDescription vmstate_nv2a_pgraph_vertex_attributes = { static const VMStateDescription vmstate_nv2a = { .name = "nv2a", - .version_id = 2, + .version_id = 3, .minimum_version_id = 1, .post_save = nv2a_post_save, .post_load = nv2a_post_load, @@ -507,9 +507,11 @@ static const VMStateDescription vmstate_nv2a = { VMSTATE_BOOL_ARRAY(pgraph.ltc1_dirty, NV2AState, NV2A_LTC1_COUNT), VMSTATE_STRUCT_ARRAY(pgraph.vertex_attributes, NV2AState, NV2A_VERTEXSHADER_ATTRIBUTES, 1, vmstate_nv2a_pgraph_vertex_attributes, VertexAttribute), VMSTATE_UINT32(pgraph.inline_array_length, NV2AState), - VMSTATE_UINT32_ARRAY(pgraph.inline_array, NV2AState, NV2A_MAX_BATCH_LENGTH), + VMSTATE_UINT32_SUB_ARRAY(pgraph.inline_array, NV2AState, 0, NV2A_MAX_BATCH_LENGTH_V2), + VMSTATE_UINT32_SUB_ARRAY_V(pgraph.inline_array, NV2AState, NV2A_MAX_BATCH_LENGTH_V2, NV2A_MAX_BATCH_LENGTH - NV2A_MAX_BATCH_LENGTH_V2, 3), VMSTATE_UINT32(pgraph.inline_elements_length, NV2AState), // fixme - VMSTATE_UINT32_ARRAY(pgraph.inline_elements, NV2AState, NV2A_MAX_BATCH_LENGTH), + VMSTATE_UINT32_SUB_ARRAY(pgraph.inline_elements, NV2AState, 0, NV2A_MAX_BATCH_LENGTH_V2), + VMSTATE_UINT32_SUB_ARRAY_V(pgraph.inline_elements, NV2AState, NV2A_MAX_BATCH_LENGTH_V2, NV2A_MAX_BATCH_LENGTH - NV2A_MAX_BATCH_LENGTH_V2, 3), VMSTATE_UINT32(pgraph.inline_buffer_length, NV2AState), // fixme VMSTATE_UINT32(pgraph.draw_arrays_length, NV2AState), VMSTATE_UINT32(pgraph.draw_arrays_max_count, NV2AState), diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 2bdac1d93f..c1804a2cef 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -1477,8 +1477,12 @@ * Retail games are known to send at least 0x410FA elements in a single draw, so * a somewhat larger value is selected to balance memory use with real-world * limits. + * + * NV2A_MAX_BATCH_LENGTH_V2 is the previous limit, for migration. + * FIXME: Remove NV2A_MAX_BATCH_LENGTH_V2 at some point in the future. */ #define NV2A_MAX_BATCH_LENGTH 0x07FFFF +#define NV2A_MAX_BATCH_LENGTH_V2 0x1FFFF #define NV2A_VERTEXSHADER_ATTRIBUTES 16 #define NV2A_MAX_TEXTURES 4 From 1a6b858fe83e6817ed8fa931ad591bf4922b65f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 04:31:22 +0000 Subject: [PATCH 54/68] ci: bump softprops/action-gh-release from 2.2.1 to 2.2.2 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda...da05d552573ad5aba039eaac05058a918a7bf631) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.2.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb2a6cc123..fb9f70df1f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -420,7 +420,7 @@ jobs: run: | cp dist/xemu-win-x86_64-release-pdb/xemu-win-x86_64-release.zip dist/xemu-win-x86_64-release-pdb/xemu-win-release.zip - name: Publish release - uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 with: tag_name: v${{ env.XEMU_VERSION }} name: v${{ env.XEMU_VERSION }} From 89185e6937c7d597ba353bc4d4800dde0015ea39 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Tue, 22 Apr 2025 14:28:31 -0700 Subject: [PATCH 55/68] nv2a/psh: Fix default alpha for unbound texture samplers --- hw/xbox/nv2a/pgraph/glsl/psh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/nv2a/pgraph/glsl/psh.c b/hw/xbox/nv2a/pgraph/glsl/psh.c index e3a566a347..448281f46c 100644 --- a/hw/xbox/nv2a/pgraph/glsl/psh.c +++ b/hw/xbox/nv2a/pgraph/glsl/psh.c @@ -949,7 +949,7 @@ static MString* psh_convert(struct PixelShader *ps) switch (ps->tex_modes[i]) { case PS_TEXTUREMODES_NONE: - mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n", + mstring_append_fmt(vars, "vec4 t%d = vec4(0.0, 0.0, 0.0, 1.0); /* PS_TEXTUREMODES_NONE */\n", i); break; case PS_TEXTUREMODES_PROJECT2D: { From 362c27b23525f700ee65c2d06538bed53abeb5ba Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 26 Apr 2025 15:53:02 -0700 Subject: [PATCH 56/68] ci: Auto-update subproject wraps periodically --- .github/workflows/bump-subproject-wraps.yml | 74 ++++++++ scripts/bump-subproject-wraps.py | 197 ++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 .github/workflows/bump-subproject-wraps.yml create mode 100644 scripts/bump-subproject-wraps.py diff --git a/.github/workflows/bump-subproject-wraps.yml b/.github/workflows/bump-subproject-wraps.yml new file mode 100644 index 0000000000..8eb239d107 --- /dev/null +++ b/.github/workflows/bump-subproject-wraps.yml @@ -0,0 +1,74 @@ +name: Bump Meson subprojects + +on: + workflow_dispatch: + schedule: + - cron: '0 6 * * 1' + +permissions: + contents: write + pull-requests: write + +jobs: + bump_wraps: + name: "Bump Meson subprojects" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Install the latest version of uv + uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6 + with: + enable-cache: false + + - name: Check for updates + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + uv run -s scripts/bump-subproject-wraps.py -m \ + subprojects/curl.wrap \ + subprojects/genconfig.wrap \ + subprojects/glslang.wrap \ + subprojects/imgui.wrap \ + subprojects/implot.wrap \ + subprojects/json.wrap \ + subprojects/nv2a_vsh_cpu.wrap \ + subprojects/SPIRV-Reflect.wrap \ + subprojects/tomlplusplus.wrap \ + subprojects/volk.wrap \ + subprojects/VulkanMemoryAllocator.wrap \ + subprojects/xxhash.wrap \ + > updated.json + + - name: Create PRs for updates + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + git config user.name "xemu-robot" + git config user.email "robot@xemu.app" + + jq -c '.[]' updated.json | while read -r item; do + path=$(echo "$item" | jq -r '.path') + file_basename=$(basename "$path") + name="${file_basename%%.*}" + + owner=$(echo "$item" | jq -r '.owner') + repo=$(echo "$item" | jq -r '.repo') + old_rev=$(echo "$item" | jq -r '.old_rev') + new_rev=$(echo "$item" | jq -r '.new_rev') + new_tag=$(echo "$item" | jq -r '.new_tag') + + echo "➤ Processing $name" + branch="sync/bump-${name//\//-}-${GITHUB_RUN_ID}" + + git switch --quiet -c "$branch" origin/master + git add "$path" + git commit -m "meson: Bump ${name} to ${new_tag}" + git push -u origin "$branch" + + gh pr create \ + --title "meson: Bump ${name} to ${new_tag}" \ + --body "Automatic bump of \`${name}\` to [${new_tag}](https://github.com/${owner}/${repo}/compare/${old_rev}..${new_rev})." \ + --base master + done diff --git a/scripts/bump-subproject-wraps.py b/scripts/bump-subproject-wraps.py new file mode 100644 index 0000000000..f9768b366a --- /dev/null +++ b/scripts/bump-subproject-wraps.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# /// script +# dependencies = ["requests"] +# /// +""" +Update Meson wrap file `revision` fields to point to latest release. +""" +from __future__ import annotations +import argparse +import configparser +import json +import logging +import os +import re +import sys +from pathlib import Path +from dataclasses import dataclass, asdict + +import requests + + +log = logging.getLogger(__name__) + + +SEMVER_RE = re.compile( + r""" + ^v? + (?P0|[1-9]\d*)\. + (?P0|[1-9]\d*)\. + (?P0|[1-9]\d*) + $""", + re.VERBOSE, +) + +ROOT = Path(__file__).resolve().parents[1] +WRAP_DIR = ROOT / "subprojects" +SESSION = requests.Session() +GH_TOKEN = os.getenv("GH_TOKEN", "") +if GH_TOKEN: + SESSION.headers["Authorization"] = f"Bearer {GH_TOKEN}" +SESSION.headers["Accept"] = "application/vnd.github+json" + + +def gh_sha_for_tag(owner: str, repo: str, tag: str) -> str: + data = SESSION.get( + f"https://api.github.com/repos/{owner}/{repo}/git/ref/tags/{tag}", timeout=30 + ).json() + + # First level: get the object it points to + obj_type = data["object"]["type"] + obj_sha = data["object"]["sha"] + + if obj_type == "commit": + # Lightweight tag + return obj_sha + elif obj_type == "tag": + # Annotated tag: need to dereference + tag_obj_url = data["object"]["url"] + tag_data = requests.get(tag_obj_url).json() + return tag_data["object"]["sha"] + else: + raise Exception(f"Unknown object type: {obj_type}") + + +def gh_latest_release( + owner: str, repo: str, pattern: re.Pattern +) -> None | tuple[str, str]: + """ + Return (tag_name, commit_sha) for the most recent matching release. + """ + releases = SESSION.get( + f"https://api.github.com/repos/{owner}/{repo}/releases", timeout=30 + ).json() + viable = [t for t in releases if pattern.match(t["tag_name"])] + + if not viable: + return None + + tag_name = viable[0]["tag_name"] + sha = gh_sha_for_tag(owner, repo, tag_name) + + return tag_name, sha + + +def gh_latest_tag(owner: str, repo: str, pattern: re.Pattern) -> tuple[str, str]: + """ + Return (tag_name, commit_sha) for the most recent matching tag. + """ + tags = SESSION.get( + f"https://api.github.com/repos/{owner}/{repo}/tags", timeout=30 + ).json() + viable = [t for t in tags if pattern.match(t["name"])] + + if not viable: + return None + + return viable[0]["name"], viable[0]["commit"]["sha"] + + +@dataclass +class UpdatedWrap: + path: str + owner: str + repo: str + old_rev: str + new_rev: str + new_tag: str + + +def update_wrap(path: Path) -> None | UpdatedWrap: + """ + Return (tag_name, commit_sha) if updated, otherwise None. + """ + cp = configparser.ConfigParser(interpolation=None) + cp.read(path, encoding="utf-8") + + if "wrap-git" not in cp: + # FIXME: Support wrap-file from wrapdb + return None + + w = cp["wrap-git"] + url = w.get("url", "") + rev = w.get("revision", "").strip() + m = re.match(r".*github\.com[:/](?P[^/]+)/(?P[^/.]+)(?:\.git)?", url) + if not (m and rev): + return None + + owner, repo = m.group("owner"), m.group("repo") + try: + pattern = cp.get("update", "tag_regex", fallback=None) + pattern = re.compile(pattern) if pattern else SEMVER_RE + + latest = gh_latest_release(owner, repo, pattern) + if latest is None: + log.info("Couldn't find latest release for %s/%s", owner, repo) + log.info("Searching for tags directly...") + latest = gh_latest_tag(owner, repo, pattern) + if latest is None: + log.info("Couldn't find latest tag for %s/%s", owner, repo) + return None + tag, sha = latest + except Exception as e: + log.exception(e) + return None + + if sha.startswith(rev): + log.info("%s already at %s (%s)", path.name, tag, sha) + return None + + log.info("%s updated to %s (%s)", path.name, tag, sha) + + w["revision"] = sha + + with open(path, "w", encoding="utf-8") as file: + cp.write(file) + + # XXX: ConfigParser writes two extra newlines. Trim the last one. + file.seek(file.tell() - 1, 0) + file.truncate() + + return UpdatedWrap(str(path), owner, repo, rev, sha, tag) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument( + "--manifest", + "-m", + action="store_true", + default=False, + help="Print JSON-formatted updated manifest", + ) + ap.add_argument( + "wraps", nargs="*", help="Which wraps to update, or all if unspecified" + ) + args = ap.parse_args() + + wraps = args.wraps + if wraps: + wraps = [Path(p) for p in wraps] + else: + wraps = WRAP_DIR.glob("*.wrap") + + logging.basicConfig(level=logging.INFO) + + updated = [] + for wrap in wraps: + info = update_wrap(wrap) + if info: + updated.append(asdict(info)) + + if args.manifest: + json.dump(updated, sys.stdout, indent=2) + + +if __name__ == "__main__": + main() From c035ff9f5d5a74e35fe9d76640910432a3943bc2 Mon Sep 17 00:00:00 2001 From: xemu-robot Date: Sat, 26 Apr 2025 23:03:30 +0000 Subject: [PATCH 57/68] meson: Bump VulkanMemoryAllocator to v3.2.1 --- subprojects/VulkanMemoryAllocator.wrap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/VulkanMemoryAllocator.wrap b/subprojects/VulkanMemoryAllocator.wrap index b5f1c7f217..56550f5c96 100644 --- a/subprojects/VulkanMemoryAllocator.wrap +++ b/subprojects/VulkanMemoryAllocator.wrap @@ -1,4 +1,4 @@ [wrap-git] -url=https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator -revision=v3.2.1 -depth=1 +url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator +revision = c788c52156f3ef7bc7ab769cb03c110a53ac8fcb +depth = 1 From 1e1ef6fbb9492c5e9b8d43bd2bc07b5bd6ff8df1 Mon Sep 17 00:00:00 2001 From: xemu-robot Date: Sat, 26 Apr 2025 23:03:29 +0000 Subject: [PATCH 58/68] meson: Bump volk to 1.4.304 --- subprojects/volk.wrap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/volk.wrap b/subprojects/volk.wrap index 46578b64ce..1cb25819be 100644 --- a/subprojects/volk.wrap +++ b/subprojects/volk.wrap @@ -1,4 +1,4 @@ [wrap-git] -url=https://github.com/zeux/volk -revision=1.4.304 -depth=1 +url = https://github.com/zeux/volk +revision = 0b17a763ba5643e32da1b2152f8140461b3b7345 +depth = 1 From c4b554fd80f218155efeb42b44a5a3e4ab031d24 Mon Sep 17 00:00:00 2001 From: mborgerson Date: Sat, 26 Apr 2025 16:13:13 -0700 Subject: [PATCH 59/68] meson: Add tag regex for subproject wrap auto-updater --- subprojects/SPIRV-Reflect.wrap | 9 ++++++--- subprojects/glslang.wrap | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/subprojects/SPIRV-Reflect.wrap b/subprojects/SPIRV-Reflect.wrap index bdc1486c5c..784ee56af5 100644 --- a/subprojects/SPIRV-Reflect.wrap +++ b/subprojects/SPIRV-Reflect.wrap @@ -1,4 +1,7 @@ [wrap-git] -url=https://github.com/KhronosGroup/SPIRV-Reflect -revision=vulkan-sdk-1.4.309.0 -depth=1 +url = https://github.com/KhronosGroup/SPIRV-Reflect +revision = vulkan-sdk-1.4.309.0 +depth = 1 + +[update] +tag_regex = ^(vulkan-sdk-)?[\d\.]+$ diff --git a/subprojects/glslang.wrap b/subprojects/glslang.wrap index 9aa182135a..96edb2d7ba 100644 --- a/subprojects/glslang.wrap +++ b/subprojects/glslang.wrap @@ -2,3 +2,6 @@ url=https://github.com/KhronosGroup/glslang revision=vulkan-sdk-1.4.309.0 depth=1 + +[update] +tag_regex = ^(vulkan-sdk-)?[\d\.]+$ From 668017518a6da4e335b82bc08d4b3aa9971744c8 Mon Sep 17 00:00:00 2001 From: xemu-robot Date: Sat, 26 Apr 2025 23:03:27 +0000 Subject: [PATCH 60/68] meson: Bump tomlplusplus to v3.4.0 --- subprojects/tomlplusplus.wrap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/tomlplusplus.wrap b/subprojects/tomlplusplus.wrap index 4f2d59c52f..7f678ce951 100644 --- a/subprojects/tomlplusplus.wrap +++ b/subprojects/tomlplusplus.wrap @@ -1,4 +1,4 @@ [wrap-git] -url=https://github.com/marzer/tomlplusplus -revision=c635f218c0aefc801d9748841930365e54fe3089 -depth=1 +url = https://github.com/marzer/tomlplusplus +revision = 30172438cee64926dc41fdd9c11fb3ba5b2ba9de +depth = 1 From a3dc07970648b9254bf17192542ded77ffa8a993 Mon Sep 17 00:00:00 2001 From: xemu-robot Date: Sat, 26 Apr 2025 23:21:39 +0000 Subject: [PATCH 61/68] meson: Bump glslang to 15.3.0 --- subprojects/glslang.wrap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/glslang.wrap b/subprojects/glslang.wrap index 96edb2d7ba..5eb28687e5 100644 --- a/subprojects/glslang.wrap +++ b/subprojects/glslang.wrap @@ -1,7 +1,7 @@ [wrap-git] -url=https://github.com/KhronosGroup/glslang -revision=vulkan-sdk-1.4.309.0 -depth=1 +url = https://github.com/KhronosGroup/glslang +revision = fc9889c889561c5882e83819dcaffef5ed45529b +depth = 1 [update] tag_regex = ^(vulkan-sdk-)?[\d\.]+$ From 4dfbe29cbd5f45ce0b89467a3e273b963ecf2556 Mon Sep 17 00:00:00 2001 From: xemu-robot Date: Sat, 26 Apr 2025 23:21:42 +0000 Subject: [PATCH 62/68] meson: Bump SPIRV-Reflect to vulkan-sdk-1.4.309.0 --- subprojects/SPIRV-Reflect.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/SPIRV-Reflect.wrap b/subprojects/SPIRV-Reflect.wrap index 784ee56af5..8107b8b7a7 100644 --- a/subprojects/SPIRV-Reflect.wrap +++ b/subprojects/SPIRV-Reflect.wrap @@ -1,6 +1,6 @@ [wrap-git] url = https://github.com/KhronosGroup/SPIRV-Reflect -revision = vulkan-sdk-1.4.309.0 +revision = c637858562fbce1b6f5dc7ca48d4e8a5bd117b70 depth = 1 [update] From 8f89ef14d7c2ea5fd2d6ebf2139add792b612803 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 26 Apr 2025 16:44:20 -0700 Subject: [PATCH 63/68] ci: Use XEMU_ROBOT_TOKEN for PR creation to trigger build workflow --- .github/workflows/bump-subproject-wraps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bump-subproject-wraps.yml b/.github/workflows/bump-subproject-wraps.yml index 8eb239d107..163d55e259 100644 --- a/.github/workflows/bump-subproject-wraps.yml +++ b/.github/workflows/bump-subproject-wraps.yml @@ -42,7 +42,7 @@ jobs: - name: Create PRs for updates env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.XEMU_ROBOT_TOKEN }} run: | set -euo pipefail git config user.name "xemu-robot" From 5af43523abf55ce3586014f1d06631ba62351951 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 04:03:11 +0000 Subject: [PATCH 64/68] ci: bump actions/download-artifact from 4.2.1 to 4.3.0 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.2.1 to 4.3.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/95815c38cf2ff2164869cbab79da8d1f422bc89e...d3f86a106a0bac45b974a628896c90dbdf5c8093) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb9f70df1f..d55279e8fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,7 +83,7 @@ jobs: steps: - name: Download source package - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: src.tar.gz - name: Extract source package @@ -140,7 +140,7 @@ jobs: arch: aarch64 steps: - name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_name }} @@ -202,7 +202,7 @@ jobs: key: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }} restore-keys: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}- - name: Download source package - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: src.tar.gz - name: Extract source package @@ -305,7 +305,7 @@ jobs: artifact_filename: xemu-macos-arm64-release.zip steps: - name: Download source package - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: src.tar.gz - name: Extract source package @@ -358,12 +358,12 @@ jobs: configuration: ["debug", "release"] steps: - name: Download x86_64 build - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: xemu-macos-x86_64-${{ matrix.configuration }} path: xemu-macos-x86_64-${{ matrix.configuration }} - name: Download arm64 build - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: xemu-macos-arm64-${{ matrix.configuration }} path: xemu-macos-arm64-${{ matrix.configuration }} @@ -398,7 +398,7 @@ jobs: needs: [Ubuntu, macOSUniversal, Windows, WindowsPdb] steps: - name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: path: dist - name: Extract source package @@ -462,7 +462,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download source package - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: src.tar.gz - name: Extract source package From 7108c7a37c6b167704ae9f863244a45a43618918 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 04:03:14 +0000 Subject: [PATCH 65/68] ci: bump actions/setup-python from 5.5.0 to 5.6.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.5.0 to 5.6.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5.5.0...v5.6.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: 5.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d55279e8fa..7b57efd6be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -310,7 +310,7 @@ jobs: name: src.tar.gz - name: Extract source package run: tar xf src.tar.gz - - uses: actions/setup-python@v5.5.0 + - uses: actions/setup-python@v5.6.0 with: python-version: '3.12' - name: Install dependencies From b48f84af792d332be7d48befc03b9e21f2c87b6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 04:03:17 +0000 Subject: [PATCH 66/68] ci: bump docker/build-push-action from 6.15.0 to 6.16.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.15.0 to 6.16.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/471d1dc4e07e5cdedd4c2171150001c434f0b7a4...14487ce63c7a62a4a324b0bfb37086795e31c6c1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: 6.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-xemu-win64-toolchain.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-xemu-win64-toolchain.yml b/.github/workflows/build-xemu-win64-toolchain.yml index 7a521389a5..346e8fad8d 100644 --- a/.github/workflows/build-xemu-win64-toolchain.yml +++ b/.github/workflows/build-xemu-win64-toolchain.yml @@ -44,7 +44,7 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v5 + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v5 with: context: ubuntu-win64-cross push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} From 6e513ed94812246cba3b17954f8da049bb41fbcb Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Tue, 29 Apr 2025 23:22:07 -0700 Subject: [PATCH 67/68] nv2a/psh: Fix 2D texture addressing in DOT_STR_3D mode --- hw/xbox/nv2a/pgraph/glsl/psh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/glsl/psh.c b/hw/xbox/nv2a/pgraph/glsl/psh.c index 448281f46c..893a8fbc9d 100644 --- a/hw/xbox/nv2a/pgraph/glsl/psh.c +++ b/hw/xbox/nv2a/pgraph/glsl/psh.c @@ -1123,8 +1123,8 @@ static MString* psh_convert(struct PixelShader *ps) i, i-2, i-1, i); apply_border_adjustment(ps, vars, i, "dotSTR%d"); - mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, dotSTR%d);\n", - i, i, i); + mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, %s(dotSTR%d%s));\n", + i, i, tex_remap, i, ps->state.dim_tex[i] == 2 ? ".xy" : ""); break; case PS_TEXTUREMODES_DOT_STR_CUBE: assert(i == 3); From d59386942947eb7ae3087548bd7e273974af20c4 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Wed, 30 Apr 2025 23:43:38 -0700 Subject: [PATCH 68/68] nv2a: Move point params to uniforms Co-authored-by: Matt Borgerson --- hw/xbox/nv2a/pgraph/gl/renderer.h | 1 + hw/xbox/nv2a/pgraph/gl/shaders.c | 12 ++++++++++++ hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 10 ++++------ hw/xbox/nv2a/pgraph/vk/renderer.h | 2 +- hw/xbox/nv2a/pgraph/vk/shaders.c | 8 ++++++++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.h b/hw/xbox/nv2a/pgraph/gl/renderer.h index 89ed6ecfd3..d1a64bb024 100644 --- a/hw/xbox/nv2a/pgraph/gl/renderer.h +++ b/hw/xbox/nv2a/pgraph/gl/renderer.h @@ -126,6 +126,7 @@ typedef struct ShaderBinding { GLint clip_region_loc[8]; + GLint point_params_loc[8]; GLint material_alpha_loc; } ShaderBinding; diff --git a/hw/xbox/nv2a/pgraph/gl/shaders.c b/hw/xbox/nv2a/pgraph/gl/shaders.c index ad2f3e1b9b..af3cfd2f40 100644 --- a/hw/xbox/nv2a/pgraph/gl/shaders.c +++ b/hw/xbox/nv2a/pgraph/gl/shaders.c @@ -190,6 +190,11 @@ static void update_shader_constant_locations(ShaderBinding *binding) binding->clip_region_loc[i] = glGetUniformLocation(binding->gl_program, tmp); } + for (int i = 0; i < 8; ++i) { + snprintf(tmp, sizeof(tmp), "pointParams[%d]", i); + binding->point_params_loc[i] = glGetUniformLocation(binding->gl_program, tmp); + } + if (binding->state.fixed_function) { binding->material_alpha_loc = glGetUniformLocation(binding->gl_program, "material_alpha"); @@ -950,6 +955,13 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding, x_min, y_min_xlat, x_max, y_max_xlat); } + for (i = 0; i < 8; ++i) { + GLint loc = binding->point_params_loc[i]; + if (loc != -1) { + glUniform1f(loc, pg->point_params[i]); + } + } + if (binding->material_alpha_loc != -1) { glUniform1f(binding->material_alpha_loc, pg->material_alpha); } diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index f1a2956ca0..6bc637d582 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -482,14 +482,12 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz /* FIXME: Testing */ if (state->point_params_enable) { - mstring_append_fmt( + mstring_append_fmt(uniforms, "%sfloat pointParams[8];\n", u); + mstring_append( body, " float d_e = length(position * modelViewMat0);\n" - " oPts.x = 1/sqrt(%f + %f*d_e + %f*d_e*d_e) + %f;\n", - state->point_params[0], state->point_params[1], state->point_params[2], - state->point_params[6]); - mstring_append_fmt(body, " oPts.x = min(oPts.x*%f + %f, 64.0) * %d;\n", - state->point_params[3], state->point_params[7], + " oPts.x = 1/sqrt(pointParams[0] + pointParams[1] * d_e + pointParams[2] * d_e * d_e) + pointParams[6];\n"); + mstring_append_fmt(body, " oPts.x = min(oPts.x * pointParams[3] + pointParams[7], 64.0) * %d;\n", state->surface_scale_factor); } else { mstring_append_fmt(body, " oPts.x = %f * %d;\n", state->point_size, diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.h b/hw/xbox/nv2a/pgraph/vk/renderer.h index d728805475..4112517e58 100644 --- a/hw/xbox/nv2a/pgraph/vk/renderer.h +++ b/hw/xbox/nv2a/pgraph/vk/renderer.h @@ -191,9 +191,9 @@ typedef struct ShaderBinding { int light_local_position_loc[NV2A_MAX_LIGHTS]; int light_local_attenuation_loc[NV2A_MAX_LIGHTS]; int specular_power_loc; + int point_params_loc; int clip_region_loc; - int material_alpha_loc; int uniform_attrs_loc; diff --git a/hw/xbox/nv2a/pgraph/vk/shaders.c b/hw/xbox/nv2a/pgraph/vk/shaders.c index 5d6e345ffb..78122c701d 100644 --- a/hw/xbox/nv2a/pgraph/vk/shaders.c +++ b/hw/xbox/nv2a/pgraph/vk/shaders.c @@ -308,6 +308,9 @@ static void update_shader_constant_locations(ShaderBinding *binding) binding->clip_region_loc = uniform_index(&binding->fragment->uniforms, "clipRegion"); + binding->point_params_loc = + uniform_index(&binding->vertex->uniforms, "pointParams"); + binding->material_alpha_loc = uniform_index(&binding->vertex->uniforms, "material_alpha"); @@ -720,6 +723,11 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding, uniform1iv(&binding->fragment->uniforms, binding->clip_region_loc, 8 * 4, (void *)clip_regions); + if (binding->point_params_loc != -1) { + uniform1iv(&binding->vertex->uniforms, binding->point_params_loc, + ARRAY_SIZE(pg->point_params), (void *)pg->point_params); + } + if (binding->material_alpha_loc != -1) { uniform1f(&binding->vertex->uniforms, binding->material_alpha_loc, pg->material_alpha);