Пример #1
0
        internal static void BuildRomFS(string outfile, string infile, RichTextBox TB_Progress = null, ProgressBar PB_Show = null)
        {
            OutFile = outfile;
            ROOT_DIR = infile;
            if (File.Exists(TempFile)) File.Delete(TempFile);

            FileNameTable FNT = new FileNameTable(ROOT_DIR);
            RomfsFile[] RomFiles = new RomfsFile[FNT.NumFiles];
            LayoutManager.Input[] In = new LayoutManager.Input[FNT.NumFiles];
            updateTB(TB_Progress, "Creating Layout...");
            for (int i = 0; i < FNT.NumFiles; i++)
            {
                In[i] = new LayoutManager.Input { FilePath = FNT.NameEntryTable[i].FullName, AlignmentSize = 0x10 };
            }
            LayoutManager.Output[] Out = LayoutManager.Create(In);
            for (int i = 0; i < Out.Length; i++)
            {
                RomFiles[i] = new RomfsFile
                {
                    Offset = Out[i].Offset,
                    PathName = Out[i].FilePath.Replace(Path.GetFullPath(ROOT_DIR), "").Replace("\\", "/"),
                    FullName = Out[i].FilePath,
                    Size = Out[i].Size
                };
            }
            using (MemoryStream memoryStream = new MemoryStream())
            {
                updateTB(TB_Progress, "Creating RomFS MetaData...");
                BuildRomFSHeader(memoryStream, RomFiles, ROOT_DIR);
                MakeRomFSData(RomFiles, memoryStream, TB_Progress, PB_Show);
            }
        }
Пример #2
0
 public ArchiveFileInfo(RomFsFileSystem parent, RomfsFile file)
 {
     RomfsParent = parent;
     FullPath    = file.FullPath;
     DataSize    = file.DataLength;
     DataOffset  = file.DataOffset;
 }
Пример #3
0
        internal static void BuildRomFS(string infile, string outfile)
        {
            OutFile = outfile;
            RootDir = infile;
            if (File.Exists(TempFile))
            {
                File.Delete(TempFile);
            }

            FileNameTable fnt = new FileNameTable(RootDir);

            RomfsFile[]           romFiles = new RomfsFile[fnt.NumFiles];
            LayoutManager.Input[] In       = new LayoutManager.Input[fnt.NumFiles];
            for (int i = 0; i < fnt.NumFiles; i++)
            {
                In[i] = new LayoutManager.Input {
                    FilePath = fnt.NameEntryTable[i].FullName, AlignmentSize = 0x10
                };
            }
            LayoutManager.Output[] Out = LayoutManager.Create(In);
            for (int i = 0; i < Out.Length; i++)
            {
                romFiles[i] = new RomfsFile {
                    Offset   = Out[i].Offset,
                    PathName = Out[i].FilePath.Replace(Path.GetFullPath(RootDir), "").Replace("\\", "/"),
                    FullName = Out[i].FilePath,
                    Size     = Out[i].Size
                };
            }
            using (MemoryStream memoryStream = new MemoryStream())
            {
                RomFS.BuildRomFSHeader(memoryStream, romFiles, RootDir);
                RomFS.MakeRomFSData(romFiles, memoryStream);
            }
        }
Пример #4
0
 public FileEntry(Romfs romfs, RomfsFile romfsFile, string root = "")
 {
     ParentROMFS = romfs;
     File        = romfsFile;
     if (root != string.Empty)
     {
         FileName = $"{root}/Romfs/{File.FullPath}";
     }
     else
     {
         FileName = $"Romfs/{File.FullPath}";
     }
 }
Пример #5
0
        // Thanks to Alex Barney for providing this code!
        public static void PopulateTreeView(TreeNodeCollection nodes, RomfsDir root)
        {
            RomfsFile fileNode = root.FirstFile;

            while (fileNode != null)
            {
                nodes.Add(fileNode.FullPath, fileNode.Name);
                fileNode = fileNode.NextSibling;
            }

            RomfsDir dirNode = root.FirstChild;

            while (dirNode != null)
            {
                TreeNode newNode = nodes.Add(dirNode.FullPath, dirNode.Name);
                PopulateTreeView(newNode.Nodes, dirNode);
                dirNode = dirNode.NextSibling;
            }
        }
Пример #6
0
        public void FillTreeNodes(TreeNodeCollection nodes, RomfsDir romfsDir)
        {
            RomfsFile fileNode = romfsDir.FirstFile;

            while (fileNode != null)
            {
                var node = new FileNode(fileNode.FullPath, fileNode.Name);
                node.romfs = romfs;

                nodes.Add(node);
                fileNode = fileNode.NextSibling;
            }

            RomfsDir dirNode = romfsDir.FirstChild;

            while (dirNode != null)
            {
                TreeNode newNode = nodes.Add(dirNode.FullPath, dirNode.Name);
                FillTreeNodes(newNode.Nodes, dirNode);
                dirNode = dirNode.NextSibling;
            }
        }
