public NcchRomFs(Stream instream) { using var br = new BinaryReaderX(instream, true); // Read header var romFsOffset = br.BaseStream.Position; header = br.ReadType <NcchRomFsHeader>(); masterHash = br.ReadBytes(header.masterHashSize); // Read Level 3 lv3Offset = romFsOffset + 0x1000; br.BaseStream.Position = lv3Offset; lv3Header = br.ReadType <NcchRomFsLevelHeader>(); // Resolve file and directory tree br.BaseStream.Position = lv3Offset + lv3Header.dirMetaTableOffset; Files = new List <FinalFileInfo>(); ResolveDirectories(br); }
/// <summary> /// Write meta data tree. /// </summary> /// <param name="output">The stream to write to.</param> /// <param name="metaData">The meta data tree to write.</param> /// <returns>The size of the written meta data.</returns> private static long WriteMetaData(Stream output, MetaData metaData) { var startPosition = output.Position; using var bw = new BinaryWriterX(output, true); var header = new NcchRomFsLevelHeader { headerLength = 0x28, dirHashTableOffset = 0x28, dirHashTableSize = metaData.DirHashTable.Length * sizeof(uint), dirMetaTableSize = metaData.Dirs.Sum(dir => dir.GetSize(4)), fileHashTableSize = metaData.FileHashTable.Length * sizeof(uint), fileMetaTableSize = metaData.Files.Sum(file => file.GetSize(4)), }; bw.BaseStream.Position = startPosition + 0x28; // Write directory hash table foreach (var hash in metaData.DirHashTable) { bw.Write(hash); } // Write directory entries header.dirMetaTableOffset = (int)(bw.BaseStream.Position - startPosition); foreach (var dir in metaData.Dirs) { bw.Write(dir.ParentOffset); bw.Write(dir.NextSiblingOffset); bw.Write(dir.FirstChildOffset); bw.Write(dir.FirstFileOffset); bw.Write(dir.NextDirInSameBucket ?? UnusedEntry_); bw.Write(Encoding.Unicode.GetByteCount(dir.Name)); bw.Write(Encoding.Unicode.GetBytes(dir.Name)); bw.WriteAlignment(4); } // Write file hash table header.fileHashTableOffset = (int)(bw.BaseStream.Position - startPosition); foreach (var hash in metaData.FileHashTable) { bw.Write(hash); } // Write file entries header.fileMetaTableOffset = (int)(bw.BaseStream.Position - startPosition); foreach (var file in metaData.Files) { bw.Write(file.ParentDirOffset); bw.Write(file.NextSiblingOffset); bw.Write(file.DataOffset); bw.Write(file.DataSize); bw.Write(file.NextFileInSameBucket ?? UnusedEntry_); bw.Write(Encoding.Unicode.GetByteCount(file.Name)); bw.Write(Encoding.Unicode.GetBytes(file.Name)); bw.WriteAlignment(4); } // Write files header.fileDataOffset = (int)((bw.BaseStream.Position - startPosition + 0xF) & ~0xF); foreach (var file in metaData.Files) { bw.WriteAlignment(); file.FileData.CopyTo(bw.BaseStream); } var level3Size = bw.BaseStream.Position - startPosition; bw.WriteAlignment(BlockSize_); bw.BaseStream.Position = startPosition; bw.WriteType(header); return(level3Size); }