Пример #1
0
        // Main wrapper that assembles the ROM based on the following specifications:
        internal static bool BuildROM(bool card2, string logoName,
                                      string exefsPath, string romfsPath, string exheaderPath,
                                      string serialText, string savePath)
        {
            // Sanity check the input files.
            if (!
                ((File.Exists(exefsPath) || Directory.Exists(exefsPath)) &&
                 (File.Exists(romfsPath) || Directory.Exists(romfsPath)) &&
                 File.Exists(exheaderPath)))
            {
                return(false);
            }

            // If ExeFS and RomFS are not built, build.
            if (!File.Exists(exefsPath) && Directory.Exists(exefsPath))
            {
                ExeFS.Set(Directory.GetFiles(exefsPath), exefsPath = "exefs.bin");
            }
            if (!File.Exists(romfsPath) && Directory.Exists(romfsPath))
            {
                RomFS.BuildRomFS(romfsPath, romfsPath = "romfs.bin");
            }

            Ncch ncch    = Ctr.SetNcch(exefsPath, romfsPath, exheaderPath, serialText, logoName);
            Ncsd ncsd    = Ctr.SetNcsd(ncch, card2);
            bool success = Ctr.WriteROM(ncsd, savePath);

            return(success);
        }
Пример #2
0
        // Sub methods that drive the operation
        internal static Ncch SetNcch(string exefsPath, string romfsPath, string exheaderPath, string tbSerial, string logoName)
        {
            Ncch ncch = new Ncch {
                Exheader    = new Exheader(exheaderPath),
                Plainregion = new byte[0]
            };

            if (ncch.Exheader.IsPokemon())
            {
                if (ncch.Exheader.IsXy())
                {
                    ncch.Plainregion = (byte[])Resources.ResourceManager.GetObject("XY");
                }
                else if (ncch.Exheader.IsOras())
                {
                    ncch.Plainregion = (byte[])Resources.ResourceManager.GetObject("ORAS");
                }
            }
            ncch.Exefs = new ExeFS(exefsPath);
            ncch.Romfs = new RomFS(romfsPath);

            ncch.Logo = (byte[])Resources.ResourceManager.GetObject(logoName);
            ulong len = 0x200;             //NCCH Signature + NCCH Header

            ncch.HeaderData = new Ncch.Header {
                Signature = new byte[0x100], Magic = 0x4843434E
            };
            ncch.HeaderData.TitleId       = ncch.HeaderData.ProgramId = ncch.Exheader.TitleID;
            ncch.HeaderData.MakerCode     = 0x3130;         //01
            ncch.HeaderData.FormatVersion = 0x2;            //Default
            ncch.HeaderData.LogoHash      = new SHA256Managed().ComputeHash(ncch.Logo);
            ncch.HeaderData.ProductCode   = Encoding.ASCII.GetBytes(tbSerial);
            Array.Resize(ref ncch.HeaderData.ProductCode, 0x10);
            ncch.HeaderData.ExheaderHash = ncch.Exheader.GetSuperBlockHash();
            ncch.HeaderData.ExheaderSize = (uint)ncch.Exheader.Data.Length;
            len += ncch.HeaderData.ExheaderSize + (uint)ncch.Exheader.AccessDescriptor.Length;
            ncch.HeaderData.Flags = new byte[0x8];
            //FLAGS
            ncch.HeaderData.Flags[3]   = 0;             // Crypto: 0 = <7.x, 1=7.x;
            ncch.HeaderData.Flags[4]   = 1;             // Content Platform: 1 = CTR;
            ncch.HeaderData.Flags[5]   = 0x3;           // Content Type Bitflags: 1=Data, 2=Executable, 4=SysUpdate, 8=Manual, 0x10=Trial;
            ncch.HeaderData.Flags[6]   = 0;             // MEDIA_UNIT_SIZE = 0x200*Math.Pow(2, Content.header.Flags[6]);
            ncch.HeaderData.Flags[7]   = 1;             // FixedCrypto = 1, NoMountRomfs = 2; NoCrypto=4;
            ncch.HeaderData.LogoOffset = (uint)(len / MediaUnitSize);
            ncch.HeaderData.LogoSize   = (uint)(ncch.Logo.Length / MediaUnitSize);
            len += (uint)ncch.Logo.Length;
            ncch.HeaderData.PlainRegionOffset = (uint)(ncch.Plainregion?.Length > 0
                                                                                                                         ? len / MediaUnitSize
                                                                                                                         : 0);
            ncch.HeaderData.PlainRegionSize = (uint)(ncch.Plainregion?.Length ?? 0) / MediaUnitSize;
            len += (uint)(ncch.Plainregion?.Length ?? 0);
            ncch.HeaderData.ExefsOffset         = (uint)(len / MediaUnitSize);
            ncch.HeaderData.ExefsSize           = (uint)(ncch.Exefs.Data.Length / MediaUnitSize);
            ncch.HeaderData.ExefsSuperBlockSize = 0x200 / MediaUnitSize; //Static 0x200 for exefs superblock
            len += (uint)ncch.Exefs.Data.Length;
            len  = (uint)Ctr.Align(len, 0x1000);                         //Romfs Start is aligned to 0x1000
            ncch.HeaderData.RomfsOffset         = (uint)(len / MediaUnitSize);
            ncch.HeaderData.RomfsSize           = (uint)(new FileInfo(ncch.Romfs.FileName).Length / MediaUnitSize);
            ncch.HeaderData.RomfsSuperBlockSize = ncch.Romfs.SuperBlockLen / MediaUnitSize;
            len += ncch.HeaderData.RomfsSize * MediaUnitSize;
            ncch.HeaderData.ExefsHash = ncch.Exefs.SuperBlockHash;
            ncch.HeaderData.RomfsHash = ncch.Romfs.SuperBlockHash;
            ncch.HeaderData.Size      = (uint)(len / MediaUnitSize);
            //Build the Header byte[].
            ncch.HeaderData.BuildHeader();

            return(ncch);
        }