Compare commits

..

14 Commits

Author SHA1 Message Date
Evan Husted
e8d3ad4d8b UI: RPC: TSUKIHIME -A piece of blue glass moon- asset image 2024-11-23 13:10:53 -06:00
Evan Husted
3b6731a351 infra: Undo packing native libraries into executable. 2024-11-22 17:51:44 -06:00
LotP1
e653848a2c JIT Sparse Function Table (#250)
More up to date build of the JIT Sparse PR for continued development.
JIT Sparse Function Table was originally developed by riperiperi for the
original Ryujinx project, and decreased the amount of layers in the
Function Table structure, to decrease lookup times at the cost of
slightly higher RAM usage.
This PR rebalances the JIT Sparse Function Table to be a bit more RAM
intensive, but faster in workloads where the JIT Function Table is a
bottleneck. Faster RAM will see a bigger impact and slower RAM (DDR3 and
potentially slow DDR4) will see a slight performance decrease.
This PR also implements a base for a PPTC profile system that could
allow for PPTC with ExeFS mods enabled in the future.
This PR also potentially fixes a strange issue where Avalonia would time
out in some rare instances, e.g. when running ExeFS mods with TotK and a
strange controller configuration.

---------

Co-authored-by: Evan Husted <gr33m11@gmail.com>
2024-11-22 15:33:44 -06:00
Evan Husted
5534001152 UI: Always save screenshots to the Ryujinx data directory. 2024-11-22 15:08:24 -06:00
Evan Husted
e05875a079 UI: It's called "live testing." 2024-11-22 14:52:56 -06:00
Evan Husted
49eeb26b6f UI: I may be stupid. Primary button result is Ok, not Yes. 2024-11-22 14:46:10 -06:00
Evan Husted
f8d63f9a2f UI: Add a show changelog button in the Updater, for new updates & when you're on the latest version. 2024-11-22 14:38:58 -06:00
GabCoolGuy
e2b7738465 Add all the missing locales from XCI Trimmer and LDN merge (#281)
Hello any fellow developers that may be reading this. Whenever you add
any new locales to `en_US.json`, please make sure to add them to the
rest of the locale files. I will not always be there to add them myself.
2024-11-22 11:07:47 -06:00
GabCoolGuy
1d42c29335 Add more mentions of canary (#258)
This should hopefully make it clearer whether or not you're using
canary.

Changelog:
- Changed github workflows to have "canary" in the zip files
- Added `App.FullAppName` in the about section, so that it's clear in
there too
- Changed log name for canary builds to
`Ryujinx_Canary_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log`
(normal builds should still be
"Ryujinx_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log)
2024-11-21 12:34:53 -06:00
Evan Husted
c2de5cc700 Fix really obvious typo, lol 2024-11-21 10:16:13 -06:00
GabCoolGuy
aaaf60b7a4 Change headless to nogui in the release artifacts (#285)
This makes it so that instead of the files you download being
`sdl2-ryujinx-headless` they are now `nogui-ryujinx`in the release (and
canary) artifacts
2024-11-20 12:20:38 -06:00
GabCoolGuy
150e06e0de Add documentation and ldn labels to labeler.yml (#282)
This should make it so that any changes made to ldn and documentation
related files should be auto-labeled
2024-11-20 11:52:16 -06:00
Luke Warner
c0a4d95c5d ARMeilleure: Implement TPIDR2_EL0 (#280)
This is an implementation of the TPIDR2_EL0 register. There may be more
potential use-cases for this register not included in this PR, but this
implements the use-case seen in SuperTuxKart.
2024-11-19 13:02:24 -06:00
Evan Husted
c3831428e0 Try and fix weird nullref 2024-11-19 10:22:11 -06:00
157 changed files with 1454 additions and 4071 deletions

View File

@@ -54,19 +54,7 @@ jobs:
with: with:
name: "Canary ${{ steps.version_info.outputs.build_version }}" name: "Canary ${{ steps.version_info.outputs.build_version }}"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
# 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 omitBodyDuringUpdate: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
@@ -193,19 +181,7 @@ jobs:
artifacts: "release_output/*.tar.gz,release_output/*.zip" artifacts: "release_output/*.tar.gz,release_output/*.zip"
#artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*" #artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
# 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 omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -272,19 +248,7 @@ jobs:
name: "Canary ${{ steps.version_info.outputs.build_version }}" name: "Canary ${{ steps.version_info.outputs.build_version }}"
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz" artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
# 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 omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true

View File

@@ -53,16 +53,7 @@ jobs:
with: with:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
# 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 omitBodyDuringUpdate: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
@@ -185,16 +176,7 @@ jobs:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*" artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
# 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 omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -261,16 +243,7 @@ jobs:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz" artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
# 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 omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true

3
.gitignore vendored
View File

@@ -175,6 +175,3 @@ PublishProfiles/
# Glade backup files # Glade backup files
*.glade~ *.glade~
# Ignore MacOS Attribute Files
._*

View File

@@ -38,7 +38,7 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" /> <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.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.6.8" /> <PackageVersion Include="Gommon" Version="2.6.6" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />

View File

@@ -1,26 +1,35 @@
<table align="center"> <h1 align="center">
<tr>
<td align="center" width="25%">
<img src="https://raw.githubusercontent.com/GreemDev/ryuassets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" >
</td>
<td align="center" width="75%">
# Ryujinx
[![Release workflow](https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml/badge.svg)](https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml)
[![Latest release](https://img.shields.io/github/v/release/GreemDev/Ryujinx)](https://github.com/GreemDev/Ryujinx/releases/latest)
<br> <br>
[![Canary workflow](https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml/badge.svg)](https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml) <img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/master/distribution/misc/Logo.svg" alt="Ryujinx" width="150"></a>
[![Latest canary release](https://img.shields.io/github/v/release/GreemDev/Ryujinx-Canary?label=canary)](https://github.com/GreemDev/Ryujinx-Canary/releases/latest) <br>
</td> <b>Ryujinx</b>
</tr> <br>
</table> <sub><sup><b>(REE-YOU-JINX)</b></sup></sub>
<br>
<a href="https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml">
<img src="https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml/badge.svg"
alt="">
</a>
<a href="https://github.com/GreemDev/Ryujinx/releases/latest">
<img src="https://img.shields.io/github/v/release/GreemDev/Ryujinx"
alt="Latest Release">
</a>
<br>
<a href="https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml">
<img src="https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml/badge.svg"
alt="">
</a>
<a href="https://github.com/GreemDev/Ryujinx-Canary/releases/latest">
<img src="https://img.shields.io/github/v/release/GreemDev/Ryujinx-Canary?label=canary"
alt="Latest Canary Release">
</a>
</h1>
<p align="center"> <p align="center">
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#. 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. 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. 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 /> <br />
</p> </p>
<p align="center"> <p align="center">

View File

@@ -14,7 +14,7 @@ if [ -z "$RYUJINX_BIN" ]; then
exit 1 exit 1
fi fi
COMMAND="env LANG=C.UTF-8 DOTNET_EnableAlternateStackCheck=1" COMMAND="env DOTNET_EnableAlternateStackCheck=1"
if command -v gamemoderun > /dev/null 2>&1; then if command -v gamemoderun > /dev/null 2>&1; then
COMMAND="$COMMAND gamemoderun" COMMAND="$COMMAND gamemoderun"

View File

@@ -40,11 +40,11 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.2</string> <string>1.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.2.0</string> <string>1.1.0</string>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>CSResourcesFileMapped</key> <key>CSResourcesFileMapped</key>

Binary file not shown.

View File

@@ -17,7 +17,7 @@ error_handler() {
set the button_pressed to the button returned of the result set the button_pressed to the button returned of the result
if the button_pressed is \"Open Download Page\" then if the button_pressed is \"Open Download Page\" then
open location \"https://ryujinx.app/download\" open location \"https://ryujinx.org/download\"
end if end if
""" """

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -36,9 +36,9 @@ namespace ARMeilleure.Common
/// </summary> /// </summary>
/// <param name="address">Guest address</param> /// <param name="address">Guest address</param>
/// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns> /// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns>
public long GetValue(ulong address) public int GetValue(ulong address)
{ {
return (long)((address & Mask) >> Index); return (int)((address & Mask) >> Index);
} }
} }
} }

View File

@@ -88,7 +88,7 @@ namespace ARMeilleure.Instructions
EmitSetTpidrEl0(context); EmitSetTpidrEl0(context);
return; return;
case 0b11_011_1101_0000_101: case 0b11_011_1101_0000_101:
EmitSetTpidr2El0(context); EmitGetTpidr2El0(context);
return; return;
default: default:
@@ -291,16 +291,5 @@ namespace ARMeilleure.Instructions
context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), value); 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);
}
} }
} }