Пример #7
0
        internal static void MakeRomFSData(RomfsFile[] RomFiles, MemoryStream metadata, RichTextBox TB_Progress = null, ProgressBar PB_Show = null)
        {
            updateTB(TB_Progress, "Computing IVFC Header Data...");
            IVFCInfo ivfc = new IVFCInfo {
                Levels = new IVFCLevel[3]
            };

            for (int i = 0; i < ivfc.Levels.Length; i++)
            {
                ivfc.Levels[i] = new IVFCLevel {
                    BlockSize = 0x1000
                };
            }
            ivfc.Levels[2].DataLength = RomfsFile.GetDataBlockLength(RomFiles, (ulong)metadata.Length);
            ivfc.Levels[1].DataLength = Align(ivfc.Levels[2].DataLength, ivfc.Levels[2].BlockSize) / ivfc.Levels[2].BlockSize * 0x20; //0x20 per SHA256 hash
            ivfc.Levels[0].DataLength = Align(ivfc.Levels[1].DataLength, ivfc.Levels[1].BlockSize) / ivfc.Levels[1].BlockSize * 0x20; //0x20 per SHA256 hash
            ulong MasterHashLen = Align(ivfc.Levels[0].DataLength, ivfc.Levels[0].BlockSize) / ivfc.Levels[0].BlockSize * 0x20;
            ulong lofs          = 0;

            foreach (IVFCLevel t in ivfc.Levels)
            {
                t.HashOffset = lofs;
                lofs        += Align(t.DataLength, t.BlockSize);
            }
            const uint IVFC_MAGIC      = 0x43465649; //IVFC
            const uint RESERVED        = 0x0;
            const uint HeaderLen       = 0x5C;
            const uint MEDIA_UNIT_SIZE = 0x200;

            byte[]     SuperBlockHash = new byte[0x20];
            FileStream OutFileStream  = new FileStream(TempFile, FileMode.Create, FileAccess.ReadWrite);

            try
            {
                OutFileStream.Seek(0, SeekOrigin.Begin);
                OutFileStream.Write(BitConverter.GetBytes(IVFC_MAGIC), 0, 0x4);
                OutFileStream.Write(BitConverter.GetBytes(0x10000), 0, 0x4);
                OutFileStream.Write(BitConverter.GetBytes(MasterHashLen), 0, 0x4);
                foreach (IVFCLevel t in ivfc.Levels)
                {
                    OutFileStream.Write(BitConverter.GetBytes(t.HashOffset), 0, 0x8);
                    OutFileStream.Write(BitConverter.GetBytes(t.DataLength), 0, 0x8);
                    OutFileStream.Write(BitConverter.GetBytes((int)Math.Log(t.BlockSize, 2)), 0, 0x4);
                    OutFileStream.Write(BitConverter.GetBytes(RESERVED), 0, 0x4);
                }
                OutFileStream.Write(BitConverter.GetBytes(HeaderLen), 0, 0x4);
                //IVFC Header is Written.
                OutFileStream.Seek((long)Align(MasterHashLen + 0x60, ivfc.Levels[0].BlockSize), SeekOrigin.Begin);
                byte[] metadataArray = metadata.ToArray();
                OutFileStream.Write(metadataArray, 0, metadataArray.Length);
                long baseOfs = OutFileStream.Position;
                updateTB(TB_Progress, "Writing Level 2 Data...");
                if (PB_Show.InvokeRequired)
                {
                    PB_Show.Invoke((MethodInvoker) delegate { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = RomFiles.Length; });
                }
                else
                {
                    PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = RomFiles.Length;
                }

                foreach (RomfsFile t in RomFiles)
                {
                    OutFileStream.Seek(baseOfs + (long)t.Offset, SeekOrigin.Begin);
                    using (FileStream inStream = new FileStream(t.FullName, FileMode.Open, FileAccess.Read))
                    {
                        while (inStream.Position < inStream.Length)
                        {
                            byte[] buffer = new byte[inStream.Length - inStream.Position > 0x100000 ? 0x100000 : inStream.Length - inStream.Position];
                            inStream.Read(buffer, 0, buffer.Length);
                            OutFileStream.Write(buffer, 0, buffer.Length);
                        }
                    }
                    if (PB_Show.InvokeRequired)
                    {
                        PB_Show.Invoke((MethodInvoker)PB_Show.PerformStep);
                    }
                    else
                    {
                        PB_Show.PerformStep();
                    }
                }
                long          hashBaseOfs = (long)Align((ulong)OutFileStream.Position, ivfc.Levels[2].BlockSize);
                long          hOfs        = (long)Align(MasterHashLen, ivfc.Levels[0].BlockSize);
                long          cOfs        = hashBaseOfs + (long)ivfc.Levels[1].HashOffset;
                SHA256Managed sha         = new SHA256Managed();
                for (int i = ivfc.Levels.Length - 1; i >= 0; i--)
                {
                    updateTB(TB_Progress, "Computing Level " + i + " Hashes...");
                    byte[] buffer = new byte[(int)ivfc.Levels[i].BlockSize];

                    var count = (int)(ivfc.Levels[i].DataLength / ivfc.Levels[i].BlockSize);
                    if (PB_Show.InvokeRequired)
                    {
                        PB_Show.Invoke((MethodInvoker) delegate { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = count; });
                    }
                    else
                    {
                        PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = count;
                    }

                    for (long ofs = 0; ofs < (long)ivfc.Levels[i].DataLength; ofs += ivfc.Levels[i].BlockSize)
                    {
                        OutFileStream.Seek(hOfs, SeekOrigin.Begin);
                        OutFileStream.Read(buffer, 0, (int)ivfc.Levels[i].BlockSize);
                        hOfs = OutFileStream.Position;
                        byte[] hash = sha.ComputeHash(buffer);
                        OutFileStream.Seek(cOfs, SeekOrigin.Begin);
                        OutFileStream.Write(hash, 0, hash.Length);
                        cOfs = OutFileStream.Position;
                        if (PB_Show.InvokeRequired)
                        {
                            PB_Show.Invoke((MethodInvoker)PB_Show.PerformStep);
                        }
                        else
                        {
                            PB_Show.PerformStep();
                        }
                    }

                    if (i <= 0)
                    {
                        continue;
                    }

                    if (i == 2)
                    {
                        long len = OutFileStream.Position;
                        if (len % 0x1000 != 0)
                        {
                            len = (long)Align((ulong)len, 0x1000);
                            byte[] buf = new byte[len - OutFileStream.Position];
                            OutFileStream.Write(buf, 0, buf.Length);
                        }
                    }

                    hOfs = hashBaseOfs + (long)ivfc.Levels[i - 1].HashOffset;
                    if (i > 1)
                    {
                        cOfs = hashBaseOfs + (long)ivfc.Levels[i - 2].HashOffset;
                    }
                    else
                    {
                        cOfs = (long)Align(HeaderLen, PADDING_ALIGN);
                    }
                }
                OutFileStream.Seek(0, SeekOrigin.Begin);
                uint   SuperBlockLen = (uint)Align(MasterHashLen + 0x60, MEDIA_UNIT_SIZE);
                byte[] MasterHashes  = new byte[SuperBlockLen];
                OutFileStream.Read(MasterHashes, 0, (int)SuperBlockLen);
                SuperBlockHash = sha.ComputeHash(MasterHashes);
            }
            finally
            {
                OutFileStream.Dispose();
            }

            if (OutFile == TempFile)
            {
                return;
            }
            if (File.Exists(OutFile))
            {
                File.Delete(OutFile);
            }
            File.Move(TempFile, OutFile);
        }
