Compare commits

..

7 Commits

Author SHA1 Message Date
0e06aace45 misc: Avoid copy of ApplicationControlProperty (#4849)
Avoid more giant copy when passing it around.
2023-05-08 01:50:07 +02:00
adf4ebcd60 Ava: Fix SystemTimeOffset calculation (#4848)
* Ava: Fix SystemTimeOffset calculation

During testing of #4822, Mary pointed out the way we calculate time offset is wrong in our Avalonia UI. This PR fixed that.
The axaml file is autoformatted too.

* DateTime.Now in local var
2023-05-08 00:31:08 +02:00
470a8031a4 time: Update for 15.0.0 changes and fixes long standing issues (#4822)
* time: Update for 15.0.0 changes

Last time we did an upgrade on the time service was during 9.x era, it was about time to take back that reverse again!

15.0.0 added a new structure on the shared memory to get steady clock raw timepoints with a granularity in nanoseconds.

This commit implements this new part.

I plan to write a follow up with a bit of refactoring of this ancient part of the emulator.

As always, reverse and work done by your truly.

PS: As a reminder, if this change is reused anywhere else, work should be credited as Ryujinx and not my person.

* time: Do not set setup value to posix time

This should fix local and network clock returning 0 under usage with
shared memory.

This probably fix #2430.

* Address gdkchan's comment

* Fix internal offset not working since changes and ensure that user clock have a valid clock id

* time: Report auto correcting clock and hardcode steady clock unique id

Fix Pokemon Sword Pokejobs for real.

* Address gdkchan's comment
2023-05-08 00:15:58 +02:00
5440d4ad5c misc: Switch ProcessResult to a class (#4846)
This avoid giant copies being performed when being returned or passed.
2023-05-07 20:50:45 +00:00
dde208b480 UI: Expose games build ID for cheat management (#4340)
* Ava UI: Expose games build ID for cheat management

* Fix bad merge

* Change integrity check level to error on invalid

* Add support for GDK

* Remove whitespace

* Add BID identifier

* PR Comments fix

* Restore title id in cheats GTK window

* use halign center instead of margin_left

* Merge

* fix after merge

* PR comments fix - design AVA

* PR fix - Move GetApplicationBuildId to ApplicationData class

* PR comment fix - Add empty line before method

* Align with PR #4755

* PR comments fix

* Change BuildId label to support translation

* Comments fix

* Remove unused BuildIdLabel property
2023-05-07 14:36:44 +00:00
4c3d2d5d75 UI: Add progress bar for re-packaging shaders (#4805)
* feat: introduce new shader loading state for progress tracking when writing shaders to disk

* fix: move translation to bottom of locale file

* fix: change back to foreach and add requested spacing between lines

* style: fix formatting

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-05-06 15:35:46 +02:00
fab11ba3f1 AM: Stub some service calls (#4825)
* AM: Stub some service call

Some IPC I have stubbed during private testing and I don't want to deal with them anymore. Nothing more.

* ICommonStateGetter disposable
2023-05-06 03:33:50 +02:00
24 changed files with 416 additions and 117 deletions

View File

@ -590,6 +590,7 @@
"DlcWindowTitle": "Manage Downloadable Content for {0} ({1})", "DlcWindowTitle": "Manage Downloadable Content for {0} ({1})",
"UpdateWindowTitle": "Title Update Manager", "UpdateWindowTitle": "Title Update Manager",
"CheatWindowHeading": "Cheats Available for {0} [{1}]", "CheatWindowHeading": "Cheats Available for {0} [{1}]",
"BuildId": "BuildId:",
"DlcWindowHeading": "{0} Downloadable Content(s)", "DlcWindowHeading": "{0} Downloadable Content(s)",
"UserProfilesEditProfile": "Edit Selected", "UserProfilesEditProfile": "Edit Selected",
"Cancel": "Cancel", "Cancel": "Cancel",
@ -644,5 +645,6 @@
"UserEditorTitleCreate" : "Create User", "UserEditorTitleCreate" : "Create User",
"SettingsTabNetworkInterface": "Network Interface:", "SettingsTabNetworkInterface": "Network Interface:",
"NetworkInterfaceTooltip": "The network interface used for LAN features", "NetworkInterfaceTooltip": "The network interface used for LAN features",
"NetworkInterfaceDefault": "Default" "NetworkInterfaceDefault": "Default",
"PackagingShaders": "Packaging Shaders"
} }

View File

@ -10,6 +10,7 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Ui.App.Common;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;
using System; using System;
@ -118,7 +119,11 @@ namespace Ryujinx.Ava.UI.Controls
if (viewModel?.SelectedApplication != null) if (viewModel?.SelectedApplication != null)
{ {
await new CheatWindow(viewModel.VirtualFileSystem, viewModel.SelectedApplication.TitleId, viewModel.SelectedApplication.TitleName).ShowDialog(viewModel.TopLevel as Window); await new CheatWindow(
viewModel.VirtualFileSystem,
viewModel.SelectedApplication.TitleId,
viewModel.SelectedApplication.TitleName,
viewModel.SelectedApplication.Path).ShowDialog(viewModel.TopLevel as Window);
} }
} }

View File

@ -1099,6 +1099,10 @@ namespace Ryujinx.Ava.UI.ViewModels
LoadHeading = LocaleManager.Instance[LocaleKeys.CompilingShaders]; LoadHeading = LocaleManager.Instance[LocaleKeys.CompilingShaders];
IsLoadingIndeterminate = false; IsLoadingIndeterminate = false;
break; break;
case ShaderCacheLoadingState.Packaging:
LoadHeading = LocaleManager.Instance[LocaleKeys.PackagingShaders];
IsLoadingIndeterminate = false;
break;
case ShaderCacheLoadingState.Loaded: case ShaderCacheLoadingState.Loaded:
LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, TitleName); LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, TitleName);
IsLoadingIndeterminate = true; IsLoadingIndeterminate = true;

View File

@ -238,8 +238,9 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public DateTimeOffset DateOffset { get; set; } public DateTimeOffset CurrentDate { get; set; }
public TimeSpan TimeOffset { get; set; } public TimeSpan CurrentTime { get; set; }
internal AvaloniaList<TimeZone> TimeZones { get; set; } internal AvaloniaList<TimeZone> TimeZones { get; set; }
public AvaloniaList<string> GameDirectories { get; set; } public AvaloniaList<string> GameDirectories { get; set; }
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; } public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
@ -397,10 +398,11 @@ namespace Ryujinx.Ava.UI.ViewModels
Language = (int)config.System.Language.Value; Language = (int)config.System.Language.Value;
TimeZone = config.System.TimeZone; TimeZone = config.System.TimeZone;
DateTime dateTimeOffset = DateTime.Now.AddSeconds(config.System.SystemTimeOffset); DateTime currentDateTime = DateTime.Now;
CurrentDate = currentDateTime.Date;
CurrentTime = currentDateTime.TimeOfDay.Add(TimeSpan.FromSeconds(config.System.SystemTimeOffset));
DateOffset = dateTimeOffset.Date;
TimeOffset = dateTimeOffset.TimeOfDay;
EnableVsync = config.Graphics.EnableVsync; EnableVsync = config.Graphics.EnableVsync;
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks; EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
ExpandDramSize = config.System.ExpandRam; ExpandDramSize = config.System.ExpandRam;
@ -487,9 +489,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.System.TimeZone.Value = TimeZone; config.System.TimeZone.Value = TimeZone;
} }
TimeSpan systemTimeOffset = DateOffset - DateTime.Now; config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
config.Graphics.EnableVsync.Value = EnableVsync; config.Graphics.EnableVsync.Value = EnableVsync;
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks; config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
config.System.ExpandRam.Value = ExpandDramSize; config.System.ExpandRam.Value = ExpandDramSize;