View File

@@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 6997; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 6992; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,8 +1,6 @@
namespace Ryujinx.Common.Configuration.Hid.Controller namespace Ryujinx.Common.Configuration.Hid.Controller
{ {
public class JoyconConfigControllerStick<TButton, TStick> public class JoyconConfigControllerStick<TButton, TStick> where TButton : unmanaged where TStick : unmanaged
where TButton : unmanaged
where TStick : unmanaged
{ {
public TStick Joystick { get; set; } public TStick Joystick { get; set; }
public bool InvertStickX { get; set; } public bool InvertStickX { get; set; }

View File

@@ -2,7 +2,7 @@ namespace Ryujinx.Common.Configuration.Hid
{ {
public class KeyboardHotkeys public class KeyboardHotkeys
{ {
public Key ToggleVSyncMode { get; set; } public Key ToggleVsync { get; set; }
public Key Screenshot { get; set; } public Key Screenshot { get; set; }
public Key ShowUI { get; set; } public Key ShowUI { get; set; }
public Key Pause { get; set; } public Key Pause { get; set; }
@@ -11,7 +11,5 @@ namespace Ryujinx.Common.Configuration.Hid
public Key ResScaleDown { get; set; } public Key ResScaleDown { get; set; }
public Key VolumeUp { get; set; } public Key VolumeUp { get; set; }
public Key VolumeDown { get; set; } public Key VolumeDown { get; set; }
public Key CustomVSyncIntervalIncrement { get; set; }
public Key CustomVSyncIntervalDecrement { get; set; }
} }
} }

View File

@@ -1,9 +0,0 @@
namespace Ryujinx.Common.Configuration
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}

View File

@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants> <DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -238,7 +238,7 @@ namespace ARMeilleure.Common
{ {
TEntry* page = GetPage(address); TEntry* page = GetPage(address);
long index = Levels[^1].GetValue(address); int index = Levels[^1].GetValue(address);
EnsureMapped((IntPtr)(page + index)); EnsureMapped((IntPtr)(page + index));

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.GAL
void SetSize(int width, int height); void SetSize(int width, int height);
void ChangeVSyncMode(VSyncMode vSyncMode); void ChangeVSyncMode(bool vsyncEnabled);
void SetAntiAliasing(AntiAliasing antialiasing); void SetAntiAliasing(AntiAliasing antialiasing);
void SetScalingFilter(ScalingFilter type); void SetScalingFilter(ScalingFilter type);

View File

@@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_impl.Window.SetSize(width, height); _impl.Window.SetSize(width, height);
} }
public void ChangeVSyncMode(VSyncMode vSyncMode) { } public void ChangeVSyncMode(bool vsyncEnabled) { }
public void SetAntiAliasing(AntiAliasing effect) { } public void SetAntiAliasing(AntiAliasing effect) { }

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@@ -1,9 +0,0 @@
namespace Ryujinx.Graphics.GAL
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.OpenGL
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
} }
public void ChangeVSyncMode(VSyncMode vSyncMode) { } public void ChangeVSyncMode(bool vsyncEnabled) { }
public void SetSize(int width, int height) public void SetSize(int width, int height)
{ {

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@@ -183,16 +183,6 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
//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; return true;
} }

View File

@@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Vulkan
private int _width; private int _width;
private int _height; private int _height;
private VSyncMode _vSyncMode; private bool _vsyncEnabled;
private bool _swapchainIsDirty; private bool _swapchainIsDirty;
private VkFormat _format; private VkFormat _format;
private AntiAliasing _currentAntiAliasing; private AntiAliasing _currentAntiAliasing;
@@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.Vulkan
ImageArrayLayers = 1, ImageArrayLayers = 1,
PreTransform = capabilities.CurrentTransform, PreTransform = capabilities.CurrentTransform,
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha), CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
PresentMode = ChooseSwapPresentMode(presentModes, _vSyncMode), PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
Clipped = true, Clipped = true,
}; };
@@ -279,9 +279,9 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, VSyncMode vSyncMode) private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, bool vsyncEnabled)
{ {
if (vSyncMode == VSyncMode.Unbounded && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr)) if (!vsyncEnabled && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr))
{ {
return PresentModeKHR.ImmediateKhr; return PresentModeKHR.ImmediateKhr;
} }
@@ -634,10 +634,9 @@ namespace Ryujinx.Graphics.Vulkan
_swapchainIsDirty = true; _swapchainIsDirty = true;
} }
public override void ChangeVSyncMode(VSyncMode vSyncMode) public override void ChangeVSyncMode(bool vsyncEnabled)
{ {
_vSyncMode = vSyncMode; _vsyncEnabled = vsyncEnabled;
//present mode may change, so mark the swapchain for recreation
_swapchainIsDirty = true; _swapchainIsDirty = true;
} }

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Vulkan
public abstract void Dispose(); public abstract void Dispose();
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback); public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
public abstract void SetSize(int width, int height); public abstract void SetSize(int width, int height);
public abstract void ChangeVSyncMode(VSyncMode vSyncMode); public abstract void ChangeVSyncMode(bool vsyncEnabled);
public abstract void SetAntiAliasing(AntiAliasing effect); public abstract void SetAntiAliasing(AntiAliasing effect);
public abstract void SetScalingFilter(ScalingFilter scalerType); public abstract void SetScalingFilter(ScalingFilter scalerType);
public abstract void SetScalingFilterLevel(float scale); public abstract void SetScalingFilterLevel(float scale);

View File

@@ -6,7 +6,6 @@
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<IsRoslynComponent>true</IsRoslynComponent> <IsRoslynComponent>true</IsRoslynComponent>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -21,7 +21,6 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace Ryujinx.HLE.FileSystem namespace Ryujinx.HLE.FileSystem
@@ -475,74 +474,6 @@ namespace Ryujinx.HLE.FileSystem
FinishInstallation(temporaryDirectory, registeredDirectory); 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) private void FinishInstallation(string temporaryDirectory, string registeredDirectory)
{ {
if (Directory.Exists(registeredDirectory)) if (Directory.Exists(registeredDirectory))
@@ -1016,70 +947,5 @@ namespace Ryujinx.HLE.FileSystem
return null; 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;
}
} }
} }

