public static string ExtractGenhFile(string pSourcePath, bool extractHeaderToFile, bool outputExtractionLog, bool outputExtractionFile) { string outputFileName = null; string headerOutputFileName = null; if (IsGenhFile(pSourcePath)) { using (FileStream fs = File.Open(pSourcePath, FileMode.Open, FileAccess.Read)) { Genh genhFile = new Genh(); genhFile.Initialize(fs, pSourcePath); Int32 headerLength = BitConverter.ToInt32(genhFile.HeaderLength, 0); Int32 originalFileSize = BitConverter.ToInt32(genhFile.OriginalFileSize, 0); string originalFileName = System.Text.Encoding.ASCII.GetString(genhFile.OriginalFileName); outputFileName = Path.Combine(Path.GetDirectoryName(pSourcePath), originalFileName).Trim(); ParseFile.ExtractChunkToFile(fs, headerLength, originalFileSize, outputFileName, outputExtractionLog, outputExtractionFile); if (extractHeaderToFile) { headerOutputFileName = Path.Combine(Path.GetDirectoryName(pSourcePath), String.Format("{0}{1}", originalFileName.Trim(), Genh.FILE_EXTENSION_HEADER)).Trim(); ParseFile.ExtractChunkToFile(fs, 0, headerLength, headerOutputFileName, outputExtractionLog, outputExtractionFile); } FileInfo fi = new FileInfo(outputFileName); if (fi.Length != (long)originalFileSize) { throw new IOException(String.Format("Extracted file <{0}> size did not match size in header of <{1}>: 0x{2}{3}", outputFileName, pSourcePath, originalFileSize.ToString("X8"), Environment.NewLine)); } } } return(outputFileName); }
public static string[] ExtractSdatsFromFile(string pPath, string pDirectorySuffix) { ArrayList extractedSdatPaths = new ArrayList(); string fullPath = Path.GetFullPath(pPath); string outputPath; string filePrefix = Path.GetFileNameWithoutExtension(fullPath); if (!String.IsNullOrEmpty(pDirectorySuffix)) { filePrefix += pDirectorySuffix; } int sdatIndex = 0; long sdatOffset; long previousOffset; byte[] sdatSizeBytes; int sdatSize; if (!File.Exists(fullPath)) { throw new FileNotFoundException(String.Format("Cannot find file <{0}>", fullPath)); } else { using (FileStream fs = File.Open(fullPath, FileMode.Open, FileAccess.Read)) { previousOffset = 0; while ((sdatOffset = ParseFile.GetNextOffset(fs, previousOffset, Sdat.ASCII_SIGNATURE)) != -1) { sdatSizeBytes = ParseFile.ParseSimpleOffset(fs, sdatOffset + 8, 4); sdatSize = BitConverter.ToInt32(sdatSizeBytes, 0); outputPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(pPath), Path.Combine(filePrefix, String.Format("sound_data_{0}.sdat", sdatIndex++.ToString("X2"))))); ParseFile.ExtractChunkToFile(fs, sdatOffset, sdatSize, outputPath); extractedSdatPaths.Add(outputPath); // only increment by one since there can be fake or bad SDATs which will move us past proper ones. previousOffset = sdatOffset + 1; } } } // return paths of extracted SDATs if (extractedSdatPaths.Count > 0) { return((string[])extractedSdatPaths.ToArray(typeof(string))); } else { return(null); } }
public void UpdateTags() { int actualFileEnd; string retaggingFilePath; string[] splitValue; string[] splitParam = new string[] { Environment.NewLine }; try { actualFileEnd = (int)(RESERVED_SECTION_OFFSET + this.reservedSectionLength + this.compressedProgramLength); retaggingFilePath = Path.Combine( Path.GetDirectoryName(this.filePath), String.Format( "{0}_RETAG_{1}{2}", Path.GetFileNameWithoutExtension(this.filePath), new Random().Next().ToString(), Path.GetExtension(this.filePath))); // extract file without tags using (FileStream fs = File.OpenRead(this.filePath)) { ParseFile.ExtractChunkToFile(fs, 0, actualFileEnd, retaggingFilePath); } // add new tags using (FileStream fs = File.Open(retaggingFilePath, FileMode.Append, FileAccess.Write)) { byte[] dataToWrite; // write [TAG] dataToWrite = System.Text.Encoding.ASCII.GetBytes(ASCII_TAG); fs.Write(dataToWrite, 0, dataToWrite.Length); // add or update utf8=1 tag this.TagHash["utf8"] = "1"; foreach (string key in this.TagHash.Keys) { splitValue = this.TagHash[key].Split(splitParam, StringSplitOptions.None); foreach (string valueItem in splitValue) { dataToWrite = System.Text.Encoding.UTF8.GetBytes(String.Format("{0}={1}", key, valueItem)); fs.Write(dataToWrite, 0, dataToWrite.Length); fs.WriteByte(0x0A); } } // foreach (string key in tagHash.Keys) } // using (FileStream fs = File.Open(this.filePath, FileMode.Append, FileAccess.Write)) File.Delete(this.filePath); File.Move(retaggingFilePath, this.filePath); } catch (Exception _ex) { throw new Exception(String.Format("Error updating tags for <{0}>", this.filePath), _ex); } }
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); } ParseFile.ExtractChunkToFile(streamCache[this.SourceFilePath], this.Offset, this.Size, destinationFile); }
static void Main(string[] args) { string inFilename; long startOffset; long blockSize; string fullInputPath; string fullOutputPath; string outputDirectory; string filePrefix; long currentOffset; long fileSize; uint fileCount = 0; if (args.Length < 3) { Console.WriteLine("Usage: snakesplit.exe <infile> <start offset> <blocksize>"); } else { inFilename = args[0]; startOffset = ByteConversion.GetLongValueFromString(args[1]); blockSize = ByteConversion.GetLongValueFromString(args[2]); fullInputPath = Path.GetFullPath(inFilename); filePrefix = Path.GetFileNameWithoutExtension(fullInputPath); outputDirectory = Path.Combine(Path.GetDirectoryName(fullInputPath), "snakesplit"); if (File.Exists(fullInputPath)) { using (FileStream fs = File.OpenRead(fullInputPath)) { fileSize = fs.Length; currentOffset = startOffset; while (currentOffset < fileSize) { fullOutputPath = Path.Combine(outputDirectory, String.Format("{0}_{1}.bin", filePrefix, fileCount.ToString("X8"))); fileCount++; ParseFile.ExtractChunkToFile(fs, currentOffset, blockSize, fullOutputPath); currentOffset += blockSize; } } } else { Console.WriteLine("File Not Found: " + fullInputPath); } } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pEasyPsfDriverExtractionStruct, DoWorkEventArgs e) { byte[] initialProgramCounter; uint initialProgramCounterValue; uint pcOffsetSeq; uint pcOffsetVb; uint pcOffsetVh; uint lengthSeq; uint lengthVb; uint lengthVh; byte[] vhNumberOfPrograms; UInt16 vhNumberOfProgramsValue; Xsf2ExeStruct decompressionOptions = new Xsf2ExeStruct(); decompressionOptions.IncludeExtension = false; decompressionOptions.StripGsfHeader = false; string extractedDataSectionPath = XsfUtil.ExtractCompressedDataSection(pPath, decompressionOptions); if (!String.IsNullOrEmpty(extractedDataSectionPath)) { using (FileStream fs = File.OpenRead(extractedDataSectionPath)) { // get offset of initial program counter initialProgramCounter = ParseFile.ParseSimpleOffset(fs, 0x10, 4); initialProgramCounterValue = BitConverter.ToUInt32(initialProgramCounter, 0); pcOffsetSeq = initialProgramCounterValue - PC_OFFSET_CORRECTION; pcOffsetVb = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, (long)(pcOffsetSeq - 4), 4), 0) - PC_OFFSET_CORRECTION; pcOffsetVh = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, (long)(pcOffsetSeq - 8), 4), 0) - PC_OFFSET_CORRECTION; lengthSeq = pcOffsetVb - pcOffsetSeq; lengthVb = pcOffsetVh - pcOffsetVb; vhNumberOfPrograms = ParseFile.ParseSimpleOffset(fs, (long)(pcOffsetVh + 0x12), 2); vhNumberOfProgramsValue = BitConverter.ToUInt16(vhNumberOfPrograms, 0); lengthVh = (UInt16)((512 * vhNumberOfProgramsValue) + 2592); // extract files ParseFile.ExtractChunkToFile(fs, (long)pcOffsetSeq, (int)lengthSeq, Path.ChangeExtension(pPath, ".seq")); ParseFile.ExtractChunkToFile(fs, (long)pcOffsetVh, (int)lengthVh, Path.ChangeExtension(pPath, ".vh")); ParseFile.ExtractChunkToFile(fs, (long)pcOffsetVb, (int)lengthVb, Path.ChangeExtension(pPath, ".vb")); } // using (FileStream fs = File.OpenRead(pPath)) // delete extracted data File.Delete(extractedDataSectionPath); } // if (!String.IsNullOrEmpty(extractedDataSectionPath)) }
protected void ConvertSubtitles(uint streamId, FileStream subtitleStream) { long subsLength = subtitleStream.Length; long currentOffset = 0; byte[] encodedPresentationTimeStamp; ulong decodedTimeStamp; ushort subtitlePacketSize; byte[] PNG_HEADER = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; byte[] PNG_END = new byte[] { 0x49, 0x45, 0x4E, 0x44 }; long pngStartOffset; long pngEndOffset; long pngSize; uint pngCount = 0; string baseDirectory = Path.GetDirectoryName(subtitleStream.Name); baseDirectory = Path.Combine(baseDirectory, String.Format("{0}_PNGs", Path.GetFileNameWithoutExtension(subtitleStream.Name))); string destinationFile; while (currentOffset < subsLength) { // decode time stamp encodedPresentationTimeStamp = ParseFile.ParseSimpleOffset(subtitleStream, currentOffset, 5); decodedTimeStamp = this.DecodePresentationTimeStamp(encodedPresentationTimeStamp); // get subtitle packet size subtitlePacketSize = ParseFile.ReadUshortBE(subtitleStream, currentOffset + 0xC); // extract PNG pngStartOffset = ParseFile.GetNextOffset(subtitleStream, currentOffset + 0x1E, PNG_HEADER); pngEndOffset = ParseFile.GetNextOffset(subtitleStream, pngStartOffset, PNG_END) + 4; pngSize = pngEndOffset - pngStartOffset; if (pngSize > (subtitlePacketSize - 0x14)) { throw new Exception("Warning, PNG size exceeds packet size."); } destinationFile = Path.Combine(baseDirectory, String.Format("{0}.png", pngCount.ToString("D8"))); ParseFile.ExtractChunkToFile(subtitleStream, pngStartOffset, pngSize, destinationFile); pngCount++; // write timestamp and PNG to file // move to next block currentOffset += 0xE + subtitlePacketSize; } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pSimpleCutterSnakebiteStruct, DoWorkEventArgs e) { SimpleCutterSnakebiteStruct simpleCutterSnakebiteStruct = (SimpleCutterSnakebiteStruct)pSimpleCutterSnakebiteStruct; using (FileStream fs = File.OpenRead(pPath)) { long startOffset = VGMToolbox.util.ByteConversion.GetLongValueFromString(simpleCutterSnakebiteStruct.StartOffset); long cutLength = -1; if (simpleCutterSnakebiteStruct.UseEndAddress) { cutLength = (VGMToolbox.util.ByteConversion.GetLongValueFromString(simpleCutterSnakebiteStruct.EndAddress) - startOffset) + 1; } else if (simpleCutterSnakebiteStruct.UseLength) { cutLength = VGMToolbox.util.ByteConversion.GetLongValueFromString(simpleCutterSnakebiteStruct.Length); } else if (simpleCutterSnakebiteStruct.UseFileEnd) { cutLength = (fs.Length - startOffset) + 1; } if (!String.IsNullOrEmpty(simpleCutterSnakebiteStruct.NewFileExtension)) { if (!simpleCutterSnakebiteStruct.NewFileExtension.StartsWith(".")) { simpleCutterSnakebiteStruct.NewFileExtension = "." + simpleCutterSnakebiteStruct.NewFileExtension; } simpleCutterSnakebiteStruct.OutputFile = Path.ChangeExtension(pPath, simpleCutterSnakebiteStruct.NewFileExtension); } if (!Path.IsPathRooted(simpleCutterSnakebiteStruct.OutputFile)) { simpleCutterSnakebiteStruct.OutputFile = Path.Combine(Path.GetDirectoryName(pPath), simpleCutterSnakebiteStruct.OutputFile); if (simpleCutterSnakebiteStruct.OutputFile.Equals(pPath)) { simpleCutterSnakebiteStruct.OutputFile = Path.Combine(Path.GetDirectoryName(simpleCutterSnakebiteStruct.OutputFile), Path.GetFileNameWithoutExtension(simpleCutterSnakebiteStruct.OutputFile) + "_cut" + Path.GetExtension(simpleCutterSnakebiteStruct.OutputFile)); } } ParseFile.ExtractChunkToFile(fs, startOffset, cutLength, simpleCutterSnakebiteStruct.OutputFile, true, true); this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("File <{0}>, extracted.{1}", simpleCutterSnakebiteStruct.OutputFile, Environment.NewLine); ReportProgress(this.progress, this.progressStruct); } }
/// <summary> /// Extract the title meta data. /// </summary> /// <returns>File name of extracted file.</returns> public string ExtractTitleMetaData() { string destinationFile = Path.Combine( this.GetUnpackFolder(false), (this.TitleId.ToString("X8") + ".tmd")); using (FileStream fs = File.OpenRead(this.SourceFileName)) { ParseFile.ExtractChunkToFile(fs, this.TitleMetaDataOffset, this.TitleMetaDataSize, destinationFile); } return(destinationFile); }
/// <summary> /// Extract the certificate chain. /// </summary> /// <returns>File name of extracted file.</returns> public string ExtractCertificateChain() { string destinationFile = Path.Combine( this.GetUnpackFolder(false), (this.TitleId.ToString("X8") + ".cert")); using (FileStream fs = File.OpenRead(this.SourceFileName)) { ParseFile.ExtractChunkToFile(fs, this.CertificateChainOffset, this.CertificateChainSize, destinationFile); } return(destinationFile); }
public static void TrimFileToLength(string path, long totalLength) { string fullPath = Path.GetFullPath(path); if (File.Exists(fullPath)) { string destinationPath = Path.ChangeExtension(fullPath, ".trimmed"); using (FileStream fs = File.OpenRead(path)) { ParseFile.ExtractChunkToFile(fs, 0, totalLength, destinationPath); } File.Copy(destinationPath, path, true); File.Delete(destinationPath); } }
/// <summary> /// Extract optional footer. /// </summary> /// <returns>File name of extracted file or String.Empty if footer is not present.</returns> public string ExtractFooter() { string destinationFile = String.Empty; if (this.FooterSize > 0) { destinationFile = Path.Combine( this.GetUnpackFolder(false), (this.TitleId.ToString("X8") + ".trailer")); using (FileStream fs = File.OpenRead(this.SourceFileName)) { ParseFile.ExtractChunkToFile(fs, this.FooterOffset, this.FooterSize, destinationFile); } } return(destinationFile); }
public void ExtractToFile(Stream pStream, string pOutputDirectory, object Options) { string outputFileName = Path.GetFileName(this.filePath); int fileCount = 0; if (!Directory.Exists(pOutputDirectory)) { Directory.CreateDirectory(pOutputDirectory); } else { fileCount = Directory.GetFiles(pOutputDirectory, String.Format("{0}*", Path.GetFileNameWithoutExtension(outputFileName)), SearchOption.TopDirectoryOnly).Length; } outputFileName = String.Format("{0}_{1}{2}", Path.GetFileNameWithoutExtension(outputFileName), fileCount.ToString("X4"), Midi.FILE_EXTENSION); outputFileName = Path.Combine(pOutputDirectory, outputFileName); ParseFile.ExtractChunkToFile(pStream, this.fileStartOffset, this.totalFileLength, outputFileName, true, true); }
public static string RemoveChunkFromFile(string path, long startingOffset, long length) { string fullPath = Path.GetFullPath(path); int bytesRead; byte[] bytes = new byte[1024]; string ret = String.Empty; if (File.Exists(fullPath)) { string destinationPath = Path.ChangeExtension(fullPath, ".cut"); using (FileStream sourceFs = File.OpenRead(fullPath)) { // extract initial chunk ParseFile.ExtractChunkToFile(sourceFs, 0, startingOffset, destinationPath); // append remainder using (FileStream outFs = File.Open(destinationPath, FileMode.Append, FileAccess.Write)) { sourceFs.Position = startingOffset + length; bytesRead = sourceFs.Read(bytes, 0, bytes.Length); while (bytesRead > 0) { outFs.Write(bytes, 0, bytesRead); bytesRead = sourceFs.Read(bytes, 0, bytes.Length); } } ret = destinationPath; } } return(ret); }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pPspSeqDataFinderStruct, DoWorkEventArgs e) { PspSeqDataFinderStruct pspStruct = (PspSeqDataFinderStruct)pPspSeqDataFinderStruct; long offset; int phdNumber = 0; PphdStruct phdObject; ArrayList phdArrayList = new ArrayList(); string midName; int midNumber = 0; Psf.ProbableItemStruct midEntry; ArrayList midFiles = new ArrayList(); bool midNamingMessageDisplayed = false; Midi midiFile = new Midi(); Psf.ProbableItemStruct potentialPbd; Psf.ProbableItemStruct[] potentialPbdList; byte[] pbdRow = new byte[Psf.SONY_ADPCM_ROW_SIZE]; ArrayList emptyRowList = new ArrayList(); // display file name this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("[{0}]{1}", pPath, Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); // open file using (FileStream fs = File.OpenRead(pPath)) { string destinationFolder = Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath)); // get PHD files #region PHD EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting PHD{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; while ((offset = ParseFile.GetNextOffset(fs, offset, PPHD_SIGNATURE)) > -1) { try { // get PPHD data phdObject = GetPphdData(fs, offset); phdObject.FileName = String.Format("{0}_{1}.PHD", Path.GetFileNameWithoutExtension(pPath), phdNumber++.ToString("X4")); // extract the file ParseFile.ExtractChunkToFile(fs, offset, (int)phdObject.length, Path.Combine(destinationFolder, phdObject.FileName), true, true); // add to array phdArrayList.Add(phdObject); } catch (Exception pphdEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Error extracting PPHD at offset 0x{0}: {1}{2}", offset.ToString("X8"), pphdEx.Message, Environment.NewLine); ReportProgress(progress, this.progressStruct); } // increment offset offset += 1; } #endregion // get MID Files #region MID EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting MID{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); midEntry = new Psf.ProbableItemStruct(); offset = 0; // build file list while ((offset = ParseFile.GetNextOffset(fs, offset, Midi.ASCII_SIGNATURE_MTHD)) > -1) { midiFile.Initialize(fs, pPath, offset); midEntry.offset = midiFile.FileStartOffset; midEntry.length = (uint)midiFile.TotalFileLength; midFiles.Add(midEntry); offset += 1; } foreach (Psf.ProbableItemStruct mid in midFiles) { if (pspStruct.ReorderMidFiles) { if (phdArrayList.Count < midFiles.Count) { if (!midNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder MID files, there are less PHD files than MID files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); midNamingMessageDisplayed = true; } midName = String.Format("{0}_{1}.MID", Path.GetFileNameWithoutExtension(pPath), midNumber++.ToString("X4")); } else { phdObject = (PphdStruct)phdArrayList[phdArrayList.Count - midFiles.Count + midNumber++]; midName = Path.ChangeExtension(phdObject.FileName, ".MID"); } } else { midName = String.Format("{0}_{1}.MID", Path.GetFileNameWithoutExtension(pPath), midNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, mid.offset, (int)mid.length, Path.Combine(destinationFolder, midName), true, true); } #endregion // get PBD files #region PBD EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting PBD...WARNING, THIS CAN TAKE A LONG TIME...{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; // build list of potential adpcm start indexes potentialPbd = new Psf.ProbableItemStruct(); // build list of potential adpcm start indexes while ((offset = ParseFile.GetNextOffset(fs, offset, Psf.VB_START_BYTES, pspStruct.UseZeroOffsetForPbd, 0x10L, 0x00L, true)) > -1) { try { pbdRow = ParseFile.ParseSimpleOffset(fs, offset, pbdRow.Length); if (Psf.IsPotentialAdpcm(fs, offset + 0x10, Psf.MIN_ADPCM_ROW_COUNT, false)) { potentialPbd.offset = offset; emptyRowList.Add(potentialPbd); } } catch (Exception pbdEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR finding BD for <{0}> at Offset 0x{1}: {2}{3}", pPath, offset.ToString("X8"), pbdEx.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } offset += 1; } potentialPbdList = (Psf.ProbableItemStruct[])emptyRowList.ToArray(typeof(Psf.ProbableItemStruct)); // set probable lengths for (int i = 0; i < potentialPbdList.Length; i++) { if (i > 0) { potentialPbdList[i - 1].length = (uint)(potentialPbdList[i].offset - potentialPbdList[i - 1].offset); } } // compare PHD sample sizes to potential adpcm sizes/indexes phdObject.startingOffset = 0; phdObject.length = 0; phdObject.pbdStartingOffset = 0; phdObject.pbdLength = 0; string pbdName; string newFileName; string[] dupeFileNames; for (int i = 0; i < phdArrayList.Count; i++) { phdObject = (PphdStruct)phdArrayList[i]; if (phdObject.vagLengths.Length < 1) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building PBD for <{0}>: {1} refers to a single VAG, cannot determine proper PBD. Skipping...{2}", pPath, phdObject.FileName, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } else { for (int j = 0; j < potentialPbdList.Length; j++) { // we have a potential match or are at the last item. if ((phdObject.vagLengths[0] <= potentialPbdList[j].length) || (potentialPbdList[j].length == 0)) { try { phdObject = PopulatePbdOffsetLength(fs, potentialPbdList, j, phdObject); if (phdObject.pbdLength > 0) { // check for other BD files that matched and rename accordingly dupeFileNames = Directory.GetFiles(destinationFolder, Path.GetFileNameWithoutExtension(phdObject.FileName) + "*.PBD"); if (dupeFileNames.Length >= 1) { pbdName = String.Format("{0}_{1}.PBD", Path.GetFileNameWithoutExtension(phdObject.FileName), (dupeFileNames.Length).ToString("X4")); if (dupeFileNames.Length == 1) { // rename existing newFileName = String.Format("{0}_{1}.PBD", Path.GetFileNameWithoutExtension(phdObject.FileName), (dupeFileNames.Length - 1).ToString("X4")); File.Move(dupeFileNames[0], Path.Combine(Path.GetDirectoryName(dupeFileNames[0]), newFileName)); } } else { pbdName = Path.ChangeExtension(phdObject.FileName, ".PBD"); } ParseFile.ExtractChunkToFile(fs, phdObject.pbdStartingOffset, phdObject.pbdLength, Path.Combine(destinationFolder, pbdName), true, true); } } catch (Exception ex) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building BD for <{0}>: {1}{2}", pPath, ex.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } } } } #endregion } }
static void Main(string[] args) { const string LBA_SWITCH = "/LBA"; const string MULTIPLIER_SWITCH = "/M"; string inFilename; string outFilename; string startOffset; string cutSize; string fullInputPath; string fullOutputPath; long longStartOffset; long longCutSize; bool doLba = false; bool doMultiplier = false; string multiplierChunk; long multiplierValue = 1; char[] multiplierSplitParam = new char[1] { '=' }; if (args.Length < 3) { Console.WriteLine("Usage: manakut.exe <infile> <outfile> <start offset> <cut size> [/lba|/m=<multiplier>]"); Console.WriteLine(" or: manakut.exe <infile> <outfile> <start offset> [/lba|/m=<multiplier>]"); Console.WriteLine(); Console.WriteLine("The 4 parameter option will read from <start offset> to EOF."); Console.WriteLine("Use the /lba switch to multiply start offset by 0x800."); Console.WriteLine("Use the /m switch to multiply start offset by the value after the equals sign."); } else { inFilename = args[0]; outFilename = args[1]; startOffset = args[2]; fullInputPath = Path.GetFullPath(inFilename); fullOutputPath = Path.GetFullPath(outFilename); if (File.Exists(fullInputPath)) { using (FileStream fs = File.OpenRead(fullInputPath)) { longStartOffset = VGMToolbox.util.ByteConversion.GetLongValueFromString(startOffset); // check for LBA or MULTIPLIER switch if ((args.Length > 4) && (args[4].ToUpper().Equals(LBA_SWITCH))) { doLba = true; } else if ((args.Length > 4) && (args[4].ToUpper().Substring(0, 2).Equals(MULTIPLIER_SWITCH))) { doMultiplier = true; multiplierChunk = args[4].Split(multiplierSplitParam)[1]; multiplierValue = VGMToolbox.util.ByteConversion.GetLongValueFromString(multiplierChunk); } else if ((args.Length > 3) && (args[3].ToUpper().Equals(LBA_SWITCH))) { doLba = true; } else if ((args.Length > 3) && (args[3].Length >= MULTIPLIER_SWITCH.Length) && (args[3].ToUpper().Substring(0, 2).Equals(MULTIPLIER_SWITCH))) { doMultiplier = true; multiplierChunk = args[3].Split(multiplierSplitParam)[1]; multiplierValue = VGMToolbox.util.ByteConversion.GetLongValueFromString(multiplierChunk); } // GET CUTSIZE if ((args.Length > 3) && (!args[3].ToUpper().Equals(LBA_SWITCH)) && ((args[3].Length < MULTIPLIER_SWITCH.Length) || (!args[3].ToUpper().Substring(0, 2).Equals(MULTIPLIER_SWITCH)))) { cutSize = args[3]; longCutSize = VGMToolbox.util.ByteConversion.GetLongValueFromString(cutSize); } else { longCutSize = fs.Length - longStartOffset; } // set LBA/MULTIPLIER values if (doLba) { longStartOffset *= 0x800; } else if (doMultiplier) { longStartOffset *= multiplierValue; } ParseFile.ExtractChunkToFile(fs, longStartOffset, longCutSize, fullOutputPath); } } else { Console.WriteLine("File Not Found: " + fullInputPath); } } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pPsfDataFinderStruct, DoWorkEventArgs e) { PsfDataFinderStruct psfStruct = (PsfDataFinderStruct)pPsfDataFinderStruct; this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("[{0}]{1}", pPath, Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); long offset; string seqName; int seqNumber = 0; ArrayList seqFiles = new ArrayList(); bool seqNamingMessageDisplayed = false; string sepName; int sepNumber = 0; ArrayList sepFiles = new ArrayList(); bool sepNamingMessageDisplayed = false; int vhNumber = 0; int minSampleSize = -1; int maxSampleSize = -1; int minRowLength; VhStruct vhObject; long sampleOffset; ArrayList vhArrayList = new ArrayList(); ArrayList emptyRowList = new ArrayList(); ProbableVbStruct potentialVb; ProbableVbStruct[] potentialVbList; byte[] vbRow = new byte[0x10]; long previousVbOffset = -1; // improve algorithm later using (FileStream fs = File.OpenRead(pPath)) { string destinationFolder = Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath)); // get VH files #region VH EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting VH{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; while ((offset = ParseFile.GetNextOffset(fs, offset, XsfUtil.VAB_SIGNATURE)) > -1) { vhObject = new VhStruct(); vhObject.FileName = String.Format("{0}_{1}.VH", Path.GetFileNameWithoutExtension(pPath), vhNumber++.ToString("X4")); vhObject.startingOffset = offset; vhObject.vhProgramCount = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, (offset + 0x12), 2), 0); vhObject.vbSampleCount = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, (offset + 0x16), 2), 0); vhObject.vbSampleSizes = new uint[vhObject.vbSampleCount]; vhObject.length = 2592 + (512 * vhObject.vhProgramCount); vhObject.vabSize = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4), 0); vhObject.expectedVbLength = vhObject.vabSize - vhObject.length; vhObject.offsetTableOffset = offset + (512 * vhObject.vhProgramCount) + 2080; vhObject.offsetTableOffset += 2; // not sure but seems to be needed vhObject.IsSmallSamplePresent = false; vhObject.HasHeaderMismatch = false; for (int i = 0; i < vhObject.vbSampleCount; i++) { sampleOffset = vhObject.offsetTableOffset + (i * 2); vhObject.vbSampleSizes[i] = (uint)BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, sampleOffset, 2), 0); vhObject.vbSampleSizes[i] <<= 3; vhObject.expectedVbLengthBySample += vhObject.vbSampleSizes[i]; if ((minSampleSize < 0) || (vhObject.vbSampleSizes[i] < minSampleSize)) { minSampleSize = (int)vhObject.vbSampleSizes[i]; if (minSampleSize < Psf.MIN_ADPCM_ROW_SIZE) { vhObject.IsSmallSamplePresent = true; } } // update max sample size if ((maxSampleSize < 0) || (vhObject.vbSampleSizes[i] > maxSampleSize)) { maxSampleSize = (int)vhObject.vbSampleSizes[i]; } } if (vhObject.expectedVbLength != vhObject.expectedVbLengthBySample) { vhObject.HasHeaderMismatch = true; //vhObject.expectedVbLength = vhObject.expectedVbLengthBySample; //this.progressStruct.Clear(); //this.progressStruct.GenericMessage = String.Format(" Warning, for VH <{0}>, header does not match samples' lengths. Ignoring header value.{1}", vhObject.FileName, Environment.NewLine); //this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); } vhArrayList.Add(vhObject); // extract file ParseFile.ExtractChunkToFile(fs, vhObject.startingOffset, (int)vhObject.length, Path.Combine(destinationFolder, vhObject.FileName), true, true); offset += 1; } #endregion // get SEQ Files #region SEQ EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting SEQ{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); // get SEQ file list seqFiles = Psf.GetSeqFileList(fs, psfStruct.UseSeqMinimumSize, psfStruct.MinimumSize); foreach (Psf.ProbableItemStruct seq in seqFiles) { if (seq.length > 0) { if (psfStruct.ReorderSeqFiles) { if ((vhArrayList.Count < seqFiles.Count)) { if (!seqNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder SEQ files, there are less VH files than SEQ files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); seqNamingMessageDisplayed = true; } seqName = String.Format("{0}_{1}.SEQ", Path.GetFileNameWithoutExtension(pPath), seqNumber++.ToString("X4")); } else { vhObject = (VhStruct)vhArrayList[vhArrayList.Count - seqFiles.Count + seqNumber++]; seqName = Path.ChangeExtension(vhObject.FileName, ".SEQ"); } } else { seqName = String.Format("{0}_{1}.SEQ", Path.GetFileNameWithoutExtension(pPath), seqNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, seq.offset, (int)seq.length, Path.Combine(destinationFolder, seqName), true, true); } else { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Warning SEQ found with length less than 0, at Offset 0x{1}: {2}{3}", seq.offset.ToString("X8"), seq.length.ToString("X8"), Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } #endregion // get SEP Files #region SEP EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting SEP{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); // get SEP file list sepFiles = Psf.GetSepFileList(fs); foreach (Psf.ProbableItemStruct sep in sepFiles) { if (sep.length > 0) { if (psfStruct.ReorderSeqFiles) { if ((vhArrayList.Count < sepFiles.Count)) { if (!sepNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder SEP files, there are less VH files than SEP files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); sepNamingMessageDisplayed = true; } sepName = String.Format("{0}_{1}.SEP", Path.GetFileNameWithoutExtension(pPath), sepNumber++.ToString("X4")); } else { vhObject = (VhStruct)vhArrayList[vhArrayList.Count - sepFiles.Count + sepNumber++]; sepName = Path.ChangeExtension(vhObject.FileName, ".SEP"); } } else { sepName = String.Format("{0}_{1}.SEP", Path.GetFileNameWithoutExtension(pPath), sepNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, sep.offset, (int)sep.length, Path.Combine(destinationFolder, sepName), true, true); } else { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Warning SEP found with length less than 0, at Offset 0x{1}: {2}{3}", sep.offset.ToString("X8"), sep.length.ToString("X8"), Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } #endregion // get VB files #region VB EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting VB...WARNING, THIS WILL TAKE A LONG TIME...{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; // setup arrays for checking skips VhStruct[] vhList = (VhStruct[])vhArrayList.ToArray(typeof(VhStruct)); Psf.ProbableItemStruct[] seqList = (Psf.ProbableItemStruct[])seqFiles.ToArray(typeof(Psf.ProbableItemStruct)); Psf.ProbableItemStruct[] sepList = (Psf.ProbableItemStruct[])sepFiles.ToArray(typeof(Psf.ProbableItemStruct)); // build list of potential adpcm start indexes (VB_START_BYTES) potentialVb = new ProbableVbStruct(); // check for the smallest found size or use default //minRowLength = (minSampleSize / 0x10) - 1; // divide into rows //if ((minRowLength > 0) && (minRowLength > MIN_ADPCM_ROW_COUNT)) //{ minRowLength = Psf.MIN_ADPCM_ROW_COUNT; //} while ((offset = ParseFile.GetNextOffset(fs, offset, Psf.VB_START_BYTES, psfStruct.UseZeroOffsetForVb, 0x10, 0)) > -1) { //if (offset >= 0x42E83) //{ // int r = 1; //} if (!CancellationPending) { try { vbRow = ParseFile.ParseSimpleOffset(fs, offset, vbRow.Length); // check for potential sony adpcm signature, and also make sure this offset is not inside another // more easily parsed file since those formats are solid //if ((!InsideAnotherFile(offset, vhList, seqList, sepList)) && // (IsPotentialAdpcm(fs, offset + 0x10, minRowLength))) if (Psf.IsPotentialAdpcm(fs, offset + 0x10, minRowLength, false)) { // check if we have passed a different file type and reset previousVbOffset if we did if (SteppedOverAnotherFile(previousVbOffset, offset, vhList, seqList, sepList)) { // need to add flag here so length calculation doesn't screw up? previousVbOffset = -1; } // check if we have exceeded the max sample size and reset previous offset // so the chunk size check doesn't apply if ((offset - previousVbOffset) > maxSampleSize) { previousVbOffset = -1; } // try to preserve proper VB chunk size if ((previousVbOffset == -1) || ((offset - previousVbOffset) % 0x10 == 0)) { previousVbOffset = offset; potentialVb.offset = offset; emptyRowList.Add(potentialVb); } } } catch (Exception vbEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR finding VB for <{0}> at Offset 0x{1}: {2}{3}", pPath, offset.ToString("X8"), vbEx.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } offset += 1; } else { e.Cancel = true; return; } } potentialVbList = (ProbableVbStruct[])emptyRowList.ToArray(typeof(ProbableVbStruct)); // set probable lengths for (int i = 0; i < potentialVbList.Length; i++) { if (i > 0) { potentialVbList[i - 1].length = (uint)(potentialVbList[i].offset - potentialVbList[i - 1].offset); } } // compare VH sample sizes to potential adpcm sizes/indexes vhObject.startingOffset = 0; vhObject.length = 0; vhObject.vbStartingOffset = 0; vhObject.vbLength = 0; string vbName; string newFileName; string[] dupeFileNames; for (int i = 0; i < vhArrayList.Count; i++) { vhObject = (VhStruct)vhArrayList[i]; if (vhObject.vbSampleSizes.Length < 1) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building VB for <{0}>: {1} refers to a single VAG, cannot determine proper VB. Skipping...{2}", pPath, vhObject.FileName, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } else { for (int j = 0; j < potentialVbList.Length; j++) { // we have a potential match or are at the last item. skip rows that are too small if ((vhObject.vbSampleSizes[0] < Psf.MIN_ADPCM_ROW_SIZE) || (vhObject.vbSampleSizes[0] <= potentialVbList[j].length) || (potentialVbList[j].length == 0)) { try { vhObject = PopulateVbOffsetLength(fs, potentialVbList, j, vhObject, psfStruct.RelaxVbEofRestrictions); if (vhObject.vbLength > 0) { // check for other BD files that matched and rename accordingly dupeFileNames = Directory.GetFiles(destinationFolder, Path.GetFileNameWithoutExtension(vhObject.FileName) + "*.VB"); if (dupeFileNames.Length >= 1) { vbName = String.Format("{0}_{1}.VB", Path.GetFileNameWithoutExtension(vhObject.FileName), (dupeFileNames.Length).ToString("X4")); if (dupeFileNames.Length == 1) { // rename existing newFileName = String.Format("{0}_{1}.VB", Path.GetFileNameWithoutExtension(vhObject.FileName), (dupeFileNames.Length - 1).ToString("X4")); File.Move(dupeFileNames[0], Path.Combine(Path.GetDirectoryName(dupeFileNames[0]), newFileName)); } } else { vbName = Path.ChangeExtension(vhObject.FileName, ".VB"); } ParseFile.ExtractChunkToFile(fs, vhObject.vbStartingOffset, (int)vhObject.vbLength, Path.Combine(destinationFolder, vbName), true, true); } } catch (Exception ex) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building VB for <{0}>: {1}{2}", pPath, ex.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } // if (vhObject.vbSampleSizes[0] == potentialVbList[j].length) } // for (int j = 0; j < potentialVbList.Length; j++) } } #endregion } }
public void ExtractGdRomData(Stream cdStream, string destinationPath, long volumeBaseOffset, long lba, long length, bool isRaw, long nonRawSectorSize, CdSectorType fileMode, bool extractAsRaw) { long offset; long adjustedLba; int maxWriteSize; long bytesWritten = 0; CdSectorType mode; long lbaCounter = 0; byte[] sectorHeader; byte[] sector; // create directory string destinationFolder = Path.GetDirectoryName(destinationPath); if (!Directory.Exists(destinationFolder)) { Directory.CreateDirectory(destinationFolder); } for (int i = (this.TrackCount - 1); i >= 0; i--) { if (lba >= this.TrackEntries[i].StartSector) { if (isRaw) { mode = fileMode; using (FileStream outStream = File.OpenWrite(destinationPath)) { adjustedLba = lba - this.TrackEntries[i].StartSector; while (bytesWritten < length) { offset = volumeBaseOffset + ((adjustedLba + lbaCounter) * this.TrackEntries[i].SectorSize); sector = ParseFile.ParseSimpleOffset(cdStream, offset, (int)CdRom.RAW_SECTOR_SIZE); sectorHeader = ParseFile.ParseSimpleOffset(sector, 0, CdRom.MAX_HEADER_SIZE); if (mode == CdSectorType.Unknown) { mode = CdRom.GetSectorType(sectorHeader); } maxWriteSize = CdRom.ModeDataSize[mode] < (length - bytesWritten) ? CdRom.ModeDataSize[mode] : (int)(length - bytesWritten); if (extractAsRaw) { outStream.Write(sector, 0, sector.Length); } else { outStream.Write(sector, CdRom.ModeHeaderSize[mode], maxWriteSize); } bytesWritten += maxWriteSize; lbaCounter++; } } } else { offset = ((lba - this.TrackEntries[i].StartSector) * this.TrackEntries[i].SectorSize) + this.TrackEntries[i].Offset; ParseFile.ExtractChunkToFile(cdStream, offset, length, destinationPath); } break; } } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractSonyAdpcmStruct, DoWorkEventArgs e) { ExtractSonyAdpcmStruct extractSonyAdpcmStruct = (ExtractSonyAdpcmStruct)pExtractSonyAdpcmStruct; long offset = extractSonyAdpcmStruct.StartOffset; ArrayList adpcmList = new ArrayList(); Psf.ProbableItemStruct adpcmDataItem = new Psf.ProbableItemStruct(); int fileCount = 0; string outputPath = Path.Combine(Path.GetDirectoryName(pPath), "_sony_adpcm_ext"); string outputFileName; string outputFilePath; bool previousRowIsZeroes = false; FileInfo fi = new FileInfo(pPath); using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read)) { while (offset < fi.Length) { if (!CancellationPending) { if (ExtractSonyAdpcmWorker.IsPotentialAdpcm(fs, offset, Psf.MIN_ADPCM_ROW_SIZE, false, ref previousRowIsZeroes)) { // create probable adpcm item adpcmDataItem.Init(); // set starting offset adpcmDataItem.offset = offset; // move to next row offset += Psf.SONY_ADPCM_ROW_SIZE; // loop until end while (Psf.IsSonyAdpcmRow(fs, offset)) { offset += Psf.SONY_ADPCM_ROW_SIZE; } adpcmDataItem.length = (uint)(offset - adpcmDataItem.offset); adpcmList.Add(adpcmDataItem); } offset += 1; } else { e.Cancel = true; return; } } // extract files foreach (Psf.ProbableItemStruct p in adpcmList) { outputFileName = String.Format("{0}_{1}.bin", Path.GetFileNameWithoutExtension(pPath), fileCount.ToString("X8")); outputFilePath = Path.Combine(outputPath, outputFileName); ParseFile.ExtractChunkToFile(fs, p.offset, (int)p.length, outputFilePath, extractSonyAdpcmStruct.OutputBatchFiles, extractSonyAdpcmStruct.OutputBatchFiles); fileCount++; } } }
public static string ExtractAdxStreams(string path, string filePrefix, string outputFolder, out string messages) { string extractedToFolder = String.Empty; StringBuilder messageBuffer = new StringBuilder(); messages = String.Empty; long offset = 0; uint copyrightOffset; byte[] copyrightBytes; uint totalHeaderSize; int encodingType; uint blockSize; uint bitDepth; uint channelCount; uint sampleRate; uint totalSamples; uint fileSize; int fileCount = 0; string outputFileName; string outputFilePath; FileInfo fi = new FileInfo(path); using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read)) { if (!String.IsNullOrEmpty(outputFolder)) { extractedToFolder = outputFolder; } else { extractedToFolder = Path.Combine(Path.GetDirectoryName(path), String.Format("{0}_ADXs", Path.GetFileNameWithoutExtension(path))); } while ((offset = ParseFile.GetNextOffset(fs, offset, ADX_SIG_BYTES)) > -1) { // get offset to copyright string copyrightOffset = (uint)ByteConversion.GetUInt16BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 2, 2)); copyrightBytes = ParseFile.ParseSimpleOffset(fs, offset + copyrightOffset - 2, CRI_COPYRIGHT_BYTES.Length); // check that copyright bytes are present if (ParseFile.CompareSegment(copyrightBytes, 0, CRI_COPYRIGHT_BYTES)) { // verify this is standard ADX encodingType = ParseFile.ParseSimpleOffset(fs, offset + 4, 1)[0]; if (encodingType != 3) { fileSize = 1; } else { // get other info blockSize = (uint)ParseFile.ParseSimpleOffset(fs, offset + 5, 1)[0]; bitDepth = (uint)ParseFile.ParseSimpleOffset(fs, offset + 6, 1)[0]; channelCount = (uint)ParseFile.ParseSimpleOffset(fs, offset + 7, 1)[0]; sampleRate = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 8, 4)); totalSamples = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4)); totalHeaderSize = copyrightOffset + 4; // calculate file size fileSize = (((totalSamples + 0x1F) / (bitDepth * 8)) * channelCount * blockSize) + totalHeaderSize + blockSize; // extract file if (!String.IsNullOrEmpty(filePrefix)) { outputFileName = String.Format("{0}_{1}.adx", filePrefix, fileCount.ToString("X8")); } else { outputFileName = String.Format("{0}_{1}.adx", Path.GetFileNameWithoutExtension(path), fileCount.ToString("X8")); } outputFilePath = Path.Combine(extractedToFolder, outputFileName); ParseFile.ExtractChunkToFile(fs, offset, (int)fileSize, outputFilePath, true, true); messageBuffer.AppendFormat("{0} - offset: 0x{1} size: 0x{2}{3}", outputFileName, offset.ToString("X8"), fileSize.ToString("X8"), Environment.NewLine); fileCount++; } offset += fileSize; } else { offset += 1; } } } messages = messageBuffer.ToString(); return(extractedToFolder); }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pPsf2DataFinderStruct, DoWorkEventArgs e) { Psf2DataFinderStruct psf2Struct = (Psf2DataFinderStruct)pPsf2DataFinderStruct; long offset; uint sqLength; string sqName; int sqNumber = 0; Psf2.ProbableItemStruct sqEntry; ArrayList sqFiles = new ArrayList(); bool sqNamingMessageDisplayed = false; uint hdLength; string hdName; int hdNumber = 0; HdStruct hdObject; ArrayList hdArrayList = new ArrayList(); ArrayList emptyRowList = new ArrayList(); Psf2.ProbableItemStruct potentialBd; Psf2.ProbableItemStruct[] potentialBdList; byte[] bdRow = new byte[0x10]; // display file name this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("[{0}]{1}", pPath, Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); using (FileStream fs = File.OpenRead(pPath)) { string destinationFolder = Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath)); // get HD Files #region HD EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting HD{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; while ((offset = ParseFile.GetNextOffset(fs, offset, Psf2.HD_SIGNATURE)) > -1) { try { hdLength = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4), 0); hdName = String.Format("{0}_{1}.HD", Path.GetFileNameWithoutExtension(pPath), hdNumber++.ToString("X4")); ParseFile.ExtractChunkToFile(fs, offset - 0x10, (int)hdLength, Path.Combine(destinationFolder, hdName), true, true); // get info hdObject = new HdStruct(); hdObject.FileName = hdName; hdObject.startingOffset = offset - 0x10; hdObject.length = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4), 0); hdObject.expectedBdLength = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0x10, 4), 0); hdObject.vagSectionOffset = hdObject.startingOffset + BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0x20, 4), 0); hdObject.maxVagInfoNumber = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, hdObject.vagSectionOffset + 0xC, 4), 0); hdObject.vagInfoOffsetAddr = new long[hdObject.maxVagInfoNumber + 1]; hdObject.vagOffset = new long[hdObject.maxVagInfoNumber + 1]; hdObject.vagLengths = new long[hdObject.maxVagInfoNumber]; hdObject.IsSmallSamplePresent = false; for (int i = 0; i <= hdObject.maxVagInfoNumber; i++) { hdObject.vagInfoOffsetAddr[i] = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, hdObject.vagSectionOffset + 0x10 + (i * 4), 4), 0); hdObject.vagOffset[i] = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, hdObject.vagSectionOffset + hdObject.vagInfoOffsetAddr[i], 4), 0); if (i > 0) { hdObject.vagLengths[i - 1] = hdObject.vagOffset[i] - hdObject.vagOffset[i - 1]; if (hdObject.vagLengths[i - 1] < Psf2.MIN_ADPCM_ROW_SIZE) { hdObject.IsSmallSamplePresent = true; } } } // add to array hdArrayList.Add(hdObject); } catch (Exception hdEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Error extracting HD at offset 0x{0}: {1}{2}", offset.ToString("X8"), hdEx.Message, Environment.NewLine); ReportProgress(progress, this.progressStruct); } // increment offset offset += 1; } #endregion // get SQ Files #region SQ EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting SQ{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); sqEntry = new Psf2.ProbableItemStruct(); offset = 0; // build file list while ((offset = ParseFile.GetNextOffset(fs, offset, Ps2SequenceData.SIGNATURE_BYTES)) > -1) { sqLength = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4), 0); if ((!psf2Struct.UseSeqMinimumSize) || ((psf2Struct.UseSeqMinimumSize) && (sqLength >= psf2Struct.MinimumSize))) { sqEntry.offset = offset - 0x10; sqEntry.length = sqLength; sqFiles.Add(sqEntry); } offset += 1; } foreach (Psf2.ProbableItemStruct sq in sqFiles) { if (psf2Struct.ReorderSqFiles) { if (hdArrayList.Count < sqFiles.Count) { if (!sqNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder SQ files, there are less HD files than SQ files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); sqNamingMessageDisplayed = true; } sqName = String.Format("{0}_{1}.SQ", Path.GetFileNameWithoutExtension(pPath), sqNumber++.ToString("X4")); } else { hdObject = (HdStruct)hdArrayList[hdArrayList.Count - sqFiles.Count + sqNumber++]; sqName = Path.ChangeExtension(hdObject.FileName, ".SQ"); } } else { sqName = String.Format("{0}_{1}.SQ", Path.GetFileNameWithoutExtension(pPath), sqNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, sq.offset, (int)sq.length, Path.Combine(destinationFolder, sqName), true, true); } #endregion // get BD files #region BD EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting BD...WARNING, THIS CAN TAKE A LONG TIME...{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; // build list of potential adpcm start indexes potentialBd = new Psf2.ProbableItemStruct(); while ((offset = ParseFile.GetNextOffset(fs, offset, Psf2.VB_START_BYTES, false)) > -1) { //if (offset == 0x1DD3800) //{ // int fff = 1; //} if ((psf2Struct.UseZeroOffsetForBd) && (offset % 0x10 == 0) || (!psf2Struct.UseZeroOffsetForBd)) { try { bdRow = ParseFile.ParseSimpleOffset(fs, offset, bdRow.Length); if (Psf2.IsPotentialAdpcm(fs, offset + 0x10, Psf2.MIN_ADPCM_ROW_COUNT, false)) { potentialBd.offset = offset; emptyRowList.Add(potentialBd); } } catch (Exception bdEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR finding BD for <{0}> at Offset 0x{1}: {2}{3}", pPath, offset.ToString("X8"), bdEx.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } offset += 1; } potentialBdList = (Psf2.ProbableItemStruct[])emptyRowList.ToArray(typeof(Psf2.ProbableItemStruct)); // set probable lengths for (int i = 0; i < potentialBdList.Length; i++) { if (i > 0) { potentialBdList[i - 1].length = (uint)(potentialBdList[i].offset - potentialBdList[i - 1].offset); } } // compare HD sample sizes to potential adpcm sizes/indexes hdObject.startingOffset = 0; hdObject.length = 0; hdObject.bdStartingOffset = 0; hdObject.bdLength = 0; string bdName; string newFileName; string[] dupeFileNames; for (int i = 0; i < hdArrayList.Count; i++) { hdObject = (HdStruct)hdArrayList[i]; if (hdObject.vagLengths.Length < 1) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building BD for <{0}>: {1} refers to a single VAG, cannot determine proper BD. Skipping...{2}", pPath, hdObject.FileName, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } else { for (int j = 0; j < potentialBdList.Length; j++) { // we have a potential match or are at the last item. if ((hdObject.vagLengths[0] <= potentialBdList[j].length) || (potentialBdList[j].length == 0)) { try { hdObject = PopulateBdOffsetLength(fs, potentialBdList, j, hdObject); if (hdObject.bdLength > 0) { // check for other BD files that matched and rename accordingly dupeFileNames = Directory.GetFiles(destinationFolder, Path.GetFileNameWithoutExtension(hdObject.FileName) + "*.BD"); if (dupeFileNames.Length >= 1) { bdName = String.Format("{0}_{1}.BD", Path.GetFileNameWithoutExtension(hdObject.FileName), (dupeFileNames.Length).ToString("X4")); if (dupeFileNames.Length == 1) { // rename existing newFileName = String.Format("{0}_{1}.BD", Path.GetFileNameWithoutExtension(hdObject.FileName), (dupeFileNames.Length - 1).ToString("X4")); File.Move(dupeFileNames[0], Path.Combine(Path.GetDirectoryName(dupeFileNames[0]), newFileName)); } } else { bdName = Path.ChangeExtension(hdObject.FileName, ".BD"); } ParseFile.ExtractChunkToFile(fs, hdObject.bdStartingOffset, (int)hdObject.bdLength, Path.Combine(destinationFolder, bdName), true, true); } } catch (Exception ex) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building BD for <{0}>: {1}{2}", pPath, ex.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } } } } #endregion } }
static void Main(string[] args) { string inFilename; string outFilename; string startOffset; string endOffset; string fullInputPath; string fullOutputPath; long longStartOffset; long longEndOffset; if (args.Length < 3) { Console.WriteLine("Usage: snakebite.exe <infile> <outfile> <start offset> <end offset>"); Console.WriteLine(" or: snakebite.exe <infile> <outfile> <start offset>"); Console.WriteLine(); Console.WriteLine("The 3 parameter option will read from <start offset> to EOF."); } else { inFilename = args[0]; outFilename = args[1]; startOffset = args[2]; fullInputPath = Path.GetFullPath(inFilename); fullOutputPath = Path.GetFullPath(outFilename); if (File.Exists(fullInputPath)) { using (FileStream fs = File.OpenRead(fullInputPath)) { if (startOffset.StartsWith("0x")) { startOffset = startOffset.Substring(2); longStartOffset = long.Parse(startOffset, System.Globalization.NumberStyles.HexNumber, null); } else { longStartOffset = long.Parse(startOffset, System.Globalization.NumberStyles.Integer, null); } if (args.Length > 3) { endOffset = args[3]; if (endOffset.StartsWith("0x")) { endOffset = endOffset.Substring(2); longEndOffset = long.Parse(endOffset, System.Globalization.NumberStyles.HexNumber, null); } else { longEndOffset = long.Parse(endOffset, System.Globalization.NumberStyles.Integer, null); } } else { longEndOffset = fs.Length; } long size = ((longEndOffset - longStartOffset) + 1); ParseFile.ExtractChunkToFile(fs, longStartOffset, size, fullOutputPath); } } else { Console.WriteLine("File Not Found: " + fullInputPath); } } }
public static void ExtractCdData(Stream cdStream, string destinationPath, long volumeBaseOffset, long lba, long length, bool isRaw, long nonRawSectorSize, CdSectorType fileMode, bool extractAsRaw) { long offset; int maxWriteSize; long bytesWritten = 0; CdSectorType mode; long lbaCounter = 0; byte[] sectorHeader; byte[] sector; // create directory string destinationFolder = Path.GetDirectoryName(destinationPath); if (!Directory.Exists(destinationFolder)) { Directory.CreateDirectory(destinationFolder); } if (isRaw) { switch (fileMode) { case CdSectorType.Audio: case CdSectorType.Mode2Form2: case CdSectorType.XaInterleaved: offset = volumeBaseOffset + ((lba + lbaCounter) * CdRom.RAW_SECTOR_SIZE); ParseFile.ExtractChunkToFile(cdStream, offset, length, destinationPath); break; default: mode = fileMode; using (FileStream outStream = File.OpenWrite(destinationPath)) { while (bytesWritten < length) { offset = volumeBaseOffset + ((lba + lbaCounter) * CdRom.RAW_SECTOR_SIZE); sector = ParseFile.ParseSimpleOffset(cdStream, offset, (int)CdRom.RAW_SECTOR_SIZE); sectorHeader = ParseFile.ParseSimpleOffset(sector, 0, MAX_HEADER_SIZE); if (mode == CdSectorType.Unknown) { mode = GetSectorType(sectorHeader); } maxWriteSize = CdRom.ModeDataSize[mode] < (length - bytesWritten) ? CdRom.ModeDataSize[mode] : (int)(length - bytesWritten); if (extractAsRaw) { outStream.Write(sector, 0, sector.Length); } else { outStream.Write(sector, CdRom.ModeHeaderSize[mode], maxWriteSize); } bytesWritten += maxWriteSize; lbaCounter++; } } break; } ; } else { offset = volumeBaseOffset + (lba * nonRawSectorSize); ParseFile.ExtractChunkToFile(cdStream, offset, length, destinationPath); } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractAdxStruct, DoWorkEventArgs e) { ExtractAdxStruct extractAdxStruct = (ExtractAdxStruct)pExtractAdxStruct; long offset = 0; uint copyrightOffset; byte[] copyrightBytes; uint totalHeaderSize; int encodingType; uint blockSize; uint bitDepth; uint channelCount; uint sampleRate; uint totalSamples; uint fileSize; int fileCount = 0; string outputPath = Path.Combine(Path.GetDirectoryName(pPath), "_cri_adx_ext"); string outputFileName; string outputFilePath; FileInfo fi = new FileInfo(pPath); using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read)) { outputPath = Path.Combine(Path.GetDirectoryName(pPath), String.Format("{0}_ADXs", Path.GetFileNameWithoutExtension(pPath))); while ((offset = ParseFile.GetNextOffset(fs, offset, ADX_SIG_BYTES)) > -1) { if (!this.CancellationPending) { // get offset to copyright string copyrightOffset = (uint)ByteConversion.GetUInt16BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 2, 2)); copyrightBytes = ParseFile.ParseSimpleOffset(fs, offset + copyrightOffset - 2, CRI_COPYRIGHT_BYTES.Length); // check that copyright bytes are present if (ParseFile.CompareSegment(copyrightBytes, 0, CRI_COPYRIGHT_BYTES)) { // verify this is standard ADX encodingType = ParseFile.ParseSimpleOffset(fs, offset + 4, 1)[0]; if (encodingType != 3) { fileSize = 1; } else { // get other info blockSize = (uint)ParseFile.ParseSimpleOffset(fs, offset + 5, 1)[0]; bitDepth = (uint)ParseFile.ParseSimpleOffset(fs, offset + 6, 1)[0]; channelCount = (uint)ParseFile.ParseSimpleOffset(fs, offset + 7, 1)[0]; sampleRate = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 8, 4)); totalSamples = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4)); totalHeaderSize = copyrightOffset + 4; // calculate file size fileSize = (((totalSamples + 0x1F) / (bitDepth * 8)) * channelCount * blockSize) + totalHeaderSize + blockSize; // extract file outputFileName = String.Format("{0}_{1}.adx", Path.GetFileNameWithoutExtension(pPath), fileCount.ToString("X8")); outputFilePath = Path.Combine(outputPath, outputFileName); this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("{0} - offset: 0x{1} size: 0x{2}{3}", outputFileName, offset.ToString("X8"), fileSize.ToString("X8"), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); ParseFile.ExtractChunkToFile(fs, offset, (int)fileSize, outputFilePath, true, true); fileCount++; } offset += fileSize; } else { offset += 1; } } else { e.Cancel = true; return; } } } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractAdxStruct, DoWorkEventArgs e) { ExtractHcaStruct extractAdxStruct = (ExtractHcaStruct)pExtractAdxStruct; long offset = 0; byte revisionMajor; byte revisionMinor; ushort dataOffset; long fmtChunkOffset; uint blockCount; ushort blockSize; long fileSize; int fileCount = 0; string outputPath = Path.Combine(Path.GetDirectoryName(pPath), "_cri_hca_ext"); string outputFileName; string outputFilePath; FileInfo fi = new FileInfo(pPath); using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read)) { outputPath = Path.Combine(Path.GetDirectoryName(pPath), String.Format("{0}_HCAs", Path.GetFileNameWithoutExtension(pPath))); while ((offset = ParseFile.GetNextOffsetMasked(fs, offset, HCA_SIG_BYTES, MASK_BYTES)) > -1) { if (!this.CancellationPending) { // get version revisionMajor = ParseFile.ReadByte(fs, offset + 4); revisionMinor = ParseFile.ReadByte(fs, offset + 5); // get data offset dataOffset = ParseFile.ReadUshortBE(fs, offset + 6); // get 'fmt' chunk offset fmtChunkOffset = ParseFile.GetNextOffsetMasked(fs, offset, FMT_CHUNK_BYTES, MASK_BYTES); if (fmtChunkOffset > -1) { // get block count blockCount = ParseFile.ReadUintBE(fs, fmtChunkOffset + 8); // get block size blockSize = this.getBlockSize(fs, offset); // calculate file size fileSize = dataOffset + (blockCount * blockSize); // extract file outputFileName = String.Format("{0}_{1}.hca", Path.GetFileNameWithoutExtension(pPath), fileCount.ToString("X8")); outputFilePath = Path.Combine(outputPath, outputFileName); this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("{0} - offset: 0x{1} size: 0x{2}{3}", outputFileName, offset.ToString("X8"), fileSize.ToString("X8"), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); ParseFile.ExtractChunkToFile(fs, offset, fileSize, outputFilePath, true, true); // increment counter fileCount++; // move pointer offset += fileSize; } else { throw new FormatException(String.Format("'fmt' chunk not found for HCA starting at 0x{0}", offset.ToString("X8"))); } } else { e.Cancel = true; return; } } } }