View File

@ -11,6 +11,7 @@ using Ryujinx.Common;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.Modules; using Ryujinx.Modules;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;
@ -176,7 +177,11 @@ namespace Ryujinx.Ava.UI.Views.Main
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString(); string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
await new CheatWindow(Window.VirtualFileSystem, ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText, name).ShowDialog(Window); await new CheatWindow(
Window.VirtualFileSystem,
ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
name,
Window.ViewModel.SelectedApplication.Path).ShowDialog(Window);
ViewModel.AppHost.Device.EnableCheats(); ViewModel.AppHost.Device.EnableCheats();
} }

View File

@ -3,12 +3,12 @@
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: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:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels:SettingsViewModel"> x:DataType="viewModels:SettingsViewModel"
mc:Ignorable="d">
<Design.DataContext> <Design.DataContext>
<viewModels:SettingsViewModel /> <viewModels:SettingsViewModel />
</Design.DataContext> </Design.DataContext>
@ -27,13 +27,15 @@
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabSystemCore}" /> <TextBlock Classes="h1" Text="{locale:Locale SettingsTabSystemCore}" />
<StackPanel Margin="10,0,0,0" Orientation="Vertical"> <StackPanel Margin="10,0,0,0" Orientation="Vertical">
<StackPanel Margin="0,0,0,10" Orientation="Horizontal"> <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock
Text="{locale:Locale SettingsTabSystemSystemRegion}" Width="250"
Width="250" /> VerticalAlignment="Center"
<ComboBox SelectedIndex="{Binding Region}" Text="{locale:Locale SettingsTabSystemSystemRegion}" />
ToolTip.Tip="{locale:Locale RegionTooltip}" <ComboBox
Width="350"
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
Width="350"> SelectedIndex="{Binding Region}"
ToolTip.Tip="{locale:Locale RegionTooltip}">
<ComboBoxItem> <ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabSystemSystemRegionJapan}" /> <TextBlock Text="{locale:Locale SettingsTabSystemSystemRegionJapan}" />
</ComboBoxItem> </ComboBoxItem>
@ -58,20 +60,21 @@
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
<StackPanel Margin="0,0,0,10" Orientation="Horizontal"> <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock
Width="250"
VerticalAlignment="Center"
Text="{locale:Locale SettingsTabSystemSystemLanguage}" Text="{locale:Locale SettingsTabSystemSystemLanguage}"
ToolTip.Tip="{locale:Locale LanguageTooltip}" ToolTip.Tip="{locale:Locale LanguageTooltip}" />
Width="250" /> <ComboBox
<ComboBox SelectedIndex="{Binding Language}" Width="350"
ToolTip.Tip="{locale:Locale LanguageTooltip}"
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
Width="350"> SelectedIndex="{Binding Language}"
ToolTip.Tip="{locale:Locale LanguageTooltip}">
<ComboBoxItem> <ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageJapanese}" /> <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageJapanese}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageAmericanEnglish}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageAmericanEnglish}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageFrench}" /> <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageFrench}" />
@ -104,71 +107,67 @@
<TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageTaiwanese}" /> <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageTaiwanese}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageBritishEnglish}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageBritishEnglish}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageCanadianFrench}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageCanadianFrench}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageLatinAmericanSpanish}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageLatinAmericanSpanish}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageSimplifiedChinese}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageSimplifiedChinese}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageTraditionalChinese}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageTraditionalChinese}" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>
<TextBlock <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
Text="{locale:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
</ComboBoxItem> </ComboBoxItem>
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
<StackPanel Margin="0,0,0,10" Orientation="Horizontal"> <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock
Width="250"
VerticalAlignment="Center"
Text="{locale:Locale SettingsTabSystemSystemTimeZone}" Text="{locale:Locale SettingsTabSystemSystemTimeZone}"
ToolTip.Tip="{locale:Locale TimezoneTooltip}" ToolTip.Tip="{locale:Locale TimezoneTooltip}" />
Width="250" />
<AutoCompleteBox <AutoCompleteBox
Name="TimeZoneBox" Name="TimeZoneBox"
Width="350" Width="350"
MaxDropDownHeight="500"
FilterMode="Contains" FilterMode="Contains"
Items="{Binding TimeZones}" Items="{Binding TimeZones}"
MaxDropDownHeight="500"
SelectionChanged="TimeZoneBox_OnSelectionChanged" SelectionChanged="TimeZoneBox_OnSelectionChanged"
Text="{Binding Path=TimeZone, Mode=OneWay}" Text="{Binding Path=TimeZone, Mode=OneWay}"
TextChanged="TimeZoneBox_OnTextChanged" TextChanged="TimeZoneBox_OnTextChanged"
ToolTip.Tip="{locale:Locale TimezoneTooltip}" /> ToolTip.Tip="{locale:Locale TimezoneTooltip}" />
</StackPanel> </StackPanel>
<StackPanel Margin="0,0,0,10" Orientation="Horizontal"> <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock
Width="250"
VerticalAlignment="Center"
Text="{locale:Locale SettingsTabSystemSystemTime}" Text="{locale:Locale SettingsTabSystemSystemTime}"
ToolTip.Tip="{locale:Locale TimeTooltip}" ToolTip.Tip="{locale:Locale TimeTooltip}" />
Width="250"/> <DatePicker
<DatePicker VerticalAlignment="Center" SelectedDate="{Binding DateOffset}" Width="350"
ToolTip.Tip="{locale:Locale TimeTooltip}" VerticalAlignment="Center"
Width="350" /> SelectedDate="{Binding CurrentDate}"
ToolTip.Tip="{locale:Locale TimeTooltip}" />
</StackPanel> </StackPanel>
<StackPanel Margin="250,0,0,10" Orientation="Horizontal"> <StackPanel Margin="250,0,0,10" Orientation="Horizontal">
<TimePicker <TimePicker
Width="350"
VerticalAlignment="Center" VerticalAlignment="Center"
ClockIdentifier="24HourClock" ClockIdentifier="24HourClock"
SelectedTime="{Binding TimeOffset}" SelectedTime="{Binding CurrentTime}"
Width="350"
ToolTip.Tip="{locale:Locale TimeTooltip}" /> ToolTip.Tip="{locale:Locale TimeTooltip}" />
</StackPanel> </StackPanel>
<CheckBox IsChecked="{Binding EnableVsync}"> <CheckBox IsChecked="{Binding EnableVsync}">
<TextBlock Text="{locale:Locale SettingsTabSystemEnableVsync}" <TextBlock Text="{locale:Locale SettingsTabSystemEnableVsync}" ToolTip.Tip="{locale:Locale VSyncToggleTooltip}" />
ToolTip.Tip="{locale:Locale VSyncToggleTooltip}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding EnableFsIntegrityChecks}"> <CheckBox IsChecked="{Binding EnableFsIntegrityChecks}">
<TextBlock Text="{locale:Locale SettingsTabSystemEnableFsIntegrityChecks}" <TextBlock Text="{locale:Locale SettingsTabSystemEnableFsIntegrityChecks}" ToolTip.Tip="{locale:Locale FsIntegrityToggleTooltip}" />
ToolTip.Tip="{locale:Locale FsIntegrityToggleTooltip}" />
</CheckBox> </CheckBox>
</StackPanel> </StackPanel>
<Separator Height="1" /> <Separator Height="1" />
@ -180,12 +179,10 @@
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Orientation="Vertical"> Orientation="Vertical">
<CheckBox IsChecked="{Binding ExpandDramSize}" <CheckBox IsChecked="{Binding ExpandDramSize}" ToolTip.Tip="{locale:Locale DRamTooltip}">
ToolTip.Tip="{locale:Locale DRamTooltip}">
<TextBlock Text="{locale:Locale SettingsTabSystemExpandDramSize}" /> <TextBlock Text="{locale:Locale SettingsTabSystemExpandDramSize}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding IgnoreMissingServices}" <CheckBox IsChecked="{Binding IgnoreMissingServices}" ToolTip.Tip="{locale:Locale IgnoreMissingServicesTooltip}">
ToolTip.Tip="{locale:Locale IgnoreMissingServicesTooltip}">
<TextBlock Text="{locale:Locale SettingsTabSystemIgnoreMissingServices}" /> <TextBlock Text="{locale:Locale SettingsTabSystemIgnoreMissingServices}" />
</CheckBox> </CheckBox>
</StackPanel> </StackPanel>