View File

@@ -223,10 +223,9 @@ namespace Ryujinx.HLE.FileSystem
{ {
KeySet ??= KeySet.CreateDefaultKeySet(); KeySet ??= KeySet.CreateDefaultKeySet();
string prodKeyFile = null; string keyFile = null;
string titleKeyFile = null; string titleKeyFile = null;
string consoleKeyFile = null; string consoleKeyFile = null;
string devKeyFile = null;
if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile) if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile)
{ {
@@ -237,14 +236,13 @@ namespace Ryujinx.HLE.FileSystem
void LoadSetAtPath(string basePath) void LoadSetAtPath(string basePath)
{ {
string localProdKeyFile = Path.Combine(basePath, "prod.keys"); string localKeyFile = Path.Combine(basePath, "prod.keys");
string localTitleKeyFile = Path.Combine(basePath, "title.keys"); string localTitleKeyFile = Path.Combine(basePath, "title.keys");
string localConsoleKeyFile = Path.Combine(basePath, "console.keys"); string localConsoleKeyFile = Path.Combine(basePath, "console.keys");
string localDevKeyFile = Path.Combine(basePath, "dev.keys");
if (File.Exists(localProdKeyFile)) if (File.Exists(localKeyFile))
{ {
prodKeyFile = localProdKeyFile; keyFile = localKeyFile;
} }
if (File.Exists(localTitleKeyFile)) if (File.Exists(localTitleKeyFile))
@@ -256,14 +254,9 @@ namespace Ryujinx.HLE.FileSystem
{ {
consoleKeyFile = localConsoleKeyFile; consoleKeyFile = localConsoleKeyFile;
} }
if (File.Exists(localDevKeyFile))
{
devKeyFile = localDevKeyFile;
}
} }
ExternalKeyReader.ReadKeyFile(KeySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, null); ExternalKeyReader.ReadKeyFile(KeySet, keyFile, titleKeyFile, consoleKeyFile, null);
} }
public void ImportTickets(IFileSystem fs) public void ImportTickets(IFileSystem fs)

View File

@@ -9,7 +9,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
using System; using System;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.HLE namespace Ryujinx.HLE
{ {
@@ -85,14 +84,9 @@ namespace Ryujinx.HLE
internal readonly RegionCode Region; internal readonly RegionCode Region;
/// <summary> /// <summary>
/// Control the initial state of the present interval in the SurfaceFlinger service (previously Vsync). /// Control the initial state of the vertical sync in the SurfaceFlinger service.
/// </summary> /// </summary>
internal readonly VSyncMode VSyncMode; internal readonly bool EnableVsync;
/// <summary>
/// Control the custom VSync interval, if enabled and active.
/// </summary>
internal readonly int CustomVSyncInterval;
/// <summary> /// <summary>
/// Control the initial state of the docked mode. /// Control the initial state of the docked mode.
@@ -201,7 +195,7 @@ namespace Ryujinx.HLE
IHostUIHandler hostUIHandler, IHostUIHandler hostUIHandler,
SystemLanguage systemLanguage, SystemLanguage systemLanguage,
RegionCode region, RegionCode region,
VSyncMode vSyncMode, bool enableVsync,
bool enableDockedMode, bool enableDockedMode,
bool enablePtc, bool enablePtc,
bool enableInternetAccess, bool enableInternetAccess,
@@ -218,8 +212,7 @@ namespace Ryujinx.HLE
MultiplayerMode multiplayerMode, MultiplayerMode multiplayerMode,
bool multiplayerDisableP2p, bool multiplayerDisableP2p,
string multiplayerLdnPassphrase, string multiplayerLdnPassphrase,
string multiplayerLdnServer, string multiplayerLdnServer)
int customVSyncInterval)
{ {
VirtualFileSystem = virtualFileSystem; VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager; LibHacHorizonManager = libHacHorizonManager;
@@ -232,8 +225,7 @@ namespace Ryujinx.HLE
HostUIHandler = hostUIHandler; HostUIHandler = hostUIHandler;
SystemLanguage = systemLanguage; SystemLanguage = systemLanguage;
Region = region; Region = region;
VSyncMode = vSyncMode; EnableVsync = enableVsync;
CustomVSyncInterval = customVSyncInterval;
EnableDockedMode = enableDockedMode; EnableDockedMode = enableDockedMode;
EnablePtc = enablePtc; EnablePtc = enablePtc;
EnableInternetAccess = enableInternetAccess; EnableInternetAccess = enableInternetAccess;

View File

@@ -1,6 +1,5 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Applets.Browser; using Ryujinx.HLE.HOS.Applets.Browser;
using Ryujinx.HLE.HOS.Applets.Cabinet;
using Ryujinx.HLE.HOS.Applets.Dummy; using Ryujinx.HLE.HOS.Applets.Dummy;
using Ryujinx.HLE.HOS.Applets.Error; using Ryujinx.HLE.HOS.Applets.Error;
using Ryujinx.HLE.HOS.Services.Am.AppletAE; using Ryujinx.HLE.HOS.Services.Am.AppletAE;
@@ -24,14 +23,14 @@ namespace Ryujinx.HLE.HOS.Applets
case AppletId.SoftwareKeyboard: case AppletId.SoftwareKeyboard:
return new SoftwareKeyboardApplet(system); return new SoftwareKeyboardApplet(system);
case AppletId.LibAppletWeb: case AppletId.LibAppletWeb:
return new BrowserApplet(system);
case AppletId.LibAppletShop: case AppletId.LibAppletShop:
return new BrowserApplet(system);
case AppletId.LibAppletOff: case AppletId.LibAppletOff:
return new BrowserApplet(); return new BrowserApplet(system);
case AppletId.MiiEdit: case AppletId.MiiEdit:
Logger.Warning?.Print(LogClass.Application, $"Please use the MiiEdit inside File/Open Applet"); Logger.Warning?.Print(LogClass.Application, $"Please use the MiiEdit inside File/Open Applet");
return new DummyApplet(system); return new DummyApplet(system);
case AppletId.Cabinet:
return new CabinetApplet(system);
} }
Logger.Warning?.Print(LogClass.Application, $"Applet {applet} not implemented!"); Logger.Warning?.Print(LogClass.Application, $"Applet {applet} not implemented!");

View File

@@ -18,6 +18,13 @@ namespace Ryujinx.HLE.HOS.Applets.Browser
private List<BrowserArgument> _arguments; private List<BrowserArgument> _arguments;
private ShimKind _shimKind; private ShimKind _shimKind;
public BrowserApplet(Horizon system) { }
public ResultCode GetResult()
{
return ResultCode.Success;
}
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession) public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession)
{ {
_normalSession = normalSession; _normalSession = normalSession;

View File

@@ -1,182 +0,0 @@
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
}
}

View File

