aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/ACI0.cs6
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/ACID.cs5
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs4
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/FsAccessHeader.cs6
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs4
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/Npdm.cs7
-rw-r--r--src/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs5
-rw-r--r--src/Ryujinx.UI.Common/App/ApplicationLibrary.cs260
8 files changed, 163 insertions, 134 deletions
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/ACI0.cs b/src/Ryujinx.HLE/Loaders/Npdm/ACI0.cs
index 9a5b6b0a..8d828e8e 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/ACI0.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/ACI0.cs
@@ -15,6 +15,12 @@ namespace Ryujinx.HLE.Loaders.Npdm
public ServiceAccessControl ServiceAccessControl { get; private set; }
public KernelAccessControl KernelAccessControl { get; private set; }
+ /// <exception cref="InvalidNpdmException">The stream doesn't contain valid ACI0 data.</exception>
+ /// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
+ /// <exception cref="System.NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
public Aci0(Stream stream, int offset)
{
stream.Seek(offset, SeekOrigin.Begin);
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/ACID.cs b/src/Ryujinx.HLE/Loaders/Npdm/ACID.cs
index ab30b40c..57d0ee27 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/ACID.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/ACID.cs
@@ -19,6 +19,11 @@ namespace Ryujinx.HLE.Loaders.Npdm
public ServiceAccessControl ServiceAccessControl { get; private set; }
public KernelAccessControl KernelAccessControl { get; private set; }
+ /// <exception cref="InvalidNpdmException">The stream doesn't contain valid ACID data.</exception>
+ /// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
public Acid(Stream stream, int offset)
{
stream.Seek(offset, SeekOrigin.Begin);
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs b/src/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs
index f17ca348..a369f9f2 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs
@@ -11,6 +11,10 @@ namespace Ryujinx.HLE.Loaders.Npdm
public int Unknown3 { get; private set; }
public int Unknown4 { get; private set; }
+ /// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
public FsAccessControl(Stream stream, int offset, int size)
{
stream.Seek(offset, SeekOrigin.Begin);
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/FsAccessHeader.cs b/src/Ryujinx.HLE/Loaders/Npdm/FsAccessHeader.cs
index 5987be0e..249f8dd9 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/FsAccessHeader.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/FsAccessHeader.cs
@@ -9,6 +9,12 @@ namespace Ryujinx.HLE.Loaders.Npdm
public int Version { get; private set; }
public ulong PermissionsBitmask { get; private set; }
+ /// <exception cref="InvalidNpdmException">The stream contains invalid data.</exception>
+ /// <exception cref="NotImplementedException">The ContentOwnerId section is not implemented.</exception>
+ /// <exception cref="ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
public FsAccessHeader(Stream stream, int offset, int size)
{
stream.Seek(offset, SeekOrigin.Begin);
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs b/src/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs
index 17124379..979c6f66 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs
@@ -6,6 +6,10 @@ namespace Ryujinx.HLE.Loaders.Npdm
{
public int[] Capabilities { get; private set; }
+ /// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
public KernelAccessControl(Stream stream, int offset, int size)
{
stream.Seek(offset, SeekOrigin.Begin);
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/Npdm.cs b/src/Ryujinx.HLE/Loaders/Npdm/Npdm.cs
index 622d7ee0..4a99de98 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/Npdm.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/Npdm.cs
@@ -24,6 +24,13 @@ namespace Ryujinx.HLE.Loaders.Npdm
public Aci0 Aci0 { get; private set; }
public Acid Acid { get; private set; }
+ /// <exception cref="InvalidNpdmException">The stream doesn't contain valid NPDM data.</exception>
+ /// <exception cref="System.NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
+ /// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="System.ArgumentException">An error occured while reading bytes from the stream.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
public Npdm(Stream stream)
{
BinaryReader reader = new(stream);
diff --git a/src/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs b/src/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs
index bb6df27f..b6bc6492 100644
--- a/src/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs
+++ b/src/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs
@@ -9,6 +9,11 @@ namespace Ryujinx.HLE.Loaders.Npdm
{
public IReadOnlyDictionary<string, bool> Services { get; private set; }
+ /// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
+ /// <exception cref="System.ArgumentException">An error occured while reading bytes from the stream.</exception>
+ /// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
+ /// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
+ /// <exception cref="IOException">An I/O error occurred.</exception>
public ServiceAccessControl(Stream stream, int offset, int size)
{
stream.Seek(offset, SeekOrigin.Begin);
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)
{