public void Extract(ref Dictionary <string, FileStream> streamCache, string destinationFolder, bool extractAsRaw) { string destinationFile = Path.Combine(Path.Combine(destinationFolder, this.ParentDirectoryName), this.FileName); byte[] magicBytes; if (!streamCache.ContainsKey(this.SourceFilePath)) { streamCache[this.SourceFilePath] = File.OpenRead(this.SourceFilePath); } // check for CRILAYLA signature since file size is not always reliable, // this will be a little slower, but hopefully the stream caching will minimize // the impact magicBytes = ParseFile.ParseSimpleOffset(streamCache[this.SourceFilePath], (long)this.Offset, CriCpkArchive.CRILAYLA_SIGNATURE.Length); if (ParseFile.CompareSegment(magicBytes, 0, CriCpkArchive.CRILAYLA_SIGNATURE)) { CriCpkArchive.Uncompress(streamCache[this.SourceFilePath], (long)this.Offset, this.Size, destinationFile); } else { ParseFile.ExtractChunkToFile64(streamCache[this.SourceFilePath], (ulong)this.Offset, (ulong)this.Size, destinationFile, false, false); } }
// @TODO: Need to update this for Internal/External CPK protected void ExtractAwbWithCueNames(string destinationFolder, AwbToExtract whichAwb) { CriUtfTable waveformTableUtf; byte encodeType; string rawFileName; CriAfs2Archive awb; string rawFileFormat = "{0}_{1}{2}"; if (whichAwb == AwbToExtract.Internal) { awb = this.InternalAwb; } else { awb = this.ExternalAwb; } using (FileStream fs = File.Open(awb.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { // use files names for internal AWB foreach (string key in this.CueNamesToWaveforms.Keys) { // extract file ParseFile.ExtractChunkToFile64(fs, (ulong)awb.Files[this.CueNamesToWaveforms[key]].FileOffsetByteAligned, (ulong)awb.Files[this.CueNamesToWaveforms[key]].FileLength, Path.Combine(destinationFolder, FileUtil.CleanFileName(key)), false, false); } //------------------------------------- // extract any items without a CueName //------------------------------------- using (FileStream acbStream = File.Open(this.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { waveformTableUtf = new CriUtfTable(); waveformTableUtf.Initialize(acbStream, (long)this.WaveformTableOffset); } // get list of unextracted files var unextractedFiles = awb.Files.Keys.Where(x => !this.CueNamesToWaveforms.ContainsValue(x)); foreach (ushort key in unextractedFiles) { encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, key, "EncodeType"); rawFileName = String.Format(rawFileFormat, Path.GetFileNameWithoutExtension(awb.SourceFile), key.ToString("D5"), CriAcbFile.GetFileExtensionForEncodeType(encodeType)); // extract file ParseFile.ExtractChunkToFile64(fs, (ulong)awb.Files[key].FileOffsetByteAligned, (ulong)awb.Files[key].FileLength, Path.Combine(destinationFolder, rawFileName), false, false); } } }
public string WriteTableToTempFile(FileStream fs, long offsetToUtfTable, int?maxTableSize = null) { string pathToUtf = null; int totalBytesRead = 0; int maxRead; byte[] buffer = new byte[Constants.FileReadChunkSize]; int tableSize; if (maxTableSize != null) // typically used for isUtf function { tableSize = (int)maxTableSize; } else { tableSize = (int)this.UtfReader.ReadUint(fs, offsetToUtfTable, 4) + 8; } pathToUtf = Path.Combine(Path.GetTempPath(), TEMP_UTF_TABLE_FILE); if (this.IsEncrypted) { using (FileStream tempStream = File.Open(pathToUtf, FileMode.Create, FileAccess.Write, FileShare.Read)) { while (totalBytesRead < tableSize) { if ((tableSize - totalBytesRead) > buffer.Length) { maxRead = buffer.Length; } else { maxRead = (tableSize - totalBytesRead); } buffer = this.UtfReader.GetBytes(fs, offsetToUtfTable, maxRead, totalBytesRead); tempStream.Write(buffer, 0, maxRead); totalBytesRead += maxRead; } } } else { if (File.Exists(pathToUtf)) { File.Delete(pathToUtf); } ParseFile.ExtractChunkToFile64(fs, (ulong)offsetToUtfTable, (ulong)tableSize, pathToUtf, false, false); } return(pathToUtf); }
public void ExtractAllRaw(string destinationFolder) { string rawFileFormat = "{0}.{1}.bin"; using (FileStream fs = File.Open(this.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { foreach (ushort key in this.Files.Keys) { ParseFile.ExtractChunkToFile64(fs, (ulong)this.Files[key].FileOffsetByteAligned, (ulong)this.Files[key].FileLength, Path.Combine(destinationFolder, String.Format(rawFileFormat, Path.GetFileName(this.SourceFile), key.ToString("D5"))), false, false); } } }
public static string[] SplitFile(string sourceFile, long startingOffset, ulong chunkSizeInBytes, string outputFolder) { string[] outputFileList; string outputFileName; var outputFiles = new ArrayList(); long fileLength; ulong currentOffset; int chunkCount; using (var sourceStream = File.OpenRead(sourceFile)) { // get file length fileLength = sourceStream.Length; // init counters chunkCount = 1; currentOffset = (ulong)startingOffset; while (currentOffset < (ulong)fileLength) { // construct output file name outputFileName = Path.Combine(outputFolder, string.Format("{0}.{1}", Path.GetFileName(sourceFile), chunkCount.ToString("D3"))); ParseFile.ExtractChunkToFile64(sourceStream, currentOffset, chunkSizeInBytes, outputFileName, true, true); outputFiles.Add(outputFileName); currentOffset += chunkSizeInBytes; chunkCount++; } } outputFileList = (string[])outputFiles.ToArray(typeof(string)); return(outputFileList); }
public void Extract(ref Dictionary <string, FileStream> streamCache, string destinationFolder, bool extractAsRaw) { string destinationFile = Path.Combine(Path.Combine(destinationFolder, this.ParentDirectoryName), this.FileName); if (!streamCache.ContainsKey(this.SourceFilePath)) { streamCache[this.SourceFilePath] = File.OpenRead(this.SourceFilePath); } //----------------------------------------------------------- // ExeFS //----------------------------------------------------------- if (this.FileSystem == Nintendo3dsCtr.FileSystemType.ExeFS) { // write file while calculating hash HashAlgorithm cryptoHash = SHA256.Create(); byte[] outputHash = ParseFile.ExtractChunkToFile64ReturningHash(streamCache[this.SourceFilePath], (ulong)this.Offset, (ulong)this.Size, destinationFile, cryptoHash, false, false); if (!ParseFile.CompareSegment(outputHash, 0, this.Sha256Hash)) { // @TODO: only show error once per file //if (!sha1ErrorDisplayed) { MessageBox.Show(String.Format("Warning: '{0},' failed SHA256 verification in ExeFS at offset 0x{1} during extraction.{2}", Path.GetFileName(destinationFile), this.Offset, Environment.NewLine), "Warning - SHA256 Failure"); } } } //--------------- // RomFS //--------------- else { // @TODO: Modify to verify on extraction ParseFile.ExtractChunkToFile64(streamCache[this.SourceFilePath], (ulong)this.Offset, (ulong)this.Size, destinationFile, false, false); } }
protected void ExtractAllUsingCueList(string destinationFolder) { CriUtfTable waveformTableUtf; ushort waveformIndex; byte encodeType; string rawFileName; string rawFileFormat = "{0}.{1}{2}"; FileStream internalFs = null; FileStream externalFs = null; ArrayList internalIdsExtracted = new ArrayList(); ArrayList externalIdsExtracted = new ArrayList(); string acbAwbDestinationFolder = Path.Combine(destinationFolder, ACB_AWB_EXTRACTION_FOLDER); string extAwbDestinationFolder = Path.Combine(destinationFolder, EXT_AWB_EXTRACTION_FOLDER); string acbCpkDestinationFolder = Path.Combine(destinationFolder, ACB_CPK_EXTRACTION_FOLDER); string extCpkDestinationFolder = Path.Combine(destinationFolder, EXT_CPK_EXTRACTION_FOLDER); try { // open streams if (this.InternalAwb != null) { internalFs = File.Open(this.InternalAwb.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read); } else if (this.InternalCpk != null) { internalFs = File.Open(this.InternalCpk.SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read); } if (this.ExternalAwb != null) { externalFs = File.Open(this.ExternalAwb.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read); } else if (this.ExternalCpk != null) { externalFs = File.Open(this.ExternalCpk.SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read); } // loop through cues and extract for (int i = 0; i < CueList.Length; i++) { CriAcbCueRecord cue = CueList[i]; if (cue.IsWaveformIdentified) { if (cue.IsStreaming) // external AWB file { if (this.ExternalAwb != null) { ParseFile.ExtractChunkToFile64(externalFs, (ulong)this.ExternalAwb.Files[cue.WaveformId].FileOffsetByteAligned, (ulong)this.ExternalAwb.Files[cue.WaveformId].FileLength, Path.Combine(extAwbDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false); } else if (this.ExternalCpk != null) { ParseFile.ExtractChunkToFile64(externalFs, (ulong)this.ExternalCpk.ItocFiles[cue.WaveformId].FileOffsetByteAligned, (ulong)this.ExternalCpk.ItocFiles[cue.WaveformId].FileLength, Path.Combine(extCpkDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false); } externalIdsExtracted.Add(cue.WaveformId); } else // internal AWB file (inside ACB) { if (this.InternalAwb != null) { ParseFile.ExtractChunkToFile64(internalFs, (ulong)this.InternalAwb.Files[cue.WaveformId].FileOffsetByteAligned, (ulong)this.InternalAwb.Files[cue.WaveformId].FileLength, Path.Combine(acbAwbDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false); } else if (this.InternalCpk != null) { ParseFile.ExtractChunkToFile64(internalFs, (ulong)this.InternalCpk.ItocFiles[cue.WaveformId].FileOffsetByteAligned, (ulong)this.InternalCpk.ItocFiles[cue.WaveformId].FileLength, Path.Combine(acbCpkDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false); } internalIdsExtracted.Add(cue.WaveformId); } } // if (cue.IsWaveformIdentified) } // extract leftovers using (FileStream acbStream = File.Open(this.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { waveformTableUtf = new CriUtfTable(); waveformTableUtf.Initialize(acbStream, (long)this.WaveformTableOffset); } if (this.ExternalAwb != null) { var unextractedExternalFiles = this.ExternalAwb.Files.Keys.Where(x => !externalIdsExtracted.Contains(x)); foreach (ushort key in unextractedExternalFiles) { waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, true); encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType"); rawFileName = String.Format(rawFileFormat, Path.GetFileName(this.ExternalAwb.SourceFile), key.ToString("D5"), CriAcbFile.GetFileExtensionForEncodeType(encodeType)); // extract file ParseFile.ExtractChunkToFile64(externalFs, (ulong)this.ExternalAwb.Files[key].FileOffsetByteAligned, (ulong)this.ExternalAwb.Files[key].FileLength, Path.Combine(extAwbDestinationFolder, rawFileName), false, false); } } else if (this.ExternalCpk != null) { var unextractedExternalFiles = this.ExternalCpk.ItocFiles.Keys.Where(x => !externalIdsExtracted.Contains(x)); foreach (ushort key in unextractedExternalFiles) { waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, true); encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType"); rawFileName = String.Format(rawFileFormat, Path.GetFileName(this.ExternalCpk.SourceFileName), key.ToString("D5"), CriAcbFile.GetFileExtensionForEncodeType(encodeType)); // extract file ParseFile.ExtractChunkToFile64(externalFs, (ulong)this.ExternalCpk.ItocFiles[key].FileOffsetByteAligned, (ulong)this.ExternalCpk.ItocFiles[key].FileLength, Path.Combine(extCpkDestinationFolder, rawFileName), false, false); } } if (this.InternalAwb != null) { var unextractedInternalFiles = this.InternalAwb.Files.Keys.Where(x => !internalIdsExtracted.Contains(x)); foreach (ushort key in unextractedInternalFiles) { waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, false); encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType"); rawFileName = String.Format(rawFileFormat, Path.GetFileName(this.InternalAwb.SourceFile), key.ToString("D5"), CriAcbFile.GetFileExtensionForEncodeType(encodeType)); // extract file ParseFile.ExtractChunkToFile64(internalFs, (ulong)this.InternalAwb.Files[key].FileOffsetByteAligned, (ulong)this.InternalAwb.Files[key].FileLength, Path.Combine(acbAwbDestinationFolder, rawFileName), false, false); } } else if (this.InternalCpk != null) { var unextractedInternalFiles = this.InternalCpk.ItocFiles.Keys.Where(x => !internalIdsExtracted.Contains(x)); foreach (ushort key in unextractedInternalFiles) { waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, false); encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType"); rawFileName = String.Format(rawFileFormat, Path.GetFileName(this.InternalCpk.SourceFileName), key.ToString("D5"), CriAcbFile.GetFileExtensionForEncodeType(encodeType)); // extract file ParseFile.ExtractChunkToFile64(internalFs, (ulong)this.InternalCpk.ItocFiles[key].FileOffsetByteAligned, (ulong)this.InternalCpk.ItocFiles[key].FileLength, Path.Combine(acbCpkDestinationFolder, rawFileName), false, false); } } } catch (Exception ex) { throw ex; } finally { if (internalFs != null) { internalFs.Close(); internalFs.Dispose(); } if (externalFs != null) { externalFs.Close(); externalFs.Dispose(); } } }