Compare commits

..

24 Commits

Author SHA1 Message Date
jcm
84d6e8d121 Standardize logging locations across desktop platforms (#6238)
* Standardize logging locations across desktop platforms

* Return null instead of empty literal on exceptions

* Remove LogDirectoryPath from LoggerModule

* Catch exception when creating DirectoryInfo in FileLogTarget

* Remove redundant log path vars, handle exception better, add null check

* Address styling issues

* Remove extra newline, quote file path in log, move directory check to OpenHelper

* Add GetOrCreateLogsDir to get/create log directory during runtime

* misc format changes

* Update src/Ryujinx.Common/Configuration/AppDataManager.cs

---------

Co-authored-by: jcm <butt@butts.com>
Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-02-11 02:17:19 +01:00
lasers
95c4912d58 Linux: Reorder available executables in Ryujinx.sh (#6171)
* Avoid Ryujinx.Headless.SDL2 as a last resort in Ryujinx.desktop when you
  have more than one executable installed.
2024-02-11 00:57:23 +01:00
Isaac Marovitz
356a75af0b Remove ReflectionBinding in Mod Manager (#6280) 2024-02-11 00:52:11 +01:00
sunshineinabox
4ae9921063 Update Avalonia About Window like requested in PR #6267 (#6278)
* Update About Window like requested in PR #6267

* Feedback

* Apply suggestions from code review

Co-authored-by: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>

* Fix indents

---------

Co-authored-by: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>
2024-02-11 00:45:14 +01:00
gdkchan
6a8ac389e5 Fix mip offset/size for full 3D texture upload on Vulkan (#6294) 2024-02-11 00:41:17 +01:00
Mary Guillemard
8dd1eb333c Add missing RID exclusions for linux-arm64 (#6298)
* Add missing RID exclusions for linux-arm64

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Remove libsoundio.so from linux-arm64 deployment

This is a x86_64 library.

Signed-off-by: Mary Guillemard <mary@mary.zone>

---------

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-10 22:49:32 +01:00
Mary Guillemard
7dc3a62c14 ci: Enable Linux ARM64 on build and release (#6291)
* ci: Enable Linux ARM64 on build and release

Signed-off-by: Mary <mary@mary.zone>

* Address gdkchan comment

Signed-off-by: Mary <mary@mary.zone>

---------

Signed-off-by: Mary <mary@mary.zone>
2024-02-10 22:05:46 +01:00
Mary Guillemard
e59dba42ef Set PointSize in shader on OpenGL (#6292)
Previously we were only doing it for Vulkan, but it turns out that
not setting it when PROGRAM_POINT_SIZE is set is considered UB
on OpenGL Core.

Signed-off-by: Mary <mary@mary.zone>
2024-02-10 20:27:17 +01:00
Mary Guillemard
bd6937ae5c Make IOpenGLContext.HasContext context dependent (#6290)
This makes IOpenGLContext.HasContext not static and be implementable.

By doing this, we can support more than WGL and WGL.

This also allows the SDL2 headless version to run under Wayland.

Signed-off-by: Mary <mary@mary.zone>
2024-02-10 20:13:10 +01:00
jcm
b82e789d4f Load custom SDL mappings from application data folder (#6295)
Co-authored-by: jcm <butt@butts.com>
2024-02-10 19:41:02 +01:00
gdkchan
4a6724622e Force CPU copy for non-identity DMA remap (#6293) 2024-02-10 15:38:58 -03:00
Mary Guillemard
0c73eba3db misc: Update to Ryujinx.Graphics.Nvdec.Dependencies 5.0.3-build14 (#6279)
Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-10 11:23:44 +01:00
Mary Guillemard
a082e14ede Revert "Bump Ava (#6271)"
This reverts commit dfc0819e72.

X popup position broke entirely (my fault oops), waiting for next release with a fix
(see https://github.com/AvaloniaUI/Avalonia/pull/14551)
2024-02-08 22:14:56 +01:00
Isaac Marovitz
d29da11d5f Remove SDC (#6275) 2024-02-08 20:36:59 +01:00
gdkchan
ea07328aea LightningJit: Reduce stack usage for Arm32 code (#6245)
* Write/read guest state to context for sync points, stop reserving stack for them

* Fix UsedGprsMask not being updated when allocating with preferencing

* POP should be also considered a return
2024-02-08 20:17:47 +01:00
Isaac Marovitz
a0b3d82ee0 Remove Vic Reference to Host1x (#6277) 2024-02-08 20:01:03 +01:00
gdkchan
609de33b0b Implement BGR10A2 render target format (#6273) 2024-02-08 19:52:38 +01:00
Isaac Marovitz
dfc0819e72 Bump Ava (#6271) 2024-02-08 19:45:18 +01:00
dependabot[bot]
d4803356bb nuget: bump Microsoft.NET.Test.Sdk from 17.8.0 to 17.9.0 (#6265)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.8.0 to 17.9.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.8.0...v17.9.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-08 19:38:51 +01:00
sunshineinabox
459efd0db7 Replace Flex Panels in favor of Wrap Panels for Avalonia (#6267)
* Switch from using Flex panel to a Wrap panel for Grid view. This allows keyboard navigation.

* Stop using Flex panel in favor of Avalonia Wrap Panel.
2024-02-08 19:34:48 +01:00
gdkchan
8bb7a3fc97 Clamp vertex buffer size to mapped size if too high (#6272)
* Clamp vertex buffer size to mapped size if too high

* Update comment
2024-02-08 18:27:12 +01:00
Mary Guillemard
628d092fc6 chore: Update Ryujinx.SDL2-CS to 2.30.0 (#6261)
Also add linux-arm64 support.

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-07 22:43:44 +01:00
SamusAranX
6c90d50c8e Redact usernames from logs (#6255)
* Redact usernames from logs

* Changed internal vars to private and applied naming rules

* Use Directory.GetParent() instead of DirectoryInfo

* Update src/Ryujinx.Common/Logging/Logger.cs

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-02-06 23:29:50 +01:00
riperiperi
d56bab1e24 AccountService: Cache token data (#6260)
* AccountService: Cache token data

This method appears to indicate that the token returned should be cached. I've made it so that it generates a token that lasts until its expiration time, and reuses it on subsequent calls.

* Private naming convention
2024-02-06 23:11:20 +01:00
45 changed files with 426 additions and 256 deletions

View File

@@ -10,28 +10,17 @@ env:
jobs:
build:
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
runs-on: ${{ matrix.os }}
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
runs-on: ${{ matrix.platform.os }}
timeout-minutes: 45
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
configuration: [Debug, Release]
include:
- os: ubuntu-latest
OS_NAME: Linux x64
DOTNET_RUNTIME_IDENTIFIER: linux-x64
RELEASE_ZIP_OS_NAME: linux_x64
- os: macOS-latest
OS_NAME: macOS x64
DOTNET_RUNTIME_IDENTIFIER: osx-x64
RELEASE_ZIP_OS_NAME: osx_x64
- os: windows-latest
OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win-x64
RELEASE_ZIP_OS_NAME: win_x64
platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
- { name: osx-x64, os: macOS-latest, zip_os_name: osx_x64 }
fail-fast: false
steps:
@@ -52,12 +41,12 @@ jobs:
- name: Change config filename
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
- name: Change config filename for macOS
run: sed -r -i '' 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request' && matrix.os == 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os == 'macOS-latest'
- name: Build
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
@@ -68,46 +57,47 @@ jobs:
commands: dotnet test --no-build -c "${{ matrix.configuration }}"
timeout-minutes: 10
retry-codes: 139
if: matrix.platform.name != 'linux-arm64'
- name: Publish Ryujinx
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
- name: Publish Ryujinx.Headless.SDL2
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
- name: Publish Ryujinx.Ava
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
- name: Set executable bit
run: |
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
chmod +x ./publish_ava/Ryujinx.Ava ./publish_ava/Ryujinx.sh
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
- name: Upload Ryujinx artifact
uses: actions/upload-artifact@v4
with:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_sdl2_headless
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
- name: Upload Ryujinx.Ava artifact
uses: actions/upload-artifact@v4
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_ava
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
build_macos:
name: macOS Universal (${{ matrix.configuration }})

View File

@@ -45,22 +45,15 @@ jobs:
})
release:
name: Release ${{ matrix.OS_NAME }}
runs-on: ${{ matrix.os }}
name: Release for ${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
include:
- os: ubuntu-latest
OS_NAME: Linux x64
DOTNET_RUNTIME_IDENTIFIER: linux-x64
RELEASE_ZIP_OS_NAME: linux_x64
- os: windows-latest
OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win-x64
RELEASE_ZIP_OS_NAME: win_x64
platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { 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
@@ -93,42 +86,42 @@ jobs:
- name: Publish
run: |
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_gtk/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 true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_gtk/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 true
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
- name: Packing Windows builds
if: matrix.os == 'windows-latest'
if: matrix.platform.os == 'windows-latest'
run: |
pushd publish_gtk
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd
pushd publish_sdl2_headless
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd
pushd publish_ava
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd
shell: bash
- name: Packing Linux builds
if: matrix.os == 'ubuntu-latest'
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish_gtk
chmod +x publish/Ryujinx.sh publish/Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd
pushd publish_sdl2_headless
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd
pushd publish_ava
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd
shell: bash

View File

@@ -17,12 +17,11 @@
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
<PackageVersion Include="LibHac" Version="0.19.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.3.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
@@ -33,10 +32,10 @@
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
@@ -51,4 +50,4 @@
<PackageVersion Include="System.Management" Version="8.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,14 +1,21 @@
#!/bin/sh
SCRIPT_DIR=$(dirname "$(realpath "$0")")
RYUJINX_BIN="Ryujinx"
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
RYUJINX_BIN="Ryujinx.Headless.SDL2"
fi
if [ -f "$SCRIPT_DIR/Ryujinx.Ava" ]; then
RYUJINX_BIN="Ryujinx.Ava"
fi
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
RYUJINX_BIN="Ryujinx.Headless.SDL2"
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then
RYUJINX_BIN="Ryujinx"
fi
if [ -z "$RYUJINX_BIN" ]; then
exit 1
fi
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
@@ -17,4 +24,4 @@ if command -v gamemoderun > /dev/null 2>&1; then
COMMAND="$COMMAND gamemoderun"
fi
$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
exec $COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"

View File

@@ -11,15 +11,15 @@
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'">
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.dylib</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libsoundio.so</TargetPath>
</ContentWithTargetPath>

View File

@@ -43,14 +43,13 @@
<PackageReference Include="Avalonia.Markup.Xaml.Loader" />
<PackageReference Include="Avalonia.Svg" />
<PackageReference Include="Avalonia.Svg.Skia" />
<PackageReference Include="jp2masa.Avalonia.Flexbox" />
<PackageReference Include="DynamicData" />
<PackageReference Include="FluentAvaloniaUI" />
<PackageReference Include="OpenTK.Core" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="Silk.NET.Vulkan" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
@@ -79,7 +78,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>alsoft.ini</TargetPath>
</Content>
@@ -93,7 +92,7 @@
</Content>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64'">
<Content Include="..\..\distribution\linux\Ryujinx.sh">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

View File

@@ -4,7 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
@@ -33,11 +32,10 @@
SelectionChanged="GameList_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<flex:FlexPanel
<WrapPanel
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
AlignContent="FlexStart"
JustifyContent="FlexStart" />
VerticalAlignment="Top"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>

View File

@@ -29,6 +29,8 @@ namespace Ryujinx.Ava.UI.Renderer
_context.MakeCurrent(_window);
}
public bool HasContext() => _context.IsCurrent;
public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext)
{
OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext);

View File

@@ -1350,16 +1350,11 @@ namespace Ryujinx.Ava.UI.ViewModels
public void OpenLogsFolder()
{
string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
if (LoggerModule.LogDirectoryPath != null)
string logPath = AppDataManager.GetOrCreateLogsDir();
if (!string.IsNullOrEmpty(logPath))
{
logPath = LoggerModule.LogDirectoryPath;
OpenHelper.OpenFolder(logPath);
}
new DirectoryInfo(logPath).Create();
OpenHelper.OpenFolder(logPath);
}
public void ToggleDockMode()

View File

@@ -4,7 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
@@ -40,11 +39,10 @@
ItemsSource="{Binding Profiles}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<flex:FlexPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AlignContent="FlexStart"
JustifyContent="FlexStart" />
<WrapPanel
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
@@ -161,4 +159,4 @@
Content="{locale:Locale UserProfilesClose}" />
</StackPanel>
</Grid>
</UserControl>
</UserControl>

View File

@@ -3,7 +3,6 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
@@ -45,33 +44,37 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Height="80"
Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
<flex:FlexPanel
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Direction="Column"
JustifyContent="SpaceAround"
RowSpacing="2">
<TextBlock
<StackPanel
Grid.Column="1"
Orientation="Horizontal"
HorizontalAlignment="Center"
Spacing="10">
<Image
Height="80"
Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common"
HorizontalAlignment="Center"
IsHitTestVisible="True" />
<WrapPanel
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="28"
FontWeight="Bold"
Text="Ryujinx"
TextAlignment="Center"
Width="110" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="11"
Text="(REE-YOU-JINX)"
TextAlignment="Center"
Width="110" />
</flex:FlexPanel>
Orientation="Vertical">
<TextBlock
FontSize="28"
FontWeight="Bold"
Text="Ryujinx"
TextAlignment="Start"
Width="110"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
<TextBlock
FontSize="11"
Text="(REE-YOU-JINX)"
TextAlignment="Start"
Width="110"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</WrapPanel>
</StackPanel>
</Grid>
<TextBlock
HorizontalAlignment="Center"

View File

@@ -40,14 +40,14 @@
Name="EnableAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding EnableAll}">
Command="{Binding EnableAll}">
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
</Button>
<Button
Name="DisableAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding DisableAll}">
Command="{Binding DisableAll}">
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
</Button>
</StackPanel>

View File

@@ -30,6 +30,8 @@ namespace Ryujinx.Common.Configuration
public static string KeysDirPath { get; private set; }
public static string KeysDirPathUser { get; }
public static string LogsDirPath { get; private set; }
public const string DefaultNandDir = "bis";
public const string DefaultSdcardDir = "sdcard";
private const string DefaultModsDir = "mods";
@@ -46,15 +48,7 @@ namespace Ryujinx.Common.Configuration
public static void Initialize(string baseDirPath)
{
string appDataPath;
if (OperatingSystem.IsMacOS())
{
appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support");
}
else
{
appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
}
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (appDataPath.Length == 0)
{
@@ -118,9 +112,126 @@ namespace Ryujinx.Common.Configuration
SetupBasePaths();
}
public static string GetOrCreateLogsDir()
{
if (Directory.Exists(LogsDirPath))
{
return LogsDirPath;
}
Logger.Notice.Print(LogClass.Application, "Logging directory not found; attempting to create new logging directory.");
LogsDirPath = SetUpLogsDir();
return LogsDirPath;
}
private static string SetUpLogsDir()
{
string logDir = "";
if (Mode == LaunchMode.Portable)
{
logDir = Path.Combine(BaseDirPath, "Logs");
try
{
Directory.CreateDirectory(logDir);
}
catch
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}'");
return null;
}
}
else
{
if (OperatingSystem.IsMacOS())
{
// NOTE: Should evaluate to "~/Library/Logs/Ryujinx/".
logDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Logs", DefaultBaseDir);
try
{
Directory.CreateDirectory(logDir);
}
catch
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}'");
logDir = "";
}
if (string.IsNullOrEmpty(logDir))
{
// NOTE: Should evaluate to "~/Library/Application Support/Ryujinx/Logs".
logDir = Path.Combine(BaseDirPath, "Logs");
try
{
Directory.CreateDirectory(logDir);
}
catch
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}'");
return null;
}
}
}
else if (OperatingSystem.IsWindows())
{
// NOTE: Should evaluate to a "Logs" directory in whatever directory Ryujinx was launched from.
logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
try
{
Directory.CreateDirectory(logDir);
}
catch
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}'");
logDir = "";
}
if (string.IsNullOrEmpty(logDir))
{
// NOTE: Should evaluate to "C:\Users\user\AppData\Roaming\Ryujinx\Logs".
logDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir, "Logs");
try
{
Directory.CreateDirectory(logDir);
}
catch
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}'");
return null;
}
}
}
else if (OperatingSystem.IsLinux())
{
// NOTE: Should evaluate to "~/.config/Ryujinx/Logs".
logDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir, "Logs");
try
{
Directory.CreateDirectory(logDir);
}
catch
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}'");
return null;
}
}
}
return logDir;
}
private static void SetupBasePaths()
{
Directory.CreateDirectory(BaseDirPath);
LogsDirPath = SetUpLogsDir();
Directory.CreateDirectory(GamesDirPath = Path.Combine(BaseDirPath, GamesDir));
Directory.CreateDirectory(ProfilesDirPath = Path.Combine(BaseDirPath, ProfilesDir));
Directory.CreateDirectory(KeysDirPath = Path.Combine(BaseDirPath, KeysDir));

View File

@@ -3,6 +3,7 @@ using Ryujinx.Common.SystemInterop;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
@@ -22,6 +23,9 @@ namespace Ryujinx.Common.Logging
public readonly struct Log
{
private static readonly string _homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir).FullName, "[redacted]");
internal readonly LogLevel Level;
internal Log(LogLevel level)
@@ -100,7 +104,12 @@ namespace Ryujinx.Common.Logging
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string FormatMessage(LogClass logClass, string caller, string message) => $"{logClass} {caller}: {message}";
private static string FormatMessage(LogClass logClass, string caller, string message)
{
message = message.Replace(_homeDir, _homeDirRedacted);
return $"{logClass} {caller}: {message}";
}
}
public static Log? Debug { get; private set; }

View File

@@ -23,7 +23,18 @@ namespace Ryujinx.Common.Logging.Targets
public static FileStream PrepareLogFile(string path)
{
// Ensure directory is present
DirectoryInfo logDir = new(path);
DirectoryInfo logDir;
try
{
logDir = new DirectoryInfo(path);
}
catch (ArgumentException exception)
{
Logger.Warning?.Print(LogClass.Application, $"Logging directory path ('{path}') was invalid: {exception}");
return null;
}
try
{
logDir.Create();

View File

@@ -10,6 +10,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
public readonly List<InstInfo> Instructions;
public readonly bool EndsWithBranch;
public readonly bool HasHostCall;
public readonly bool HasHostCallSkipContext;
public readonly bool IsTruncated;
public readonly bool IsLoopEnd;
public readonly bool IsThumb;
@@ -20,6 +21,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
List<InstInfo> instructions,
bool endsWithBranch,
bool hasHostCall,
bool hasHostCallSkipContext,
bool isTruncated,
bool isLoopEnd,
bool isThumb)
@@ -31,6 +33,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Instructions = instructions;
EndsWithBranch = endsWithBranch;
HasHostCall = hasHostCall;
HasHostCallSkipContext = hasHostCallSkipContext;
IsTruncated = isTruncated;
IsLoopEnd = isLoopEnd;
IsThumb = isThumb;
@@ -57,6 +60,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Instructions.GetRange(0, splitIndex),
false,
HasHostCall,
HasHostCallSkipContext,
false,
false,
IsThumb);
@@ -67,6 +71,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Instructions.GetRange(splitIndex, splitCount),
EndsWithBranch,
HasHostCall,
HasHostCallSkipContext,
IsTruncated,
IsLoopEnd,
IsThumb);

View File

@@ -208,6 +208,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
InstMeta meta;
InstFlags extraFlags = InstFlags.None;
bool hasHostCall = false;
bool hasHostCallSkipContext = false;
bool isTruncated = false;
do
@@ -246,9 +247,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
meta = InstTableA32<T>.GetMeta(encoding, cpuPreset.Version, cpuPreset.Features);
}
if (meta.Name.IsSystemOrCall() && !hasHostCall)
if (meta.Name.IsSystemOrCall())
{
hasHostCall = meta.Name.IsCall() || InstEmitSystem.NeedsCall(meta.Name);
if (!hasHostCall)
{
hasHostCall = InstEmitSystem.NeedsCall(meta.Name);
}
if (!hasHostCallSkipContext)
{
hasHostCallSkipContext = meta.Name.IsCall() || InstEmitSystem.NeedsCallSkipContext(meta.Name);
}
}
insts.Add(new(encoding, meta.Name, meta.EmitFunc, meta.Flags | extraFlags));
@@ -259,8 +268,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
if (!isTruncated && IsBackwardsBranch(meta.Name, encoding))
{
hasHostCall = true;
isLoopEnd = true;
hasHostCallSkipContext = true;
}
return new(
@@ -269,6 +278,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
insts,
!isTruncated,
hasHostCall,
hasHostCallSkipContext,
isTruncated,
isLoopEnd,
isThumb);

View File

@@ -6,6 +6,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
{
public readonly List<Block> Blocks;
public readonly bool HasHostCall;
public readonly bool HasHostCallSkipContext;
public readonly bool IsTruncated;
public MultiBlock(List<Block> blocks)
@@ -15,12 +16,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
Block block = blocks[0];
HasHostCall = block.HasHostCall;
HasHostCallSkipContext = block.HasHostCallSkipContext;
for (int index = 1; index < blocks.Count; index++)
{
block = blocks[index];
HasHostCall |= block.HasHostCall;
HasHostCallSkipContext |= block.HasHostCallSkipContext;
}
block = blocks[^1];

View File

@@ -106,6 +106,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
if ((regMask & AbiConstants.ReservedRegsMask) == 0)
{
_gprMask |= regMask;
UsedGprsMask |= regMask;
return firstCalleeSaved;
}

View File

@@ -305,12 +305,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
ForceConditionalEnd(cgContext, ref lastCondition, lastConditionIp);
}
int reservedStackSize = 0;
if (multiBlock.HasHostCall)
{
reservedStackSize = CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask);
}
else if (multiBlock.HasHostCallSkipContext)
{
reservedStackSize = 2 * sizeof(ulong); // Context and page table pointers.
}
RegisterSaveRestore rsr = new(
regAlloc.UsedGprsMask & AbiConstants.GprCalleeSavedRegsMask,
regAlloc.UsedFpSimdMask & AbiConstants.FpSimdCalleeSavedRegsMask,
OperandType.FP64,
multiBlock.HasHostCall,
multiBlock.HasHostCall ? CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask) : 0);
multiBlock.HasHostCall || multiBlock.HasHostCallSkipContext,
reservedStackSize);
TailMerger tailMerger = new();
@@ -596,7 +607,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
name == InstName.Ldm ||
name == InstName.Ldmda ||
name == InstName.Ldmdb ||
name == InstName.Ldmib)
name == InstName.Ldmib ||
name == InstName.Pop)
{
// Arm32 does not have a return instruction, instead returns are implemented
// either using BX LR (for leaf functions), or POP { ... PC }.
@@ -711,7 +723,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
switch (type)
{
case BranchType.SyncPoint:
InstEmitSystem.WriteSyncPoint(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset());
InstEmitSystem.WriteSyncPoint(
context.Writer,
ref asm,
context.RegisterAllocator,
context.TailMerger,
context.GetReservedStackOffset(),
context.StoreToContext,
context.LoadFromContext);
break;
case BranchType.SoftwareInterrupt:
context.StoreToContext();

View File

@@ -199,12 +199,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
}
}
private static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
public static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
{
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: true);
}
private static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
public static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
{
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: false);
}

