add support for open fs of internal files
This commit is contained in:
parent
a6c21db0e3
commit
9c287b211b
7 changed files with 154 additions and 33 deletions
|
@ -252,5 +252,17 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
|
|
||||||
throw new InvalidOperationException($"Path {Path} is not a child directory of {RootPath}");
|
throw new InvalidOperationException($"Path {Path} is not a child directory of {RootPath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Disposed { get; private set; }
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
Disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.HLE.HOS.Services.FspSrv;
|
using Ryujinx.HLE.HOS.Services.FspSrv;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.FileSystem
|
namespace Ryujinx.HLE.FileSystem
|
||||||
{
|
{
|
||||||
interface IFileSystemProvider
|
interface IFileSystemProvider : IDisposable
|
||||||
{
|
{
|
||||||
|
bool Disposed { get; }
|
||||||
|
|
||||||
long CreateFile(string Name, long Size);
|
long CreateFile(string Name, long Size);
|
||||||
|
|
||||||
long CreateDirectory(string Name);
|
long CreateDirectory(string Name);
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
{
|
{
|
||||||
private Pfs Pfs;
|
private Pfs Pfs;
|
||||||
|
|
||||||
|
public bool Disposed { get; private set; }
|
||||||
|
|
||||||
public PFsProvider(Pfs Pfs)
|
public PFsProvider(Pfs Pfs)
|
||||||
{
|
{
|
||||||
this.Pfs = Pfs;
|
this.Pfs = Pfs;
|
||||||
|
@ -143,5 +145,15 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
{
|
{
|
||||||
private Romfs RomFs;
|
private Romfs RomFs;
|
||||||
|
|
||||||
|
public bool Disposed { get; private set; }
|
||||||
|
|
||||||
public RomFsProvider(Stream StorageStream)
|
public RomFsProvider(Stream StorageStream)
|
||||||
{
|
{
|
||||||
RomFs = new Romfs(StorageStream);
|
RomFs = new Romfs(StorageStream);
|
||||||
|
@ -159,5 +161,15 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
Disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
public const int PathDoesNotExist = 1;
|
public const int PathDoesNotExist = 1;
|
||||||
public const int PathAlreadyExists = 2;
|
public const int PathAlreadyExists = 2;
|
||||||
public const int PathAlreadyInUse = 7;
|
public const int PathAlreadyInUse = 7;
|
||||||
|
public const int PartitionNotFound = 1001;
|
||||||
public const int InvalidInput = 6001;
|
public const int InvalidInput = 6001;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@ using static Ryujinx.HLE.Utilities.StringUtils;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.FspSrv
|
namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
{
|
{
|
||||||
class IFileSystem : IpcService
|
class IFileSystem : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
|
@ -386,5 +386,15 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
OpenPaths.Remove(DirInterface.DirectoryPath);
|
OpenPaths.Remove(DirInterface.DirectoryPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
Provider.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -85,6 +85,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
|
|
||||||
if (!File.Exists(FullPath))
|
if (!File.Exists(FullPath))
|
||||||
{
|
{
|
||||||
|
if (FullPath.Contains("."))
|
||||||
|
{
|
||||||
|
return OpenFileSystemFromInternalFile(Context, FullPath);
|
||||||
|
}
|
||||||
|
|
||||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,40 +99,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
|
|
||||||
if (Extension == ".nca")
|
if (Extension == ".nca")
|
||||||
{
|
{
|
||||||
Nca Nca = new Nca(Context.Device.System.KeySet, FileStream, false);
|
return OpenNcaFs(Context, FullPath, FileStream);
|
||||||
|
|
||||||
NcaSection RomfsSection = Nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs);
|
|
||||||
|
|
||||||
if (RomfsSection != null)
|
|
||||||
{
|
|
||||||
Stream RomfsStream = Nca.OpenSection(RomfsSection.SectionNum, false, Context.Device.System.FsIntegrityCheckLevel);
|
|
||||||
|
|
||||||
IFileSystem NcaFileSystem = new IFileSystem(SwitchPath, new RomFsProvider(RomfsStream));
|
|
||||||
|
|
||||||
MakeObject(Context, NcaFileSystem);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Extension == ".nsp")
|
else if (Extension == ".nsp")
|
||||||
{
|
{
|
||||||
Pfs Nsp = new Pfs(FileStream);
|
return OpenNsp(Context, FullPath);
|
||||||
|
|
||||||
PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));
|
|
||||||
|
|
||||||
if (TicketFile != null)
|
|
||||||
{
|
|
||||||
Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));
|
|
||||||
|
|
||||||
Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
|
|
||||||
Ticket.GetTitleKey(Context.Device.System.KeySet);
|
|
||||||
}
|
|
||||||
|
|
||||||
IFileSystem NspFileSystem = new IFileSystem(SwitchPath, new PFsProvider(Nsp));
|
|
||||||
|
|
||||||
MakeObject(Context, NspFileSystem);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeError(ErrorModule.Fs, FsErr.InvalidInput);
|
return MakeError(ErrorModule.Fs, FsErr.InvalidInput);
|
||||||
|
@ -264,5 +240,100 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
|
|
||||||
MakeObject(Context, new IFileSystem(SavePath, FileSystemProvider));
|
MakeObject(Context, new IFileSystem(SavePath, FileSystemProvider));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long OpenNsp(ServiceCtx Context, string PfsPath)
|
||||||
|
{
|
||||||
|
FileStream PfsFile = new FileStream(PfsPath, FileMode.Open, FileAccess.Read);
|
||||||
|
|
||||||
|
Pfs Nsp = new Pfs(PfsFile);
|
||||||
|
|
||||||
|
PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));
|
||||||
|
|
||||||
|
if (TicketFile != null)
|
||||||
|
{
|
||||||
|
Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));
|
||||||
|
|
||||||
|
Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
|
||||||
|
Ticket.GetTitleKey(Context.Device.System.KeySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
IFileSystem NspFileSystem = new IFileSystem(PfsPath, new PFsProvider(Nsp));
|
||||||
|
|
||||||
|
MakeObject(Context, NspFileSystem);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long OpenNcaFs(ServiceCtx Context,string NcaPath, Stream NcaStream)
|
||||||
|
{
|
||||||
|
Nca Nca = new Nca(Context.Device.System.KeySet, NcaStream, false);
|
||||||
|
|
||||||
|
NcaSection RomfsSection = Nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs);
|
||||||
|
NcaSection PfsSection = Nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Pfs0);
|
||||||
|
|
||||||
|
if (RomfsSection != null)
|
||||||
|
{
|
||||||
|
Stream RomfsStream = Nca.OpenSection(RomfsSection.SectionNum, false, Context.Device.System.FsIntegrityCheckLevel);
|
||||||
|
|
||||||
|
IFileSystem NcaFileSystem = new IFileSystem(NcaPath, new RomFsProvider(RomfsStream));
|
||||||
|
|
||||||
|
MakeObject(Context, NcaFileSystem);
|
||||||
|
}
|
||||||
|
else if(PfsSection !=null)
|
||||||
|
{
|
||||||
|
Stream PfsStream = Nca.OpenSection(PfsSection.SectionNum, false, Context.Device.System.FsIntegrityCheckLevel);
|
||||||
|
|
||||||
|
Pfs Pfs = new Pfs(PfsStream);
|
||||||
|
|
||||||
|
IFileSystem NcaFileSystem = new IFileSystem(NcaPath, new PFsProvider(Pfs));
|
||||||
|
|
||||||
|
MakeObject(Context, NcaFileSystem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MakeError(ErrorModule.Fs, FsErr.PartitionNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long OpenFileSystemFromInternalFile(ServiceCtx Context, string FullPath)
|
||||||
|
{
|
||||||
|
DirectoryInfo ArchivePath = new DirectoryInfo(FullPath).Parent;
|
||||||
|
|
||||||
|
while (string.IsNullOrWhiteSpace(ArchivePath.Extension))
|
||||||
|
{
|
||||||
|
ArchivePath = ArchivePath.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArchivePath.Extension == ".nsp" && File.Exists(ArchivePath.FullName))
|
||||||
|
{
|
||||||
|
FileStream PfsFile = new FileStream(
|
||||||
|
ArchivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
|
||||||
|
FileMode.Open,
|
||||||
|
FileAccess.Read);
|
||||||
|
|
||||||
|
Pfs Nsp = new Pfs(PfsFile);
|
||||||
|
|
||||||
|
PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));
|
||||||
|
|
||||||
|
if (TicketFile != null)
|
||||||
|
{
|
||||||
|
Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));
|
||||||
|
|
||||||
|
Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
|
||||||
|
Ticket.GetTitleKey(Context.Device.System.KeySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
string Filename = FullPath.Replace(ArchivePath.FullName, string.Empty);
|
||||||
|
|
||||||
|
if (Nsp.FileExists(Filename))
|
||||||
|
{
|
||||||
|
return OpenNcaFs(Context, FullPath, Nsp.OpenFile(Filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue