Compare commits

..

9 Commits

Author SHA1 Message Date
GreemDev
e9824c9053 Comment AppImage builds
It randomly started erroring in GitHub actions with exit code 8 but only sometimes, and I don't have the patience to debug it. I don't even use linux lol
2025-07-28 19:35:47 -05:00
LotP
d2037da65f Nullify Locales (ryubing/ryujinx!83)
See merge request ryubing/ryujinx!83
2025-07-28 19:35:47 -05:00
Rondo
8fe7d54f85 Changes to uk_UA (ryubing/ryujinx!84)
See merge request ryubing/ryujinx!84
2025-07-28 19:35:47 -05:00
Daenorth
b8f9f3e16a Edit TileIDs.cs (ryubing/ryujinx!81)
See merge request ryubing/ryujinx!81
2025-07-28 19:35:47 -05:00
Daenorth
7b1c8717ef Edit compatibility.csv (ryubing/ryujinx!80)
See merge request ryubing/ryujinx!80
2025-07-28 19:35:47 -05:00
GreemDev
6122fa204f simplify completion callback 2025-07-28 17:58:54 -05:00
GreemDev
217fd90568 Use a single parser execution per text box update
Before it would: parse, compile, then execute for getting the formatted result, then run the suggestions function which did parsing on its own. It has now been moved to the new ParseAndGetCompletions function which returns the used ParserResult, saving some work.
2025-07-27 17:35:06 -05:00
GreemDev
95157c0cfd make ApplicationLibrary implement IStarscriptObject 2025-07-27 17:32:39 -05:00
GreemDev
8a3ccaafe3 basic starscript support + a textbox that provides the starscript executed result & compiled script as well as suggestions 2025-07-27 01:09:59 -05:00
704 changed files with 18552 additions and 28353 deletions

1
.gitattributes vendored
View File

@@ -2,4 +2,3 @@
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto eol=lf
*.json text eol=lf

View File

@@ -1,4 +1,4 @@
name: Canary CI
name: Canary release job
on:
workflow_dispatch:
@@ -19,6 +19,7 @@ concurrency: release
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.3"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
RELEASE: 1
@@ -29,8 +30,8 @@ jobs:
strategy:
matrix:
platform:
- { name: win-x64, os: ubuntu-latest, zip_os_name: win_x64 }
#- { name: win-arm64, os: ubuntu-latest, zip_os_name: win_arm64 }
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
steps:
@@ -43,25 +44,11 @@ jobs:
- name: Overwrite csc problem matcher
run: echo "::add-matcher::.github/csc.json"
- name: Install 7zip
run: |
sudo apt install -y 7zip
- name: Install gli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
run: |
echo "build_version=$(gli get-next-version -c Canary -R)" >> $GITHUB_OUTPUT
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $GITHUB_OUTPUT
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
@@ -82,66 +69,84 @@ jobs:
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
- name: Packing Windows builds
if: contains(matrix.platform.name, 'win')
if: matrix.platform.os == 'windows-latest'
run: |
pushd publish
rm libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -r 5 -p release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install GitLabCli
if: matrix.platform.os == 'ubuntu-latest'
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Packing Linux builds
if: contains(matrix.platform.name, 'linux')
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish
rm libarmeilleure-jitsupport.dylib
chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -r 5 -p release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz
shell: bash
- name: Build AppImage (Linux)
if: contains(matrix.platform.name, 'linux')
run: |
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
PLATFORM_NAME="${{ matrix.platform.name }}"
sudo apt install -y zsync desktop-file-utils appstream
mkdir -p tools
export PATH="$PATH:$(readlink -f tools)"
# Setup appimagetool
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x tools/appimagetool
chmod +x distribution/linux/appimage/build-appimage.sh
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
ARCH_NAME=x64
export ARCH=x86_64
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
ARCH_NAME=arm64
export ARCH=aarch64
else
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
exit 1
fi
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
pushd publish_appimage
mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
popd
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -r 5 -p release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
shell: bash
# If anyone wants to look into why appimagetool randomly errors with exit code 8, that would be cool
# - name: Build AppImage (Linux)
# if: matrix.platform.os == 'ubuntu-latest'
# run: |
# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
# PLATFORM_NAME="${{ matrix.platform.name }}"
#
# sudo apt install -y zsync desktop-file-utils appstream
#
# mkdir -p tools
# export PATH="$PATH:$(readlink -f tools)"
#
# # Setup appimagetool
# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
# chmod +x tools/appimagetool
# chmod +x distribution/linux/appimage/build-appimage.sh
#
# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
# if [ "$PLATFORM_NAME" = "linux-x64" ]; then
# ARCH_NAME=x64
# export ARCH=x86_64
# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
# ARCH_NAME=arm64
# export ARCH=aarch64
# else
# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# exit 1
# fi
#
# export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync"
# BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
#
# pushd publish_appimage
# mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# popd
#
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage"
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
# shell: bash
macos_release:
name: Release MacOS universal
@@ -159,10 +164,10 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 17
- name: Install gli
- name: Install GitLabCli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
@@ -183,10 +188,9 @@ jobs:
- name: Get version info
id: version_info
run: |
echo "build_version=$(gli get-next-version -c Canary -R)" >> $GITHUB_OUTPUT
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $GITHUB_OUTPUT
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Configure for release
run: |
@@ -201,7 +205,7 @@ jobs:
- name: Publish macOS Ryujinx
run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -r 5 -p publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
create_gitlab_release:
name: Create GitLab Release
@@ -211,41 +215,37 @@ jobs:
- release
steps:
- uses: actions/checkout@v4
- name: Install gli
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Install GitLabCli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
run: |
echo "build_version=$(gli get-next-version -c Canary -R)" >> $GITHUB_OUTPUT
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Create tag
run: |
gli create-tag -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Canary-${{ steps.version_info.outputs.build_version }} -r ${{ steps.version_info.outputs.git_short_hash }}
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}"
- name: Create release
run: |
gli create-release-from-generic-package-files -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -r main -t "Canary ${{ steps.version_info.outputs.build_version }}" -b "**Full Changelog:** [${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
- name: Send notification webhook
run: |
gli send-update-message -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -t ${{ steps.version_info.outputs.build_version }} -c FF4500 -w ${{ secrets.CANARY_DISCORD_WEBHOOK }} -i https://avatars.githubusercontent.com/u/192939710?s=200&v=4
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
- name: Notify update server of new builds
run: |
gli refresh-version-cache -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Canary
- name: Advance to the next version
run: |
gli increment-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Canary
curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=canary' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}'

224
.github/workflows/debug_release.yml vendored Normal file
View File