View File

@ -21,23 +21,52 @@
</Window.Styles> </Window.Styles>
<Grid Name="CheatGrid" Margin="15"> <Grid Name="CheatGrid" Margin="15">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
MaxWidth="500" MaxWidth="500"
Margin="20,15,20,20" Margin="20,15,20,5"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
LineHeight="18" LineHeight="18"
Text="{Binding Heading}" Text="{Binding Heading}"
TextAlignment="Center" TextAlignment="Center"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<Border <TextBlock
Grid.Row="2" Grid.Row="2"
Grid.Column="0"
MaxWidth="500"
Margin="140,15,20,5"
HorizontalAlignment="Center"
VerticalAlignment="Center"
LineHeight="30"
Text="{locale:Locale BuildId}"
TextAlignment="Center"
TextWrapping="Wrap" />
<TextBox
Grid.Row="2"
Grid.Column="1"
Margin="0,5,110,5"
MinWidth="160"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding BuildId}"
IsReadOnly="True" />
<Border
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="5" Margin="5"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
@ -81,7 +110,9 @@
</TreeView> </TreeView>
</Border> </Border>
<DockPanel <DockPanel
Grid.Row="3" Grid.Row="4"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0" Margin="0"
HorizontalAlignment="Stretch"> HorizontalAlignment="Stretch">
<DockPanel Margin="0" HorizontalAlignment="Right"> <DockPanel Margin="0" HorizontalAlignment="Right">

