示例#1
0
        public IEnumerable <Tuple <string, string> > InstallNSP(ObservableCollection <AluminumFoil.NSP> NSPs)
        {
            // Installs NSP to Switch via TinFoil
            using (AluminumFoil.Switch NX = new AluminumFoil.Switch())
            {
                // Send NSP List
                yield return(new InstallUpdate("Sending NSP names to TinFoil", "installing"));

                NX.Write(MAGIC);

                Console.WriteLine("Sending NSP names to TinFoil");
                string concatenatedNames = string.Join("\n", NSPs.Select(n => n.BaseName));

                byte[] namesBytes = concatenatedNames.AsBytes();
                NX.Write(BitConverter.GetBytes(Convert.ToUInt32(namesBytes.Length)));
                NX.Write(new byte[0x8] {
                    0, 0, 0, 0, 0, 0, 0, 0
                });
                NX.Write(namesBytes);

                Console.WriteLine("Waiting for response from TinFoil");
                yield return(new InstallUpdate("Select NSP on TinFoil", "waiting"));

                // Poll Commands
                while (true)
                {
                    byte[] command = NX.Read(0x20);

                    if (!command.SubArray(0x0, 0x4).SequenceEqual(COMMANDMAGIC))
                    {
                        continue;
                    }
                    ;

                    byte[] cmdType     = command.SubArray(0x4, 0x1);
                    uint   cmdID       = BitConverter.ToUInt32(command, 0x8);
                    ulong  payloadSize = BitConverter.ToUInt64(command, 0xC);

                    if (cmdID == (uint)CommandIDs.Exit)
                    {
                        yield return(new InstallUpdate("Finished", "finished"));

                        break;
                    }
                    else if (cmdID == (uint)CommandIDs.FileRange)
                    {
                        // File Range Command
                        byte[] fileRangeRequest = NX.Read(0x20);

                        ulong size    = BitConverter.ToUInt64(fileRangeRequest, 0x0);
                        ulong offset  = BitConverter.ToUInt64(fileRangeRequest, 0x8);
                        ulong nameLen = BitConverter.ToUInt64(fileRangeRequest, 0x10);

                        string selectedBaseName = NX.Read(Convert.ToInt32(nameLen)).AsString();

                        AluminumFoil.NSP selectedNSP = NSPs.FirstOrDefault(n => n.BaseName == selectedBaseName);

                        if (selectedNSP == null)
                        {
                            throw new Exception(string.Format("TinFoil requested {0} but this NSP is not opened for installation.", selectedBaseName));
                        }

                        yield return(new InstallUpdate(string.Format("Transferring {0} requested bytes to TinFoil", size), "installing"));

                        NX.Write(ResponseHeader((uint)CommandIDs.FileRange, size));

                        using (BinaryReader fileReader = new BinaryReader(new FileStream(selectedNSP.FilePath, FileMode.Open)))
                        {
                            fileReader.BaseStream.Seek((long)offset, SeekOrigin.Begin);

                            ulong bytesRead = 0;

                            while (bytesRead < size)
                            {
                                ulong readLen;
                                if (bytesRead + ChunkSize >= size)
                                {
                                    readLen = size - bytesRead;
                                }
                                else
                                {
                                    readLen = ChunkSize;
                                }

                                NX.Write(fileReader.ReadBytes((int)readLen));
                                bytesRead += readLen;
                                selectedNSP.Transferred += readLen;
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        public IEnumerable <(string, string)> InstallNSP(ObservableCollection <AluminumFoil.NSP> NSPs)
        {
            AluminumFoil.NSP nsp = NSPs.First();

            Console.WriteLine(string.Format("Installing {0} via GoldLeaf", nsp.BaseName));
            // Installs NSP to Switch via GoldLeaf
            int txLen;

            using (AluminumFoil.Switch NX = new AluminumFoil.Switch())
            {
                Console.WriteLine("Sending ConnectionRequest");
                NX.Write(commandHeaders["ConnectionRequest"]);

                bool finished = false;
                while (!finished)
                {
                    byte[] resp = NX.Read(0x8);

                    string CommandName = RespType(resp);

                    Console.WriteLine("Recieved command from GoldLeaf: " + CommandName);
                    switch (CommandName)
                    {
                    case "ConnectionResponse":
                        Console.WriteLine("Sending NSP name to GoldLeaf");
                        yield return(new InstallUpdate("Sending NSP name to GoldLeaf", "installing"));

                        NX.Write(commandHeaders["NSPName"]);

                        var nameBytes = nsp.BaseName.AsBytes();

                        NX.Write(BitConverter.GetBytes(Convert.ToUInt32(nameBytes.Length)));
                        NX.Write(nameBytes);

                        yield return(new InstallUpdate("Confirm Installation Options on GoldLeaf", "waiting"));

                        break;

                    case "Start":
                        Console.WriteLine("Sending NSP metadata to GoldLeaf");
                        yield return(new InstallUpdate("Sending NSP Metadata", "installing"));

                        NX.Write(commandHeaders["NSPData"]);
                        NX.Write(BitConverter.GetBytes(Convert.ToUInt32(nsp.Contents.Count)));

                        foreach (var file in nsp.Contents)
                        {
                            // uint [4] Name len
                            NX.Write(BitConverter.GetBytes(Convert.ToUInt32(file.Name.Length)));

                            // str [*] Name
                            NX.Write(file.Name.AsBytes());

                            // ulong [8] File offset
                            NX.Write(BitConverter.GetBytes(file.Offset));

                            // ulong [8] File size
                            NX.Write(BitConverter.GetBytes(file.Size));
                        }

                        break;

                    case "NSPContent":
                        byte[] indBytes = NX.Read(0x4);

                        var idx = (int)BitConverter.ToUInt32(indBytes, 0);


                        Console.WriteLine(string.Format("GoldLeaf requested nca {0}: {1}", idx, nsp.Contents[idx].Name));
                        yield return(new InstallUpdate("Installing " + nsp.Contents[idx].Name, "installing"));

                        foreach (var chunk in nsp.ReadFile(idx))
                        {
                            txLen            = NX.Write(chunk);
                            nsp.Transferred += (ulong)chunk.Length;
                        }

                        nsp.Contents[idx].Finished = true;

                        break;

                    case "NSPTicket":
                        Console.WriteLine("Sending NSP ticket");
                        yield return(new InstallUpdate("Installing Ticket", "installing"));

                        var tikind = -1;

                        for (var i = 0; i < nsp.Contents.Count; i++)
                        {
                            if (nsp.Contents[i].Name.EndsWith("tik"))
                            {
                                tikind = i;
                                break;
                            }
                        }

                        if (tikind == -1)
                        {
                            Console.WriteLine("Could not find tik in NSP");
                            Exception exc = new IndexOutOfRangeException("Ticket file not found in NSP header.");
                            exc.Source = nsp.FilePath;
                            throw exc;
                        }
                        ;

                        byte[] ticketFile = new byte[nsp.Contents[tikind].Size];

                        using (BinaryReader reader = new BinaryReader(new FileStream(nsp.FilePath, FileMode.Open)))
                        {
                            var tikoffset = nsp.Contents[tikind].Offset;
                            reader.BaseStream.Seek(Convert.ToInt64(tikoffset), SeekOrigin.Begin);
                            reader.Read(ticketFile, 0, ticketFile.Length);
                        }

                        NX.Write(ticketFile);

                        break;

                    case "Finish":
                        Console.WriteLine("Finished installing " + nsp.BaseName);
                        yield return(new InstallUpdate("Finished", "finished"));

                        finished = true;
                        break;

                    default:
                        Console.WriteLine("Unhandled command from GoldLeaf: " + resp.AsString());
                        yield return(new InstallUpdate("Unknown request from GoldLeaf: " + resp.AsString(), "alert"));

                        finished = true;
                        break;
                    }
                }
            }
        }