public static long CalculateRomFsSize(IList <IArchiveFileInfo> files, UPath rootDirectory) { var rootNode = RomFsDirectoryNode.Parse(files, rootDirectory); long totalSize = BlockSize_; // Calculate meta size totalSize += GetHashTableEntryCount(rootNode.DirectoryCount) * 4; totalSize += GetHashTableEntryCount(files.Count) * 4; totalSize += rootNode.SizeInBytes; totalSize += files.Sum(x => MetaData.FileEntry.Size + ((Encoding.Unicode.GetByteCount(x.FilePath.GetName()) + 3) & ~3)); // Calculate file size totalSize = (totalSize + 0xF) & ~0xF; totalSize += files.Sum(x => (x.FileSize + 0xF) & ~0xF); totalSize = (totalSize + BlockSize_ - 1) & ~(BlockSize_ - 1); // Calculate hash level sizes var levelSize = totalSize - BlockSize_; for (var i = 0; i < 2; i++) { var currentLevelSize = levelSize / BlockSize_ * 0x20; currentLevelSize = (currentLevelSize + BlockSize_ - 1) & ~(BlockSize_ - 1); totalSize += currentLevelSize; levelSize = currentLevelSize; } return(totalSize); }
public static (long, long) Build(Stream input, IList <IArchiveFileInfo> files, UPath rootDirectory) { // Parse files into file tree var rootNode = RomFsDirectoryNode.Parse(files, rootDirectory); // Create MetaData Tree var metaData = new MetaData { DirMetaOffset = rootNode.Directories.Count <= 0 ? UnusedEntry_ : 0x18 }; metaData.Dirs.Add(new MetaData.DirEntry { MetaOffset = 0, ParentOffset = 0, NextSiblingOffset = UnusedEntry_, FirstChildOffset = rootNode.Directories.Count <= 0 ? UnusedEntry_ : 0x18, FirstFileOffset = 0, NextDirInSameBucket = UnusedEntry_, Hash = CalculatePathHash(0, Encoding.Unicode.GetBytes(string.Empty)), Name = string.Empty }); PopulateMetaData(metaData, rootNode, metaData.Dirs[0]); // Creating directory hash buckets metaData.DirHashTable = Enumerable.Repeat(0xFFFFFFFF, GetHashTableEntryCount(metaData.Dirs.Count)).ToArray(); PopulateDirHashTable(metaData.Dirs, metaData.DirHashTable); // Creating file hash buckets metaData.FileHashTable = Enumerable.Repeat(0xFFFFFFFF, GetHashTableEntryCount(metaData.Files.Count)).ToArray(); PopulateFileHashTable(metaData.Files, metaData.FileHashTable); // Write RomFs var romFsSizes = WriteRomFs(input, metaData); return(romFsSizes); }