Пример #8
0
 public FileEntry(Romfs romfs, RomfsFile romfsFile)
 {
     ParentROMFS = romfs;
     File        = romfsFile;
     FileName    = $"Romfs/{File.FullPath}";
 }
Пример #9
0
 public static ulong GetDataBlockLength(RomfsFile[] files, ulong PreData)
 {
     return (files.Length == 0) ? PreData : PreData + files[files.Length - 1].Offset + files[files.Length - 1].Size;
 }
Пример #10
0
        internal static void PopulateRomfs(Romfs_MetaData MetaData, RomfsFile[] Entries)
        {
            //Recursively Add All Directories to DirectoryTable
            AddDir(MetaData, new DirectoryInfo(ROOT_DIR), 0, ROMFS_UNUSED_ENTRY);

            //Iteratively Add All Files to FileTable
            AddFiles(MetaData, Entries);

            //Set Weird Offsets, Build HashKeyPointers, Build HashTables
            PopulateHashTables(MetaData);

            //Thats it.
        }
Пример #11
0
        internal static Stream BuildRomFS(string outfile, string infile, string _patchDir)
        {
            OutFile  = outfile;
            ROOT_DIR = infile;
            if (outfile != null)
            {
                if (File.Exists(TempFile))
                {
                    File.Delete(TempFile);
                }
            }

            FileNameTable FNT = new FileNameTable(ROOT_DIR);

            RomfsFile[]           RomFiles = new RomfsFile[FNT.NumFiles];
            LayoutManager.Input[] In       = new LayoutManager.Input[FNT.NumFiles];
            updateTB("Creating Layout...");
            for (int i = 0; i < FNT.NumFiles; i++)
            {
                In[i] = new LayoutManager.Input {
                    FilePath = FNT.NameEntryTable[i].FullName, AlignmentSize = 0x10
                };
            }

            String[] _relativePaths = new String[FNT.NumFiles];
            for (int i = 0; i < _relativePaths.Length; ++i)
            {
                _relativePaths[i] = makePathRelative(In[i].FilePath, ROOT_DIR);
            }

            if (_patchDir != null)
            {
                string[] _altFiles = Directory.GetFiles(_patchDir, "*", SearchOption.AllDirectories);
                for (int i = 0; i < _altFiles.Length; ++i)
                {
                    string _stippedStart = makePathRelative(_altFiles[i], _patchDir);
                    int    j;
                    for (j = 0; j < In.Length; ++j)
                    {
                        if (_relativePaths[j] == _stippedStart)
                        {
                            In[j].FilePath = _altFiles[i];
                            break;
                        }
                    }
                }
            }

            LayoutManager.Output[] Out = LayoutManager.Create(In);
            for (int i = 0; i < Out.Length; i++)
            {
                RomFiles[i] = new RomfsFile
                {
                    Offset       = Out[i].Offset,
                    PathName     = _relativePaths[i],
                    FullName     = FNT.NameEntryTable[i].FullName,
                    realFilePath = In[i].FilePath,
                    Size         = Out[i].Size
                };
            }

            Stream _possibleRetStream;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                updateTB("Creating RomFS MetaData...");
                BuildRomFSHeader(memoryStream, RomFiles, ROOT_DIR);
                _possibleRetStream = MakeRomFSData(RomFiles, memoryStream, outfile != null ? outfile : null);
            }
            if (outfile != null)
            {
                return(null);
            }
            else
            {
                return(_possibleRetStream);
            }
        }