@@ -0,0 +1,224 @@
name: Release job (Debug)
on:
workflow_dispatch:
inputs: {}
concurrency: release
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.3"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
RELEASE: 1
jobs:
release:
name: Release for ${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
strategy:
matrix:
platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: Overwrite csc problem matcher
run: echo "::add-matcher::.github/csc.json"
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Configure for release
run: |
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Create output dir
run: "mkdir release_output"
- name: Publish
run: |
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
- name: Packing Windows builds
if: matrix.platform.os == 'windows-latest'
run: |
pushd publish
rm libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install GitLabCli
if: matrix.platform.os == 'ubuntu-latest'
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Packing Linux builds
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish
rm libarmeilleure-jitsupport.dylib
chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
shell: bash
- name: Build AppImage (Linux)
if: matrix.platform.os == 'ubuntu-latest'
run: |
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
PLATFORM_NAME="${{ matrix.platform.name }}"
sudo apt install -y zsync desktop-file-utils appstream
mkdir -p tools
export PATH="$PATH:$(readlink -f tools)"
# Setup appimagetool
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x tools/appimagetool
chmod +x distribution/linux/appimage/build-appimage.sh
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
ARCH_NAME=x64
export ARCH=x86_64
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
ARCH_NAME=arm64
export ARCH=aarch64
else
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
exit 1
fi
export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
pushd publish_appimage
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
popd
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
shell: bash
macos_release:
name: Release MacOS universal
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: Setup LLVM 17
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 17
- name: Install GitLabCli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install rcodesign
run: |
mkdir -p $HOME/.bin
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
rm apple-codesign.tar.gz
mv rcodesign $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
- name: Configure for release
run: |
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Publish macOS Ryujinx
run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
create_gitlab_release:
name: Create GitLab Release
runs-on: ubuntu-24.04
needs:
- macos_release
- release
steps:
- uses: actions/checkout@v4
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Install GitLabCli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
run: |
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|test|THIS IS NOT INTENDED FOR END USER USAGE"

View File

@@ -1,18 +1,15 @@
name: Stable CI
name: Release job
on:
workflow_dispatch:
inputs:
is_bugfix_release:
description: "Bug fix release: If checked, this will increment the third number for only Stable, and leave the Major version alone for both Stable and Canary."
required: true
type: boolean
inputs: {}
concurrency: release
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.3"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
RELEASE: 1
@@ -23,8 +20,8 @@ jobs:
strategy:
matrix:
platform:
- { name: win-x64, os: ubuntu-latest, zip_os_name: win_x64 }
#- { name: win-arm64, os: ubuntu-latest, zip_os_name: win_arm64 }
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
steps:
@@ -36,30 +33,12 @@ jobs:
- name: Overwrite csc problem matcher
run: echo "::add-matcher::.github/csc.json"
- name: Install 7zip
run: |
sudo apt install -y 7zip
- name: Install gli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
run: |
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $GITHUB_OUTPUT
else
echo "build_version=$(gli get-next-version -c Stable -R)" >> $GITHUB_OUTPUT
fi
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $GITHUB_OUTPUT
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
@@ -79,68 +58,86 @@ jobs:
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
- name: Packing Windows builds
if: contains(matrix.platform.name, 'win')
if: matrix.platform.os == 'windows-latest'
run: |
pushd publish
rm libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -r 5 -p release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install GitLabCli
if: matrix.platform.os == 'ubuntu-latest'
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Packing Linux builds
if: contains(matrix.platform.name, 'linux')
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish
rm libarmeilleure-jitsupport.dylib
chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -r 5 -p release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build AppImage (Linux)
if: contains(matrix.platform.name, 'linux')
run: |
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
PLATFORM_NAME="${{ matrix.platform.name }}"
sudo apt install -y zsync desktop-file-utils appstream
mkdir -p tools
export PATH="$PATH:$(readlink -f tools)"
# Setup appimagetool
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x tools/appimagetool
chmod +x distribution/linux/appimage/build-appimage.sh
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
ARCH_NAME=x64
export ARCH=x86_64
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
ARCH_NAME=arm64
export ARCH=aarch64
else
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
exit 1
fi
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
pushd publish_appimage
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
popd
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -r 5 -p release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
shell: bash
# If anyone wants to look into why appimagetool randomly errors with exit code 8, that would be cool
# - name: Build AppImage (Linux)
# if: matrix.platform.os == 'ubuntu-latest'
# run: |
# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
# PLATFORM_NAME="${{ matrix.platform.name }}"
#
# sudo apt install -y zsync desktop-file-utils appstream
#
# mkdir -p tools
# export PATH="$PATH:$(readlink -f tools)"
#
# # Setup appimagetool
# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
# chmod +x tools/appimagetool
# chmod +x distribution/linux/appimage/build-appimage.sh
#
# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
# if [ "$PLATFORM_NAME" = "linux-x64" ]; then
# ARCH_NAME=x64
# export ARCH=x86_64
# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
# ARCH_NAME=arm64
# export ARCH=aarch64
# else
# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# exit 1
# fi
#
# export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
# BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
#
# pushd publish_appimage
# mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# popd
#
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
# shell: bash
macos_release:
name: Release MacOS universal
@@ -158,10 +155,10 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 17
- name: Install gli
- name: Install GitLabCli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
@@ -182,14 +179,9 @@ jobs:
- name: Get version info
id: version_info
run: |
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $GITHUB_OUTPUT
else
echo "build_version=$(gli get-next-version -c Stable -R)" >> $GITHUB_OUTPUT
fi
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $GITHUB_OUTPUT
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Configure for release
run: |
@@ -202,8 +194,7 @@ jobs:
- name: Publish macOS Ryujinx
run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -r 5 -p publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
create_gitlab_release:
name: Create GitLab Release
@@ -214,45 +205,32 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install gli
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Install GitLabCli
run: |
mkdir -p $HOME/.bin
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
chmod +x gli
mv gli $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
run: |
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $GITHUB_OUTPUT
else
echo "build_version=$(gli get-next-version -c Stable -R)" >> $GITHUB_OUTPUT
fi
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
echo "commit_message=$(git log -1 --pretty=%B)" >> $GITHUB_OUTPUT
shell: bash
- name: Create release
run: |
gli create-release-from-generic-package-files -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -r ${{ steps.version_info.outputs.git_short_hash }} -t "${{ steps.version_info.outputs.build_version }}" -b "msd:${{ steps.version_info.outputs.build_version }}"
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|msd:${{ steps.version_info.outputs.build_version }}"
- name: Send notification webhook
run: |
gli send-update-message -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -t ${{ steps.version_info.outputs.build_version }} -c 32cd32 -w ${{ secrets.STABLE_DISCORD_WEBHOOK }} -i https://avatars.githubusercontent.com/u/192939710?s=200&v=4
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|32cd32|${{ secrets.STABLE_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
- name: Notify update server of new builds
run: |
gli refresh-version-cache -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Stable
- name: Advance to the next version
run: |
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
gli advance-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}
else
gli increment-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Stable
fi
curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=stable' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}'

3
.gitignore vendored
View File

@@ -18,8 +18,6 @@ build/
[Oo]bj/
AppDir/
publish_appimage/
publish_ava/
publish_tmp_ava/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
@@ -100,7 +98,6 @@ DocProject/Help/html
# Click-Once directory
publish/
RyubingMaintainerTools/
# Publish Web Output
*.Publish.xml

18
BuildAndPushLibraries.sh Normal file
View File

@@ -0,0 +1,18 @@
function pub {
dotnet publish -c release
}
function package {
cd src/$1
pub
mv bin/Release/$1.1.0.0.nupkg ../../pkgs/$1.1.0.0.nupkg
cd ../../
}
rm -rf pkgs
mkdir pkgs
package ARMeilleure
package Ryujinx.Memory
dotnet nuget push pkgs/*.nupkg --source RyubingPkgs

View File

@@ -21,8 +21,8 @@ Additionally, 1.2.74 & 75 were fixes for uploading Windows build artifacts.
1.2.76 fixes a rare crash on startup.
## [1.2.72](<https://git.ryujinx.app/ryubing/ryujinx/-/tags/1.2.72>) - 2024-11-03
PRs [#163](<https://web.archive.org/web/20241123015123/https://github.com/GreemDev/Ryujinx/pull/163>), [#164](<https://web.archive.org/web/20250307192526/https://github.com/Ryubing/Ryujinx/pull/164>), [#139](<https://web.archive.org/web/20250306123457/https://github.com/Ryubing/Ryujinx/pull/139>)
## [1.2.72](<https://github.com/GreemDev/Ryujinx/releases/tag/1.2.72>) - 2024-11-03
PRs [#163](<https://github.com/GreemDev/Ryujinx/pull/163>), [#164](<https://github.com/GreemDev/Ryujinx/pull/164>), [#139](<https://github.com/GreemDev/Ryujinx/pull/139>)
### HLE:
- Add DebugMouse HID device.
- Fixes "Clock Tower Rewind" crashing while loading.
@@ -32,7 +32,7 @@ PRs [#163](<https://web.archive.org/web/20241123015123/https://github.com/GreemD
### misc:
- Update macOS distribution .icns.
## [1.2.69](<https://git.ryujinx.app/ryubing/ryujinx/-/tags/1.2.69>) - 2024-11-01
## [1.2.69](<https://github.com/GreemDev/Ryujinx/releases/tag/1.2.69>) - 2024-11-01
### Infra:
- Compile the native libraries into the Ryujinx executable.
- Remove `libarmeilleure-jitsupport.dylib` from Windows & Linux releases (dylibs are macOS-only)
@@ -42,8 +42,8 @@ PRs [#163](<https://web.archive.org/web/20241123015123/https://github.com/GreemD
- Replace "" with `string.Empty`.
- Code cleanups & simplifications.
## [1.2.67](<https://git.ryujinx.app/ryubing/ryujinx/-/tags/1.2.67>) - 2024-11-01
PRs [#36](<https://web.archive.org/web/20250306215917/https://github.com/Ryubing/Ryujinx/pull/36>), [#135](<https://web.archive.org/web/20241122135125/https://github.com/GreemDev/Ryujinx/pull/135>)
## [1.2.67](<https://github.com/GreemDev/Ryujinx/releases/tag/1.2.67>) - 2024-11-01
PRs [#36](<https://github.com/GreemDev/Ryujinx/pull/36>), [#135](<https://github.com/GreemDev/Ryujinx/pull/135>)
### GUI:
- Set UseFloatingWatermark to false when watermark is empty
@@ -54,8 +54,8 @@ PRs [#36](<https://web.archive.org/web/20250306215917/https://github.com/Ryubing
- Fix homebrew loading.
## [1.2.64](https://git.ryujinx.app/ryubing/ryujinx/-/tags/1.2.64) - 2024-10-30
PRs [#92](https://web.archive.org/web/20241118052724/https://github.com/GreemDev/Ryujinx/pull/92), ~~[#96](https://github.com/GreemDev/Ryujinx/pull/96)~~, ~~[#97](https://github.com/GreemDev/Ryujinx/pull/97)~~, [#101](https://web.archive.org/web/20250306223605/https://github.com/Ryubing/Ryujinx/pull/101), ~~[#103](https://github.com/GreemDev/Ryujinx/pull/103)~~
## [1.2.64](https://github.com/GreemDev/Ryujinx/releases/tag/1.2.64) - 2024-10-30
PRs [#92](https://github.com/GreemDev/Ryujinx/pull/92), [#96](https://github.com/GreemDev/Ryujinx/pull/96), [#97](https://github.com/GreemDev/Ryujinx/pull/97), [#101](https://github.com/GreemDev/Ryujinx/pull/101), [#103](https://github.com/GreemDev/Ryujinx/pull/103)
### GUI:
- Option to show classic-style title bar. Requires restart of emulator to take effect.
- This is only relevant on Windows. Other Operating Systems default to this being on and not being changeable, because the custom (current) title bar only works on Windows in the first place.
@@ -71,14 +71,14 @@ PRs [#92](https://web.archive.org/web/20241118052724/https://github.com/GreemDev
## 1.2.59 - 2024-10-27
PRs ~~[#88](https://github.com/GreemDev/Ryujinx/pull/88), [#87](https://github.com/GreemDev/Ryujinx/pull/87)~~
PRs [#88](https://github.com/GreemDev/Ryujinx/pull/88), [#87](https://github.com/GreemDev/Ryujinx/pull/87)
### i18n:
- fr_FR:
- Add missing translations for new features & fix a couple wrong ones.
- Fix Ignore Missing Services / Ignore Applet tooltip.
## 1.2.57 - 2024-10-27
PRs ~~[#60](https://github.com/GreemDev/Ryujinx/pull/60)~~, [#42](https://web.archive.org/web/20241126203614/https://github.com/GreemDev/Ryujinx/pull/42)
PRs [#60](https://github.com/GreemDev/Ryujinx/pull/60), [#42](https://github.com/GreemDev/Ryujinx/pull/42)
### GUI:
- Automatically remove invalid DLC & updates as part of autoload.
- Added Thai translation for Ignore Applet hover tooltip.
@@ -104,7 +104,7 @@ PRs ~~[#60](https://github.com/GreemDev/Ryujinx/pull/60)~~, [#42](https://web.ar
- Code cleanup.
## 1.2.44 - 2024-10-25
PR [#59](https://web.archive.org/web/20241125060420/https://github.com/GreemDev/Ryujinx/pull/59)
PR [#59](https://github.com/GreemDev/Ryujinx/pull/59)
### GUI:
- Add descriptions for "ignoring applet" translated into other languages.
@@ -117,9 +117,9 @@ NOTE: The translation isn't referenced in the code yet, it will be in the next u
## 1.2.42 - 2024-10-24
Sources:
Init function: [archive of github.com/MutantAura/Ryujinx/commit/9cef4ceba40d66492ff775af793ff70e6e7551a9](https://web.archive.org/web/20241122193401/https://github.com/MutantAura/Ryujinx/commit/9cef4ceba40d66492ff775af793ff70e6e7551a9)
Init function: https://github.com/MutantAura/Ryujinx/commit/9cef4ceba40d66492ff775af793ff70e6e7551a9
Shader counter: ~~https://github.com/MutantAura/Ryujinx/commit/67b873645fd593e83d042a77bf7ab12e5ec97357~~ Original commit has been lost
Shader counter: https://github.com/MutantAura/Ryujinx/commit/67b873645fd593e83d042a77bf7ab12e5ec97357
Thanks MutantAura :D
### GUI:
@@ -127,14 +127,14 @@ Thanks MutantAura :D
- Remove graphics backend / GPU name event logic in favor of a single init function.
## 1.2.41 - 2024-10-24
PR ~~[#54](https://github.com/GreemDev/Ryujinx/pull/54)~~
PR [#54](https://github.com/GreemDev/Ryujinx/pull/54)
Thanks Whitescatz!
### i18n:
- th_TH (Thai): Added missing translations, reduce transliterated words, fix grammar.
## 1.2.40 - 2024-10-23
PR ~~[#40](https://github.com/GreemDev/Ryujinx/pull/40)~~
PR [#40](https://github.com/GreemDev/Ryujinx/pull/40)
Thanks Вова С!
### GUI:
@@ -148,30 +148,30 @@ Thanks Вова С!
- Should prevent crashing on config loads in some circumstances.
## 1.2.38 - 2024-10-23
PR [#51](https://web.archive.org/web/20241127022413/https://github.com/GreemDev/Ryujinx/pull/51)
PR [#51](https://github.com/GreemDev/Ryujinx/pull/51)
### i18n:
- zh_CH (Simplified Chinese): Add some missing translations.
## 1.2.37 - 2024-10-23
PR [#37](https://web.archive.org/web/20241123010103/https://github.com/GreemDev/Ryujinx/pull/37)
PR [#37](https://github.com/GreemDev/Ryujinx/pull/37)
Thanks Last Breath!
### GUI:
- Set the default controller to the Pro Controller.
## 1.2.36 - 2024-10-21
PR ~~[#30](https://github.com/GreemDev/Ryujinx/pull/30)~~
PR [#30](https://github.com/GreemDev/Ryujinx/pull/30)
### GUI:
- Fix repeated dialog popup notifying you of new updates when there aren't any, while having a bundled update inside an XCI and an external update file.
## 1.2.35 - 2024-10-21
PR [#32](https://web.archive.org/web/20241127010942/https://github.com/GreemDev/Ryujinx/pull/32)
PR [#32](https://github.com/GreemDev/Ryujinx/pull/32)
### GUI:
- Replace "expand DRAM" option with a DRAM size dropdown.
- Allows for using mods which require a ridiculous amount of memory to allocate from.
## 1.2.34 - 2024-10-21
PR [#29](https://web.archive.org/web/20241125093029/https://github.com/GreemDev/Ryujinx/pull/29)
PR [#29](https://github.com/GreemDev/Ryujinx/pull/29)
### GUI:
- Fix duplicate controller names when 2 controllers of the same type are connected.
### INPUT:
@@ -248,7 +248,7 @@ Added Low-power PPTC mode strings to the translation files.
## 1.2.1-1.2.19 - 2024-10-08 - 2024-10-11
### GUI/INFRA/MISC:
- Remove GTK UI.
- Autoload DLC/Updates from dir ([#12](https://web.archive.org/web/20241127004005/https://github.com/GreemDev/Ryujinx/pull/12)).
- Autoload DLC/Updates from dir ([#12](https://github.com/GreemDev/Ryujinx/pull/12)).
- Changed executable icon to rainbow logo.
- Extract Data > Logo now also extracts the square thumbnail you see for the game in the UI.
- The "use random UUID hack" checkbox in the Amiibo screen now remembers its last state when you reopen the window in a given session.

View File

@@ -5,12 +5,12 @@ If you wish to build the emulator yourself, follow these steps:
### Step 1
Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0).
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0).
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
### Step 2
Either use `git clone https://git.ryujinx.app/ryubing/ryujinx.git` on the command line to clone the repository or use Code --> Download zip button to get the files.
Either use `git clone https://github.com/Ryubing/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
### Step 3

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
</Project>

View File

@@ -3,26 +3,25 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="11.3.6" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.6" />
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.6.2" />
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.6.2" />
<PackageVersion Include="Avalonia" Version="11.0.13" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.6.2" />
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />
<PackageVersion Include="ppy.SDL3-CS" Version="2025.920.0" />
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.4.0" />
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
<PackageVersion Include="Concentus" Version="2.2.2" />
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageVersion Include="DynamicData" Version="9.4.1" />
<PackageVersion Include="FluentAvaloniaUI.NoAnim" Version="2.4.0-build3" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="9.0.4" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="Humanizer" Version="2.14.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
@@ -41,12 +40,13 @@
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
<PackageVersion Include="Gommon" Version="2.8.0.1" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.116" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.29" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.29" />
<PackageVersion Include="Gommon" Version="2.7.1.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.11.1" />
<PackageVersion Include="Sep" Version="0.6.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
@@ -55,8 +55,9 @@
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageVersion Include="SPB" Version="0.0.4-build32" />
<PackageVersion Include="Starscript.Net" Version="1.0.36" />
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" />
<PackageVersion Include="System.Management" Version="9.0.2" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup>
</Project>
</Project>

View File

@@ -66,7 +66,7 @@ If you are planning to contribute or just want to learn more about this project
- **Audio**
Audio output is entirely supported, audio input (microphone) isn't supported.
We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL3](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
- **CPU**

View File

@@ -21,8 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.GAL", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.OpenGL", "src\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj", "{9558FB96-075D-4219-8FFF-401979DC0B69}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.RenderDoc", "src\Ryujinx.Graphics.RenderDocApi\Ryujinx.Graphics.RenderDocApi.csproj", "{D58FA894-27D5-4EAA-9042-AD422AD82931}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Texture", "src\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj", "{E1B1AD28-289D-47B7-A106-326972240207}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Shader", "src\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj", "{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}"
@@ -47,17 +45,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.Apple", "src\Ryujinx.Audio.Backends.Apple\Ryujinx.Audio.Backends.Apple.csproj", "{AC26EFF0-8593-4184-9A09-98E37EFFB32E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SoundIo", "src\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj", "{716364DE-B988-41A6-BAB4-327964266ECC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input", "src\Ryujinx.Input\Ryujinx.Input.csproj", "{C16F112F-38C3-40BC-9F5F-4791112063D6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL2", "src\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj", "{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\Ryujinx.SDL2.Common\Ryujinx.SDL2.Common.csproj", "{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
EndProject
@@ -81,15 +79,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL3.Common", "src\Ryujinx.SDL3.Common\Ryujinx.SDL3.Common.csproj", "{F6F9826A-BC58-4D78-A700-F358A66B2B06}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props
Directory.Build.props = Directory.Build.props
.github\workflows\release.yml = .github\workflows\release.yml
nuget.config = nuget.config
EndProjectSection
@@ -97,482 +92,164 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x64.ActiveCfg = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x64.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x86.ActiveCfg = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x86.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x64.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x64.Build.0 = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x86.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x86.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x64.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x64.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x86.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x86.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x64.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x64.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x86.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x86.Build.0 = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x64.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x64.Build.0 = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x86.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x86.Build.0 = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x64.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x64.Build.0 = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x86.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x86.Build.0 = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x64.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x64.Build.0 = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x86.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x86.Build.0 = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.Build.0 = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x64.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x64.Build.0 = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x86.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x86.Build.0 = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x64.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x64.Build.0 = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x86.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x86.Build.0 = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.Build.0 = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x64.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x64.Build.0 = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x86.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x86.Build.0 = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x64.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x64.Build.0 = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x86.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x86.Build.0 = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x64.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x64.Build.0 = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x86.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x86.Build.0 = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x64.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x64.Build.0 = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x86.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x86.Build.0 = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.Build.0 = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x64.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x64.Build.0 = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x86.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x86.Build.0 = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x64.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x64.Build.0 = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x86.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x86.Build.0 = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.Build.0 = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x64.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x64.Build.0 = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x86.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x86.Build.0 = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x64.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x64.Build.0 = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x86.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x86.Build.0 = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.Build.0 = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x64.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x64.Build.0 = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x86.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x86.Build.0 = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x64.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x64.Build.0 = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x86.Build.0 = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.Build.0 = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x64.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x64.Build.0 = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x86.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x86.Build.0 = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x64.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x64.Build.0 = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x86.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x86.Build.0 = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.Build.0 = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x64.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x64.Build.0 = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x86.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x86.Build.0 = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x64.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x64.Build.0 = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x86.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x86.Build.0 = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.Build.0 = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x64.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x64.Build.0 = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x86.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x86.Build.0 = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.Build.0 = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x64.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x64.Build.0 = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x86.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x86.Build.0 = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.Build.0 = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x64.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x64.Build.0 = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x86.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x86.Build.0 = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x64.Build.0 = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x86.Build.0 = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.Build.0 = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x64.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x64.Build.0 = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x86.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x86.Build.0 = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x64.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x64.Build.0 = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x86.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x86.Build.0 = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.Build.0 = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x64.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x64.Build.0 = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x86.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x86.Build.0 = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x64.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x64.Build.0 = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x86.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x86.Build.0 = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.Build.0 = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x64.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x64.Build.0 = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x86.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x86.Build.0 = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x64.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x64.Build.0 = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x86.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x86.Build.0 = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.Build.0 = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x64.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x64.Build.0 = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x86.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x86.Build.0 = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x64.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x64.Build.0 = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x86.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x86.Build.0 = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.Build.0 = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x64.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x64.Build.0 = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x86.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x86.Build.0 = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x64.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x64.Build.0 = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x86.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x86.Build.0 = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.Build.0 = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x64.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x64.Build.0 = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x86.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x86.Build.0 = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x64.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x64.Build.0 = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x86.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x86.Build.0 = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x64.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x64.Build.0 = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x86.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x86.Build.0 = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x64.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x64.Build.0 = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x86.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x86.Build.0 = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.Build.0 = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x64.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x64.Build.0 = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x86.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x86.Build.0 = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x64.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x64.Build.0 = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x86.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x86.Build.0 = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.Build.0 = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x64.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x64.Build.0 = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x86.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x86.Build.0 = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x64.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x64.Build.0 = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x86.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x86.Build.0 = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.Build.0 = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x64.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x64.Build.0 = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x86.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x86.Build.0 = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x64.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x64.Build.0 = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x86.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x86.Build.0 = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.Build.0 = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x64.ActiveCfg = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x64.Build.0 = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x86.ActiveCfg = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x86.Build.0 = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.Build.0 = Release|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Release|Any CPU.Build.0 = Release|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x64.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x64.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x86.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x86.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x64.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x64.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x86.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x86.Build.0 = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x64.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x64.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x86.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x86.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x64.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x64.Build.0 = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x86.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x86.Build.0 = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x64.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x64.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x86.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x86.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x64.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x64.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x86.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x86.Build.0 = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x64.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x64.Build.0 = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x86.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x86.Build.0 = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.Build.0 = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x64.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x64.Build.0 = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x86.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x86.Build.0 = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x64.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x64.Build.0 = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x86.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x86.Build.0 = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.Build.0 = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x64.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x64.Build.0 = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x86.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x86.Build.0 = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x64.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x64.Build.0 = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x86.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x86.Build.0 = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.Build.0 = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x64.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x64.Build.0 = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x86.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x86.Build.0 = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x64.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x64.Build.0 = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x86.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x86.Build.0 = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.Build.0 = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x64.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x64.Build.0 = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x86.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x86.Build.0 = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x64.Build.0 = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x86.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x86.Build.0 = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.Build.0 = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x64.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x64.Build.0 = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x86.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x86.Build.0 = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x64.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x64.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x86.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x64.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x64.Build.0 = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x86.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x86.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x64.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x64.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x86.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x86.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x64.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x64.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x86.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x86.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x64.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x86.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x86.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x64.ActiveCfg = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x64.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x86.ActiveCfg = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x86.Build.0 = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x64.ActiveCfg = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x64.Build.0 = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x86.ActiveCfg = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x86.Build.0 = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|Any CPU.Build.0 = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x64.ActiveCfg = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x64.Build.0 = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x86.ActiveCfg = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x86.Build.0 = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x64.ActiveCfg = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x64.Build.0 = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x86.ActiveCfg = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x86.Build.0 = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|Any CPU.Build.0 = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x64.ActiveCfg = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x64.Build.0 = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x86.ActiveCfg = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x86.Build.0 = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x64.ActiveCfg = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x64.Build.0 = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x86.ActiveCfg = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x86.Build.0 = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|Any CPU.Build.0 = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x64.ActiveCfg = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x64.Build.0 = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.ActiveCfg = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.Build.0 = Release|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x64.ActiveCfg = Debug|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x64.Build.0 = Debug|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x86.ActiveCfg = Debug|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x86.Build.0 = Debug|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|Any CPU.Build.0 = Release|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x64.ActiveCfg = Release|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x64.Build.0 = Release|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x86.ActiveCfg = Release|Any CPU
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x86.Build.0 = Release|Any CPU
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,24 +0,0 @@
{
"Languages": {
"ar_SA": "اَلْعَرَبِيَّةُ",
"de_DE": "Deutsch",
"el_GR": "Ελληνικά",
"en_US": "English (US)",
"es_ES": "Español (ES)",
"fr_FR": "Français (FR)",
"he_IL": "עִברִית",
"it_IT": "Italiano",
"ja_JP": "日本語",
"ko_KR": "한국어",
"no_NO": "Norsk",
"pl_PL": "Polski",
"pt_BR": "Português (BR)",
"ru_RU": "Русский",
"sv_SE": "Svenska",
"th_TH": "ภาษาไทย",
"tr_TR": "Türkçe",
"uk_UA": "Українська",
"zh_CN": "简体中文",
"zh_TW": "繁體中文 (台灣)"
}
}

View File

@@ -1,60 +0,0 @@
# Ryubing Locales
Ryubing Locales uses a custom format, which uses a file for defining the supported languages and a folder of json files for the locales themselves.
Each json file holds the locales for a specific part of the emulator, e.g. the Setup Wizard locales are in `SetupWizard.json`, and each locale entry in the file includes all the supported languages in the same place.
## Languages
in the `/assets/` folder you will find the `Languages.json` file, which defines all the languages supported by the emulator.
The file includes a table of the langauge codes and their langauge names.
#Example of the format for Languages.json
{
"Languages": {
"ar_SA": "اَلْعَرَبِيَّةُ",
"en_US": "English (US)",
...
"zh_TW": "繁體中文 (台灣)"
}
}
## Locales
in the `/assets/Locales/` folder you will find the json files, which define all the locales supported by the emulator.
Each json file holds locales for a specific part of the emulator in a large array of locale objects.
Each locale is made up an ID used for lookup and a list of the languages and their matching translations.
Any empty string or null value will automatically use the English translation instead in the emulator.
### Format
When adding a new locale, you just need to add the ID and the en_US language translation, then the validation system will add default values for the rest of languages automatically, when rebuilding the project.
If you want to signal that a translation is supposed to match the English translation, you just have to replace the empty string with `null`.
When you want to check what translations are missing for a language just search for `"<lang_code>": ""`, e.g: `"en_US": ""` (but with any other language, as English will never be missing translations).
### Legacy file (Root.json)
Currently all older locales are stored in `Root.json`, but they are slowly being moved into newer, more descriptive json files, to make the locale system more accessible.
Do **not** add new locales to `Root.json`.
If no json file exists for the specific part of the emulator you're working on, you should instead add a new json file for that part.
#Example of the format for Root.json
{
"Locales": [
{
"ID": "MenuBarActionsOpenMiiEditor",
"Translations": {
"ar_SA": "",
"en_US": "Mii Editor",
...
"zh_TW": "Mii 編輯器"
}
},
{
"ID": "KeyNumber9",
"Translations": {
"ar_SA": "٩",
"en_US": "9",
...
"zh_TW": null
}
}
]
}

View File

@@ -1,104 +0,0 @@
{
"Locales": [
{
"ID": "MenuBarActions_StartCapture",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Start RenderDoc Frame Capture",
"es_ES": "Iniciar una captura de fotograma de RenderDoc",
"fr_FR": "Démarrer une capture de trame RenderDoc",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "RenderDoc 프레임 캡처 시작",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "MenuBarActions_EndCapture",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "End RenderDoc Frame Capture",
"es_ES": "Detener la captura de fotograma de RenderDoc",
"fr_FR": "Arrêter la capture de trame RenderDoc",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "RenderDoc 프레임 캡처 종료",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "MenuBarActions_DiscardCapture",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Discard RenderDoc Frame Capture",
"es_ES": "Descartar la captura de fotograma de RenderDoc",
"fr_FR": "Supprimer la capture de trame RenderDoc",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "RenderDoc 프레임 캡처 폐기",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "MenuBarActions_DiscardCapture_ToolTip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Ends the currently active RenderDoc Frame Capture, immediately discarding its result.",
"es_ES": "Finaliza la captura de fotograma de RenderDoc actualmente activa y descarta inmediatamente su resultado.",
"fr_FR": "Met fin à la capture de trame RenderDoc en cours, en supprimant immédiatement son résultat.",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "현재 활성화된 RenderDoc 프레임 캡처를 종료하고 결과를 즉시 폐기합니다.",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@
SCRIPT_DIR=$(dirname "$(realpath "$0")")
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL3" ]; then
RYUJINX_BIN="Ryujinx.Headless.SDL3"
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
RYUJINX_BIN="Ryujinx.Headless.SDL2"
fi
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then

View File

@@ -6,6 +6,7 @@ cd "$ROOTDIR"
BUILDDIR=${BUILDDIR:-publish}
OUTDIR=${OUTDIR:-publish_appimage}
UFLAG=${UFLAG:-"gh-releases-zsync|Ryubing|ryujinx|latest|*-x64.AppImage.zsync"}
rm -rf AppDir
mkdir -p AppDir/usr/bin
@@ -22,5 +23,11 @@ chmod +x AppDir/AppRun AppDir/usr/bin/Ryujinx*
mkdir -p "$OUTDIR"
appimagetool -n --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 21 \
appimagetool --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 21 \
-u "$UFLAG" \
AppDir "$OUTDIR"/Ryujinx.AppImage
# Move zsync file needed for delta updates
if [ "$RELEASE" = "1" ]; then
mv ./*.AppImage.zsync "$OUTDIR"
fi

Binary file not shown.

View File

@@ -10,8 +10,6 @@
<string>Ryujinx</string>
<key>CFBundleIconFile</key>
<string>Ryujinx.icns</string>
<key>CFBundleIconName</key>
<string>Ryujinx</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
@@ -36,23 +34,23 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>%%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%</string>
<string>%%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%"</string>
<key>CFBundleName</key>
<string>Ryujinx</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.3</string>
<string>1.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>%%RYUJINX_BUILD_VERSION%%</string>
<string>1.2.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 - 2024 Ryujinx Team and Contributors. Copyright © 2024 - 2025 Ryubing and Contributors.</string>
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>

View File

@@ -25,7 +25,6 @@ cp "$PUBLISH_DIRECTORY"/*.dylib "$APP_BUNDLE_DIRECTORY/Contents/Frameworks"
cp Info.plist "$APP_BUNDLE_DIRECTORY/Contents"
cp Ryujinx.icns "$APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns"
cp updater.sh "$APP_BUNDLE_DIRECTORY/Contents/Resources/updater.sh"
cp Assets.car "$APP_BUNDLE_DIRECTORY/Contents/Resources/Assets.car"
cp -r "$PUBLISH_DIRECTORY/THIRDPARTY.md" "$APP_BUNDLE_DIRECTORY/Contents/Resources"
echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo"

View File

@@ -0,0 +1,124 @@
#!/bin/bash
set -e
if [ "$#" -lt 8 ]; then
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <CANARY>"
exit 1
fi
mkdir -p "$1"
mkdir -p "$2"
mkdir -p "$3"
BASE_DIR=$(readlink -f "$1")
TEMP_DIRECTORY=$(readlink -f "$2")
OUTPUT_DIRECTORY=$(readlink -f "$3")
ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
VERSION=$5
SOURCE_REVISION_ID=$6
CONFIGURATION=$7
CANARY=$8
if [[ "$(uname)" == "Darwin" ]]; then
echo "Clearing xattr on all dot undercsore files"
find "$BASE_DIR" -type f -name "._*" -exec sh -c '
for f; do
dir=$(dirname "$f")
base=$(basename "$f")
orig="$dir/${base#._}"
[ -f "$orig" ] && xattr -c "$orig" || true
done
' sh {} +
fi
if [ "$CANARY" == "1" ]; then
RELEASE_TAR_FILE_NAME=nogui-ryujinx-canary-$VERSION-macos_universal.tar
elif [ "$VERSION" == "1.1.0" ]; then
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
else
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$VERSION-macos_universal.tar
fi
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL2
rm -rf "$TEMP_DIRECTORY"
mkdir -p "$TEMP_DIRECTORY"
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
dotnet restore
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL2
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
# Get rid of libsoundio from arm64 builds as we don't have a arm64 variant
# TODO: remove this once done
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
rm -rf "$OUTPUT_DIRECTORY"
mkdir -p "$OUTPUT_DIRECTORY"
# Let's copy one of the two different outputs and remove the executable
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
# Make its libraries universal
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
if ! [ -x "$(command -v lipo)" ];
then
if ! [ -x "$(command -v llvm-lipo-17)" ];
then
LIPO=llvm-lipo
else
LIPO=llvm-lipo-17
fi
else
LIPO=lipo
fi
# Make the executable universal
$LIPO "$ARM64_OUTPUT/$EXECUTABLE_SUB_PATH" "$X64_OUTPUT/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" -create
# Now sign it
if ! [ -x "$(command -v codesign)" ];
then
if ! [ -x "$(command -v rcodesign)" ];
then
echo "Cannot find rcodesign on your system, please install rcodesign."
exit 1
fi
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
echo "Using rcodesign for ad-hoc signing"
for FILE in "$UNIVERSAL_OUTPUT"/*; do
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$FILE"
fi
done
else
echo "Using codesign for ad-hoc signing"
for FILE in "$UNIVERSAL_OUTPUT"/*; do
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$FILE"
fi
done
fi
echo "Creating archive"
pushd "$OUTPUT_DIRECTORY"
tar --exclude "publish/Ryujinx.Headless.SDL2" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
rm "$RELEASE_TAR_FILE_NAME"
popd
echo "Done"

View File

@@ -8,7 +8,7 @@ Intro to Ryujinx
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
* The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions.
* The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
* Audio output is entirely supported via C# wrappers for SDL3, with OpenAL & libsoundio as fallbacks.
* Audio output is entirely supported via C# wrappers for SDL2, with OpenAL & libsoundio as fallbacks.
Getting Started
===============

View File

@@ -188,8 +188,6 @@
01003DD00BFEE000,"Airheart - Tales of broken Wings",,playable,2021-02-26 15:20:27
01007F100DE52000,"Akane",nvdec,playable,2022-07-21 00:12:18
01009A800F0C8000,"Akash: Path of the Five",gpu;nvdec,ingame,2020-12-14 22:33:12
01009E8012976000,"AKIBA'S TRIP: Hellbound & Debriefed",,playable,2025-07-30 23:22:47
0100D74019A0E000,"AKIBA'S TRIP: Undead & Undressed Director's Cut",,playable,2025-07-31 13:58:42
010053100B0EA000,"Akihabara - Feel the Rhythm Remixed",,playable,2021-02-22 14:39:35
0100D4C00EE0C000,"Akuarium",slow,playable,2020-12-12 23:43:36
010026E00FEBE000,"Akuto: Showdown",,playable,2020-08-04 19:43:27
@@ -978,7 +976,7 @@
0100416004C00000,"DOOM",gpu;slow;nvdec;online-broken,ingame,2024-09-23 15:40:07
010018900DD00000,"DOOM (1993)",nvdec;online-broken,menus,2022-09-06 13:32:19
01008CB01E52E000,"DOOM + DOOM II",opengl;ldn-untested;LAN,playable,2024-09-12 07:06:01
010029D00E740000,"DOOM 3",crash;slow,menus,2024-08-03 05:25:47
010029D00E740000,"DOOM 3",crash,menus,2024-08-03 05:25:47
01005D700E742000,"DOOM 64",nvdec;vulkan,playable,2020-10-13 23:47:28
0100D4F00DD02000,"DOOM II (Classic)",nvdec;online,playable,2021-06-03 20:10:01
0100B1A00D8CE000,"DOOM® Eternal",gpu;slow;nvdec;online-broken,ingame,2024-08-28 15:57:17
@@ -1097,7 +1095,6 @@
0100F9600E746000,"ESP Ra.De. Psi",audio;slow,ingame,2024-03-07 15:05:08
010073000FE18000,"Esports powerful pro yakyuu 2020",gpu;crash;Needs More Attention,ingame,2024-04-29 05:34:14
01004F9012FD8000,"Estranged: The Departure",nvdec;UE4,playable,2022-10-24 10:37:58
010018F01E0A0000,"Eternights",,playable,2025-07-30 12:10:24
0100CB900B498000,"Eternum Ex",,playable,2021-01-13 20:28:32
010092501EB2C000,"Europa (Demo)",gpu;crash;UE4,ingame,2024-04-23 10:47:12
01007BE0160D6000,"EVE ghost enemies",gpu,ingame,2023-01-14 03:13:30
@@ -1175,7 +1172,6 @@
0100EB100AB42000,"FINAL FANTASY XII THE ZODIAC AGE",opengl;vulkan-backend-bug,playable,2024-08-11 07:01:54
010068F00AA78000,"FINAL FANTASY XV POCKET EDITION HD",,playable,2021-01-05 17:52:08
0100CE4010AAC000,"FINAL FANTASY® CRYSTAL CHRONICLES™ Remastered Edition",,playable,2023-04-02 23:39:12
010038B015560000,FINAL FANTASY TACTICS - The Ivalice Chronicles,gpu,boots,2024-09-30 02:59:00
01001BA00AE4E000,"Final Light, The Prison",,playable,2020-07-31 21:48:44
0100FF100FB68000,"Finding Teddy 2 : Definitive Edition",gpu,ingame,2024-04-19 16:51:33
0100F4E013AAE000,"Fire & Water",,playable,2020-12-15 15:43:20
@@ -1244,8 +1240,6 @@
010003F00BD48000,"Friday the 13th: Killer Puzzle",,playable,2021-01-28 01:33:38
010092A00C4B6000,"Friday the 13th: The Game Ultimate Slasher Edition",nvdec;online-broken;UE4,playable,2022-09-06 17:33:27
0100F200178F4000,"FRONT MISSION 1st: Remake",,playable,2023-06-09 07:44:24
0100C4E018A24000,"FRONT MISSION 2: Remake",,playable,2025-07-30 12:11:23
01007E6019872000,"FRONT MISSION 3: Remake",,playable,2025-07-30 12:12:02
0100861012474000,"Frontline Zed",,playable,2020-10-03 12:55:59
0100B5300B49A000,"Frost",,playable,2022-07-27 12:00:36
010038A007AA4000,"FruitFall Crush",,playable,2020-10-20 11:33:33
@@ -1441,7 +1435,6 @@
0100C2700E338000,"Heroland",,playable,2020-08-05 15:35:39
01007AC00E012000,"HexaGravity",,playable,2021-05-28 13:47:48
01004E800F03C000,"Hidden",slow,ingame,2022-10-05 10:56:53
0100C1101EE5A000,"High on Life",,menus,2025-08-26 19:11:00
0100F6A00A684000,"Higurashi no Naku Koro ni Hō",audio,ingame,2021-09-18 14:40:28
0100F8D0129F4000,"Himehibi 1 gakki - Princess Days",crash,nothing,2021-11-03 08:34:19
0100F3D008436000,"Hiragana Pixel Party",,playable,2021-01-14 08:36:50
@@ -1451,7 +1444,6 @@
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
0100F7E00C70E000,"Hogwarts Legacy",UE4;slow,ingame,2024-09-03 19:53:58
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
010013C00E930000,"Hollow Knight: Silksong",,playable,2025-09-04 17:23:22
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
010071B00C904000,"HoPiKo",,playable,2021-01-13 20:12:38
@@ -1526,7 +1518,6 @@
010095C016C14000,"Iridium",,playable,2022-08-05 23:19:53
0100AD300B786000,"Iris School of Wizardry -Vinculum Hearts-",,playable,2022-12-05 13:11:15
0100945012168000,"Iris.Fall",nvdec,playable,2022-10-18 13:40:22
010059801B736000,"IronFall: Invasion",,playable,2025-07-30 11:42:30
01005270118D6000,"Iron Wings",slow,ingame,2022-08-07 08:32:57
01004DB003E6A000,"IRONCAST",,playable,2021-01-13 13:54:29
0100E5700CD56000,"Irony Curtain: From Matryoshka with Love",,playable,2021-06-04 20:12:37
@@ -1890,7 +1881,7 @@
010097800EA20000,"Monster Energy Supercross - The Official Videogame 3",UE4;audout;nvdec;online,playable,2021-06-14 12:37:54
0100E9900ED74000,"Monster Farm",32-bit;nvdec,playable,2021-05-05 19:29:13
0100770008DD8000,"Monster Hunter Generations Ultimate™",32-bit;online-broken;ldn-works,playable,2024-03-18 14:35:36
0100B04011742000,"MONSTER HUNTER RISE",gpu;slow;crash;nvdec;online-broken;Needs Update;ldn-works,ingame,2024-08-24 11:04:59
0100B04011742000,"Monster Hunter Rise",gpu;slow;crash;nvdec;online-broken;Needs Update;ldn-works,ingame,2024-08-24 11:04:59
010093A01305C000,"Monster Hunter Rise Demo",online-broken;ldn-works;demo,playable,2022-10-18 23:04:17
0100E21011446000,"Monster Hunter Stories 2: Wings of Ruin",services,ingame,2022-07-10 19:27:30
010042501329E000,"MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version",demo,playable,2022-11-13 22:20:26
@@ -2272,10 +2263,8 @@
0100ABF008968000,"Pokémon Sword + Pokémon Sword Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-26 15:40:37
01009AD008C4C000,"Pokémon: Let's Go, Pikachu! demo",slow;demo,playable,2023-11-26 11:23:20
0100000011D90000,"Pokémon™ Brilliant Diamond",gpu;ldn-works,ingame,2024-08-28 13:26:35
010018E011D92000,"Pokémon™ Shining Pearl",gpu;ldn-works,ingame,2024-08-28 13:26:35
010015F008C54000,"Pokémon™ HOME",Needs Update;crash;services,menus,2020-12-06 06:01:51
01001F5010DFA000,"Pokémon™ Legends: Arceus",gpu;Needs Update;ldn-works,ingame,2024-09-19 10:02:02
0100F43008C44000,"Pokémon™ Legends: Z-A",gpu;crash;ldn-works,ingame,2025-11-16 00:30:00
01005D100807A000,"Pokémon™ Quest",,playable,2022-02-22 16:12:32
0100A3D008C5C000,"Pokémon™ Scarlet",gpu;nvdec;ldn-works;amd-vendor-bug,ingame,2023-12-14 13:18:29
01008F6008C5E000,"Pokémon™ Violet",gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug,ingame,2024-07-30 02:51:48
@@ -2317,7 +2306,6 @@
010077B00BDD8000,"Professional Farmer: Nintendo Switch™ Edition",slow,playable,2020-12-16 13:38:19
010018300C83A000,"Professor Lupo and his Horrible Pets",,playable,2020-06-12 00:08:45
0100D1F0132F6000,"Professor Lupo: Ocean",,playable,2021-04-14 16:33:33
0100C3A017834000,"Prodeus",,playable,2025-07-30 12:07:52
0100BBD00976C000,"Project Highrise: Architect's Edition",,playable,2022-08-10 17:19:12
0100ACE00DAB6000,"Project Nimbus: Complete Edition",nvdec;UE4;vulkan-backend-bug,playable,2022-08-10 17:35:43
01002980140F6000,"Project TRIANGLE STRATEGY™ Debut Demo",UE4;demo,playable,2022-10-24 21:40:27
@@ -2583,7 +2571,6 @@
0100C610154CA000,"Shadowrun: Hong Kong - Extended Edition",gpu;Needs Update,ingame,2022-10-04 20:53:09
010000000EEF0000,"Shadows 2: Perfidia",,playable,2020-08-07 12:43:46
0100AD700CBBE000,"Shadows of Adam",,playable,2021-01-11 13:35:58
010037A01F96C000,"Shadows of the Damned: Hella Remastered",,playable,2025-09-05 11:34:32
01002A800C064000,"Shadowverse Champions Battle",,playable,2022-10-02 22:59:29
01003B90136DA000,"Shadowverse: Champion's Battle",crash,nothing,2023-03-06 00:31:50
0100820013612000,"Shady Part of Me",,playable,2022-10-20 11:31:55
@@ -2710,8 +2697,6 @@
01008F701C074000,"SONIC SUPERSTARS",gpu;nvdec,ingame,2023-10-28 17:48:07
010088801C150000,"Sonic Superstars Digital Art Book with Mini Digital Soundtrack",,playable,2024-08-20 13:26:56
01005EA01C0FC000,"SONIC X SHADOW GENERATIONS",crash,ingame,2025-01-07 04:20:45
010064B0242BE000,"Sonic Racing: CrossWorlds - Demo",gpu;vulkan-backend-bug;demo,ingame,2024-09-25 11:27:53
01006E001823C000,"Sonic Racing: CrossWorlds",gpu;vulkan-backend-bug;ldn-broken,ingame,2024-09-30 17:23:00
010064F00C212000,"Soul Axiom Rebooted",nvdec;slow,ingame,2020-09-04 12:41:01
0100F2100F0B2000,"Soul Searching",,playable,2020-07-09 18:39:07
01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken;vulkan-backend-bug;gpu,ingame,2025-01-21 17:35:10
@@ -2783,7 +2768,7 @@
0100E6B0115FC000,"Star99",online,menus,2021-11-26 14:18:51
01002100137BA000,"Stardash",,playable,2021-01-21 16:31:19
0100E65002BB8000,"Stardew Valley",online-broken;ldn-untested,playable,2024-02-14 03:11:19
01002CC003FE6000,"Starlink: Battle for Atlas™ Digital Edition",,playable,2025-07-30 12:09:37
01002CC003FE6000,"Starlink: Battle for Atlas™ Digital Edition",services-horizon;crash;Needs Update,nothing,2024-05-05 17:25:11
010098E010FDA000,"Starlit Adventures Golden Stars",,playable,2020-11-21 12:14:43
01001BB00AC26000,"STARSHIP AVENGER Operation: Take Back Earth",,playable,2021-01-12 15:52:55
010000700A572000,"State of Anarchy: Master of Mayhem",nvdec,playable,2021-01-12 19:00:05
@@ -2869,13 +2854,11 @@
0100BC0018138000,"Super Mario RPG™",gpu;audio;nvdec,ingame,2024-06-19 17:43:42
,"Super Mario World",homebrew,boots,2024-06-13 01:40:31
010049900F546000,"Super Mario™ 3D All-Stars",services-horizon;slow;vulkan;amd-vendor-bug,ingame,2024-05-07 02:38:16
010099C022B96000,"Super Mario Galaxy",slow;vulkan;amd-vendor-bug;vulkan-vendor-bug,ingame,2025-10-01 15:30:00
0100FD8022DAA000,"Super Mario Galaxy 2",slow;vulkan;amd-vendor-bug;vulkan-vendor-bug;deadlock,ingame,2025-10-04 18:50:00
010028600EBDA000,"Super Mario™ 3D World + Bowsers Fury",ldn-works,playable,2024-07-31 10:45:37
01004F8006A78000,"Super Meat Boy",services,playable,2020-04-02 23:10:07
01009C200D60E000,"Super Meat Boy Forever",gpu,boots,2021-04-26 14:25:39
0100BDD00EC5C000,"Super Mega Space Blaster Special Turbo",online,playable,2020-08-06 12:13:25
010031F019294000,"Super Monkey Ball Banana Rumble",ldn-broken,playable,2025-10-01 18:03:00
010031F019294000,"Super Monkey Ball Banana Rumble",,playable,2024-06-28 10:39:18
0100B2A00E1E0000,"Super Monkey Ball: Banana Blitz HD",online-broken,playable,2022-09-16 13:16:25
01006D000D2A0000,"Super Mutant Alien Assault",,playable,2020-06-07 23:32:45
01004D600AC14000,"Super Neptunia RPG",nvdec,playable,2022-08-17 16:38:52
@@ -2941,7 +2924,6 @@
0100B76011DAA000,"Taxi Chaos",slow;online-broken;UE4,playable,2022-10-25 19:13:00
0100F43011E5A000,"Tcheco in the Castle of Lucio",,playable,2020-06-27 13:35:43
010092B0091D0000,"Team Sonic Racing",online-broken;ldn-works,playable,2024-02-05 15:05:27
010084B00B36E000,"Team Sonic Racing",online-broken;ldn-works,playable,2024-02-05 15:05:27
0100FE701475A000,"Teenage Mutant Ninja Turtles: Shredder's Revenge",deadlock;crash,boots,2024-09-28 09:31:39
01005CF01E784000,"Teenage Mutant Ninja Turtles: Splintered Fate",,playable,2024-08-03 13:50:42
0100FDB0154E4000,"Teenage Mutant Ninja Turtles: The Cowabunga Collection",,playable,2024-01-22 19:39:04
@@ -2987,7 +2969,6 @@
0100EBA01548E000,"The Cruel King and the Great Hero",gpu;services,ingame,2022-12-02 07:02:08
010051800E922000,"The Dark Crystal: Age of Resistance Tactics",,playable,2020-08-11 13:43:41
01003DE00918E000,"The Darkside Detective",,playable,2020-06-03 22:16:18
010032B015D66000,"The DioField Chronicle",,playable,2025-09-05 11:35:50
01000A10041EA000,"The Elder Scrolls V: Skyrim",gpu;crash,ingame,2024-07-14 03:21:31
01004A9006B84000,"The End Is Nigh",,playable,2020-06-01 11:26:45
0100CA100489C000,"The Escapists 2",nvdec,playable,2020-09-24 12:31:31
@@ -2995,7 +2976,6 @@
0100C2E0129A6000,"The Executioner",nvdec,playable,2021-01-23 00:31:28
01006050114D4000,"The Experiment: Escape Room",gpu,ingame,2022-09-30 13:20:35
0100B5900DFB2000,"The Eyes of Ara",,playable,2022-09-16 14:44:06
0100BA5013E52000,"The Falconeer: Warrior Edition",,playable,2025-07-30 12:04:50
01002DD00AF9E000,"The Fall",gpu,ingame,2020-05-31 23:31:16
01003E5002320000,"The Fall Part 2: Unbound",,playable,2021-11-06 02:18:08
0100CDC00789E000,"The Final Station",nvdec,playable,2022-08-22 15:54:39
@@ -3218,7 +3198,6 @@
010000400F582000,"TT Isle of Man Ride on the Edge 2",gpu;nvdec;online-broken,ingame,2022-09-30 22:13:05
0100752011628000,"TTV2",,playable,2020-11-27 13:21:36
0100AFE00452E000,"Tumblestone",,playable,2021-01-07 17:49:20
0100D1A01D7BA000,"Turbo Overkill",,playable,2025-07-30 12:08:57
010085500D5F6000,"Turok",gpu,ingame,2021-06-04 13:16:24
0100CDC00D8D6000,"Turok 2: Seeds of Evil",gpu;vulkan,ingame,2022-09-12 17:50:05
010004B0130C8000,"Turrican Flashback",audout,playable,2021-08-30 10:07:56
@@ -3228,7 +3207,6 @@
010038400C2FE000,"TY the Tasmanian Tiger™ HD",32-bit;crash;nvdec,menus,2020-12-17 21:15:00
010073A00C4B2000,"Tyd wag vir Niemand",,playable,2021-03-02 13:39:53
0100D5B00D6DA000,"Type:Rider",,playable,2021-01-06 13:12:55
01008AF01AD22000,"The Patrick Star Game",,playable,2025-10-01 17:55:30
010040D01222C000,"UBERMOSH: SANTICIDE",,playable,2020-11-27 15:05:01
0100992010BF8000,"Ubongo",,playable,2021-02-04 21:15:01
010079000B56C000,"UglyDolls: An Imperfect Adventure",nvdec;UE4,playable,2022-08-25 14:42:16
@@ -3243,8 +3221,6 @@
0100592005164000,"UNBOX: Newbie's Adventure",UE4,playable,2022-08-29 13:12:56
01002D900C5E4000,"Uncanny Valley",nvdec,playable,2021-06-04 13:28:45
010076F011F54000,"Undead & Beyond",nvdec,playable,2022-10-04 09:11:18
01009B700D0B8000,"Undead Horde",,playable,2025-07-30 12:05:05
0100FC301A878000,"Undead Horde 2: Necropolis",,playable,2025-07-30 12:06:07
01008F3013E4E000,"Under Leaves",,playable,2021-05-22 18:13:58
010080B00AD66000,"Undertale",,playable,2022-08-31 17:31:46
01008F80049C6000,"Unepic",,playable,2024-01-15 17:03:00
@@ -3475,6 +3451,3 @@
0100F4401940A000,"超探偵事件簿 レインコード (Master Detective Archives: Rain Code)",crash,ingame,2024-02-12 20:58:31
010064801A01C000,"超次元ゲイム ネプテューヌ GameMaker R:Evolution",crash,nothing,2023-10-30 22:37:40
0100F3400332C000,"ブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41
010075000ECBE000,"超级马力欧 奥德赛",nvdec;intel-vendor-bug;mac-bug,playable,2024-08-25 01:32:34
010075100E8EC000,"马力欧卡丁车8 豪华版",32-bit;ldn-works;LAN;amd-vendor-bug,playable,2024-09-19 11:55:17
0100E8C00F506000,"新 超级马力欧兄弟U 豪华版",32-bit,playable,2023-10-08 02:06:37
1 title_id game_name labels status last_updated
188 01003DD00BFEE000 Airheart - Tales of broken Wings playable 2021-02-26 15:20:27
189 01007F100DE52000 Akane nvdec playable 2022-07-21 00:12:18
190 01009A800F0C8000 Akash: Path of the Five gpu;nvdec ingame 2020-12-14 22:33:12
01009E8012976000 AKIBA'S TRIP: Hellbound & Debriefed playable 2025-07-30 23:22:47
0100D74019A0E000 AKIBA'S TRIP: Undead & Undressed Director's Cut playable 2025-07-31 13:58:42
191 010053100B0EA000 Akihabara - Feel the Rhythm Remixed playable 2021-02-22 14:39:35
192 0100D4C00EE0C000 Akuarium slow playable 2020-12-12 23:43:36
193 010026E00FEBE000 Akuto: Showdown playable 2020-08-04 19:43:27
976 0100416004C00000 DOOM gpu;slow;nvdec;online-broken ingame 2024-09-23 15:40:07
977 010018900DD00000 DOOM (1993) nvdec;online-broken menus 2022-09-06 13:32:19
978 01008CB01E52E000 DOOM + DOOM II opengl;ldn-untested;LAN playable 2024-09-12 07:06:01
979 010029D00E740000 DOOM 3 crash;slow crash menus 2024-08-03 05:25:47
980 01005D700E742000 DOOM 64 nvdec;vulkan playable 2020-10-13 23:47:28
981 0100D4F00DD02000 DOOM II (Classic) nvdec;online playable 2021-06-03 20:10:01
982 0100B1A00D8CE000 DOOM® Eternal gpu;slow;nvdec;online-broken ingame 2024-08-28 15:57:17
1095 0100F9600E746000 ESP Ra.De. Psi audio;slow ingame 2024-03-07 15:05:08
1096 010073000FE18000 Esports powerful pro yakyuu 2020 gpu;crash;Needs More Attention ingame 2024-04-29 05:34:14
1097 01004F9012FD8000 Estranged: The Departure nvdec;UE4 playable 2022-10-24 10:37:58
010018F01E0A0000 Eternights playable 2025-07-30 12:10:24
1098 0100CB900B498000 Eternum Ex playable 2021-01-13 20:28:32
1099 010092501EB2C000 Europa (Demo) gpu;crash;UE4 ingame 2024-04-23 10:47:12
1100 01007BE0160D6000 EVE ghost enemies gpu ingame 2023-01-14 03:13:30
1172 0100EB100AB42000 FINAL FANTASY XII THE ZODIAC AGE opengl;vulkan-backend-bug playable 2024-08-11 07:01:54
1173 010068F00AA78000 FINAL FANTASY XV POCKET EDITION HD playable 2021-01-05 17:52:08
1174 0100CE4010AAC000 FINAL FANTASY® CRYSTAL CHRONICLES™ Remastered Edition playable 2023-04-02 23:39:12
010038B015560000 FINAL FANTASY TACTICS - The Ivalice Chronicles gpu boots 2024-09-30 02:59:00
1175 01001BA00AE4E000 Final Light, The Prison playable 2020-07-31 21:48:44
1176 0100FF100FB68000 Finding Teddy 2 : Definitive Edition gpu ingame 2024-04-19 16:51:33
1177 0100F4E013AAE000 Fire & Water playable 2020-12-15 15:43:20
1240 010003F00BD48000 Friday the 13th: Killer Puzzle playable 2021-01-28 01:33:38
1241 010092A00C4B6000 Friday the 13th: The Game Ultimate Slasher Edition nvdec;online-broken;UE4 playable 2022-09-06 17:33:27
1242 0100F200178F4000 FRONT MISSION 1st: Remake playable 2023-06-09 07:44:24
0100C4E018A24000 FRONT MISSION 2: Remake playable 2025-07-30 12:11:23
01007E6019872000 FRONT MISSION 3: Remake playable 2025-07-30 12:12:02
1243 0100861012474000 Frontline Zed playable 2020-10-03 12:55:59
1244 0100B5300B49A000 Frost playable 2022-07-27 12:00:36
1245 010038A007AA4000 FruitFall Crush playable 2020-10-20 11:33:33
1435 0100C2700E338000 Heroland playable 2020-08-05 15:35:39
1436 01007AC00E012000 HexaGravity playable 2021-05-28 13:47:48
1437 01004E800F03C000 Hidden slow ingame 2022-10-05 10:56:53
0100C1101EE5A000 High on Life menus 2025-08-26 19:11:00
1438 0100F6A00A684000 Higurashi no Naku Koro ni Hō audio ingame 2021-09-18 14:40:28
1439 0100F8D0129F4000 Himehibi 1 gakki - Princess Days crash nothing 2021-11-03 08:34:19
1440 0100F3D008436000 Hiragana Pixel Party playable 2021-01-14 08:36:50
1444 0100F7300ED2C000 Hoggy2 playable 2022-10-10 13:53:35
1445 0100F7E00C70E000 Hogwarts Legacy UE4;slow ingame 2024-09-03 19:53:58
1446 0100633007D48000 Hollow Knight nvdec playable 2023-01-16 15:44:56
010013C00E930000 Hollow Knight: Silksong playable 2025-09-04 17:23:22
1447 0100F2100061E800 Hollow0 UE4;gpu ingame 2021-03-03 23:42:56
1448 0100342009E16000 Holy Potatoes! What The Hell?! playable 2020-07-03 10:48:56
1449 010071B00C904000 HoPiKo playable 2021-01-13 20:12:38
1518 010095C016C14000 Iridium playable 2022-08-05 23:19:53
1519 0100AD300B786000 Iris School of Wizardry -Vinculum Hearts- playable 2022-12-05 13:11:15
1520 0100945012168000 Iris.Fall nvdec playable 2022-10-18 13:40:22
010059801B736000 IronFall: Invasion playable 2025-07-30 11:42:30
1521 01005270118D6000 Iron Wings slow ingame 2022-08-07 08:32:57
1522 01004DB003E6A000 IRONCAST playable 2021-01-13 13:54:29
1523 0100E5700CD56000 Irony Curtain: From Matryoshka with Love playable 2021-06-04 20:12:37
1881 010097800EA20000 Monster Energy Supercross - The Official Videogame 3 UE4;audout;nvdec;online playable 2021-06-14 12:37:54
1882 0100E9900ED74000 Monster Farm 32-bit;nvdec playable 2021-05-05 19:29:13
1883 0100770008DD8000 Monster Hunter Generations Ultimate™ 32-bit;online-broken;ldn-works playable 2024-03-18 14:35:36
1884 0100B04011742000 MONSTER HUNTER RISE Monster Hunter Rise gpu;slow;crash;nvdec;online-broken;Needs Update;ldn-works ingame 2024-08-24 11:04:59
1885 010093A01305C000 Monster Hunter Rise Demo online-broken;ldn-works;demo playable 2022-10-18 23:04:17
1886 0100E21011446000 Monster Hunter Stories 2: Wings of Ruin services ingame 2022-07-10 19:27:30
1887 010042501329E000 MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version demo playable 2022-11-13 22:20:26
2263 0100ABF008968000 Pokémon Sword + Pokémon Sword Expansion Pass deadlock;crash;online-broken;ldn-works;LAN ingame 2024-08-26 15:40:37
2264 01009AD008C4C000 Pokémon: Let's Go, Pikachu! demo slow;demo playable 2023-11-26 11:23:20
2265 0100000011D90000 Pokémon™ Brilliant Diamond gpu;ldn-works ingame 2024-08-28 13:26:35
010018E011D92000 Pokémon™ Shining Pearl gpu;ldn-works ingame 2024-08-28 13:26:35
2266 010015F008C54000 Pokémon™ HOME Needs Update;crash;services menus 2020-12-06 06:01:51
2267 01001F5010DFA000 Pokémon™ Legends: Arceus gpu;Needs Update;ldn-works ingame 2024-09-19 10:02:02
0100F43008C44000 Pokémon™ Legends: Z-A gpu;crash;ldn-works ingame 2025-11-16 00:30:00
2268 01005D100807A000 Pokémon™ Quest playable 2022-02-22 16:12:32
2269 0100A3D008C5C000 Pokémon™ Scarlet gpu;nvdec;ldn-works;amd-vendor-bug ingame 2023-12-14 13:18:29
2270 01008F6008C5E000 Pokémon™ Violet gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug ingame 2024-07-30 02:51:48
2306 010077B00BDD8000 Professional Farmer: Nintendo Switch™ Edition slow playable 2020-12-16 13:38:19
2307 010018300C83A000 Professor Lupo and his Horrible Pets playable 2020-06-12 00:08:45
2308 0100D1F0132F6000 Professor Lupo: Ocean playable 2021-04-14 16:33:33
0100C3A017834000 Prodeus playable 2025-07-30 12:07:52
2309 0100BBD00976C000 Project Highrise: Architect's Edition playable 2022-08-10 17:19:12
2310 0100ACE00DAB6000 Project Nimbus: Complete Edition nvdec;UE4;vulkan-backend-bug playable 2022-08-10 17:35:43
2311 01002980140F6000 Project TRIANGLE STRATEGY™ Debut Demo UE4;demo playable 2022-10-24 21:40:27
2571 0100C610154CA000 Shadowrun: Hong Kong - Extended Edition gpu;Needs Update ingame 2022-10-04 20:53:09
2572 010000000EEF0000 Shadows 2: Perfidia playable 2020-08-07 12:43:46
2573 0100AD700CBBE000 Shadows of Adam playable 2021-01-11 13:35:58
010037A01F96C000 Shadows of the Damned: Hella Remastered playable 2025-09-05 11:34:32
2574 01002A800C064000 Shadowverse Champions Battle playable 2022-10-02 22:59:29
2575 01003B90136DA000 Shadowverse: Champion's Battle crash nothing 2023-03-06 00:31:50
2576 0100820013612000 Shady Part of Me playable 2022-10-20 11:31:55
2697 01008F701C074000 SONIC SUPERSTARS gpu;nvdec ingame 2023-10-28 17:48:07
2698 010088801C150000 Sonic Superstars Digital Art Book with Mini Digital Soundtrack playable 2024-08-20 13:26:56
2699 01005EA01C0FC000 SONIC X SHADOW GENERATIONS crash ingame 2025-01-07 04:20:45
010064B0242BE000 Sonic Racing: CrossWorlds - Demo gpu;vulkan-backend-bug;demo ingame 2024-09-25 11:27:53
01006E001823C000 Sonic Racing: CrossWorlds gpu;vulkan-backend-bug;ldn-broken ingame 2024-09-30 17:23:00
2700 010064F00C212000 Soul Axiom Rebooted nvdec;slow ingame 2020-09-04 12:41:01
2701 0100F2100F0B2000 Soul Searching playable 2020-07-09 18:39:07
2702 01008F2005154000 South Park™: The Fractured but Whole™ - Standard Edition slow;online-broken;vulkan-backend-bug;gpu ingame 2025-01-21 17:35:10
2768 0100E6B0115FC000 Star99 online menus 2021-11-26 14:18:51
2769 01002100137BA000 Stardash playable 2021-01-21 16:31:19
2770 0100E65002BB8000 Stardew Valley online-broken;ldn-untested playable 2024-02-14 03:11:19
2771 01002CC003FE6000 Starlink: Battle for Atlas™ Digital Edition services-horizon;crash;Needs Update playable nothing 2025-07-30 12:09:37 2024-05-05 17:25:11
2772 010098E010FDA000 Starlit Adventures Golden Stars playable 2020-11-21 12:14:43
2773 01001BB00AC26000 STARSHIP AVENGER Operation: Take Back Earth playable 2021-01-12 15:52:55
2774 010000700A572000 State of Anarchy: Master of Mayhem nvdec playable 2021-01-12 19:00:05
2854 0100BC0018138000 Super Mario RPG™ gpu;audio;nvdec ingame 2024-06-19 17:43:42
2855 Super Mario World homebrew boots 2024-06-13 01:40:31
2856 010049900F546000 Super Mario™ 3D All-Stars services-horizon;slow;vulkan;amd-vendor-bug ingame 2024-05-07 02:38:16
010099C022B96000 Super Mario Galaxy slow;vulkan;amd-vendor-bug;vulkan-vendor-bug ingame 2025-10-01 15:30:00
0100FD8022DAA000 Super Mario Galaxy 2 slow;vulkan;amd-vendor-bug;vulkan-vendor-bug;deadlock ingame 2025-10-04 18:50:00
2857 010028600EBDA000 Super Mario™ 3D World + Bowser’s Fury ldn-works playable 2024-07-31 10:45:37
2858 01004F8006A78000 Super Meat Boy services playable 2020-04-02 23:10:07
2859 01009C200D60E000 Super Meat Boy Forever gpu boots 2021-04-26 14:25:39
2860 0100BDD00EC5C000 Super Mega Space Blaster Special Turbo online playable 2020-08-06 12:13:25
2861 010031F019294000 Super Monkey Ball Banana Rumble ldn-broken playable 2025-10-01 18:03:00 2024-06-28 10:39:18
2862 0100B2A00E1E0000 Super Monkey Ball: Banana Blitz HD online-broken playable 2022-09-16 13:16:25
2863 01006D000D2A0000 Super Mutant Alien Assault playable 2020-06-07 23:32:45
2864 01004D600AC14000 Super Neptunia RPG nvdec playable 2022-08-17 16:38:52
2924 0100B76011DAA000 Taxi Chaos slow;online-broken;UE4 playable 2022-10-25 19:13:00
2925 0100F43011E5A000 Tcheco in the Castle of Lucio playable 2020-06-27 13:35:43
2926 010092B0091D0000 Team Sonic Racing online-broken;ldn-works playable 2024-02-05 15:05:27
010084B00B36E000 Team Sonic Racing online-broken;ldn-works playable 2024-02-05 15:05:27
2927 0100FE701475A000 Teenage Mutant Ninja Turtles: Shredder's Revenge deadlock;crash boots 2024-09-28 09:31:39
2928 01005CF01E784000 Teenage Mutant Ninja Turtles: Splintered Fate playable 2024-08-03 13:50:42
2929 0100FDB0154E4000 Teenage Mutant Ninja Turtles: The Cowabunga Collection playable 2024-01-22 19:39:04
2969 0100EBA01548E000 The Cruel King and the Great Hero gpu;services ingame 2022-12-02 07:02:08
2970 010051800E922000 The Dark Crystal: Age of Resistance Tactics playable 2020-08-11 13:43:41
2971 01003DE00918E000 The Darkside Detective playable 2020-06-03 22:16:18
010032B015D66000 The DioField Chronicle playable 2025-09-05 11:35:50
2972 01000A10041EA000 The Elder Scrolls V: Skyrim gpu;crash ingame 2024-07-14 03:21:31
2973 01004A9006B84000 The End Is Nigh playable 2020-06-01 11:26:45
2974 0100CA100489C000 The Escapists 2 nvdec playable 2020-09-24 12:31:31
2976 0100C2E0129A6000 The Executioner nvdec playable 2021-01-23 00:31:28
2977 01006050114D4000 The Experiment: Escape Room gpu ingame 2022-09-30 13:20:35
2978 0100B5900DFB2000 The Eyes of Ara playable 2022-09-16 14:44:06
0100BA5013E52000 The Falconeer: Warrior Edition playable 2025-07-30 12:04:50
2979 01002DD00AF9E000 The Fall gpu ingame 2020-05-31 23:31:16
2980 01003E5002320000 The Fall Part 2: Unbound playable 2021-11-06 02:18:08
2981 0100CDC00789E000 The Final Station nvdec playable 2022-08-22 15:54:39
3198 010000400F582000 TT Isle of Man Ride on the Edge 2 gpu;nvdec;online-broken ingame 2022-09-30 22:13:05
3199 0100752011628000 TTV2 playable 2020-11-27 13:21:36
3200 0100AFE00452E000 Tumblestone playable 2021-01-07 17:49:20
0100D1A01D7BA000 Turbo Overkill playable 2025-07-30 12:08:57
3201 010085500D5F6000 Turok gpu ingame 2021-06-04 13:16:24
3202 0100CDC00D8D6000 Turok 2: Seeds of Evil gpu;vulkan ingame 2022-09-12 17:50:05
3203 010004B0130C8000 Turrican Flashback audout playable 2021-08-30 10:07:56
3207 010038400C2FE000 TY the Tasmanian Tiger™ HD 32-bit;crash;nvdec menus 2020-12-17 21:15:00
3208 010073A00C4B2000 Tyd wag vir Niemand playable 2021-03-02 13:39:53
3209 0100D5B00D6DA000 Type:Rider playable 2021-01-06 13:12:55
01008AF01AD22000 The Patrick Star Game playable 2025-10-01 17:55:30
3210 010040D01222C000 UBERMOSH: SANTICIDE playable 2020-11-27 15:05:01
3211 0100992010BF8000 Ubongo playable 2021-02-04 21:15:01
3212 010079000B56C000 UglyDolls: An Imperfect Adventure nvdec;UE4 playable 2022-08-25 14:42:16
3221 0100592005164000 UNBOX: Newbie's Adventure UE4 playable 2022-08-29 13:12:56
3222 01002D900C5E4000 Uncanny Valley nvdec playable 2021-06-04 13:28:45
3223 010076F011F54000 Undead & Beyond nvdec playable 2022-10-04 09:11:18
01009B700D0B8000 Undead Horde playable 2025-07-30 12:05:05
0100FC301A878000 Undead Horde 2: Necropolis playable 2025-07-30 12:06:07
3224 01008F3013E4E000 Under Leaves playable 2021-05-22 18:13:58
3225 010080B00AD66000 Undertale playable 2022-08-31 17:31:46
3226 01008F80049C6000 Unepic playable 2024-01-15 17:03:00
3451 0100F4401940A000 超探偵事件簿 レインコード (Master Detective Archives: Rain Code) crash ingame 2024-02-12 20:58:31
3452 010064801A01C000 超次元ゲイム ネプテューヌ GameMaker R:Evolution crash nothing 2023-10-30 22:37:40
3453 0100F3400332C000 ゼノブレイド2 deadlock;amd-vendor-bug ingame 2024-03-28 14:31:41
010075000ECBE000 超级马力欧 奥德赛 nvdec;intel-vendor-bug;mac-bug playable 2024-08-25 01:32:34
010075100E8EC000 马力欧卡丁车8 豪华版 32-bit;ldn-works;LAN;amd-vendor-bug playable 2024-09-19 11:55:17
0100E8C00F506000 新 超级马力欧兄弟U 豪华版 32-bit playable 2023-10-08 02:06:37

View File

@@ -1,6 +1,6 @@
{
"sdk": {
"version": "10.0.100",
"version": "9.0.100",
"rollForward": "latestFeature"
}
}

View File

@@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.Arm64
static class ComparisonArm64Extensions
{
extension(Comparison comparison)
public static ArmCondition ToArmCondition(this Comparison comp)
{
public ArmCondition Arm => comparison switch
return comp switch
{
#pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => ArmCondition.Eq,
@@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.Arm64
Comparison.LessUI => ArmCondition.LtUn,
#pragma warning restore IDE0055
_ => throw new ArgumentException(null, nameof(comparison))
_ => throw new ArgumentException(null, nameof(comp)),
};
}
}

View File

@@ -181,10 +181,10 @@ namespace ARMeilleure.CodeGen.Arm64
public void Fmov(Operand rd, Operand rn, bool topHalf)
{
Debug.Assert(rd.Type.IsInteger != rn.Type.IsInteger);
Debug.Assert(rd.Type.IsInteger() != rn.Type.IsInteger());
Debug.Assert(rd.Type == OperandType.I64 || rn.Type == OperandType.I64 || !topHalf);
uint opcode = rd.Type.IsInteger ? 0b110u : 0b111u;
uint opcode = rd.Type.IsInteger() ? 0b110u : 0b111u;
uint rmode = topHalf ? 1u << 19 : 0u;
uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u;
@@ -411,7 +411,7 @@ namespace ARMeilleure.CodeGen.Arm64
public void Mov(Operand rd, Operand rn)
{
if (rd.Type.IsInteger)
if (rd.Type.IsInteger())
{
Orr(rd, Factory.Register(ZrRegister, RegisterType.Integer, rd.Type), rn);
}
@@ -973,7 +973,7 @@ namespace ARMeilleure.CodeGen.Arm64
uint instruction;
int scale;
if (type.IsInteger)
if (type.IsInteger())
{
instruction = intInst;
@@ -1009,7 +1009,7 @@ namespace ARMeilleure.CodeGen.Arm64
{
uint instruction;
if (type.IsInteger)
if (type.IsInteger())
{
instruction = intInst;

View File

@@ -250,7 +250,7 @@ namespace ARMeilleure.CodeGen.Arm64
// ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Add(dest, src1, src2);
}
@@ -268,7 +268,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.And(dest, src1, src2);
}
@@ -281,7 +281,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Eor(dest, src1, src2);
}
@@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Mvn(dest, source);
}
@@ -311,7 +311,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Orr(dest, src1, src2);
}
@@ -322,7 +322,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant);
ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
GenerateCompareCommon(context, operation);
@@ -336,7 +336,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Rev(dest, source);
}
@@ -354,7 +354,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant);
ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
GenerateCompareCommon(context, operation);
@@ -428,7 +428,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(src1, src2);
Debug.Assert(src1.Type.IsInteger);
Debug.Assert(src1.Type.IsInteger());
context.Assembler.Cmp(src1, src2);
}
@@ -442,7 +442,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Cmp(src1, Const(src1.Type, 0));
@@ -468,7 +468,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type != source.Type);
Debug.Assert(source.Type != OperandType.V128);
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
context.Assembler.ScvtfScalar(dest, source);
}
@@ -485,7 +485,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
Debug.Assert(dest.Type != source.Type);
Debug.Assert(source.Type.IsInteger);
Debug.Assert(source.Type.IsInteger());
context.Assembler.UcvtfScalar(dest, source);
}
@@ -497,7 +497,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant);
// Moves to the same register are useless.
if (dest.Kind == source.Kind && dest.Value == source.Value)
@@ -529,7 +529,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Clz(dest, source);
}
@@ -542,7 +542,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, dividend, divisor);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Sdiv(dest, dividend, divisor);
}
@@ -576,7 +576,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.Destination;
Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.LdrhRiUn(value, address, 0);
}
@@ -586,7 +586,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.Destination;
Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.LdrbRiUn(value, address, 0);
}
@@ -604,7 +604,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Mul(dest, src1, src2);
}
@@ -647,7 +647,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Neg(dest, source);
}
@@ -732,7 +732,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Sxth(dest, source);
}
@@ -742,7 +742,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Sxtw(dest, source);
}
@@ -752,7 +752,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Sxtb(dest, source);
}
@@ -823,7 +823,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.StrhRiUn(value, address, 0);
}
@@ -833,7 +833,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.StrbRiUn(value, address, 0);
}
@@ -858,7 +858,7 @@ namespace ARMeilleure.CodeGen.Arm64
// ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Sub(dest, src1, src2);
}
@@ -882,7 +882,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (dest != default)
{
Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger());
OperandType destType = source.Type == OperandType.I64 ? OperandType.FP64 : OperandType.FP32;
@@ -901,9 +901,9 @@ namespace ARMeilleure.CodeGen.Arm64
byte index = src2.AsByte();
Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes());
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Umov(dest, src1, index, dest.Type == OperandType.I64 ? 3 : 2);
}
@@ -959,7 +959,7 @@ namespace ARMeilleure.CodeGen.Arm64
byte index = src3.AsByte();
if (src2.Type.IsInteger)
if (src2.Type.IsInteger())
{
context.Assembler.Ins(dest, src2, index, src2.Type == OperandType.I64 ? 3 : 2);
}
@@ -1007,7 +1007,7 @@ namespace ARMeilleure.CodeGen.Arm64
{
Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger());
context.Assembler.CmeqVector(dest, dest, dest, 2);
}
@@ -1016,7 +1016,7 @@ namespace ARMeilleure.CodeGen.Arm64
{
Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger());
context.Assembler.EorVector(dest, dest, dest);
}
@@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Uxth(dest, source);
}
@@ -1056,7 +1056,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
// We can eliminate the move if source is already 32-bit and the registers are the same.
if (dest.Value == source.Value && source.Type == OperandType.I32)
@@ -1072,7 +1072,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Uxtb(dest, source);
}
@@ -1169,7 +1169,7 @@ namespace ARMeilleure.CodeGen.Arm64
context.Assembler.StrRiPre(Register(reg, type), Register(SpRegister), -calleeSaveRegionSize);
}
offset += type.ByteSize;
offset += type.GetSizeInBytes();
}
while (mask != 0)
@@ -1195,7 +1195,7 @@ namespace ARMeilleure.CodeGen.Arm64
context.Assembler.StpRiPre(Register(reg, type), Register(reg2, type), Register(SpRegister), -calleeSaveRegionSize);
}
offset += type.ByteSize * 2;
offset += type.GetSizeInBytes() * 2;
}
}
@@ -1273,7 +1273,7 @@ namespace ARMeilleure.CodeGen.Arm64
mask &= ~(1 << reg2);
offset -= type.ByteSize * 2;
offset -= type.GetSizeInBytes() * 2;
if (offset != 0)
{
@@ -1286,7 +1286,7 @@ namespace ARMeilleure.CodeGen.Arm64
}
else
{
offset -= type.ByteSize;
offset -= type.GetSizeInBytes();
if (offset != 0)
{
@@ -1435,12 +1435,12 @@ namespace ARMeilleure.CodeGen.Arm64
OperandType valueType = GetMemOpValueType(currentOp);
if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.ByteSize != op2Offset)
if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.GetSizeInBytes() != op2Offset)
{
return false;
}
if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.ByteSizeLog2))
if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.GetSizeInBytesLog2()))
{
return false;
}
@@ -1549,7 +1549,7 @@ namespace ARMeilleure.CodeGen.Arm64
// EnsureSameReg (dest, src1);
EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32);
}
private static void EnsureSameReg(Operand op1, Operand op2)

View File

@@ -462,7 +462,7 @@ namespace ARMeilleure.CodeGen.Arm64
{
instruction |= (sz << 22);
if (rd.Type.IsInteger)
if (rd.Type.IsInteger())
{
context.Assembler.WriteInstructionAuto(instruction, rd, rn);
}
@@ -490,7 +490,7 @@ namespace ARMeilleure.CodeGen.Arm64
instruction |= (sz << 22);
instruction |= (64 - fBits) << 10;
if (rd.Type.IsInteger)
if (rd.Type.IsInteger())
{
Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);

View File

@@ -112,7 +112,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src1.Kind == OperandKind.Constant)
{
if (!src1.Type.IsInteger)
if (!src1.Type.IsInteger())
{
// Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following:
@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src2.Kind == OperandKind.Constant)
{
if (!src2.Type.IsInteger)
if (!src2.Type.IsInteger())
{
src2 = AddFloatConstantCopy(constants, nodes, node, src2);
@@ -191,7 +191,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src.Kind == OperandKind.Constant)
{
if (!src.Type.IsInteger)
if (!src.Type.IsInteger())
{
src = AddFloatConstantCopy(constants, nodes, node, src);
@@ -282,7 +282,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
passOnReg = intCount < intMax;
}
@@ -309,7 +309,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (passOnReg)
{
Operand argReg = source.Type.IsInteger
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -327,7 +327,7 @@ namespace ARMeilleure.CodeGen.Arm64
InsertConstantRegCopies(constants, nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.ByteSize;
stackOffset += source.Type.GetSizeInBytes();
}
}
@@ -345,7 +345,7 @@ namespace ARMeilleure.CodeGen.Arm64
}
else
{
Operand retReg = dest.Type.IsInteger
Operand retReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
passOnReg = intCount + 1 < intMax;
}
@@ -408,7 +408,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (passOnReg)
{
Operand argReg = source.Type.IsInteger
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -521,7 +521,7 @@ namespace ARMeilleure.CodeGen.Arm64
}
else
{
Operand retReg = source.Type.IsInteger
Operand retReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
@@ -551,7 +551,7 @@ namespace ARMeilleure.CodeGen.Arm64
{
OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger)
if (argType.IsInteger())
{
intCount++;
}
@@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount();
}
@@ -606,7 +606,7 @@ namespace ARMeilleure.CodeGen.Arm64
{
Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger
Operand argReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);

View File

@@ -51,7 +51,7 @@ namespace ARMeilleure.CodeGen.Optimizations
if (trueSucc == block.ListNext)
{
Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32();
Comparison compInv = comp.Inverse;
Comparison compInv = comp.Invert();
branchOp.SetSource(2, Const((int)compInv));

View File

@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
}
else if (otherCompType == Comparison.Equal)
{
propCompType = compType.Inverse;
propCompType = compType.Invert();
}
else
{

View File

@@ -105,7 +105,7 @@ namespace ARMeilleure.CodeGen.Optimizations
Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1);
if (x == y && x.Type.IsInteger)
if (x == y && x.Type.IsInteger())
{
operation.TurnIntoCopy(Const(x.Type, 0));
}
@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
private static bool IsConstEqual(Operand operand, ulong comparand)
{
if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger)
if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger())
{
return false;
}

View File

@@ -98,7 +98,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
OperandType type = types[copyDest];
type = type.IsInteger ? OperandType.I64 : OperandType.V128;
type = type.IsInteger() ? OperandType.I64 : OperandType.V128;
EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type));

View File

@@ -178,7 +178,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
else if (dest.Kind == OperandKind.Register)
{
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
intFixedRegisters |= 1 << dest.GetRegister().Index;
}
@@ -236,7 +236,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Register reg = info.Register.GetRegister();
if (local.Type.IsInteger)
if (local.Type.IsInteger())
{
intLocalFreeRegisters |= 1 << reg.Index;
}
@@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (temp == default || info.Sequence != sequence)
{
temp = local.Type.IsInteger
temp = local.Type.IsInteger()
? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse)
: GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse);
@@ -335,7 +335,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (info.UsesAllocated == 0)
{
int mask = dest.Type.IsInteger
int mask = dest.Type.IsInteger()
? intLocalFreeRegisters
: vecLocalFreeRegisters;
@@ -343,9 +343,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
int selectedReg = BitOperations.TrailingZeroCount(mask);
info.Register = Register(selectedReg, info.Type.Register, info.Type);
info.Register = Register(selectedReg, info.Type.ToRegisterType(), info.Type);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
intLocalFreeRegisters &= ~(1 << selectedReg);
intUsedRegisters |= 1 << selectedReg;
@@ -359,7 +359,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
else
{
info.Register = default;
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.ByteSize));
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.GetSizeInBytes()));
}
}
@@ -377,7 +377,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (temp == default || info.Sequence != sequence)
{
temp = dest.Type.IsInteger
temp = dest.Type.IsInteger()
? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg)
: GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg);
@@ -443,7 +443,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
useMask |= 1 << selectedReg;
return Register(selectedReg, local.Type.Register, local.Type);
return Register(selectedReg, local.Type.ToRegisterType(), local.Type);
}
private static int UsesCount(Operand local)

View File

@@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{
RegisterType regType = current.Local.Type.Register;
RegisterType regType = current.Local.Type.ToRegisterType();
Span<int> freePositions = stackalloc int[registersCount];
@@ -318,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{
RegisterType regType = current.Local.Type.Register;
RegisterType regType = current.Local.Type.ToRegisterType();
Span<int> usePositions = stackalloc int[registersCount];
Span<int> blockedPositions = stackalloc int[registersCount];

View File

@@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public int Allocate(OperandType type)
{
return Allocate(type.ByteSize);
return Allocate(type.GetSizeInBytes());
}
public int Allocate(int sizeInBytes)

View File

@@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
{
ref readonly InstructionInfo info = ref _instTable[(int)X86Instruction.Movd];
if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory)
{
WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true);
}
@@ -416,11 +416,11 @@ namespace ARMeilleure.CodeGen.X86
InstructionFlags flags = info.Flags | InstructionFlags.RexW;
if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory)
{
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true);
}
else if (dest.Type.IsInteger || dest.Kind == OperandKind.Memory)
else if (dest.Type.IsInteger() || dest.Kind == OperandKind.Memory)
{
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR);
}
@@ -1107,17 +1107,17 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
if ((flags & InstructionFlags.Prefix66) != 0)
if (flags.HasFlag(InstructionFlags.Prefix66))
{
WriteByte(0x66);
}
if ((flags & InstructionFlags.PrefixF2) != 0f)
if (flags.HasFlag(InstructionFlags.PrefixF2))
{
WriteByte(0xf2);
}
if ((flags & InstructionFlags.PrefixF3) != 0f)
if (flags.HasFlag(InstructionFlags.PrefixF3))
{
WriteByte(0xf3);
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86
{

View File

@@ -2,6 +2,7 @@ using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation;
using Microsoft.IO;
using Ryujinx.Common.Memory;
using System.IO;
using System.Numerics;
namespace ARMeilleure.CodeGen.X86

View File

@@ -289,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Popcnt(dest, source, dest.Type);
@@ -303,7 +303,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source);
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, source);
@@ -315,7 +315,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && !source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger());
if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
{
@@ -349,8 +349,8 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!src2.Type.IsInteger || src2.Kind == OperandKind.Constant);
Debug.Assert(!dest.Type.IsInteger());
Debug.Assert(!src2.Type.IsInteger() || src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
@@ -370,7 +370,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger && src2.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger() && src2.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type);
@@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1);
Debug.Assert(dest.Type.IsInteger && src1.Type.IsInteger && src2.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && src1.Type.IsInteger() && src2.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type);
@@ -405,7 +405,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger && src2.Kind == OperandKind.Constant);
Debug.Assert(!dest.Type.IsInteger() && src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte());
@@ -421,7 +421,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, src1, src2, src3);
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger());
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
{
@@ -461,7 +461,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger && src3.Kind == OperandKind.Constant);
Debug.Assert(!dest.Type.IsInteger() && src3.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte());
@@ -512,7 +512,7 @@ namespace ARMeilleure.CodeGen.X86
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
// If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA.
if (dest.Kind == src1.Kind && dest.Value == src1.Value)
@@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
// Note: GenerateCompareCommon makes the assumption that BitwiseAnd will emit only a single `and`
// instruction.
@@ -582,7 +582,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Xor(dest, src2, dest.Type);
}
@@ -599,7 +599,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Not(dest);
}
@@ -612,7 +612,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Or(dest, src2, dest.Type);
}
@@ -623,7 +623,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant);
X86Condition cond = ((Comparison)comp.AsInt32()).X86;
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
GenerateCompareCommon(context, operation);
@@ -637,7 +637,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Bswap(dest);
}
@@ -661,7 +661,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant);
X86Condition cond = ((Comparison)comp.AsInt32()).X86;
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
GenerateCompareCommon(context, operation);
@@ -676,7 +676,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src1, src2);
Debug.Assert(src1.Type.IsInteger);
Debug.Assert(src1.Type.IsInteger());
if (src2.Kind == OperandKind.Constant && src2.Value == 0)
{
@@ -766,7 +766,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src3);
EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Test(src1, src1, src1.Type);
@@ -792,9 +792,9 @@ namespace ARMeilleure.CodeGen.X86
if (dest.Type == OperandType.FP32)
{
Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP64);
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP64);
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2ss(dest, dest, source, source.Type);
@@ -808,9 +808,9 @@ namespace ARMeilleure.CodeGen.X86
}
else /* if (dest.Type == OperandType.FP64) */
{
Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP32);
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP32);
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2sd(dest, dest, source, source.Type);
@@ -831,7 +831,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant);
// Moves to the same register are useless.
if (dest.Kind == source.Kind && dest.Value == source.Value)
@@ -845,7 +845,7 @@ namespace ARMeilleure.CodeGen.X86
// Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient.
context.Assembler.Xor(dest, dest, OperandType.I32);
}
else if (dest.Type.IsInteger)
else if (dest.Type.IsInteger())
{
context.Assembler.Mov(dest, source, dest.Type);
}
@@ -862,7 +862,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Bsr(dest, source, dest.Type);
@@ -894,12 +894,12 @@ namespace ARMeilleure.CodeGen.X86
Operand dividend = operation.GetSource(0);
Operand divisor = operation.GetSource(1);
if (!dest.Type.IsInteger)
if (!dest.Type.IsInteger())
{
ValidateBinOp(dest, dividend, divisor);
}
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
divisor = operation.GetSource(2);
@@ -932,7 +932,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rdx = Register(X86Register.Rdx);
Debug.Assert(divisor.Type.IsInteger);
Debug.Assert(divisor.Type.IsInteger());
context.Assembler.Xor(rdx, rdx, OperandType.I32);
context.Assembler.Div(divisor);
@@ -967,7 +967,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.Movzx16(value, address, value.Type);
}
@@ -977,7 +977,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.Movzx8(value, address, value.Type);
}
@@ -1000,7 +1000,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
if (src2.Kind == OperandKind.Constant)
{
@@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger());
context.Assembler.Neg(dest);
}
@@ -1107,7 +1107,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Movsx16(dest, source, dest.Type);
}
@@ -1117,7 +1117,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Movsx32(dest, source, dest.Type);
}
@@ -1127,7 +1127,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Movsx8(dest, source, dest.Type);
}
@@ -1187,7 +1187,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.Mov16(address, value);
}
@@ -1197,7 +1197,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger);
Debug.Assert(value.Type.IsInteger());
context.Assembler.Mov8(address, value);
}
@@ -1210,7 +1210,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
context.Assembler.Sub(dest, src2, dest.Type);
}
@@ -1236,7 +1236,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger());
if (source.Type == OperandType.I32)
{
@@ -1259,7 +1259,7 @@ namespace ARMeilleure.CodeGen.X86
byte index = src2.AsByte();
Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes());
if (dest.Type == OperandType.I32)
{
@@ -1541,7 +1541,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger());
context.Assembler.Pcmpeqw(dest, dest, dest);
}
@@ -1550,7 +1550,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!dest.Type.IsInteger());
context.Assembler.Xorps(dest, dest, dest);
}
@@ -1580,7 +1580,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Movzx16(dest, source, OperandType.I32);
}
@@ -1590,7 +1590,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
// We can eliminate the move if source is already 32-bit and the registers are the same.
if (dest.Value == source.Value && source.Type == OperandType.I32)
@@ -1606,7 +1606,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
context.Assembler.Movzx8(dest, source, OperandType.I32);
}
@@ -1713,12 +1713,12 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1);
EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32);
}
private static void EnsureSameReg(Operand op1, Operand op2)
{
if (!op1.Type.IsInteger && HardwareCapabilities.SupportsVexEncoding)
if (!op1.Type.IsInteger() && HardwareCapabilities.SupportsVexEncoding)
{
return;
}

View File

@@ -86,7 +86,7 @@ namespace ARMeilleure.CodeGen.X86
break;
case Instruction.Negate:
if (!node.GetSource(0).Type.IsInteger)
if (!node.GetSource(0).Type.IsInteger())
{
GenerateNegate(block.Operations, node);
}
@@ -159,7 +159,7 @@ namespace ARMeilleure.CodeGen.X86
if (src1.Kind == OperandKind.Constant)
{
if (!src1.Type.IsInteger)
if (!src1.Type.IsInteger())
{
// Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following:
@@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.X86
if (src2.Kind == OperandKind.Constant)
{
if (!src2.Type.IsInteger)
if (!src2.Type.IsInteger())
{
src2 = AddXmmCopy(nodes, node, src2);
@@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.X86
// - The dividend is always in RDX:RAX.
// - The result is always in RAX.
// - Additionally it also writes the remainder in RDX.
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
Operand src1 = node.GetSource(0);
@@ -466,7 +466,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = node.Destination;
Operand source = node.GetSource(0);
Debug.Assert(source.Type.IsInteger, $"Invalid source type \"{source.Type}\".");
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\".");
Operation currentNode = node;
@@ -654,10 +654,10 @@ namespace ARMeilleure.CodeGen.X86
switch (operation.Instruction)
{
case Instruction.Add:
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger();
case Instruction.Multiply:
case Instruction.Subtract:
return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger;
return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger();
case Instruction.BitwiseAnd:
case Instruction.BitwiseExclusiveOr:
@@ -672,7 +672,7 @@ namespace ARMeilleure.CodeGen.X86
return true;
case Instruction.Divide:
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger();
case Instruction.VectorInsert:
case Instruction.VectorInsert16:

View File

@@ -35,7 +35,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
passOnReg = intCount < intMax;
}
@@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg)
{
Operand argReg = source.Type.IsInteger
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -80,7 +80,7 @@ namespace ARMeilleure.CodeGen.X86
InsertConstantRegCopies(nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.ByteSize;
stackOffset += source.Type.GetSizeInBytes();
}
}
@@ -102,7 +102,7 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
Operand retReg = dest.Type.IsInteger
Operand retReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@@ -137,7 +137,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
passOnReg = intCount + 1 < intMax;
}
@@ -160,7 +160,7 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg)
{
Operand argReg = source.Type.IsInteger
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -210,7 +210,7 @@ namespace ARMeilleure.CodeGen.X86
{
OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger)
if (argType.IsInteger())
{
intCount++;
}
@@ -226,7 +226,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
passOnReg = intCount < CallingConvention.GetIntArgumentsOnRegsCount();
}
@@ -265,7 +265,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger
Operand argReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
@@ -320,7 +320,7 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
Operand retReg = source.Type.IsInteger
Operand retReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);