View File

@ -1,8 +1,10 @@
using Avalonia.Collections; using Avalonia;
using Avalonia.Collections;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.Ui.App.Common;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -17,6 +19,7 @@ namespace Ryujinx.Ava.UI.Windows
private AvaloniaList<CheatsList> LoadedCheats { get; } private AvaloniaList<CheatsList> LoadedCheats { get; }
public string Heading { get; } public string Heading { get; }
public string BuildId { get; }
public CheatWindow() public CheatWindow()
{ {
@ -27,11 +30,12 @@ namespace Ryujinx.Ava.UI.Windows
Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle]; Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle];
} }
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName) public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
{ {
LoadedCheats = new AvaloniaList<CheatsList>(); LoadedCheats = new AvaloniaList<CheatsList>();
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper()); Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
InitializeComponent(); InitializeComponent();

View File

@ -299,10 +299,13 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
if (_programList.Count != 0) if (_programList.Count != 0)
{ {
_stateChangeCallback(ShaderCacheState.Packaging, 0, _programList.Count);
Logger.Info?.Print(LogClass.Gpu, $"Rebuilding {_programList.Count} shaders..."); Logger.Info?.Print(LogClass.Gpu, $"Rebuilding {_programList.Count} shaders...");
using var streams = _hostStorage.GetOutputStreams(_context); using var streams = _hostStorage.GetOutputStreams(_context);
int packagedShaders = 0;
foreach (var kv in _programList) foreach (var kv in _programList)
{ {
if (!Active) if (!Active)
@ -311,7 +314,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
} }
(CachedShaderProgram program, byte[] binaryCode) = kv.Value; (CachedShaderProgram program, byte[] binaryCode) = kv.Value;
_hostStorage.AddShader(_context, program, binaryCode, streams); _hostStorage.AddShader(_context, program, binaryCode, streams);
_stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count);
} }
Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {_programList.Count} shaders successfully."); Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {_programList.Count} shaders successfully.");

View File

@ -7,6 +7,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
Start, Start,
/// <summary>Shader cache is loading</summary> /// <summary>Shader cache is loading</summary>
Loading, Loading,
/// <summary>Shader cache is written to disk</summary>
Packaging,
/// <summary>Shader cache finished loading</summary> /// <summary>Shader cache finished loading</summary>
Loaded Loaded
} }