Пример #12
0
        internal static void BuildRomFSHeader(MemoryStream romfs_stream, RomfsFile[] Entries, string DIR)
        {
            ROOT_DIR = DIR;

            Romfs_MetaData MetaData = new Romfs_MetaData();

            InitializeMetaData(MetaData);

            CalcRomfsSize(MetaData);

            PopulateRomfs(MetaData, Entries);

            WriteMetaDataToStream(MetaData, romfs_stream);
        }
Пример #13
0
        internal static void BuildRomFS(string outfile, string infile, RichTextBox TB_Progress = null, ProgressBar PB_Show = null)
        {
            OutFile = outfile;
            ROOT_DIR = infile;
            if (File.Exists(TempFile)) File.Delete(TempFile);

            FileNameTable FNT = new FileNameTable(ROOT_DIR);
            RomfsFile[] RomFiles = new RomfsFile[FNT.NumFiles];
            LayoutManager.Input[] In = new LayoutManager.Input[FNT.NumFiles];
            updateTB(TB_Progress, "Creating Layout...");
            for (int i = 0; i < FNT.NumFiles; i++)
            {
                In[i] = new LayoutManager.Input { FilePath = FNT.NameEntryTable[i].FullName, AlignmentSize = 0x10 };
            }
            LayoutManager.Output[] Out = LayoutManager.Create(In);
            for (int i = 0; i < Out.Length; i++)
            {
                RomFiles[i] = new RomfsFile
                {
                    Offset = Out[i].Offset,
                    PathName = Out[i].FilePath.Replace(Path.GetFullPath(ROOT_DIR), "").Replace("\\", "/"),
                    FullName = Out[i].FilePath,
                    Size = Out[i].Size
                };
            }
            using (MemoryStream memoryStream = new MemoryStream())
            {
                updateTB(TB_Progress, "Creating RomFS MetaData...");
                BuildRomFSHeader(memoryStream, RomFiles, ROOT_DIR);
                MakeRomFSData(RomFiles, memoryStream, TB_Progress, PB_Show);
            }
        }
Пример #14
0
 internal static void AddFiles(Romfs_MetaData MetaData, RomfsFile[] Entries)
 {
     string PrevDirPath = "";
     for (int i = 0; i < Entries.Length; i++)
     {
         FileInfo file = new FileInfo(Entries[i].FullName);
         Romfs_FileEntry Entry = new Romfs_FileEntry();
         string DirPath = Path.GetDirectoryName(Entries[i].FullName);
         int ParentIndex = GetRomfsDirEntry(MetaData, DirPath);
         Entry.FullName = Entries[i].FullName;
         Entry.Offset = MetaData.FileTableLen;
         Entry.ParentDirOffset = MetaData.DirTable.DirectoryTable[ParentIndex].Offset;
         Entry.SiblingOffset = ROMFS_UNUSED_ENTRY;
         if (DirPath == PrevDirPath)
         {
             MetaData.FileTable.FileTable[i - 1].SiblingOffset = Entry.Offset;
         }
         if (MetaData.DirTable.DirectoryTable[ParentIndex].FileOffset == ROMFS_UNUSED_ENTRY)
         {
             MetaData.DirTable.DirectoryTable[ParentIndex].FileOffset = Entry.Offset;
         }
         Entry.HashKeyPointer = ROMFS_UNUSED_ENTRY;
         Entry.NameSize = (uint)file.Name.Length * 2;
         Entry.Name = file.Name;
         Entry.DataOffset = Entries[i].Offset;
         Entry.DataSize = Entries[i].Size;
         MetaData.FileTable.FileTable.Add(Entry);
         MetaData.FileTableLen += 0x20 + (uint)Align((ulong)file.Name.Length * 2, 4);
         PrevDirPath = DirPath;
     }
 }
