diff --git a/Ryujinx.HLE/FileSystem/Content/ContentManager.cs b/Ryujinx.HLE/FileSystem/Content/ContentManager.cs index 9ed2e1422..17faa19f6 100644 --- a/Ryujinx.HLE/FileSystem/Content/ContentManager.cs +++ b/Ryujinx.HLE/FileSystem/Content/ContentManager.cs @@ -1,5 +1,5 @@ -using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; using Ryujinx.HLE.HOS.Services.Time; using Ryujinx.HLE.Utilities; using System; @@ -16,13 +16,13 @@ namespace Ryujinx.HLE.FileSystem.Content private Dictionary _sharedFontTitleDictionary; private Dictionary _sharedFontFilenameDictionary; - private SortedDictionary<(ulong, ContentType), string> _contentDictionary; + private SortedDictionary<(ulong, NcaContentType), string> _contentDictionary; private Switch _device; public ContentManager(Switch device) { - _contentDictionary = new SortedDictionary<(ulong, ContentType), string>(); + _contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>(); _locationEntries = new Dictionary>(); _sharedFontTitleDictionary = new Dictionary @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.FileSystem.Content public void LoadEntries() { - _contentDictionary = new SortedDictionary<(ulong, ContentType), string>(); + _contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>(); foreach (StorageId storageId in Enum.GetValues(typeof(StorageId))) { @@ -146,7 +146,7 @@ namespace Ryujinx.HLE.FileSystem.Content TimeManager.Instance.InitializeTimeZone(_device); } - public void ClearEntry(long titleId, ContentType contentType, StorageId storageId) + public void ClearEntry(long titleId, NcaContentType contentType, StorageId storageId) { RemoveLocationEntry(titleId, contentType, storageId); } @@ -173,10 +173,10 @@ namespace Ryujinx.HLE.FileSystem.Content { if (_contentDictionary.ContainsValue(ncaId)) { - var content = _contentDictionary.FirstOrDefault(x => x.Value == ncaId); - long titleId = (long)content.Key.Item1; - ContentType contentType = content.Key.Item2; - StorageId storage = GetInstalledStorage(titleId, contentType, storageId); + var content = _contentDictionary.FirstOrDefault(x => x.Value == ncaId); + long titleId = (long)content.Key.Item1; + NcaContentType contentType = content.Key.Item2; + StorageId storage = GetInstalledStorage(titleId, contentType, storageId); return storage == storageId; } @@ -184,7 +184,7 @@ namespace Ryujinx.HLE.FileSystem.Content return false; } - public UInt128 GetInstalledNcaId(long titleId, ContentType contentType) + public UInt128 GetInstalledNcaId(long titleId, NcaContentType contentType) { if (_contentDictionary.ContainsKey(((ulong)titleId,contentType))) { @@ -194,7 +194,7 @@ namespace Ryujinx.HLE.FileSystem.Content return new UInt128(); } - public StorageId GetInstalledStorage(long titleId, ContentType contentType, StorageId storageId) + public StorageId GetInstalledStorage(long titleId, NcaContentType contentType, StorageId storageId) { LocationEntry locationEntry = GetLocation(titleId, contentType, storageId); @@ -202,7 +202,7 @@ namespace Ryujinx.HLE.FileSystem.Content LocationHelper.GetStorageId(locationEntry.ContentPath) : StorageId.None; } - public string GetInstalledContentPath(long titleId, StorageId storageId, ContentType contentType) + public string GetInstalledContentPath(long titleId, StorageId storageId, NcaContentType contentType) { LocationEntry locationEntry = GetLocation(titleId, contentType, storageId); @@ -226,7 +226,7 @@ namespace Ryujinx.HLE.FileSystem.Content AddLocationEntry(newEntry, storageId); } - private bool VerifyContentType(LocationEntry locationEntry, ContentType contentType) + private bool VerifyContentType(LocationEntry locationEntry, NcaContentType contentType) { if (locationEntry.ContentPath == null) { @@ -273,7 +273,7 @@ namespace Ryujinx.HLE.FileSystem.Content } } - private void RemoveLocationEntry(long titleId, ContentType contentType, StorageId storageId) + private void RemoveLocationEntry(long titleId, NcaContentType contentType, StorageId storageId) { LinkedList locationList = null; @@ -304,7 +304,7 @@ namespace Ryujinx.HLE.FileSystem.Content return _sharedFontFilenameDictionary.TryGetValue(fontName, out filename); } - private LocationEntry GetLocation(long titleId, ContentType contentType, StorageId storageId) + private LocationEntry GetLocation(long titleId, NcaContentType contentType, StorageId storageId) { LinkedList locationList = _locationEntries[storageId]; diff --git a/Ryujinx.HLE/FileSystem/Content/LocationEntry.cs b/Ryujinx.HLE/FileSystem/Content/LocationEntry.cs index 2ab7ea80f..15485148e 100644 --- a/Ryujinx.HLE/FileSystem/Content/LocationEntry.cs +++ b/Ryujinx.HLE/FileSystem/Content/LocationEntry.cs @@ -1,15 +1,15 @@ -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem.NcaUtils; namespace Ryujinx.HLE.FileSystem.Content { public struct LocationEntry { - public string ContentPath { get; private set; } - public int Flag { get; private set; } - public long TitleId { get; private set; } - public ContentType ContentType { get; private set; } + public string ContentPath { get; private set; } + public int Flag { get; private set; } + public long TitleId { get; private set; } + public NcaContentType ContentType { get; private set; } - public LocationEntry(string contentPath, int flag, long titleId, ContentType contentType) + public LocationEntry(string contentPath, int flag, long titleId, NcaContentType contentType) { ContentPath = contentPath; Flag = flag; diff --git a/Ryujinx.HLE/FileSystem/SaveHelper.cs b/Ryujinx.HLE/FileSystem/SaveHelper.cs index a10724982..b9abcb855 100644 --- a/Ryujinx.HLE/FileSystem/SaveHelper.cs +++ b/Ryujinx.HLE/FileSystem/SaveHelper.cs @@ -1,4 +1,5 @@ using LibHac.Fs; +using LibHac.FsSystem; using Ryujinx.HLE.HOS; using System.IO; @@ -21,9 +22,9 @@ namespace Ryujinx.HLE.FileSystem using (LocalStorage systemSaveData = new LocalStorage(savePath, FileAccess.Read, FileMode.Open)) { - IFileSystem saveFs = new LibHac.Fs.Save.SaveDataFileSystem(context.Device.System.KeySet, systemSaveData, IntegrityCheckLevel.None, false); + IFileSystem saveFs = new LibHac.FsSystem.Save.SaveDataFileSystem(context.Device.System.KeySet, systemSaveData, IntegrityCheckLevel.None, false); - saveFs.CopyFileSystem(outputFolder); + saveFs.CopyDirectory(outputFolder, "/", "/"); } File.Delete(savePath); diff --git a/Ryujinx.HLE/HOS/Font/SharedFontManager.cs b/Ryujinx.HLE/HOS/Font/SharedFontManager.cs index 11ba1ab45..40a81b86e 100644 --- a/Ryujinx.HLE/HOS/Font/SharedFontManager.cs +++ b/Ryujinx.HLE/HOS/Font/SharedFontManager.cs @@ -1,5 +1,6 @@ using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; using Ryujinx.Common; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.FileSystem; @@ -55,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Font if (contentManager.TryGetFontTitle(name, out long fontTitle) && contentManager.TryGetFontFilename(name, out string fontFilename)) { - string contentPath = contentManager.GetInstalledContentPath(fontTitle, StorageId.NandSystem, ContentType.Data); + string contentPath = contentManager.GetInstalledContentPath(fontTitle, StorageId.NandSystem, NcaContentType.Data); string fontPath = _device.FileSystem.SwitchPathToSystemPath(contentPath); if (!string.IsNullOrWhiteSpace(fontPath)) @@ -66,9 +67,10 @@ namespace Ryujinx.HLE.HOS.Font { Nca nca = new Nca(_device.System.KeySet, ncaFileStream); IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel); - Stream fontFile = romfs.OpenFile(fontFilename, OpenMode.Read).AsStream(); - data = DecryptFont(fontFile); + romfs.OpenFile(out IFile fontFile, "/" + fontFilename, OpenMode.Read).ThrowIfFailure(); + + data = DecryptFont(fontFile.AsStream()); } FontInfo info = new FontInfo((int)fontOffset, data.Length); diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 80c9ef0cb..0deb7ac16 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -1,6 +1,9 @@ using LibHac; using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsService; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; +using LibHac.Spl; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS.Font; @@ -116,6 +119,9 @@ namespace Ryujinx.HLE.HOS internal long HidBaseAddress { get; private set; } + internal FileSystemServer FsServer { get; private set; } + internal EmulatedGameCard GameCard { get; private set; } + public Horizon(Switch device) { ControlData = new Nacp(); @@ -228,6 +234,21 @@ namespace Ryujinx.HLE.HOS // FIXME: TimeZone shoud be init here but it's actually done in ContentManager TimeServiceManager.Instance.SetupEphemeralNetworkSystemClock(); + + LocalFileSystem serverBaseFs = new LocalFileSystem(device.FileSystem.GetBasePath()); + + DefaultFsServerObjects fsServerObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(serverBaseFs, KeySet); + + GameCard = fsServerObjects.GameCard; + + FileSystemServerConfig fsServerConfig = new FileSystemServerConfig + { + FsCreators = fsServerObjects.FsCreators, + DeviceOperator = fsServerObjects.DeviceOperator, + ExternalKeySet = KeySet.ExternalKeySet + }; + + FsServer = new FileSystemServer(fsServerConfig); } public void LoadCart(string exeFsDir, string romFsFile = null) @@ -283,25 +304,31 @@ namespace Ryujinx.HLE.HOS XciPartition securePartition = xci.OpenPartition(XciPartitionType.Secure); - foreach (DirectoryEntry ticketEntry in securePartition.EnumerateEntries("*.tik")) + foreach (DirectoryEntryEx ticketEntry in securePartition.EnumerateEntries("/", "*.tik")) { - Ticket ticket = new Ticket(securePartition.OpenFile(ticketEntry.FullPath, OpenMode.Read).AsStream()); + Result result = securePartition.OpenFile(out IFile ticketFile, ticketEntry.FullPath, OpenMode.Read); - if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId)) + if (result.IsSuccess()) { - KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet)); + Ticket ticket = new Ticket(ticketFile.AsStream()); + + KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet))); } } - foreach (DirectoryEntry fileEntry in securePartition.EnumerateEntries("*.nca")) + foreach (DirectoryEntryEx fileEntry in securePartition.EnumerateEntries("/", "*.nca")) { - IStorage ncaStorage = securePartition.OpenFile(fileEntry.FullPath, OpenMode.Read).AsStorage(); - - Nca nca = new Nca(KeySet, ncaStorage); - - if (nca.Header.ContentType == ContentType.Program) + Result result = securePartition.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read); + if (result.IsFailure()) { - int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, ContentType.Program); + continue; + } + + Nca nca = new Nca(KeySet, ncaFile.AsStorage()); + + if (nca.Header.ContentType == NcaContentType.Program) + { + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.Header.GetFsHeader(dataIndex).IsPatchSection()) { @@ -312,7 +339,7 @@ namespace Ryujinx.HLE.HOS mainNca = nca; } } - else if (nca.Header.ContentType == ContentType.Control) + else if (nca.Header.ContentType == NcaContentType.Control) { controlNca = nca; } @@ -335,11 +362,14 @@ namespace Ryujinx.HLE.HOS { IFileSystem controlFs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel); - IFile controlFile = controlFs.OpenFile("/control.nacp", OpenMode.Read); + Result result = controlFs.OpenFile(out IFile controlFile, "/control.nacp", OpenMode.Read); - ControlData = new Nacp(controlFile.AsStream()); + if (result.IsSuccess()) + { + ControlData = new Nacp(controlFile.AsStream()); - TitleName = CurrentTitle = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title; + TitleName = CurrentTitle = ControlData.Descriptions[(int) State.DesiredTitleLanguage].Title; + } } public void LoadNca(string ncaFile) @@ -357,13 +387,15 @@ namespace Ryujinx.HLE.HOS PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage()); - foreach (DirectoryEntry ticketEntry in nsp.EnumerateEntries("*.tik")) + foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik")) { - Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry.FullPath, OpenMode.Read).AsStream()); + Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath, OpenMode.Read); - if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId)) + if (result.IsSuccess()) { - KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet)); + Ticket ticket = new Ticket(ticketFile.AsStream()); + + KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet))); } } @@ -371,15 +403,15 @@ namespace Ryujinx.HLE.HOS Nca patchNca = null; Nca controlNca = null; - foreach (DirectoryEntry fileEntry in nsp.EnumerateEntries("*.nca")) + foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca")) { - IStorage ncaStorage = nsp.OpenFile(fileEntry.FullPath, OpenMode.Read).AsStorage(); + nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); - Nca nca = new Nca(KeySet, ncaStorage); + Nca nca = new Nca(KeySet, ncaFile.AsStorage()); - if (nca.Header.ContentType == ContentType.Program) + if (nca.Header.ContentType == NcaContentType.Program) { - int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, ContentType.Program); + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); if (nca.Header.GetFsHeader(dataIndex).IsPatchSection()) { @@ -390,7 +422,7 @@ namespace Ryujinx.HLE.HOS mainNca = nca; } } - else if (nca.Header.ContentType == ContentType.Control) + else if (nca.Header.ContentType == NcaContentType.Control) { controlNca = nca; } @@ -409,7 +441,7 @@ namespace Ryujinx.HLE.HOS public void LoadNca(Nca mainNca, Nca patchNca, Nca controlNca) { - if (mainNca.Header.ContentType != ContentType.Program) + if (mainNca.Header.ContentType != NcaContentType.Program) { Logger.PrintError(LogClass.Loader, "Selected NCA is not a \"Program\" NCA"); @@ -466,7 +498,7 @@ namespace Ryujinx.HLE.HOS { IFileSystem controlRomfs = controlNca.OpenFileSystem(NcaSectionType.Data, FsIntegrityCheckLevel); - IFile controlFile = controlRomfs.OpenFile("/control.nacp", OpenMode.Read); + controlRomfs.OpenFile(out IFile controlFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); Nacp controlData = new Nacp(controlFile.AsStream()); @@ -493,24 +525,24 @@ namespace Ryujinx.HLE.HOS private void LoadExeFs(IFileSystem codeFs, out Npdm metaData) { - if (codeFs.FileExists("/main.npdm")) - { - Logger.PrintInfo(LogClass.Loader, "Loading main.npdm..."); + Result result = codeFs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read); - metaData = new Npdm(codeFs.OpenFile("/main.npdm", OpenMode.Read).AsStream()); - } - else + if (result == ResultFs.PathNotFound) { Logger.PrintWarning(LogClass.Loader, "NPDM file not found, using default values!"); metaData = GetDefaultNpdm(); } + else + { + metaData = new Npdm(npdmFile.AsStream()); + } List staticObjects = new List(); void LoadNso(string filename) { - foreach (DirectoryEntry file in codeFs.EnumerateEntries($"{filename}*")) + foreach (DirectoryEntryEx file in codeFs.EnumerateEntries("/", $"{filename}*")) { if (Path.GetExtension(file.Name) != string.Empty) { @@ -519,7 +551,9 @@ namespace Ryujinx.HLE.HOS Logger.PrintInfo(LogClass.Loader, $"Loading {file.Name}..."); - NxStaticObject staticObject = new NxStaticObject(codeFs.OpenFile(file.FullPath, OpenMode.Read).AsStream()); + codeFs.OpenFile(out IFile nsoFile, file.FullPath, OpenMode.Read).ThrowIfFailure(); + + NxStaticObject staticObject = new NxStaticObject(nsoFile.AsStream()); staticObjects.Add(staticObject); } @@ -654,7 +688,7 @@ namespace Ryujinx.HLE.HOS LoadSetAtPath(Path.Combine(home, ".switch")); LoadSetAtPath(Device.FileSystem.GetSystemPath()); - KeySet = ExternalKeys.ReadKeyFile(keyFile, titleKeyFile, consoleKeyFile); + KeySet = ExternalKeyReader.ReadKeyFile(keyFile, titleKeyFile, consoleKeyFile); void LoadSetAtPath(string basePath) { diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs index 04b87b57f..2b0f06dda 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs @@ -1,6 +1,8 @@ using LibHac; using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; +using LibHac.Spl; using Ryujinx.Common; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.Utilities; @@ -25,7 +27,14 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy try { LocalFileSystem fileSystem = new LocalFileSystem(savePath); - LibHac.Fs.IFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem); + + Result result = DirectorySaveDataFileSystem.CreateNew(out DirectorySaveDataFileSystem dirFileSystem, fileSystem); + if (result.IsFailure()) + { + return (ResultCode)result.Value; + } + + LibHac.Fs.IFileSystem saveFileSystem = dirFileSystem; if (readOnly) { @@ -111,13 +120,16 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage()); ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet); - + string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\'); - if (nsp.FileExists(filename)) + Result result = nsp.OpenFile(out LibHac.Fs.IFile ncaFile, filename, OpenMode.Read); + if (result.IsFailure()) { - return OpenNcaFs(context, fullPath, nsp.OpenFile(filename, OpenMode.Read).AsStorage(), out openedFileSystem); + return (ResultCode)result.Value; } + + return OpenNcaFs(context, fullPath, ncaFile.AsStorage(), out openedFileSystem); } catch (HorizonResultException ex) { @@ -130,15 +142,17 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy public static void ImportTitleKeysFromNsp(LibHac.Fs.IFileSystem nsp, Keyset keySet) { - foreach (DirectoryEntry ticketEntry in nsp.EnumerateEntries("*.tik")) + foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik")) { - Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry.FullPath, OpenMode.Read).AsStream()); + Result result = nsp.OpenFile(out LibHac.Fs.IFile ticketFile, ticketEntry.FullPath, OpenMode.Read); - if (!keySet.TitleKeys.ContainsKey(ticket.RightsId)) + if (result.IsSuccess()) { - keySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(keySet)); + Ticket ticket = new Ticket(ticketFile.AsStream()); + + keySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(keySet))); } } } } -} \ No newline at end of file +} diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs index 4fc8a6873..c042ed8e9 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs @@ -1,21 +1,17 @@ using LibHac; -using System.Collections.Generic; -using System.Text; +using LibHac.Fs; +using System; +using System.Runtime.InteropServices; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { class IDirectory : IpcService { - private const int DirectoryEntrySize = 0x310; - - private IEnumerator _enumerator; - private LibHac.Fs.IDirectory _baseDirectory; public IDirectory(LibHac.Fs.IDirectory directory) { _baseDirectory = directory; - _enumerator = directory.Read().GetEnumerator(); } [Command(0)] @@ -25,60 +21,26 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy long bufferPosition = context.Request.ReceiveBuff[0].Position; long bufferLen = context.Request.ReceiveBuff[0].Size; - int maxReadCount = (int)(bufferLen / DirectoryEntrySize); - int readCount = 0; + byte[] entriesBytes = new byte[bufferLen]; + Span entries = MemoryMarshal.Cast(entriesBytes); - try - { - while (readCount < maxReadCount && _enumerator.MoveNext()) - { - long position = bufferPosition + readCount * DirectoryEntrySize; + Result result = _baseDirectory.Read(out long entriesRead, entries); - WriteDirectoryEntry(context, position, _enumerator.Current); + context.Memory.WriteBytes(bufferPosition, entriesBytes); + context.ResponseData.Write(entriesRead); - readCount++; - } - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - context.ResponseData.Write((long)readCount); - - return ResultCode.Success; - } - - private void WriteDirectoryEntry(ServiceCtx context, long position, LibHac.Fs.DirectoryEntry entry) - { - for (int offset = 0; offset < 0x300; offset += 8) - { - context.Memory.WriteInt64(position + offset, 0); - } - - byte[] nameBuffer = Encoding.UTF8.GetBytes(entry.Name); - - context.Memory.WriteBytes(position, nameBuffer); - - context.Memory.WriteInt32(position + 0x300, (int)entry.Attributes); - context.Memory.WriteInt32(position + 0x304, (byte)entry.Type); - context.Memory.WriteInt64(position + 0x308, entry.Size); + return (ResultCode)result.Value; } [Command(1)] // GetEntryCount() -> u64 public ResultCode GetEntryCount(ServiceCtx context) { - try - { - context.ResponseData.Write((long)_baseDirectory.GetEntryCount()); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _baseDirectory.GetEntryCount(out long entryCount); - return ResultCode.Success; + context.ResponseData.Write(entryCount); + + return (ResultCode)result.Value; } } } diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs index df9209e60..f09624f87 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs @@ -26,22 +26,14 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy long size = context.RequestData.ReadInt64(); byte[] data = new byte[size]; - int readSize; - try - { - readSize = _baseFile.Read(data, offset, readOption); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _baseFile.Read(out long bytesRead, offset, data, readOption); context.Memory.WriteBytes(position, data); - context.ResponseData.Write((long)readSize); + context.ResponseData.Write(bytesRead); - return ResultCode.Success; + return (ResultCode)result.Value; } [Command(1)] @@ -58,66 +50,34 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy byte[] data = context.Memory.ReadBytes(position, size); - try - { - _baseFile.Write(data, offset, writeOption); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_baseFile.Write(offset, data, writeOption).Value; } [Command(2)] // Flush() public ResultCode Flush(ServiceCtx context) { - try - { - _baseFile.Flush(); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_baseFile.Flush().Value; } [Command(3)] // SetSize(u64 size) public ResultCode SetSize(ServiceCtx context) { - try - { - long size = context.RequestData.ReadInt64(); + long size = context.RequestData.ReadInt64(); - _baseFile.SetSize(size); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_baseFile.SetSize(size).Value; } [Command(4)] // GetSize() -> u64 fileSize public ResultCode GetSize(ServiceCtx context) { - try - { - context.ResponseData.Write(_baseFile.GetSize()); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _baseFile.GetSize(out long size); - return ResultCode.Success; + context.ResponseData.Write(size); + + return (ResultCode)result.Value; } public void Dispose() diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs index 7a7fdbaf1..ed7ae0c17 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs @@ -25,16 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy long size = context.RequestData.ReadInt64(); - try - { - _fileSystem.CreateFile(name, size, createOption); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.CreateFile(name, size, createOption).Value; } [Command(1)] @@ -43,16 +34,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - _fileSystem.DeleteFile(name); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.DeleteFile(name).Value; } [Command(2)] @@ -61,16 +43,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - _fileSystem.CreateDirectory(name); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.CreateDirectory(name).Value; } [Command(3)] @@ -79,16 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - _fileSystem.DeleteDirectory(name); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.DeleteDirectory(name).Value; } [Command(4)] @@ -97,16 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - _fileSystem.DeleteDirectoryRecursively(name); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.DeleteDirectoryRecursively(name).Value; } [Command(5)] @@ -116,16 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy string oldName = ReadUtf8String(context, 0); string newName = ReadUtf8String(context, 1); - try - { - _fileSystem.RenameFile(oldName, newName); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.RenameFile(oldName, newName).Value; } [Command(6)] @@ -135,16 +81,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy string oldName = ReadUtf8String(context, 0); string newName = ReadUtf8String(context, 1); - try - { - _fileSystem.RenameDirectory(oldName, newName); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.RenameDirectory(oldName, newName).Value; } [Command(7)] @@ -153,25 +90,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - DirectoryEntryType entryType = _fileSystem.GetEntryType(name); + Result result = _fileSystem.GetEntryType(out DirectoryEntryType entryType, name); - if (entryType == DirectoryEntryType.Directory || entryType == DirectoryEntryType.File) - { - context.ResponseData.Write((int)entryType); - } - else - { - return ResultCode.PathDoesNotExist; - } - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + context.ResponseData.Write((int)entryType); - return ResultCode.Success; + return (ResultCode)result.Value; } [Command(8)] @@ -182,20 +105,16 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy string name = ReadUtf8String(context); - try - { - LibHac.Fs.IFile file = _fileSystem.OpenFile(name, mode); + Result result = _fileSystem.OpenFile(out LibHac.Fs.IFile file, name, mode); + if (result.IsSuccess()) + { IFile fileInterface = new IFile(file); MakeObject(context, fileInterface); } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - return ResultCode.Success; + return (ResultCode)result.Value; } [Command(9)] @@ -206,36 +125,23 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy string name = ReadUtf8String(context); - try - { - LibHac.Fs.IDirectory dir = _fileSystem.OpenDirectory(name, mode); + Result result = _fileSystem.OpenDirectory(out LibHac.Fs.IDirectory dir, name, mode); + if (result.IsSuccess()) + { IDirectory dirInterface = new IDirectory(dir); MakeObject(context, dirInterface); } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - return ResultCode.Success; + return (ResultCode)result.Value; } [Command(10)] // Commit() public ResultCode Commit(ServiceCtx context) { - try - { - _fileSystem.Commit(); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.Commit().Value; } [Command(11)] @@ -244,16 +150,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - context.ResponseData.Write(_fileSystem.GetFreeSpaceSize(name)); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _fileSystem.GetFreeSpaceSize(out long size, name); - return ResultCode.Success; + context.ResponseData.Write(size); + + return (ResultCode)result.Value; } [Command(12)] @@ -262,16 +163,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - context.ResponseData.Write(_fileSystem.GetTotalSpaceSize(name)); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _fileSystem.GetTotalSpaceSize(out long size, name); - return ResultCode.Success; + context.ResponseData.Write(size); + + return (ResultCode)result.Value; } [Command(13)] @@ -280,16 +176,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - _fileSystem.CleanDirectoryRecursively(name); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } - - return ResultCode.Success; + return (ResultCode)_fileSystem.CleanDirectoryRecursively(name).Value; } [Command(14)] @@ -298,27 +185,20 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { string name = ReadUtf8String(context); - try - { - FileTimeStampRaw timestamp = _fileSystem.GetFileTimeStampRaw(name); + Result result = _fileSystem.GetFileTimeStampRaw(out FileTimeStampRaw timestamp, name); - context.ResponseData.Write(timestamp.Created); - context.ResponseData.Write(timestamp.Modified); - context.ResponseData.Write(timestamp.Accessed); + context.ResponseData.Write(timestamp.Created); + context.ResponseData.Write(timestamp.Modified); + context.ResponseData.Write(timestamp.Accessed); - byte[] data = new byte[8]; + byte[] data = new byte[8]; - // is valid? - data[0] = 1; + // is valid? + data[0] = 1; - context.ResponseData.Write(data); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + context.ResponseData.Write(data); - return ResultCode.Success; + return (ResultCode)result.Value; } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs index 107599a47..cc407039b 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs @@ -31,16 +31,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy byte[] data = new byte[size]; - try - { - _baseStorage.Read(data, offset); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _baseStorage.Read(offset, data); context.Memory.WriteBytes(buffDesc.Position, data); + + return (ResultCode)result.Value; } return ResultCode.Success; @@ -50,16 +45,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // GetSize() -> u64 size public ResultCode GetSize(ServiceCtx context) { - try - { - context.ResponseData.Write(_baseStorage.GetSize()); - } - catch (HorizonResultException ex) - { - return (ResultCode)ex.ResultValue.Value; - } + Result result = _baseStorage.GetSize(out long size); - return ResultCode.Success; + context.ResponseData.Write(size); + + return (ResultCode)result.Value; } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs b/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs new file mode 100644 index 000000000..426b50ed2 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs @@ -0,0 +1,37 @@ +using LibHac; +using LibHac.FsService; + +namespace Ryujinx.HLE.HOS.Services.Fs +{ + class IDeviceOperator : IpcService + { + private LibHac.FsService.IDeviceOperator _baseOperator; + + public IDeviceOperator(LibHac.FsService.IDeviceOperator baseOperator) + { + _baseOperator = baseOperator; + } + + [Command(200)] + // IsGameCardInserted() -> b8 is_inserted + public ResultCode IsGameCardInserted(ServiceCtx context) + { + Result result = _baseOperator.IsGameCardInserted(out bool isInserted); + + context.ResponseData.Write(isInserted); + + return (ResultCode)result.Value; + } + + [Command(202)] + // GetGameCardHandle() -> u32 gamecard_handle + public ResultCode GetGameCardHandle(ServiceCtx context) + { + Result result = _baseOperator.GetGameCardHandle(out GameCardHandle handle); + + context.ResponseData.Write(handle.Value); + + return (ResultCode)result.Value; + } + } +} diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index a0d22595a..381110199 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -1,6 +1,8 @@ using LibHac; using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsService; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy; @@ -14,7 +16,12 @@ namespace Ryujinx.HLE.HOS.Services.Fs [Service("fsp-srv")] class IFileSystemProxy : IpcService { - public IFileSystemProxy(ServiceCtx context) { } + private LibHac.FsService.IFileSystemProxy _baseFileSystemProxy; + + public IFileSystemProxy(ServiceCtx context) + { + _baseFileSystemProxy = context.Device.System.FsServer.CreateFileSystemProxyService(); + } [Command(1)] // Initialize(u64, pid) @@ -125,6 +132,23 @@ namespace Ryujinx.HLE.HOS.Services.Fs return ResultCode.Success; } + [Command(30)] + // OpenGameCardStorage(u32, u32) -> object + public ResultCode OpenGameCardStorage(ServiceCtx context) + { + GameCardHandle handle = new GameCardHandle(context.RequestData.ReadInt32()); + GameCardPartitionRaw partitionId = (GameCardPartitionRaw)context.RequestData.ReadInt32(); + + Result result = _baseFileSystemProxy.OpenGameCardStorage(out LibHac.Fs.IStorage storage, handle, partitionId); + + if (result.IsSuccess()) + { + MakeObject(context, new FileSystemProxy.IStorage(storage)); + } + + return (ResultCode)result.Value; + } + [Command(51)] // OpenSaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object saveDataFs public ResultCode OpenSaveDataFileSystem(ServiceCtx context) @@ -184,14 +208,14 @@ namespace Ryujinx.HLE.HOS.Services.Fs byte[] padding = context.RequestData.ReadBytes(7); long titleId = context.RequestData.ReadInt64(); - ContentType contentType = ContentType.Data; + NcaContentType contentType = NcaContentType.Data; StorageId installedStorage = context.Device.System.ContentManager.GetInstalledStorage(titleId, contentType, storageId); if (installedStorage == StorageId.None) { - contentType = ContentType.PublicData; + contentType = NcaContentType.PublicData; installedStorage = context.Device.System.ContentManager.GetInstalledStorage(titleId, contentType, storageId); @@ -246,6 +270,20 @@ namespace Ryujinx.HLE.HOS.Services.Fs return ResultCode.Success; } + [Command(400)] + // OpenDataStorageByCurrentProcess() -> object dataStorage + public ResultCode OpenDeviceOperator(ServiceCtx context) + { + Result result = _baseFileSystemProxy.OpenDeviceOperator(out LibHac.FsService.IDeviceOperator deviceOperator); + + if (result.IsSuccess()) + { + MakeObject(context, new IDeviceOperator(deviceOperator)); + } + + return (ResultCode)result.Value; + } + [Command(1005)] // GetGlobalAccessLogMode() -> u32 logMode public ResultCode GetGlobalAccessLogMode(ServiceCtx context) diff --git a/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs b/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs index d77bac738..88ba45e0a 100644 --- a/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs +++ b/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs @@ -1,4 +1,4 @@ -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem.NcaUtils; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem.Content; using System.Text; @@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - if (ResolvePath(context, titleId, ContentType.Program)) + if (ResolvePath(context, titleId, NcaContentType.Program)) { return ResultCode.Success; } @@ -38,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - RedirectPath(context, titleId, 0, ContentType.Program); + RedirectPath(context, titleId, 0, NcaContentType.Program); return ResultCode.Success; } @@ -49,7 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - if (ResolvePath(context, titleId, ContentType.Control)) + if (ResolvePath(context, titleId, NcaContentType.Control)) { return ResultCode.Success; } @@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - if (ResolvePath(context, titleId, ContentType.Manual)) + if (ResolvePath(context, titleId, NcaContentType.Manual)) { return ResultCode.Success; } @@ -81,7 +81,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - if (ResolvePath(context, titleId, ContentType.Data) || ResolvePath(context, titleId, ContentType.PublicData)) + if (ResolvePath(context, titleId, NcaContentType.Data) || ResolvePath(context, titleId, NcaContentType.PublicData)) { return ResultCode.Success; } @@ -97,7 +97,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - RedirectPath(context, titleId, 1, ContentType.Control); + RedirectPath(context, titleId, 1, NcaContentType.Control); return ResultCode.Success; } @@ -108,7 +108,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - RedirectPath(context, titleId, 1, ContentType.Manual); + RedirectPath(context, titleId, 1, NcaContentType.Manual); return ResultCode.Success; } @@ -119,7 +119,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - if (ResolvePath(context, titleId, ContentType.Manual)) + if (ResolvePath(context, titleId, NcaContentType.Manual)) { return ResultCode.Success; } @@ -135,7 +135,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - RedirectPath(context, titleId, 1, ContentType.Manual); + RedirectPath(context, titleId, 1, NcaContentType.Manual); return ResultCode.Success; } @@ -155,7 +155,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - RedirectPath(context, titleId, 1, ContentType.Program); + RedirectPath(context, titleId, 1, NcaContentType.Program); return ResultCode.Success; } @@ -175,7 +175,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - DeleteContentPath(context, titleId, ContentType.Program); + DeleteContentPath(context, titleId, NcaContentType.Program); return ResultCode.Success; } @@ -186,7 +186,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - DeleteContentPath(context, titleId, ContentType.Control); + DeleteContentPath(context, titleId, NcaContentType.Control); return ResultCode.Success; } @@ -197,7 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - DeleteContentPath(context, titleId, ContentType.Manual); + DeleteContentPath(context, titleId, NcaContentType.Manual); return ResultCode.Success; } @@ -208,12 +208,12 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager { long titleId = context.RequestData.ReadInt64(); - DeleteContentPath(context, titleId, ContentType.Manual); + DeleteContentPath(context, titleId, NcaContentType.Manual); return ResultCode.Success; } - private void RedirectPath(ServiceCtx context, long titleId, int flag, ContentType contentType) + private void RedirectPath(ServiceCtx context, long titleId, int flag, NcaContentType contentType) { string contentPath = ReadUtf8String(context); LocationEntry newLocation = new LocationEntry(contentPath, flag, titleId, contentType); @@ -221,10 +221,10 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager context.Device.System.ContentManager.RedirectLocation(newLocation, _storageId); } - private bool ResolvePath(ServiceCtx context, long titleId,ContentType contentType) + private bool ResolvePath(ServiceCtx context, long titleId, NcaContentType contentType) { ContentManager contentManager = context.Device.System.ContentManager; - string contentPath = contentManager.GetInstalledContentPath(titleId, _storageId, ContentType.Program); + string contentPath = contentManager.GetInstalledContentPath(titleId, _storageId, NcaContentType.Program); if (!string.IsNullOrWhiteSpace(contentPath)) { @@ -243,12 +243,12 @@ namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager return true; } - private void DeleteContentPath(ServiceCtx context, long titleId, ContentType contentType) + private void DeleteContentPath(ServiceCtx context, long titleId, NcaContentType contentType) { ContentManager contentManager = context.Device.System.ContentManager; - string contentPath = contentManager.GetInstalledContentPath(titleId, _storageId, ContentType.Manual); + string contentPath = contentManager.GetInstalledContentPath(titleId, _storageId, NcaContentType.Manual); - contentManager.ClearEntry(titleId, ContentType.Manual, _storageId); + contentManager.ClearEntry(titleId, NcaContentType.Manual, _storageId); } } } diff --git a/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs b/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs index 7af78dbf2..490d0e8ef 100644 --- a/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs +++ b/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs @@ -1,5 +1,7 @@ +using LibHac; using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.SystemState; @@ -165,7 +167,7 @@ namespace Ryujinx.HLE.HOS.Services.Settings public byte[] GetFirmwareData(Switch device) { long titleId = 0x0100000000000809; - string contentPath = device.System.ContentManager.GetInstalledContentPath(titleId, StorageId.NandSystem, ContentType.Data); + string contentPath = device.System.ContentManager.GetInstalledContentPath(titleId, StorageId.NandSystem, NcaContentType.Data); if (string.IsNullOrWhiteSpace(contentPath)) { @@ -185,11 +187,25 @@ namespace Ryujinx.HLE.HOS.Services.Settings IFileSystem firmwareRomFs = firmwareContent.OpenFileSystem(NcaSectionType.Data, device.System.FsIntegrityCheckLevel); - IFile firmwareFile = firmwareRomFs.OpenFile("/file", OpenMode.Read); + Result result = firmwareRomFs.OpenFile(out IFile firmwareFile, "/file", OpenMode.Read); + if (result.IsFailure()) + { + return null; + } - byte[] data = new byte[firmwareFile.GetSize()]; + result = firmwareFile.GetSize(out long fileSize); + if (result.IsFailure()) + { + return null; + } - firmwareFile.Read(data, 0); + byte[] data = new byte[fileSize]; + + result = firmwareFile.Read(out _, 0, data); + if (result.IsFailure()) + { + return null; + } return data; } diff --git a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs index e9ec654ba..f48452f31 100644 --- a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs +++ b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs @@ -1,5 +1,7 @@ -using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac; +using LibHac.Fs; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; using Ryujinx.Common.Logging; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.FileSystem; @@ -58,9 +60,10 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { Nca nca = new Nca(_device.System.KeySet, ncaFileStream); IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel); - Stream binaryListStream = romfs.OpenFile("binaryList.txt", OpenMode.Read).AsStream(); - StreamReader reader = new StreamReader(binaryListStream); + romfs.OpenFile(out IFile binaryListFile, "/binaryList.txt", OpenMode.Read).ThrowIfFailure(); + + StreamReader reader = new StreamReader(binaryListFile.AsStream()); List locationNameList = new List(); @@ -139,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone public string GetTimeZoneBinaryTitleContentPath() { - return _device.System.ContentManager.GetInstalledContentPath(TimeZoneBinaryTitleId, StorageId.NandSystem, ContentType.Data); + return _device.System.ContentManager.GetInstalledContentPath(TimeZoneBinaryTitleId, StorageId.NandSystem, NcaContentType.Data); } public bool HasTimeZoneBinaryTitle() @@ -162,9 +165,11 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone Nca nca = new Nca(_device.System.KeySet, ncaFile); IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel); - timeZoneBinaryStream = romfs.OpenFile($"/zoneinfo/{locationName}", OpenMode.Read).AsStream(); + Result result = romfs.OpenFile(out IFile timeZoneBinaryFile, $"/zoneinfo/{locationName}", OpenMode.Read); - return ResultCode.Success; + timeZoneBinaryStream = timeZoneBinaryFile.AsStream(); + + return (ResultCode)result.Value; } internal ResultCode LoadTimeZoneRule(out TimeZoneRule outRules, string locationName) diff --git a/Ryujinx.HLE/Ryujinx.HLE.csproj b/Ryujinx.HLE/Ryujinx.HLE.csproj index 38a6f5aed..0f36843e5 100644 --- a/Ryujinx.HLE/Ryujinx.HLE.csproj +++ b/Ryujinx.HLE/Ryujinx.HLE.csproj @@ -48,7 +48,7 @@ - + diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs index 53560521b..57980c500 100644 --- a/Ryujinx/Configuration.cs +++ b/Ryujinx/Configuration.cs @@ -1,5 +1,5 @@ using JsonPrettyPrinterPlus; -using LibHac.Fs; +using LibHac.FsSystem; using OpenTK.Input; using Ryujinx.Common; using Ryujinx.Common.Logging; diff --git a/Ryujinx/Ui/ApplicationLibrary.cs b/Ryujinx/Ui/ApplicationLibrary.cs index 7e731f794..1b697e426 100644 --- a/Ryujinx/Ui/ApplicationLibrary.cs +++ b/Ryujinx/Ui/ApplicationLibrary.cs @@ -1,6 +1,8 @@ using LibHac; using LibHac.Fs; -using LibHac.Fs.NcaUtils; +using LibHac.FsSystem; +using LibHac.FsSystem.NcaUtils; +using LibHac.Spl; using Ryujinx.Common.Logging; using System; using System.Collections.Generic; @@ -8,6 +10,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; + using SystemState = Ryujinx.HLE.HOS.SystemState; namespace Ryujinx.UI @@ -115,8 +118,9 @@ namespace Ryujinx.UI } // Creates NACP class from the NACP file - IFile controlNacp = controlFs.OpenFile("/control.nacp", OpenMode.Read); - Nacp controlData = new Nacp(controlNacp.AsStream()); + controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); + + Nacp controlData = new Nacp(controlNacpFile.AsStream()); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; @@ -150,7 +154,8 @@ namespace Ryujinx.UI // Read the icon from the ControlFS and store it as a byte array try { - IFile icon = controlFs.OpenFile($"/icon_{DesiredTitleLanguage}.dat", OpenMode.Read); + controlFs.OpenFile(out IFile icon, $"/icon_{DesiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure(); + using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); @@ -159,15 +164,15 @@ namespace Ryujinx.UI } catch (HorizonResultException) { - IDirectory controlDir = controlFs.OpenDirectory("./", OpenDirectoryMode.All); - foreach (DirectoryEntry entry in controlDir.Read()) + foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) { if (entry.Name == "control.nacp") { continue; } - IFile icon = controlFs.OpenFile(entry.FullPath, OpenMode.Read); + controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); + using (MemoryStream stream = new MemoryStream()) { icon.AsStream().CopyTo(stream); @@ -346,21 +351,26 @@ namespace Ryujinx.UI Nca controlNca = null; // Add keys to keyset if needed - foreach (DirectoryEntry ticketEntry in Pfs.EnumerateEntries("*.tik")) + foreach (DirectoryEntryEx ticketEntry in Pfs.EnumerateEntries("/", "*.tik")) { - Ticket ticket = new Ticket(Pfs.OpenFile(ticketEntry.FullPath, OpenMode.Read).AsStream()); + Result result = Pfs.OpenFile(out IFile ticketFile, ticketEntry.FullPath, OpenMode.Read); - if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId)) + if (result.IsSuccess()) { - KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet)); + Ticket ticket = new Ticket(ticketFile.AsStream()); + + KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet))); } } // Find the Control NCA and store it in variable called controlNca - foreach (DirectoryEntry fileEntry in Pfs.EnumerateEntries("*.nca")) + foreach (DirectoryEntryEx fileEntry in Pfs.EnumerateEntries("/", "*.nca")) { - Nca nca = new Nca(KeySet, Pfs.OpenFile(fileEntry.FullPath, OpenMode.Read).AsStorage()); - if (nca.Header.ContentType == ContentType.Control) + Pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); + + Nca nca = new Nca(KeySet, ncaFile.AsStorage()); + + if (nca.Header.ContentType == NcaContentType.Control) { controlNca = nca; }