Exemplo n.º 1
0
        internal static bool writeROM(NCSD NCSD, string SAVE_PATH,
                                      ProgressBar PB_Show = null, RichTextBox TB_Progress = null)
        {
            PB_Show     = PB_Show ?? new ProgressBar();
            TB_Progress = TB_Progress ?? new RichTextBox();
            using (FileStream OutFileStream = new FileStream(SAVE_PATH, FileMode.Create))
            {
                updateTB(TB_Progress, "Writing NCSD Header...");
                OutFileStream.Write(NCSD.Data, 0, NCSD.Data.Length);
                updateTB(TB_Progress, "Writing NCCH...");
                OutFileStream.Write(NCSD.NCCH_Array[0].header.Data, 0, NCSD.NCCH_Array[0].header.Data.Length); //Write NCCH header
                //AES time.
                byte[] key = new byte[0x10];                                                                   //Fixed-Crypto key is all zero.
                for (int i = 0; i < 3; i++)
                {
                    AesCtr aesctr = new AesCtr(key, NCSD.NCCH_Array[0].header.ProgramId, (ulong)(i + 1) << 56); //CTR is ProgramID, section id<<88
                    switch (i)
                    {
                    case 0:     //Exheader + AccessDesc
                        updateTB(TB_Progress, "Writing Exheader...");
                        byte[] inEncExheader  = new byte[NCSD.NCCH_Array[0].exheader.Data.Length + NCSD.NCCH_Array[0].exheader.AccessDescriptor.Length];
                        byte[] outEncExheader = new byte[NCSD.NCCH_Array[0].exheader.Data.Length + NCSD.NCCH_Array[0].exheader.AccessDescriptor.Length];
                        Array.Copy(NCSD.NCCH_Array[0].exheader.Data, inEncExheader, NCSD.NCCH_Array[0].exheader.Data.Length);
                        Array.Copy(NCSD.NCCH_Array[0].exheader.AccessDescriptor, 0, inEncExheader, NCSD.NCCH_Array[0].exheader.Data.Length, NCSD.NCCH_Array[0].exheader.AccessDescriptor.Length);
                        aesctr.TransformBlock(inEncExheader, 0, inEncExheader.Length, outEncExheader, 0);
                        OutFileStream.Write(outEncExheader, 0, outEncExheader.Length);     // Write Exheader
                        break;

                    case 1:     //Exefs
                        updateTB(TB_Progress, "Writing Exefs...");
                        OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.ExefsOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                        byte[] OutExefs = new byte[NCSD.NCCH_Array[0].exefs.Data.Length];
                        aesctr.TransformBlock(NCSD.NCCH_Array[0].exefs.Data, 0, NCSD.NCCH_Array[0].exefs.Data.Length, OutExefs, 0);
                        OutFileStream.Write(OutExefs, 0, OutExefs.Length);
                        break;

                    case 2:     //Romfs
                        updateTB(TB_Progress, "Writing Romfs...");
                        OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.RomfsOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                        using (FileStream InFileStream = new FileStream(NCSD.NCCH_Array[0].romfs.FileName, FileMode.Open, FileAccess.Read))
                        {
                            uint  BUFFER_SIZE;
                            ulong RomfsLen = NCSD.NCCH_Array[0].header.RomfsSize * MEDIA_UNIT_SIZE;
                            PB_Show.Invoke((Action)(() =>
                            {
                                PB_Show.Minimum = 0;
                                PB_Show.Maximum = (int)(RomfsLen / 0x400000);
                                PB_Show.Value = 0;
                                PB_Show.Step = 1;
                            }));
                            for (ulong j = 0; j < RomfsLen; j += BUFFER_SIZE)
                            {
                                BUFFER_SIZE = RomfsLen - j > 0x400000 ? 0x400000 : (uint)(RomfsLen - j);
                                byte[] buf    = new byte[BUFFER_SIZE];
                                byte[] outbuf = new byte[BUFFER_SIZE];
                                InFileStream.Read(buf, 0, (int)BUFFER_SIZE);
                                aesctr.TransformBlock(buf, 0, (int)BUFFER_SIZE, outbuf, 0);
                                OutFileStream.Write(outbuf, 0, (int)BUFFER_SIZE);
                                PB_Show.Invoke((Action)PB_Show.PerformStep);
                            }
                        }
                        break;
                    }
                }
                updateTB(TB_Progress, "Writing Logo...");
                OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.LogoOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                OutFileStream.Write(NCSD.NCCH_Array[0].logo, 0, NCSD.NCCH_Array[0].logo.Length);
                if (NCSD.NCCH_Array[0].plainregion.Length > 0)
                {
                    updateTB(TB_Progress, "Writing Plain Region...");
                    OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.PlainRegionOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                    OutFileStream.Write(NCSD.NCCH_Array[0].plainregion, 0, NCSD.NCCH_Array[0].plainregion.Length);
                }

                //NCSD Padding
                OutFileStream.Seek(NCSD.header.OffsetSizeTable[NCSD.NCCH_Array.Count - 1].Offset * MEDIA_UNIT_SIZE + NCSD.header.OffsetSizeTable[NCSD.NCCH_Array.Count - 1].Size * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                ulong  TotalLen = NCSD.header.MediaSize * MEDIA_UNIT_SIZE;
                byte[] Buffer   = Enumerable.Repeat((byte)0xFF, 0x400000).ToArray();
                updateTB(TB_Progress, "Writing NCSD Padding...");
                while ((ulong)OutFileStream.Position < TotalLen)
                {
                    int BUFFER_LEN = TotalLen - (ulong)OutFileStream.Position < 0x400000 ? (int)(TotalLen - (ulong)OutFileStream.Position) : 0x400000;
                    OutFileStream.Write(Buffer, 0, BUFFER_LEN);
                }
            }

            //Delete Temporary Romfs File
            if (NCSD.NCCH_Array[0].romfs.isTempFile)
            {
                File.Delete(NCSD.NCCH_Array[0].romfs.FileName);
            }

            updateTB(TB_Progress, "Done!");
            return(true);
        }
Exemplo n.º 2
0
        internal static bool writeROM(NCSD NCSD, string SAVE_PATH,
            ProgressBar PB_Show = null, RichTextBox TB_Progress = null)
        {
            PB_Show = PB_Show ?? new ProgressBar();
            TB_Progress = TB_Progress ?? new RichTextBox();
            using (FileStream OutFileStream = new FileStream(SAVE_PATH, FileMode.Create))
            {
                updateTB(TB_Progress, "Writing NCSD Header...");
                OutFileStream.Write(NCSD.Data, 0, NCSD.Data.Length);
                updateTB(TB_Progress, "Writing NCCH...");
                OutFileStream.Write(NCSD.NCCH_Array[0].header.Data, 0, NCSD.NCCH_Array[0].header.Data.Length); //Write NCCH header
                //AES time.
                byte[] key = new byte[0x10]; //Fixed-Crypto key is all zero.
                for (int i = 0; i < 3; i++)
                {
                    AesCtr aesctr = new AesCtr(key, NCSD.NCCH_Array[0].header.ProgramId, (ulong)(i + 1) << 56); //CTR is ProgramID, section id<<88
                    switch (i)
                    {
                        case 0: //Exheader + AccessDesc
                            updateTB(TB_Progress, "Writing Exheader...");
                            byte[] inEncExheader = new byte[NCSD.NCCH_Array[0].exheader.Data.Length + NCSD.NCCH_Array[0].exheader.AccessDescriptor.Length];
                            byte[] outEncExheader = new byte[NCSD.NCCH_Array[0].exheader.Data.Length + NCSD.NCCH_Array[0].exheader.AccessDescriptor.Length];
                            Array.Copy(NCSD.NCCH_Array[0].exheader.Data, inEncExheader, NCSD.NCCH_Array[0].exheader.Data.Length);
                            Array.Copy(NCSD.NCCH_Array[0].exheader.AccessDescriptor, 0, inEncExheader, NCSD.NCCH_Array[0].exheader.Data.Length, NCSD.NCCH_Array[0].exheader.AccessDescriptor.Length);
                            aesctr.TransformBlock(inEncExheader, 0, inEncExheader.Length, outEncExheader, 0);
                            OutFileStream.Write(outEncExheader, 0, outEncExheader.Length); // Write Exheader
                            break;
                        case 1: //Exefs
                            updateTB(TB_Progress, "Writing Exefs...");
                            OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.ExefsOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                            byte[] OutExefs = new byte[NCSD.NCCH_Array[0].exefs.Data.Length];
                            aesctr.TransformBlock(NCSD.NCCH_Array[0].exefs.Data, 0, NCSD.NCCH_Array[0].exefs.Data.Length, OutExefs, 0);
                            OutFileStream.Write(OutExefs, 0, OutExefs.Length);
                            break;
                        case 2: //Romfs
                            updateTB(TB_Progress, "Writing Romfs...");
                            OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.RomfsOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                            using (FileStream InFileStream = new FileStream(NCSD.NCCH_Array[0].romfs.FileName, FileMode.Open, FileAccess.Read))
                            {
                                uint BUFFER_SIZE;
                                ulong RomfsLen = NCSD.NCCH_Array[0].header.RomfsSize * MEDIA_UNIT_SIZE;
                                PB_Show.Invoke((Action)(() =>
                                {
                                    PB_Show.Minimum = 0;
                                    PB_Show.Maximum = (int)(RomfsLen / 0x400000);
                                    PB_Show.Value = 0;
                                    PB_Show.Step = 1;
                                }));
                                for (ulong j = 0; j < RomfsLen; j += BUFFER_SIZE)
                                {
                                    BUFFER_SIZE = RomfsLen - j > 0x400000 ? 0x400000 : (uint)(RomfsLen - j);
                                    byte[] buf = new byte[BUFFER_SIZE];
                                    byte[] outbuf = new byte[BUFFER_SIZE];
                                    InFileStream.Read(buf, 0, (int)BUFFER_SIZE);
                                    aesctr.TransformBlock(buf, 0, (int)BUFFER_SIZE, outbuf, 0);
                                    OutFileStream.Write(outbuf, 0, (int)BUFFER_SIZE);
                                    PB_Show.Invoke((Action)PB_Show.PerformStep);
                                }
                            }
                            break;
                    }
                }
                updateTB(TB_Progress, "Writing Logo...");
                OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.LogoOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                OutFileStream.Write(NCSD.NCCH_Array[0].logo, 0, NCSD.NCCH_Array[0].logo.Length);
                if (NCSD.NCCH_Array[0].plainregion.Length > 0)
                {
                    updateTB(TB_Progress, "Writing Plain Region...");
                    OutFileStream.Seek(0x4000 + NCSD.NCCH_Array[0].header.PlainRegionOffset * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                    OutFileStream.Write(NCSD.NCCH_Array[0].plainregion, 0, NCSD.NCCH_Array[0].plainregion.Length);
                }

                //NCSD Padding
                OutFileStream.Seek(NCSD.header.OffsetSizeTable[NCSD.NCCH_Array.Count - 1].Offset * MEDIA_UNIT_SIZE + NCSD.header.OffsetSizeTable[NCSD.NCCH_Array.Count - 1].Size * MEDIA_UNIT_SIZE, SeekOrigin.Begin);
                ulong TotalLen = NCSD.header.MediaSize * MEDIA_UNIT_SIZE;
                byte[] Buffer = Enumerable.Repeat((byte)0xFF, 0x400000).ToArray();
                updateTB(TB_Progress, "Writing NCSD Padding...");
                while ((ulong)OutFileStream.Position < TotalLen)
                {
                    int BUFFER_LEN = TotalLen - (ulong)OutFileStream.Position < 0x400000 ? (int)(TotalLen - (ulong)OutFileStream.Position) : 0x400000;
                    OutFileStream.Write(Buffer, 0, BUFFER_LEN);
                }
            }

            //Delete Temporary Romfs File
            if (NCSD.NCCH_Array[0].romfs.isTempFile)
                File.Delete(NCSD.NCCH_Array[0].romfs.FileName);

            updateTB(TB_Progress, "Done!");
            return true;
        }