View File

@@ -354,11 +354,18 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// All instructions that might do a host call should be included here.
// That is required to reserve space on the stack for caller saved registers.
return name == InstName.Mrrc;
}
public static bool NeedsCallSkipContext(InstName name)
{
// All instructions that might do a host call should be included here.
// That is required to reserve space on the stack for caller saved registers.
switch (name)
{
case InstName.Mcr:
case InstName.Mrc:
case InstName.Mrrc:
case InstName.Svc:
case InstName.Udf:
return true;
@@ -372,7 +379,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Assembler asm = new(writer);
WriteCall(ref asm, regAlloc, GetBkptHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
}
public static void WriteSvc(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint svcId)
@@ -380,7 +387,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Assembler asm = new(writer);
WriteCall(ref asm, regAlloc, GetSvcHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, svcId);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
}
public static void WriteUdf(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint imm)
@@ -388,7 +395,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Assembler asm = new(writer);
WriteCall(ref asm, regAlloc, GetUdfHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
}
public static void WriteReadCntpct(CodeWriter writer, RegisterAllocator regAlloc, int spillBaseOffset, int rt, int rt2)
@@ -422,14 +429,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
WriteFill(ref asm, regAlloc, resultMask, skipContext: false, spillBaseOffset, tempRegister);
}
public static void WriteSyncPoint(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset)
{
Assembler asm = new(writer);
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: false, spillBaseOffset);
}
private static void WriteSyncPoint(CodeWriter writer, ref Assembler asm, RegisterAllocator regAlloc, TailMerger tailMerger, bool skipContext, int spillBaseOffset)
public static void WriteSyncPoint(
CodeWriter writer,
ref Assembler asm,
RegisterAllocator regAlloc,
TailMerger tailMerger,
int spillBaseOffset,
Action storeToContext = null,
Action loadFromContext = null)
{
int tempRegister = regAlloc.AllocateTempGprRegister();
@@ -440,7 +447,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
int branchIndex = writer.InstructionPointer;
asm.Cbnz(rt, 0);
WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister);
storeToContext?.Invoke();
WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext: true, spillBaseOffset, tempRegister);
Operand rn = Register(tempRegister == 0 ? 1 : 0);
@@ -449,7 +457,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
tailMerger.AddConditionalZeroReturn(writer, asm, Register(0, OperandType.I32));
WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister);
WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext: true, spillBaseOffset, tempRegister);
loadFromContext?.Invoke();
asm.LdrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset);
@@ -514,18 +523,31 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
private static void WriteSpill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
{
WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: true);
if (skipContext)
{
InstEmitFlow.WriteSpillSkipContext(ref asm, regAlloc, spillOffset);
}
else
{
WriteSpillOrFill(ref asm, regAlloc, exceptMask, spillOffset, tempRegister, spill: true);
}
}
private static void WriteFill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
{
WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: false);
if (skipContext)
{
InstEmitFlow.WriteFillSkipContext(ref asm, regAlloc, spillOffset);
}
else
{
WriteSpillOrFill(ref asm, regAlloc, exceptMask, spillOffset, tempRegister, spill: false);
}
}
private static void WriteSpillOrFill(
ref Assembler asm,
RegisterAllocator regAlloc,
bool skipContext,
uint exceptMask,
int spillOffset,
int tempRegister,
@@ -533,11 +555,6 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
uint gprMask = regAlloc.UsedGprsMask & ~(AbiConstants.GprCalleeSavedRegsMask | exceptMask);
if (skipContext)
{
gprMask &= ~Compiler.UsableGprsMask;
}
if (!spill)
{
// We must reload the status register before reloading the GPRs,
@@ -600,11 +617,6 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
uint fpSimdMask = regAlloc.UsedFpSimdMask;
if (skipContext)
{
fpSimdMask &= ~Compiler.UsableFpSimdMask;
}
while (fpSimdMask != 0)
{
int reg = BitOperations.TrailingZeroCount(fpSimdMask);

View File

@@ -147,6 +147,7 @@ namespace Ryujinx.Graphics.GAL
A1B5G5R5Unorm,
B8G8R8A8Unorm,
B8G8R8A8Srgb,
B10G10R10A2Unorm,
}
public static class FormatExtensions
@@ -260,6 +261,7 @@ namespace Ryujinx.Graphics.GAL
case Format.R10G10B10A2Sint:
case Format.R10G10B10A2Uscaled:
case Format.R10G10B10A2Sscaled:
case Format.B10G10R10A2Unorm:
return 4;
case Format.S8Uint:
@@ -451,6 +453,7 @@ namespace Ryujinx.Graphics.GAL
case Format.R32G32Uint:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
case Format.B10G10R10A2Unorm:
case Format.R10G10B10A2Unorm:
case Format.R10G10B10A2Uint:
case Format.R8G8B8A8Unorm:
@@ -611,6 +614,7 @@ namespace Ryujinx.Graphics.GAL
case Format.B5G5R5A1Unorm:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
case Format.B10G10R10A2Unorm:
return true;
}

View File

@@ -277,6 +277,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
// If remapping is disabled, we always copy the components directly, in order.
// If it's enabled, but the mapping is just XYZW, we also copy them in order.
bool isIdentityRemap = !remap ||
(_state.State.SetRemapComponentsDstX == SetRemapComponentsDst.SrcX &&
(dstComponents < 2 || _state.State.SetRemapComponentsDstY == SetRemapComponentsDst.SrcY) &&
(dstComponents < 3 || _state.State.SetRemapComponentsDstZ == SetRemapComponentsDst.SrcZ) &&
(dstComponents < 4 || _state.State.SetRemapComponentsDstW == SetRemapComponentsDst.SrcW));
bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
@@ -284,7 +292,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
// but only if we are doing a complete copy,
// and not for block linear to linear copies, since those are typically accessed from the CPU.
if (completeSource && completeDest && !(dstLinear && !srcLinear))
if (completeSource && completeDest && !(dstLinear && !srcLinear) && isIdentityRemap)
{
var target = memoryManager.Physical.TextureCache.FindTexture(
memoryManager,
@@ -353,14 +361,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
TextureParams srcParams = new(srcRegionX, srcRegionY, srcBaseOffset, srcBpp, srcLinear, srcCalculator);
TextureParams dstParams = new(dstRegionX, dstRegionY, dstBaseOffset, dstBpp, dstLinear, dstCalculator);
// If remapping is enabled, we always copy the components directly, in order.
// If it's enabled, but the mapping is just XYZW, we also copy them in order.
bool isIdentityRemap = !remap ||
(_state.State.SetRemapComponentsDstX == SetRemapComponentsDst.SrcX &&
(dstComponents < 2 || _state.State.SetRemapComponentsDstY == SetRemapComponentsDst.SrcY) &&
(dstComponents < 3 || _state.State.SetRemapComponentsDstZ == SetRemapComponentsDst.SrcZ) &&
(dstComponents < 4 || _state.State.SetRemapComponentsDstW == SetRemapComponentsDst.SrcW));
if (isIdentityRemap)
{
// The order of the components doesn't change, so we can just copy directly

View File

@@ -26,6 +26,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public const int PrimitiveRestartStateIndex = 12;
public const int RenderTargetStateIndex = 27;
// Vertex buffers larger than this size will be clamped to the mapped size.
private const ulong VertexBufferSizeToMappedSizeThreshold = 256 * 1024 * 1024; // 256 MB
private readonly GpuContext _context;
private readonly GpuChannel _channel;
private readonly DeviceStateWithShadow<ThreedClassState> _state;
@@ -1144,6 +1147,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
size = Math.Min(size, maxVertexBufferSize);
}
else if (size > VertexBufferSizeToMappedSizeThreshold)
{
// Make sure we have a sane vertex buffer size, since in some cases applications
// might set the "end address" of the vertex buffer to the end of the GPU address space,
// which would result in a several GBs large buffer.
size = _channel.MemoryManager.GetMappedSize(address, size);
}
}
else
{

View File

@@ -37,6 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
R16G16Sint = 0xdc,
R16G16Uint = 0xdd,
R16G16Float = 0xde,
B10G10R10A2Unorm = 0xdf,
R11G11B10Float = 0xe0,
R32Sint = 0xe3,
R32Uint = 0xe4,
@@ -104,6 +105,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
ColorFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2),
ColorFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2),
ColorFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2),
ColorFormat.B10G10R10A2Unorm => new FormatInfo(Format.B10G10R10A2Unorm, 1, 1, 4, 4),
ColorFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3),
ColorFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1),
ColorFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1),

