Compare commits
5 Commits
Canary-1.2
...
feature/av
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d64bf7d93c | ||
|
|
52338db1e8 | ||
|
|
aa01f70f46 | ||
|
|
a624fe64b9 | ||
|
|
e02ef52069 |
@@ -296,7 +296,7 @@ namespace Ryujinx.HLE.HOS
|
|||||||
AddModsFromDirectory(mods, applicationDir, modMetadata);
|
AddModsFromDirectory(mods, applicationDir, modMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void QueryContentsDir(ModCache mods, DirectoryInfo contentsDir, ulong applicationId)
|
public static void QueryContentsDir(ModCache mods, DirectoryInfo contentsDir, ulong applicationId, ulong[] installedDlcs)
|
||||||
{
|
{
|
||||||
if (!contentsDir.Exists)
|
if (!contentsDir.Exists)
|
||||||
{
|
{
|
||||||
@@ -311,6 +311,16 @@ namespace Ryujinx.HLE.HOS
|
|||||||
{
|
{
|
||||||
QueryApplicationDir(mods, applicationDir, applicationId);
|
QueryApplicationDir(mods, applicationDir, applicationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (ulong installedDlcId in installedDlcs)
|
||||||
|
{
|
||||||
|
DirectoryInfo dlcModDir = FindApplicationDir(contentsDir, $"{installedDlcId:x16}");
|
||||||
|
|
||||||
|
if (dlcModDir != null)
|
||||||
|
{
|
||||||
|
QueryApplicationDir(mods, dlcModDir, applicationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int QueryCheatsDir(ModCache mods, DirectoryInfo cheatsDir)
|
private static int QueryCheatsDir(ModCache mods, DirectoryInfo cheatsDir)
|
||||||
@@ -417,7 +427,7 @@ namespace Ryujinx.HLE.HOS
|
|||||||
{
|
{
|
||||||
foreach ((ulong applicationId, ModCache cache) in modCaches)
|
foreach ((ulong applicationId, ModCache cache) in modCaches)
|
||||||
{
|
{
|
||||||
QueryContentsDir(cache, searchDir, applicationId);
|
QueryContentsDir(cache, searchDir, applicationId, Array.Empty<ulong>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -206,6 +206,16 @@ namespace Ryujinx.Ava
|
|||||||
_ => ConfigurationState.Instance.Graphics.GraphicsBackend
|
_ => ConfigurationState.Instance.Graphics.GraphicsBackend
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if backend threading was overridden
|
||||||
|
if (CommandLineState.OverrideBackendThreading is not null)
|
||||||
|
ConfigurationState.Instance.Graphics.BackendThreading.Value = CommandLineState.OverrideBackendThreading.ToLower() switch
|
||||||
|
{
|
||||||
|
"auto" => BackendThreading.Auto,
|
||||||
|
"off" => BackendThreading.Off,
|
||||||
|
"on" => BackendThreading.On,
|
||||||
|
_ => ConfigurationState.Instance.Graphics.BackendThreading
|
||||||
|
};
|
||||||
|
|
||||||
// Check if docked mode was overriden.
|
// Check if docked mode was overriden.
|
||||||
if (CommandLineState.OverrideDockedMode.HasValue)
|
if (CommandLineState.OverrideDockedMode.HasValue)
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value;
|
||||||
|
|||||||
@@ -128,7 +128,11 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
|
||||||
await ModManagerWindow.Show(viewModel.SelectedApplication.Id, viewModel.SelectedApplication.Name);
|
await ModManagerWindow.Show(
|
||||||
|
viewModel.SelectedApplication.Id,
|
||||||
|
viewModel.SelectedApplication.IdBase,
|
||||||
|
viewModel.ApplicationLibrary,
|
||||||
|
viewModel.SelectedApplication.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void PurgePtcCache_Click(object sender, RoutedEventArgs args)
|
public async void PurgePtcCache_Click(object sender, RoutedEventArgs args)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using System.IO;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Models
|
namespace Ryujinx.Ava.UI.Models
|
||||||
{
|
{
|
||||||
@@ -21,6 +21,11 @@ namespace Ryujinx.Ava.UI.Models
|
|||||||
public string Path { get; }
|
public string Path { get; }
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
|
public string FormattedName =>
|
||||||
|
InSd && ulong.TryParse(Name, NumberStyles.HexNumber, null, out ulong applicationId)
|
||||||
|
? $"Atmosphère: {System.IO.Path.GetFileNameWithoutExtension(RyujinxApp.MainWindow.ApplicationLibrary.GetNameForApplicationId(applicationId))}"
|
||||||
|
: Name;
|
||||||
|
|
||||||
public ModModel(string path, string name, bool enabled, bool inSd)
|
public ModModel(string path, string name, bool enabled, bool inSd)
|
||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Gommon;
|
|||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
@@ -29,6 +30,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
private string _search;
|
private string _search;
|
||||||
private readonly ulong _applicationId;
|
private readonly ulong _applicationId;
|
||||||
|
private readonly ulong[] _installedDlcIds;
|
||||||
private readonly IStorageProvider _storageProvider;
|
private readonly IStorageProvider _storageProvider;
|
||||||
|
|
||||||
private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
@@ -61,18 +63,23 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
get => string.Format(LocaleManager.Instance[LocaleKeys.ModWindowHeading], Mods.Count);
|
get => string.Format(LocaleManager.Instance[LocaleKeys.ModWindowHeading], Mods.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModManagerViewModel(ulong applicationId)
|
public ModManagerViewModel(ulong applicationId, ulong applicationIdBase, ApplicationLibrary appLibrary)
|
||||||
{
|
{
|
||||||
_applicationId = applicationId;
|
_applicationId = applicationId;
|
||||||
|
|
||||||
|
_installedDlcIds = appLibrary.DownloadableContents.Keys
|
||||||
|
.Where(x => x.TitleIdBase == applicationIdBase)
|
||||||
|
.Select(x => x.TitleId)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
|
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
|
||||||
|
|
||||||
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
|
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
|
||||||
|
|
||||||
LoadMods(applicationId);
|
LoadMods(applicationId, _installedDlcIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadMods(ulong applicationId)
|
private void LoadMods(ulong applicationId, ulong[] installedDlcIds)
|
||||||
{
|
{
|
||||||
Mods.Clear();
|
Mods.Clear();
|
||||||
SelectedMods.Clear();
|
SelectedMods.Clear();
|
||||||
@@ -84,7 +91,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
bool inSd = path == ModLoader.GetSdModsBasePath();
|
bool inSd = path == ModLoader.GetSdModsBasePath();
|
||||||
ModLoader.ModCache modCache = new();
|
ModLoader.ModCache modCache = new();
|
||||||
|
|
||||||
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId);
|
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId, _installedDlcIds);
|
||||||
|
|
||||||
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.RomfsDirs)
|
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.RomfsDirs)
|
||||||
{
|
{
|
||||||
@@ -278,7 +285,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true);
|
File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadMods(_applicationId);
|
LoadMods(_applicationId, _installedDlcIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Add()
|
public async void Add()
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
ModLoader.ModCache mods = new();
|
ModLoader.ModCache mods = new();
|
||||||
|
|
||||||
ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleIdValue);
|
ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleIdValue, []);
|
||||||
|
|
||||||
string currentCheatFile = string.Empty;
|
string currentCheatFile = string.Empty;
|
||||||
string buildId = string.Empty;
|
string buildId = string.Empty;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
MaxLines="2"
|
MaxLines="2"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
TextTrimming="CharacterEllipsis"
|
TextTrimming="CharacterEllipsis"
|
||||||
Text="{Binding Name}" />
|
Text="{Binding FormattedName}" />
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Spacing="10"
|
Spacing="10"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Ryujinx.Ava.Common.Locale;
|
|||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Models;
|
using Ryujinx.Ava.UI.Models;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Button = Avalonia.Controls.Button;
|
using Button = Avalonia.Controls.Button;
|
||||||
@@ -23,21 +24,21 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModManagerWindow(ulong titleId)
|
public ModManagerWindow(ulong titleId, ulong titleIdBase, ApplicationLibrary applicationLibrary)
|
||||||
{
|
{
|
||||||
DataContext = ViewModel = new ModManagerViewModel(titleId);
|
DataContext = ViewModel = new ModManagerViewModel(titleId, titleIdBase, applicationLibrary);
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Show(ulong titleId, string titleName)
|
public static async Task Show(ulong titleId, ulong titleIdBase, ApplicationLibrary appLibrary, string titleName)
|
||||||
{
|
{
|
||||||
ContentDialog contentDialog = new()
|
ContentDialog contentDialog = new()
|
||||||
{
|
{
|
||||||
PrimaryButtonText = string.Empty,
|
PrimaryButtonText = string.Empty,
|
||||||
SecondaryButtonText = string.Empty,
|
SecondaryButtonText = string.Empty,
|
||||||
CloseButtonText = string.Empty,
|
CloseButtonText = string.Empty,
|
||||||
Content = new ModManagerWindow(titleId),
|
Content = new ModManagerWindow(titleId, titleIdBase, appLibrary),
|
||||||
Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowTitle], titleName, titleId.ToString("X16")),
|
Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowTitle], titleName, titleId.ToString("X16")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,30 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a name for an available content file based on the Application ID '<paramref name="id"/>'.
|
||||||
|
/// <br/><br/>
|
||||||
|
/// For Applications, this returns the localized name of the app found in the file.
|
||||||
|
/// For DLCs, this returns the name of the file that contains the DLC, minus the file extension.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The Application ID to search for.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the provided Application ID does not have a corresponding Application OR DLC file,
|
||||||
|
/// <paramref name="id"/> formatted as hexadecimal is returned.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A formatted Application name, or <paramref name="id"/> as hexadecimal if none is found.</returns>
|
||||||
|
public string GetNameForApplicationId(ulong id)
|
||||||
|
{
|
||||||
|
DynamicData.Kernel.Optional<ApplicationData> appData = Applications.Lookup(id);
|
||||||
|
if (appData.HasValue)
|
||||||
|
return appData.Value.Name;
|
||||||
|
|
||||||
|
if (DownloadableContents.Keys.FindFirst(x => x.TitleId == id).TryGet(out DownloadableContentModel dlcData))
|
||||||
|
return dlcData.FileName;
|
||||||
|
|
||||||
|
return id.ToString("X16");
|
||||||
|
}
|
||||||
|
|
||||||
/// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception>
|
/// <exception cref="LibHac.Common.Keys.MissingKeyException">The configured key set is missing a key.</exception>
|
||||||
/// <exception cref="InvalidDataException">The NCA header could not be decrypted.</exception>
|
/// <exception cref="InvalidDataException">The NCA header could not be decrypted.</exception>
|
||||||
/// <exception cref="NotSupportedException">The NCA version is not supported.</exception>
|
/// <exception cref="NotSupportedException">The NCA version is not supported.</exception>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace Ryujinx.Ava.Utilities
|
|||||||
public static bool? OverrideDockedMode { get; private set; }
|
public static bool? OverrideDockedMode { get; private set; }
|
||||||
public static bool? OverrideHardwareAcceleration { get; private set; }
|
public static bool? OverrideHardwareAcceleration { get; private set; }
|
||||||
public static string OverrideGraphicsBackend { get; private set; }
|
public static string OverrideGraphicsBackend { get; private set; }
|
||||||
|
public static string OverrideBackendThreading { get; private set; }
|
||||||
public static string OverrideHideCursor { get; private set; }
|
public static string OverrideHideCursor { get; private set; }
|
||||||
public static string BaseDirPathArg { get; private set; }
|
public static string BaseDirPathArg { get; private set; }
|
||||||
public static string Profile { get; private set; }
|
public static string Profile { get; private set; }
|
||||||
@@ -74,6 +75,16 @@ namespace Ryujinx.Ava.Utilities
|
|||||||
|
|
||||||
OverrideGraphicsBackend = args[++i];
|
OverrideGraphicsBackend = args[++i];
|
||||||
break;
|
break;
|
||||||
|
case "--backend-threading":
|
||||||
|
if (i + 1 >= args.Length)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverrideBackendThreading = args[++i];
|
||||||
|
break;
|
||||||
case "-i":
|
case "-i":
|
||||||
case "--application-id":
|
case "--application-id":
|
||||||
LaunchApplicationId = args[++i];
|
LaunchApplicationId = args[++i];
|
||||||
|
|||||||
Reference in New Issue
Block a user