@@ -117,6 +117,11 @@ namespace Ryujinx.HLE.HOS.Applets
return ResultCode.Success; return ResultCode.Success;
} }
public ResultCode GetResult()
{
return ResultCode.Success;
}
private static byte[] BuildResponse(ControllerSupportResultInfo result) private static byte[] BuildResponse(ControllerSupportResultInfo result)
{ {
using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); using MemoryStream stream = MemoryStreamManager.Shared.GetStream();

View File

@@ -11,14 +11,11 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy
{ {
private readonly Horizon _system; private readonly Horizon _system;
private AppletSession _normalSession; private AppletSession _normalSession;
public event EventHandler AppletStateChanged; public event EventHandler AppletStateChanged;
public DummyApplet(Horizon system) public DummyApplet(Horizon system)
{ {
_system = system; _system = system;
} }
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession) public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession)
{ {
_normalSession = normalSession; _normalSession = normalSession;
@@ -27,7 +24,10 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy
_system.ReturnFocus(); _system.ReturnFocus();
return ResultCode.Success; return ResultCode.Success;
} }
private static T ReadStruct<T>(byte[] data) where T : struct
{
return MemoryMarshal.Read<T>(data.AsSpan());
}
private static byte[] BuildResponse() private static byte[] BuildResponse()
{ {
using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
@@ -35,5 +35,9 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy
writer.Write((ulong)ResultCode.Success); writer.Write((ulong)ResultCode.Success);
return stream.ToArray(); return stream.ToArray();
} }
public ResultCode GetResult()
{
return ResultCode.Success;
}
} }
} }

View File

@@ -203,5 +203,10 @@ namespace Ryujinx.HLE.HOS.Applets.Error
_horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber} (Details)", "\n" + detailsText, buttons.ToArray()); _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Number: {applicationErrorArg.ErrorNumber} (Details)", "\n" + detailsText, buttons.ToArray());
} }
} }
public ResultCode GetResult()
{
return ResultCode.Success;
}
} }
} }

View File

@@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Applets
ResultCode Start(AppletSession normalSession, ResultCode Start(AppletSession normalSession,
AppletSession interactiveSession); AppletSession interactiveSession);
ResultCode GetResult() => ResultCode.Success; ResultCode GetResult();
bool DrawTo(RenderingSurfaceInfo surfaceInfo, IVirtualMemoryManager destination, ulong position) => false; bool DrawTo(RenderingSurfaceInfo surfaceInfo, IVirtualMemoryManager destination, ulong position) => false;

View File

@@ -37,6 +37,11 @@ namespace Ryujinx.HLE.HOS.Applets
return ResultCode.Success; return ResultCode.Success;
} }
public ResultCode GetResult()
{
return ResultCode.Success;
}
private byte[] BuildResponse() private byte[] BuildResponse()
{ {
UserProfile currentUser = _system.AccountManager.LastOpenedUser; UserProfile currentUser = _system.AccountManager.LastOpenedUser;

View File

@@ -144,6 +144,11 @@ namespace Ryujinx.HLE.HOS.Applets
} }
} }
public ResultCode GetResult()
{
return ResultCode.Success;
}
private bool IsKeyboardActive() private bool IsKeyboardActive()
{ {
return _backgroundState >= InlineKeyboardState.Appearing && _backgroundState < InlineKeyboardState.Disappearing; return _backgroundState >= InlineKeyboardState.Appearing && _backgroundState < InlineKeyboardState.Disappearing;

View File

@@ -2,7 +2,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
{ {
/// <summary> /// <summary>
/// Wraps a type in a class so it gets stored in the GC managed heap. This is used as communication mechanism /// Wraps a type in a class so it gets stored in the GC managed heap. This is used as communication mechanism
/// between classes that need to be disposed and, thus, can't share their references. /// between classed that need to be disposed and, thus, can't share their references.
/// </summary> /// </summary>
/// <typeparam name="T">The internal type.</typeparam> /// <typeparam name="T">The internal type.</typeparam>
class TRef<T> class TRef<T>

View File

@@ -5,23 +5,5 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
class IServiceCreator : IpcService class IServiceCreator : IpcService
{ {
public IServiceCreator(ServiceCtx context) { } 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;
}
} }
} }

View File

@@ -1,54 +0,0 @@
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;
}
}
}

View File

@@ -1,86 +0,0 @@
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;
}
}
}

View File

@@ -1,5 +1,3 @@
using Gommon;
using Humanizer;
using NetCoreServer; using NetCoreServer;
using Open.Nat; using Open.Nat;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -155,10 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy
if (_publicPort != 0) if (_publicPort != 0)
{ {
_ = Executor.ExecuteAfterDelayAsync( _ = Task.Delay(PortLeaseRenew * 1000, _disposedCancellation.Token).ContinueWith((task) => Task.Run(RefreshLease));
PortLeaseRenew.Seconds(),
_disposedCancellation.Token,
RefreshLease);
} }
_natDevice = device; _natDevice = device;
@@ -262,10 +257,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy
} }
_ = Executor.ExecuteAfterDelayAsync( _ = Task.Delay(PortLeaseRenew, _disposedCancellation.Token).ContinueWith((task) => Task.Run(RefreshLease));
PortLeaseRenew.Milliseconds(),
_disposedCancellation.Token,
RefreshLease);
} }
public bool TryRegisterUser(P2pProxySession session, ExternalProxyConfig config) public bool TryRegisterUser(P2pProxySession session, ExternalProxyConfig config)

View File

@@ -93,13 +93,6 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
return registerInfo; 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) public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
{ {
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId); VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);

View File

