Beispiel #1
0
        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());
        }
Beispiel #2
0
 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}";
     }
 }
Beispiel #3
0
        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");
        }
Beispiel #4
0
        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");
        }
Beispiel #5
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);
        }
Beispiel #6
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);
        }
Beispiel #7
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);
                }
            }
        }
Beispiel #8
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).TrimStart('\\');

                if (nsp.FileExists(filename))
                {
                    return(OpenNcaFs(context, fullPath, nsp.OpenFile(filename)));
                }
            }

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
Beispiel #9
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).TrimStart('\\');

                if (Nsp.FileExists(Filename))
                {
                    return(OpenNcaFs(Context, FullPath, Nsp.OpenFile(Filename)));
                }
            }

            return(MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist));
        }
Beispiel #10
0
 public PartEntry(Pfs pfs, PfsFileEntry entry)
 {
     ParentPfs = pfs;
     fileEntry = entry;
     FileName  = fileEntry.Name;
 }
Beispiel #11
0
        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());
            }
        }
Beispiel #12
0
        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;
            }
        }
Beispiel #13
0
 public ExefsEntry(Pfs pfs, PfsFileEntry entry)
 {
     ParentPfs = pfs;
     fileEntry = entry;
     FileName  = $"Exefs/{fileEntry.Name}";
 }