View File

@ -200,9 +200,10 @@ namespace Ryujinx.HLE.HOS
LibHacHorizonManager = device.Configuration.LibHacHorizonManager; LibHacHorizonManager = device.Configuration.LibHacHorizonManager;
// We hardcode a clock source id to avoid it changing between each start.
// TODO: use set:sys (and get external clock source id from settings) // TODO: use set:sys (and get external clock source id from settings)
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate. // TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
UInt128 clockSourceId = UInt128Utils.CreateRandom(); UInt128 clockSourceId = new UInt128(0x36a0328702ce8bc1, 0x1608eaba02333284);
IRtcManager.GetExternalRtcValue(out ulong rtcValue); IRtcManager.GetExternalRtcValue(out ulong rtcValue);
// We assume the rtc is system time. // We assume the rtc is system time.
@ -222,22 +223,22 @@ namespace Ryujinx.HLE.HOS
internalOffset = internalOffset.AddSeconds(-3600L); internalOffset = internalOffset.AddSeconds(-3600L);
} }
internalOffset = new TimeSpanType(-internalOffset.NanoSeconds); systemTime = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds);
// First init the standard steady clock // First init the standard steady clock
TimeServiceManager.Instance.SetupStandardSteadyClock(TickSource, clockSourceId, systemTime, internalOffset, TimeSpanType.Zero, false); TimeServiceManager.Instance.SetupStandardSteadyClock(TickSource, clockSourceId, TimeSpanType.Zero, TimeSpanType.Zero, TimeSpanType.Zero, false);
TimeServiceManager.Instance.SetupStandardLocalSystemClock(TickSource, new SystemClockContext(), systemTime.ToSeconds()); TimeServiceManager.Instance.SetupStandardLocalSystemClock(TickSource, new SystemClockContext(), systemTime.ToSeconds());
TimeServiceManager.Instance.StandardLocalSystemClock.GetClockContext(TickSource, out SystemClockContext localSytemClockContext);
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes)) if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
{ {
TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000); TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000);
// The network system clock needs a valid system clock, as such we setup this system clock using the local system clock. // The network system clock needs a valid system clock, as such we setup this system clock using the local system clock.
TimeServiceManager.Instance.StandardLocalSystemClock.GetClockContext(TickSource, out SystemClockContext localSytemClockContext);
TimeServiceManager.Instance.SetupStandardNetworkSystemClock(localSytemClockContext, standardNetworkClockSufficientAccuracy); TimeServiceManager.Instance.SetupStandardNetworkSystemClock(localSytemClockContext, standardNetworkClockSufficientAccuracy);
} }
TimeServiceManager.Instance.SetupStandardUserSystemClock(TickSource, false, SteadyClockTimePoint.GetRandom()); TimeServiceManager.Instance.SetupStandardUserSystemClock(TickSource, true, localSytemClockContext.SteadyTimePoint);
// FIXME: TimeZone should be init here but it's actually done in ContentManager // FIXME: TimeZone should be init here but it's actually done in ContentManager

View File

@ -92,6 +92,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
return ResultCode.Success; return ResultCode.Success;
} }
[CommandCmif(23)]
// GetAppletCommonFunctions() -> object<nn::am::service::IAppletCommonFunctions>
public ResultCode GetAppletCommonFunctions(ServiceCtx context)
{
MakeObject(context, new IAppletCommonFunctions());
return ResultCode.Success;
}
[CommandCmif(1000)] [CommandCmif(1000)]
// GetDebugFunctions() -> object<nn::am::service::IDebugFunctions> // GetDebugFunctions() -> object<nn::am::service::IDebugFunctions>
public ResultCode GetDebugFunctions(ServiceCtx context) public ResultCode GetDebugFunctions(ServiceCtx context)

View File