Пример #15
0
        internal static void MakeRomFSData(RomfsFile[] RomFiles, MemoryStream metadata, RichTextBox TB_Progress = null, ProgressBar PB_Show = null)
        {
            updateTB(TB_Progress, "Computing IVFC Header Data...");
            IVFCInfo ivfc = new IVFCInfo { Levels = new IVFCLevel[3] };
            for (int i = 0; i < ivfc.Levels.Length; i++)
            {
                ivfc.Levels[i] = new IVFCLevel { BlockSize = 0x1000 };
            }
            ivfc.Levels[2].DataLength = RomfsFile.GetDataBlockLength(RomFiles, (ulong)metadata.Length);
            ivfc.Levels[1].DataLength = (Align(ivfc.Levels[2].DataLength, ivfc.Levels[2].BlockSize) / ivfc.Levels[2].BlockSize) * 0x20; //0x20 per SHA256 hash
            ivfc.Levels[0].DataLength = (Align(ivfc.Levels[1].DataLength, ivfc.Levels[1].BlockSize) / ivfc.Levels[1].BlockSize) * 0x20; //0x20 per SHA256 hash
            ulong MasterHashLen = (Align(ivfc.Levels[0].DataLength, ivfc.Levels[0].BlockSize) / ivfc.Levels[0].BlockSize) * 0x20;
            ulong lofs = 0;
            foreach (IVFCLevel t in ivfc.Levels)
            {
                t.HashOffset = lofs;
                lofs += Align(t.DataLength, t.BlockSize);
            }
            const uint IVFC_MAGIC = 0x43465649; //IVFC
            const uint RESERVED = 0x0;
            const uint HeaderLen = 0x5C;
            FileStream OutFileStream = new FileStream(TempFile, FileMode.Create, FileAccess.ReadWrite);
            try
            {
                OutFileStream.Seek(0, SeekOrigin.Begin);
                OutFileStream.Write(BitConverter.GetBytes(IVFC_MAGIC), 0, 0x4);
                OutFileStream.Write(BitConverter.GetBytes(0x10000), 0, 0x4);
                OutFileStream.Write(BitConverter.GetBytes(MasterHashLen), 0, 0x4);
                foreach (IVFCLevel t in ivfc.Levels)
                {
                    OutFileStream.Write(BitConverter.GetBytes(t.HashOffset), 0, 0x8);
                    OutFileStream.Write(BitConverter.GetBytes(t.DataLength), 0, 0x8);
                    OutFileStream.Write(BitConverter.GetBytes((int)(Math.Log(t.BlockSize, 2))), 0, 0x4);
                    OutFileStream.Write(BitConverter.GetBytes(RESERVED), 0, 0x4);
                }
                OutFileStream.Write(BitConverter.GetBytes(HeaderLen), 0, 0x4);
                //IVFC Header is Written.
                OutFileStream.Seek((long)Align(MasterHashLen + 0x60, ivfc.Levels[0].BlockSize), SeekOrigin.Begin);
                byte[] metadataArray = metadata.ToArray();
                OutFileStream.Write(metadataArray, 0, metadataArray.Length);
                long baseOfs = OutFileStream.Position;
                updateTB(TB_Progress, "Writing Level 2 Data...");
                if (PB_Show.InvokeRequired)
                    PB_Show.Invoke((MethodInvoker)delegate { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = RomFiles.Length; });
                else { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = RomFiles.Length; }

                foreach (RomfsFile t in RomFiles)
                {
                    OutFileStream.Seek(baseOfs + (long)t.Offset, SeekOrigin.Begin);
                    using (FileStream inStream = new FileStream(t.FullName, FileMode.Open, FileAccess.Read))
                    {
                        while (inStream.Position < inStream.Length)
                        {
                            byte[] buffer = new byte[inStream.Length - inStream.Position > 0x100000 ? 0x100000 : inStream.Length - inStream.Position];
                            inStream.Read(buffer, 0, buffer.Length);
                            OutFileStream.Write(buffer, 0, buffer.Length);
                        }
                    }
                    if (PB_Show.InvokeRequired)
                        PB_Show.Invoke((MethodInvoker)delegate { PB_Show.PerformStep(); });
                    else { PB_Show.PerformStep(); }
                }
                long hashBaseOfs = (long)Align((ulong)OutFileStream.Position, ivfc.Levels[2].BlockSize);
                long hOfs = (long)Align(MasterHashLen, ivfc.Levels[0].BlockSize);
                long cOfs = hashBaseOfs + (long)ivfc.Levels[1].HashOffset;
                SHA256Managed sha = new SHA256Managed();
                for (int i = ivfc.Levels.Length - 1; i >= 0; i--)
                {
                    updateTB(TB_Progress, "Computing Level " + i + " Hashes...");
                    byte[] buffer = new byte[(int)ivfc.Levels[i].BlockSize];

                    if (PB_Show.InvokeRequired)
                        PB_Show.Invoke((MethodInvoker)delegate { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = (int)(ivfc.Levels[i].DataLength / ivfc.Levels[i].BlockSize); });
                    else { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = (int)(ivfc.Levels[i].DataLength / ivfc.Levels[i].BlockSize); }

                    for (long ofs = 0; ofs < (long)ivfc.Levels[i].DataLength; ofs += ivfc.Levels[i].BlockSize)
                    {
                        OutFileStream.Seek(hOfs, SeekOrigin.Begin);
                        OutFileStream.Read(buffer, 0, (int)ivfc.Levels[i].BlockSize);
                        hOfs = OutFileStream.Position;
                        byte[] hash = sha.ComputeHash(buffer);
                        OutFileStream.Seek(cOfs, SeekOrigin.Begin);
                        OutFileStream.Write(hash, 0, hash.Length);
                        cOfs = OutFileStream.Position;
                        if (PB_Show.InvokeRequired)
                            PB_Show.Invoke((MethodInvoker)delegate { PB_Show.PerformStep(); });
                        else { PB_Show.PerformStep(); }
                    }
                    if (i == 2)
                    {
                        long len = OutFileStream.Position;
                        if (len % 0x1000 != 0)
                        {
                            len = (long)Align((ulong)len, 0x1000);
                            byte[] buf = new byte[len - OutFileStream.Position];
                            OutFileStream.Write(buf, 0, buf.Length);
                        }
                    }
                    if (i <= 0) continue;
                    hOfs = hashBaseOfs + (long)ivfc.Levels[i - 1].HashOffset;
                    if (i > 1)
                        cOfs = hashBaseOfs + (long)ivfc.Levels[i - 2].HashOffset;
                    else
                        cOfs = (long)Align(HeaderLen, PADDING_ALIGN);
                }
            }
            finally
            {
                if (OutFileStream != null)
                    OutFileStream.Dispose();
            }
            if (OutFile != TempFile)
            {
                if (File.Exists(OutFile)) File.Delete(OutFile);
                File.Move(TempFile, OutFile);
            }
        }