View File

@@ -30,6 +30,8 @@ namespace Ryujinx.Graphics.OpenGL
_thread.Start();
}
public bool HasContext() => _backgroundContext.HasContext();
private void Run()
{
InBackground = true;

View File

@@ -161,6 +161,7 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B10G10R10A2Unorm, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed));
Add(Format.R8Unorm, SizedInternalFormat.R8);
Add(Format.R8Uint, SizedInternalFormat.R8ui);

View File

@@ -7,21 +7,6 @@ namespace Ryujinx.Graphics.OpenGL
{
void MakeCurrent();
// TODO: Support more APIs per platform.
static bool HasContext()
{
if (OperatingSystem.IsWindows())
{
return WGLHelper.GetCurrentContext() != IntPtr.Zero;
}
else if (OperatingSystem.IsLinux())
{
return GLXHelper.GetCurrentContext() != IntPtr.Zero;
}
else
{
return false;
}
}
bool HasContext();
}
}

View File

@@ -248,7 +248,7 @@ namespace Ryujinx.Graphics.OpenGL
{
// alwaysBackground is ignored, since we cannot switch from the current context.
if (IOpenGLContext.HasContext())
if (_window.BackgroundContext.HasContext())
{
action(); // We have a context already - use that (assuming it is the main one).
}

View File

@@ -80,9 +80,10 @@ namespace Ryujinx.Graphics.Shader.Translation
return;
}
if (TranslatorContext.Definitions.Stage == ShaderStage.Vertex && TranslatorContext.Options.TargetApi == TargetApi.Vulkan)
// Vulkan requires the point size to be always written on the shader if the primitive topology is points.
// OpenGL requires the point size to be always written on the shader if PROGRAM_POINT_SIZE is set.
if (TranslatorContext.Definitions.Stage == ShaderStage.Vertex)
{
// Vulkan requires the point size to be always written on the shader if the primitive topology is points.
this.Store(StorageKind.Output, IoVariable.PointSize, null, ConstF(TranslatorContext.Definitions.PointSize));
}

