private static string Print(this Pfs pfs) { const int colLen = 36; const int fileNameLen = 39; var sb = new StringBuilder(); sb.AppendLine(); sb.AppendLine("PFS0:"); PrintItem(sb, colLen, "Magic:", pfs.Header.Magic); PrintItem(sb, colLen, "Number of files:", pfs.Header.NumFiles); for (int i = 0; i < pfs.Files.Length; i++) { PfsFileEntry file = pfs.Files[i]; string label = i == 0 ? "Files:" : ""; string offsets = $"{file.Offset:x12}-{file.Offset + file.Size:x12}{file.HashValidity.GetValidityString()}"; string data = $"pfs0:/{file.Name}".PadRight(fileNameLen) + offsets; PrintItem(sb, colLen, label, data); } return(sb.ToString()); }
public ExefsEntry(Pfs pfs, PfsFileEntry entry, string root = "") : base(pfs, entry) { if (root != string.Empty) { FileName = $"{root}/Exefs/{entry.Name}"; } else { FileName = $"Exefs/{entry.Name}"; } }
public void LoadNsp(string NspFile) { FileStream File = new FileStream(NspFile, FileMode.Open, FileAccess.Read); Pfs Nsp = new Pfs(File); 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 Ticket Ticket = new Ticket(new BinaryReader(Nsp.OpenFile(TicketFile))); KeySet.TitleKeys[Ticket.RightsId] = Ticket.GetTitleKey(KeySet); } Nca MainNca = null; Nca ControlNca = null; 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) { MainNca = Nca; } else if (Nca.Header.ContentType == ContentType.Control) { ControlNca = Nca; } } if (MainNca != null) { LoadNca(MainNca, ControlNca); return; } Device.Log.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file"); }
public void LoadNsp(string nspFile) { FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read); Pfs nsp = new Pfs(file); 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) { Ticket ticket = new Ticket(nsp.OpenFile(ticketFile)); KeySet.TitleKeys[ticket.RightsId] = ticket.GetTitleKey(KeySet); } Nca mainNca = null; Nca controlNca = null; 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) { mainNca = nca; } else if (nca.Header.ContentType == ContentType.Control) { controlNca = nca; } } if (mainNca != null) { LoadNca(mainNca, controlNca); return; } Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file"); }
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 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 static void PrintPartition(StringBuilder sb, int colLen, XciPartition partition) { const int fileNameLen = 57; sb.AppendLine($"{GetDisplayName(partition.Name)} Partition:{partition.HashValidity.GetValidityString()}"); PrintItem(sb, colLen, " Magic:", partition.Header.Magic); PrintItem(sb, colLen, " Offset:", $"{partition.Offset:x12}"); PrintItem(sb, colLen, " Number of files:", partition.Files.Length); if (partition.Files.Length > 0 && partition.Files.Length < 100) { for (int i = 0; i < partition.Files.Length; i++) { PfsFileEntry file = partition.Files[i]; string label = i == 0 ? " Files:" : ""; string offsets = $"{file.Offset:x12}-{file.Offset + file.Size:x12}{file.HashValidity.GetValidityString()}"; string data = $"{partition.Name}:/{file.Name}".PadRight(fileNameLen) + offsets; PrintItem(sb, colLen, label, data); } } }
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).TrimStart('\\'); if (nsp.FileExists(filename)) { return(OpenNcaFs(context, fullPath, nsp.OpenFile(filename))); } } return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist)); }
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).TrimStart('\\'); if (Nsp.FileExists(Filename)) { return(OpenNcaFs(Context, FullPath, Nsp.OpenFile(Filename))); } } return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist)); }
public PartEntry(Pfs pfs, PfsFileEntry entry) { ParentPfs = pfs; fileEntry = entry; FileName = fileEntry.Name; }
public void LoadNsp(string nspFile) { FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read); Pfs nsp = new Pfs(file.AsStorage(false)); foreach (PfsFileEntry ticketEntry in nsp.Files.Where(x => x.Name.EndsWith(".tik"))) { Ticket ticket = new Ticket(nsp.OpenFile(ticketEntry).AsStream()); if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId)) { KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet)); } } Nca mainNca = null; Nca controlNca = null; 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) { mainNca = nca; } else if (nca.Header.ContentType == ContentType.Control) { controlNca = nca; } } if (mainNca != null) { LoadNca(mainNca, controlNca); return; } // This is not a normal NSP, it's actually a ExeFS as a NSP Npdm metaData = null; PfsFileEntry npdmFile = nsp.Files.FirstOrDefault(x => x.Name.Equals("main.npdm")); if (npdmFile != null) { Logger.PrintInfo(LogClass.Loader, $"Loading main.npdm..."); metaData = new Npdm(nsp.OpenFile(npdmFile).AsStream()); } else { Logger.PrintWarning(LogClass.Loader, $"NPDM file not found, using default values!"); metaData = GetDefaultNpdm(); } List <IExecutable> staticObjects = new List <IExecutable>(); void LoadNso(string searchPattern) { PfsFileEntry entry = nsp.Files.FirstOrDefault(x => x.Name.Equals(searchPattern)); if (entry != null) { Logger.PrintInfo(LogClass.Loader, $"Loading {entry.Name}..."); NxStaticObject staticObject = new NxStaticObject(nsp.OpenFile(entry).AsStream()); staticObjects.Add(staticObject); } } CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); LoadNso("rtld"); LoadNso("main"); LoadNso("subsdk*"); LoadNso("sdk"); ContentManager.LoadEntries(); if (staticObjects.Count == 0) { Logger.PrintError(LogClass.Loader, "Could not find an Application NCA in the provided NSP file"); } else { ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray()); } }
public static void Main(string[] Args) { usbnsp: Console.Clear(); Initialize(); try { var pat = new KLST_PATTERN_MATCH { DeviceID = @"USB\VID_057E&PID_3000" }; var lst = new LstK(0, ref pat); lst.MoveNext(out var dinfo); USB = new UsbK(dinfo); } catch { Error.Log("No USB connection was found. Make sure you have Goldleaf open before running Goldtree."); } try { Command c = new Command(CommandId.ConnectionRequest); USB.Write(c); Log.Log("Attempting to connect to Goldleaf via USB..."); Command rc = USB.Read(); if (rc.MagicOk()) { if (rc.IsCommandId(CommandId.ConnectionResponse)) { Log.Log("Connection was established with Goldleaf."); Log.Log("Select the NSP to send to Goldleaf on the dialog."); OpenFileDialog fd = new OpenFileDialog() { Title = "Select NSP to send to Goldleaf via USB", Filter = "NSP / Nintendo Submission Package (*.nsp)|*.nsp", Multiselect = false, }; if (fd.ShowDialog() == DialogResult.OK) { string nsp = fd.FileName; string nspname = Path.GetFileName(nsp); c = new Command(CommandId.NSPName); USB.Write(c); USB.Write((uint)nspname.Length); USB.Write(nspname); Log.Log("Selected NSP's name was sent to Goldleaf. Waiting for install approval from Goldleaf..."); Command rc2 = USB.Read(); if (rc2.MagicOk()) { if (rc2.IsCommandId(CommandId.Start)) { Log.Log("Goldleaf is ready for the installation. Preparing everything..."); try { FileStream fs = new FileStream(nsp, FileMode.Open); StreamStorage ist = new StreamStorage(fs, true); Pfs pnsp = new Pfs(ist); ist.Dispose(); fs.Close(); fs = new FileStream(nsp, FileMode.Open); uint filecount = (uint)pnsp.Files.Length; c = new Command(CommandId.NSPData); USB.Write(c); USB.Write(filecount); int tikidx = -1; int certidx = -1; int tmpidx = 0; foreach (var file in pnsp.Files) { ulong offset = (ulong)pnsp.HeaderSize + (ulong)file.Offset; ulong size = (ulong)file.Size; uint len = (uint)file.Name.Length; USB.Write(len); USB.Write(file.Name); USB.Write(offset); USB.Write(size); if (Path.GetExtension(file.Name).Replace(".", "").ToLower() == "tik") { tikidx = tmpidx; } else if (Path.GetExtension(file.Name).Replace(".", "").ToLower() == "cert") { certidx = tmpidx; } tmpidx++; } BinaryReader br = new BinaryReader(fs); while (true) { Command ccmd = USB.Read(); if (ccmd.MagicOk()) { if (ccmd.IsCommandId(CommandId.NSPContent)) { USB.Read(out uint idx); Log.Log("Sending content \'" + pnsp.Files[idx].Name + "\'... (" + (idx + 1) + " of " + pnsp.Files.Length + ")"); PfsFileEntry ent = pnsp.Files[idx]; long rsize = 0x800000; long coffset = pnsp.HeaderSize + ent.Offset; long toread = ent.Size; long tmpread = 1; byte[] bufb; while ((tmpread > 0) && (toread > 0) && (coffset < (coffset + ent.Size))) { if (rsize >= ent.Size) { rsize = ent.Size; } int tor = (int)Math.Min(rsize, toread); br.BaseStream.Position = coffset; bufb = br.ReadBytes(tor); tmpread = bufb.Length; USB.Write(bufb); coffset += tmpread; toread -= tmpread; } Log.Log("Content was sent to Goldleaf."); } else if (ccmd.IsCommandId(CommandId.NSPTicket)) { Log.Log("Sending ticket file..."); PfsFileEntry tik = pnsp.Files[tikidx]; br.BaseStream.Seek(pnsp.HeaderSize + tik.Offset, SeekOrigin.Begin); byte[] file = br.ReadBytes((int)tik.Size); USB.Write(file); Log.Log("Ticket was sent to Goldleaf."); } else if (ccmd.IsCommandId(CommandId.Finish)) { break; } else { USB = null; Error.Log("An invalid command was received. Are you sure Goldleaf is active?"); } } else { USB = null; Error.Log("An invalid command was received. Are you sure Goldleaf is active?"); } } } catch { Error.Log("An error ocurred opening the selected NSP. Are you sure it's a valid NSP?"); } } else if (rc2.IsCommandId(CommandId.Finish)) { USB = null; Error.Log("Goldleaf has canceled the installation."); } else { USB = null; Error.Log("An invalid command was received. Are you sure Goldleaf is active?"); } } else { USB = null; Error.Log("An invalid command was received. Are you sure Goldleaf is active?"); } } else { Error.Log("The dialog was closed without selecting a NSP, or another error ocurred. Reopen Goldleaf and Goldtree and try again."); } } else if (rc.IsCommandId(CommandId.Finish)) { USB = null; Error.Log("Goldleaf has canceled the installation."); } else { USB = null; Error.Log("An invalid command was received. Are you sure Goldleaf is active?"); } } else { USB = null; Error.Log("An invalid command was received. Are you sure Goldleaf is active?"); } } catch { Error.Log("An error ocurred selecting the NSP to be sent."); } Log.Log("The installation has finished. Press ENTER to close Goldtree, or any other key to start another USB installation.", true); ConsoleKeyInfo ki = Console.ReadKey(); if (ki.Key == ConsoleKey.Enter) { if (USB != null) { Command cmd = new Command(CommandId.Finish); USB.Write(cmd); } Environment.Exit(0); } else { goto usbnsp; } }
public ExefsEntry(Pfs pfs, PfsFileEntry entry) { ParentPfs = pfs; fileEntry = entry; FileName = $"Exefs/{fileEntry.Name}"; }