Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
56fe2ff535 | ||
|
b1f8f868f6 | ||
|
d773d5152e | ||
|
33ba170315 | ||
|
638be5f296 | ||
|
49b37550ca | ||
|
a42f0bbb87 | ||
|
b4bb22ba06 | ||
|
6fdf774845 | ||
|
76b53e018a | ||
|
28dd7d80af | ||
|
1e06b28b22 | ||
|
e768a54f17 | ||
|
4e2bb13080 | ||
|
ac4f2c1e70 |
@@ -3,13 +3,13 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.0.4" />
|
<PackageVersion Include="Avalonia" Version="11.0.5" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.4" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.5" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.4" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.0.5" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.4" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.5" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.4" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.5" />
|
||||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.2" />
|
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.3" />
|
||||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.2" />
|
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.3" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="1.1.7" />
|
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||||
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
|
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
|
||||||
<PackageVersion Include="LibHac" Version="0.18.0" />
|
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||||
@@ -35,6 +35,7 @@
|
|||||||
<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.GtkSharp" Version="3.24.24.59-ryujinx" />
|
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
|
||||||
|
<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" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||||
|
@@ -141,3 +141,4 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY
|
|||||||
|
|
||||||
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||||
|
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
||||||
|
@@ -682,3 +682,32 @@
|
|||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
# ShellLink (MIT)
|
||||||
|
<details>
|
||||||
|
<summary>See License</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Yorick Koster, Securify B.V.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
```
|
||||||
|
</details>
|
@@ -3,8 +3,8 @@ Version=1.0
|
|||||||
Name=Ryujinx
|
Name=Ryujinx
|
||||||
Type=Application
|
Type=Application
|
||||||
Icon=Ryujinx
|
Icon=Ryujinx
|
||||||
Exec=env DOTNET_EnableAlternateStackCheck=1 Ryujinx %f
|
Exec=Ryujinx.sh %f
|
||||||
Comment=A Nintendo Switch Emulator
|
Comment=Plays Nintendo Switch applications
|
||||||
GenericName=Nintendo Switch Emulator
|
GenericName=Nintendo Switch Emulator
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Categories=Game;Emulator;
|
Categories=Game;Emulator;
|
||||||
|
13
distribution/linux/shortcut-template.desktop
Normal file
13
distribution/linux/shortcut-template.desktop
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Name={0}
|
||||||
|
Type=Application
|
||||||
|
Icon={1}
|
||||||
|
Exec={2} %f
|
||||||
|
Comment=Nintendo Switch application
|
||||||
|
GenericName=Nintendo Switch Emulator
|
||||||
|
Terminal=false
|
||||||
|
Categories=Game;Emulator;
|
||||||
|
Keywords=Switch;Nintendo;Emulator;
|
||||||
|
StartupWMClass=Ryujinx
|
||||||
|
PrefersNonDefaultGPU=true
|
35
distribution/macos/shortcut-template.plist
Normal file
35
distribution/macos/shortcut-template.plist
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>{0}</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>{1}</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>{2}</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<true/>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string>public.app-category.games</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>11.0</string>
|
||||||
|
<key>UIPrerenderedIcon</key>
|
||||||
|
<true/>
|
||||||
|
<key>LSEnvironment</key>
|
||||||
|
<dict>
|
||||||
|
<key>DOTNET_DefaultStackSize</key>
|
||||||
|
<string>200000</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -7,14 +7,14 @@ namespace ARMeilleure.Translation
|
|||||||
internal class TranslatorCache<T>
|
internal class TranslatorCache<T>
|
||||||
{
|
{
|
||||||
private readonly IntervalTree<ulong, T> _tree;
|
private readonly IntervalTree<ulong, T> _tree;
|
||||||
private readonly ReaderWriterLock _treeLock;
|
private readonly ReaderWriterLockSlim _treeLock;
|
||||||
|
|
||||||
public int Count => _tree.Count;
|
public int Count => _tree.Count;
|
||||||
|
|
||||||
public TranslatorCache()
|
public TranslatorCache()
|
||||||
{
|
{
|
||||||
_tree = new IntervalTree<ulong, T>();
|
_tree = new IntervalTree<ulong, T>();
|
||||||
_treeLock = new ReaderWriterLock();
|
_treeLock = new ReaderWriterLockSlim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryAdd(ulong address, ulong size, T value)
|
public bool TryAdd(ulong address, ulong size, T value)
|
||||||
@@ -24,70 +24,70 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public bool AddOrUpdate(ulong address, ulong size, T value, Func<ulong, T, T> updateFactoryCallback)
|
public bool AddOrUpdate(ulong address, ulong size, T value, Func<ulong, T, T> updateFactoryCallback)
|
||||||
{
|
{
|
||||||
_treeLock.AcquireWriterLock(Timeout.Infinite);
|
_treeLock.EnterWriteLock();
|
||||||
bool result = _tree.AddOrUpdate(address, address + size, value, updateFactoryCallback);
|
bool result = _tree.AddOrUpdate(address, address + size, value, updateFactoryCallback);
|
||||||
_treeLock.ReleaseWriterLock();
|
_treeLock.ExitWriteLock();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetOrAdd(ulong address, ulong size, T value)
|
public T GetOrAdd(ulong address, ulong size, T value)
|
||||||
{
|
{
|
||||||
_treeLock.AcquireWriterLock(Timeout.Infinite);
|
_treeLock.EnterWriteLock();
|
||||||
value = _tree.GetOrAdd(address, address + size, value);
|
value = _tree.GetOrAdd(address, address + size, value);
|
||||||
_treeLock.ReleaseWriterLock();
|
_treeLock.ExitWriteLock();
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(ulong address)
|
public bool Remove(ulong address)
|
||||||
{
|
{
|
||||||
_treeLock.AcquireWriterLock(Timeout.Infinite);
|
_treeLock.EnterWriteLock();
|
||||||
bool removed = _tree.Remove(address) != 0;
|
bool removed = _tree.Remove(address) != 0;
|
||||||
_treeLock.ReleaseWriterLock();
|
_treeLock.ExitWriteLock();
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
_treeLock.AcquireWriterLock(Timeout.Infinite);
|
_treeLock.EnterWriteLock();
|
||||||
_tree.Clear();
|
_tree.Clear();
|
||||||
_treeLock.ReleaseWriterLock();
|
_treeLock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(ulong address)
|
public bool ContainsKey(ulong address)
|
||||||
{
|
{
|
||||||
_treeLock.AcquireReaderLock(Timeout.Infinite);
|
_treeLock.EnterReadLock();
|
||||||
bool result = _tree.ContainsKey(address);
|
bool result = _tree.ContainsKey(address);
|
||||||
_treeLock.ReleaseReaderLock();
|
_treeLock.ExitReadLock();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(ulong address, out T value)
|
public bool TryGetValue(ulong address, out T value)
|
||||||
{
|
{
|
||||||
_treeLock.AcquireReaderLock(Timeout.Infinite);
|
_treeLock.EnterReadLock();
|
||||||
bool result = _tree.TryGet(address, out value);
|
bool result = _tree.TryGet(address, out value);
|
||||||
_treeLock.ReleaseReaderLock();
|
_treeLock.ExitReadLock();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOverlaps(ulong address, ulong size, ref ulong[] overlaps)
|
public int GetOverlaps(ulong address, ulong size, ref ulong[] overlaps)
|
||||||
{
|
{
|
||||||
_treeLock.AcquireReaderLock(Timeout.Infinite);
|
_treeLock.EnterReadLock();
|
||||||
int count = _tree.Get(address, address + size, ref overlaps);
|
int count = _tree.Get(address, address + size, ref overlaps);
|
||||||
_treeLock.ReleaseReaderLock();
|
_treeLock.ExitReadLock();
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> AsList()
|
public List<T> AsList()
|
||||||
{
|
{
|
||||||
_treeLock.AcquireReaderLock(Timeout.Infinite);
|
_treeLock.EnterReadLock();
|
||||||
List<T> list = _tree.AsList();
|
List<T> list = _tree.AsList();
|
||||||
_treeLock.ReleaseReaderLock();
|
_treeLock.ExitReadLock();
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,8 @@
|
|||||||
"GameListContextMenuExtractDataRomFSToolTip": "Extract the RomFS section from Application's current config (including updates)",
|
"GameListContextMenuExtractDataRomFSToolTip": "Extract the RomFS section from Application's current config (including updates)",
|
||||||
"GameListContextMenuExtractDataLogo": "Logo",
|
"GameListContextMenuExtractDataLogo": "Logo",
|
||||||
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
|
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
|
||||||
|
"GameListContextMenuCreateShortcut": "Create Application Shortcut",
|
||||||
|
"GameListContextMenuCreateShortcutToolTip": "Create a Desktop Shortcut that launches the selected Application",
|
||||||
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
|
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
|
||||||
"StatusBarSystemVersion": "System Version: {0}",
|
"StatusBarSystemVersion": "System Version: {0}",
|
||||||
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",
|
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",
|
||||||
|
@@ -173,7 +173,7 @@ namespace Ryujinx.Ava.Common
|
|||||||
string extension = Path.GetExtension(titleFilePath).ToLower();
|
string extension = Path.GetExtension(titleFilePath).ToLower();
|
||||||
if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
|
if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
|
||||||
{
|
{
|
||||||
PartitionFileSystem pfs;
|
IFileSystem pfs;
|
||||||
|
|
||||||
if (extension == ".xci")
|
if (extension == ".xci")
|
||||||
{
|
{
|
||||||
@@ -181,7 +181,9 @@ namespace Ryujinx.Ava.Common
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pfs = new PartitionFileSystem(file.AsStorage());
|
var pfsTemp = new PartitionFileSystem();
|
||||||
|
pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
|
||||||
|
pfs = pfsTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
|
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
|
||||||
|
@@ -82,4 +82,9 @@
|
|||||||
Header="{locale:Locale GameListContextMenuExtractDataLogo}"
|
Header="{locale:Locale GameListContextMenuExtractDataLogo}"
|
||||||
ToolTip.Tip="{locale:Locale GameListContextMenuExtractDataLogoToolTip}" />
|
ToolTip.Tip="{locale:Locale GameListContextMenuExtractDataLogoToolTip}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
Click="CreateApplicationShortcut_Click"
|
||||||
|
Header="{locale:Locale GameListContextMenuCreateShortcut}"
|
||||||
|
IsEnabled="{Binding CreateShortcutEnabled}"
|
||||||
|
ToolTip.Tip="{locale:Locale GameListContextMenuCreateShortcutToolTip}" />
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
@@ -337,6 +337,17 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||||
|
|
||||||
|
if (viewModel?.SelectedApplication != null)
|
||||||
|
{
|
||||||
|
ApplicationData selectedApplication = viewModel.SelectedApplication;
|
||||||
|
ShortcutHelper.CreateAppShortcut(selectedApplication.Path, selectedApplication.TitleName, selectedApplication.TitleId, selectedApplication.Icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async void RunApplication_Click(object sender, RoutedEventArgs args)
|
public async void RunApplication_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||||
|
31
src/Ryujinx.Ava/UI/Controls/SliderScroll.axaml.cs
Normal file
31
src/Ryujinx.Ava/UI/Controls/SliderScroll.axaml.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
|
{
|
||||||
|
public class SliderScroll : Slider
|
||||||
|
{
|
||||||
|
protected override Type StyleKeyOverride => typeof(Slider);
|
||||||
|
|
||||||
|
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
|
||||||
|
{
|
||||||
|
var newValue = Value + e.Delta.Y * TickFrequency;
|
||||||
|
|
||||||
|
if (newValue < Minimum)
|
||||||
|
{
|
||||||
|
Value = Minimum;
|
||||||
|
}
|
||||||
|
else if (newValue > Maximum)
|
||||||
|
{
|
||||||
|
Value = Maximum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -126,7 +126,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
{
|
{
|
||||||
using FileStream containerFile = File.OpenRead(downloadableContentContainer.ContainerPath);
|
using FileStream containerFile = File.OpenRead(downloadableContentContainer.ContainerPath);
|
||||||
|
|
||||||
PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
|
PartitionFileSystem partitionFileSystem = new();
|
||||||
|
partitionFileSystem.Initialize(containerFile.AsStorage()).ThrowIfFailure();
|
||||||
|
|
||||||
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
||||||
|
|
||||||
@@ -232,7 +233,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
using FileStream containerFile = File.OpenRead(path);
|
using FileStream containerFile = File.OpenRead(path);
|
||||||
|
|
||||||
PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
|
PartitionFileSystem partitionFileSystem = new();
|
||||||
|
partitionFileSystem.Initialize(containerFile.AsStorage()).ThrowIfFailure();
|
||||||
bool containsDownloadableContent = false;
|
bool containsDownloadableContent = false;
|
||||||
|
|
||||||
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
||||||
|
@@ -356,6 +356,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
|
public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
|
||||||
|
|
||||||
|
public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild();
|
||||||
|
|
||||||
public string LoadHeading
|
public string LoadHeading
|
||||||
{
|
{
|
||||||
get => _loadHeading;
|
get => _loadHeading;
|
||||||
@@ -1278,6 +1280,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
Glyph = Glyph.Grid;
|
Glyph = Glyph.Grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetAspectRatio(AspectRatio aspectRatio)
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.Graphics.AspectRatio.Value = aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task InstallFirmwareFromFile()
|
public async Task InstallFirmwareFromFile()
|
||||||
{
|
{
|
||||||
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||||
@@ -1483,7 +1490,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
Logger.RestartTime();
|
Logger.RestartTime();
|
||||||
|
|
||||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(path);
|
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(path, ConfigurationState.Instance.System.Language);
|
||||||
|
|
||||||
PrepareLoadScreen();
|
PrepareLoadScreen();
|
||||||
|
|
||||||
@@ -1691,7 +1698,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -170,7 +170,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
(Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(VirtualFileSystem, new PartitionFileSystem(file.AsStorage()), TitleId.ToString("x16"), 0);
|
var pfs = new PartitionFileSystem();
|
||||||
|
pfs.Initialize(file.AsStorage()).ThrowIfFailure();
|
||||||
|
(Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(VirtualFileSystem, pfs, TitleId.ToString("x16"), 0);
|
||||||
|
|
||||||
if (controlNca != null && patchNca != null)
|
if (controlNca != null && patchNca != null)
|
||||||
{
|
{
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
|
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
@@ -460,7 +461,7 @@
|
|||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Width="130"
|
Width="130"
|
||||||
Maximum="1"
|
Maximum="1"
|
||||||
TickFrequency="0.01"
|
TickFrequency="0.01"
|
||||||
@@ -480,7 +481,7 @@
|
|||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Width="130"
|
Width="130"
|
||||||
Maximum="2"
|
Maximum="2"
|
||||||
TickFrequency="0.01"
|
TickFrequency="0.01"
|
||||||
@@ -604,7 +605,7 @@
|
|||||||
<StackPanel
|
<StackPanel
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Width="130"
|
Width="130"
|
||||||
Maximum="1"
|
Maximum="1"
|
||||||
TickFrequency="0.01"
|
TickFrequency="0.01"
|
||||||
@@ -1083,7 +1084,7 @@
|
|||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Width="130"
|
Width="130"
|
||||||
Maximum="1"
|
Maximum="1"
|
||||||
TickFrequency="0.01"
|
TickFrequency="0.01"
|
||||||
@@ -1105,7 +1106,7 @@
|
|||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Width="130"
|
Width="130"
|
||||||
Maximum="2"
|
Maximum="2"
|
||||||
TickFrequency="0.01"
|
TickFrequency="0.01"
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
@@ -23,11 +24,11 @@
|
|||||||
Margin="0"
|
Margin="0"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Text="{locale:Locale ControllerSettingsMotionGyroSensitivity}" />
|
Text="{locale:Locale ControllerSettingsMotionGyroSensitivity}" />
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Margin="0,-5,0,-5"
|
Margin="0,-5,0,-5"
|
||||||
Width="150"
|
Width="150"
|
||||||
MaxWidth="150"
|
MaxWidth="150"
|
||||||
TickFrequency="0.01"
|
TickFrequency="1"
|
||||||
IsSnapToTickEnabled="True"
|
IsSnapToTickEnabled="True"
|
||||||
SmallChange="0.01"
|
SmallChange="0.01"
|
||||||
Maximum="100"
|
Maximum="100"
|
||||||
@@ -45,11 +46,11 @@
|
|||||||
Margin="0"
|
Margin="0"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Text="{locale:Locale ControllerSettingsMotionGyroDeadzone}" />
|
Text="{locale:Locale ControllerSettingsMotionGyroDeadzone}" />
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Margin="0,-5,0,-5"
|
Margin="0,-5,0,-5"
|
||||||
Width="150"
|
Width="150"
|
||||||
MaxWidth="150"
|
MaxWidth="150"
|
||||||
TickFrequency="0.01"
|
TickFrequency="1"
|
||||||
IsSnapToTickEnabled="True"
|
IsSnapToTickEnabled="True"
|
||||||
SmallChange="0.01"
|
SmallChange="0.01"
|
||||||
Maximum="100"
|
Maximum="100"
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
@@ -21,7 +22,7 @@
|
|||||||
TextWrapping="WrapWithOverflow"
|
TextWrapping="WrapWithOverflow"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Text="{locale:Locale ControllerSettingsRumbleStrongMultiplier}" />
|
Text="{locale:Locale ControllerSettingsRumbleStrongMultiplier}" />
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Margin="0,-5,0,-5"
|
Margin="0,-5,0,-5"
|
||||||
Width="200"
|
Width="200"
|
||||||
TickFrequency="0.01"
|
TickFrequency="0.01"
|
||||||
@@ -41,7 +42,7 @@
|
|||||||
TextWrapping="WrapWithOverflow"
|
TextWrapping="WrapWithOverflow"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Text="{locale:Locale ControllerSettingsRumbleWeakMultiplier}" />
|
Text="{locale:Locale ControllerSettingsRumbleWeakMultiplier}" />
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Margin="0,-5,0,-5"
|
Margin="0,-5,0,-5"
|
||||||
Width="200"
|
Width="200"
|
||||||
MaxWidth="200"
|
MaxWidth="200"
|
||||||
|
@@ -3,9 +3,11 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
|
xmlns:config="clr-namespace:Ryujinx.Common.Configuration;assembly=Ryujinx.Common"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView"
|
x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView"
|
||||||
x:DataType="viewModels:MainWindowViewModel">
|
x:DataType="viewModels:MainWindowViewModel">
|
||||||
@@ -112,15 +114,52 @@
|
|||||||
Background="Gray"
|
Background="Gray"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
<TextBlock
|
<SplitButton
|
||||||
Name="AspectRatioStatus"
|
Name="AspectRatioStatus"
|
||||||
Margin="5,0,5,0"
|
Padding="5,0,5,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderThickness="0"
|
||||||
|
CornerRadius="0"
|
||||||
IsVisible="{Binding !ShowLoadProgress}"
|
IsVisible="{Binding !ShowLoadProgress}"
|
||||||
PointerReleased="AspectRatioStatus_PointerReleased"
|
Content="{Binding AspectRatioStatusText}"
|
||||||
Text="{Binding AspectRatioStatusText}"
|
Click="AspectRatioStatus_OnClick"
|
||||||
TextAlignment="Left" />
|
ToolTip.Tip="{locale:Locale AspectRatioTooltip}">
|
||||||
|
<SplitButton.Styles>
|
||||||
|
<Style Selector="Border#SeparatorBorder">
|
||||||
|
<Setter Property="Opacity" Value="0" />
|
||||||
|
</Style>
|
||||||
|
</SplitButton.Styles>
|
||||||
|
<SplitButton.Flyout>
|
||||||
|
<MenuFlyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
|
||||||
|
<MenuItem
|
||||||
|
Header="{locale:Locale SettingsTabGraphicsAspectRatio4x3}"
|
||||||
|
Command="{Binding SetAspectRatio}"
|
||||||
|
CommandParameter="{x:Static config:AspectRatio.Fixed4x3}"/>
|
||||||
|
<MenuItem
|
||||||
|
Header="{locale:Locale SettingsTabGraphicsAspectRatio16x9}"
|
||||||
|
Command="{Binding SetAspectRatio}"
|
||||||
|
CommandParameter="{x:Static config:AspectRatio.Fixed16x9}"/>
|
||||||
|
<MenuItem
|
||||||
|
Header="{locale:Locale SettingsTabGraphicsAspectRatio16x10}"
|
||||||
|
Command="{Binding SetAspectRatio}"
|
||||||
|
CommandParameter="{x:Static config:AspectRatio.Fixed16x10}"/>
|
||||||
|
<MenuItem
|
||||||
|
Header="{locale:Locale SettingsTabGraphicsAspectRatio21x9}"
|
||||||
|
Command="{Binding SetAspectRatio}"
|
||||||
|
CommandParameter="{x:Static config:AspectRatio.Fixed21x9}"/>
|
||||||
|
<MenuItem
|
||||||
|
Header="{locale:Locale SettingsTabGraphicsAspectRatio32x9}"
|
||||||
|
Command="{Binding SetAspectRatio}"
|
||||||
|
CommandParameter="{x:Static config:AspectRatio.Fixed32x9}"/>
|
||||||
|
<MenuItem
|
||||||
|
Header="{locale:Locale SettingsTabGraphicsAspectRatioStretch}"
|
||||||
|
Command="{Binding SetAspectRatio}"
|
||||||
|
CommandParameter="{x:Static config:AspectRatio.Stretched}"/>
|
||||||
|
</MenuFlyout>
|
||||||
|
</SplitButton.Flyout>
|
||||||
|
</SplitButton>
|
||||||
<Border
|
<Border
|
||||||
Width="2"
|
Width="2"
|
||||||
Height="12"
|
Height="12"
|
||||||
@@ -138,6 +177,7 @@
|
|||||||
Content="{Binding VolumeStatusText}"
|
Content="{Binding VolumeStatusText}"
|
||||||
IsChecked="{Binding VolumeMuted}"
|
IsChecked="{Binding VolumeMuted}"
|
||||||
IsVisible="{Binding !ShowLoadProgress}"
|
IsVisible="{Binding !ShowLoadProgress}"
|
||||||
|
PointerWheelChanged="VolumeStatus_OnPointerWheelChanged"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
BorderThickness="0"
|
BorderThickness="0"
|
||||||
CornerRadius="0">
|
CornerRadius="0">
|
||||||
@@ -154,7 +194,7 @@
|
|||||||
<ToggleSplitButton.Flyout>
|
<ToggleSplitButton.Flyout>
|
||||||
<Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
|
<Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
|
||||||
<Grid Margin="0">
|
<Grid Margin="0">
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
MaxHeight="40"
|
MaxHeight="40"
|
||||||
Width="150"
|
Width="150"
|
||||||
Margin="0"
|
Margin="0"
|
||||||
|
@@ -43,10 +43,9 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
|
ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AspectRatioStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
|
private void AspectRatioStatus_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
|
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
|
||||||
|
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
|
ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,5 +53,20 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
{
|
{
|
||||||
Window.LoadApplications();
|
Window.LoadApplications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void VolumeStatus_OnPointerWheelChanged(object sender, PointerWheelEventArgs e)
|
||||||
|
{
|
||||||
|
// Change the volume by 5% at a time
|
||||||
|
float newValue = Window.ViewModel.Volume + (float)e.Delta.Y * 0.05f;
|
||||||
|
|
||||||
|
Window.ViewModel.Volume = newValue switch
|
||||||
|
{
|
||||||
|
< 0 => 0,
|
||||||
|
> 1 => 1,
|
||||||
|
_ => newValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{locale:Locale IconSize}"
|
Text="{locale:Locale IconSize}"
|
||||||
ToolTip.Tip="{locale:Locale IconSizeTooltip}" />
|
ToolTip.Tip="{locale:Locale IconSizeTooltip}" />
|
||||||
<Slider
|
<controls:SliderScroll
|
||||||
Width="150"
|
Width="150"
|
||||||
Height="35"
|
Height="35"
|
||||||
Margin="5,-10,5,0"
|
Margin="5,-10,5,0"
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
@@ -63,13 +64,13 @@
|
|||||||
Maximum="100" />
|
Maximum="100" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||||
<Slider Value="{Binding Volume}"
|
<controls:SliderScroll Value="{Binding Volume}"
|
||||||
Margin="250,0,0,0"
|
Margin="250,0,0,0"
|
||||||
ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
|
ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
|
||||||
Minimum="0"
|
Minimum="0"
|
||||||
Maximum="100"
|
Maximum="100"
|
||||||
SmallChange="5"
|
SmallChange="1"
|
||||||
TickFrequency="5"
|
TickFrequency="1"
|
||||||
IsSnapToTickEnabled="True"
|
IsSnapToTickEnabled="True"
|
||||||
LargeChange="10"
|
LargeChange="10"
|
||||||
Width="350" />
|
Width="350" />
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
@@ -173,7 +174,7 @@
|
|||||||
<TextBlock Text="FSR" />
|
<TextBlock Text="FSR" />
|
||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
<Slider Value="{Binding ScalingFilterLevel}"
|
<controls:SliderScroll Value="{Binding ScalingFilterLevel}"
|
||||||
ToolTip.Tip="{locale:Locale GraphicsScalingFilterLevelTooltip}"
|
ToolTip.Tip="{locale:Locale GraphicsScalingFilterLevelTooltip}"
|
||||||
MinWidth="150"
|
MinWidth="150"
|
||||||
Margin="10,-3,0,0"
|
Margin="10,-3,0,0"
|
||||||
|
@@ -5,7 +5,7 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
public class ReactiveObject<T>
|
public class ReactiveObject<T>
|
||||||
{
|
{
|
||||||
private readonly ReaderWriterLock _readerWriterLock = new();
|
private readonly ReaderWriterLockSlim _readerWriterLock = new();
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
private T _value;
|
private T _value;
|
||||||
|
|
||||||
@@ -15,15 +15,15 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
_readerWriterLock.AcquireReaderLock(Timeout.Infinite);
|
_readerWriterLock.EnterReadLock();
|
||||||
T value = _value;
|
T value = _value;
|
||||||
_readerWriterLock.ReleaseReaderLock();
|
_readerWriterLock.ExitReadLock();
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_readerWriterLock.AcquireWriterLock(Timeout.Infinite);
|
_readerWriterLock.EnterWriteLock();
|
||||||
|
|
||||||
T oldValue = _value;
|
T oldValue = _value;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ namespace Ryujinx.Common
|
|||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
_value = value;
|
_value = value;
|
||||||
|
|
||||||
_readerWriterLock.ReleaseWriterLock();
|
_readerWriterLock.ExitWriteLock();
|
||||||
|
|
||||||
if (!oldIsInitialized || oldValue == null || !oldValue.Equals(_value))
|
if (!oldIsInitialized || oldValue == null || !oldValue.Equals(_value))
|
||||||
{
|
{
|
||||||
|
@@ -38,6 +38,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
public readonly bool SupportsShaderBallot;
|
public readonly bool SupportsShaderBallot;
|
||||||
public readonly bool SupportsShaderBarrierDivergence;
|
public readonly bool SupportsShaderBarrierDivergence;
|
||||||
public readonly bool SupportsShaderFloat64;
|
public readonly bool SupportsShaderFloat64;
|
||||||
|
public readonly bool SupportsTextureGatherOffsets;
|
||||||
public readonly bool SupportsTextureShadowLod;
|
public readonly bool SupportsTextureShadowLod;
|
||||||
public readonly bool SupportsVertexStoreAndAtomics;
|
public readonly bool SupportsVertexStoreAndAtomics;
|
||||||
public readonly bool SupportsViewportIndexVertexTessellation;
|
public readonly bool SupportsViewportIndexVertexTessellation;
|
||||||
@@ -92,6 +93,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
bool supportsShaderBallot,
|
bool supportsShaderBallot,
|
||||||
bool supportsShaderBarrierDivergence,
|
bool supportsShaderBarrierDivergence,
|
||||||
bool supportsShaderFloat64,
|
bool supportsShaderFloat64,
|
||||||
|
bool supportsTextureGatherOffsets,
|
||||||
bool supportsTextureShadowLod,
|
bool supportsTextureShadowLod,
|
||||||
bool supportsVertexStoreAndAtomics,
|
bool supportsVertexStoreAndAtomics,
|
||||||
bool supportsViewportIndexVertexTessellation,
|
bool supportsViewportIndexVertexTessellation,
|
||||||
@@ -142,6 +144,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
SupportsShaderBallot = supportsShaderBallot;
|
SupportsShaderBallot = supportsShaderBallot;
|
||||||
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
|
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
|
||||||
SupportsShaderFloat64 = supportsShaderFloat64;
|
SupportsShaderFloat64 = supportsShaderFloat64;
|
||||||
|
SupportsTextureGatherOffsets = supportsTextureGatherOffsets;
|
||||||
SupportsTextureShadowLod = supportsTextureShadowLod;
|
SupportsTextureShadowLod = supportsTextureShadowLod;
|
||||||
SupportsVertexStoreAndAtomics = supportsVertexStoreAndAtomics;
|
SupportsVertexStoreAndAtomics = supportsVertexStoreAndAtomics;
|
||||||
SupportsViewportIndexVertexTessellation = supportsViewportIndexVertexTessellation;
|
SupportsViewportIndexVertexTessellation = supportsViewportIndexVertexTessellation;
|
||||||
|
@@ -374,6 +374,13 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.LayoutIncompatible;
|
return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.LayoutIncompatible;
|
||||||
}
|
}
|
||||||
|
else if (lhs.Target.IsMultisample() != rhs.Target.IsMultisample() && alignedWidthMatches && lhsAlignedSize.Height == rhsAlignedSize.Height)
|
||||||
|
{
|
||||||
|
// Copy between multisample and non-multisample textures with mismatching size is allowed,
|
||||||
|
// as long aligned size matches.
|
||||||
|
|
||||||
|
return TextureViewCompatibility.CopyOnly;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return TextureViewCompatibility.LayoutIncompatible;
|
return TextureViewCompatibility.LayoutIncompatible;
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 5767;
|
private const uint CodeGenVersion = 5791;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
@@ -186,6 +186,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
public bool QueryHostSupportsSnormBufferTextureFormat() => _context.Capabilities.SupportsSnormBufferTextureFormat;
|
public bool QueryHostSupportsSnormBufferTextureFormat() => _context.Capabilities.SupportsSnormBufferTextureFormat;
|
||||||
|
|
||||||
|
public bool QueryHostSupportsTextureGatherOffsets() => _context.Capabilities.SupportsTextureGatherOffsets;
|
||||||
|
|
||||||
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
|
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
|
||||||
|
|
||||||
public bool QueryHostSupportsTransformFeedback() => _context.Capabilities.SupportsTransformFeedback;
|
public bool QueryHostSupportsTransformFeedback() => _context.Capabilities.SupportsTransformFeedback;
|
||||||
|
@@ -163,6 +163,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
supportsShaderBallot: HwCapabilities.SupportsShaderBallot,
|
supportsShaderBallot: HwCapabilities.SupportsShaderBallot,
|
||||||
supportsShaderBarrierDivergence: !(intelWindows || intelUnix),
|
supportsShaderBarrierDivergence: !(intelWindows || intelUnix),
|
||||||
supportsShaderFloat64: true,
|
supportsShaderFloat64: true,
|
||||||
|
supportsTextureGatherOffsets: true,
|
||||||
supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod,
|
supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod,
|
||||||
supportsVertexStoreAndAtomics: true,
|
supportsVertexStoreAndAtomics: true,
|
||||||
supportsViewportIndexVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
|
supportsViewportIndexVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
|
||||||
|
@@ -339,6 +339,15 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries host GPU texture gather with multiple offsets support.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the GPU and driver supports texture gather offsets, false otherwise</returns>
|
||||||
|
bool QueryHostSupportsTextureGatherOffsets()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries host GPU texture shadow LOD support.
|
/// Queries host GPU texture shadow LOD support.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -766,7 +766,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
flags |= offset == TexOffset.Ptp ? TextureFlags.Offsets : TextureFlags.Offset;
|
flags |= offset == TexOffset.Ptp ? TextureFlags.Offsets : TextureFlags.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasDepthCompare)
|
||||||
|
{
|
||||||
sourcesList.Add(Const((int)component));
|
sourcesList.Add(Const((int)component));
|
||||||
|
}
|
||||||
|
|
||||||
Operand[] sources = sourcesList.ToArray();
|
Operand[] sources = sourcesList.ToArray();
|
||||||
Operand[] dests = new Operand[BitOperations.PopCount((uint)componentMask)];
|
Operand[] dests = new Operand[BitOperations.PopCount((uint)componentMask)];
|
||||||
|
@@ -303,7 +303,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
||||||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||||
|
|
||||||
bool hasInvalidOffset = (hasOffset || hasOffsets) && !gpuAccessor.QueryHostSupportsNonConstantTextureOffset();
|
bool needsOffsetsEmulation = hasOffsets && !gpuAccessor.QueryHostSupportsTextureGatherOffsets();
|
||||||
|
|
||||||
|
bool hasInvalidOffset = needsOffsetsEmulation || ((hasOffset || hasOffsets) && !gpuAccessor.QueryHostSupportsNonConstantTextureOffset());
|
||||||
|
|
||||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
|
|
||||||
@@ -402,12 +404,15 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
offsets[index] = offset;
|
offsets[index] = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!needsOffsetsEmulation)
|
||||||
|
{
|
||||||
hasInvalidOffset &= !areAllOffsetsConstant;
|
hasInvalidOffset &= !areAllOffsetsConstant;
|
||||||
|
|
||||||
if (!hasInvalidOffset)
|
if (!hasInvalidOffset)
|
||||||
{
|
{
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hasLodBias)
|
if (hasLodBias)
|
||||||
{
|
{
|
||||||
@@ -434,13 +439,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
|
|
||||||
LinkedListNode<INode> oldNode = node;
|
LinkedListNode<INode> oldNode = node;
|
||||||
|
|
||||||
if (isGather && !isShadow)
|
if (isGather && !isShadow && hasOffsets)
|
||||||
{
|
{
|
||||||
Operand[] newSources = new Operand[sources.Length];
|
Operand[] newSources = new Operand[sources.Length];
|
||||||
|
|
||||||
sources.CopyTo(newSources, 0);
|
sources.CopyTo(newSources, 0);
|
||||||
|
|
||||||
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
Operand[] texSizes = InsertTextureBaseSize(node, texOp, bindlessHandle, coordsCount);
|
||||||
|
|
||||||
int destIndex = 0;
|
int destIndex = 0;
|
||||||
|
|
||||||
@@ -455,7 +460,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
{
|
{
|
||||||
Operand offset = Local();
|
Operand offset = Local();
|
||||||
|
|
||||||
Operand intOffset = offsets[index + (hasOffsets ? compIndex * coordsCount : 0)];
|
Operand intOffset = offsets[index + compIndex * coordsCount];
|
||||||
|
|
||||||
node.List.AddBefore(node, new Operation(
|
node.List.AddBefore(node, new Operation(
|
||||||
Instruction.FP32 | Instruction.Divide,
|
Instruction.FP32 | Instruction.Divide,
|
||||||
@@ -478,7 +483,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
|
texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
1,
|
1 << 3, // W component: i=0, j=0
|
||||||
new[] { dests[destIndex++] },
|
new[] { dests[destIndex++] },
|
||||||
newSources);
|
newSources);
|
||||||
|
|
||||||
@@ -502,7 +507,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
Operand[] texSizes = isGather
|
||||||
|
? InsertTextureBaseSize(node, texOp, bindlessHandle, coordsCount)
|
||||||
|
: InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
||||||
|
|
||||||
for (int index = 0; index < coordsCount; index++)
|
for (int index = 0; index < coordsCount; index++)
|
||||||
{
|
{
|
||||||
@@ -549,6 +556,43 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Operand[] InsertTextureBaseSize(
|
||||||
|
LinkedListNode<INode> node,
|
||||||
|
TextureOperation texOp,
|
||||||
|
Operand bindlessHandle,
|
||||||
|
int coordsCount)
|
||||||
|
{
|
||||||
|
Operand[] texSizes = new Operand[coordsCount];
|
||||||
|
|
||||||
|
for (int index = 0; index < coordsCount; index++)
|
||||||
|
{
|
||||||
|
texSizes[index] = Local();
|
||||||
|
|
||||||
|
Operand[] texSizeSources;
|
||||||
|
|
||||||
|
if (bindlessHandle != null)
|
||||||
|
{
|
||||||
|
texSizeSources = new Operand[] { bindlessHandle, Const(0) };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texSizeSources = new Operand[] { Const(0) };
|
||||||
|
}
|
||||||
|
|
||||||
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
|
Instruction.TextureQuerySize,
|
||||||
|
texOp.Type,
|
||||||
|
texOp.Format,
|
||||||
|
texOp.Flags,
|
||||||
|
texOp.Binding,
|
||||||
|
index,
|
||||||
|
new[] { texSizes[index] },
|
||||||
|
texSizeSources));
|
||||||
|
}
|
||||||
|
|
||||||
|
return texSizes;
|
||||||
|
}
|
||||||
|
|
||||||
private static Operand[] InsertTextureLod(
|
private static Operand[] InsertTextureLod(
|
||||||
LinkedListNode<INode> node,
|
LinkedListNode<INode> node,
|
||||||
TextureOperation texOp,
|
TextureOperation texOp,
|
||||||
|
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private int _flushTemp;
|
private int _flushTemp;
|
||||||
private int _lastFlushWrite = -1;
|
private int _lastFlushWrite = -1;
|
||||||
|
|
||||||
private readonly ReaderWriterLock _flushLock;
|
private readonly ReaderWriterLockSlim _flushLock;
|
||||||
private FenceHolder _flushFence;
|
private FenceHolder _flushFence;
|
||||||
private int _flushWaiting;
|
private int _flushWaiting;
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_currentType = currentType;
|
_currentType = currentType;
|
||||||
DesiredType = currentType;
|
DesiredType = currentType;
|
||||||
|
|
||||||
_flushLock = new ReaderWriterLock();
|
_flushLock = new ReaderWriterLockSlim();
|
||||||
_useMirrors = gd.IsTBDR;
|
_useMirrors = gd.IsTBDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_currentType = currentType;
|
_currentType = currentType;
|
||||||
DesiredType = currentType;
|
DesiredType = currentType;
|
||||||
|
|
||||||
_flushLock = new ReaderWriterLock();
|
_flushLock = new ReaderWriterLockSlim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryBackingSwap(ref CommandBufferScoped? cbs)
|
public bool TryBackingSwap(ref CommandBufferScoped? cbs)
|
||||||
@@ -116,7 +116,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
// Only swap if the buffer is not used in any queued command buffer.
|
// Only swap if the buffer is not used in any queued command buffer.
|
||||||
bool isRented = _buffer.HasRentedCommandBufferDependency(_gd.CommandBufferPool);
|
bool isRented = _buffer.HasRentedCommandBufferDependency(_gd.CommandBufferPool);
|
||||||
|
|
||||||
if (!isRented && _gd.CommandBufferPool.OwnedByCurrentThread && !_flushLock.IsReaderLockHeld && (_pendingData == null || cbs != null))
|
if (!isRented && _gd.CommandBufferPool.OwnedByCurrentThread && !_flushLock.IsReadLockHeld && (_pendingData == null || cbs != null))
|
||||||
{
|
{
|
||||||
var currentAllocation = _allocationAuto;
|
var currentAllocation = _allocationAuto;
|
||||||
var currentBuffer = _buffer;
|
var currentBuffer = _buffer;
|
||||||
@@ -131,7 +131,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ClearMirrors(cbs.Value, 0, Size);
|
ClearMirrors(cbs.Value, 0, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
_flushLock.AcquireWriterLock(Timeout.Infinite);
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
ClearFlushFence();
|
ClearFlushFence();
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_gd.PipelineInternal.SwapBuffer(currentBuffer, _buffer);
|
_gd.PipelineInternal.SwapBuffer(currentBuffer, _buffer);
|
||||||
|
|
||||||
_flushLock.ReleaseWriterLock();
|
_flushLock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
_swapQueued = false;
|
_swapQueued = false;
|
||||||
@@ -548,13 +548,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void WaitForFlushFence()
|
private void WaitForFlushFence()
|
||||||
{
|
{
|
||||||
// Assumes the _flushLock is held as reader, returns in same state.
|
if (_flushFence == null)
|
||||||
|
|
||||||
if (_flushFence != null)
|
|
||||||
{
|
{
|
||||||
// If storage has changed, make sure the fence has been reached so that the data is in place.
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var cookie = _flushLock.UpgradeToWriterLock(Timeout.Infinite);
|
// If storage has changed, make sure the fence has been reached so that the data is in place.
|
||||||
|
_flushLock.ExitReadLock();
|
||||||
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
if (_flushFence != null)
|
if (_flushFence != null)
|
||||||
{
|
{
|
||||||
@@ -563,11 +564,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
// Don't wait in the lock.
|
// Don't wait in the lock.
|
||||||
|
|
||||||
var restoreCookie = _flushLock.ReleaseLock();
|
_flushLock.ExitWriteLock();
|
||||||
|
|
||||||
fence.Wait();
|
fence.Wait();
|
||||||
|
|
||||||
_flushLock.RestoreLock(ref restoreCookie);
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
if (Interlocked.Decrement(ref _flushWaiting) == 0)
|
if (Interlocked.Decrement(ref _flushWaiting) == 0)
|
||||||
{
|
{
|
||||||
@@ -577,13 +578,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_flushFence = null;
|
_flushFence = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_flushLock.DowngradeFromWriterLock(ref cookie);
|
// Assumes the _flushLock is held as reader, returns in same state.
|
||||||
}
|
_flushLock.ExitWriteLock();
|
||||||
|
_flushLock.EnterReadLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PinnedSpan<byte> GetData(int offset, int size)
|
public PinnedSpan<byte> GetData(int offset, int size)
|
||||||
{
|
{
|
||||||
_flushLock.AcquireReaderLock(Timeout.Infinite);
|
_flushLock.EnterReadLock();
|
||||||
|
|
||||||
WaitForFlushFence();
|
WaitForFlushFence();
|
||||||
|
|
||||||
@@ -603,7 +605,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
// Need to be careful here, the buffer can't be unmapped while the data is being used.
|
// Need to be careful here, the buffer can't be unmapped while the data is being used.
|
||||||
_buffer.IncrementReferenceCount();
|
_buffer.IncrementReferenceCount();
|
||||||
|
|
||||||
_flushLock.ReleaseReaderLock();
|
_flushLock.ExitReadLock();
|
||||||
|
|
||||||
return PinnedSpan<byte>.UnsafeFromSpan(result, _buffer.DecrementReferenceCount);
|
return PinnedSpan<byte>.UnsafeFromSpan(result, _buffer.DecrementReferenceCount);
|
||||||
}
|
}
|
||||||
@@ -621,7 +623,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
result = resource.GetFlushBuffer().GetBufferData(resource.GetPool(), this, offset, size);
|
result = resource.GetFlushBuffer().GetBufferData(resource.GetPool(), this, offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
_flushLock.ReleaseReaderLock();
|
_flushLock.ExitReadLock();
|
||||||
|
|
||||||
// Flush buffer is pinned until the next GetBufferData on the thread, which is fine for current uses.
|
// Flush buffer is pinned until the next GetBufferData on the thread, which is fine for current uses.
|
||||||
return PinnedSpan<byte>.UnsafeFromSpan(result);
|
return PinnedSpan<byte>.UnsafeFromSpan(result);
|
||||||
@@ -1073,11 +1075,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_allocationAuto.Dispose();
|
_allocationAuto.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_flushLock.AcquireWriterLock(Timeout.Infinite);
|
_flushLock.EnterWriteLock();
|
||||||
|
|
||||||
ClearFlushFence();
|
ClearFlushFence();
|
||||||
|
|
||||||
_flushLock.ReleaseWriterLock();
|
_flushLock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -605,6 +605,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportsShaderBallot: false,
|
supportsShaderBallot: false,
|
||||||
supportsShaderBarrierDivergence: Vendor != Vendor.Intel,
|
supportsShaderBarrierDivergence: Vendor != Vendor.Intel,
|
||||||
supportsShaderFloat64: Capabilities.SupportsShaderFloat64,
|
supportsShaderFloat64: Capabilities.SupportsShaderFloat64,
|
||||||
|
supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended && !IsMoltenVk,
|
||||||
supportsTextureShadowLod: false,
|
supportsTextureShadowLod: false,
|
||||||
supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics,
|
supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics,
|
||||||
supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex,
|
supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex,
|
||||||
|
@@ -198,7 +198,7 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
{
|
{
|
||||||
using var ncaFile = new UniqueRef<IFile>();
|
using var ncaFile = new UniqueRef<IFile>();
|
||||||
|
|
||||||
fs.OpenFile(ref ncaFile.Ref, ncaPath.FullPath.ToU8Span(), OpenMode.Read);
|
fs.OpenFile(ref ncaFile.Ref, ncaPath.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
var nca = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
|
var nca = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
|
||||||
if (nca.Header.ContentType != NcaContentType.Meta)
|
if (nca.Header.ContentType != NcaContentType.Meta)
|
||||||
{
|
{
|
||||||
@@ -210,7 +210,7 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
using var pfs0 = nca.OpenFileSystem(0, integrityCheckLevel);
|
using var pfs0 = nca.OpenFileSystem(0, integrityCheckLevel);
|
||||||
using var cnmtFile = new UniqueRef<IFile>();
|
using var cnmtFile = new UniqueRef<IFile>();
|
||||||
|
|
||||||
pfs0.OpenFile(ref cnmtFile.Ref, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);
|
pfs0.OpenFile(ref cnmtFile.Ref, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
|
|
||||||
var cnmt = new Cnmt(cnmtFile.Get.AsStream());
|
var cnmt = new Cnmt(cnmtFile.Get.AsStream());
|
||||||
if (cnmt.Type != ContentMetaType.AddOnContent || (cnmt.TitleId & 0xFFFFFFFFFFFFE000) != aocBaseId)
|
if (cnmt.Type != ContentMetaType.AddOnContent || (cnmt.TitleId & 0xFFFFFFFFFFFFE000) != aocBaseId)
|
||||||
@@ -220,7 +220,7 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
|
|
||||||
string ncaId = Convert.ToHexString(cnmt.ContentEntries[0].NcaId).ToLower();
|
string ncaId = Convert.ToHexString(cnmt.ContentEntries[0].NcaId).ToLower();
|
||||||
|
|
||||||
AddAocItem(cnmt.TitleId, containerPath, $"{ncaId}.nca", true);
|
AddAocItem(cnmt.TitleId, containerPath, $"/{ncaId}.nca", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,8 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
if (!mergedToContainer)
|
if (!mergedToContainer)
|
||||||
{
|
{
|
||||||
using FileStream fileStream = File.OpenRead(containerPath);
|
using FileStream fileStream = File.OpenRead(containerPath);
|
||||||
using PartitionFileSystem partitionFileSystem = new(fileStream.AsStorage());
|
using PartitionFileSystem partitionFileSystem = new();
|
||||||
|
partitionFileSystem.Initialize(fileStream.AsStorage()).ThrowIfFailure();
|
||||||
|
|
||||||
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
||||||
}
|
}
|
||||||
@@ -259,17 +260,17 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
{
|
{
|
||||||
var file = new FileStream(aoc.ContainerPath, FileMode.Open, FileAccess.Read);
|
var file = new FileStream(aoc.ContainerPath, FileMode.Open, FileAccess.Read);
|
||||||
using var ncaFile = new UniqueRef<IFile>();
|
using var ncaFile = new UniqueRef<IFile>();
|
||||||
PartitionFileSystem pfs;
|
|
||||||
|
|
||||||
switch (Path.GetExtension(aoc.ContainerPath))
|
switch (Path.GetExtension(aoc.ContainerPath))
|
||||||
{
|
{
|
||||||
case ".xci":
|
case ".xci":
|
||||||
pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
|
var xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
|
||||||
pfs.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read);
|
xci.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
break;
|
break;
|
||||||
case ".nsp":
|
case ".nsp":
|
||||||
pfs = new PartitionFileSystem(file.AsStorage());
|
var pfs = new PartitionFileSystem();
|
||||||
pfs.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read);
|
pfs.Initialize(file.AsStorage());
|
||||||
|
pfs.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false; // Print error?
|
return false; // Print error?
|
||||||
@@ -606,11 +607,11 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
|
|
||||||
if (filesystem.FileExists($"{path}/00"))
|
if (filesystem.FileExists($"{path}/00"))
|
||||||
{
|
{
|
||||||
filesystem.OpenFile(ref file.Ref, $"{path}/00".ToU8Span(), mode);
|
filesystem.OpenFile(ref file.Ref, $"{path}/00".ToU8Span(), mode).ThrowIfFailure();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
filesystem.OpenFile(ref file.Ref, path.ToU8Span(), mode);
|
filesystem.OpenFile(ref file.Ref, path.ToU8Span(), mode).ThrowIfFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
return file.Release();
|
return file.Release();
|
||||||
|
@@ -7,6 +7,7 @@ using LibHac.Fs.Shim;
|
|||||||
using LibHac.FsSrv;
|
using LibHac.FsSrv;
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
|
using LibHac.Sdmmc;
|
||||||
using LibHac.Spl;
|
using LibHac.Spl;
|
||||||
using LibHac.Tools.Es;
|
using LibHac.Tools.Es;
|
||||||
using LibHac.Tools.Fs;
|
using LibHac.Tools.Fs;
|
||||||
@@ -32,7 +33,7 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
|
|
||||||
public KeySet KeySet { get; private set; }
|
public KeySet KeySet { get; private set; }
|
||||||
public EmulatedGameCard GameCard { get; private set; }
|
public EmulatedGameCard GameCard { get; private set; }
|
||||||
public EmulatedSdCard SdCard { get; private set; }
|
public SdmmcApi SdCard { get; private set; }
|
||||||
public ModLoader ModLoader { get; private set; }
|
public ModLoader ModLoader { get; private set; }
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<ulong, Stream> _romFsByPid;
|
private readonly ConcurrentDictionary<ulong, Stream> _romFsByPid;
|
||||||
@@ -198,15 +199,15 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
fsServerObjects.FsCreators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator();
|
fsServerObjects.FsCreators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator();
|
||||||
|
|
||||||
GameCard = fsServerObjects.GameCard;
|
GameCard = fsServerObjects.GameCard;
|
||||||
SdCard = fsServerObjects.SdCard;
|
SdCard = fsServerObjects.Sdmmc;
|
||||||
|
|
||||||
SdCard.SetSdCardInsertionStatus(true);
|
SdCard.SetSdCardInserted(true);
|
||||||
|
|
||||||
var fsServerConfig = new FileSystemServerConfig
|
var fsServerConfig = new FileSystemServerConfig
|
||||||
{
|
{
|
||||||
DeviceOperator = fsServerObjects.DeviceOperator,
|
|
||||||
ExternalKeySet = KeySet.ExternalKeySet,
|
ExternalKeySet = KeySet.ExternalKeySet,
|
||||||
FsCreators = fsServerObjects.FsCreators,
|
FsCreators = fsServerObjects.FsCreators,
|
||||||
|
StorageDeviceManagerFactory = fsServerObjects.StorageDeviceManagerFactory,
|
||||||
RandomGenerator = randomGenerator,
|
RandomGenerator = randomGenerator,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -263,7 +264,16 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
|
|
||||||
if (result.IsSuccess())
|
if (result.IsSuccess())
|
||||||
{
|
{
|
||||||
Ticket ticket = new(ticketFile.Get.AsStream());
|
// When reading a file from a Sha256PartitionFileSystem, you can't start a read in the middle
|
||||||
|
// of the hashed portion (usually the first 0x200 bytes) of the file and end the read after
|
||||||
|
// the end of the hashed portion, so we read the ticket file using a single read.
|
||||||
|
byte[] ticketData = new byte[0x2C0];
|
||||||
|
result = ticketFile.Get.Read(out long bytesRead, 0, ticketData);
|
||||||
|
|
||||||
|
if (result.IsFailure() || bytesRead != ticketData.Length)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Ticket ticket = new(new MemoryStream(ticketData));
|
||||||
var titleKey = ticket.GetTitleKey(KeySet);
|
var titleKey = ticket.GetTitleKey(KeySet);
|
||||||
|
|
||||||
if (titleKey != null)
|
if (titleKey != null)
|
||||||
|
@@ -533,7 +533,9 @@ namespace Ryujinx.HLE.HOS
|
|||||||
|
|
||||||
Logger.Info?.Print(LogClass.ModLoader, "Using replacement ExeFS partition");
|
Logger.Info?.Print(LogClass.ModLoader, "Using replacement ExeFS partition");
|
||||||
|
|
||||||
exefs = new PartitionFileSystem(mods.ExefsContainers[0].Path.OpenRead().AsStorage());
|
var pfs = new PartitionFileSystem();
|
||||||
|
pfs.Initialize(mods.ExefsContainers[0].Path.OpenRead().AsStorage()).ThrowIfFailure();
|
||||||
|
exefs = pfs;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
LocalStorage storage = new(pfsPath, FileAccess.Read, FileMode.Open);
|
LocalStorage storage = new(pfsPath, FileAccess.Read, FileMode.Open);
|
||||||
using SharedRef<LibHac.Fs.Fsa.IFileSystem> nsp = new(new PartitionFileSystem(storage));
|
var pfs = new PartitionFileSystem();
|
||||||
|
using SharedRef<LibHac.Fs.Fsa.IFileSystem> nsp = new(pfs);
|
||||||
|
pfs.Initialize(storage).ThrowIfFailure();
|
||||||
|
|
||||||
ImportTitleKeysFromNsp(nsp.Get, context.Device.System.KeySet);
|
ImportTitleKeysFromNsp(nsp.Get, context.Device.System.KeySet);
|
||||||
|
|
||||||
@@ -90,7 +92,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PartitionFileSystem nsp = new(pfsFile.AsStorage());
|
PartitionFileSystem nsp = new();
|
||||||
|
nsp.Initialize(pfsFile.AsStorage()).ThrowIfFailure();
|
||||||
|
|
||||||
ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
|
ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
using LibHac.Fs.Fsa;
|
||||||
using Path = LibHac.FsSrv.Sf.Path;
|
using Path = LibHac.FsSrv.Sf.Path;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||||
@@ -202,6 +203,16 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
|||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandCmif(16)]
|
||||||
|
public ResultCode GetFileSystemAttribute(ServiceCtx context)
|
||||||
|
{
|
||||||
|
Result result = _fileSystem.Get.GetFileSystemAttribute(out FileSystemAttribute attribute);
|
||||||
|
|
||||||
|
context.ResponseData.Write(SpanHelpers.AsReadOnlyByteSpan(in attribute));
|
||||||
|
|
||||||
|
return (ResultCode)result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
if (isDisposing)
|
if (isDisposing)
|
||||||
|
@@ -1380,7 +1380,10 @@ namespace Ryujinx.HLE.HOS.Services.Fs
|
|||||||
[CommandCmif(1016)]
|
[CommandCmif(1016)]
|
||||||
public ResultCode FlushAccessLogOnSdCard(ServiceCtx context)
|
public ResultCode FlushAccessLogOnSdCard(ServiceCtx context)
|
||||||
{
|
{
|
||||||
return (ResultCode)_baseFileSystemProxy.Get.FlushAccessLogOnSdCard().Value;
|
// Logging the access log to the SD card isn't implemented, meaning this function will be a no-op since
|
||||||
|
// there's nothing to flush. Return success until it's implemented.
|
||||||
|
// return (ResultCode)_baseFileSystemProxy.Get.FlushAccessLogOnSdCard().Value;
|
||||||
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandCmif(1017)]
|
[CommandCmif(1017)]
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Ins
|
|
||||||
{
|
|
||||||
[Service("ins:r")]
|
|
||||||
class IReceiverManager : IpcService
|
|
||||||
{
|
|
||||||
public IReceiverManager(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Ins
|
|
||||||
{
|
|
||||||
[Service("ins:s")]
|
|
||||||
class ISenderManager : IpcService
|
|
||||||
{
|
|
||||||
public ISenderManager(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -29,6 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
private const bool IsDevelopment = false;
|
private const bool IsDevelopment = false;
|
||||||
|
|
||||||
private readonly KEvent _stateChangeEvent;
|
private readonly KEvent _stateChangeEvent;
|
||||||
|
private int _stateChangeEventHandle;
|
||||||
|
|
||||||
private NetworkState _state;
|
private NetworkState _state;
|
||||||
private DisconnectReason _disconnectReason;
|
private DisconnectReason _disconnectReason;
|
||||||
@@ -277,12 +278,12 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
// AttachStateChangeEvent() -> handle<copy>
|
// AttachStateChangeEvent() -> handle<copy>
|
||||||
public ResultCode AttachStateChangeEvent(ServiceCtx context)
|
public ResultCode AttachStateChangeEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_stateChangeEvent.ReadableEvent, out int stateChangeEventHandle) != Result.Success)
|
if (_stateChangeEventHandle == 0 && context.Process.HandleTable.GenerateHandle(_stateChangeEvent.ReadableEvent, out _stateChangeEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(stateChangeEventHandle);
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangeEventHandle);
|
||||||
|
|
||||||
// Returns ResultCode.InvalidArgument if handle is null, doesn't occur in our case since we already throw an Exception.
|
// Returns ResultCode.InvalidArgument if handle is null, doesn't occur in our case since we already throw an Exception.
|
||||||
|
|
||||||
@@ -964,6 +965,12 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
SetDisconnectReason(DisconnectReason.None);
|
SetDisconnectReason(DisconnectReason.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_stateChangeEventHandle != 0)
|
||||||
|
{
|
||||||
|
context.Process.HandleTable.CloseHandle(_stateChangeEventHandle);
|
||||||
|
_stateChangeEventHandle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return resultCode;
|
return resultCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,7 +1028,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
|
|
||||||
SetState(NetworkState.None);
|
SetState(NetworkState.None);
|
||||||
|
|
||||||
NetworkClient?.DisconnectAndStop();
|
NetworkClient?.Dispose();
|
||||||
NetworkClient = null;
|
NetworkClient = null;
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
@@ -1072,7 +1079,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: Service returns differents ResultCode here related to the nifm ResultCode.
|
// NOTE: Service returns different ResultCode here related to the nifm ResultCode.
|
||||||
resultCode = ResultCode.DeviceDisabled;
|
resultCode = ResultCode.DeviceDisabled;
|
||||||
_nifmResultCode = resultCode;
|
_nifmResultCode = resultCode;
|
||||||
}
|
}
|
||||||
@@ -1083,15 +1090,14 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
|
||||||
if (NetworkClient != null)
|
|
||||||
{
|
{
|
||||||
_station?.Dispose();
|
_station?.Dispose();
|
||||||
|
_station = null;
|
||||||
|
|
||||||
_accessPoint?.Dispose();
|
_accessPoint?.Dispose();
|
||||||
|
_accessPoint = null;
|
||||||
|
|
||||||
NetworkClient.DisconnectAndStop();
|
NetworkClient?.Dispose();
|
||||||
}
|
|
||||||
|
|
||||||
NetworkClient = null;
|
NetworkClient = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Ovln
|
|
||||||
{
|
|
||||||
[Service("ovln:rcv")]
|
|
||||||
class IReceiverService : IpcService
|
|
||||||
{
|
|
||||||
public IReceiverService(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Ovln
|
|
||||||
{
|
|
||||||
[Service("ovln:snd")]
|
|
||||||
class ISenderService : IpcService
|
|
||||||
{
|
|
||||||
public ISenderService(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Psc
|
|
||||||
{
|
|
||||||
[Service("psc:c")]
|
|
||||||
class IPmControl : IpcService
|
|
||||||
{
|
|
||||||
public IPmControl(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Psc
|
|
||||||
{
|
|
||||||
[Service("psc:m")]
|
|
||||||
class IPmService : IpcService
|
|
||||||
{
|
|
||||||
public IPmService(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Psc
|
|
||||||
{
|
|
||||||
[Service("psc:l")] // 9.0.0+
|
|
||||||
class IPmUnknown : IpcService
|
|
||||||
{
|
|
||||||
public IPmUnknown(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Srepo
|
|
||||||
{
|
|
||||||
[Service("srepo:a")] // 5.0.0+
|
|
||||||
[Service("srepo:u")] // 5.0.0+
|
|
||||||
class ISrepoService : IpcService
|
|
||||||
{
|
|
||||||
public ISrepoService(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:hs")]
|
|
||||||
[Service("usb:hs:a")] // 7.0.0+
|
|
||||||
class IClientRootSession : IpcService
|
|
||||||
{
|
|
||||||
public IClientRootSession(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:ds")]
|
|
||||||
class IDsService : IpcService
|
|
||||||
{
|
|
||||||
public IDsService(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:pd:c")]
|
|
||||||
class IPdCradleManager : IpcService
|
|
||||||
{
|
|
||||||
public IPdCradleManager(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:pd")]
|
|
||||||
class IPdManager : IpcService
|
|
||||||
{
|
|
||||||
public IPdManager(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:pm")]
|
|
||||||
class IPmService : IpcService
|
|
||||||
{
|
|
||||||
public IPmService(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:qdb")] // 7.0.0+
|
|
||||||
class IUnknown1 : IpcService
|
|
||||||
{
|
|
||||||
public IUnknown1(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
namespace Ryujinx.HLE.HOS.Services.Usb
|
|
||||||
{
|
|
||||||
[Service("usb:obsv")] // 8.0.0+
|
|
||||||
class IUnknown2 : IpcService
|
|
||||||
{
|
|
||||||
public IUnknown2(ServiceCtx context) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -20,7 +20,11 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
|||||||
private static readonly DownloadableContentJsonSerializerContext _contentSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly DownloadableContentJsonSerializerContext _contentSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
internal static (bool, ProcessResult) TryLoad(this PartitionFileSystem partitionFileSystem, Switch device, string path, out string errorMessage)
|
internal static (bool, ProcessResult) TryLoad<TMetaData, TFormat, THeader, TEntry>(this PartitionFileSystemCore<TMetaData, TFormat, THeader, TEntry> partitionFileSystem, Switch device, string path, out string errorMessage)
|
||||||
|
where TMetaData : PartitionFileSystemMetaCore<TFormat, THeader, TEntry>, new()
|
||||||
|
where TFormat : IPartitionFileSystemFormat
|
||||||
|
where THeader : unmanaged, IPartitionFileSystemHeader
|
||||||
|
where TEntry : unmanaged, IPartitionFileSystemEntry
|
||||||
{
|
{
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
|
|
||||||
@@ -91,7 +95,8 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
|||||||
string updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
|
string updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
|
||||||
if (File.Exists(updatePath))
|
if (File.Exists(updatePath))
|
||||||
{
|
{
|
||||||
PartitionFileSystem updatePartitionFileSystem = new(new FileStream(updatePath, FileMode.Open, FileAccess.Read).AsStorage());
|
PartitionFileSystem updatePartitionFileSystem = new();
|
||||||
|
updatePartitionFileSystem.Initialize(new FileStream(updatePath, FileMode.Open, FileAccess.Read).AsStorage()).ThrowIfFailure();
|
||||||
|
|
||||||
device.Configuration.VirtualFileSystem.ImportTickets(updatePartitionFileSystem);
|
device.Configuration.VirtualFileSystem.ImportTickets(updatePartitionFileSystem);
|
||||||
|
|
||||||
|
@@ -69,7 +69,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
public bool LoadNsp(string path)
|
public bool LoadNsp(string path)
|
||||||
{
|
{
|
||||||
FileStream file = new(path, FileMode.Open, FileAccess.Read);
|
FileStream file = new(path, FileMode.Open, FileAccess.Read);
|
||||||
PartitionFileSystem partitionFileSystem = new(file.AsStorage());
|
PartitionFileSystem partitionFileSystem = new();
|
||||||
|
partitionFileSystem.Initialize(file.AsStorage()).ThrowIfFailure();
|
||||||
|
|
||||||
(bool success, ProcessResult processResult) = partitionFileSystem.TryLoad(_device, path, out string errorMessage);
|
(bool success, ProcessResult processResult) = partitionFileSystem.TryLoad(_device, path, out string errorMessage);
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
using LibHac.Account;
|
using LibHac.Account;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
using LibHac.Fs.Fsa;
|
||||||
using LibHac.Fs.Shim;
|
using LibHac.Fs.Shim;
|
||||||
using LibHac.FsSystem;
|
|
||||||
using LibHac.Loader;
|
using LibHac.Loader;
|
||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
@@ -33,7 +33,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
// TODO: Remove this workaround when ASLR is implemented.
|
// TODO: Remove this workaround when ASLR is implemented.
|
||||||
private const ulong CodeStartOffset = 0x500000UL;
|
private const ulong CodeStartOffset = 0x500000UL;
|
||||||
|
|
||||||
public static LibHac.Result RegisterProgramMapInfo(Switch device, PartitionFileSystem partitionFileSystem)
|
public static LibHac.Result RegisterProgramMapInfo(Switch device, IFileSystem partitionFileSystem)
|
||||||
{
|
{
|
||||||
ulong applicationId = 0;
|
ulong applicationId = 0;
|
||||||
int programCount = 0;
|
int programCount = 0;
|
||||||
|
@@ -93,7 +93,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
|
|||||||
generator.LeaveScope();
|
generator.LeaveScope();
|
||||||
generator.LeaveScope();
|
generator.LeaveScope();
|
||||||
|
|
||||||
context.AddSource($"{className}.g.cs", generator.ToString());
|
context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
src/Ryujinx.Horizon/Hshl/HshlIpcServer.cs
Normal file
47
src/Ryujinx.Horizon/Hshl/HshlIpcServer.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Ryujinx.Horizon.Hshl.Ipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sm;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Hshl
|
||||||
|
{
|
||||||
|
class HshlIpcServer
|
||||||
|
{
|
||||||
|
private const int HshlMaxSessionsCount = 10;
|
||||||
|
private const int TotalMaxSessionsCount = HshlMaxSessionsCount * 2;
|
||||||
|
|
||||||
|
private const int PointerBufferSize = 0;
|
||||||
|
private const int MaxDomains = 0;
|
||||||
|
private const int MaxDomainObjects = 0;
|
||||||
|
private const int MaxPortsCount = 2;
|
||||||
|
|
||||||
|
private static readonly ManagerOptions _options = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
|
||||||
|
|
||||||
|
private SmApi _sm;
|
||||||
|
private ServerManager _serverManager;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
HeapAllocator allocator = new();
|
||||||
|
|
||||||
|
_sm = new SmApi();
|
||||||
|
_sm.Initialize().AbortOnFailure();
|
||||||
|
|
||||||
|
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _options, TotalMaxSessionsCount);
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
_serverManager.RegisterObjectForServer(new SetterManager(), ServiceName.Encode("hshl:set"), HshlMaxSessionsCount); // 11.0.0+
|
||||||
|
_serverManager.RegisterObjectForServer(new Manager(), ServiceName.Encode("hshl:sys"), HshlMaxSessionsCount); // 11.0.0+
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServiceRequests()
|
||||||
|
{
|
||||||
|
_serverManager.ServiceRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
_serverManager.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Ryujinx.Horizon/Hshl/HshlMain.cs
Normal file
17
src/Ryujinx.Horizon/Hshl/HshlMain.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ryujinx.Horizon.Hshl
|
||||||
|
{
|
||||||
|
class HshlMain : IService
|
||||||
|
{
|
||||||
|
public static void Main(ServiceTable serviceTable)
|
||||||
|
{
|
||||||
|
HshlIpcServer ipcServer = new();
|
||||||
|
|
||||||
|
ipcServer.Initialize();
|
||||||
|
|
||||||
|
serviceTable.SignalServiceReady();
|
||||||
|
|
||||||
|
ipcServer.ServiceRequests();
|
||||||
|
ipcServer.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Hshl/Ipc/Manager.cs
Normal file
8
src/Ryujinx.Horizon/Hshl/Ipc/Manager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Hshl;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Hshl.Ipc
|
||||||
|
{
|
||||||
|
partial class Manager : IManager
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Hshl/Ipc/SetterManager.cs
Normal file
8
src/Ryujinx.Horizon/Hshl/Ipc/SetterManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Hshl;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Hshl.Ipc
|
||||||
|
{
|
||||||
|
partial class SetterManager : ISetterManager
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
47
src/Ryujinx.Horizon/Ins/InsIpcServer.cs
Normal file
47
src/Ryujinx.Horizon/Ins/InsIpcServer.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Ryujinx.Horizon.Ins.Ipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sm;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Ins
|
||||||
|
{
|
||||||
|
class InsIpcServer
|
||||||
|
{
|
||||||
|
private const int InsMaxSessionsCount = 8;
|
||||||
|
private const int TotalMaxSessionsCount = InsMaxSessionsCount * 2;
|
||||||
|
|
||||||
|
private const int PointerBufferSize = 0x200;
|
||||||
|
private const int MaxDomains = 0;
|
||||||
|
private const int MaxDomainObjects = 0;
|
||||||
|
private const int MaxPortsCount = 2;
|
||||||
|
|
||||||
|
private static readonly ManagerOptions _options = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
|
||||||
|
|
||||||
|
private SmApi _sm;
|
||||||
|
private ServerManager _serverManager;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
HeapAllocator allocator = new();
|
||||||
|
|
||||||
|
_sm = new SmApi();
|
||||||
|
_sm.Initialize().AbortOnFailure();
|
||||||
|
|
||||||
|
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _options, TotalMaxSessionsCount);
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
_serverManager.RegisterObjectForServer(new ReceiverManager(), ServiceName.Encode("ins:r"), InsMaxSessionsCount); // 9.0.0+
|
||||||
|
_serverManager.RegisterObjectForServer(new SenderManager(), ServiceName.Encode("ins:s"), InsMaxSessionsCount); // 9.0.0+
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServiceRequests()
|
||||||
|
{
|
||||||
|
_serverManager.ServiceRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
_serverManager.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Ryujinx.Horizon/Ins/InsMain.cs
Normal file
17
src/Ryujinx.Horizon/Ins/InsMain.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ryujinx.Horizon.Ins
|
||||||
|
{
|
||||||
|
class InsMain : IService
|
||||||
|
{
|
||||||
|
public static void Main(ServiceTable serviceTable)
|
||||||
|
{
|
||||||
|
InsIpcServer ipcServer = new();
|
||||||
|
|
||||||
|
ipcServer.Initialize();
|
||||||
|
|
||||||
|
serviceTable.SignalServiceReady();
|
||||||
|
|
||||||
|
ipcServer.ServiceRequests();
|
||||||
|
ipcServer.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Ins/Ipc/ReceiverManager.cs
Normal file
8
src/Ryujinx.Horizon/Ins/Ipc/ReceiverManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Ins;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Ins.Ipc
|
||||||
|
{
|
||||||
|
partial class ReceiverManager : IReceiverManager
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Ins/Ipc/SenderManager.cs
Normal file
8
src/Ryujinx.Horizon/Ins/Ipc/SenderManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Ins;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Ins.Ipc
|
||||||
|
{
|
||||||
|
partial class SenderManager : ISenderManager
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Ovln/Ipc/ReceiverService.cs
Normal file
8
src/Ryujinx.Horizon/Ovln/Ipc/ReceiverService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Ovln;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Ovln.Ipc
|
||||||
|
{
|
||||||
|
partial class ReceiverService : IReceiverService
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Ovln/Ipc/SenderService.cs
Normal file
8
src/Ryujinx.Horizon/Ovln/Ipc/SenderService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Ovln;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Ovln.Ipc
|
||||||
|
{
|
||||||
|
partial class SenderService : ISenderService
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
48
src/Ryujinx.Horizon/Ovln/OvlnIpcServer.cs
Normal file
48
src/Ryujinx.Horizon/Ovln/OvlnIpcServer.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using Ryujinx.Horizon.Ovln.Ipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sm;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Ovln
|
||||||
|
{
|
||||||
|
class OvlnIpcServer
|
||||||
|
{
|
||||||
|
private const int OvlnRcvMaxSessionsCount = 2;
|
||||||
|
private const int OvlnSndMaxSessionsCount = 20;
|
||||||
|
private const int TotalMaxSessionsCount = OvlnRcvMaxSessionsCount + OvlnSndMaxSessionsCount;
|
||||||
|
|
||||||
|
private const int PointerBufferSize = 0;
|
||||||
|
private const int MaxDomains = 21;
|
||||||
|
private const int MaxDomainObjects = 60;
|
||||||
|
private const int MaxPortsCount = 2;
|
||||||
|
|
||||||
|
private static readonly ManagerOptions _options = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
|
||||||
|
|
||||||
|
private SmApi _sm;
|
||||||
|
private ServerManager _serverManager;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
HeapAllocator allocator = new();
|
||||||
|
|
||||||
|
_sm = new SmApi();
|
||||||
|
_sm.Initialize().AbortOnFailure();
|
||||||
|
|
||||||
|
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _options, TotalMaxSessionsCount);
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
_serverManager.RegisterObjectForServer(new ReceiverService(), ServiceName.Encode("ovln:rcv"), OvlnRcvMaxSessionsCount); // 8.0.0+
|
||||||
|
_serverManager.RegisterObjectForServer(new SenderService(), ServiceName.Encode("ovln:snd"), OvlnSndMaxSessionsCount); // 8.0.0+
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServiceRequests()
|
||||||
|
{
|
||||||
|
_serverManager.ServiceRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
_serverManager.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Ryujinx.Horizon/Ovln/OvlnMain.cs
Normal file
17
src/Ryujinx.Horizon/Ovln/OvlnMain.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ryujinx.Horizon.Ovln
|
||||||
|
{
|
||||||
|
class OvlnMain : IService
|
||||||
|
{
|
||||||
|
public static void Main(ServiceTable serviceTable)
|
||||||
|
{
|
||||||
|
OvlnIpcServer ipcServer = new();
|
||||||
|
|
||||||
|
ipcServer.Initialize();
|
||||||
|
|
||||||
|
serviceTable.SignalServiceReady();
|
||||||
|
|
||||||
|
ipcServer.ServiceRequests();
|
||||||
|
ipcServer.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Psc/Ipc/PmControl.cs
Normal file
8
src/Ryujinx.Horizon/Psc/Ipc/PmControl.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Psc;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Psc.Ipc
|
||||||
|
{
|
||||||
|
partial class PmControl : IPmControl
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Psc/Ipc/PmService.cs
Normal file
8
src/Ryujinx.Horizon/Psc/Ipc/PmService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Psc;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Psc.Ipc
|
||||||
|
{
|
||||||
|
partial class PmService : IPmService
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Psc/Ipc/PmStateLock.cs
Normal file
8
src/Ryujinx.Horizon/Psc/Ipc/PmStateLock.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Psc;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Psc.Ipc
|
||||||
|
{
|
||||||
|
partial class PmStateLock : IPmStateLock
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
50
src/Ryujinx.Horizon/Psc/PscIpcServer.cs
Normal file
50
src/Ryujinx.Horizon/Psc/PscIpcServer.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using Ryujinx.Horizon.Psc.Ipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sm;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Psc
|
||||||
|
{
|
||||||
|
class PscIpcServer
|
||||||
|
{
|
||||||
|
private const int PscCMaxSessionsCount = 1;
|
||||||
|
private const int PscMMaxSessionsCount = 50;
|
||||||
|
private const int PscLMaxSessionsCount = 5;
|
||||||
|
private const int TotalMaxSessionsCount = PscCMaxSessionsCount + PscMMaxSessionsCount + PscLMaxSessionsCount;
|
||||||
|
|
||||||
|
private const int PointerBufferSize = 0;
|
||||||
|
private const int MaxDomains = 0;
|
||||||
|
private const int MaxDomainObjects = 0;
|
||||||
|
private const int MaxPortsCount = 3;
|
||||||
|
|
||||||
|
private static readonly ManagerOptions _options = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
|
||||||
|
|
||||||
|
private SmApi _sm;
|
||||||
|
private ServerManager _serverManager;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
HeapAllocator allocator = new();
|
||||||
|
|
||||||
|
_sm = new SmApi();
|
||||||
|
_sm.Initialize().AbortOnFailure();
|
||||||
|
|
||||||
|
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _options, TotalMaxSessionsCount);
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
_serverManager.RegisterObjectForServer(new PmControl(), ServiceName.Encode("psc:c"), PscCMaxSessionsCount);
|
||||||
|
_serverManager.RegisterObjectForServer(new PmService(), ServiceName.Encode("psc:m"), PscMMaxSessionsCount);
|
||||||
|
_serverManager.RegisterObjectForServer(new PmStateLock(), ServiceName.Encode("psc:l"), PscLMaxSessionsCount); // 9.0.0+
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServiceRequests()
|
||||||
|
{
|
||||||
|
_serverManager.ServiceRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
_serverManager.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Ryujinx.Horizon/Psc/PscMain.cs
Normal file
17
src/Ryujinx.Horizon/Psc/PscMain.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ryujinx.Horizon.Psc
|
||||||
|
{
|
||||||
|
class PscMain : IService
|
||||||
|
{
|
||||||
|
public static void Main(ServiceTable serviceTable)
|
||||||
|
{
|
||||||
|
PscIpcServer ipcServer = new();
|
||||||
|
|
||||||
|
ipcServer.Initialize();
|
||||||
|
|
||||||
|
serviceTable.SignalServiceReady();
|
||||||
|
|
||||||
|
ipcServer.ServiceRequests();
|
||||||
|
ipcServer.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Hshl/IManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Hshl/IManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Hshl
|
||||||
|
{
|
||||||
|
interface IManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Hshl/ISetterManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Hshl/ISetterManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Hshl
|
||||||
|
{
|
||||||
|
interface ISetterManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Ins/IReceiverManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Ins/IReceiverManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Ins
|
||||||
|
{
|
||||||
|
interface IReceiverManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Ins/ISenderManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Ins/ISenderManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Ins
|
||||||
|
{
|
||||||
|
interface ISenderManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Ovln/IReceiverService.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Ovln/IReceiverService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Ovln
|
||||||
|
{
|
||||||
|
interface IReceiverService : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Ovln/ISenderService.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Ovln/ISenderService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Ovln
|
||||||
|
{
|
||||||
|
interface ISenderService : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Psc/IPmControl.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Psc/IPmControl.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Psc
|
||||||
|
{
|
||||||
|
interface IPmControl : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Psc/IPmService.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Psc/IPmService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Psc
|
||||||
|
{
|
||||||
|
interface IPmService : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Psc/IPmStateLock.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Psc/IPmStateLock.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Psc
|
||||||
|
{
|
||||||
|
interface IPmStateLock : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Srepo/ISrepoService.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Srepo/ISrepoService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Srepo
|
||||||
|
{
|
||||||
|
interface ISrepoService : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IClientRootSession.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IClientRootSession.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IClientRootSession : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IDsRootSession.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IDsRootSession.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IDsRootSession : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IPdCradleManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IPdCradleManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IPdCradleManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IPdManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IPdManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IPdManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IPdManufactureManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IPdManufactureManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IPdManufactureManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IPmObserverService.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IPmObserverService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IPmObserverService : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IPmService.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IPmService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IPmService : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Sdk/Usb/IQdbManager.cs
Normal file
8
src/Ryujinx.Horizon/Sdk/Usb/IQdbManager.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Sdk.Usb
|
||||||
|
{
|
||||||
|
interface IQdbManager : IServiceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@@ -1,9 +1,15 @@
|
|||||||
using Ryujinx.Horizon.Bcat;
|
using Ryujinx.Horizon.Bcat;
|
||||||
|
using Ryujinx.Horizon.Hshl;
|
||||||
|
using Ryujinx.Horizon.Ins;
|
||||||
using Ryujinx.Horizon.Lbl;
|
using Ryujinx.Horizon.Lbl;
|
||||||
using Ryujinx.Horizon.LogManager;
|
using Ryujinx.Horizon.LogManager;
|
||||||
using Ryujinx.Horizon.MmNv;
|
using Ryujinx.Horizon.MmNv;
|
||||||
using Ryujinx.Horizon.Ngc;
|
using Ryujinx.Horizon.Ngc;
|
||||||
|
using Ryujinx.Horizon.Ovln;
|
||||||
using Ryujinx.Horizon.Prepo;
|
using Ryujinx.Horizon.Prepo;
|
||||||
|
using Ryujinx.Horizon.Psc;
|
||||||
|
using Ryujinx.Horizon.Srepo;
|
||||||
|
using Ryujinx.Horizon.Usb;
|
||||||
using Ryujinx.Horizon.Wlan;
|
using Ryujinx.Horizon.Wlan;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -27,12 +33,18 @@ namespace Ryujinx.Horizon
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegisterService<BcatMain>();
|
RegisterService<BcatMain>();
|
||||||
|
RegisterService<HshlMain>();
|
||||||
|
RegisterService<InsMain>();
|
||||||
RegisterService<LblMain>();
|
RegisterService<LblMain>();
|
||||||
RegisterService<LmMain>();
|
RegisterService<LmMain>();
|
||||||
RegisterService<MmNvMain>();
|
RegisterService<MmNvMain>();
|
||||||
RegisterService<PrepoMain>();
|
|
||||||
RegisterService<WlanMain>();
|
|
||||||
RegisterService<NgcMain>();
|
RegisterService<NgcMain>();
|
||||||
|
RegisterService<OvlnMain>();
|
||||||
|
RegisterService<PrepoMain>();
|
||||||
|
RegisterService<PscMain>();
|
||||||
|
RegisterService<SrepoMain>();
|
||||||
|
RegisterService<UsbMain>();
|
||||||
|
RegisterService<WlanMain>();
|
||||||
|
|
||||||
_totalServices = entries.Count;
|
_totalServices = entries.Count;
|
||||||
|
|
||||||
|
8
src/Ryujinx.Horizon/Srepo/Ipc/SrepoService.cs
Normal file
8
src/Ryujinx.Horizon/Srepo/Ipc/SrepoService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Srepo;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Srepo.Ipc
|
||||||
|
{
|
||||||
|
partial class SrepoService : ISrepoService
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
46
src/Ryujinx.Horizon/Srepo/SrepoIpcServer.cs
Normal file
46
src/Ryujinx.Horizon/Srepo/SrepoIpcServer.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sm;
|
||||||
|
using Ryujinx.Horizon.Srepo.Ipc;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Srepo
|
||||||
|
{
|
||||||
|
class SrepoIpcServer
|
||||||
|
{
|
||||||
|
private const int SrepoAMaxSessionsCount = 2;
|
||||||
|
private const int SrepoUMaxSessionsCount = 30;
|
||||||
|
private const int TotalMaxSessionsCount = SrepoAMaxSessionsCount + SrepoUMaxSessionsCount;
|
||||||
|
|
||||||
|
private const int PointerBufferSize = 0x80;
|
||||||
|
private const int MaxDomains = 32;
|
||||||
|
private const int MaxDomainObjects = 192;
|
||||||
|
private const int MaxPortsCount = 2;
|
||||||
|
|
||||||
|
private static readonly ManagerOptions _options = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
|
||||||
|
|
||||||
|
private SmApi _sm;
|
||||||
|
private ServerManager _serverManager;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
HeapAllocator allocator = new();
|
||||||
|
|
||||||
|
_sm = new SmApi();
|
||||||
|
_sm.Initialize().AbortOnFailure();
|
||||||
|
|
||||||
|
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _options, TotalMaxSessionsCount);
|
||||||
|
|
||||||
|
_serverManager.RegisterObjectForServer(new SrepoService(), ServiceName.Encode("srepo:a"), SrepoAMaxSessionsCount); // 5.0.0+
|
||||||
|
_serverManager.RegisterObjectForServer(new SrepoService(), ServiceName.Encode("srepo:u"), SrepoUMaxSessionsCount); // 5.0.0+
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServiceRequests()
|
||||||
|
{
|
||||||
|
_serverManager.ServiceRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
_serverManager.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Ryujinx.Horizon/Srepo/SrepoMain.cs
Normal file
17
src/Ryujinx.Horizon/Srepo/SrepoMain.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ryujinx.Horizon.Srepo
|
||||||
|
{
|
||||||
|
class SrepoMain : IService
|
||||||
|
{
|
||||||
|
public static void Main(ServiceTable serviceTable)
|
||||||
|
{
|
||||||
|
SrepoIpcServer ipcServer = new();
|
||||||
|
|
||||||
|
ipcServer.Initialize();
|
||||||
|
|
||||||
|
serviceTable.SignalServiceReady();
|
||||||
|
|
||||||
|
ipcServer.ServiceRequests();
|
||||||
|
ipcServer.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Ryujinx.Horizon/Usb/Ipc/ClientRootSession.cs
Normal file
8
src/Ryujinx.Horizon/Usb/Ipc/ClientRootSession.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ryujinx.Horizon.Sdk.Usb;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Usb.Ipc
|
||||||
|
{
|
||||||
|
partial class ClientRootSession : IClientRootSession
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user