@ -9,8 +9,10 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{ {
class ICommonStateGetter : IpcService class ICommonStateGetter : DisposableIpcService
{ {
private readonly ServiceCtx _context;
private Apm.ManagerServer _apmManagerServer; private Apm.ManagerServer _apmManagerServer;
private Apm.SystemManagerServer _apmSystemManagerServer; private Apm.SystemManagerServer _apmSystemManagerServer;
private Lbl.LblControllerServer _lblControllerServer; private Lbl.LblControllerServer _lblControllerServer;
@ -23,11 +25,18 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
private int _messageEventHandle; private int _messageEventHandle;
private int _displayResolutionChangedEventHandle; private int _displayResolutionChangedEventHandle;
private KEvent _acquiredSleepLockEvent;
private int _acquiredSleepLockEventHandle;
public ICommonStateGetter(ServiceCtx context) public ICommonStateGetter(ServiceCtx context)
{ {
_context = context;
_apmManagerServer = new Apm.ManagerServer(context); _apmManagerServer = new Apm.ManagerServer(context);
_apmSystemManagerServer = new Apm.SystemManagerServer(context); _apmSystemManagerServer = new Apm.SystemManagerServer(context);
_lblControllerServer = new Lbl.LblControllerServer(context); _lblControllerServer = new Lbl.LblControllerServer(context);
_acquiredSleepLockEvent = new KEvent(context.Device.System.KernelContext);
} }
[CommandCmif(0)] [CommandCmif(0)]
@ -117,6 +126,34 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
[CommandCmif(10)]
// RequestToAcquireSleepLock()
public ResultCode RequestToAcquireSleepLock(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
[CommandCmif(13)]
// GetAcquiredSleepLockEvent() -> handle<copy>
public ResultCode GetAcquiredSleepLockEvent(ServiceCtx context)
{
if (_acquiredSleepLockEventHandle == 0)
{
if (context.Process.HandleTable.GenerateHandle(_acquiredSleepLockEvent.ReadableEvent, out _acquiredSleepLockEventHandle) != Result.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_acquiredSleepLockEventHandle);
Logger.Stub?.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
[CommandCmif(50)] // 3.0.0+ [CommandCmif(50)] // 3.0.0+
// IsVrModeEnabled() -> b8 // IsVrModeEnabled() -> b8
public ResultCode IsVrModeEnabled(ServiceCtx context) public ResultCode IsVrModeEnabled(ServiceCtx context)
@ -281,5 +318,17 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
if (_acquiredSleepLockEventHandle != 0)
{
_context.Process.HandleTable.CloseHandle(_acquiredSleepLockEventHandle);
_acquiredSleepLockEventHandle = 0;
}
}
}
} }
} }

View File

@ -0,0 +1,13 @@
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Time.Clock.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ContinuousAdjustmentTimePoint
{
public ulong ClockOffset;
public long Multiplier;
public long DivisorLog2;
public SystemClockContext Context;
}
}

View File

@ -1,8 +1,8 @@
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Services.Time.Clock; using Ryujinx.HLE.HOS.Services.Time.Clock;
using Ryujinx.HLE.HOS.Services.Time.Clock.Types;
using Ryujinx.HLE.HOS.Services.Time.Types; using Ryujinx.HLE.HOS.Services.Time.Types;
using Ryujinx.HLE.Utilities;
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
@ -20,6 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
private const uint LocalSystemClockContextOffset = 0x38; private const uint LocalSystemClockContextOffset = 0x38;
private const uint NetworkSystemClockContextOffset = 0x80; private const uint NetworkSystemClockContextOffset = 0x80;
private const uint AutomaticCorrectionEnabledOffset = 0xC8; private const uint AutomaticCorrectionEnabledOffset = 0xC8;
private const uint ContinuousAdjustmentTimePointOffset = 0xD0;
public void Initialize(Switch device, KSharedMemory sharedMemory, SharedMemoryStorage timeSharedMemoryStorage, int timeSharedMemorySize) public void Initialize(Switch device, KSharedMemory sharedMemory, SharedMemoryStorage timeSharedMemoryStorage, int timeSharedMemorySize)
{ {
@ -39,15 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
public void SetupStandardSteadyClock(ITickSource tickSource, UInt128 clockSourceId, TimeSpanType currentTimePoint) public void SetupStandardSteadyClock(ITickSource tickSource, UInt128 clockSourceId, TimeSpanType currentTimePoint)
{ {
TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency); UpdateSteadyClock(tickSource, clockSourceId, currentTimePoint);
SteadyClockContext context = new SteadyClockContext
{
InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds),
ClockSourceId = clockSourceId
};
WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
} }
public void SetAutomaticCorrectionEnabled(bool isAutomaticCorrectionEnabled) public void SetAutomaticCorrectionEnabled(bool isAutomaticCorrectionEnabled)
@ -59,9 +52,37 @@ namespace Ryujinx.HLE.HOS.Services.Time
public void SetSteadyClockRawTimePoint(ITickSource tickSource, TimeSpanType currentTimePoint) public void SetSteadyClockRawTimePoint(ITickSource tickSource, TimeSpanType currentTimePoint)
{ {
SteadyClockContext context = ReadObjectFromSharedMemory<SteadyClockContext>(SteadyClockContextOffset, 4); SteadyClockContext context = ReadObjectFromSharedMemory<SteadyClockContext>(SteadyClockContextOffset, 4);
UpdateSteadyClock(tickSource, context.ClockSourceId, currentTimePoint);
}
private void UpdateSteadyClock(ITickSource tickSource, UInt128 clockSourceId, TimeSpanType currentTimePoint)
{
TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency); TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(tickSource.Counter, tickSource.Frequency);
context.InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds); ContinuousAdjustmentTimePoint adjustmentTimePoint = new ContinuousAdjustmentTimePoint
{
ClockOffset = (ulong)ticksTimeSpan.NanoSeconds,
Multiplier = 1,
DivisorLog2 = 0,
Context = new SystemClockContext
{
Offset = 0,
SteadyTimePoint = new SteadyClockTimePoint
{
ClockSourceId = clockSourceId,
TimePoint = 0
}
}
};
WriteObjectToSharedMemory(ContinuousAdjustmentTimePointOffset, 4, adjustmentTimePoint);
SteadyClockContext context = new SteadyClockContext
{
InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds),
ClockSourceId = clockSourceId
};
WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context); WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
} }