View File

@@ -40,7 +40,7 @@ namespace ARMeilleure.CodeGen.X86
if (dest != default && dest.Type == OperandType.V128)
{
int stackOffset = AllocateOnStack(dest.Type.ByteSize);
int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes());
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
@@ -76,7 +76,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand stackAddr = Local(OperandType.I64);
int stackOffset = AllocateOnStack(source.Type.ByteSize);
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes());
nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
@@ -96,7 +96,7 @@ namespace ARMeilleure.CodeGen.X86
int argIndex = index + retArgs;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type);
}
@@ -140,7 +140,7 @@ namespace ARMeilleure.CodeGen.X86
}
else
{
Operand retReg = dest.Type.IsInteger
Operand retReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@@ -171,7 +171,7 @@ namespace ARMeilleure.CodeGen.X86
for (int index = 0; index < argsCount; index++)
{
Operand source = node.GetSource(1 + index);
Operand argReg = source.Type.IsInteger
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type);
@@ -219,7 +219,7 @@ namespace ARMeilleure.CodeGen.X86
{
Operand argReg, pArg;
if (dest.Type.IsInteger)
if (dest.Type.IsInteger())
{
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type);
pArg = Local(dest.Type);
@@ -283,7 +283,7 @@ namespace ARMeilleure.CodeGen.X86
Operand source = node.GetSource(0);
Operand retReg;
if (source.Type.IsInteger)
if (source.Type.IsInteger())
{
retReg = Gpr(CallingConvention.GetIntReturnRegister(), source.Type);
}

View File

@@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.X86
static class ComparisonX86Extensions
{
extension(Comparison comparison)
public static X86Condition ToX86Condition(this Comparison comp)
{
public X86Condition X86 => comparison switch
return comp switch
{
#pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => X86Condition.Equal,
@@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.X86
Comparison.LessUI => X86Condition.Below,
#pragma warning restore IDE0055
_ => throw new ArgumentException(null, nameof(comparison))
_ => throw new ArgumentException(null, nameof(comp)),
};
}
}

View File

@@ -1,3 +1,5 @@
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86
{
enum X86Register

View File

@@ -168,7 +168,7 @@ namespace ARMeilleure.Common
{
_allocated.Dispose();
foreach (nint page in _pages.Values)
foreach (IntPtr page in _pages.Values)
{
NativeAllocator.Instance.Free((void*)page);
}

View File

@@ -22,11 +22,11 @@ namespace ARMeilleure.Decoders
static class ConditionExtensions
{
extension(Condition condition)
public static Condition Invert(this Condition cond)
{
// Bit 0 of all conditions is basically a negation bit, so
// inverting this bit has the effect of inverting the condition.
public Condition Inverse => (Condition)((int)condition ^ 1);
return (Condition)((int)cond ^ 1);
}
}
}

View File

@@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
context.LoadFromContext();
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
context.Return(Const(op.Address));
}
public static void Svc(ArmEmitterContext context)
@@ -49,7 +49,7 @@ namespace ARMeilleure.Instructions
context.LoadFromContext();
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
context.Return(Const(op.Address));
}
}
}

View File

@@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions
context.LoadFromContext();
InstEmitFlowHelper.EmitReturn(context, Const(context.CurrOp.Address));
context.Return(Const(context.CurrOp.Address));
}
}
}

View File

@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
EmitReturn(context, GetIntOrZR(context, op.Rn));
context.Return(GetIntOrZR(context, op.Rn));
}
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);

View File

@@ -13,10 +13,6 @@ namespace ARMeilleure.Instructions
{
static class InstEmitFlowHelper
{
// How many calls we can have in our call stack before we give up and return to the dispatcher.
// This prevents stack overflows caused by deep recursive calls.
private const int MaxCallDepth = 200;
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
{
if (cond != Condition.Al)
@@ -147,12 +143,6 @@ namespace ARMeilleure.Instructions
public static void EmitCall(ArmEmitterContext context, ulong immediate)
{
if (context.IsSingleStep)
{
context.Return(Const(immediate));
return;
}
bool isRecursive = immediate == context.EntryAddress;
if (isRecursive)
@@ -167,7 +157,12 @@ namespace ARMeilleure.Instructions
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
{
if (context.IsSingleStep)
EmitTableBranch(context, target, isJump: false);
}
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
{
if (isReturn)
{
if (target.Type == OperandType.I32)
{
@@ -177,36 +172,11 @@ namespace ARMeilleure.Instructions
context.Return(target);
}
else
{
EmitTableBranch(context, target, isJump: false);
}
}
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
{
if (isReturn || context.IsSingleStep)
{
EmitReturn(context, target);
}
else
{
EmitTableBranch(context, target, isJump: true);
}
}
public static void EmitReturn(ArmEmitterContext context, Operand target)
{
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
DecreaseCallDepth(context, nativeContext);
if (target.Type == OperandType.I32)
{
target = context.ZeroExtend32(OperandType.I64, target);
}
context.Return(target);
}
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
{
context.StoreToContext();
@@ -269,8 +239,6 @@ namespace ARMeilleure.Instructions
if (isJump)
{
DecreaseCallDepth(context, nativeContext);
context.Tailcall(hostAddress, nativeContext);
}
else
@@ -292,42 +260,8 @@ namespace ARMeilleure.Instructions
Operand lblContinue = context.GetLabel(nextAddr.Value);
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
DecreaseCallDepth(context, nativeContext);
context.Return(returnAddress);
}
}
public static void EmitCallDepthCheckAndIncrement(EmitterContext context, Operand guestAddress)
{
if (!Optimizations.EnableDeepCallRecursionProtection)
{
return;
}
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
Operand lblDoCall = Label();
context.BranchIf(lblDoCall, currentCallDepth, Const(MaxCallDepth), Comparison.LessUI);
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
context.Return(guestAddress);
context.MarkLabel(lblDoCall);
context.Store(callDepthAddr, context.Add(currentCallDepth, Const(1)));
}
private static void DecreaseCallDepth(EmitterContext context, Operand nativeContext)
{
if (!Optimizations.EnableDeepCallRecursionProtection)
{
return;
}
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
}
}
}

View File

@@ -16,7 +16,7 @@ namespace ARMeilleure.Instructions
public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli)
{
Debug.Assert(crc.Type.IsInteger && value.Type.IsInteger);
Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger());
Debug.Assert(size is >= 0 and < 4);
Debug.Assert((size < 3) || (value.Type == OperandType.I64));

View File

@@ -157,7 +157,7 @@ namespace ARMeilleure.Instructions
context.Copy(temp, value);
if (!context.Memory.Type.IsHostMappedOrTracked)
if (!context.Memory.Type.IsHostMappedOrTracked())
{
context.Branch(lblEnd);
@@ -198,7 +198,7 @@ namespace ARMeilleure.Instructions
SetInt(context, rt, value);
if (!context.Memory.Type.IsHostMappedOrTracked)
if (!context.Memory.Type.IsHostMappedOrTracked())
{
context.Branch(lblEnd);
@@ -265,7 +265,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(rt), value);
if (!context.Memory.Type.IsHostMappedOrTracked)
if (!context.Memory.Type.IsHostMappedOrTracked())
{
context.Branch(lblEnd);
@@ -312,7 +312,7 @@ namespace ARMeilleure.Instructions
break;
}
if (!context.Memory.Type.IsHostMappedOrTracked)
if (!context.Memory.Type.IsHostMappedOrTracked())
{
context.Branch(lblEnd);
@@ -385,7 +385,7 @@ namespace ARMeilleure.Instructions
break;
}
if (!context.Memory.Type.IsHostMappedOrTracked)
if (!context.Memory.Type.IsHostMappedOrTracked())
{
context.Branch(lblEnd);
@@ -399,11 +399,11 @@ namespace ARMeilleure.Instructions
public static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath, bool write, int size)
{
if (context.Memory.Type.IsHostMapped)
if (context.Memory.Type.IsHostMapped())
{
return EmitHostMappedPointer(context, address);
}
else if (context.Memory.Type.IsHostTracked)
else if (context.Memory.Type.IsHostTracked())
{
if (address.Type == OperandType.I32)
{

View File

@@ -2,6 +2,7 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Diagnostics.CodeAnalysis;
using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions

View File

@@ -3,7 +3,6 @@ using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Runtime.InteropServices;
using ExecutionContext = ARMeilleure.State.ExecutionContext;
namespace ARMeilleure.Instructions
{

View File

@@ -0,0 +1,692 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFallback
{
#region "ShrImm64"
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
if (shift <= 63)
{
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (shift == 64) */
{
return 0L;
}
}
}
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
ulong add = value + (ulong)roundConst;
if ((add < value) && (add < (ulong)roundConst))
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
}
}
#endregion
#region "Saturation"
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
#endregion
#region "Count"
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
#endregion
#region "Table"
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(default, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(default, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
}
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(dest, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
}
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{
byte[] res = new byte[16];
if (dest != default)
{
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
}
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
{
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
}
byte[] v = vector.ToArray();
for (byte index = 0; index < bytes; index++)
{
byte tblIndex = v[index];
if (tblIndex < table.Length)
{
res[index] = table[tblIndex];
}
}
return new V128(res);
}
#endregion
#region "Crc32"
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
return crc;
}
private static uint Crc32w(uint crc, uint poly, uint val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
return crc;
}
private static uint Crc32x(uint crc, uint poly, ulong val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
crc = Crc32(crc, poly, (byte)(val >> 32));
crc = Crc32(crc, poly, (byte)(val >> 40));
crc = Crc32(crc, poly, (byte)(val >> 48));
crc = Crc32(crc, poly, (byte)(val >> 56));
return crc;
}
private static uint Crc32(uint crc, uint poly, byte val)
{
crc ^= val;
for (int bit = 7; bit >= 0; bit--)
{
uint mask = (uint)(-(int)(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
}
return crc;
}
#endregion
#region "Aes"
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
#endregion
#region "Sha1"
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e)
{
return hash_e.Rol(30);
}
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaParity(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{
ulong t2 = w4_7.Extract<ulong>(0);
ulong t1 = w0_3.Extract<ulong>(1);
V128 result = new(t1, t2);
return result ^ (w0_3 ^ w8_11);
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{
V128 t = tw0_3 ^ (w12_15 >> 32);
uint tE0 = t.Extract<uint>(0);
uint tE1 = t.Extract<uint>(1);
uint tE2 = t.Extract<uint>(2);
uint tE3 = t.Extract<uint>(3);
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
}
private static void Rol32_160(ref uint y, ref V128 x)
{
uint xE3 = x.Extract<uint>(3);
x <<= 32;
x.Insert(0, y);
y = xE3;
}
private static uint ShaChoose(uint x, uint y, uint z)
{
return ((y ^ z) & x) ^ z;
}
private static uint ShaMajority(uint x, uint y, uint z)
{
return (x & y) | ((x | y) & z);
}
private static uint ShaParity(uint x, uint y, uint z)
{
return x ^ y ^ z;
}
private static uint Rol(this uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
#endregion
#region "Sha256"
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{
V128 result = new();
for (int e = 0; e <= 3; e++)
{
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
elt += w0_3.Extract<uint>(e);
result.Insert(e, elt);
}
return result;
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{
V128 result = new();
ulong t1 = w12_15.Extract<ulong>(1);
for (int e = 0; e <= 1; e++)
{
uint elt = t1.ULongPart(e);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
result.Insert(e, elt);
}
t1 = result.Extract<ulong>(0);
for (int e = 2; e <= 3; e++)
{
uint elt = t1.ULongPart(e - 2);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
result.Insert(e, elt);
}
return result;
}
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
{
for (int e = 0; e <= 3; e++)
{
uint chs = ShaChoose(y.Extract<uint>(0),
y.Extract<uint>(1),
y.Extract<uint>(2));
uint maj = ShaMajority(x.Extract<uint>(0),
x.Extract<uint>(1),
x.Extract<uint>(2));
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
uint t2 = t1 + x.Extract<uint>(3);
x.Insert(3, t2);
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
y.Insert(3, t2);
Rol32_256(ref y, ref x);
}
return part1 ? x : y;
}
private static void Rol32_256(ref V128 y, ref V128 x)
{
uint yE3 = y.Extract<uint>(3);
uint xE3 = x.Extract<uint>(3);
y <<= 32;
x <<= 32;
y.Insert(0, xE3);
x.Insert(0, yE3);
}
private static uint ShaHashSigma0(uint x)
{
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
}
private static uint ShaHashSigma1(uint x)
{
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
}
private static uint Ror(this uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static uint Lsr(this uint value, int count)
{
return value >> count;
}
private static uint ULongPart(this ulong value, int part)
{
return part == 0
? (uint)(value & 0xFFFFFFFFUL)
: (uint)(value >> 32);
}
#endregion
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{
V128 result = V128.Zero;
V128 op2_128 = new(op2, 0);
for (int i = 0; i < 64; i++)
{
if (((op1 >> i) & 1) == 1)
{
result ^= op2_128 << i;
}
}
return result;
}
}
}

View File

@@ -1,32 +0,0 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
}
}

View File

@@ -1,50 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
}
}

View File

@@ -1,74 +0,0 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
return crc;
}
private static uint Crc32w(uint crc, uint poly, uint val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
return crc;
}
private static uint Crc32x(uint crc, uint poly, ulong val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
crc = Crc32(crc, poly, (byte)(val >> 32));
crc = Crc32(crc, poly, (byte)(val >> 40));
crc = Crc32(crc, poly, (byte)(val >> 48));
crc = Crc32(crc, poly, (byte)(val >> 56));
return crc;
}
private static uint Crc32(uint crc, uint poly, byte val)
{
crc ^= val;
for (int bit = 7; bit >= 0; bit--)
{
uint mask = (uint)(-(int)(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
}
return crc;
}
}
}

View File

@@ -1,103 +0,0 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
}
}

View File

@@ -1,131 +0,0 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e)
{
return hash_e.Rol(30);
}
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaParity(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{
ulong t2 = w4_7.Extract<ulong>(0);
ulong t1 = w0_3.Extract<ulong>(1);
V128 result = new(t1, t2);
return result ^ (w0_3 ^ w8_11);
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{
V128 t = tw0_3 ^ (w12_15 >> 32);
uint tE0 = t.Extract<uint>(0);
uint tE1 = t.Extract<uint>(1);
uint tE2 = t.Extract<uint>(2);
uint tE3 = t.Extract<uint>(3);
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
}
private static void Rol32_160(ref uint y, ref V128 x)
{
uint xE3 = x.Extract<uint>(3);
x <<= 32;
x.Insert(0, y);
y = xE3;
}
private static uint ShaChoose(uint x, uint y, uint z)
{
return ((y ^ z) & x) ^ z;
}
private static uint ShaMajority(uint x, uint y, uint z)
{
return (x & y) | ((x | y) & z);
}
private static uint ShaParity(uint x, uint y, uint z)
{
return x ^ y ^ z;
}
private static uint Rol(this uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
}
}

View File

@@ -1,140 +0,0 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{
V128 result = new();
for (int e = 0; e <= 3; e++)
{
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
elt += w0_3.Extract<uint>(e);
result.Insert(e, elt);
}
return result;
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{
V128 result = new();
ulong t1 = w12_15.Extract<ulong>(1);
for (int e = 0; e <= 1; e++)
{
uint elt = t1.ULongPart(e);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
result.Insert(e, elt);
}
t1 = result.Extract<ulong>(0);
for (int e = 2; e <= 3; e++)
{
uint elt = t1.ULongPart(e - 2);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
result.Insert(e, elt);
}
return result;
}
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
{
for (int e = 0; e <= 3; e++)
{
uint chs = ShaChoose(y.Extract<uint>(0),
y.Extract<uint>(1),
y.Extract<uint>(2));
uint maj = ShaMajority(x.Extract<uint>(0),
x.Extract<uint>(1),
x.Extract<uint>(2));
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
uint t2 = t1 + x.Extract<uint>(3);
x.Insert(3, t2);
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
y.Insert(3, t2);
Rol32_256(ref y, ref x);
}
return part1 ? x : y;
}
private static void Rol32_256(ref V128 y, ref V128 x)
{
uint yE3 = y.Extract<uint>(3);
uint xE3 = x.Extract<uint>(3);
y <<= 32;
x <<= 32;
y.Insert(0, xE3);
x.Insert(0, yE3);
}
private static uint ShaHashSigma0(uint x)
{
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
}
private static uint ShaHashSigma1(uint x)
{
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
}
private static uint Ror(this uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static uint Lsr(this uint value, int count)
{
return value >> count;
}
private static uint ULongPart(this ulong value, int part)
{
return part == 0
? (uint)(value & 0xFFFFFFFFUL)
: (uint)(value >> 32);
}
}
}

View File

@@ -1,93 +0,0 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
if (shift <= 63)
{
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (shift == 64) */
{
return 0L;
}
}
}
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
ulong add = value + (ulong)roundConst;
if ((add < value) && (add < (ulong)roundConst))
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
}
}
}
}

