diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index ac60c59ca1..05e2b7a167 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -164,6 +164,45 @@ namespace Ryujinx.HLE.HOS LoadNca(Nca); } + public void LoadNsp(string NspFile) + { + FileStream File = new FileStream(NspFile, FileMode.Open, FileAccess.Read); + Pfs Nsp = new Pfs(File); + + Nca ProgramNca = null; + + PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik")); + + // Load title key from the NSP's ticket in case the user doesn't have a title key file + if (TicketFile != null) + { + // todo Change when Ticket(Stream) overload is added + BinaryReader TicketReader = new BinaryReader(Nsp.OpenFile(TicketFile)); + Ticket Ticket = new Ticket(TicketReader); + + byte[] TitleKey = Ticket.GetTitleKey(Keyset); + Keyset.TitleKeys[Ticket.RightsId] = TitleKey; + } + + foreach (PfsFileEntry NcaFile in Nsp.Files.Where(x => x.Name.EndsWith(".nca"))) + { + Nca Nca = new Nca(Keyset, Nsp.OpenFile(NcaFile), true); + + if (Nca.Header.ContentType == ContentType.Program) + { + ProgramNca = Nca; + break; + } + } + + if (ProgramNca == null) + { + Device.Log.PrintError(LogClass.Loader, "Could not find program NCA inside NSP file"); + } + + LoadNca(ProgramNca); + } + public void LoadNca(Nca Nca) { NcaSection RomfsSection = Nca.Sections.FirstOrDefault(x => x.Type == SectionType.Romfs); diff --git a/Ryujinx.HLE/Switch.cs b/Ryujinx.HLE/Switch.cs index 2061321db3..ee07ea2296 100644 --- a/Ryujinx.HLE/Switch.cs +++ b/Ryujinx.HLE/Switch.cs @@ -71,6 +71,11 @@ namespace Ryujinx.HLE System.LoadNca(NcaFile); } + public void LoadNsp(string NspFile) + { + System.LoadNsp(NspFile); + } + public void LoadProgram(string FileName) { System.LoadProgram(FileName); diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index 7f3c0ae99b..7f6477953d 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -60,6 +60,10 @@ namespace Ryujinx Console.WriteLine("Loading as NCA."); Device.LoadNca(args[0]); break; + case ".nsp": + Console.WriteLine("Loading as NSP."); + Device.LoadNsp(args[0]); + break; default: Console.WriteLine("Loading as homebrew."); Device.LoadProgram(args[0]);