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}");
|
||||
}
|
||||
|
||||
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.Services.FspSrv;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
interface IFileSystemProvider
|
||||
interface IFileSystemProvider : IDisposable
|
||||
{
|
||||
bool Disposed { get; }
|
||||
|
||||
long CreateFile(string Name, long Size);
|
||||
|
||||
long CreateDirectory(string Name);
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
private Pfs Pfs;
|
||||
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
public PFsProvider(Pfs Pfs)
|
||||
{
|
||||
this.Pfs = Pfs;
|
||||
|
@ -143,5 +145,15 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
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;
|
||||
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
public RomFsProvider(Stream StorageStream)
|
||||
{
|
||||
RomFs = new Romfs(StorageStream);
|
||||
|
@ -159,5 +161,15 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
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 PathAlreadyExists = 2;
|
||||
public const int PathAlreadyInUse = 7;
|
||||
public const int PartitionNotFound = 1001;
|
||||
public const int InvalidInput = 6001;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ using static Ryujinx.HLE.Utilities.StringUtils;
|
|||
|
||||
namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||
{
|
||||
class IFileSystem : IpcService
|
||||
class IFileSystem : IpcService, IDisposable
|
||||
{
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
|
||||
|
@ -386,5 +386,15 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
|||
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 (FullPath.Contains("."))
|
||||
{
|
||||
return OpenFileSystemFromInternalFile(Context, FullPath);
|
||||
}
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
|
@ -94,40 +99,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
|||
|
||||
if (Extension == ".nca")
|
||||
{
|
||||
Nca Nca = new Nca(Context.Device.System.KeySet, FileStream, false);
|
||||
|
||||
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;
|
||||
}
|
||||
return OpenNcaFs(Context, FullPath, FileStream);
|
||||
}
|
||||
else if (Extension == ".nsp")
|
||||
{
|
||||
Pfs Nsp = new Pfs(FileStream);
|
||||
|
||||
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 OpenNsp(Context, FullPath);
|
||||
}
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.InvalidInput);
|
||||
|
@ -264,5 +240,100 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
|||
|
||||
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
Reference in a new issue