View File

@@ -1,88 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(default, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(default, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
}
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(dest, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
}
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{
byte[] res = new byte[16];
if (dest != default)
{
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
}
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
{
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
}
byte[] v = vector.ToArray();
for (byte index = 0; index < bytes; index++)
{
byte tblIndex = v[index];
if (tblIndex < table.Length)
{
res[index] = table[tblIndex];
}
}
return new V128(res);
}
}
}

View File

@@ -1,26 +0,0 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{
V128 result = V128.Zero;
V128 op2_128 = new(op2, 0);
for (int i = 0; i < 64; i++)
{
if (((op1 >> i) & 1) == 1)
{
result ^= op2_128 << i;
}
}
return result;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,111 +0,0 @@
using ARMeilleure.State;
using System;
using System.Diagnostics;
namespace ARMeilleure.Instructions
{
static class SoftFloat
{
static SoftFloat()
{
RecipEstimateTable = BuildRecipEstimateTable();
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
}
public static readonly byte[] RecipEstimateTable;
public static readonly byte[] RecipSqrtEstimateTable;
private static byte[] BuildRecipEstimateTable()
{
byte[] tbl = new byte[256];
for (int idx = 0; idx < 256; idx++)
{
uint src = (uint)idx + 256u;
Debug.Assert(src is >= 256u and < 512u);
src = (src << 1) + 1u;
uint aux = (1u << 19) / src;
uint dst = (aux + 1u) >> 1;
Debug.Assert(dst is >= 256u and < 512u);
tbl[idx] = (byte)(dst - 256u);
}
return tbl;
}
private static byte[] BuildRecipSqrtEstimateTable()
{
byte[] tbl = new byte[384];
for (int idx = 0; idx < 384; idx++)
{
uint src = (uint)idx + 128u;
Debug.Assert(src is >= 128u and < 512u);
if (src < 256u)
{
src = (src << 1) + 1u;
}
else
{
src = (src >> 1) << 1;
src = (src + 1u) << 1;
}
uint aux = 512u;
while (src * (aux + 1u) * (aux + 1u) < (1u << 28))
{
aux++;
}
uint dst = (aux + 1u) >> 1;
Debug.Assert(dst is >= 256u and < 512u);
tbl[idx] = (byte)(dst - 256u);
}
return tbl;
}
public static void FPProcessException(FPException exc, ExecutionContext context)
{
FPProcessException(exc, context, context.Fpcr);
}
public static void FPProcessException(FPException exc, ExecutionContext context, FPCR fpcr)
{
int enable = (int)exc + 8;
if ((fpcr & (FPCR)(1 << enable)) != 0)
{
throw new NotImplementedException("Floating-point trap handling.");
}
else
{
context.Fpsr |= (FPSR)(1 << (int)exc);
}
}
extension(FPCR fpcr)
{
public FPRoundingMode RoundingMode
{
get
{
const int RModeShift = 22;
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
}
}
}
}
}

View File

@@ -1,212 +0,0 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Instructions
{
static class SoftFloat16
{
public static ushort FPDefaultNaN()
{
return (ushort)0x7E00u;
}
public static ushort FPInfinity(bool sign)
{
return sign ? (ushort)0xFC00u : (ushort)0x7C00u;
}
public static ushort FPZero(bool sign)
{
return sign ? (ushort)0x8000u : (ushort)0x0000u;
}
public static ushort FPMaxNormal(bool sign)
{
return sign ? (ushort)0xFBFFu : (ushort)0x7BFFu;
}
public static double FPUnpackCv(
this ushort valueBits,
out FPType type,
out bool sign,
ExecutionContext context)
{
sign = (~(uint)valueBits & 0x8000u) == 0u;
uint exp16 = ((uint)valueBits & 0x7C00u) >> 10;
uint frac16 = (uint)valueBits & 0x03FFu;
double real;
if (exp16 == 0u)
{
if (frac16 == 0u)
{
type = FPType.Zero;
real = 0d;
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -14) * ((double)frac16 * Math.Pow(2d, -10));
}
}
else if (exp16 == 0x1Fu && (context.Fpcr & FPCR.Ahp) == 0)
{
if (frac16 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000);
}
else
{
type = (~frac16 & 0x0200u) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp16 - 15) * (1d + (double)frac16 * Math.Pow(2d, -10));
}
return sign ? -real : real;
}
public static ushort FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -14;
const int E = 5;
const int F = 10;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1u << F)
{
biasedExp = 1u;
}
if (intMant == 1u << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
ushort resultBits;
if ((context.Fpcr & FPCR.Ahp) == 0)
{
if (biasedExp >= (1u << E) - 1u)
{
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
}
}
else
{
if (biasedExp >= 1u << E)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
error = 0d;
}
else
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
}
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return resultBits;
}
}
}

