diff options
Diffstat (limited to 'src/Ryujinx.UI.Common/App/ApplicationLibrary.cs')
-rw-r--r-- | src/Ryujinx.UI.Common/App/ApplicationLibrary.cs | 260 |
1 files changed, 126 insertions, 134 deletions
diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs index 2baf0608..e7c48162 100644 --- a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs +++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs @@ -72,37 +72,43 @@ namespace Ryujinx.UI.App.Common return resourceByteArray; } + /// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception> + /// <exception cref="NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception> + /// <exception cref="ArgumentException">An error occured while reading bytes from the stream.</exception> + /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception> + /// <exception cref="IOException">An I/O error occurred.</exception> private ApplicationData GetApplicationFromExeFs(PartitionFileSystem pfs, string filePath) { ApplicationData data = new() { Icon = _nspIcon, + Path = filePath, }; using UniqueRef<IFile> npdmFile = new(); - try - { - Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read); - - if (ResultFs.PathNotFound.Includes(result)) - { - Npdm npdm = new(npdmFile.Get.AsStream()); + Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read); - data.Name = npdm.TitleName; - data.Id = npdm.Aci0.TitleId; - } - - return data; - } - catch (Exception exception) + if (ResultFs.PathNotFound.Includes(result)) { - Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{filePath}' Error: {exception.Message}"); + Npdm npdm = new(npdmFile.Get.AsStream()); - return null; + data.Name = npdm.TitleName; + data.Id = npdm.Aci0.TitleId; } + + return data; } + /// <exception cref="MissingKeyException">The configured key set is missing a key.</exception> + /// <exception cref="InvalidDataException">The NCA header could not be decrypted.</exception> + /// <exception cref="NotSupportedException">The NCA version is not supported.</exception> + /// <exception cref="HorizonResultException">An error occured while reading PFS data.</exception> + /// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception> + /// <exception cref="NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception> + /// <exception cref="ArgumentException">An error occured while reading bytes from the stream.</exception> + /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception> + /// <exception cref="IOException">An I/O error occurred.</exception> private ApplicationData GetApplicationFromNsp(PartitionFileSystem pfs, string filePath) { bool isExeFs = false; @@ -170,99 +176,88 @@ namespace Ryujinx.UI.App.Common return null; } + /// <exception cref="MissingKeyException">The configured key set is missing a key.</exception> + /// <exception cref="InvalidDataException">The NCA header could not be decrypted.</exception> + /// <exception cref="NotSupportedException">The NCA version is not supported.</exception> + /// <exception cref="HorizonResultException">An error occured while reading PFS data.</exception> private List<ApplicationData> GetApplicationsFromPfs(IFileSystem pfs, string filePath) { var applications = new List<ApplicationData>(); string extension = Path.GetExtension(filePath).ToLower(); - try + foreach ((ulong titleId, ContentMetaData content) in pfs.GetContentData(ContentMetaType.Application, _virtualFileSystem, _checkLevel)) { - foreach ((ulong titleId, ContentMetaData content) in pfs.GetContentData(ContentMetaType.Application, _virtualFileSystem, _checkLevel)) + ApplicationData applicationData = new() { - ApplicationData applicationData = new() - { - Id = titleId, - Path = filePath, - }; + Id = titleId, + Path = filePath, + }; - Nca mainNca = content.GetNcaByType(_virtualFileSystem.KeySet, ContentType.Program); - Nca controlNca = content.GetNcaByType(_virtualFileSystem.KeySet, ContentType.Control); + Nca mainNca = content.GetNcaByType(_virtualFileSystem.KeySet, ContentType.Program); + Nca controlNca = content.GetNcaByType(_virtualFileSystem.KeySet, ContentType.Control); - BlitStruct<ApplicationControlProperty> controlHolder = new(1); + BlitStruct<ApplicationControlProperty> controlHolder = new(1); - IFileSystem controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, _checkLevel); + IFileSystem controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, _checkLevel); - // Check if there is an update available. - if (IsUpdateApplied(mainNca, out IFileSystem updatedControlFs)) - { - // Replace the original ControlFs by the updated one. - controlFs = updatedControlFs; - } + // Check if there is an update available. + if (IsUpdateApplied(mainNca, out IFileSystem updatedControlFs)) + { + // Replace the original ControlFs by the updated one. + controlFs = updatedControlFs; + } - if (controlFs == null) - { - continue; - } + if (controlFs == null) + { + continue; + } - ReadControlData(controlFs, controlHolder.ByteSpan); + ReadControlData(controlFs, controlHolder.ByteSpan); - GetApplicationInformation(ref controlHolder.Value, ref applicationData); + GetApplicationInformation(ref controlHolder.Value, ref applicationData); - // Read the icon from the ControlFS and store it as a byte array - try - { - using UniqueRef<IFile> icon = new(); + // Read the icon from the ControlFS and store it as a byte array + try + { + using UniqueRef<IFile> icon = new(); - controlFs.OpenFile(ref icon.Ref, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure(); + controlFs.OpenFile(ref icon.Ref, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure(); - using MemoryStream stream = new(); + using MemoryStream stream = new(); - icon.Get.AsStream().CopyTo(stream); - applicationData.Icon = stream.ToArray(); - } - catch (HorizonResultException) + icon.Get.AsStream().CopyTo(stream); + applicationData.Icon = stream.ToArray(); + } + catch (HorizonResultException) + { + foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) { - foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) + if (entry.Name == "control.nacp") { - if (entry.Name == "control.nacp") - { - continue; - } + continue; + } - using var icon = new UniqueRef<IFile>(); + using var icon = new UniqueRef<IFile>(); - controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); - using MemoryStream stream = new(); + using MemoryStream stream = new(); - icon.Get.AsStream().CopyTo(stream); - applicationData.Icon = stream.ToArray(); + icon.Get.AsStream().CopyTo(stream); + applicationData.Icon = stream.ToArray(); - if (applicationData.Icon != null) - { - break; - } + if (applicationData.Icon != null) + { + break; } - - applicationData.Icon ??= extension == ".xci" ? _xciIcon : _nspIcon; } - applicationData.ControlHolder = controlHolder; - - applications.Add(applicationData); + applicationData.Icon ??= extension == ".xci" ? _xciIcon : _nspIcon; } - } - catch (MissingKeyException exception) - { - Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); - } - catch (InvalidDataException) - { - Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {filePath}"); - } - catch (Exception exception) - { - Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{filePath}' Error: {exception}"); + + applicationData.ControlHolder = controlHolder; + + applications.Add(applicationData); } return applications; @@ -319,53 +314,44 @@ namespace Ryujinx.UI.App.Common BinaryReader reader = new(file); ApplicationData application = new(); - try - { - file.Seek(24, SeekOrigin.Begin); - - int assetOffset = reader.ReadInt32(); - - if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET") - { - byte[] iconSectionInfo = Read(assetOffset + 8, 0x10); + file.Seek(24, SeekOrigin.Begin); - long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0); - long iconSize = BitConverter.ToInt64(iconSectionInfo, 8); + int assetOffset = reader.ReadInt32(); - ulong nacpOffset = reader.ReadUInt64(); - ulong nacpSize = reader.ReadUInt64(); + if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET") + { + byte[] iconSectionInfo = Read(assetOffset + 8, 0x10); - // Reads and stores game icon as byte array - if (iconSize > 0) - { - application.Icon = Read(assetOffset + iconOffset, (int)iconSize); - } - else - { - application.Icon = _nroIcon; - } + long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0); + long iconSize = BitConverter.ToInt64(iconSectionInfo, 8); - // Read the NACP data - Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan); + ulong nacpOffset = reader.ReadUInt64(); + ulong nacpSize = reader.ReadUInt64(); - GetApplicationInformation(ref controlHolder.Value, ref application); + // Reads and stores game icon as byte array + if (iconSize > 0) + { + application.Icon = Read(assetOffset + iconOffset, (int)iconSize); } else { application.Icon = _nroIcon; - application.Name = Path.GetFileNameWithoutExtension(applicationPath); } - application.ControlHolder = controlHolder; - applications.Add(application); + // Read the NACP data + Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan); + + GetApplicationInformation(ref controlHolder.Value, ref application); } - catch + else { - Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); - - return false; + application.Icon = _nroIcon; + application.Name = Path.GetFileNameWithoutExtension(applicationPath); } + application.ControlHolder = controlHolder; + applications.Add(application); + break; byte[] Read(long position, int size) @@ -377,34 +363,21 @@ namespace Ryujinx.UI.App.Common } case ".nca": { - try - { - ApplicationData application = new(); - - Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage()); - - if (!nca.IsProgram() || nca.IsPatch()) - { - return false; - } + ApplicationData application = new(); - application.Icon = _ncaIcon; - application.Name = Path.GetFileNameWithoutExtension(applicationPath); - application.ControlHolder = controlHolder; + Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage()); - applications.Add(application); - } - catch (InvalidDataException) + if (!nca.IsProgram() || nca.IsPatch()) { - Logger.Warning?.Print(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}"); - } - catch - { - Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); - return false; } + application.Icon = _ncaIcon; + application.Name = Path.GetFileNameWithoutExtension(applicationPath); + application.ControlHolder = controlHolder; + + applications.Add(application); + break; } // If its an NSO we just set defaults @@ -417,16 +390,35 @@ namespace Ryujinx.UI.App.Common }; applications.Add(application); + break; } } } + catch (MissingKeyException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); + + return false; + } + catch (InvalidDataException) + { + Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}"); + + return false; + } catch (IOException exception) { Logger.Warning?.Print(LogClass.Application, exception.Message); return false; } + catch (Exception exception) + { + Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}"); + + return false; + } foreach (var data in applications) { |