Пример #16
0
        internal static void MakeRomFSData(RomfsFile[] romFiles, MemoryStream metadata)
        {
            IvfcInfo ivfc = new IvfcInfo {
                Levels = new IvfcLevel[3]
            };

            for (int i = 0; i < ivfc.Levels.Length; i++)
            {
                ivfc.Levels[i] = new IvfcLevel {
                    BlockSize = 0x1000
                };
            }
            ivfc.Levels[2].DataLength = RomfsFile.GetDataBlockLength(romFiles, (ulong)metadata.Length);
            ivfc.Levels[1].DataLength = RomFS.Align(ivfc.Levels[2].DataLength, ivfc.Levels[2].BlockSize) / ivfc.Levels[2].BlockSize * 0x20;                       //0x20 per SHA256 hash
            ivfc.Levels[0].DataLength = RomFS.Align(ivfc.Levels[1].DataLength, ivfc.Levels[1].BlockSize) / ivfc.Levels[1].BlockSize * 0x20;                       //0x20 per SHA256 hash
            ulong masterHashLen = RomFS.Align(ivfc.Levels[0].DataLength, ivfc.Levels[0].BlockSize) / ivfc.Levels[0].BlockSize * 0x20;
            ulong lofs          = 0;

            foreach (IvfcLevel t in ivfc.Levels)
            {
                t.HashOffset = lofs;
                lofs        += RomFS.Align(t.DataLength, t.BlockSize);
            }
            const uint ivfcMagic     = 0x43465649;         //IVFC
            const uint reserved      = 0x0;
            const uint headerLen     = 0x5C;
            const uint mediaUnitSize = 0x200;
            FileStream outFileStream = new FileStream(TempFile, FileMode.Create, FileAccess.ReadWrite);

            try
            {
                outFileStream.Seek(0, SeekOrigin.Begin);
                outFileStream.Write(BitConverter.GetBytes(ivfcMagic), 0, 0x4);
                outFileStream.Write(BitConverter.GetBytes(0x10000), 0, 0x4);
                outFileStream.Write(BitConverter.GetBytes(masterHashLen), 0, 0x4);
                foreach (IvfcLevel t in ivfc.Levels)
                {
                    outFileStream.Write(BitConverter.GetBytes(t.HashOffset), 0, 0x8);
                    outFileStream.Write(BitConverter.GetBytes(t.DataLength), 0, 0x8);
                    outFileStream.Write(BitConverter.GetBytes((int)Math.Log(t.BlockSize, 2)), 0, 0x4);
                    outFileStream.Write(BitConverter.GetBytes(reserved), 0, 0x4);
                }
                outFileStream.Write(BitConverter.GetBytes(headerLen), 0, 0x4);
                //IVFC Header is Written.
                outFileStream.Seek((long)RomFS.Align(masterHashLen + 0x60, ivfc.Levels[0].BlockSize), SeekOrigin.Begin);
                byte[] metadataArray = metadata.ToArray();
                outFileStream.Write(metadataArray, 0, metadataArray.Length);
                long baseOfs = outFileStream.Position;

                foreach (RomfsFile t in romFiles)
                {
                    outFileStream.Seek(baseOfs + (long)t.Offset, SeekOrigin.Begin);
                    using (FileStream inStream = new FileStream(t.FullName, FileMode.Open, FileAccess.Read))
                    {
                        while (inStream.Position < inStream.Length)
                        {
                            byte[] buffer = new byte[inStream.Length - inStream.Position > 0x100000
                                                                                                                  ? 0x100000
                                                                                                                  : inStream.Length - inStream.Position];
                            inStream.Read(buffer, 0, buffer.Length);
                            outFileStream.Write(buffer, 0, buffer.Length);
                        }
                    }
                }
                long          hashBaseOfs = (long)RomFS.Align((ulong)outFileStream.Position, ivfc.Levels[2].BlockSize);
                long          hOfs        = (long)RomFS.Align(masterHashLen, ivfc.Levels[0].BlockSize);
                long          cOfs        = hashBaseOfs + (long)ivfc.Levels[1].HashOffset;
                SHA256Managed sha         = new SHA256Managed();
                for (int i = ivfc.Levels.Length - 1; i >= 0; i--)
                {
                    byte[] buffer = new byte[(int)ivfc.Levels[i].BlockSize];

                    for (long ofs = 0; ofs < (long)ivfc.Levels[i].DataLength; ofs += ivfc.Levels[i].BlockSize)
                    {
                        outFileStream.Seek(hOfs, SeekOrigin.Begin);
                        outFileStream.Read(buffer, 0, (int)ivfc.Levels[i].BlockSize);
                        hOfs = outFileStream.Position;
                        byte[] hash = sha.ComputeHash(buffer);
                        outFileStream.Seek(cOfs, SeekOrigin.Begin);
                        outFileStream.Write(hash, 0, hash.Length);
                        cOfs = outFileStream.Position;
                    }

                    if (i <= 0)
                    {
                        continue;
                    }

                    if (i == 2)
                    {
                        long len = outFileStream.Position;
                        if (len % 0x1000 != 0)
                        {
                            len = (long)RomFS.Align((ulong)len, 0x1000);
                            byte[] buf = new byte[len - outFileStream.Position];
                            outFileStream.Write(buf, 0, buf.Length);
                        }
                    }

                    hOfs = hashBaseOfs + (long)ivfc.Levels[i - 1].HashOffset;
                    if (i > 1)
                    {
                        cOfs = hashBaseOfs + (long)ivfc.Levels[i - 2].HashOffset;
                    }
                    else
                    {
                        cOfs = (long)RomFS.Align(headerLen, PaddingAlign);
                    }
                }
                outFileStream.Seek(0, SeekOrigin.Begin);
                uint   superBlockLen = (uint)RomFS.Align(masterHashLen + 0x60, mediaUnitSize);
                byte[] masterHashes  = new byte[superBlockLen];
                outFileStream.Read(masterHashes, 0, (int)superBlockLen);
                sha.ComputeHash(masterHashes);
            }
            finally
            {
                outFileStream.Dispose();
            }

            if (OutFile == TempFile)
            {
                return;
            }
            if (File.Exists(OutFile))
            {
                File.Delete(OutFile);
            }
            File.Move(TempFile, OutFile);
        }