View File

@@ -8,7 +8,6 @@
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
</ItemGroup>

View File

@@ -161,6 +161,7 @@ namespace Ryujinx.Graphics.Vulkan
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
Add(Format.B10G10R10A2Unorm, VkFormat.A2R10G10B10UnormPack32);
#pragma warning restore IDE0055
}

View File

@@ -839,7 +839,9 @@ namespace Ryujinx.Graphics.Vulkan
for (int level = 0; level < levels; level++)
{
int mipSize = GetBufferDataLength(Info.GetMipSize2D(dstLevel + level) * dstLayers);
int mipSize = GetBufferDataLength(is3D && !singleSlice
? Info.GetMipSize(dstLevel + level)
: Info.GetMipSize2D(dstLevel + level) * dstLayers);
int endOffset = offset + mipSize;

View File

@@ -22,6 +22,9 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
private readonly UserId _userId;
#pragma warning restore IDE0052
private byte[] _cachedTokenData;
private DateTime _cachedTokenExpiry;
public ManagerServer(UserId userId)
{
_userId = userId;
@@ -144,7 +147,13 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
}
*/
byte[] tokenData = Encoding.ASCII.GetBytes(GenerateIdToken());
if (_cachedTokenData == null || DateTime.UtcNow > _cachedTokenExpiry)
{
_cachedTokenExpiry = DateTime.UtcNow + TimeSpan.FromHours(3);
_cachedTokenData = Encoding.ASCII.GetBytes(GenerateIdToken());
}
byte[] tokenData = _cachedTokenData;
context.Memory.Write(bufferPosition, tokenData);
context.ResponseData.Write(tokenData.Length);

View File

@@ -96,6 +96,8 @@ namespace Ryujinx.Headless.SDL2.OpenGL
}
}
public bool HasContext() => SDL_GL_GetCurrentContext() != IntPtr.Zero;
public void Dispose()
{
SDL_GL_DeleteContext(_context);

View File

@@ -427,16 +427,12 @@ namespace Ryujinx.Headless.SDL2
if (!option.DisableFileLog)
{
FileStream logFile = FileLogTarget.PrepareLogFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
string logDir = AppDataManager.LogsDirPath;
FileStream logFile = null;
if (logFile == null)
if (!string.IsNullOrEmpty(logDir))
{
logFile = FileLogTarget.PrepareLogFile(Path.Combine(AppDataManager.BaseDirPath, "Logs"));
if (logFile == null)
{
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the application directory or the Ryujinx directory is writable.");
}
logFile = FileLogTarget.PrepareLogFile(logDir);
}
if (logFile != null)
@@ -447,6 +443,10 @@ namespace Ryujinx.Headless.SDL2
AsyncLogTargetOverflowAction.Block
));
}
else
{
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the Logs directory, Application Data, or the Ryujinx directory is writable.");
}
}
// Setup graphics configuration