View File

@ -116,7 +116,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
device, device,
device.System.KernelContext, device.System.KernelContext,
metaLoader, metaLoader,
nacpData.Value, nacpData,
enablePtc, enablePtc,
allowCodeMemoryForJit, allowCodeMemoryForJit,
programName, programName,

View File

@ -209,7 +209,7 @@ namespace Ryujinx.HLE.Loaders.Processes
ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device, ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device,
_device.System.KernelContext, _device.System.KernelContext,
dummyExeFs.GetNpdm(), dummyExeFs.GetNpdm(),
nacpData.Value, nacpData,
diskCacheEnabled: false, diskCacheEnabled: false,
allowCodeMemoryForJit: true, allowCodeMemoryForJit: true,
programName, programName,

View File

@ -219,7 +219,7 @@ namespace Ryujinx.HLE.Loaders.Processes
Switch device, Switch device,
KernelContext context, KernelContext context,
MetaLoader metaLoader, MetaLoader metaLoader,
ApplicationControlProperty applicationControlProperties, BlitStruct<ApplicationControlProperty> applicationControlProperties,
bool diskCacheEnabled, bool diskCacheEnabled,
bool allowCodeMemoryForJit, bool allowCodeMemoryForJit,
string name, string name,
@ -355,7 +355,7 @@ namespace Ryujinx.HLE.Loaders.Processes
context.Device.System.TickSource, context.Device.System.TickSource,
context.Device.Gpu, context.Device.Gpu,
$"{programId:x16}", $"{programId:x16}",
applicationControlProperties.DisplayVersionString.ToString(), applicationControlProperties.Value.DisplayVersionString.ToString(),
diskCacheEnabled, diskCacheEnabled,
codeStart, codeStart,
codeSize); codeSize);

View File