@@ -10,12 +10,13 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
class SurfaceFlinger : IConsumerListener, IDisposable class SurfaceFlinger : IConsumerListener, IDisposable
{ {
private const int TargetFps = 60;
private readonly Switch _device; private readonly Switch _device;
private readonly Dictionary<long, Layer> _layers; private readonly Dictionary<long, Layer> _layers;
@@ -31,9 +32,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private readonly long _spinTicks; private readonly long _spinTicks;
private readonly long _1msTicks; private readonly long _1msTicks;
private VSyncMode _vSyncMode;
private long _targetVSyncInterval;
private int _swapInterval; private int _swapInterval;
private int _swapIntervalDelay; private int _swapIntervalDelay;
@@ -90,8 +88,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
} }
else else
{ {
_ticksPerFrame = Stopwatch.Frequency / _device.TargetVSyncInterval; _ticksPerFrame = Stopwatch.Frequency / TargetFps;
_targetVSyncInterval = _device.TargetVSyncInterval;
} }
} }
@@ -373,20 +370,15 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (acquireStatus == Status.Success) if (acquireStatus == Status.Success)
{ {
if (_device.VSyncMode == VSyncMode.Unbounded) // If device vsync is disabled, reflect the change.
if (!_device.EnableDeviceVsync)
{ {
if (_swapInterval != 0) if (_swapInterval != 0)
{ {
UpdateSwapInterval(0); UpdateSwapInterval(0);
_vSyncMode = _device.VSyncMode;
} }
} }
else if (_device.VSyncMode != _vSyncMode) else if (item.SwapInterval != _swapInterval)
{
UpdateSwapInterval(_device.VSyncMode == VSyncMode.Unbounded ? 0 : item.SwapInterval);
_vSyncMode = _device.VSyncMode;
}
else if (item.SwapInterval != _swapInterval || _device.TargetVSyncInterval != _targetVSyncInterval)
{ {
UpdateSwapInterval(item.SwapInterval); UpdateSwapInterval(item.SwapInterval);
} }

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
{ {
private static readonly TitleUpdateMetadataJsonSerializerContext _applicationSerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly TitleUpdateMetadataJsonSerializerContext _applicationSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public static ProcessResult Load(this Nca nca, Switch device, Nca patchNca, Nca controlNca, BlitStruct<ApplicationControlProperty>? customNacpData = null) public static ProcessResult Load(this Nca nca, Switch device, Nca patchNca, Nca controlNca)
{ {
// Extract RomFs and ExeFs from NCA. // Extract RomFs and ExeFs from NCA.
IStorage romFs = nca.GetRomFs(device, patchNca); IStorage romFs = nca.GetRomFs(device, patchNca);
@@ -55,10 +55,6 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
{ {
nacpData = controlNca.GetNacp(device); 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. /* TODO: Rework this since it's wrong and doesn't work as it takes the DisplayVersion from a "potential" non-existent update.

View File

@@ -98,12 +98,12 @@ namespace Ryujinx.HLE.Loaders.Processes
return false; return false;
} }
public bool LoadNca(string path, BlitStruct<ApplicationControlProperty>? customNacpData = null) public bool LoadNca(string path)
{ {
FileStream file = new(path, FileMode.Open, FileAccess.Read); FileStream file = new(path, FileMode.Open, FileAccess.Read);
Nca nca = new(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false)); Nca nca = new(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false));
ProcessResult processResult = nca.Load(_device, null, null, customNacpData); ProcessResult processResult = nca.Load(_device, null, null);
if (processResult.ProcessId != 0 && _processesByPid.TryAdd(processResult.ProcessId, processResult)) if (processResult.ProcessId != 0 && _processesByPid.TryAdd(processResult.ProcessId, processResult))
{ {

View File

@@ -84,19 +84,12 @@ namespace Ryujinx.HLE.Loaders.Processes
return false; 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. // TODO: LibHac npdm currently doesn't support version field.
string version = !isFirmware string version = ProgramId > 0x0100000000007FFF
? (!string.IsNullOrWhiteSpace(DisplayVersion) ? DisplayVersion : "<Unknown Version>") ? DisplayVersion
: device.System.ContentManager.GetCurrentFirmwareVersion()?.VersionString ?? "?"; : 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; return true;
} }

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,37 +0,0 @@
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;
}
}
}

View File

@@ -1,5 +1,3 @@
using LibHac.Common;
using LibHac.Ns;
using Ryujinx.Audio.Backends.CompatLayer; using Ryujinx.Audio.Backends.CompatLayer;
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
@@ -29,11 +27,7 @@ namespace Ryujinx.HLE
public TamperMachine TamperMachine { get; } public TamperMachine TamperMachine { get; }
public IHostUIHandler UIHandler { get; } public IHostUIHandler UIHandler { get; }
public VSyncMode VSyncMode { get; set; } = VSyncMode.Switch; public bool EnableDeviceVsync { get; set; }
public bool CustomVSyncIntervalEnabled { get; set; } = false;
public int CustomVSyncInterval { get; set; }
public long TargetVSyncInterval { get; set; } = 60;
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
@@ -65,14 +59,12 @@ namespace Ryujinx.HLE
System.State.SetLanguage(Configuration.SystemLanguage); System.State.SetLanguage(Configuration.SystemLanguage);
System.State.SetRegion(Configuration.Region); System.State.SetRegion(Configuration.Region);
VSyncMode = Configuration.VSyncMode; EnableDeviceVsync = Configuration.EnableVsync;
CustomVSyncInterval = Configuration.CustomVSyncInterval;
System.State.DockedMode = Configuration.EnableDockedMode; System.State.DockedMode = Configuration.EnableDockedMode;
System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default; System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
System.EnablePtc = Configuration.EnablePtc; System.EnablePtc = Configuration.EnablePtc;
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel; System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode; System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
UpdateVSyncInterval();
#pragma warning restore IDE0055 #pragma warning restore IDE0055
} }
@@ -83,37 +75,9 @@ namespace Ryujinx.HLE
Gpu.GPFifo.DispatchCalls(); 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 LoadCart(string exeFsDir, string romFsFile = null) => Processes.LoadUnpackedNca(exeFsDir, romFsFile);
public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId); public bool LoadXci(string xciFile, ulong applicationId = 0) => Processes.LoadXci(xciFile, applicationId);
public bool LoadNca(string ncaFile, BlitStruct<ApplicationControlProperty>? customNacpData = null) => Processes.LoadNca(ncaFile, customNacpData); public bool LoadNca(string ncaFile) => Processes.LoadNca(ncaFile);
public bool LoadNsp(string nspFile, ulong applicationId = 0) => Processes.LoadNsp(nspFile, applicationId); public bool LoadNsp(string nspFile, ulong applicationId = 0) => Processes.LoadNsp(nspFile, applicationId);
public bool LoadProgram(string fileName) => Processes.LoadNxo(fileName); public bool LoadProgram(string fileName) => Processes.LoadNxo(fileName);

View File

@@ -24,18 +24,6 @@ namespace Ryujinx.HLE.UI
/// <returns>True when OK is pressed, False otherwise.</returns> /// <returns>True when OK is pressed, False otherwise.</returns>
bool DisplayMessageDialog(ControllerAppletUIArgs args); 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> /// <summary>
/// Tell the UI that we need to transition to another program. /// Tell the UI that we need to transition to another program.
/// </summary> /// </summary>

View File

@@ -115,11 +115,8 @@ namespace Ryujinx.Headless.SDL2
[Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")] [Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")]
public int FsGlobalAccessLogMode { get; set; } public int FsGlobalAccessLogMode { get; set; }
[Option("vsync-mode", Required = false, Default = VSyncMode.Switch, HelpText = "Sets the emulated VSync mode (Switch, Unbounded, or Custom).")] [Option("disable-vsync", Required = false, HelpText = "Disables Vertical Sync.")]
public VSyncMode VSyncMode { get; set; } public bool DisableVSync { 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.")] [Option("disable-shader-cache", Required = false, HelpText = "Disables Shader cache.")]
public bool DisableShaderCache { get; set; } public bool DisableShaderCache { get; set; }

View File

@@ -1,5 +1,4 @@
using CommandLine; using CommandLine;
using Gommon;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Common; using Ryujinx.Common;
@@ -97,13 +96,8 @@ namespace Ryujinx.Headless.SDL2
} }
Parser.Default.ParseArguments<Options>(args) Parser.Default.ParseArguments<Options>(args)
.WithParsed(Load) .WithParsed(Load)
.WithNotParsed(errors => .WithNotParsed(errors => errors.Output());
{
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) private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
@@ -569,7 +563,7 @@ namespace Ryujinx.Headless.SDL2
window, window,
options.SystemLanguage, options.SystemLanguage,
options.SystemRegion, options.SystemRegion,
options.VSyncMode, !options.DisableVSync,
!options.DisableDockedMode, !options.DisableDockedMode,
!options.DisablePTC, !options.DisablePTC,
options.EnableInternetAccess, options.EnableInternetAccess,
@@ -585,9 +579,8 @@ namespace Ryujinx.Headless.SDL2
options.MultiplayerLanInterfaceId, options.MultiplayerLanInterfaceId,
Common.Configuration.Multiplayer.MultiplayerMode.Disabled, Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
false, false,
string.Empty, "",
string.Empty, "");
options.CustomVSyncInterval);
return new Switch(configuration); return new Switch(configuration);
} }

View File

@@ -9,7 +9,6 @@
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants> <DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate> <SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
<TieredPGO>true</TieredPGO> <TieredPGO>true</TieredPGO>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Headless.SDL2 namespace Ryujinx.Headless.SDL2
{ {
class StatusUpdatedEventArgs( class StatusUpdatedEventArgs(
string vSyncMode, bool vSyncEnabled,
string dockedMode, string dockedMode,
string aspectRatio, string aspectRatio,
string gameStatus, string gameStatus,
@@ -11,7 +11,7 @@ namespace Ryujinx.Headless.SDL2
string gpuName) string gpuName)
: EventArgs : EventArgs
{ {
public string VSyncMode = vSyncMode; public bool VSyncEnabled = vSyncEnabled;
public string DockedMode = dockedMode; public string DockedMode = dockedMode;
public string AspectRatio = aspectRatio; public string AspectRatio = aspectRatio;
public string GameStatus = gameStatus; public string GameStatus = gameStatus;

View File

@@ -1,5 +1,4 @@
using Humanizer; using Humanizer;
using LibHac.Tools.Fs;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -315,7 +314,7 @@ namespace Ryujinx.Headless.SDL2
} }
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs( StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.VSyncMode.ToString(), Device.EnableDeviceVsync,
dockedMode, dockedMode,
Device.Configuration.AspectRatio.ToText(), Device.Configuration.AspectRatio.ToText(),
$"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
@@ -486,19 +485,6 @@ namespace Ryujinx.Headless.SDL2
return true; 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) public bool DisplayMessageDialog(ControllerAppletUIArgs args)
{ {
if (_ignoreControllerApplet) return false; if (_ignoreControllerApplet) return false;

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,8 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@@ -10,7 +10,6 @@
<TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">linux</TargetOS> <TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">linux</TargetOS>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<RunSettingsFilePath>$(MSBuildProjectDirectory)\.runsettings</RunSettingsFilePath> <RunSettingsFilePath>$(MSBuildProjectDirectory)\.runsettings</RunSettingsFilePath>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@@ -1,4 +1,5 @@
using DynamicData; using DynamicData;
using DynamicData.Kernel;
using Gommon; using Gommon;
using LibHac; using LibHac;
using LibHac.Common; using LibHac.Common;
@@ -36,13 +37,14 @@ using System.Threading.Tasks;
using ContentType = LibHac.Ncm.ContentType; using ContentType = LibHac.Ncm.ContentType;
using MissingKeyException = LibHac.Common.Keys.MissingKeyException; using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
using Path = System.IO.Path; using Path = System.IO.Path;
using SpanHelpers = LibHac.Common.SpanHelpers;
using TimeSpan = System.TimeSpan; using TimeSpan = System.TimeSpan;
namespace Ryujinx.UI.App.Common namespace Ryujinx.UI.App.Common
{ {
public class ApplicationLibrary public class ApplicationLibrary
{ {
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com"; public static string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
public Language DesiredLanguage { get; set; } public Language DesiredLanguage { get; set; }
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated; public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived; public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
@@ -189,9 +191,12 @@ namespace Ryujinx.UI.App.Common
} }
} }
return isExeFs if (isExeFs)
? GetApplicationFromExeFs(pfs, filePath) {
: null; return GetApplicationFromExeFs(pfs, filePath);
}
return null;
} }
/// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception> /// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception>
@@ -507,6 +512,10 @@ namespace Ryujinx.UI.App.Common
case ".xci": case ".xci":
case ".nsp": case ".nsp":
{ {
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem); using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem);
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
@@ -595,7 +604,7 @@ namespace Ryujinx.UI.App.Common
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None) controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None)
.OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read) .OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read)
.ThrowIfFailure(); .ThrowIfFailure();
nacpFile.Get.Read(out _, 0, LibHac.Common.SpanHelpers.AsByteSpan(ref controlData), nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData),
ReadOption.None).ThrowIfFailure(); ReadOption.None).ThrowIfFailure();
var displayVersion = controlData.DisplayVersionString.ToString(); var displayVersion = controlData.DisplayVersionString.ToString();
@@ -818,7 +827,7 @@ namespace Ryujinx.UI.App.Common
{ {
_downloadableContents.Edit(it => _downloadableContents.Edit(it =>
{ {
DownloadableContentsHelper.SaveDownloadableContentsJson(application.IdBase, dlcs); DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, application.IdBase, dlcs);
it.Remove(it.Items.Where(item => item.Dlc.TitleIdBase == application.IdBase)); it.Remove(it.Items.Where(item => item.Dlc.TitleIdBase == application.IdBase));
it.AddOrUpdate(dlcs); it.AddOrUpdate(dlcs);
@@ -830,7 +839,7 @@ namespace Ryujinx.UI.App.Common
{ {
_titleUpdates.Edit(it => _titleUpdates.Edit(it =>
{ {
TitleUpdatesHelper.SaveTitleUpdatesJson(application.IdBase, updates); TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, application.IdBase, updates);
it.Remove(it.Items.Where(item => item.TitleUpdate.TitleIdBase == application.IdBase)); it.Remove(it.Items.Where(item => item.TitleUpdate.TitleIdBase == application.IdBase));
it.AddOrUpdate(updates); it.AddOrUpdate(updates);
@@ -1079,12 +1088,11 @@ namespace Ryujinx.UI.App.Common
private bool AddAndAutoSelectUpdate(TitleUpdateModel update) private bool AddAndAutoSelectUpdate(TitleUpdateModel update)
{ {
if (update == null) return false; var currentlySelected = TitleUpdates.Items.FirstOrOptional(it =>
var currentlySelected = TitleUpdates.Items.FindFirst(it =>
it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected); it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected);
var shouldSelect = currentlySelected.Check(curr => curr.TitleUpdate?.Version < update.Version); var shouldSelect = !currentlySelected.HasValue ||
currentlySelected.Value.TitleUpdate.Version < update.Version;
_titleUpdates.AddOrUpdate((update, shouldSelect)); _titleUpdates.AddOrUpdate((update, shouldSelect));
@@ -1456,7 +1464,7 @@ namespace Ryujinx.UI.App.Common
if (addedNewDlc) if (addedNewDlc)
{ {
var gameDlcs = it.Items.Where(dlc => dlc.Dlc.TitleIdBase == application.IdBase).ToList(); var gameDlcs = it.Items.Where(dlc => dlc.Dlc.TitleIdBase == application.IdBase).ToList();
DownloadableContentsHelper.SaveDownloadableContentsJson(application.IdBase, DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, application.IdBase,
gameDlcs); gameDlcs);
} }
} }
@@ -1475,11 +1483,11 @@ namespace Ryujinx.UI.App.Common
TitleUpdatesHelper.LoadTitleUpdatesJson(_virtualFileSystem, application.IdBase); TitleUpdatesHelper.LoadTitleUpdatesJson(_virtualFileSystem, application.IdBase);
it.AddOrUpdate(savedUpdates); it.AddOrUpdate(savedUpdates);
var selectedUpdate = savedUpdates.FindFirst(update => update.IsSelected); var selectedUpdate = savedUpdates.FirstOrOptional(update => update.IsSelected);
if (TryGetTitleUpdatesFromFile(application.Path, out var bundledUpdates)) if (TryGetTitleUpdatesFromFile(application.Path, out var bundledUpdates))
{ {
var savedUpdateLookup = savedUpdates.Select(update => update.Update).ToHashSet(); var savedUpdateLookup = savedUpdates.Select(update => update.Item1).ToHashSet();
bool updatesChanged = false; bool updatesChanged = false;
foreach (var update in bundledUpdates.OrderByDescending(bundled => bundled.Version)) foreach (var update in bundledUpdates.OrderByDescending(bundled => bundled.Version))
@@ -1487,11 +1495,12 @@ namespace Ryujinx.UI.App.Common
if (!savedUpdateLookup.Contains(update)) if (!savedUpdateLookup.Contains(update))
{ {
bool shouldSelect = false; bool shouldSelect = false;
if (selectedUpdate.Check(su => su.Update?.Version < update.Version)) if (!selectedUpdate.HasValue || selectedUpdate.Value.Item1.Version < update.Version)
{ {
shouldSelect = true; shouldSelect = true;
_titleUpdates.AddOrUpdate((selectedUpdate.Value.Update, false)); if (selectedUpdate.HasValue)
selectedUpdate = (update, true); _titleUpdates.AddOrUpdate((selectedUpdate.Value.Item1, false));
selectedUpdate = DynamicData.Kernel.Optional<(TitleUpdateModel, bool IsSelected)>.Create((update, true));
} }
modifiedVersion = modifiedVersion || shouldSelect; modifiedVersion = modifiedVersion || shouldSelect;
@@ -1504,7 +1513,7 @@ namespace Ryujinx.UI.App.Common
if (updatesChanged) if (updatesChanged)
{ {
var gameUpdates = it.Items.Where(update => update.TitleUpdate.TitleIdBase == application.IdBase).ToList(); var gameUpdates = it.Items.Where(update => update.TitleUpdate.TitleIdBase == application.IdBase).ToList();
TitleUpdatesHelper.SaveTitleUpdatesJson(application.IdBase, gameUpdates); TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, application.IdBase, gameUpdates);
} }
} }
}); });
@@ -1516,14 +1525,14 @@ namespace Ryujinx.UI.App.Common
private void SaveDownloadableContentsForGame(ulong titleIdBase) private void SaveDownloadableContentsForGame(ulong titleIdBase)
{ {
var dlcs = DownloadableContents.Items.Where(dlc => dlc.Dlc.TitleIdBase == titleIdBase).ToList(); var dlcs = DownloadableContents.Items.Where(dlc => dlc.Dlc.TitleIdBase == titleIdBase).ToList();
DownloadableContentsHelper.SaveDownloadableContentsJson(titleIdBase, dlcs); DownloadableContentsHelper.SaveDownloadableContentsJson(_virtualFileSystem, titleIdBase, dlcs);
} }
// Save the _currently tracked_ update state for the game // Save the _currently tracked_ update state for the game
private void SaveTitleUpdatesForGame(ulong titleIdBase) private void SaveTitleUpdatesForGame(ulong titleIdBase)
{ {
var updates = TitleUpdates.Items.Where(update => update.TitleUpdate.TitleIdBase == titleIdBase).ToList(); var updates = TitleUpdates.Items.Where(update => update.TitleUpdate.TitleIdBase == titleIdBase).ToList();
TitleUpdatesHelper.SaveTitleUpdatesJson(titleIdBase, updates); TitleUpdatesHelper.SaveTitleUpdatesJson(_virtualFileSystem, titleIdBase, updates);
} }
// ApplicationData isnt live-updating (e.g. when an update gets applied) and so this is meant to trigger a refresh // ApplicationData isnt live-updating (e.g. when an update gets applied) and so this is meant to trigger a refresh

View File

@@ -1,4 +1,3 @@
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
@@ -17,7 +16,7 @@ namespace Ryujinx.UI.Common.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 57; public const int CurrentVersion = 56;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@@ -192,25 +191,8 @@ namespace Ryujinx.UI.Common.Configuration
/// <summary> /// <summary>
/// Enables or disables Vertical Sync /// Enables or disables Vertical Sync
/// </summary> /// </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; } 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> /// <summary>
/// Enables or disables Shader cache /// Enables or disables Shader cache
/// </summary> /// </summary>

View File

@@ -82,7 +82,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = Key.F1, ToggleVsync = Key.F1,
}; };
configurationFileUpdated = true; configurationFileUpdated = true;
@@ -276,7 +276,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = Key.F1, ToggleVsync = Key.F1,
Screenshot = Key.F8, Screenshot = Key.F8,
}; };
@@ -289,7 +289,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = Key.F1, ToggleVsync = Key.F1,
Screenshot = Key.F8, Screenshot = Key.F8,
ShowUI = Key.F4, ShowUI = Key.F4,
}; };
@@ -332,7 +332,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode, ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = Key.F5, Pause = Key.F5,
@@ -347,7 +347,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode, ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
@@ -421,7 +421,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode, ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
@@ -448,7 +448,7 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode, ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
Screenshot = configurationFileFormat.Hotkeys.Screenshot, Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI, ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause, Pause = configurationFileFormat.Hotkeys.Pause,
@@ -611,33 +611,6 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileUpdated = true; 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; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
@@ -673,9 +646,7 @@ namespace Ryujinx.UI.Common.Configuration
ShowTitleBar.Value = configurationFileFormat.ShowTitleBar; ShowTitleBar.Value = configurationFileFormat.ShowTitleBar;
EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration; EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration;
HideCursor.Value = configurationFileFormat.HideCursor; HideCursor.Value = configurationFileFormat.HideCursor;
Graphics.VSyncMode.Value = configurationFileFormat.VSyncMode; Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
Graphics.EnableCustomVSyncInterval.Value = configurationFileFormat.EnableCustomVSyncInterval;
Graphics.CustomVSyncInterval.Value = configurationFileFormat.CustomVSyncInterval;
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression; Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE; Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;

View File

@@ -1,4 +1,4 @@
using ARMeilleure; using ARMeilleure;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@@ -474,19 +474,9 @@ namespace Ryujinx.UI.Common.Configuration
public ReactiveObject<string> ShadersDumpPath { get; private set; } public ReactiveObject<string> ShadersDumpPath { get; private set; }
/// <summary> /// <summary>
/// Toggles the present interval mode. Options are Switch (60Hz), Unbounded (previously Vsync off), and Custom, if enabled. /// Enables or disables Vertical Sync
/// </summary> /// </summary>
public ReactiveObject<VSyncMode> VSyncMode { get; private set; } public ReactiveObject<bool> EnableVsync { 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> /// <summary>
/// Enables or disables Shader cache /// Enables or disables Shader cache
@@ -546,12 +536,8 @@ namespace Ryujinx.UI.Common.Configuration
AspectRatio = new ReactiveObject<AspectRatio>(); AspectRatio = new ReactiveObject<AspectRatio>();
AspectRatio.LogChangesToValue(nameof(AspectRatio)); AspectRatio.LogChangesToValue(nameof(AspectRatio));
ShadersDumpPath = new ReactiveObject<string>(); ShadersDumpPath = new ReactiveObject<string>();
VSyncMode = new ReactiveObject<VSyncMode>(); EnableVsync = new ReactiveObject<bool>();
VSyncMode.LogChangesToValue(nameof(VSyncMode)); EnableVsync.LogChangesToValue(nameof(EnableVsync));
EnableCustomVSyncInterval = new ReactiveObject<bool>();
EnableCustomVSyncInterval.LogChangesToValue(nameof(EnableCustomVSyncInterval));
CustomVSyncInterval = new ReactiveObject<int>();
CustomVSyncInterval.LogChangesToValue(nameof(CustomVSyncInterval));
EnableShaderCache = new ReactiveObject<bool>(); EnableShaderCache = new ReactiveObject<bool>();
EnableShaderCache.LogChangesToValue(nameof(EnableShaderCache)); EnableShaderCache.LogChangesToValue(nameof(EnableShaderCache));
EnableTextureRecompression = new ReactiveObject<bool>(); EnableTextureRecompression = new ReactiveObject<bool>();

View File

@@ -1,12 +1,16 @@
using ARMeilleure;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.UI.Common.Configuration.System; using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Configuration.UI; using Ryujinx.UI.Common.Configuration.UI;
using System; using System;
using System.Collections.Generic;
namespace Ryujinx.UI.Common.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
@@ -17,10 +21,10 @@ namespace Ryujinx.UI.Common.Configuration
if (Instance != null) if (Instance != null)
{ {
throw new InvalidOperationException("Configuration is already initialized"); throw new InvalidOperationException("Configuration is already initialized");
} }
Instance = new ConfigurationState(); Instance = new ConfigurationState();
} }
public ConfigurationFileFormat ToFileFormat() public ConfigurationFileFormat ToFileFormat()
{ {
@@ -60,9 +64,7 @@ namespace Ryujinx.UI.Common.Configuration
ShowTitleBar = ShowTitleBar, ShowTitleBar = ShowTitleBar,
EnableHardwareAcceleration = EnableHardwareAcceleration, EnableHardwareAcceleration = EnableHardwareAcceleration,
HideCursor = HideCursor, HideCursor = HideCursor,
VSyncMode = Graphics.VSyncMode, EnableVsync = Graphics.EnableVsync,
EnableCustomVSyncInterval = Graphics.EnableCustomVSyncInterval,
CustomVSyncInterval = Graphics.CustomVSyncInterval,
EnableShaderCache = Graphics.EnableShaderCache, EnableShaderCache = Graphics.EnableShaderCache,
EnableTextureRecompression = Graphics.EnableTextureRecompression, EnableTextureRecompression = Graphics.EnableTextureRecompression,
EnableMacroHLE = Graphics.EnableMacroHLE, EnableMacroHLE = Graphics.EnableMacroHLE,
@@ -177,9 +179,7 @@ namespace Ryujinx.UI.Common.Configuration
ShowTitleBar.Value = !OperatingSystem.IsWindows(); ShowTitleBar.Value = !OperatingSystem.IsWindows();
EnableHardwareAcceleration.Value = true; EnableHardwareAcceleration.Value = true;
HideCursor.Value = HideCursorMode.OnIdle; HideCursor.Value = HideCursorMode.OnIdle;
Graphics.VSyncMode.Value = VSyncMode.Switch; Graphics.EnableVsync.Value = true;
Graphics.CustomVSyncInterval.Value = 120;
Graphics.EnableCustomVSyncInterval.Value = false;
Graphics.EnableShaderCache.Value = true; Graphics.EnableShaderCache.Value = true;
Graphics.EnableTextureRecompression.Value = false; Graphics.EnableTextureRecompression.Value = false;
Graphics.EnableMacroHLE.Value = true; Graphics.EnableMacroHLE.Value = true;
@@ -240,7 +240,7 @@ namespace Ryujinx.UI.Common.Configuration
Hid.EnableMouse.Value = false; Hid.EnableMouse.Value = false;
Hid.Hotkeys.Value = new KeyboardHotkeys Hid.Hotkeys.Value = new KeyboardHotkeys
{ {
ToggleVSyncMode = Key.F1, ToggleVsync = Key.F1,
ToggleMute = Key.F2, ToggleMute = Key.F2,
Screenshot = Key.F8, Screenshot = Key.F8,
ShowUI = Key.F4, ShowUI = Key.F4,

View File

@@ -247,7 +247,6 @@ namespace Ryujinx.UI.Common
"0100dbf01000a000", // Burnout Paradise Remastered "0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win "0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast "0100b41013c82000", // Cruis'n Blast
"01001b300b9be000", // Diablo III: Eternal Collection
"01008c8012920000", // Dying Light Platinum Edition "01008c8012920000", // Dying Light Platinum Edition
"010073c01af34000", // LEGO Horizon Adventures "010073c01af34000", // LEGO Horizon Adventures
"0100770008dd8000", // Monster Hunter Generations Ultimate "0100770008dd8000", // Monster Hunter Generations Ultimate

View File

@@ -7,24 +7,6 @@ namespace Ryujinx.UI.Common.Helper
{ {
public static partial class ConsoleHelper 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 bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
public static void SetConsoleWindowState(bool show) public static void SetConsoleWindowState(bool show)
@@ -53,11 +35,16 @@ namespace Ryujinx.UI.Common.Helper
return; return;
} }
SetForegroundWindow(hWnd);
hWnd = GetForegroundWindow();
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE); 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);
} }
} }

View File

@@ -42,7 +42,7 @@ namespace Ryujinx.UI.Common.Helper
} }
} }
public static void SaveDownloadableContentsJson(ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs) public static void SaveDownloadableContentsJson(VirtualFileSystem vfs, ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs)
{ {
DownloadableContentContainer container = default; DownloadableContentContainer container = default;
List<DownloadableContentContainer> downloadableContentContainerList = new(); List<DownloadableContentContainer> downloadableContentContainerList = new();

View File

@@ -28,7 +28,7 @@ namespace Ryujinx.UI.Common.Helper
{ {
private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public static List<(TitleUpdateModel Update, bool IsSelected)> LoadTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase) public static List<(TitleUpdateModel, bool IsSelected)> LoadTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase)
{ {
var titleUpdatesJsonPath = PathToGameUpdatesJson(applicationIdBase); var titleUpdatesJsonPath = PathToGameUpdatesJson(applicationIdBase);
@@ -49,7 +49,7 @@ namespace Ryujinx.UI.Common.Helper
} }
} }
public static void SaveTitleUpdatesJson(ulong applicationIdBase, List<(TitleUpdateModel, bool IsSelected)> updates) public static void SaveTitleUpdatesJson(VirtualFileSystem vfs, ulong applicationIdBase, List<(TitleUpdateModel, bool IsSelected)> updates)
{ {
var titleUpdateWindowData = new TitleUpdateMetadata var titleUpdateWindowData = new TitleUpdateMetadata
{ {
@@ -77,7 +77,7 @@ namespace Ryujinx.UI.Common.Helper
JsonHelper.SerializeToFile(titleUpdatesJsonPath, titleUpdateWindowData, _serializerContext.TitleUpdateMetadata); JsonHelper.SerializeToFile(titleUpdatesJsonPath, titleUpdateWindowData, _serializerContext.TitleUpdateMetadata);
} }
private static List<(TitleUpdateModel Update, bool IsSelected)> LoadTitleUpdates(VirtualFileSystem vfs, TitleUpdateMetadata titleUpdateMetadata, ulong applicationIdBase) private static List<(TitleUpdateModel, bool IsSelected)> LoadTitleUpdates(VirtualFileSystem vfs, TitleUpdateMetadata titleUpdateMetadata, ulong applicationIdBase)
{ {
var result = new List<(TitleUpdateModel, bool IsSelected)>(); var result = new List<(TitleUpdateModel, bool IsSelected)>();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 KiB

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