View File

@@ -34,7 +34,7 @@
<ItemGroup>
<PackageReference Include="CommandLineParser" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
</ItemGroup>
<ItemGroup>
@@ -48,7 +48,7 @@
</Content>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64'">
<Content Include="..\..\distribution\linux\Ryujinx.sh">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

View File

@@ -1,3 +1,4 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using System;
using System.Collections.Concurrent;
@@ -93,7 +94,7 @@ namespace Ryujinx.SDL2.Common
SDL_EventState(SDL_EventType.SDL_CONTROLLERSENSORUPDATE, SDL_DISABLE);
string gamepadDbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SDL_GameControllerDB.txt");
string gamepadDbPath = Path.Combine(AppDataManager.BaseDirPath, "SDL_GameControllerDB.txt");
if (File.Exists(gamepadDbPath))
{

View File

@@ -9,8 +9,6 @@ namespace Ryujinx.Ui.Common.Configuration
{
public static class LoggerModule
{
public static string LogDirectoryPath { get; private set; }
public static void Initialize()
{
ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug;
@@ -84,26 +82,22 @@ namespace Ryujinx.Ui.Common.Configuration
{
if (e.NewValue)
{
string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
FileStream logFile = FileLogTarget.PrepareLogFile(logDir);
string logDir = AppDataManager.LogsDirPath;
FileStream logFile = null;
if (!string.IsNullOrEmpty(logDir))
{
logFile = FileLogTarget.PrepareLogFile(logDir);
}
if (logFile == null)
{
logDir = Path.Combine(AppDataManager.BaseDirPath, "Logs");
logFile = FileLogTarget.PrepareLogFile(logDir);
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the Logs directory, Application Data, or the Ryujinx directory is writable.");
Logger.RemoveTarget("file");
if (logFile == null)
{
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the application directory or the Ryujinx directory is writable.");
LogDirectoryPath = null;
Logger.RemoveTarget("file");
return;
}
return;
}
LogDirectoryPath = logDir;
Logger.AddTarget(new AsyncLogTargetWrapper(
new FileLogTarget("file", logFile),
1000,

View File

@@ -2,15 +2,13 @@ using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using ShellLink;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.Versioning;
using Image = System.Drawing.Image;
namespace Ryujinx.Ui.Common.Helper
{
@@ -23,12 +21,9 @@ namespace Ryujinx.Ui.Common.Helper
iconPath += ".ico";
MemoryStream iconDataStream = new(iconData);
using Image image = Image.FromStream(iconDataStream);
using Bitmap bitmap = new(128, 128);
using System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(bitmap);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.DrawImage(image, 0, 0, 128, 128);
SaveBitmapAsIcon(bitmap, iconPath);
var image = Image.Load(iconDataStream);
image.Mutate(x => x.Resize(128, 128));
SaveBitmapAsIcon(image, iconPath);
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
shortcut.StringData.NameString = cleanedAppName;
@@ -42,7 +37,7 @@ namespace Ryujinx.Ui.Common.Helper
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.desktop");
iconPath += ".png";
var image = SixLabors.ImageSharp.Image.Load<Rgba32>(iconData);
var image = Image.Load<Rgba32>(iconData);
image.SaveAsPng(iconPath);
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
@@ -83,7 +78,7 @@ namespace Ryujinx.Ui.Common.Helper
}
const string IconName = "icon.png";
var image = SixLabors.ImageSharp.Image.Load<Rgba32>(iconData);
var image = Image.Load<Rgba32>(iconData);
image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
// plist file
@@ -147,7 +142,7 @@ namespace Ryujinx.Ui.Common.Helper
/// <param name="source">The source bitmap image that will be saved as an .ico file</param>
/// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
[SupportedOSPlatform("windows")]
private static void SaveBitmapAsIcon(Bitmap source, string filePath)
private static void SaveBitmapAsIcon(Image source, string filePath)
{
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
@@ -155,7 +150,7 @@ namespace Ryujinx.Ui.Common.Helper
fs.Write(header);
// Writing actual data
source.Save(fs, ImageFormat.Png);
source.Save(fs, PngFormat.Instance);
// Getting data length (file length minus header)
long dataLength = fs.Length - header.Length;
// Write it in the correct place

View File

@@ -45,7 +45,7 @@
<EmbeddedResource Include="Resources\Logo_Twitter_Light.png" />
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == ''">
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR '$(RuntimeIdentifier)' == ''">
<EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" />
</ItemGroup>
@@ -57,7 +57,6 @@
<ItemGroup>
<PackageReference Include="DiscordRichPresence" />
<PackageReference Include="securifybv.ShellLink" />
<PackageReference Include="System.Drawing.Common" />
</ItemGroup>
<ItemGroup>

View File

@@ -21,11 +21,11 @@
<ItemGroup>
<PackageReference Include="Ryujinx.GtkSharp" />
<PackageReference Include="GtkSharp.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="GtkSharp.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="GtkSharp.Dependencies.osx" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="OpenTK.Core" />
<PackageReference Include="OpenTK.Graphics" />
<PackageReference Include="SPB" />
@@ -49,7 +49,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>alsoft.ini</TargetPath>
</Content>
@@ -63,7 +63,7 @@
</Content>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64'">
<Content Include="..\..\distribution\linux\Ryujinx.sh">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

View File

@@ -1376,16 +1376,11 @@ namespace Ryujinx.Ui
private void OpenLogsFolder_Pressed(object sender, EventArgs args)
{
string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
if (LoggerModule.LogDirectoryPath != null)
string logPath = AppDataManager.GetOrCreateLogsDir();
if (!string.IsNullOrEmpty(logPath))
{
logPath = LoggerModule.LogDirectoryPath;
OpenHelper.OpenFolder(logPath);
}
new DirectoryInfo(logPath).Create();
OpenHelper.OpenFolder(logPath);
}
private void Exit_Pressed(object sender, EventArgs args)

View File

@@ -29,6 +29,8 @@ namespace Ryujinx.Ui
_context.MakeCurrent(_window);
}
public bool HasContext() => _context.IsCurrent;
public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext)
{
OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext);