mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-08-01 10:39:50 -06:00
Compare commits
46 Commits
Canary-1.2
...
Canary-1.2
Author | SHA1 | Date | |
---|---|---|---|
b97b8ca8f5 | |||
d7d4225e0d | |||
a9e0fac9dc | |||
1b9656e960 | |||
8994e7476c | |||
b3944a18b7 | |||
18c957f90b | |||
1a005f96e7 | |||
072cd2824a | |||
9da97bc911 | |||
39252b7267 | |||
ec11bf2af9 | |||
8ae72c1a00 | |||
06abba25c1 | |||
de00a71690 | |||
315a1819c0 | |||
4ffb8aef12 | |||
290a6ad5de | |||
eda4f4349b | |||
5fbcb1f3a7 | |||
d00754477e | |||
0bc1eddaeb | |||
baad1e313f | |||
a1e6d11dcb | |||
3d168a8bfa | |||
000c1756de | |||
1d0152b961 | |||
07690e4527 | |||
08b7257be5 | |||
17483aad24 | |||
6b5cb151c3 | |||
3680df6092 | |||
facc12a94a | |||
8e55e6d6d7 | |||
346dfe9542 | |||
8a2b56cae6 | |||
baf179efdb | |||
2a72fb2088 | |||
0caeab2270 | |||
f72d2c1b2b | |||
a18cecbc30 | |||
2e6794e69b | |||
7e16fccfc1 | |||
a81212bbf1 | |||
e8d3ad4d8b | |||
3b6731a351 |
46
.github/workflows/canary.yml
vendored
46
.github/workflows/canary.yml
vendored
@ -54,7 +54,19 @@ jobs:
|
||||
with:
|
||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
||||
body: |
|
||||
# Canary builds:
|
||||
|
||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ github.repository }}/releases/latest) instead if that sounds like something you don't want to deal with.
|
||||
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64 bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||
| Linux 64 bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||
| Linux arm 64 bit | [Canary Linux arm Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||
| macOS | [Canary macOS artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||
|
||||
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
|
||||
omitBodyDuringUpdate: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
@ -103,8 +115,8 @@ jobs:
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
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 --self-contained -p:IncludeNativeLibrariesForSelfExtract=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 -p:IncludeNativeLibrariesForSelfExtract=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 --self-contained
|
||||
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
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.platform.os == 'windows-latest'
|
||||
@ -181,7 +193,19 @@ jobs:
|
||||
artifacts: "release_output/*.tar.gz,release_output/*.zip"
|
||||
#artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
||||
body: |
|
||||
# Canary builds:
|
||||
|
||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
|
||||
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
||||
|
||||
"**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
@ -248,7 +272,19 @@ jobs:
|
||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
||||
body: |
|
||||
# Canary builds:
|
||||
|
||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
|
||||
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
||||
|
||||
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
|
37
.github/workflows/release.yml
vendored
37
.github/workflows/release.yml
vendored
@ -53,7 +53,16 @@ jobs:
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||
body: |
|
||||
# Regular builds:
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64 bit | [Release Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||
| Linux 64 bit | [Release Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||
| Linux arm 64 bit | [Release Linux arm Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||
| macOS | [Release macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||
|
||||
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
|
||||
omitBodyDuringUpdate: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
@ -102,8 +111,8 @@ jobs:
|
||||
|
||||
- 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 -p:IncludeNativeLibrariesForSelfExtract=true
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -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 -p:IncludeNativeLibrariesForSelfExtract=true
|
||||
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
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -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
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.platform.os == 'windows-latest'
|
||||
@ -176,7 +185,16 @@ jobs:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||
body: |
|
||||
# Regular builds:
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
||||
|
||||
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
@ -243,7 +261,16 @@ jobs:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||
body: |
|
||||
# Regular builds:
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
|
||||
| Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
|
||||
| Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
|
||||
| Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
|
||||
|
||||
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -175,3 +175,6 @@ PublishProfiles/
|
||||
|
||||
# Glade backup files
|
||||
*.glade~
|
||||
|
||||
# Ignore MacOS Attribute Files
|
||||
._*
|
||||
|
@ -38,7 +38,7 @@
|
||||
<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.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="Gommon" Version="2.6.6" />
|
||||
<PackageVersion Include="Gommon" Version="2.6.8" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
|
@ -29,7 +29,7 @@
|
||||
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017.
|
||||
Ryujinx is available on Github under the <a href="https://github.com/GreemDev/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
Ryujinx is available on GitHub under the <a href="https://github.com/GreemDev/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
<br />
|
||||
</p>
|
||||
<p align="center">
|
||||
|
@ -14,7 +14,7 @@ if [ -z "$RYUJINX_BIN" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
|
||||
COMMAND="env LANG=C.UTF-8 DOTNET_EnableAlternateStackCheck=1"
|
||||
|
||||
if command -v gamemoderun > /dev/null 2>&1; then
|
||||
COMMAND="$COMMAND gamemoderun"
|
||||
|
@ -40,11 +40,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.1</string>
|
||||
<string>1.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.1.0</string>
|
||||
<string>1.2.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
|
Binary file not shown.
@ -17,7 +17,7 @@ error_handler() {
|
||||
set the button_pressed to the button returned of the result
|
||||
|
||||
if the button_pressed is \"Open Download Page\" then
|
||||
open location \"https://ryujinx.org/download\"
|
||||
open location \"https://ryujinx.app/download\"
|
||||
end if
|
||||
"""
|
||||
|
||||
@ -54,4 +54,4 @@ if [ "$#" -le 3 ]; then
|
||||
open -a "$INSTALL_DIRECTORY"
|
||||
else
|
||||
open -a "$INSTALL_DIRECTORY" --args "${APP_ARGUMENTS[@]}"
|
||||
fi
|
||||
fi
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.2 MiB |
61
distribution/misc/macOS.svg
Normal file
61
distribution/misc/macOS.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 48 KiB |
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -36,9 +36,9 @@ namespace ARMeilleure.Common
|
||||
/// </summary>
|
||||
/// <param name="address">Guest address</param>
|
||||
/// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns>
|
||||
public int GetValue(ulong address)
|
||||
public long GetValue(ulong address)
|
||||
{
|
||||
return (int)((address & Mask) >> Index);
|
||||
return (long)((address & Mask) >> Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ namespace ARMeilleure.Instructions
|
||||
EmitSetTpidrEl0(context);
|
||||
return;
|
||||
case 0b11_011_1101_0000_101:
|
||||
EmitGetTpidr2El0(context);
|
||||
EmitSetTpidr2El0(context);
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -291,5 +291,16 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), value);
|
||||
}
|
||||
|
||||
private static void EmitSetTpidr2El0(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand value = GetIntOrZR(context, op.Rt);
|
||||
|
||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||
|
||||
context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidr2El0Offset())), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 6992; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 6997; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,6 +1,8 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||
{
|
||||
public class JoyconConfigControllerStick<TButton, TStick> where TButton : unmanaged where TStick : unmanaged
|
||||
public class JoyconConfigControllerStick<TButton, TStick>
|
||||
where TButton : unmanaged
|
||||
where TStick : unmanaged
|
||||
{
|
||||
public TStick Joystick { get; set; }
|
||||
public bool InvertStickX { get; set; }
|
||||
|
@ -2,7 +2,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
public class KeyboardHotkeys
|
||||
{
|
||||
public Key ToggleVsync { get; set; }
|
||||
public Key ToggleVSyncMode { get; set; }
|
||||
public Key Screenshot { get; set; }
|
||||
public Key ShowUI { get; set; }
|
||||
public Key Pause { get; set; }
|
||||
@ -11,5 +11,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||
public Key ResScaleDown { get; set; }
|
||||
public Key VolumeUp { get; set; }
|
||||
public Key VolumeDown { get; set; }
|
||||
public Key CustomVSyncIntervalIncrement { get; set; }
|
||||
public Key CustomVSyncIntervalDecrement { get; set; }
|
||||
}
|
||||
}
|
||||
|
9
src/Ryujinx.Common/Configuration/VSyncMode.cs
Normal file
9
src/Ryujinx.Common/Configuration/VSyncMode.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum VSyncMode
|
||||
{
|
||||
Switch,
|
||||
Unbounded,
|
||||
Custom
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -238,7 +238,7 @@ namespace ARMeilleure.Common
|
||||
{
|
||||
TEntry* page = GetPage(address);
|
||||
|
||||
int index = Levels[^1].GetValue(address);
|
||||
long index = Levels[^1].GetValue(address);
|
||||
|
||||
EnsureMapped((IntPtr)(page + index));
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
|
||||
void SetSize(int width, int height);
|
||||
|
||||
void ChangeVSyncMode(bool vsyncEnabled);
|
||||
void ChangeVSyncMode(VSyncMode vSyncMode);
|
||||
|
||||
void SetAntiAliasing(AntiAliasing antialiasing);
|
||||
void SetScalingFilter(ScalingFilter type);
|
||||
|
@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
_impl.Window.SetSize(width, height);
|
||||
}
|
||||
|
||||
public void ChangeVSyncMode(bool vsyncEnabled) { }
|
||||
public void ChangeVSyncMode(VSyncMode vSyncMode) { }
|
||||
|
||||
public void SetAntiAliasing(AntiAliasing effect) { }
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
9
src/Ryujinx.Graphics.GAL/VSyncMode.cs
Normal file
9
src/Ryujinx.Graphics.GAL/VSyncMode.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public enum VSyncMode
|
||||
{
|
||||
Switch,
|
||||
Unbounded,
|
||||
Custom
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
|
||||
}
|
||||
|
||||
public void ChangeVSyncMode(bool vsyncEnabled) { }
|
||||
public void ChangeVSyncMode(VSyncMode vSyncMode) { }
|
||||
|
||||
public void SetSize(int width, int height)
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
@ -182,6 +182,16 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Prevent the sum of descriptors from exceeding MaxPushDescriptors
|
||||
int totalDescriptors = 0;
|
||||
foreach (ResourceDescriptor desc in layout.Sets.First().Descriptors)
|
||||
{
|
||||
if (!reserved.Contains(desc.Binding))
|
||||
totalDescriptors += desc.Count;
|
||||
}
|
||||
if (totalDescriptors > gd.Capabilities.MaxPushDescriptors)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private int _width;
|
||||
private int _height;
|
||||
private bool _vsyncEnabled;
|
||||
private VSyncMode _vSyncMode;
|
||||
private bool _swapchainIsDirty;
|
||||
private VkFormat _format;
|
||||
private AntiAliasing _currentAntiAliasing;
|
||||
@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ImageArrayLayers = 1,
|
||||
PreTransform = capabilities.CurrentTransform,
|
||||
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
|
||||
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
||||
PresentMode = ChooseSwapPresentMode(presentModes, _vSyncMode),
|
||||
Clipped = true,
|
||||
};
|
||||
|
||||
@ -279,9 +279,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, bool vsyncEnabled)
|
||||
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, VSyncMode vSyncMode)
|
||||
{
|
||||
if (!vsyncEnabled && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr))
|
||||
if (vSyncMode == VSyncMode.Unbounded && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr))
|
||||
{
|
||||
return PresentModeKHR.ImmediateKhr;
|
||||
}
|
||||
@ -634,9 +634,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_swapchainIsDirty = true;
|
||||
}
|
||||
|
||||
public override void ChangeVSyncMode(bool vsyncEnabled)
|
||||
public override void ChangeVSyncMode(VSyncMode vSyncMode)
|
||||
{
|
||||
_vsyncEnabled = vsyncEnabled;
|
||||
_vSyncMode = vSyncMode;
|
||||
//present mode may change, so mark the swapchain for recreation
|
||||
_swapchainIsDirty = true;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
public abstract void Dispose();
|
||||
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
|
||||
public abstract void SetSize(int width, int height);
|
||||
public abstract void ChangeVSyncMode(bool vsyncEnabled);
|
||||
public abstract void ChangeVSyncMode(VSyncMode vSyncMode);
|
||||
public abstract void SetAntiAliasing(AntiAliasing effect);
|
||||
public abstract void SetScalingFilter(ScalingFilter scalerType);
|
||||
public abstract void SetScalingFilterLevel(float scale);
|
||||
|
@ -6,6 +6,7 @@
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
|
||||
<IsRoslynComponent>true</IsRoslynComponent>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -21,6 +21,7 @@ using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Path = System.IO.Path;
|
||||
|
||||
namespace Ryujinx.HLE.FileSystem
|
||||
@ -474,6 +475,74 @@ namespace Ryujinx.HLE.FileSystem
|
||||
FinishInstallation(temporaryDirectory, registeredDirectory);
|
||||
}
|
||||
|
||||
public void InstallKeys(string keysSource, string installDirectory)
|
||||
{
|
||||
if (Directory.Exists(keysSource))
|
||||
{
|
||||
foreach (var filePath in Directory.EnumerateFiles(keysSource, "*.keys"))
|
||||
{
|
||||
VerifyKeysFile(filePath);
|
||||
File.Copy(filePath, Path.Combine(installDirectory, Path.GetFileName(filePath)), true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!File.Exists(keysSource))
|
||||
{
|
||||
throw new FileNotFoundException("Keys file does not exist.");
|
||||
}
|
||||
|
||||
FileInfo info = new(keysSource);
|
||||
|
||||
using FileStream file = File.OpenRead(keysSource);
|
||||
|
||||
switch (info.Extension)
|
||||
{
|
||||
case ".zip":
|
||||
using (ZipArchive archive = ZipFile.OpenRead(keysSource))
|
||||
{
|
||||
InstallKeysFromZip(archive, installDirectory);
|
||||
}
|
||||
break;
|
||||
case ".keys":
|
||||
VerifyKeysFile(keysSource);
|
||||
File.Copy(keysSource, Path.Combine(installDirectory, info.Name), true);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidFirmwarePackageException("Input file is not a valid key package");
|
||||
}
|
||||
}
|
||||
|
||||
private void InstallKeysFromZip(ZipArchive archive, string installDirectory)
|
||||
{
|
||||
string temporaryDirectory = Path.Combine(installDirectory, "temp");
|
||||
if (Directory.Exists(temporaryDirectory))
|
||||
{
|
||||
Directory.Delete(temporaryDirectory, true);
|
||||
}
|
||||
Directory.CreateDirectory(temporaryDirectory);
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string extractDestination = Path.Combine(temporaryDirectory, entry.Name);
|
||||
entry.ExtractToFile(extractDestination, overwrite: true);
|
||||
try
|
||||
{
|
||||
VerifyKeysFile(extractDestination);
|
||||
File.Move(extractDestination, Path.Combine(installDirectory, entry.Name), true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Directory.Delete(temporaryDirectory, true);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
Directory.Delete(temporaryDirectory, true);
|
||||
}
|
||||
|
||||
private void FinishInstallation(string temporaryDirectory, string registeredDirectory)
|
||||
{
|
||||
if (Directory.Exists(registeredDirectory))
|
||||
@ -947,5 +1016,70 @@ namespace Ryujinx.HLE.FileSystem
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void VerifyKeysFile(string filePath)
|
||||
{
|
||||
// Verify the keys file format refers to https://github.com/Thealexbarney/LibHac/blob/master/KEYS.md
|
||||
string genericPattern = @"^[a-z0-9_]+ = [a-z0-9]+$";
|
||||
string titlePattern = @"^[a-z0-9]{32} = [a-z0-9]{32}$";
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
// Read all lines from the file
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
string[] lines = File.ReadAllLines(filePath);
|
||||
|
||||
bool verified = false;
|
||||
switch (fileName)
|
||||
{
|
||||
case "prod.keys":
|
||||
verified = verifyKeys(lines, genericPattern);
|
||||
break;
|
||||
case "title.keys":
|
||||
verified = verifyKeys(lines, titlePattern);
|
||||
break;
|
||||
case "console.keys":
|
||||
verified = verifyKeys(lines, genericPattern);
|
||||
break;
|
||||
case "dev.keys":
|
||||
verified = verifyKeys(lines, genericPattern);
|
||||
break;
|
||||
default:
|
||||
throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported.");
|
||||
}
|
||||
if (!verified)
|
||||
{
|
||||
throw new FormatException($"Invalid \"{filePath}\" file format.");
|
||||
}
|
||||
} else
|
||||
{
|
||||
throw new FileNotFoundException($"Keys file not found at \"{filePath}\".");
|
||||
}
|
||||
}
|
||||
|
||||
private bool verifyKeys(string[] lines, string regex)
|
||||
{
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (!Regex.IsMatch(line, regex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool AreKeysAlredyPresent(string pathToCheck)
|
||||
{
|
||||
string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" };
|
||||
foreach (var file in fileNames)
|
||||
{
|
||||
if (File.Exists(Path.Combine(pathToCheck, file)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,9 +223,10 @@ namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
KeySet ??= KeySet.CreateDefaultKeySet();
|
||||
|
||||
string keyFile = null;
|
||||
string prodKeyFile = null;
|
||||
string titleKeyFile = null;
|
||||
string consoleKeyFile = null;
|
||||
string devKeyFile = null;
|
||||
|
||||
if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile)
|
||||
{
|
||||
@ -236,13 +237,14 @@ namespace Ryujinx.HLE.FileSystem
|
||||
|
||||
void LoadSetAtPath(string basePath)
|
||||
{
|
||||
string localKeyFile = Path.Combine(basePath, "prod.keys");
|
||||
string localProdKeyFile = Path.Combine(basePath, "prod.keys");
|
||||
string localTitleKeyFile = Path.Combine(basePath, "title.keys");
|
||||
string localConsoleKeyFile = Path.Combine(basePath, "console.keys");
|
||||
string localDevKeyFile = Path.Combine(basePath, "dev.keys");
|
||||
|
||||
if (File.Exists(localKeyFile))
|
||||
if (File.Exists(localProdKeyFile))
|
||||
{
|
||||
keyFile = localKeyFile;
|
||||
prodKeyFile = localProdKeyFile;
|
||||
}
|
||||
|
||||
if (File.Exists(localTitleKeyFile))
|
||||
@ -254,9 +256,14 @@ namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
consoleKeyFile = localConsoleKeyFile;
|
||||
}
|
||||
|
||||
if (File.Exists(localDevKeyFile))
|
||||
{
|
||||
devKeyFile = localDevKeyFile;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalKeyReader.ReadKeyFile(KeySet, keyFile, titleKeyFile, consoleKeyFile, null);
|
||||
ExternalKeyReader.ReadKeyFile(KeySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, null);
|
||||
}
|
||||
|
||||
public void ImportTickets(IFileSystem fs)
|
||||
|
@ -9,6 +9,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.HLE.UI;
|
||||
using System;
|
||||
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
||||
|
||||
namespace Ryujinx.HLE
|
||||
{
|
||||
@ -84,9 +85,14 @@ namespace Ryujinx.HLE
|
||||
internal readonly RegionCode Region;
|
||||
|
||||
/// <summary>
|
||||
/// Control the initial state of the vertical sync in the SurfaceFlinger service.
|
||||
/// Control the initial state of the present interval in the SurfaceFlinger service (previously Vsync).
|
||||
/// </summary>
|
||||
internal readonly bool EnableVsync;
|
||||
internal readonly VSyncMode VSyncMode;
|
||||
|
||||
/// <summary>
|
||||
/// Control the custom VSync interval, if enabled and active.
|
||||
/// </summary>
|
||||
internal readonly int CustomVSyncInterval;
|
||||
|
||||
/// <summary>
|
||||
/// Control the initial state of the docked mode.
|
||||
@ -195,7 +201,7 @@ namespace Ryujinx.HLE
|
||||
IHostUIHandler hostUIHandler,
|
||||
SystemLanguage systemLanguage,
|
||||
RegionCode region,
|
||||
bool enableVsync,
|
||||
VSyncMode vSyncMode,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableInternetAccess,
|
||||
@ -212,7 +218,8 @@ namespace Ryujinx.HLE
|
||||
MultiplayerMode multiplayerMode,
|
||||
bool multiplayerDisableP2p,
|
||||
string multiplayerLdnPassphrase,
|
||||
string multiplayerLdnServer)
|
||||
string multiplayerLdnServer,
|
||||
int customVSyncInterval)
|
||||
{
|
||||
VirtualFileSystem = virtualFileSystem;
|
||||
LibHacHorizonManager = libHacHorizonManager;
|
||||
@ -225,7 +232,8 @@ namespace Ryujinx.HLE
|
||||
HostUIHandler = hostUIHandler;
|
||||
SystemLanguage = systemLanguage;
|
||||
Region = region;
|
||||
EnableVsync = enableVsync;
|
||||
VSyncMode = vSyncMode;
|
||||
CustomVSyncInterval = customVSyncInterval;
|
||||
EnableDockedMode = enableDockedMode;
|
||||
EnablePtc = enablePtc;
|
||||
EnableInternetAccess = enableInternetAccess;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Applets.Browser;
|
||||
using Ryujinx.HLE.HOS.Applets.Cabinet;
|
||||
using Ryujinx.HLE.HOS.Applets.Dummy;
|
||||
using Ryujinx.HLE.HOS.Applets.Error;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||
@ -23,14 +24,14 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
case AppletId.SoftwareKeyboard:
|
||||
return new SoftwareKeyboardApplet(system);
|
||||
case AppletId.LibAppletWeb:
|
||||
return new BrowserApplet(system);
|
||||
case AppletId.LibAppletShop:
|
||||
return new BrowserApplet(system);
|
||||
case AppletId.LibAppletOff:
|
||||
return new BrowserApplet(system);
|
||||
return new BrowserApplet();
|
||||
case AppletId.MiiEdit:
|
||||
Logger.Warning?.Print(LogClass.Application, $"Please use the MiiEdit inside File/Open Applet");
|
||||
return new DummyApplet(system);
|
||||
case AppletId.Cabinet:
|
||||
return new CabinetApplet(system);
|
||||
}
|
||||
|
||||
Logger.Warning?.Print(LogClass.Application, $"Applet {applet} not implemented!");
|
||||
|
@ -18,13 +18,6 @@ namespace Ryujinx.HLE.HOS.Applets.Browser
|
||||
private List<BrowserArgument> _arguments;
|
||||
private ShimKind _shimKind;
|
||||
|
||||
public BrowserApplet(Horizon system) { }
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession)
|
||||
{
|
||||
_normalSession = normalSession;
|
||||
|
182
src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs
Normal file
182
src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs
Normal file
@ -0,0 +1,182 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
||||
using Ryujinx.HLE.HOS.Services.Hid;
|
||||
using Ryujinx.HLE.HOS.Services.Nfc.Nfp;
|
||||
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Applets.Cabinet
|
||||
{
|
||||
internal unsafe class CabinetApplet : IApplet
|
||||
{
|
||||
private readonly Horizon _system;
|
||||
private AppletSession _normalSession;
|
||||
|
||||
public event EventHandler AppletStateChanged;
|
||||
|
||||
public CabinetApplet(Horizon system)
|
||||
{
|
||||
_system = system;
|
||||
}
|
||||
|
||||
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession)
|
||||
{
|
||||
_normalSession = normalSession;
|
||||
|
||||
byte[] launchParams = _normalSession.Pop();
|
||||
byte[] startParamBytes = _normalSession.Pop();
|
||||
|
||||
StartParamForAmiiboSettings startParam = IApplet.ReadStruct<StartParamForAmiiboSettings>(startParamBytes);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceAm, $"CabinetApplet Start Type: {startParam.Type}");
|
||||
|
||||
switch (startParam.Type)
|
||||
{
|
||||
case 0:
|
||||
StartNicknameAndOwnerSettings(ref startParam);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
StartFormatter(ref startParam);
|
||||
break;
|
||||
default:
|
||||
Logger.Error?.Print(LogClass.ServiceAm, $"Unknown AmiiboSettings type: {startParam.Type}");
|
||||
break;
|
||||
}
|
||||
|
||||
// Prepare the response
|
||||
ReturnValueForAmiiboSettings returnValue = new()
|
||||
{
|
||||
AmiiboSettingsReturnFlag = (byte)AmiiboSettingsReturnFlag.HasRegisterInfo,
|
||||
DeviceHandle = new DeviceHandle
|
||||
{
|
||||
Handle = 0 // Dummy device handle
|
||||
},
|
||||
RegisterInfo = startParam.RegisterInfo
|
||||
};
|
||||
|
||||
// Push the response
|
||||
_normalSession.Push(BuildResponse(returnValue));
|
||||
AppletStateChanged?.Invoke(this, null);
|
||||
|
||||
_system.ReturnFocus();
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
_system.Device.System.NfpDevices.RemoveAt(0);
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
private void StartFormatter(ref StartParamForAmiiboSettings startParam)
|
||||
{
|
||||
// Initialize RegisterInfo
|
||||
startParam.RegisterInfo = new RegisterInfo();
|
||||
}
|
||||
|
||||
private void StartNicknameAndOwnerSettings(ref StartParamForAmiiboSettings startParam)
|
||||
{
|
||||
_system.Device.UIHandler.DisplayCabinetDialog(out string newName);
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(newName);
|
||||
Array41<byte> nickName = new Array41<byte>();
|
||||
nameBytes.CopyTo(nickName.AsSpan());
|
||||
startParam.RegisterInfo.Nickname = nickName;
|
||||
NfpDevice devicePlayer1 = new()
|
||||
{
|
||||
NpadIdType = NpadIdType.Player1,
|
||||
Handle = HidUtils.GetIndexFromNpadIdType(NpadIdType.Player1),
|
||||
State = NfpDeviceState.SearchingForTag,
|
||||
};
|
||||
_system.Device.System.NfpDevices.Add(devicePlayer1);
|
||||
_system.Device.UIHandler.DisplayCabinetMessageDialog();
|
||||
string amiiboId = string.Empty;
|
||||
bool scanned = false;
|
||||
while (!scanned)
|
||||
{
|
||||
for (int i = 0; i < _system.Device.System.NfpDevices.Count; i++)
|
||||
{
|
||||
if (_system.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound)
|
||||
{
|
||||
amiiboId = _system.Device.System.NfpDevices[i].AmiiboId;
|
||||
scanned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
VirtualAmiibo.UpdateNickName(amiiboId, newName);
|
||||
}
|
||||
|
||||
private static byte[] BuildResponse(ReturnValueForAmiiboSettings returnValue)
|
||||
{
|
||||
int size = Unsafe.SizeOf<ReturnValueForAmiiboSettings>();
|
||||
byte[] bytes = new byte[size];
|
||||
|
||||
fixed (byte* bytesPtr = bytes)
|
||||
{
|
||||
Unsafe.Write(bytesPtr, returnValue);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#region Structs
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public unsafe struct TagInfo
|
||||
{
|
||||
public fixed byte Data[0x58];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public unsafe struct StartParamForAmiiboSettings
|
||||
{
|
||||
public byte ZeroValue; // Left at zero by sdknso
|
||||
public byte Type;
|
||||
public byte Flags;
|
||||
public byte AmiiboSettingsStartParamOffset28;
|
||||
public ulong AmiiboSettingsStartParam0;
|
||||
|
||||
public TagInfo TagInfo; // Only enabled when flags bit 1 is set
|
||||
public RegisterInfo RegisterInfo; // Only enabled when flags bit 2 is set
|
||||
|
||||
public fixed byte StartParamExtraData[0x20];
|
||||
|
||||
public fixed byte Reserved[0x24];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public unsafe struct ReturnValueForAmiiboSettings
|
||||
{
|
||||
public byte AmiiboSettingsReturnFlag;
|
||||
private byte Padding1;
|
||||
private byte Padding2;
|
||||
private byte Padding3;
|
||||
public DeviceHandle DeviceHandle;
|
||||
public TagInfo TagInfo;
|
||||
public RegisterInfo RegisterInfo;
|
||||
public fixed byte IgnoredBySdknso[0x24];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct DeviceHandle
|
||||
{
|
||||
public ulong Handle;
|
||||
}
|
||||
|
||||
public enum AmiiboSettingsReturnFlag : byte
|
||||
{
|
||||
Cancel = 0,
|
||||
HasTagInfo = 2,
|
||||
HasRegisterInfo = 4,
|
||||
HasTagInfoAndRegisterInfo = 6
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -117,11 +117,6 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
private static byte[] BuildResponse(ControllerSupportResultInfo result)
|
||||
{
|
||||
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||
|
@ -11,11 +11,14 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy
|
||||
{
|
||||
private readonly Horizon _system;
|
||||
private AppletSession _normalSession;
|
||||
|
||||
public event EventHandler AppletStateChanged;
|
||||
|
||||
public DummyApplet(Horizon system)
|
||||
{
|
||||
_system = system;
|
||||
}
|
||||
|
||||
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession)
|
||||
{
|
||||
_normalSession = normalSession;
|
||||
@ -24,10 +27,7 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy
|
||||
_system.ReturnFocus();
|
||||
return ResultCode.Success;
|
||||
}
|
||||
private static T ReadStruct<T>(byte[] data) where T : struct
|
||||
{
|
||||
return MemoryMarshal.Read<T>(data.AsSpan());
|
||||
}
|
||||
|
||||
private static byte[] BuildResponse()
|
||||
{
|
||||
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||
@ -35,9 +35,5 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy
|
||||
writer.Write((ulong)ResultCode.Success);
|
||||
return stream.ToArray();
|
||||
}
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,10 +203,5 @@ namespace Ryujinx.HLE.HOS.Applets.Error
|
||||
_horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber} (Details)", "\n" + detailsText, buttons.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
ResultCode Start(AppletSession normalSession,
|
||||
AppletSession interactiveSession);
|
||||
|
||||
ResultCode GetResult();
|
||||
ResultCode GetResult() => ResultCode.Success;
|
||||
|
||||
bool DrawTo(RenderingSurfaceInfo surfaceInfo, IVirtualMemoryManager destination, ulong position) => false;
|
||||
|
||||
|
@ -37,11 +37,6 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
private byte[] BuildResponse()
|
||||
{
|
||||
UserProfile currentUser = _system.AccountManager.LastOpenedUser;
|
||||
|
@ -144,11 +144,6 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||
}
|
||||
}
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
private bool IsKeyboardActive()
|
||||
{
|
||||
return _backgroundState >= InlineKeyboardState.Appearing && _backgroundState < InlineKeyboardState.Disappearing;
|
||||
|
@ -2,7 +2,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps a type in a class so it gets stored in the GC managed heap. This is used as communication mechanism
|
||||
/// between classed that need to be disposed and, thus, can't share their references.
|
||||
/// between classes that need to be disposed and, thus, can't share their references.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The internal type.</typeparam>
|
||||
class TRef<T>
|
||||
|
@ -5,5 +5,23 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
|
||||
class IServiceCreator : IpcService
|
||||
{
|
||||
public IServiceCreator(ServiceCtx context) { }
|
||||
|
||||
[CommandCmif(0)]
|
||||
// CreateNetworkService(pid, u64, u32) -> object<nn::ldn::detail::ISfService>
|
||||
public ResultCode CreateNetworkService(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISfService(context));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(8)]
|
||||
// CreateNetworkServiceMonitor(pid, u64) -> object<nn::ldn::detail::ISfServiceMonitor>
|
||||
public ResultCode CreateNetworkServiceMonitor(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISfServiceMonitor(context));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
54
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs
Normal file
54
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
|
||||
{
|
||||
class ISfService : IpcService
|
||||
{
|
||||
public ISfService(ServiceCtx context) { }
|
||||
|
||||
[CommandCmif(0)]
|
||||
// Initialize()
|
||||
public ResultCode Initialize(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write(0);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(768)]
|
||||
// CreateGroup(buffer<nn::lp2p::GroupInfo, 0x31)
|
||||
public ResultCode CreateGroup(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(776)]
|
||||
// DestroyGroup()
|
||||
public ResultCode DestroyGroup(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(1536)]
|
||||
// SendToOtherGroup(nn::lp2p::MacAddress, nn::lp2p::GroupId, s16, s16, u32, buffer<unknown, 0x21>)
|
||||
public ResultCode SendToOtherGroup(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(1544)]
|
||||
// RecvFromOtherGroup(u32, buffer<unknown, 0x22>) -> (nn::lp2p::MacAddress, u16, s16, u32, s32)
|
||||
public ResultCode RecvFromOtherGroup(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
86
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs
Normal file
86
src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Ipc;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
|
||||
{
|
||||
class ISfServiceMonitor : IpcService
|
||||
{
|
||||
private readonly KEvent _stateChangeEvent;
|
||||
private readonly KEvent _jointEvent;
|
||||
private int _stateChangeEventHandle = 0;
|
||||
private int _jointEventHandle = 0;
|
||||
|
||||
public ISfServiceMonitor(ServiceCtx context)
|
||||
{
|
||||
_stateChangeEvent = new KEvent(context.Device.System.KernelContext);
|
||||
_jointEvent = new KEvent(context.Device.System.KernelContext);
|
||||
}
|
||||
|
||||
[CommandCmif(0)]
|
||||
// Initialize()
|
||||
public ResultCode Initialize(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write(0);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(256)]
|
||||
// AttachNetworkInterfaceStateChangeEvent() -> handle<copy>
|
||||
public ResultCode AttachNetworkInterfaceStateChangeEvent(ServiceCtx context)
|
||||
{
|
||||
if (context.Process.HandleTable.GenerateHandle(_stateChangeEvent.ReadableEvent, out _stateChangeEventHandle) != Result.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangeEventHandle);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(288)]
|
||||
// GetGroupInfo(buffer<nn::lp2p::GroupInfo, 0x32>)
|
||||
public ResultCode GetGroupInfo(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(296)]
|
||||
// GetGroupInfo2(buffer<nn::lp2p::GroupInfo, 0x32>, buffer<nn::lp2p::GroupInfo, 0x31>)
|
||||
public ResultCode GetGroupInfo2(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(312)]
|
||||
// GetIpConfig(buffer<unknown<0x100>, 0x1a>)
|
||||
public ResultCode GetIpConfig(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceLdn);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(328)]
|
||||
// AttachNetworkInterfaceStateChangeEvent() -> handle<copy>
|
||||
public ResultCode AttachJoinEvent(ServiceCtx context)
|
||||
{
|
||||
if (context.Process.HandleTable.GenerateHandle(_jointEvent.ReadableEvent, out _jointEventHandle) != Result.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_jointEventHandle);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
using Gommon;
|
||||
using Humanizer;
|
||||
using NetCoreServer;
|
||||
using Open.Nat;
|
||||
using Ryujinx.Common.Logging;
|
||||
@ -153,7 +155,10 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy
|
||||
|
||||
if (_publicPort != 0)
|
||||
{
|
||||
_ = Task.Delay(PortLeaseRenew * 1000, _disposedCancellation.Token).ContinueWith((task) => Task.Run(RefreshLease));
|
||||
_ = Executor.ExecuteAfterDelayAsync(
|
||||
PortLeaseRenew.Seconds(),
|
||||
_disposedCancellation.Token,
|
||||
RefreshLease);
|
||||
}
|
||||
|
||||
_natDevice = device;
|
||||
@ -257,7 +262,10 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy
|
||||
|
||||
}
|
||||
|
||||
_ = Task.Delay(PortLeaseRenew, _disposedCancellation.Token).ContinueWith((task) => Task.Run(RefreshLease));
|
||||
_ = Executor.ExecuteAfterDelayAsync(
|
||||
PortLeaseRenew.Milliseconds(),
|
||||
_disposedCancellation.Token,
|
||||
RefreshLease);
|
||||
}
|
||||
|
||||
public bool TryRegisterUser(P2pProxySession session, ExternalProxyConfig config)
|
||||
|
@ -93,6 +93,13 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
||||
return registerInfo;
|
||||
}
|
||||
|
||||
public static void UpdateNickName(string amiiboId, string newNickName)
|
||||
{
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
virtualAmiiboFile.NickName = newNickName;
|
||||
SaveAmiiboFile(virtualAmiiboFile);
|
||||
}
|
||||
|
||||
public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
|
||||
{
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
@ -10,13 +10,12 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
{
|
||||
class SurfaceFlinger : IConsumerListener, IDisposable
|
||||
{
|
||||
private const int TargetFps = 60;
|
||||
|
||||
private readonly Switch _device;
|
||||
|
||||
private readonly Dictionary<long, Layer> _layers;
|
||||
@ -32,6 +31,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
private readonly long _spinTicks;
|
||||
private readonly long _1msTicks;
|
||||
|
||||
private VSyncMode _vSyncMode;
|
||||
private long _targetVSyncInterval;
|
||||
|
||||
private int _swapInterval;
|
||||
private int _swapIntervalDelay;
|
||||
|
||||
@ -88,7 +90,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
}
|
||||
else
|
||||
{
|
||||
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
||||
_ticksPerFrame = Stopwatch.Frequency / _device.TargetVSyncInterval;
|
||||
_targetVSyncInterval = _device.TargetVSyncInterval;
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,15 +373,20 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
|
||||
if (acquireStatus == Status.Success)
|
||||
{
|
||||
// If device vsync is disabled, reflect the change.
|
||||
if (!_device.EnableDeviceVsync)
|
||||
if (_device.VSyncMode == VSyncMode.Unbounded)
|
||||
{
|
||||
if (_swapInterval != 0)
|
||||
{
|
||||
UpdateSwapInterval(0);
|
||||
_vSyncMode = _device.VSyncMode;
|
||||
}
|
||||
}
|
||||
else if (item.SwapInterval != _swapInterval)
|
||||
else if (_device.VSyncMode != _vSyncMode)
|
||||
{
|
||||
UpdateSwapInterval(_device.VSyncMode == VSyncMode.Unbounded ? 0 : item.SwapInterval);
|
||||
_vSyncMode = _device.VSyncMode;
|
||||
}
|
||||
else if (item.SwapInterval != _swapInterval || _device.TargetVSyncInterval != _targetVSyncInterval)
|
||||
{
|
||||
UpdateSwapInterval(item.SwapInterval);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
||||
{
|
||||
private static readonly TitleUpdateMetadataJsonSerializerContext _applicationSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
public static ProcessResult Load(this Nca nca, Switch device, Nca patchNca, Nca controlNca)
|
||||
public static ProcessResult Load(this Nca nca, Switch device, Nca patchNca, Nca controlNca, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||
{
|
||||
// Extract RomFs and ExeFs from NCA.
|
||||
IStorage romFs = nca.GetRomFs(device, patchNca);
|
||||
@ -55,6 +55,10 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
||||
{
|
||||
nacpData = controlNca.GetNacp(device);
|
||||
}
|
||||
else if (customNacpData != null) // if the Application doesn't provide a nacp file but the Application provides an override, use the provided nacp override
|
||||
{
|
||||
nacpData = (BlitStruct<ApplicationControlProperty>)customNacpData;
|
||||
}
|
||||
|
||||
/* TODO: Rework this since it's wrong and doesn't work as it takes the DisplayVersion from a "potential" non-existent update.
|
||||
|
||||
|
@ -98,12 +98,12 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool LoadNca(string path)
|
||||
public bool LoadNca(string path, BlitStruct<ApplicationControlProperty>? customNacpData = null)
|
||||
{
|
||||
FileStream file = new(path, FileMode.Open, FileAccess.Read);
|
||||
Nca nca = new(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false));
|
||||
|
||||
ProcessResult processResult = nca.Load(_device, null, null);
|
||||
ProcessResult processResult = nca.Load(_device, null, null, customNacpData);
|
||||
|
||||
if (processResult.ProcessId != 0 && _processesByPid.TryAdd(processResult.ProcessId, processResult))
|
||||
{
|
||||
|
@ -84,12 +84,19 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isFirmware = ProgramId is >= 0x0100000000000819 and <= 0x010000000000081C;
|
||||
bool isFirmwareApplication = ProgramId <= 0x0100000000007FFF;
|
||||
|
||||
string name = !isFirmware
|
||||
? (isFirmwareApplication ? "Firmware Application " : "") + (!string.IsNullOrWhiteSpace(Name) ? Name : "<Unknown Name>")
|
||||
: "Firmware";
|
||||
|
||||
// TODO: LibHac npdm currently doesn't support version field.
|
||||
string version = ProgramId > 0x0100000000007FFF
|
||||
? DisplayVersion
|
||||
string version = !isFirmware
|
||||
? (!string.IsNullOrWhiteSpace(DisplayVersion) ? DisplayVersion : "<Unknown Version>")
|
||||
: device.System.ContentManager.GetCurrentFirmwareVersion()?.VersionString ?? "?";
|
||||
|
||||
Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {Name} v{version} [{ProgramIdText}] [{(Is64Bit ? "64-bit" : "32-bit")}]");
|
||||
Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {name} v{version} [{ProgramIdText}] [{(Is64Bit ? "64-bit" : "32-bit")}]");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
37
src/Ryujinx.HLE/StructHelpers.cs
Normal file
37
src/Ryujinx.HLE/StructHelpers.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Ns;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.HLE
|
||||
{
|
||||
public static class StructHelpers
|
||||
{
|
||||
public static BlitStruct<ApplicationControlProperty> CreateCustomNacpData(string name, string version)
|
||||
{
|
||||
// https://switchbrew.org/wiki/NACP
|
||||
const int OffsetOfDisplayVersion = 0x3060;
|
||||
|
||||
// https://switchbrew.org/wiki/NACP#ApplicationTitle
|
||||
const int TotalApplicationTitles = 0x10;
|
||||
const int SizeOfApplicationTitle = 0x300;
|
||||
const int OffsetOfApplicationPublisherStrings = 0x200;
|
||||
|
||||
|
||||
var nacpData = new BlitStruct<ApplicationControlProperty>(1);
|
||||
|
||||
// name and publisher buffer
|
||||
// repeat once for each locale (the ApplicationControlProperty has 16 locales)
|
||||
for (int i = 0; i < TotalApplicationTitles; i++)
|
||||
{
|
||||
Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle)..]);
|
||||
"Ryujinx"u8.CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle + OffsetOfApplicationPublisherStrings)..]);
|
||||
}
|
||||
|
||||
// version buffer
|
||||
Encoding.ASCII.GetBytes(version).AsSpan().CopyTo(nacpData.ByteSpan[OffsetOfDisplayVersion..]);
|
||||
|
||||
return nacpData;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Ns;
|
||||
using Ryujinx.Audio.Backends.CompatLayer;
|
||||
using Ryujinx.Audio.Integration;
|
||||
using Ryujinx.Common.Configuration;
|
||||
@ -27,7 +29,11 @@ namespace Ryujinx.HLE
|
||||
public TamperMachine TamperMachine { get; }
|
||||
public IHostUIHandler UIHandler { get; }
|
||||
|
||||
public bool EnableDeviceVsync { get; set; }
|
||||
public VSyncMode VSyncMode { get; set; } = VSyncMode.Switch;
|
||||
public bool CustomVSyncIntervalEnabled { get; set; } = false;
|
||||
public int CustomVSyncInterval { get; set; }
|
||||
|
||||
public long TargetVSyncInterval { get; set; } = 60;
|
||||
|
||||
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
|
||||
|
||||
@ -59,12 +65,14 @@ namespace Ryujinx.HLE
|
||||
System.State.SetLanguage(Configuration.SystemLanguage);
|
||||
System.State.SetRegion(Configuration.Region);
|
||||
|
||||
EnableDeviceVsync = Configuration.EnableVsync;
|
||||
VSyncMode = Configuration.VSyncMode;
|
||||
CustomVSyncInterval = Configuration.CustomVSyncInterval;
|
||||
System.State.DockedMode = Configuration.EnableDockedMode;
|
||||
System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
|
||||
System.EnablePtc = Configuration.EnablePtc;
|
||||
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
|
||||
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
|
||||
UpdateVSyncInterval();
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
@ -75,9 +83,37 @@ namespace Ryujinx.HLE
|
||||
Gpu.GPFifo.DispatchCalls();
|
||||
}
|
||||
|
||||
public void IncrementCustomVSyncInterval()
|
||||
{
|
||||
CustomVSyncInterval += 1;
|
||||
UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
public void DecrementCustomVSyncInterval()
|
||||
{
|
||||
CustomVSyncInterval -= 1;
|
||||
UpdateVSyncInterval();
|
||||
}
|
||||
|
||||
public void UpdateVSyncInterval()
|
||||
{
|
||||
switch (VSyncMode)
|
||||
{
|
||||
case VSyncMode.Custom:
|
||||
TargetVSyncInterval = CustomVSyncInterval;
|
||||
break;
|
||||
case VSyncMode.Switch:
|
||||
TargetVSyncInterval = 60;
|
||||
break;
|
||||
case VSyncMode.Unbounded:
|
||||
TargetVSyncInterval = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile);
|
||||
public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId);
|
||||
public bool LoadNca(string ncaFile) => Processes.LoadNca(ncaFile);
|
||||
public bool LoadNca(string ncaFile, BlitStruct<ApplicationControlProperty>? customNacpData = null) => Processes.LoadNca(ncaFile, customNacpData);
|
||||
public bool LoadNsp(string nspFile, ulong applicationId = 0) => Processes.LoadNsp(nspFile, applicationId);
|
||||
public bool LoadProgram(string fileName) => Processes.LoadNxo(fileName);
|
||||
|
||||
|
@ -24,6 +24,18 @@ namespace Ryujinx.HLE.UI
|
||||
/// <returns>True when OK is pressed, False otherwise.</returns>
|
||||
bool DisplayMessageDialog(ControllerAppletUIArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Displays an Input Dialog box to the user so they can enter the Amiibo's new name
|
||||
/// </summary>
|
||||
/// <param name="userText">Text that the user entered. Set to `null` on internal errors</param>
|
||||
/// <returns>True when OK is pressed, False otherwise. Also returns True on internal errors</returns>
|
||||
bool DisplayCabinetDialog(out string userText);
|
||||
|
||||
/// <summary>
|
||||
/// Displays a Message Dialog box to the user to notify them to scan the Amiibo.
|
||||
/// </summary>
|
||||
void DisplayCabinetMessageDialog();
|
||||
|
||||
/// <summary>
|
||||
/// Tell the UI that we need to transition to another program.
|
||||
/// </summary>
|
||||
|
@ -115,8 +115,11 @@ namespace Ryujinx.Headless.SDL2
|
||||
[Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")]
|
||||
public int FsGlobalAccessLogMode { get; set; }
|
||||
|
||||
[Option("disable-vsync", Required = false, HelpText = "Disables Vertical Sync.")]
|
||||
public bool DisableVSync { get; set; }
|
||||
[Option("vsync-mode", Required = false, Default = VSyncMode.Switch, HelpText = "Sets the emulated VSync mode (Switch, Unbounded, or Custom).")]
|
||||
public VSyncMode VSyncMode { get; set; }
|
||||
|
||||
[Option("custom-refresh-rate", Required = false, Default = 90, HelpText = "Sets the custom refresh rate target value (integer).")]
|
||||
public int CustomVSyncInterval { get; set; }
|
||||
|
||||
[Option("disable-shader-cache", Required = false, HelpText = "Disables Shader cache.")]
|
||||
public bool DisableShaderCache { get; set; }
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CommandLine;
|
||||
using Gommon;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
using Ryujinx.Common;
|
||||
@ -96,8 +97,13 @@ namespace Ryujinx.Headless.SDL2
|
||||
}
|
||||
|
||||
Parser.Default.ParseArguments<Options>(args)
|
||||
.WithParsed(Load)
|
||||
.WithNotParsed(errors => errors.Output());
|
||||
.WithParsed(Load)
|
||||
.WithNotParsed(errors =>
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
||||
|
||||
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
|
||||
});
|
||||
}
|
||||
|
||||
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||
@ -563,7 +569,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
window,
|
||||
options.SystemLanguage,
|
||||
options.SystemRegion,
|
||||
!options.DisableVSync,
|
||||
options.VSyncMode,
|
||||
!options.DisableDockedMode,
|
||||
!options.DisablePTC,
|
||||
options.EnableInternetAccess,
|
||||
@ -579,8 +585,9 @@ namespace Ryujinx.Headless.SDL2
|
||||
options.MultiplayerLanInterfaceId,
|
||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
||||
false,
|
||||
"",
|
||||
"");
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
options.CustomVSyncInterval);
|
||||
|
||||
return new Switch(configuration);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
|
||||
<TieredPGO>true</TieredPGO>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,7 +3,7 @@ using System;
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
class StatusUpdatedEventArgs(
|
||||
bool vSyncEnabled,
|
||||
string vSyncMode,
|
||||
string dockedMode,
|
||||
string aspectRatio,
|
||||
string gameStatus,
|
||||
@ -11,7 +11,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
string gpuName)
|
||||
: EventArgs
|
||||
{
|
||||
public bool VSyncEnabled = vSyncEnabled;
|
||||
public string VSyncMode = vSyncMode;
|
||||
public string DockedMode = dockedMode;
|
||||
public string AspectRatio = aspectRatio;
|
||||
public string GameStatus = gameStatus;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Humanizer;
|
||||
using LibHac.Tools.Fs;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
@ -314,7 +315,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
}
|
||||
|
||||
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
|
||||
Device.EnableDeviceVsync,
|
||||
Device.VSyncMode.ToString(),
|
||||
dockedMode,
|
||||
Device.Configuration.AspectRatio.ToText(),
|
||||
$"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||
@ -485,6 +486,19 @@ namespace Ryujinx.Headless.SDL2
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DisplayCabinetDialog(out string userText)
|
||||
{
|
||||
// SDL2 doesn't support input dialogs
|
||||
userText = "Ryujinx";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void DisplayCabinetMessageDialog()
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, "Cabinet Dialog", "Please scan your Amiibo now.", WindowHandle);
|
||||
}
|
||||
|
||||
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
||||
{
|
||||
if (_ignoreControllerApplet) return false;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,8 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">linux</TargetOS>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<RunSettingsFilePath>$(MSBuildProjectDirectory)\.runsettings</RunSettingsFilePath>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@ -1,5 +1,4 @@
|
||||
using DynamicData;
|
||||
using DynamicData.Kernel;
|
||||
using Gommon;
|
||||
using LibHac;
|
||||
using LibHac.Common;
|
||||
@ -37,14 +36,13 @@ using System.Threading.Tasks;
|
||||
using ContentType = LibHac.Ncm.ContentType;
|
||||
using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
|
||||
using Path = System.IO.Path;
|
||||
using SpanHelpers = LibHac.Common.SpanHelpers;
|
||||
using TimeSpan = System.TimeSpan;
|
||||
|
||||
namespace Ryujinx.UI.App.Common
|
||||
{
|
||||
public class ApplicationLibrary
|
||||
{
|
||||
public static string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
public Language DesiredLanguage { get; set; }
|
||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||
@ -191,12 +189,9 @@ namespace Ryujinx.UI.App.Common
|
||||
}
|
||||
}
|
||||
|
||||
if (isExeFs)
|
||||
{
|
||||
return GetApplicationFromExeFs(pfs, filePath);
|
||||
}
|
||||
|
||||
return null;
|
||||
return isExeFs
|
||||
? GetApplicationFromExeFs(pfs, filePath)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception>
|
||||
@ -512,10 +507,6 @@ namespace Ryujinx.UI.App.Common
|
||||
case ".xci":
|
||||
case ".nsp":
|
||||
{
|
||||
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
|
||||
? IntegrityCheckLevel.ErrorOnInvalid
|
||||
: IntegrityCheckLevel.None;
|
||||
|
||||
using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem);
|
||||
|
||||
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
|
||||
@ -604,7 +595,7 @@ namespace Ryujinx.UI.App.Common
|
||||
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None)
|
||||
.OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read)
|
||||
.ThrowIfFailure();
|
||||
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData),
|
||||
nacpFile.Get.Read(out _, 0, LibHac.Common.SpanHelpers.AsByteSpan(ref controlData),
|
||||
ReadOption.None).ThrowIfFailure();
|
||||
|
||||
var displayVersion = controlData.DisplayVersionString.ToString();
|
||||
@ -827,7 +818,7 @@ namespace Ryujinx.UI.App.Common
|
||||
{
|
||||
_downloadableContents.Edit(it =>
|
||||
{
|
||||
DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, application.IdBase, dlcs);
|
||||
DownloadableContentsHelper.SaveDownloadableContentsJson(application.IdBase, dlcs);
|
||||
|
||||
it.Remove(it.Items.Where(item => item.Dlc.TitleIdBase == application.IdBase));
|
||||
it.AddOrUpdate(dlcs);
|
||||
@ -839,7 +830,7 @@ namespace Ryujinx.UI.App.Common
|
||||
{
|
||||
_titleUpdates.Edit(it =>
|
||||
{
|
||||
TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, application.IdBase, updates);
|
||||
TitleUpdatesHelper.SaveTitleUpdatesJson(application.IdBase, updates);
|
||||
|
||||
it.Remove(it.Items.Where(item => item.TitleUpdate.TitleIdBase == application.IdBase));
|
||||
it.AddOrUpdate(updates);
|
||||
@ -1088,14 +1079,15 @@ namespace Ryujinx.UI.App.Common
|
||||
|
||||
private bool AddAndAutoSelectUpdate(TitleUpdateModel update)
|
||||
{
|
||||
var currentlySelected = TitleUpdates.Items.FirstOrOptional(it =>
|
||||
if (update == null) return false;
|
||||
|
||||
var currentlySelected = TitleUpdates.Items.FindFirst(it =>
|
||||
it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected);
|
||||
|
||||
var shouldSelect = !currentlySelected.HasValue ||
|
||||
currentlySelected.Value.TitleUpdate.Version < update.Version;
|
||||
var shouldSelect = currentlySelected.Check(curr => curr.TitleUpdate?.Version < update.Version);
|
||||
|
||||
_titleUpdates.AddOrUpdate((update, shouldSelect));
|
||||
|
||||
|
||||
if (currentlySelected.HasValue && shouldSelect)
|
||||
{
|
||||
_titleUpdates.AddOrUpdate((currentlySelected.Value.TitleUpdate, false));
|
||||
@ -1464,7 +1456,7 @@ namespace Ryujinx.UI.App.Common
|
||||
if (addedNewDlc)
|
||||
{
|
||||
var gameDlcs = it.Items.Where(dlc => dlc.Dlc.TitleIdBase == application.IdBase).ToList();
|
||||
DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, application.IdBase,
|
||||
DownloadableContentsHelper.SaveDownloadableContentsJson(application.IdBase,
|
||||
gameDlcs);
|
||||
}
|
||||
}
|
||||
@ -1483,11 +1475,11 @@ namespace Ryujinx.UI.App.Common
|
||||
TitleUpdatesHelper.LoadTitleUpdatesJson(_virtualFileSystem, application.IdBase);
|
||||
it.AddOrUpdate(savedUpdates);
|
||||
|
||||
var selectedUpdate = savedUpdates.FirstOrOptional(update => update.IsSelected);
|
||||
var selectedUpdate = savedUpdates.FindFirst(update => update.IsSelected);
|
||||
|
||||
if (TryGetTitleUpdatesFromFile(application.Path, out var bundledUpdates))
|
||||
{
|
||||
var savedUpdateLookup = savedUpdates.Select(update => update.Item1).ToHashSet();
|
||||
var savedUpdateLookup = savedUpdates.Select(update => update.Update).ToHashSet();
|
||||
bool updatesChanged = false;
|
||||
|
||||
foreach (var update in bundledUpdates.OrderByDescending(bundled => bundled.Version))
|
||||
@ -1495,12 +1487,11 @@ namespace Ryujinx.UI.App.Common
|
||||
if (!savedUpdateLookup.Contains(update))
|
||||
{
|
||||
bool shouldSelect = false;
|
||||
if (!selectedUpdate.HasValue || selectedUpdate.Value.Item1.Version < update.Version)
|
||||
if (selectedUpdate.Check(su => su.Update?.Version < update.Version))
|
||||
{
|
||||
shouldSelect = true;
|
||||
if (selectedUpdate.HasValue)
|
||||
_titleUpdates.AddOrUpdate((selectedUpdate.Value.Item1, false));
|
||||
selectedUpdate = DynamicData.Kernel.Optional<(TitleUpdateModel, bool IsSelected)>.Create((update, true));
|
||||
_titleUpdates.AddOrUpdate((selectedUpdate.Value.Update, false));
|
||||
selectedUpdate = (update, true);
|
||||
}
|
||||
|
||||
modifiedVersion = modifiedVersion || shouldSelect;
|
||||
@ -1513,7 +1504,7 @@ namespace Ryujinx.UI.App.Common
|
||||
if (updatesChanged)
|
||||
{
|
||||
var gameUpdates = it.Items.Where(update => update.TitleUpdate.TitleIdBase == application.IdBase).ToList();
|
||||
TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, application.IdBase, gameUpdates);
|
||||
TitleUpdatesHelper.SaveTitleUpdatesJson(application.IdBase, gameUpdates);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1525,14 +1516,14 @@ namespace Ryujinx.UI.App.Common
|
||||
private void SaveDownloadableContentsForGame(ulong titleIdBase)
|
||||
{
|
||||
var dlcs = DownloadableContents.Items.Where(dlc => dlc.Dlc.TitleIdBase == titleIdBase).ToList();
|
||||
DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, titleIdBase, dlcs);
|
||||
DownloadableContentsHelper.SaveDownloadableContentsJson(titleIdBase, dlcs);
|
||||
}
|
||||
|
||||
// Save the _currently tracked_ update state for the game
|
||||
private void SaveTitleUpdatesForGame(ulong titleIdBase)
|
||||
{
|
||||
var updates = TitleUpdates.Items.Where(update => update.TitleUpdate.TitleIdBase == titleIdBase).ToList();
|
||||
TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, titleIdBase, updates);
|
||||
TitleUpdatesHelper.SaveTitleUpdatesJson(titleIdBase, updates);
|
||||
}
|
||||
|
||||
// ApplicationData isnt live-updating (e.g. when an update gets applied) and so this is meant to trigger a refresh
|
||||
|
@ -1,3 +1,4 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
@ -16,7 +17,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
/// <summary>
|
||||
/// The current version of the file format
|
||||
/// </summary>
|
||||
public const int CurrentVersion = 56;
|
||||
public const int CurrentVersion = 57;
|
||||
|
||||
/// <summary>
|
||||
/// Version of the configuration file format
|
||||
@ -191,8 +192,25 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
/// <summary>
|
||||
/// Enables or disables Vertical Sync
|
||||
/// </summary>
|
||||
/// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks>
|
||||
/// TODO: Remove this when those older versions aren't in use anymore.
|
||||
public bool EnableVsync { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current VSync mode; 60 (Switch), unbounded ("Vsync off"), or custom
|
||||
/// </summary>
|
||||
public VSyncMode VSyncMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables the custom present interval
|
||||
/// </summary>
|
||||
public bool EnableCustomVSyncInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The custom present interval value
|
||||
/// </summary>
|
||||
public int CustomVSyncInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables Shader cache
|
||||
/// </summary>
|
||||
|
@ -82,7 +82,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
ToggleVSyncMode = Key.F1,
|
||||
};
|
||||
|
||||
configurationFileUpdated = true;
|
||||
@ -276,7 +276,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
ToggleVSyncMode = Key.F1,
|
||||
Screenshot = Key.F8,
|
||||
};
|
||||
|
||||
@ -289,7 +289,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
ToggleVSyncMode = Key.F1,
|
||||
Screenshot = Key.F8,
|
||||
ShowUI = Key.F4,
|
||||
};
|
||||
@ -332,7 +332,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
||||
Pause = Key.F5,
|
||||
@ -347,7 +347,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||
@ -421,7 +421,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||
@ -448,7 +448,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||
@ -611,6 +611,33 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
if (configurationFileFormat.Version < 57)
|
||||
{
|
||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 57.");
|
||||
|
||||
configurationFileFormat.VSyncMode = VSyncMode.Switch;
|
||||
configurationFileFormat.EnableCustomVSyncInterval = false;
|
||||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVSyncMode = Key.F1,
|
||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
||||
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
|
||||
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
|
||||
VolumeUp = configurationFileFormat.Hotkeys.VolumeUp,
|
||||
VolumeDown = configurationFileFormat.Hotkeys.VolumeDown,
|
||||
CustomVSyncIntervalIncrement = Key.Unbound,
|
||||
CustomVSyncIntervalDecrement = Key.Unbound,
|
||||
};
|
||||
|
||||
configurationFileFormat.CustomVSyncInterval = 120;
|
||||
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
||||
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
||||
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
||||
@ -646,7 +673,9 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
ShowTitleBar.Value = configurationFileFormat.ShowTitleBar;
|
||||
EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration;
|
||||
HideCursor.Value = configurationFileFormat.HideCursor;
|
||||
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
|
||||
Graphics.VSyncMode.Value = configurationFileFormat.VSyncMode;
|
||||
Graphics.EnableCustomVSyncInterval.Value = configurationFileFormat.EnableCustomVSyncInterval;
|
||||
Graphics.CustomVSyncInterval.Value = configurationFileFormat.CustomVSyncInterval;
|
||||
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
|
||||
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
|
||||
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using ARMeilleure;
|
||||
using ARMeilleure;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
@ -474,9 +474,19 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
public ReactiveObject<string> ShadersDumpPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables Vertical Sync
|
||||
/// Toggles the present interval mode. Options are Switch (60Hz), Unbounded (previously Vsync off), and Custom, if enabled.
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableVsync { get; private set; }
|
||||
public ReactiveObject<VSyncMode> VSyncMode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables the custom present interval mode.
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableCustomVSyncInterval { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Changes the custom present interval.
|
||||
/// </summary>
|
||||
public ReactiveObject<int> CustomVSyncInterval { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables Shader cache
|
||||
@ -536,8 +546,12 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
AspectRatio = new ReactiveObject<AspectRatio>();
|
||||
AspectRatio.LogChangesToValue(nameof(AspectRatio));
|
||||
ShadersDumpPath = new ReactiveObject<string>();
|
||||
EnableVsync = new ReactiveObject<bool>();
|
||||
EnableVsync.LogChangesToValue(nameof(EnableVsync));
|
||||
VSyncMode = new ReactiveObject<VSyncMode>();
|
||||
VSyncMode.LogChangesToValue(nameof(VSyncMode));
|
||||
EnableCustomVSyncInterval = new ReactiveObject<bool>();
|
||||
EnableCustomVSyncInterval.LogChangesToValue(nameof(EnableCustomVSyncInterval));
|
||||
CustomVSyncInterval = new ReactiveObject<int>();
|
||||
CustomVSyncInterval.LogChangesToValue(nameof(CustomVSyncInterval));
|
||||
EnableShaderCache = new ReactiveObject<bool>();
|
||||
EnableShaderCache.LogChangesToValue(nameof(EnableShaderCache));
|
||||
EnableTextureRecompression = new ReactiveObject<bool>();
|
||||
|
@ -1,16 +1,12 @@
|
||||
using ARMeilleure;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.UI.Common.Configuration.System;
|
||||
using Ryujinx.UI.Common.Configuration.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.UI.Common.Configuration
|
||||
{
|
||||
@ -21,10 +17,10 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
if (Instance != null)
|
||||
{
|
||||
throw new InvalidOperationException("Configuration is already initialized");
|
||||
}
|
||||
}
|
||||
|
||||
Instance = new ConfigurationState();
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigurationFileFormat ToFileFormat()
|
||||
{
|
||||
@ -64,7 +60,9 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
ShowTitleBar = ShowTitleBar,
|
||||
EnableHardwareAcceleration = EnableHardwareAcceleration,
|
||||
HideCursor = HideCursor,
|
||||
EnableVsync = Graphics.EnableVsync,
|
||||
VSyncMode = Graphics.VSyncMode,
|
||||
EnableCustomVSyncInterval = Graphics.EnableCustomVSyncInterval,
|
||||
CustomVSyncInterval = Graphics.CustomVSyncInterval,
|
||||
EnableShaderCache = Graphics.EnableShaderCache,
|
||||
EnableTextureRecompression = Graphics.EnableTextureRecompression,
|
||||
EnableMacroHLE = Graphics.EnableMacroHLE,
|
||||
@ -179,7 +177,9 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
ShowTitleBar.Value = !OperatingSystem.IsWindows();
|
||||
EnableHardwareAcceleration.Value = true;
|
||||
HideCursor.Value = HideCursorMode.OnIdle;
|
||||
Graphics.EnableVsync.Value = true;
|
||||
Graphics.VSyncMode.Value = VSyncMode.Switch;
|
||||
Graphics.CustomVSyncInterval.Value = 120;
|
||||
Graphics.EnableCustomVSyncInterval.Value = false;
|
||||
Graphics.EnableShaderCache.Value = true;
|
||||
Graphics.EnableTextureRecompression.Value = false;
|
||||
Graphics.EnableMacroHLE.Value = true;
|
||||
@ -240,7 +240,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||
Hid.EnableMouse.Value = false;
|
||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
ToggleVSyncMode = Key.F1,
|
||||
ToggleMute = Key.F2,
|
||||
Screenshot = Key.F8,
|
||||
ShowUI = Key.F4,
|
||||
|
@ -247,6 +247,7 @@ namespace Ryujinx.UI.Common
|
||||
"0100dbf01000a000", // Burnout Paradise Remastered
|
||||
"0100744001588000", // Cars 3: Driven to Win
|
||||
"0100b41013c82000", // Cruis'n Blast
|
||||
"01001b300b9be000", // Diablo III: Eternal Collection
|
||||
"01008c8012920000", // Dying Light Platinum Edition
|
||||
"010073c01af34000", // LEGO Horizon Adventures
|
||||
"0100770008dd8000", // Monster Hunter Generations Ultimate
|
||||
@ -264,6 +265,7 @@ namespace Ryujinx.UI.Common
|
||||
"0100800015926000", // Suika Game
|
||||
"0100e46006708000", // Terraria
|
||||
"01000a10041ea000", // The Elder Scrolls V: Skyrim
|
||||
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
|
||||
"010080b00ad66000", // Undertale
|
||||
];
|
||||
}
|
||||
|
@ -7,6 +7,24 @@ namespace Ryujinx.UI.Common.Helper
|
||||
{
|
||||
public static partial class ConsoleHelper
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32")]
|
||||
private static partial nint GetConsoleWindow();
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("user32")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool ShowWindow(nint hWnd, int nCmdShow);
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("user32")]
|
||||
private static partial nint GetForegroundWindow();
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("user32")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool SetForegroundWindow(nint hWnd);
|
||||
|
||||
public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
|
||||
|
||||
public static void SetConsoleWindowState(bool show)
|
||||
@ -35,16 +53,11 @@ namespace Ryujinx.UI.Common.Helper
|
||||
return;
|
||||
}
|
||||
|
||||
SetForegroundWindow(hWnd);
|
||||
|
||||
hWnd = GetForegroundWindow();
|
||||
|
||||
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32")]
|
||||
private static partial nint GetConsoleWindow();
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("user32")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool ShowWindow(nint hWnd, int nCmdShow);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.UI.Common.Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveDownloadableContentsJson(VirtualFileSystem vfs, ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs)
|
||||
public static void SaveDownloadableContentsJson(ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs)
|
||||
{
|
||||
DownloadableContentContainer container = default;
|
||||
List<DownloadableContentContainer> downloadableContentContainerList = new();
|
||||
|
@ -28,7 +28,7 @@ namespace Ryujinx.UI.Common.Helper
|
||||
{
|
||||
private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
public static List<(TitleUpdateModel, bool IsSelected)> LoadTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase)
|
||||
public static List<(TitleUpdateModel Update, bool IsSelected)> LoadTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase)
|
||||
{
|
||||
var titleUpdatesJsonPath = PathToGameUpdatesJson(applicationIdBase);
|
||||
|
||||
@ -49,7 +49,7 @@ namespace Ryujinx.UI.Common.Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase, List<(TitleUpdateModel, bool IsSelected)> updates)
|
||||
public static void SaveTitleUpdatesJson(ulong applicationIdBase, List<(TitleUpdateModel, bool IsSelected)> updates)
|
||||
{
|
||||
var titleUpdateWindowData = new TitleUpdateMetadata
|
||||
{
|
||||
@ -77,7 +77,7 @@ namespace Ryujinx.UI.Common.Helper
|
||||
JsonHelper.SerializeToFile(titleUpdatesJsonPath, titleUpdateWindowData, _serializerContext.TitleUpdateMetadata);
|
||||
}
|
||||
|
||||
private static List<(TitleUpdateModel, bool IsSelected)> LoadTitleUpdates(VirtualFileSystem vfs, TitleUpdateMetadata titleUpdateMetadata, ulong applicationIdBase)
|
||||
private static List<(TitleUpdateModel Update, bool IsSelected)> LoadTitleUpdates(VirtualFileSystem vfs, TitleUpdateMetadata titleUpdateMetadata, ulong applicationIdBase)
|
||||
{
|
||||
var result = new List<(TitleUpdateModel, bool IsSelected)>();
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 253 KiB |
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user