View File

@@ -1,182 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat16_32
{
[UnmanagedCallersOnly]
public static float FPConvert(ushort valueBits)
{
ExecutionContext context = NativeInterface.GetContext();
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
float result;
if (type is FPType.SNaN or FPType.QNaN)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat32.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat32.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat32.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
}
return result;
}
private static float FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -126;
const int E = 8;
const int F = 23;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{
context.Fpsr |= FPSR.Ufc;
return SoftFloat32.FPZero(sign);
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1u << F)
{
biasedExp = 1u;
}
if (intMant == 1u << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
float result;
if (biasedExp >= (1u << E) - 1u)
{
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
result = BitConverter.Int32BitsToSingle(
(int)((sign ? 1u : 0u) << 31 | (biasedExp & 0xFFu) << 23 | (intMant & 0x007FFFFFu)));
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return result;
}
private static float FPConvertNaN(ushort valueBits)
{
return BitConverter.Int32BitsToSingle(
(int)(((uint)valueBits & 0x8000u) << 16 | 0x7FC00000u | ((uint)valueBits & 0x01FFu) << 13));
}
}
}

View File

@@ -1,182 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat16_64
{
[UnmanagedCallersOnly]
public static double FPConvert(ushort valueBits)
{
ExecutionContext context = NativeInterface.GetContext();
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
double result;
if (type is FPType.SNaN or FPType.QNaN)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat64.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat64.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat64.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
}
return result;
}
private static double FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -1022;
const int E = 11;
const int F = 52;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{
context.Fpsr |= FPSR.Ufc;
return SoftFloat64.FPZero(sign);
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1ul << F)
{
biasedExp = 1u;
}
if (intMant == 1ul << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
double result;
if (biasedExp >= (1u << E) - 1u)
{
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
result = BitConverter.Int64BitsToDouble(
(long)((sign ? 1ul : 0ul) << 63 | (biasedExp & 0x7FFul) << 52 | (intMant & 0x000FFFFFFFFFFFFFul)));
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return result;
}
private static double FPConvertNaN(ushort valueBits)
{
return BitConverter.Int64BitsToDouble(
(long)(((ulong)valueBits & 0x8000ul) << 48 | 0x7FF8000000000000ul | ((ulong)valueBits & 0x01FFul) << 42));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,126 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat32_16
{
[UnmanagedCallersOnly]
public static ushort FPConvert(float value)
{
ExecutionContext context = NativeInterface.GetContext();
double real = value.FPUnpackCv(out FPType type, out bool sign, out uint valueBits, context);
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
ushort resultBits;
if (type is FPType.SNaN or FPType.QNaN)
{
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
}
return resultBits;
}
private static double FPUnpackCv(
this float value,
out FPType type,
out bool sign,
out uint valueBits,
ExecutionContext context)
{
valueBits = (uint)BitConverter.SingleToInt32Bits(value);
sign = (~valueBits & 0x80000000u) == 0u;
uint exp32 = (valueBits & 0x7F800000u) >> 23;
uint frac32 = valueBits & 0x007FFFFFu;
double real;
if (exp32 == 0u)
{
if (frac32 == 0u || (context.Fpcr & FPCR.Fz) != 0)
{
type = FPType.Zero;
real = 0d;
if (frac32 != 0u)
{
SoftFloat.FPProcessException(FPException.InputDenorm, context);
}
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -126) * ((double)frac32 * Math.Pow(2d, -23));
}
}
else if (exp32 == 0xFFu)
{
if (frac32 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000);
}
else
{
type = (~frac32 & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp32 - 127) * (1d + (double)frac32 * Math.Pow(2d, -23));
}
return sign ? -real : real;
}
private static ushort FPConvertNaN(uint valueBits)
{
return (ushort)((valueBits & 0x80000000u) >> 16 | 0x7E00u | (valueBits & 0x003FE000u) >> 13);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,127 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat64_16
{
[UnmanagedCallersOnly]
public static ushort FPConvert(double value)
{
ExecutionContext context = NativeInterface.GetContext();
double real = value.FPUnpackCv(out FPType type, out bool sign, out ulong valueBits, context);
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
ushort resultBits;
if (type is FPType.SNaN or FPType.QNaN)
{
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
}
return resultBits;
}
private static double FPUnpackCv(
this double value,
out FPType type,
out bool sign,
out ulong valueBits,
ExecutionContext context)
{
valueBits = (ulong)BitConverter.DoubleToInt64Bits(value);
sign = (~valueBits & 0x8000000000000000ul) == 0u;
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
double real;
if (exp64 == 0u)
{
if (frac64 == 0u || (context.Fpcr & FPCR.Fz) != 0)
{
type = FPType.Zero;
real = 0d;
if (frac64 != 0u)
{
SoftFloat.FPProcessException(FPException.InputDenorm, context);
}
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -1022) * ((double)frac64 * Math.Pow(2d, -52));
}
}
else if (exp64 == 0x7FFul)
{
if (frac64 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000000);
}
else
{
type = (~frac64 & 0x0008000000000000ul) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp64 - 1023) * (1d + (double)frac64 * Math.Pow(2d, -52));
}
return sign ? -real : real;
}
private static ushort FPConvertNaN(ulong valueBits)
{
return (ushort)((valueBits & 0x8000000000000000ul) >> 48 | 0x7E00u |
(valueBits & 0x0007FC0000000000ul) >> 42);
}
}
}

View File

