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:
parent
596b61ce1f
commit
f723f6f39a
8 changed files with 238 additions and 357 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue