public NintendoContentArchiveSource(NintendoContentFileSystemInfo fileSystemInfo, KeyConfiguration config, bool needsLogoPartition = false) { this.m_fileSystemInfo = fileSystemInfo; this.m_keyConfig = config; this.SetCryptor(this.m_keyConfig); this.AddDefaultLogoPartitionIfNeeded(needsLogoPartition); fileSystemInfo.fsEntries.Sort((Comparison <NintendoContentFileSystemInfo.EntryInfo>)((x, y) => x.partitionIndex.CompareTo(y.partitionIndex))); NintendoContentFileSystemMeta meta = new NintendoContentFileSystemMeta(); NintendoContentFileSystemEntryInfoContainer fsEntries = new NintendoContentFileSystemEntryInfoContainer(fileSystemInfo.fsEntries); List <ConcatenatedSource.Element> elements1 = new List <ConcatenatedSource.Element>(); NintendoContentArchiveSource.BodySourceElement[] bodySources = new NintendoContentArchiveSource.BodySourceElement[fileSystemInfo.fsEntries.Count]; long offset = (long)meta.GetFsHeaderSize() * 4L; foreach (NintendoContentFileSystemInfo.EntryInfo entryInfo in fsEntries) { if (entryInfo.type != null) { ISource source = NintendoContentArchiveSource.GetDataSource(entryInfo); if (fileSystemInfo.isProdEncryption && fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 0) { source = this.AcidResignedSource(source); } if (fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 1) { source = this.NrrSignedSource(source); } int currentIndex = fsEntries.CurrentIndex; bodySources[currentIndex].DataOffset = offset; NintendoContentArchiveSource.BuildDataInfo buildInfo = new NintendoContentArchiveSource.BuildDataInfo(meta, source, offset, currentIndex); fileSystemInfo.fsEntries[currentIndex] = this.BuildData(entryInfo, buildInfo); offset = buildInfo.CurrentOffset; Sha256HierarchicalHashCalculatedSource calculatedSource = new Sha256HierarchicalHashCalculatedSource(buildInfo.HeaderSource, (int)buildInfo.HeaderSource.Size, 1); ConcatenatedSource.Element element1 = new ConcatenatedSource.Element(calculatedSource.GetMasterHashSource(), "fsHeaderHash" + (object)currentIndex, (long)(32 * currentIndex)); elements1.Add(element1); ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource)calculatedSource, "fsHeader" + (object)currentIndex, (long)currentIndex * (long)meta.GetFsHeaderSize()); bodySources[currentIndex].HeaderElement = element2; bodySources[currentIndex].DataSourceElements = buildInfo.DataSourceElements; } } if (fsEntries.IsReverse) { elements1.Reverse(); } NintendoContentArchiveSource.BodyEncryptionKey bodyEncryptionKey = new NintendoContentArchiveSource.BodyEncryptionKey(fileSystemInfo); this.MakeBody(meta, fsEntries, bodySources, bodyEncryptionKey); this.MakeNcaHeader(meta, (ISource) new ConcatenatedSource(elements1), bodyEncryptionKey); List <ConcatenatedSource.Element> elements2 = new List <ConcatenatedSource.Element>(); ConcatenatedSource.Element element3 = new ConcatenatedSource.Element(this.m_headerSource, "header", 0L); ConcatenatedSource.Element element4 = new ConcatenatedSource.Element(this.m_bodySource, "body", element3.Source.Size); elements2.Add(element3); elements2.Add(element4); this.m_source = (ISource) new ConcatenatedSource(elements2); this.Size = this.m_source.Size; }
private NintendoContentFileSystemInfo.EntryInfo BuildData(NintendoContentFileSystemInfo.EntryInfo entryInfo, NintendoContentArchiveSource.BuildDataInfo buildInfo) { entryInfo.hashType = NintendoContentArchiveSource.VerifyHashType(this.m_fileSystemInfo, entryInfo); entryInfo.encryptionType = NintendoContentArchiveSource.VerifyEncryptionType(this.m_fileSystemInfo, entryInfo); entryInfo.startOffset = (ulong)buildInfo.CurrentOffset + buildInfo.Meta.GetHeaderSize(); entryInfo.hashTargetSize = (ulong)buildInfo.DataSource.Size; IHierarchicalHashCalculatedSource calculatedSource; switch (entryInfo.hashType) { case 2: calculatedSource = (IHierarchicalHashCalculatedSource) new Sha256HierarchicalHashCalculatedSource(buildInfo.DataSource, buildInfo.Meta.GetHashBlockSize((ValueType)entryInfo), 2); break; case 3: calculatedSource = (IHierarchicalHashCalculatedSource) new IntegrityHierarchicalHashCalculatedSource(buildInfo.DataSource); break; default: throw new NotImplementedException(); } long offset1 = 0; ISource layerHashSource = calculatedSource.GetLayerHashSource(); entryInfo.hashDataSize = (ulong)layerHashSource.Size; ConcatenatedSource.Element element1 = new ConcatenatedSource.Element(layerHashSource, "fsHash" + (object)buildInfo.Index, offset1); buildInfo.DataSourceElements.Add(element1); long offset2 = offset1 + element1.Source.Size; int num1 = (int)(offset2 % 512L); if (0 < num1) { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource) new PaddingSource((long)(512 - num1)), "fsHashPadding" + (object)buildInfo.Index, offset2); buildInfo.DataSourceElements.Add(element2); offset2 += element2.Source.Size; } entryInfo.hashTargetOffset = (ulong)offset2; ConcatenatedSource.Element element3 = new ConcatenatedSource.Element((ISource)calculatedSource, "fsData" + (object)buildInfo.Index, offset2); buildInfo.DataSourceElements.Add(element3); long offset3 = offset2 + element3.Source.Size; int num2 = (int)(offset3 % 512L); if (0 < num2) { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource) new PaddingSource((long)(512 - num2)), "fsDataPadding" + (object)buildInfo.Index, offset3); buildInfo.DataSourceElements.Add(element2); offset3 += element2.Source.Size; } buildInfo.CurrentOffset += offset3; entryInfo.endOffset = (ulong)buildInfo.CurrentOffset + buildInfo.Meta.GetHeaderSize(); buildInfo.HeaderSource = calculatedSource.GetFsHeaderSource(entryInfo); return(entryInfo); }