@ -1,4 +1,5 @@
using LibHac.Loader; using LibHac.Common;
using LibHac.Loader;
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Cpu; using Ryujinx.Cpu;
@ -9,9 +10,9 @@ using System.Linq;
namespace Ryujinx.HLE.Loaders.Processes namespace Ryujinx.HLE.Loaders.Processes
{ {
public struct ProcessResult public class ProcessResult
{ {
public static ProcessResult Failed => new(null, new ApplicationControlProperty(), false, false, null, 0, 0, 0, TitleLanguage.AmericanEnglish); public static ProcessResult Failed => new(null, new BlitStruct<ApplicationControlProperty>(1), false, false, null, 0, 0, 0, TitleLanguage.AmericanEnglish);
private readonly byte _mainThreadPriority; private readonly byte _mainThreadPriority;
private readonly uint _mainThreadStackSize; private readonly uint _mainThreadStackSize;
@ -32,7 +33,7 @@ namespace Ryujinx.HLE.Loaders.Processes
public ProcessResult( public ProcessResult(
MetaLoader metaLoader, MetaLoader metaLoader,
ApplicationControlProperty applicationControlProperties, BlitStruct<ApplicationControlProperty> applicationControlProperties,
bool diskCacheEnabled, bool diskCacheEnabled,
bool allowCodeMemoryForJit, bool allowCodeMemoryForJit,
IDiskCacheLoadState diskCacheLoadState, IDiskCacheLoadState diskCacheLoadState,
@ -48,7 +49,7 @@ namespace Ryujinx.HLE.Loaders.Processes
ProcessId = pid; ProcessId = pid;
MetaLoader = metaLoader; MetaLoader = metaLoader;
ApplicationControlProperties = applicationControlProperties; ApplicationControlProperties = applicationControlProperties.Value;
if (metaLoader is not null) if (metaLoader is not null)
{ {

View File

@ -1,5 +1,16 @@
using LibHac.Common; using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.FsSystem;
using LibHac.Loader;
using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using System;
using System.IO;
namespace Ryujinx.Ui.App.Common namespace Ryujinx.Ui.App.Common
{ {
@ -19,5 +30,122 @@ namespace Ryujinx.Ui.App.Common
public double FileSizeBytes { get; set; } public double FileSizeBytes { get; set; }
public string Path { get; set; } public string Path { get; set; }
public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; } public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
public static string GetApplicationBuildId(VirtualFileSystem virtualFileSystem, string titleFilePath)
{
using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read);
Nca mainNca = null;
Nca patchNca = null;
if (!System.IO.Path.Exists(titleFilePath))
{
Logger.Error?.Print(LogClass.Application, $"File does not exists. {titleFilePath}");
return string.Empty;
}
string extension = System.IO.Path.GetExtension(titleFilePath).ToLower();
if (extension is ".nsp" or ".xci")
{
PartitionFileSystem pfs;
if (extension == ".xci")
{
Xci xci = new(virtualFileSystem.KeySet, file.AsStorage());
pfs = xci.OpenPartition(XciPartitionType.Secure);
}
else
{
pfs = new PartitionFileSystem(file.AsStorage());
}
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
{
using var ncaFile = new UniqueRef<IFile>();
pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = new(virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
if (nca.Header.ContentType != NcaContentType.Program)
{
continue;
}
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{
patchNca = nca;
}
else
{
mainNca = nca;
}
}
}
else if (extension == ".nca")
{
mainNca = new Nca(virtualFileSystem.KeySet, file.AsStorage());
}
if (mainNca == null)
{
Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file");
return string.Empty;
}
(Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _);
if (updatePatchNca != null)
{
patchNca = updatePatchNca;
}
IFileSystem codeFs = null;
if (patchNca == null)
{
if (mainNca.CanOpenSection(NcaSectionType.Code))
{
codeFs = mainNca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
}
}
else
{
if (patchNca.CanOpenSection(NcaSectionType.Code))
{
codeFs = mainNca.OpenFileSystemWithPatch(patchNca, NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid);
}
}
if (codeFs == null)
{
Logger.Error?.Print(LogClass.Loader, "No ExeFS found in NCA");
return string.Empty;
}
const string mainExeFs = "main";
if (!codeFs.FileExists($"/{mainExeFs}"))
{
Logger.Error?.Print(LogClass.Loader, "No main binary ExeFS found in ExeFS");
return string.Empty;
}
using var nsoFile = new UniqueRef<IFile>();
codeFs.OpenFile(ref nsoFile.Ref, $"/{mainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure();
NsoReader reader = new NsoReader();
reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure();
return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16];
}
} }
} }

View File

@ -1626,9 +1626,12 @@ namespace Ryujinx.Ui
private void ManageCheats_Pressed(object sender, EventArgs args) private void ManageCheats_Pressed(object sender, EventArgs args)
{ {
var window = new CheatWindow(_virtualFileSystem, var window = new CheatWindow(
_virtualFileSystem,
_emulationContext.Processes.ActiveApplication.ProgramId, _emulationContext.Processes.ActiveApplication.ProgramId,
_emulationContext.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString()); _emulationContext.Processes.ActiveApplication.ApplicationControlProperties
.Title[(int)_emulationContext.System.State.DesiredTitleLanguage].NameString.ToString(),
_currentEmulatedGamePath);
window.Destroyed += CheatWindow_Destroyed; window.Destroyed += CheatWindow_Destroyed;
window.Show(); window.Show();

View File

@ -461,7 +461,7 @@ namespace Ryujinx.Ui.Widgets
private void ManageCheats_Clicked(object sender, EventArgs args) private void ManageCheats_Clicked(object sender, EventArgs args)
{ {
new CheatWindow(_virtualFileSystem, _titleId, _titleName).Show(); new CheatWindow(_virtualFileSystem, _titleId, _titleName, _titleFilePath).Show();
} }
private void OpenTitleModDir_Clicked(object sender, EventArgs args) private void OpenTitleModDir_Clicked(object sender, EventArgs args)

View File

@ -1,6 +1,7 @@
using Gtk; using Gtk;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.Ui.App.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -17,16 +18,18 @@ namespace Ryujinx.Ui.Windows
#pragma warning disable CS0649, IDE0044 #pragma warning disable CS0649, IDE0044
[GUI] Label _baseTitleInfoLabel; [GUI] Label _baseTitleInfoLabel;
[GUI] TextView _buildIdTextView;
[GUI] TreeView _cheatTreeView; [GUI] TreeView _cheatTreeView;
[GUI] Button _saveButton; [GUI] Button _saveButton;
#pragma warning restore CS0649, IDE0044 #pragma warning restore CS0649, IDE0044
public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.CheatWindow.glade"), virtualFileSystem, titleId, titleName) { } public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : this(new Builder("Ryujinx.Ui.Windows.CheatWindow.glade"), virtualFileSystem, titleId, titleName, titlePath) { }
private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) : base(builder.GetRawOwnedObject("_cheatWindow")) private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : base(builder.GetRawOwnedObject("_cheatWindow"))
{ {
builder.Autoconnect(this); builder.Autoconnect(this);
_baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]"; _baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]";
_buildIdTextView.Buffer.Text = $"BuildId: {ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath)}";
string modsBasePath = ModLoader.GetModsBasePath(); string modsBasePath = ModLoader.GetModsBasePath();
string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId.ToString("X16")); string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId.ToString("X16"));

View File

@ -31,6 +31,21 @@
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkTextView" id="_buildIdTextView">
<property name="visible">True</property>
<property name="margin_top">10</property>
<property name="halign">center</property>
<property name="margin_bottom">10</property>
<property name="editable">False</property>
<property name="cursor_visible">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">True</property> <property name="visible">True</property>
@ -57,7 +72,7 @@
<packing> <packing>
<property name="expand">True</property> <property name="expand">True</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>