@@ -16,9 +16,9 @@ namespace ARMeilleure.IntermediateRepresentation
static class ComparisonExtensions
{
extension(Comparison comparison)
public static Comparison Invert(this Comparison comp)
{
public Comparison Inverse => (Comparison)((int)comparison ^ 1);
return (Comparison)((int)comp ^ 1);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.IntermediateRepresentation
{

View File

@@ -14,38 +14,48 @@ namespace ARMeilleure.IntermediateRepresentation
static class OperandTypeExtensions
{
extension(OperandType type)
public static bool IsInteger(this OperandType type)
{
public bool IsInteger => type is OperandType.I32 or OperandType.I64;
public RegisterType Register => type switch
return type is OperandType.I32 or
OperandType.I64;
}
public static RegisterType ToRegisterType(this OperandType type)
{
return type switch
{
OperandType.FP32 => RegisterType.Vector,
OperandType.FP64 => RegisterType.Vector,
OperandType.I32 => RegisterType.Integer,
OperandType.I64 => RegisterType.Integer,
OperandType.V128 => RegisterType.Vector,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
};
public int ByteSize => type switch
}
public static int GetSizeInBytes(this OperandType type)
{
return type switch
{
OperandType.FP32 => 4,
OperandType.FP64 => 8,
OperandType.I32 => 4,
OperandType.I64 => 8,
OperandType.V128 => 16,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
};
public int ByteSizeLog2 => type switch
}
public static int GetSizeInBytesLog2(this OperandType type)
{
return type switch
{
OperandType.FP32 => 2,
OperandType.FP64 => 3,
OperandType.I32 => 2,
OperandType.I64 => 3,
OperandType.V128 => 4,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
};
}
}

View File

@@ -45,12 +45,19 @@ namespace ARMeilleure.Memory
public static class MemoryManagerTypeExtensions
{
extension(MemoryManagerType type)
public static bool IsHostMapped(this MemoryManagerType type)
{
public bool IsHostMapped => type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
public bool IsHostTracked => type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
public bool IsHostMappedOrTracked => type.IsHostMapped || type.IsHostTracked;
return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
}
public static bool IsHostTracked(this MemoryManagerType type)
{
return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
}
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
{
return type.IsHostMapped() || type.IsHostTracked();
}
}
}

View File

@@ -12,8 +12,6 @@ namespace ARMeilleure
public static bool AllowLcqInFunctionTable { get; set; } = true;
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
public static bool EnableDebugging { get; set; } = false;
public static bool EnableDeepCallRecursionProtection { get; set; } = true;
public static bool UseAdvSimdIfAvailable { get; set; } = true;
public static bool UseArm64AesIfAvailable { get; set; } = true;

View File

@@ -1,5 +1,4 @@
using ARMeilleure.Memory;
using System.Threading;
namespace ARMeilleure.State
{
@@ -11,7 +10,7 @@ namespace ARMeilleure.State
internal nint NativeContextPtr => _nativeContext.BasePtr;
internal bool Interrupted { get; private set; }
private bool _interrupted;
private readonly ICounter _counter;
@@ -66,8 +65,6 @@ namespace ARMeilleure.State
public bool IsAarch32 { get; set; }
public ulong ThreadUid { get; set; }
internal ExecutionMode ExecutionMode
{
get
@@ -93,19 +90,14 @@ namespace ARMeilleure.State
private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback;
private readonly ExceptionCallbackNoArgs _stepCallback;
private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback;
internal int ShouldStep;
public ulong DebugPc { get; set; }
public ExecutionContext(
IJitMemoryAllocator allocator,
ICounter counter,
ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null,
ExceptionCallbackNoArgs stepCallback = null,
ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null)
{
@@ -113,7 +105,6 @@ namespace ARMeilleure.State
_counter = counter;
_interruptCallback = interruptCallback;
_breakCallback = breakCallback;
_stepCallback = stepCallback;
_supervisorCallback = supervisorCallback;
_undefinedCallback = undefinedCallback;
@@ -134,16 +125,11 @@ namespace ARMeilleure.State
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
internal void ResetCallDepth()
{
_nativeContext.ResetCallDepth();
}
internal void CheckInterrupt()
{
if (Interrupted)
if (_interrupted)
{
Interrupted = false;
_interrupted = false;
_interruptCallback?.Invoke(this);
}
@@ -153,37 +139,16 @@ namespace ARMeilleure.State
public void RequestInterrupt()
{
Interrupted = true;
}
public void StepHandler()
{
_stepCallback?.Invoke(this);
}
public void RequestDebugStep()
{
Interlocked.Exchange(ref ShouldStep, 1);
RequestInterrupt();
_interrupted = true;
}
internal void OnBreak(ulong address, int imm)
{
if (Optimizations.EnableDebugging)
{
DebugPc = Pc;
}
_breakCallback?.Invoke(this, address, imm);
}
internal void OnSupervisorCall(ulong address, int imm)
{
if (Optimizations.EnableDebugging)
{
DebugPc = Pc;
}
_supervisorCallback?.Invoke(this, address, imm);
}

View File

@@ -22,13 +22,6 @@ namespace ARMeilleure.State
public ulong ExclusiveValueHigh;
public int Running;
public long Tpidr2El0;
public int CallDepth;
/// <summary>
/// Precise PC value used for debugging.
/// This will only be set when Optimizations.EnableDebugging is true.
/// </summary>
public ulong DebugPrecisePc;
}
private static NativeCtxStorage _dummyStorage = new();
@@ -46,11 +39,6 @@ namespace ARMeilleure.State
public ulong GetPc()
{
if (Optimizations.EnableDebugging)
{
return GetStorage().DebugPrecisePc;
}
// TODO: More precise tracking of PC value.
return GetStorage().DispatchAddress;
}
@@ -200,8 +188,6 @@ namespace ARMeilleure.State
public bool GetRunning() => GetStorage().Running != 0;
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
public void ResetCallDepth() => GetStorage().CallDepth = 0;
public unsafe static int GetRegisterOffset(Register reg)
{
if (reg.Type == RegisterType.Integer)
@@ -282,16 +268,6 @@ namespace ARMeilleure.State
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
}
public static int GetDebugPrecisePcOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
}
public static int GetCallDepthOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth);
}
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
{
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);

View File

@@ -52,7 +52,6 @@ namespace ARMeilleure.Translation
public bool HighCq { get; }
public bool HasPtc { get; }
public Aarch32Mode Mode { get; }
public bool IsSingleStep { get; }
private int _ifThenBlockStateIndex = 0;
private Condition[] _ifThenBlockState = [];
@@ -67,8 +66,7 @@ namespace ARMeilleure.Translation
ulong entryAddress,
bool highCq,
bool hasPtc,
Aarch32Mode mode,
bool isSingleStep)
Aarch32Mode mode)
{
Memory = memory;
CountTable = countTable;
@@ -78,7 +76,6 @@ namespace ARMeilleure.Translation
HighCq = highCq;
HasPtc = hasPtc;
Mode = mode;
IsSingleStep = isSingleStep;
_labels = new Dictionary<ulong, Operand>();
}

View File

@@ -361,7 +361,10 @@ namespace ARMeilleure.Translation
IntervalTreeNode<TK, TV> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
tmp?.Parent = ParentOf(replacementNode);
if (tmp != null)
{
tmp.Parent = ParentOf(replacementNode);
}
if (ParentOf(replacementNode) == null)
{
@@ -579,7 +582,10 @@ namespace ARMeilleure.Translation
{
IntervalTreeNode<TK, TV> right = RightOf(node);
node.Right = LeftOf(right);
node.Right?.Parent = node;
if (node.Right != null)
{
node.Right.Parent = node;
}
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
right.Parent = nodeParent;
@@ -609,7 +615,10 @@ namespace ARMeilleure.Translation
{
IntervalTreeNode<TK, TV> left = LeftOf(node);
node.Left = RightOf(left);
node.Left?.Parent = node;
if (node.Left != null)
{
node.Left.Parent = node;
}
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
left.Parent = nodeParent;
@@ -658,7 +667,10 @@ namespace ARMeilleure.Translation
/// <param name="color">Color (Boolean)</param>
private static void SetColor(IntervalTreeNode<TK, TV> node, bool color)
{
node?.Color = color;
if (node != null)
{
node.Color = color;
}
}
/// <summary>

View File

@@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@@ -303,13 +303,6 @@ namespace ARMeilleure.Translation.PTC
return false;
}
if (outerHeader.DebuggerMode != Optimizations.EnableDebugging)
{
InvalidateCompressedStream(compressedStream);
return false;
}
nint intPtr = nint.Zero;
try
@@ -486,7 +479,6 @@ namespace ARMeilleure.Translation.PTC
MemoryManagerMode = GetMemoryManagerMode(),
OSPlatform = GetOSPlatform(),
Architecture = (uint)RuntimeInformation.ProcessArchitecture,
DebuggerMode = Optimizations.EnableDebugging,
UncompressedStreamSize =
(long)Unsafe.SizeOf<InnerHeader>() +
@@ -1076,7 +1068,7 @@ namespace ARMeilleure.Translation.PTC
return osPlatform;
}
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 87*/)]
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)]
private struct OuterHeader
{
public ulong Magic;
@@ -1088,7 +1080,6 @@ namespace ARMeilleure.Translation.PTC
public byte MemoryManagerMode;
public uint OSPlatform;
public uint Architecture;
public bool DebuggerMode;
public long UncompressedStreamSize;

View File

@@ -119,25 +119,7 @@ namespace ARMeilleure.Translation
NativeInterface.RegisterThread(context, Memory, this);
if (Optimizations.EnableDebugging)
{
context.DebugPc = address;
do
{
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
{
context.DebugPc = Step(context, context.DebugPc);
context.StepHandler();
}
else
{
context.DebugPc = ExecuteSingle(context, context.DebugPc);
}
context.CheckInterrupt();
}
while (context.Running && context.DebugPc != 0);
}
else if (Optimizations.UseUnmanagedDispatchLoop)
if (Optimizations.UseUnmanagedDispatchLoop)
{
Stubs.DispatchLoop(context.NativeContextPtr, address);
}
@@ -186,7 +168,6 @@ namespace ARMeilleure.Translation
Statistics.StartTimer();
context.ResetCallDepth();
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
Statistics.StopTimer(address);
@@ -194,7 +175,7 @@ namespace ARMeilleure.Translation
return nextAddr;
}
private ulong Step(State.ExecutionContext context, ulong address)
public ulong Step(State.ExecutionContext context, ulong address)
{
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
@@ -205,8 +186,6 @@ namespace ARMeilleure.Translation
return address;
}
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{
if (!Functions.TryGetValue(address, out TranslatedFunction func))
@@ -250,8 +229,7 @@ namespace ARMeilleure.Translation
address,
highCq,
_ptc.State != PtcState.Disabled,
mode: Aarch32Mode.User,
isSingleStep: singleStep);
mode: Aarch32Mode.User);
Logger.StartPass(PassName.Decoding);
@@ -261,7 +239,6 @@ namespace ARMeilleure.Translation
Logger.StartPass(PassName.Translation);
InstEmitFlowHelper.EmitCallDepthCheckAndIncrement(context, Const(address));
EmitSynchronization(context);
if (blocks[0].Address != address)
@@ -390,13 +367,9 @@ namespace ARMeilleure.Translation
if (block.Exit)
{
// Return to managed rather than tail call.
bool useReturns = Optimizations.EnableDebugging;
if (Optimizations.EnableDebugging)
{
EmitDebugPrecisePcUpdate(context, block.Address);
}
// Left option here as it may be useful if we need to return to managed rather than tail call in
// future. (eg. for debug)
bool useReturns = false;
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
}
@@ -414,31 +387,26 @@ namespace ARMeilleure.Translation
{
context.SyncQcFlag();
if (block.Branch is { Exit: false } && block.Branch.Address <= block.Address)
if (block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
{
EmitSynchronization(context);
}
}
if (Optimizations.EnableDebugging)
{
EmitDebugPrecisePcUpdate(context, opCode.Address);
}
Operand lblPredicateSkip = default;
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
{
lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Inverse);
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert());
}
if (opCode is OpCode32 { Cond: < Condition.Al } op)
if (opCode is OpCode32 op && op.Cond < Condition.Al)
{
lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Inverse);
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert());
}
if (opCode.Instruction.Emitter != null)
@@ -521,14 +489,6 @@ namespace ARMeilleure.Translation
context.MarkLabel(lblExit);
}
internal static void EmitDebugPrecisePcUpdate(EmitterContext context, ulong address)
{
long debugPrecisePcOffs = NativeContext.GetDebugPrecisePcOffset();
Operand debugPrecisePcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(debugPrecisePcOffs));
context.Store(debugPrecisePcAddr, Const(address));
}
public void InvalidateJitCacheRegion(ulong address, ulong size)
{
ulong[] overlapAddresses = [];

View File

@@ -262,18 +262,10 @@ namespace ARMeilleure.Translation
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
Operand callDepthAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
EmitSyncFpContext(context, nativeContext, true);
context.MarkLabel(beginLbl);
if (Optimizations.EnableDeepCallRecursionProtection)
{
// Reset the call depth counter, since this is our first guest function call.
context.Store(callDepthAddress, Const(0));
}
context.Store(dispatchAddress, guestAddress);
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
context.BranchIfFalse(endLbl, guestAddress);

View File

@@ -1,16 +0,0 @@
namespace Ryujinx.Audio.Backends.Apple
{
class AppleAudioBuffer
{
public readonly ulong DriverIdentifier;
public readonly ulong SampleCount;
public ulong SamplePlayed;
public AppleAudioBuffer(ulong driverIdentifier, ulong sampleCount)
{
DriverIdentifier = driverIdentifier;
SampleCount = sampleCount;
SamplePlayed = 0;
}
}
}

View File

@@ -1,196 +0,0 @@
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Common.Logging;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.Versioning;
using Ryujinx.Audio.Backends.Apple.Native;
using static Ryujinx.Audio.Backends.Apple.Native.AudioToolbox;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
namespace Ryujinx.Audio.Backends.Apple
{
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("ios")]
public sealed class AppleHardwareDeviceDriver : IHardwareDeviceDriver
{
private readonly ManualResetEvent _updateRequiredEvent;
private readonly ManualResetEvent _pauseEvent;
private readonly ConcurrentDictionary<AppleHardwareDeviceSession, byte> _sessions;
private readonly bool _supportSurroundConfiguration;
public float Volume { get; set; }
public AppleHardwareDeviceDriver()
{
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
_sessions = new ConcurrentDictionary<AppleHardwareDeviceSession, byte>();
_supportSurroundConfiguration = TestSurroundSupport();
Volume = 1f;
}
private bool TestSurroundSupport()
{
try
{
AudioStreamBasicDescription format =
GetAudioFormat(SampleFormat.PcmFloat, Constants.TargetSampleRate, 6);
int result = AudioQueueNewOutput(
ref format,
nint.Zero,
nint.Zero,
nint.Zero,
nint.Zero,
0,
out nint testQueue);
if (result == 0)
{
AudioChannelLayout layout = new AudioChannelLayout
{
AudioChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A,
AudioChannelBitmap = 0,
NumberChannelDescriptions = 0
};
int layoutResult = AudioQueueSetProperty(
testQueue,
kAudioQueueProperty_ChannelLayout,
ref layout,
(uint)Marshal.SizeOf<AudioChannelLayout>());
if (layoutResult == 0)
{
AudioQueueDispose(testQueue, true);
return true;
}
AudioQueueDispose(testQueue, true);
}
return false;
}
catch
{
return false;
}
}
public static bool IsSupported => OperatingSystem.IsMacOSVersionAtLeast(10, 5);
public ManualResetEvent GetUpdateRequiredEvent()
=> _updateRequiredEvent;
public ManualResetEvent GetPauseEvent()
=> _pauseEvent;
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager,
SampleFormat sampleFormat, uint sampleRate, uint channelCount)
{
if (channelCount == 0)
{
channelCount = 2;
}
if (sampleRate == 0)
{
sampleRate = Constants.TargetSampleRate;
}
if (direction != Direction.Output)
{
throw new NotImplementedException("Input direction is currently not implemented on Apple backend!");
}
AppleHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
_sessions.TryAdd(session, 0);
return session;
}
internal bool Unregister(AppleHardwareDeviceSession session)
=> _sessions.TryRemove(session, out _);
internal static AudioStreamBasicDescription GetAudioFormat(SampleFormat sampleFormat, uint sampleRate,
uint channelCount)
{
uint formatFlags;
uint bitsPerChannel;
switch (sampleFormat)
{
case SampleFormat.PcmInt8:
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
bitsPerChannel = 8;
break;
case SampleFormat.PcmInt16:
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
bitsPerChannel = 16;
break;
case SampleFormat.PcmInt32:
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
bitsPerChannel = 32;
break;
case SampleFormat.PcmFloat:
formatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
bitsPerChannel = 32;
break;
default:
throw new ArgumentException($"Unsupported sample format {sampleFormat}");
}
uint bytesPerFrame = (bitsPerChannel / 8) * channelCount;
return new AudioStreamBasicDescription
{
SampleRate = sampleRate,
FormatID = kAudioFormatLinearPCM,
FormatFlags = formatFlags,
BytesPerPacket = bytesPerFrame,
FramesPerPacket = 1,
BytesPerFrame = bytesPerFrame,
ChannelsPerFrame = channelCount,
BitsPerChannel = bitsPerChannel,
Reserved = 0
};
}
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
private void Dispose(bool disposing)
{
if (disposing)
{
foreach (AppleHardwareDeviceSession session in _sessions.Keys)
{
session.Dispose();
}
_pauseEvent.Dispose();
}
}
public bool SupportsDirection(Direction direction)
=> direction != Direction.Input;
public bool SupportsSampleRate(uint sampleRate) => true;
public bool SupportsSampleFormat(SampleFormat sampleFormat)
=> sampleFormat != SampleFormat.PcmInt24;
public bool SupportsChannelCount(uint channelCount)
=> channelCount != 6 || _supportSurroundConfiguration;
}
}

View File

