Update to LibHac 0.5.0 (#725)

* Update to libhac 0.5

* Catch HorizonResultException in IFileSystemProxy

* Changes based on feedback
This commit is contained in:
Alex Barney 2019-07-10 12:20:01 -05:00 committed by Ac_K
parent 596b61ce1f
commit f723f6f39a
8 changed files with 238 additions and 357 deletions

View file

@ -321,8 +321,7 @@ namespace Ryujinx.HLE.HOS.Services.Acc
// Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current PID and store the result (NACP File) internally. // Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current PID and store the result (NACP File) internally.
// But since we use LibHac and we load one Application at a time, it's not necessary. // But since we use LibHac and we load one Application at a time, it's not necessary.
// TODO : Use "context.Device.System.ControlData.UserAccountSwitchLock" when LibHac is updated. context.ResponseData.Write(context.Device.System.ControlData.UserAccountSwitchLock);
context.ResponseData.Write(false);
Logger.PrintStub(LogClass.ServiceAcc); Logger.PrintStub(LogClass.ServiceAcc);

View file

@ -1,11 +1,11 @@
using LibHac;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace Ryujinx.HLE.HOS.Services.FspSrv namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
class IDirectory : IpcService, IDisposable class IDirectory : IpcService
{ {
private const int DirectoryEntrySize = 0x310; private const int DirectoryEntrySize = 0x310;
@ -15,11 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
private IEnumerator<LibHac.Fs.DirectoryEntry> _enumerator; private IEnumerator<LibHac.Fs.DirectoryEntry> _enumerator;
public event EventHandler<EventArgs> Disposed; private LibHac.Fs.IDirectory _baseDirectory;
public string Path { get; }
private LibHac.Fs.IDirectory _provider;
public IDirectory(LibHac.Fs.IDirectory directory) public IDirectory(LibHac.Fs.IDirectory directory)
{ {
@ -29,9 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ 1, GetEntryCount } { 1, GetEntryCount }
}; };
_provider = directory; _baseDirectory = directory;
Path = directory.FullPath;
_enumerator = directory.Read().GetEnumerator(); _enumerator = directory.Read().GetEnumerator();
} }
@ -45,6 +39,8 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
int maxReadCount = (int)(bufferLen / DirectoryEntrySize); int maxReadCount = (int)(bufferLen / DirectoryEntrySize);
int readCount = 0; int readCount = 0;
try
{
while (readCount < maxReadCount && _enumerator.MoveNext()) while (readCount < maxReadCount && _enumerator.MoveNext())
{ {
long position = bufferPosition + readCount * DirectoryEntrySize; long position = bufferPosition + readCount * DirectoryEntrySize;
@ -53,6 +49,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
readCount++; readCount++;
} }
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
context.ResponseData.Write((long)readCount); context.ResponseData.Write((long)readCount);
@ -78,22 +79,16 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
// GetEntryCount() -> u64 // GetEntryCount() -> u64
public long GetEntryCount(ServiceCtx context) public long GetEntryCount(ServiceCtx context)
{ {
context.ResponseData.Write((long)_provider.GetEntryCount()); try
{
context.ResponseData.Write((long)_baseDirectory.GetEntryCount());
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Disposed?.Invoke(this, EventArgs.Empty);
}
}
} }
} }

View file

@ -1,3 +1,4 @@
using LibHac;
using LibHac.Fs; using LibHac.Fs;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using System; using System;
@ -13,11 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
private LibHac.Fs.IFile _baseFile; private LibHac.Fs.IFile _baseFile;
public event EventHandler<EventArgs> Disposed; public IFile(LibHac.Fs.IFile baseFile)
public string Path { get; private set; }
public IFile(LibHac.Fs.IFile baseFile, string path)
{ {
_commands = new Dictionary<int, ServiceProcessRequest> _commands = new Dictionary<int, ServiceProcessRequest>
{ {
@ -29,7 +26,6 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
}; };
_baseFile = baseFile; _baseFile = baseFile;
Path = PathTools.Normalize(path);
} }
// Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf) // Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf)
@ -44,8 +40,16 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
long size = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64();
byte[] data = new byte[size]; byte[] data = new byte[size];
int readSize;
int readSize = _baseFile.Read(data, offset, readOption); try
{
readSize = _baseFile.Read(data, offset, readOption);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
context.Memory.WriteBytes(position, data); context.Memory.WriteBytes(position, data);
@ -67,33 +71,61 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
byte[] data = context.Memory.ReadBytes(position, size); byte[] data = context.Memory.ReadBytes(position, size);
try
{
_baseFile.Write(data, offset, writeOption); _baseFile.Write(data, offset, writeOption);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
// Flush() // Flush()
public long Flush(ServiceCtx context) public long Flush(ServiceCtx context)
{
try
{ {
_baseFile.Flush(); _baseFile.Flush();
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
// SetSize(u64 size) // SetSize(u64 size)
public long SetSize(ServiceCtx context) public long SetSize(ServiceCtx context)
{
try
{ {
long size = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64();
_baseFile.SetSize(size); _baseFile.SetSize(size);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
// GetSize() -> u64 fileSize // GetSize() -> u64 fileSize
public long GetSize(ServiceCtx context) public long GetSize(ServiceCtx context)
{
try
{ {
context.ResponseData.Write(_baseFile.GetSize()); context.ResponseData.Write(_baseFile.GetSize());
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -105,11 +137,9 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (disposing && _baseFile != null) if (disposing)
{ {
_baseFile.Dispose(); _baseFile?.Dispose();
Disposed?.Invoke(this, EventArgs.Empty);
} }
} }
} }

View file

@ -1,9 +1,8 @@
using LibHac;
using LibHac.Fs; using LibHac.Fs;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Ryujinx.Common.Logging;
using static Ryujinx.HLE.HOS.ErrorCode; using static Ryujinx.HLE.HOS.ErrorCode;
using static Ryujinx.HLE.Utilities.StringUtils; using static Ryujinx.HLE.Utilities.StringUtils;
@ -15,9 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands; public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
private HashSet<string> _openPaths; private LibHac.Fs.IFileSystem _fileSystem;
private LibHac.Fs.IFileSystem _provider;
public IFileSystem(LibHac.Fs.IFileSystem provider) public IFileSystem(LibHac.Fs.IFileSystem provider)
{ {
@ -40,9 +37,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ 14, GetFileTimeStampRaw } { 14, GetFileTimeStampRaw }
}; };
_openPaths = new HashSet<string>(); _fileSystem = provider;
_provider = provider;
} }
// CreateFile(u32 createOption, u64 size, buffer<bytes<0x301>, 0x19, 0x301> path) // CreateFile(u32 createOption, u64 size, buffer<bytes<0x301>, 0x19, 0x301> path)
@ -55,34 +50,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
long size = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64();
if (name == null)
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (_provider.FileExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.CreateFile(name, size, createOption); _fileSystem.CreateFile(name, size, createOption);
} }
catch (DirectoryNotFoundException) catch (HorizonResultException ex)
{ {
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return ex.ResultValue.Value;
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
throw;
} }
return 0; return 0;
@ -93,29 +67,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (!_provider.FileExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.DeleteFile(name); _fileSystem.DeleteFile(name);
} }
catch (FileNotFoundException) catch (HorizonResultException ex)
{ {
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return ex.ResultValue.Value;
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
throw;
} }
return 0; return 0;
@ -126,34 +84,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (name == null)
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (_provider.DirectoryExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.CreateDirectory(name); _fileSystem.CreateDirectory(name);
} }
catch (DirectoryNotFoundException) catch (HorizonResultException ex)
{ {
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return ex.ResultValue.Value;
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
throw;
} }
return 0; return 0;
@ -164,29 +101,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (!_provider.DirectoryExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.DeleteDirectory(name); _fileSystem.DeleteDirectory(name);
} }
catch (DirectoryNotFoundException) catch (HorizonResultException ex)
{ {
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return ex.ResultValue.Value;
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
throw;
} }
return 0; return 0;
@ -197,25 +118,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (!_provider.DirectoryExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.DeleteDirectoryRecursively(name); _fileSystem.DeleteDirectoryRecursively(name);
} }
catch (UnauthorizedAccessException) catch (HorizonResultException ex)
{ {
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}"); return ex.ResultValue.Value;
throw;
} }
return 0; return 0;
@ -227,34 +136,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
string oldName = ReadUtf8String(context, 0); string oldName = ReadUtf8String(context, 0);
string newName = ReadUtf8String(context, 1); string newName = ReadUtf8String(context, 1);
if (_provider.FileExists(oldName))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (_provider.FileExists(newName))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
}
if (IsPathAlreadyInUse(oldName))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.RenameFile(oldName, newName); _fileSystem.RenameFile(oldName, newName);
} }
catch (FileNotFoundException) catch (HorizonResultException ex)
{ {
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return ex.ResultValue.Value;
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {oldName} or {newName}");
throw;
} }
return 0; return 0;
@ -266,34 +154,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
string oldName = ReadUtf8String(context, 0); string oldName = ReadUtf8String(context, 0);
string newName = ReadUtf8String(context, 1); string newName = ReadUtf8String(context, 1);
if (!_provider.DirectoryExists(oldName))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (!_provider.DirectoryExists(newName))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
}
if (IsPathAlreadyInUse(oldName))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.RenameFile(oldName, newName); _fileSystem.RenameDirectory(oldName, newName);
} }
catch (DirectoryNotFoundException) catch (HorizonResultException ex)
{ {
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return ex.ResultValue.Value;
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {oldName} or {newName}");
throw;
} }
return 0; return 0;
@ -306,16 +173,21 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
try try
{ {
DirectoryEntryType entryType = _provider.GetEntryType(name); DirectoryEntryType entryType = _fileSystem.GetEntryType(name);
if (entryType == DirectoryEntryType.Directory || entryType == DirectoryEntryType.File)
{
context.ResponseData.Write((int)entryType); context.ResponseData.Write((int)entryType);
} }
catch (FileNotFoundException) else
{ {
context.ResponseData.Write(0);
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
} }
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -327,39 +199,18 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (!_provider.FileExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
IFile fileInterface;
try try
{ {
LibHac.Fs.IFile file = _provider.OpenFile(name, mode); LibHac.Fs.IFile file = _fileSystem.OpenFile(name, mode);
fileInterface = new IFile(file, name); IFile fileInterface = new IFile(file);
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
throw;
}
fileInterface.Disposed += RemoveFileInUse;
lock (_openPaths)
{
_openPaths.Add(fileInterface.Path);
}
MakeObject(context, fileInterface); MakeObject(context, fileInterface);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -371,39 +222,18 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (!_provider.DirectoryExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
IDirectory dirInterface;
try try
{ {
LibHac.Fs.IDirectory dir = _provider.OpenDirectory(name, mode); LibHac.Fs.IDirectory dir = _fileSystem.OpenDirectory(name, mode);
dirInterface = new IDirectory(dir); IDirectory dirInterface = new IDirectory(dir);
}
catch (UnauthorizedAccessException)
{
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
throw;
}
dirInterface.Disposed += RemoveDirectoryInUse;
lock (_openPaths)
{
_openPaths.Add(dirInterface.Path);
}
MakeObject(context, dirInterface); MakeObject(context, dirInterface);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -411,7 +241,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
// Commit() // Commit()
public long Commit(ServiceCtx context) public long Commit(ServiceCtx context)
{ {
_provider.Commit(); try
{
_fileSystem.Commit();
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -421,7 +258,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
context.ResponseData.Write(_provider.GetFreeSpaceSize(name)); try
{
context.ResponseData.Write(_fileSystem.GetFreeSpaceSize(name));
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -431,7 +275,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
context.ResponseData.Write(_provider.GetTotalSpaceSize(name)); try
{
context.ResponseData.Write(_fileSystem.GetTotalSpaceSize(name));
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -441,25 +292,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (!_provider.DirectoryExists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
if (IsPathAlreadyInUse(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
}
try try
{ {
_provider.CleanDirectoryRecursively(name); _fileSystem.CleanDirectoryRecursively(name);
} }
catch (UnauthorizedAccessException) catch (HorizonResultException ex)
{ {
Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}"); return ex.ResultValue.Value;
throw;
} }
return 0; return 0;
@ -470,9 +309,9 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ {
string name = ReadUtf8String(context); string name = ReadUtf8String(context);
if (_provider.FileExists(name) || _provider.DirectoryExists(name)) try
{ {
FileTimeStampRaw timestamp = _provider.GetFileTimeStampRaw(name); FileTimeStampRaw timestamp = _fileSystem.GetFileTimeStampRaw(name);
context.ResponseData.Write(timestamp.Created); context.ResponseData.Write(timestamp.Created);
context.ResponseData.Write(timestamp.Modified); context.ResponseData.Write(timestamp.Modified);
@ -484,43 +323,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
data[0] = 1; data[0] = 1;
context.ResponseData.Write(data); context.ResponseData.Write(data);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
private bool IsPathAlreadyInUse(string path)
{
lock (_openPaths)
{
return _openPaths.Contains(path);
}
}
private void RemoveFileInUse(object sender, EventArgs e)
{
IFile fileInterface = (IFile)sender;
lock (_openPaths)
{
fileInterface.Disposed -= RemoveFileInUse;
_openPaths.Remove(fileInterface.Path);
}
}
private void RemoveDirectoryInUse(object sender, EventArgs e)
{
IDirectory dirInterface = (IDirectory)sender;
lock (_openPaths)
{
dirInterface.Disposed -= RemoveDirectoryInUse;
_openPaths.Remove(dirInterface.Path);
}
}
} }
} }

View file

@ -127,17 +127,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
// OpenSaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> saveDataFs // OpenSaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> saveDataFs
public long OpenSaveDataFileSystem(ServiceCtx context) public long OpenSaveDataFileSystem(ServiceCtx context)
{ {
LoadSaveDataFileSystem(context); return LoadSaveDataFileSystem(context);
return 0;
} }
// OpenSaveDataFileSystemBySystemSaveDataId(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> systemSaveDataFs // OpenSaveDataFileSystemBySystemSaveDataId(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> systemSaveDataFs
public long OpenSaveDataFileSystemBySystemSaveDataId(ServiceCtx context) public long OpenSaveDataFileSystemBySystemSaveDataId(ServiceCtx context)
{ {
LoadSaveDataFileSystem(context); return LoadSaveDataFileSystem(context);
return 0;
} }
// OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage // OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage
@ -178,12 +174,19 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
string ncaPath = installPath; string ncaPath = installPath;
if (File.Exists(ncaPath)) if (File.Exists(ncaPath))
{
try
{ {
LibHac.Fs.IStorage ncaStorage = new LocalStorage(ncaPath, FileAccess.Read, FileMode.Open); LibHac.Fs.IStorage ncaStorage = new LocalStorage(ncaPath, FileAccess.Read, FileMode.Open);
Nca nca = new Nca(context.Device.System.KeySet, ncaStorage); Nca nca = new Nca(context.Device.System.KeySet, ncaStorage);
LibHac.Fs.IStorage romfsStorage = nca.OpenStorage(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel); LibHac.Fs.IStorage romfsStorage = nca.OpenStorage(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
MakeObject(context, new IStorage(romfsStorage)); MakeObject(context, new IStorage(romfsStorage));
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -230,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
return 0; return 0;
} }
public void LoadSaveDataFileSystem(ServiceCtx context) public long LoadSaveDataFileSystem(ServiceCtx context)
{ {
SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64(); SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64();
@ -242,14 +245,25 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
SaveDataType saveDataType = (SaveDataType)context.RequestData.ReadByte(); SaveDataType saveDataType = (SaveDataType)context.RequestData.ReadByte();
SaveInfo saveInfo = new SaveInfo(titleId, saveId, saveDataType, userId, saveSpaceId); SaveInfo saveInfo = new SaveInfo(titleId, saveId, saveDataType, userId, saveSpaceId);
string savePath = context.Device.FileSystem.GetGameSavePath(saveInfo, context); string savePath = context.Device.FileSystem.GetGameSavePath(saveInfo, context);
LocalFileSystem fileSystem = new LocalFileSystem(savePath);
try
{
LocalFileSystem fileSystem = new LocalFileSystem(savePath);
DirectorySaveDataFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem); DirectorySaveDataFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem);
MakeObject(context, new IFileSystem(saveFileSystem)); MakeObject(context, new IFileSystem(saveFileSystem));
} }
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0;
}
private long OpenNsp(ServiceCtx context, string pfsPath) private long OpenNsp(ServiceCtx context, string pfsPath)
{
try
{ {
LocalStorage storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open); LocalStorage storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open);
PartitionFileSystem nsp = new PartitionFileSystem(storage); PartitionFileSystem nsp = new PartitionFileSystem(storage);
@ -259,11 +273,18 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
IFileSystem nspFileSystem = new IFileSystem(nsp); IFileSystem nspFileSystem = new IFileSystem(nsp);
MakeObject(context, nspFileSystem); MakeObject(context, nspFileSystem);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
private long OpenNcaFs(ServiceCtx context, string ncaPath, LibHac.Fs.IStorage ncaStorage) private long OpenNcaFs(ServiceCtx context, string ncaPath, LibHac.Fs.IStorage ncaStorage)
{
try
{ {
Nca nca = new Nca(context.Device.System.KeySet, ncaStorage); Nca nca = new Nca(context.Device.System.KeySet, ncaStorage);
@ -275,6 +296,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
LibHac.Fs.IFileSystem fileSystem = nca.OpenFileSystem(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel); LibHac.Fs.IFileSystem fileSystem = nca.OpenFileSystem(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
MakeObject(context, new IFileSystem(fileSystem)); MakeObject(context, new IFileSystem(fileSystem));
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }
@ -295,6 +321,8 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
FileMode.Open, FileMode.Open,
FileAccess.Read); FileAccess.Read);
try
{
PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage()); PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage());
ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet); ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
@ -306,6 +334,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
return OpenNcaFs(context, fullPath, nsp.OpenFile(filename, OpenMode.Read).AsStorage()); return OpenNcaFs(context, fullPath, nsp.OpenFile(filename, OpenMode.Read).AsStorage());
} }
} }
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
}
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
} }

View file

@ -1,3 +1,4 @@
using LibHac;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using System.Collections.Generic; using System.Collections.Generic;
@ -40,7 +41,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
byte[] data = new byte[size]; byte[] data = new byte[size];
try
{
_baseStorage.Read(data, offset); _baseStorage.Read(data, offset);
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
context.Memory.WriteBytes(buffDesc.Position, data); context.Memory.WriteBytes(buffDesc.Position, data);
} }
@ -50,8 +58,15 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
// GetSize() -> u64 size // GetSize() -> u64 size
public long GetSize(ServiceCtx context) public long GetSize(ServiceCtx context)
{
try
{ {
context.ResponseData.Write(_baseStorage.GetSize()); context.ResponseData.Write(_baseStorage.GetSize());
}
catch (HorizonResultException ex)
{
return ex.ResultValue.Value;
}
return 0; return 0;
} }

View file

@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns
position += isbn.Length; position += isbn.Length;
context.Memory.WriteByte(position++, nacp.StartupUserAccount); context.Memory.WriteByte(position++, nacp.StartupUserAccount);
context.Memory.WriteByte(position++, nacp.TouchScreenUsageMode); context.Memory.WriteByte(position++, nacp.UserAccountSwitchLock);
context.Memory.WriteByte(position++, nacp.AocRegistrationType); context.Memory.WriteByte(position++, nacp.AocRegistrationType);
context.Memory.WriteInt32(position, nacp.AttributeFlag); context.Memory.WriteInt32(position, nacp.AttributeFlag);

View file

@ -47,7 +47,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Concentus" Version="1.1.7" /> <PackageReference Include="Concentus" Version="1.1.7" />
<PackageReference Include="LibHac" Version="0.4.1" /> <PackageReference Include="LibHac" Version="0.5.0" />
<PackageReference Include="TimeZoneConverter.Posix" Version="2.1.0" /> <PackageReference Include="TimeZoneConverter.Posix" Version="2.1.0" />
</ItemGroup> </ItemGroup>