Пример #17
0
        internal static Stream MakeRomFSData(RomfsFile[] RomFiles, MemoryStream metadata, string _writeDest)
        {
            updateTB("Computing IVFC Header Data...");
            IVFCInfo ivfc = new IVFCInfo {
                Levels = new IVFCLevel[3]
            };

            for (int i = 0; i < ivfc.Levels.Length; i++)
            {
                ivfc.Levels[i] = new IVFCLevel {
                    BlockSize = 0x1000
                };
            }
            ivfc.Levels[2].DataLength = RomfsFile.GetDataBlockLength(RomFiles, (ulong)metadata.Length);
            ivfc.Levels[1].DataLength = (Align(ivfc.Levels[2].DataLength, ivfc.Levels[2].BlockSize) / ivfc.Levels[2].BlockSize) * 0x20; //0x20 per SHA256 hash
            ivfc.Levels[0].DataLength = (Align(ivfc.Levels[1].DataLength, ivfc.Levels[1].BlockSize) / ivfc.Levels[1].BlockSize) * 0x20; //0x20 per SHA256 hash
            ulong MasterHashLen = (Align(ivfc.Levels[0].DataLength, ivfc.Levels[0].BlockSize) / ivfc.Levels[0].BlockSize) * 0x20;
            ulong lofs          = 0;

            foreach (IVFCLevel t in ivfc.Levels)
            {
                t.HashOffset = lofs;
                lofs        += Align(t.DataLength, t.BlockSize);
            }
            const uint IVFC_MAGIC = 0x43465649; //IVFC
            const uint RESERVED   = 0x0;
            const uint HeaderLen  = 0x5C;
            Stream     OutFileStream;

            if (_writeDest != null)
            {
                OutFileStream = new FileStream(TempFile, FileMode.Create, FileAccess.ReadWrite);
            }
            else
            {
                OutFileStream = new MemoryStream();
            }
            try
            {
                OutFileStream.Seek(0, SeekOrigin.Begin);
                OutFileStream.Write(BitConverter.GetBytes(IVFC_MAGIC), 0, 0x4);
                OutFileStream.Write(BitConverter.GetBytes(0x10000), 0, 0x4);
                OutFileStream.Write(BitConverter.GetBytes(MasterHashLen), 0, 0x4);
                foreach (IVFCLevel t in ivfc.Levels)
                {
                    OutFileStream.Write(BitConverter.GetBytes(t.HashOffset), 0, 0x8);
                    OutFileStream.Write(BitConverter.GetBytes(t.DataLength), 0, 0x8);
                    OutFileStream.Write(BitConverter.GetBytes((int)(Math.Log(t.BlockSize, 2))), 0, 0x4);
                    OutFileStream.Write(BitConverter.GetBytes(RESERVED), 0, 0x4);
                }
                OutFileStream.Write(BitConverter.GetBytes(HeaderLen), 0, 0x4);
                //IVFC Header is Written.
                OutFileStream.Seek((long)Align(MasterHashLen + 0x60, ivfc.Levels[0].BlockSize), SeekOrigin.Begin);
                byte[] metadataArray = metadata.ToArray();
                OutFileStream.Write(metadataArray, 0, metadataArray.Length);
                long baseOfs = OutFileStream.Position;
                updateTB("Writing Level 2 Data...");

                foreach (RomfsFile t in RomFiles)
                {
                    OutFileStream.Seek(baseOfs + (long)t.Offset, SeekOrigin.Begin);
                    using (FileStream inStream = new FileStream(t.realFilePath, FileMode.Open, FileAccess.Read))
                    {
                        while (inStream.Position < inStream.Length)
                        {
                            byte[] buffer = new byte[inStream.Length - inStream.Position > 0x100000 ? 0x100000 : inStream.Length - inStream.Position];
                            inStream.Read(buffer, 0, buffer.Length);
                            OutFileStream.Write(buffer, 0, buffer.Length);
                        }
                    }
                }
                long          hashBaseOfs = (long)Align((ulong)OutFileStream.Position, ivfc.Levels[2].BlockSize);
                long          hOfs        = (long)Align(MasterHashLen, ivfc.Levels[0].BlockSize);
                long          cOfs        = hashBaseOfs + (long)ivfc.Levels[1].HashOffset;
                SHA256Managed sha         = new SHA256Managed();
                for (int i = ivfc.Levels.Length - 1; i >= 0; i--)
                {
                    updateTB("Computing Level " + i + " Hashes...");
                    byte[] buffer = new byte[(int)ivfc.Levels[i].BlockSize];

                    for (long ofs = 0; ofs < (long)ivfc.Levels[i].DataLength; ofs += ivfc.Levels[i].BlockSize)
                    {
                        OutFileStream.Seek(hOfs, SeekOrigin.Begin);
                        OutFileStream.Read(buffer, 0, (int)ivfc.Levels[i].BlockSize);
                        hOfs = OutFileStream.Position;
                        byte[] hash = sha.ComputeHash(buffer);
                        OutFileStream.Seek(cOfs, SeekOrigin.Begin);
                        OutFileStream.Write(hash, 0, hash.Length);
                        cOfs = OutFileStream.Position;
                    }
                    if (i == 2)
                    {
                        long len = OutFileStream.Position;
                        if (len % 0x1000 != 0)
                        {
                            len = (long)Align((ulong)len, 0x1000);
                            byte[] buf = new byte[len - OutFileStream.Position];
                            OutFileStream.Write(buf, 0, buf.Length);
                        }
                    }
                    if (i <= 0)
                    {
                        continue;
                    }
                    hOfs = hashBaseOfs + (long)ivfc.Levels[i - 1].HashOffset;
                    if (i > 1)
                    {
                        cOfs = hashBaseOfs + (long)ivfc.Levels[i - 2].HashOffset;
                    }
                    else
                    {
                        cOfs = (long)Align(HeaderLen, PADDING_ALIGN);
                    }
                }
            }
            finally
            {
                if (OutFileStream != null && _writeDest != null)
                {
                    OutFileStream.Dispose();
                }
            }
            if (_writeDest != null)
            {
                OutFileStream.Dispose();
                if (_writeDest != TempFile)
                {
                    if (File.Exists(OutFile))
                    {
                        File.Delete(OutFile);
                    }
                    File.Move(TempFile, OutFile);
                }
                return(null);
            }
            else
            {
                return(OutFileStream);
            }
        }