@@ -1,285 +0,0 @@
using Ryujinx.Audio.Backends.Common;
using Ryujinx.Audio.Common;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.Versioning;
using static Ryujinx.Audio.Backends.Apple.Native.AudioToolbox;
namespace Ryujinx.Audio.Backends.Apple
{
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("ios")]
class AppleHardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private const int NumBuffers = 3;
private readonly AppleHardwareDeviceDriver _driver;
private readonly ConcurrentQueue<AppleAudioBuffer> _queuedBuffers = new();
private readonly DynamicRingBuffer _ringBuffer = new();
private readonly ManualResetEvent _updateRequiredEvent;
private readonly AudioQueueOutputCallback _callbackDelegate;
private readonly GCHandle _gcHandle;
private nint _audioQueue;
private readonly nint[] _audioQueueBuffers = new nint[NumBuffers];
private readonly int[] _bufferBytesFilled = new int[NumBuffers];
private readonly int _bytesPerFrame;
private ulong _playedSampleCount;
private bool _started;
private float _volume = 1f;
private readonly object _lock = new();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void AudioQueueOutputCallback(
nint userData,
nint audioQueue,
nint buffer);
public AppleHardwareDeviceSession(
AppleHardwareDeviceDriver driver,
IVirtualMemoryManager memoryManager,
SampleFormat requestedSampleFormat,
uint requestedSampleRate,
uint requestedChannelCount)
: base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{
_driver = driver;
_updateRequiredEvent = driver.GetUpdateRequiredEvent();
_callbackDelegate = OutputCallback;
_bytesPerFrame = BackendHelper.GetSampleSize(requestedSampleFormat) * (int)requestedChannelCount;
_gcHandle = GCHandle.Alloc(this, GCHandleType.Normal);
SetupAudioQueue();
}
private void SetupAudioQueue()
{
lock (_lock)
{
AudioStreamBasicDescription format = AppleHardwareDeviceDriver.GetAudioFormat(
RequestedSampleFormat,
RequestedSampleRate,
RequestedChannelCount);
nint callbackPtr = Marshal.GetFunctionPointerForDelegate(_callbackDelegate);
nint userData = GCHandle.ToIntPtr(_gcHandle);
int result = AudioQueueNewOutput(
ref format,
callbackPtr,
userData,
nint.Zero,
nint.Zero,
0,
out _audioQueue);
if (result != 0)
{
throw new InvalidOperationException($"AudioQueueNewOutput failed: {result}");
}
uint framesPerBuffer = RequestedSampleRate / 100;
uint bufferSize = framesPerBuffer * (uint)_bytesPerFrame;
for (int i = 0; i < NumBuffers; i++)
{
AudioQueueAllocateBuffer(_audioQueue, bufferSize, out _audioQueueBuffers[i]);
_bufferBytesFilled[i] = 0;
PrimeBuffer(_audioQueueBuffers[i], i);
}
}
}
private unsafe void PrimeBuffer(nint bufferPtr, int bufferIndex)
{
AudioQueueBuffer* buffer = (AudioQueueBuffer*)bufferPtr;
int capacityBytes = (int)buffer->AudioDataBytesCapacity;
int framesPerBuffer = capacityBytes / _bytesPerFrame;
int availableFrames = _ringBuffer.Length / _bytesPerFrame;
int framesToRead = Math.Min(availableFrames, framesPerBuffer);
int bytesToRead = framesToRead * _bytesPerFrame;
Span<byte> dst = new((void*)buffer->AudioData, capacityBytes);
dst.Clear();
if (bytesToRead > 0)
{
Span<byte> audio = dst.Slice(0, bytesToRead);
_ringBuffer.Read(audio, 0, bytesToRead);
ApplyVolume(buffer->AudioData, bytesToRead);
}
buffer->AudioDataByteSize = (uint)capacityBytes;
_bufferBytesFilled[bufferIndex] = bytesToRead;
AudioQueueEnqueueBuffer(_audioQueue, bufferPtr, 0, nint.Zero);
}
private void OutputCallback(nint userData, nint audioQueue, nint bufferPtr)
{
if (!_started || bufferPtr == nint.Zero)
return;
int bufferIndex = Array.IndexOf(_audioQueueBuffers, bufferPtr);
if (bufferIndex < 0)
return;
int bytesPlayed = _bufferBytesFilled[bufferIndex];
if (bytesPlayed > 0)
{
ProcessPlayedSamples(bytesPlayed);
}
PrimeBuffer(bufferPtr, bufferIndex);
}
private void ProcessPlayedSamples(int bytesPlayed)
{
ulong samplesPlayed = GetSampleCount(bytesPlayed);
ulong remaining = samplesPlayed;
bool needUpdate = false;
while (remaining > 0 && _queuedBuffers.TryPeek(out AppleAudioBuffer buffer))
{
ulong needed = buffer.SampleCount - Interlocked.Read(ref buffer.SamplePlayed);
ulong take = Math.Min(needed, remaining);
ulong played = Interlocked.Add(ref buffer.SamplePlayed, take);
remaining -= take;
if (played == buffer.SampleCount)
{
_queuedBuffers.TryDequeue(out _);
needUpdate = true;
}
Interlocked.Add(ref _playedSampleCount, take);
}
if (needUpdate)
{
_updateRequiredEvent.Set();
}
}
private unsafe void ApplyVolume(nint dataPtr, int byteSize)
{
float volume = Math.Clamp(_volume * _driver.Volume, 0f, 1f);
if (volume >= 0.999f)
return;
int sampleCount = byteSize / BackendHelper.GetSampleSize(RequestedSampleFormat);
switch (RequestedSampleFormat)
{
case SampleFormat.PcmInt16:
short* s16 = (short*)dataPtr;
for (int i = 0; i < sampleCount; i++)
s16[i] = (short)(s16[i] * volume);
break;
case SampleFormat.PcmFloat:
float* f32 = (float*)dataPtr;
for (int i = 0; i < sampleCount; i++)
f32[i] *= volume;
break;
case SampleFormat.PcmInt32:
int* s32 = (int*)dataPtr;
for (int i = 0; i < sampleCount; i++)
s32[i] = (int)(s32[i] * volume);
break;
case SampleFormat.PcmInt8:
sbyte* s8 = (sbyte*)dataPtr;
for (int i = 0; i < sampleCount; i++)
s8[i] = (sbyte)(s8[i] * volume);
break;
}
}
public override void QueueBuffer(AudioBuffer buffer)
{
_ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
_queuedBuffers.Enqueue(new AppleAudioBuffer(buffer.DataPointer, GetSampleCount(buffer)));
}
public override void Start()
{
lock (_lock)
{
if (_started)
return;
_started = true;
AudioQueueStart(_audioQueue, nint.Zero);
}
}
public override void Stop()
{
lock (_lock)
{
if (!_started)
return;
_started = false;
AudioQueuePause(_audioQueue);
}
}
public override ulong GetPlayedSampleCount()
=> Interlocked.Read(ref _playedSampleCount);
public override float GetVolume() => _volume;
public override void SetVolume(float volume) => _volume = volume;
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{
if (!_queuedBuffers.TryPeek(out AppleAudioBuffer driverBuffer))
return true;
return driverBuffer.DriverIdentifier != buffer.DataPointer;
}
public override void PrepareToClose() { }
public override void UnregisterBuffer(AudioBuffer buffer) { }
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Stop();
if (_audioQueue != nint.Zero)
{
AudioQueueStop(_audioQueue, true);
AudioQueueDispose(_audioQueue, true);
_audioQueue = nint.Zero;
}
if (_gcHandle.IsAllocated)
{
_gcHandle.Free();
}
}
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@@ -1,102 +0,0 @@
using System.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
namespace Ryujinx.Audio.Backends.Apple.Native
{
public static partial class AudioToolbox
{
[StructLayout(LayoutKind.Sequential)]
internal struct AudioStreamBasicDescription
{
public double SampleRate;
public uint FormatID;
public uint FormatFlags;
public uint BytesPerPacket;
public uint FramesPerPacket;
public uint BytesPerFrame;
public uint ChannelsPerFrame;
public uint BitsPerChannel;
public uint Reserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct AudioChannelLayout
{
public uint AudioChannelLayoutTag;
public uint AudioChannelBitmap;
public uint NumberChannelDescriptions;
}
internal const uint kAudioFormatLinearPCM = 0x6C70636D;
internal const uint kAudioQueueProperty_ChannelLayout = 0x6171636c;
internal const uint kAudioChannelLayoutTag_MPEG_5_1_A = 0x650006;
internal const uint kAudioFormatFlagIsFloat = (1 << 0);
internal const uint kAudioFormatFlagIsSignedInteger = (1 << 2);
internal const uint kAudioFormatFlagIsPacked = (1 << 3);
internal const uint kAudioFormatFlagIsBigEndian = (1 << 1);
internal const uint kAudioFormatFlagIsAlignedHigh = (1 << 4);
internal const uint kAudioFormatFlagIsNonInterleaved = (1 << 5);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueNewOutput(
ref AudioStreamBasicDescription format,
nint callback,
nint userData,
nint callbackRunLoop,
nint callbackRunLoopMode,
uint flags,
out nint audioQueue);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueSetProperty(
nint audioQueue,
uint propertyID,
ref AudioChannelLayout layout,
uint layoutSize);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueDispose(nint audioQueue, [MarshalAs(UnmanagedType.I1)] bool immediate);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueAllocateBuffer(
nint audioQueue,
uint bufferByteSize,
out nint buffer);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueStart(nint audioQueue, nint startTime);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueuePause(nint audioQueue);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueStop(nint audioQueue, [MarshalAs(UnmanagedType.I1)] bool immediate);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueSetParameter(
nint audioQueue,
uint parameterID,
float value);
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
internal static partial int AudioQueueEnqueueBuffer(
nint audioQueue,
nint buffer,
uint numPacketDescs,
nint packetDescs);
[StructLayout(LayoutKind.Sequential)]
internal struct AudioQueueBuffer
{
public uint AudioDataBytesCapacity;
public nint AudioData;
public uint AudioDataByteSize;
public nint UserData;
public uint PacketDescriptionCapacity;
public nint PacketDescriptions;
public uint PacketDescriptionCount;
}
internal const uint kAudioQueueParam_Volume = 1;
}
}

View File

@@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
</ItemGroup>
</Project>

View File

@@ -10,8 +10,7 @@ using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
namespace Ryujinx.Audio.Backends.OpenAL
{
// ReSharper disable once InconsistentNaming
public sealed class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
public class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
{
private readonly ALDevice _device;
private readonly ALContext _context;
@@ -149,7 +148,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
Dispose(true);
}
private void Dispose(bool disposing)
protected virtual void Dispose(bool disposing)
{
if (disposing)
{

View File

@@ -9,8 +9,7 @@ using System.Threading;
namespace Ryujinx.Audio.Backends.OpenAL
{
// ReSharper disable once InconsistentNaming
sealed class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private readonly OpenALHardwareDeviceDriver _driver;
private readonly int _sourceId;
@@ -191,7 +190,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
}
}
private void Dispose(bool disposing)
protected virtual void Dispose(bool disposing)
{
if (disposing && _driver.Unregister(this))
{

View File

@@ -7,7 +7,7 @@
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<ProjectReference Include="..\Ryujinx.SDL3.Common\Ryujinx.SDL3.Common.csproj" />
<ProjectReference Include="..\Ryujinx.SDL2.Common\Ryujinx.SDL2.Common.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,12 +1,12 @@
namespace Ryujinx.Audio.Backends.SDL3
namespace Ryujinx.Audio.Backends.SDL2
{
class SDL3AudioBuffer
class SDL2AudioBuffer
{
public readonly ulong DriverIdentifier;
public readonly ulong SampleCount;
public ulong SamplePlayed;
public SDL3AudioBuffer(ulong driverIdentifier, ulong sampleCount)
public SDL2AudioBuffer(ulong driverIdentifier, ulong sampleCount)
{
DriverIdentifier = driverIdentifier;
SampleCount = sampleCount;

View File

@@ -2,41 +2,42 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Common.Logging;
using Ryujinx.Memory;
using Ryujinx.SDL3.Common;
using Ryujinx.SDL2.Common;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
using SDL;
using static SDL.SDL3;
using System.Runtime.InteropServices;
using static SDL2.SDL;
namespace Ryujinx.Audio.Backends.SDL3
namespace Ryujinx.Audio.Backends.SDL2
{
using unsafe SDL_AudioStreamCallbackPointer = delegate* unmanaged[Cdecl]<nint, SDL_AudioStream*, int, int, void>;
public sealed class SDL3HardwareDeviceDriver : IHardwareDeviceDriver
public class SDL2HardwareDeviceDriver : IHardwareDeviceDriver
{
private readonly ManualResetEvent _updateRequiredEvent;
private readonly ManualResetEvent _pauseEvent;
private readonly ConcurrentDictionary<SDL3HardwareDeviceSession, byte> _sessions;
private readonly ConcurrentDictionary<SDL2HardwareDeviceSession, byte> _sessions;
private readonly bool _supportSurroundConfiguration;
public float Volume { get; set; }
public unsafe SDL3HardwareDeviceDriver()
// TODO: Add this to SDL2-CS
// NOTE: We use a DllImport here because of marshaling issue for spec.
[DllImport("SDL2")]
private static extern int SDL_GetDefaultAudioInfo(nint name, out SDL_AudioSpec spec, int isCapture);
public SDL2HardwareDeviceDriver()
{
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
_sessions = new ConcurrentDictionary<SDL3HardwareDeviceSession, byte>();
_sessions = new ConcurrentDictionary<SDL2HardwareDeviceSession, byte>();
SDL3Driver.Instance.Initialize();
SDL2Driver.Instance.Initialize();
SDL_AudioSpec spec;
if (!SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, null))
int res = SDL_GetDefaultAudioInfo(nint.Zero, out SDL_AudioSpec spec, 0);
if (res != 0)
{
Logger.Error?.Print(LogClass.Application,
$"SDL_GetDefaultAudioInfo failed with error \"{SDL_GetError()}\"");
@@ -53,16 +54,16 @@ namespace Ryujinx.Audio.Backends.SDL3
public static bool IsSupported => IsSupportedInternal();
private unsafe static bool IsSupportedInternal()
private static bool IsSupportedInternal()
{
SDL_AudioStream* device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, Constants.TargetSampleCount, null);
uint device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, Constants.TargetSampleCount, null);
if (device != null)
if (device != 0)
{
SDL_DestroyAudioStream(device);
SDL_CloseAudioDevice(device);
}
return device != null;
return device != 0;
}
public ManualResetEvent GetUpdateRequiredEvent()
@@ -89,68 +90,67 @@ namespace Ryujinx.Audio.Backends.SDL3
if (direction != Direction.Output)
{
throw new NotImplementedException("Input direction is currently not implemented on SDL3 backend!");
throw new NotImplementedException("Input direction is currently not implemented on SDL2 backend!");
}
SDL3HardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
SDL2HardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
_sessions.TryAdd(session, 0);
return session;
}
internal bool Unregister(SDL3HardwareDeviceSession session)
internal bool Unregister(SDL2HardwareDeviceSession session)
{
return _sessions.TryRemove(session, out _);
}
private static SDL_AudioSpec GetSDL3Spec(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount)
private static SDL_AudioSpec GetSDL2Spec(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount)
{
return new SDL_AudioSpec
{
channels = (byte)requestedChannelCount,
format = GetSDL3Format(requestedSampleFormat),
format = GetSDL2Format(requestedSampleFormat),
freq = (int)requestedSampleRate,
samples = (ushort)sampleCount,
};
}
internal static SDL_AudioFormat GetSDL3Format(SampleFormat format)
internal static ushort GetSDL2Format(SampleFormat format)
{
return format switch
{
SampleFormat.PcmInt8 => SDL_AudioFormat.SDL_AUDIO_S8,
SampleFormat.PcmInt16 => SDL_AudioFormat.SDL_AUDIO_S16LE,
SampleFormat.PcmInt32 => SDL_AudioFormat.SDL_AUDIO_S32LE,
SampleFormat.PcmFloat => SDL_AudioFormat.SDL_AUDIO_F32LE,
SampleFormat.PcmInt8 => AUDIO_S8,
SampleFormat.PcmInt16 => AUDIO_S16,
SampleFormat.PcmInt32 => AUDIO_S32,
SampleFormat.PcmFloat => AUDIO_F32,
_ => throw new ArgumentException($"Unsupported sample format {format}"),
};
}
internal unsafe static SDL_AudioStream* OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount, SDL3HardwareDeviceSession.SDL_AudioStreamCallback callback)
internal static uint OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount, SDL_AudioCallback callback)
{
SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount);
SDL_AudioSpec got = desired;
var pCallback = callback != null ? (SDL_AudioStreamCallbackPointer)Marshal.GetFunctionPointerForDelegate(callback) : null;
SDL_AudioSpec desired = GetSDL2Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount, sampleCount);
// From SDL 3 and on, SDL requires us to set this as a hint
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, $"{sampleCount}");
SDL_AudioStream* device = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &got, pCallback, 0);
desired.callback = callback;
if (device == null)
uint device = SDL_OpenAudioDevice(nint.Zero, 0, ref desired, out SDL_AudioSpec got, 0);
if (device == 0)
{
Logger.Error?.Print(LogClass.Application, $"SDL3 open audio device initialization failed with error \"{SDL_GetError()}\"");
Logger.Error?.Print(LogClass.Application, $"SDL2 open audio device initialization failed with error \"{SDL_GetError()}\"");
return null;
return 0;
}
bool isValid = got.format == desired.format && got.freq == desired.freq && got.channels == desired.channels;
if (!isValid)
{
Logger.Error?.Print(LogClass.Application, "SDL3 open audio device is not valid");
SDL_DestroyAudioStream(device);
Logger.Error?.Print(LogClass.Application, "SDL2 open audio device is not valid");
SDL_CloseAudioDevice(device);
return null;
return 0;
}
return device;
@@ -162,16 +162,16 @@ namespace Ryujinx.Audio.Backends.SDL3
Dispose(true);
}
private void Dispose(bool disposing)
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
foreach (SDL3HardwareDeviceSession session in _sessions.Keys)
foreach (SDL2HardwareDeviceSession session in _sessions.Keys)
{
session.Dispose();
}
SDL3Driver.Instance.Dispose();
SDL2Driver.Instance.Dispose();
_pauseEvent.Dispose();
}

View File

@@ -6,40 +6,36 @@ using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Threading;
using SDL;
using static SDL.SDL3;
using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Backends.SDL3
using static SDL2.SDL;
namespace Ryujinx.Audio.Backends.SDL2
{
sealed unsafe class SDL3HardwareDeviceSession : HardwareDeviceSessionOutputBase
class SDL2HardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private readonly SDL3HardwareDeviceDriver _driver;
private readonly ConcurrentQueue<SDL3AudioBuffer> _queuedBuffers;
private readonly SDL2HardwareDeviceDriver _driver;
private readonly ConcurrentQueue<SDL2AudioBuffer> _queuedBuffers;
private readonly DynamicRingBuffer _ringBuffer;
private ulong _playedSampleCount;
private readonly ManualResetEvent _updateRequiredEvent;
private SDL_AudioStream* _outputStream;
private uint _outputStream;
private bool _hasSetupError;
private readonly SDL_AudioStreamCallback _callbackDelegate;
private readonly SDL_AudioCallback _callbackDelegate;
private readonly int _bytesPerFrame;
private uint _sampleCount;
private bool _started;
private float _volume;
private readonly SDL_AudioFormat _nativeSampleFormat;
private readonly ushort _nativeSampleFormat;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SDL_AudioStreamCallback(nint session, SDL_AudioStream* stream, int stream_count, int device_count);
public SDL3HardwareDeviceSession(SDL3HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
public SDL2HardwareDeviceSession(SDL2HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{
_driver = driver;
_updateRequiredEvent = _driver.GetUpdateRequiredEvent();
_queuedBuffers = new ConcurrentQueue<SDL3AudioBuffer>();
_queuedBuffers = new ConcurrentQueue<SDL2AudioBuffer>();
_ringBuffer = new DynamicRingBuffer();
_callbackDelegate = Update;
_bytesPerFrame = BackendHelper.GetSampleSize(RequestedSampleFormat) * (int)RequestedChannelCount;
_nativeSampleFormat = SDL3HardwareDeviceDriver.GetSDL3Format(RequestedSampleFormat);
_nativeSampleFormat = SDL2HardwareDeviceDriver.GetSDL2Format(RequestedSampleFormat);
_sampleCount = uint.MaxValue;
_started = false;
_volume = 1f;
@@ -48,51 +44,45 @@ namespace Ryujinx.Audio.Backends.SDL3
private void EnsureAudioStreamSetup(AudioBuffer buffer)
{
uint bufferSampleCount = (uint)GetSampleCount(buffer);
bool needAudioSetup = (_outputStream == null && !_hasSetupError) ||
bool needAudioSetup = (_outputStream == 0 && !_hasSetupError) ||
(bufferSampleCount >= Constants.TargetSampleCount && bufferSampleCount < _sampleCount);
if (needAudioSetup)
{
_sampleCount = Math.Max(Constants.TargetSampleCount, bufferSampleCount);
SDL_AudioStream* newOutputStream = SDL3HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, RequestedChannelCount, _sampleCount, _callbackDelegate);
uint newOutputStream = SDL2HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, RequestedChannelCount, _sampleCount, _callbackDelegate);
_hasSetupError = newOutputStream == null;
_hasSetupError = newOutputStream == 0;
if (!_hasSetupError)
{
if (_outputStream != null)
if (_outputStream != 0)
{
SDL_DestroyAudioStream(_outputStream);
SDL_CloseAudioDevice(_outputStream);
}
_outputStream = newOutputStream;
if (_started) {
SDL_ResumeAudioStreamDevice(_outputStream);
} else {
SDL_PauseAudioStreamDevice(_outputStream);
}
SDL_PauseAudioDevice(_outputStream, _started ? 0 : 1);
Logger.Info?.Print(LogClass.Audio, $"New audio stream setup with a target sample count of {_sampleCount}");
}
}
}
private unsafe void Update(nint userdata, SDL_AudioStream* streamDevice, int additionalAmount, int totalAmmount)
private unsafe void Update(nint userdata, nint stream, int streamLength)
{
using SpanOwner<byte> stream = SpanOwner<byte>.Rent(additionalAmount);
Span<byte> streamSpan = stream.Span;
Span<byte> streamSpan = new((void*)stream, streamLength);
int maxFrameCount = (int)GetSampleCount(additionalAmount);
int maxFrameCount = (int)GetSampleCount(streamLength);
int bufferedFrames = _ringBuffer.Length / _bytesPerFrame;
int frameCount = Math.Min(bufferedFrames, maxFrameCount);
if (frameCount == 0)
{
// SDL3 left the responsibility to the user to clear the buffer.
// SDL2 left the responsibility to the user to clear the buffer.
streamSpan.Clear();
return;
@@ -104,17 +94,15 @@ namespace Ryujinx.Audio.Backends.SDL3
_ringBuffer.Read(samples, 0, samples.Length);
// Zero the dest buffer
streamSpan.Clear();
fixed (byte* p = samples)
{
nint pStreamSrc = (nint)p;
fixed (byte* pStreamDst = streamSpan) {
fixed (byte* pStreamSrc = samples)
{
// Zero the dest buffer
streamSpan.Clear();
// Apply volume to written data
SDL_MixAudio(pStreamDst, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, _driver.Volume * _volume);
SDL_PutAudioStreamData(streamDevice, (nint)pStreamDst, additionalAmount);
}
// Apply volume to written data
SDL_MixAudioFormat(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, (int)(_driver.Volume * _volume * SDL_MIX_MAXVOLUME));
}
ulong sampleCount = GetSampleCount(samples.Length);
@@ -123,7 +111,7 @@ namespace Ryujinx.Audio.Backends.SDL3
bool needUpdate = false;
while (availaibleSampleCount > 0 && _queuedBuffers.TryPeek(out SDL3AudioBuffer driverBuffer))
while (availaibleSampleCount > 0 && _queuedBuffers.TryPeek(out SDL2AudioBuffer driverBuffer))
{
ulong sampleStillNeeded = driverBuffer.SampleCount - Interlocked.Read(ref driverBuffer.SamplePlayed);
ulong playedAudioBufferSampleCount = Math.Min(sampleStillNeeded, availaibleSampleCount);
@@ -164,9 +152,9 @@ namespace Ryujinx.Audio.Backends.SDL3
{
EnsureAudioStreamSetup(buffer);
if (_outputStream != null)
if (_outputStream != 0)
{
SDL3AudioBuffer driverBuffer = new(buffer.DataPointer, GetSampleCount(buffer));
SDL2AudioBuffer driverBuffer = new(buffer.DataPointer, GetSampleCount(buffer));
_ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
@@ -189,9 +177,9 @@ namespace Ryujinx.Audio.Backends.SDL3
{
if (!_started)
{
if (_outputStream != null)
if (_outputStream != 0)
{
SDL_ResumeAudioStreamDevice(_outputStream);
SDL_PauseAudioDevice(_outputStream, 0);
}
_started = true;
@@ -202,9 +190,9 @@ namespace Ryujinx.Audio.Backends.SDL3
{
if (_started)
{
if (_outputStream != null)
if (_outputStream != 0)
{
SDL_PauseAudioStreamDevice(_outputStream);
SDL_PauseAudioDevice(_outputStream, 1);
}
_started = false;
@@ -215,7 +203,7 @@ namespace Ryujinx.Audio.Backends.SDL3
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{
if (!_queuedBuffers.TryPeek(out SDL3AudioBuffer driverBuffer))
if (!_queuedBuffers.TryPeek(out SDL2AudioBuffer driverBuffer))
{
return true;
}
@@ -223,16 +211,16 @@ namespace Ryujinx.Audio.Backends.SDL3
return driverBuffer.DriverIdentifier != buffer.DataPointer;
}
private void Dispose(bool disposing)
protected virtual void Dispose(bool disposing)
{
if (disposing && _driver.Unregister(this))
{
PrepareToClose();
Stop();
if (_outputStream != null)
if (_outputStream != 0)
{
SDL_DestroyAudioStream(_outputStream);
SDL_CloseAudioDevice(_outputStream);
}
}
}

View File

@@ -130,7 +130,7 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
unsafe
{
int* frameCountPtr = &nativeFrameCount;
nint* arenasPtr = &arenas;
IntPtr* arenasPtr = &arenas;
CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr));
frameCount = *frameCountPtr;

View File

@@ -10,7 +10,7 @@ using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
namespace Ryujinx.Audio.Backends.SoundIo
{
public sealed class SoundIoHardwareDeviceDriver : IHardwareDeviceDriver
public class SoundIoHardwareDeviceDriver : IHardwareDeviceDriver
{
private readonly SoundIoContext _audioContext;
private readonly SoundIoDeviceContext _audioDevice;
@@ -227,7 +227,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
}
}
private void Dispose(bool disposing)
protected virtual void Dispose(bool disposing)
{
if (disposing)
{

Some files were not shown because too many files have changed in this diff Show More