private static int DoWork(Options options, DecodeParams baseDecodeParams) { var fileInfo = new FileInfo(options.InputFileName); var baseExtractDirPath = Path.Combine(fileInfo.DirectoryName ?? string.Empty, string.Format(DirTemplate, fileInfo.Name)); if (!Directory.Exists(baseExtractDirPath)) { Directory.CreateDirectory(baseExtractDirPath); } using (var acb = AcbFile.FromFile(options.InputFileName)) { var formatVersion = acb.FormatVersion; if (acb.InternalAwb != null) { var internalDirPath = Path.Combine(baseExtractDirPath, "internal"); ProcessAllBinaries(formatVersion, baseDecodeParams, internalDirPath, acb.InternalAwb, acb.Stream, true); } if (acb.ExternalAwb != null) { var externalDirPath = Path.Combine(baseExtractDirPath, "external"); using (var fs = File.Open(acb.ExternalAwb.FileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { ProcessAllBinaries(formatVersion, baseDecodeParams, externalDirPath, acb.ExternalAwb, fs, false); } } } return(0); }
private LiveMusicWaveStream(Stream hcaStream, DecodeParams decodeParams) { var hcaWaveStream = new HcaAudioStream(hcaStream, decodeParams); _waveStream = new WaveFileReader(hcaWaveStream); _sourceStream = hcaStream; _syncObject = new object(); }
private static void ProcessAllBinaries(uint acbFormatVersion, DecodeParams baseDecodeParams, string extractDir, Afs2Archive archive, Stream dataStream, bool isInternal) { if (!Directory.Exists(extractDir)) { Directory.CreateDirectory(extractDir); } var afsSource = isInternal ? "internal" : "external"; var decodeParams = baseDecodeParams; if (acbFormatVersion >= NewEncryptionVersion) { decodeParams.KeyModifier = archive.HcaKeyModifier; } else { decodeParams.KeyModifier = 0; } foreach (var entry in archive.Files) { var record = entry.Value; var extractFileName = AcbFile.GetSymbolicFileNameFromCueId(record.CueId); extractFileName = extractFileName.ReplaceExtension(".bin", ".wav"); var extractFilePath = Path.Combine(extractDir, extractFileName); using (var fileData = AcbHelper.ExtractToNewStream(dataStream, record.FileOffsetAligned, (int)record.FileLength)) { var isHcaStream = HcaReader.IsHcaStream(fileData); Console.Write("Processing {0} AFS: #{1} (offset={2} size={3})... ", afsSource, record.CueId, record.FileOffsetAligned, record.FileLength); if (isHcaStream) { try { using (var fs = File.Open(extractFilePath, FileMode.Create, FileAccess.Write, FileShare.Write)) { DecodeHca(fileData, fs, decodeParams); } Console.WriteLine("decoded"); } catch (Exception ex) { if (File.Exists(extractFilePath)) { File.Delete(extractFilePath); } Console.WriteLine(ex.Message); } } else { Console.WriteLine("skipped (not HCA)"); } } } }
private LiveMusicWaveStream(Stream acbStream, string acbFileName, DecodeParams decodeParams) { _acb = AcbFile.FromStream(acbStream, acbFileName, false); var names = _acb.GetFileNames(); _internalName = names[0]; _hcaDataStream = _acb.OpenDataStream(_internalName); var hcaWaveStream = new HcaAudioStream(_hcaDataStream, decodeParams); _waveStream = new WaveFileReader(hcaWaveStream); _sourceStream = acbStream; _syncObject = new object(); }
public static void HcaToWav(Stream input, Stream output, DecodeParams decodeParams) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (output == null) { throw new ArgumentNullException(nameof(output)); } using var hcaStream = new OneWayHcaAudioStream(input, decodeParams, true); hcaStream.CopyTo(output); }
private static void DecodeHca(Stream hcaDataStream, Stream waveStream, DecodeParams decodeParams) { using (var hcaStream = new OneWayHcaAudioStream(hcaDataStream, decodeParams, true)) { var buffer = new byte[10240]; var read = 1; while (read > 0) { read = hcaStream.Read(buffer, 0, buffer.Length); if (read > 0) { waveStream.Write(buffer, 0, read); } } } }
private static int CreateDecodeParams(Options options, out DecodeParams decodeParams) { uint key1, key2; var formatProvider = new NumberFormatInfo(); decodeParams = DecodeParams.Default; if (!string.IsNullOrWhiteSpace(options.Key1)) { if (!uint.TryParse(options.Key1, NumberStyles.HexNumber, formatProvider, out key1)) { Console.WriteLine("ERROR: key 1 is in wrong format. It should look like \"a1b2c3d4\"."); return(DefaultExitCodeFail); } } else { key1 = CgssCipher.Key1; } if (!string.IsNullOrWhiteSpace(options.Key2)) { if (!uint.TryParse(options.Key2, NumberStyles.HexNumber, formatProvider, out key2)) { Console.WriteLine("ERROR: key 2 is in wrong format. It should look like \"a1b2c3d4\"."); return(DefaultExitCodeFail); } } else { key2 = CgssCipher.Key2; } decodeParams = DecodeParams.CreateDefault(key1, key2); return(0); }
// ReSharper disable once IdentifierTypo private static void AfsToWav(Afs2FileRecord afsRecord, Stream awbStream, DecodeParams decodeParams, string output) { using var fileData = AcbHelper.ExtractToNewStream(awbStream, afsRecord.FileOffsetAligned, (int)afsRecord.FileLength); var isHcaStream = DereTore.Exchange.Audio.HCA.HcaReader.IsHcaStream(fileData); if (!isHcaStream) { return; } using var fs = File.OpenWrite(output); try { HcaToWav(fileData, fs, decodeParams); } catch (Exception) { Console.Error.WriteLine($"Failed to convert {output}:"); throw; } }
public static void DecodeAcbFiles(FileInfo filename, DirectoryInfo AudioFolder) { var volume = 1F; var mode = 16; var loop = 0; var ciphKey1 = 0x92EBF464; uint ciphKey2 = 0x7E896318; var dir = AudioFolder; var dir2 = new DirectoryInfo(AudioFolder.FullName + @"\DecodedWavs\"); var acbfile = filename; var fs = new FileStream(acbfile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var af = new CriAcbFile(fs, 0, false); af.ExtractAll(); fs.Close(); var destinationFolder = new DirectoryInfo(Path.Combine(acbfile.DirectoryName, "_vgmt_acb_ext_" + Path.GetFileNameWithoutExtension(acbfile.FullName))); var OutFolder = Path.Combine(Path.GetDirectoryName(acbfile.FullName.Replace(dir.FullName, dir2.FullName)), Path.GetFileNameWithoutExtension(acbfile.FullName)); Directory.CreateDirectory(OutFolder); Parallel.ForEach(destinationFolder.GetFiles("*.hca", SearchOption.AllDirectories), hcafile => { using (var inputFileStream = File.Open(hcafile.FullName, FileMode.Open, FileAccess.Read)) { using (var outputFileStream = File.Open(OutFolder + @"\" + hcafile.Name.Substring(0, hcafile.Name.Length - 4) + ".wav", FileMode.Create, FileAccess.Write)) { var decodeParams = DecodeParams.CreateDefault(); decodeParams.Key1 = ciphKey1; decodeParams.Key2 = ciphKey2; decodeParams.KeyModifier = 0; var audioParams = AudioParams.CreateDefault(); audioParams.InfiniteLoop = AudioParams.Default.InfiniteLoop; audioParams.SimulatedLoopCount = AudioParams.Default.SimulatedLoopCount; audioParams.OutputWaveHeader = true; using (var hcaStream = new HcaAudioStream(inputFileStream, decodeParams, audioParams)) { var read = 1; var dataBuffer = new byte[1024]; while (read > 0) { read = hcaStream.Read(dataBuffer, 0, dataBuffer.Length); if (read > 0) { outputFileStream.Write(dataBuffer, 0, read); } } } } } File.Delete(hcafile.FullName); }); var awbfilename = acbfile.FullName.Substring(0, acbfile.FullName.Length - 4) + ".awb"; File.Delete(acbfile.FullName); File.Delete(awbfilename); Directory.Delete(destinationFolder.FullName, true); }
// ReSharper disable once IdentifierTypo public static List <string> AcbToWavs(FileInfo source, DirectoryInfo dest) { var res = new List <string>(); if (source == null) { throw new ArgumentNullException(nameof(source)); } if (dest == null) { throw new ArgumentNullException(nameof(dest)); } const uint newEncryptionVersion = 0x01300000; var acb = AcbFile.FromFile(source.FullName); var acbFormatVersion = acb.FormatVersion; if (acb.ExternalAwb != null) { var awb = acb.ExternalAwb; var decodeParams = DecodeParams.CreateDefault( 0x0030D9E8, 0, acbFormatVersion >= newEncryptionVersion ? awb.HcaKeyModifier : (ushort)0); foreach (var entry in awb.Files) { var record = entry.Value; var cueName = acb.Cues.FirstOrDefault(x => x.CueId == record.CueId)?.CueName; var fileName = cueName == null ? Path.GetFileNameWithoutExtension(source.Name) + record.CueId.ToString("D3") : Path.GetFileNameWithoutExtension(cueName); var extractFileName = Path.Combine(dest.FullName, fileName + ".wav"); var guessAwbFullName = Path.Combine(source.DirectoryName ?? ".", awb.FileName); if (source.DirectoryName != null && File.Exists(guessAwbFullName)) { AfsToWav(record, File.OpenRead(guessAwbFullName), decodeParams, extractFileName); } else if (File.Exists(awb.FileName)) { AfsToWav(record, File.OpenRead(awb.FileName), decodeParams, extractFileName); } else { throw new FileNotFoundException($"Awb file not found, skip {source}", awb.FileName); } res.Add(extractFileName); } } if (acb.InternalAwb != null) { var awb = acb.InternalAwb; var decodeParams = DecodeParams.CreateDefault( 0x0030D9E8, 0, acbFormatVersion >= newEncryptionVersion ? awb.HcaKeyModifier : (ushort)0); foreach (var entry in awb.Files) { var record = entry.Value; var extractFileName = Path.Combine(dest.FullName, Path.GetFileNameWithoutExtension(source.Name) + $"_{record.CueId:D3}.wav"); AfsToWav(record, acb.Stream, decodeParams, extractFileName); res.Add(extractFileName); } } return(res); }
private static int Main(string[] args) { const int defaultExitCodeFail = -1; var parser = new Parser(settings => { settings.IgnoreUnknownArguments = true; }); var parsedResult = parser.ParseArguments <Options>(args); var succeeded = parsedResult.Tag == ParserResultType.Parsed; Options options = null; if (succeeded) { options = ((Parsed <Options>)parsedResult).Value; } if (succeeded) { if (string.IsNullOrWhiteSpace(options.InputFileName)) { succeeded = false; } } if (!succeeded) { var helpText = CommandLine.Text.HelpText.AutoBuild(parsedResult, null, null); helpText.AddPreOptionsLine(" "); helpText.AddPreOptionsLine("Usage: hca2wav <input HCA> [options]"); Console.Error.WriteLine(helpText); return(defaultExitCodeFail); } if (!File.Exists(options.InputFileName)) { Console.Error.WriteLine("File not found: {0}", options.InputFileName); return(defaultExitCodeFail); } if (string.IsNullOrWhiteSpace(options.OutputFileName)) { var fileInfo = new FileInfo(options.InputFileName); options.OutputFileName = fileInfo.FullName.Substring(0, fileInfo.FullName.Length - fileInfo.Extension.Length); options.OutputFileName += ".wav"; } uint key1, key2; ushort keyModifier; var formatProvider = new NumberFormatInfo(); if (!string.IsNullOrWhiteSpace(options.Key1)) { if (!uint.TryParse(options.Key1, NumberStyles.HexNumber, formatProvider, out key1)) { Console.WriteLine("ERROR: key 1 is in wrong format. It should look like \"a1b2c3d4\"."); return(defaultExitCodeFail); } } else { key1 = CgssCipher.Key1; } if (!string.IsNullOrWhiteSpace(options.Key2)) { if (!uint.TryParse(options.Key2, NumberStyles.HexNumber, formatProvider, out key2)) { Console.WriteLine("ERROR: key 2 is in wrong format. It should look like \"a1b2c3d4\"."); return(defaultExitCodeFail); } } else { key2 = CgssCipher.Key2; } if (!string.IsNullOrWhiteSpace(options.KeyModifier)) { if (!ushort.TryParse(options.KeyModifier, NumberStyles.HexNumber, formatProvider, out keyModifier)) { Console.WriteLine("ERROR: key modifier is in wrong format. It should look like \"abcd\"."); return(defaultExitCodeFail); } } else { keyModifier = 0; } using (var inputFileStream = File.Open(options.InputFileName, FileMode.Open, FileAccess.Read)) { using (var outputFileStream = File.Open(options.OutputFileName, FileMode.Create, FileAccess.Write)) { var decodeParams = DecodeParams.CreateDefault(); decodeParams.Key1 = key1; decodeParams.Key2 = key2; decodeParams.KeyModifier = keyModifier; if (options.OverridesCipherType) { decodeParams.CipherTypeOverrideEnabled = true; decodeParams.OverriddenCipherType = (CipherType)options.OverriddenCipherType; } var audioParams = AudioParams.CreateDefault(); audioParams.InfiniteLoop = options.InfiniteLoop; audioParams.SimulatedLoopCount = options.SimulatedLoopCount; audioParams.OutputWaveHeader = !options.NoWaveHeader; using (var hcaStream = new HcaAudioStream(inputFileStream, decodeParams, audioParams)) { var read = 1; var dataBuffer = new byte[1024]; while (read > 0) { read = hcaStream.Read(dataBuffer, 0, dataBuffer.Length); if (read > 0) { outputFileStream.Write(dataBuffer, 0, read); } } } } } return(0); }
private static int Main(string[] args) { var options = new Options(); var succeeded = CommandLine.Parser.Default.ParseArguments(args, options); if (!succeeded) { Console.WriteLine(HelpMessage); return(CommandLine.Parser.DefaultExitCodeFail); } if (string.IsNullOrWhiteSpace(options.OutputFileName)) { var fileInfo = new FileInfo(options.InputFileName); options.OutputFileName = fileInfo.FullName.Substring(0, fileInfo.FullName.Length - fileInfo.Extension.Length); options.OutputFileName += ".wav"; } uint key1, key2; var formatProvider = new NumberFormatInfo(); if (!string.IsNullOrWhiteSpace(options.Key1)) { if (!uint.TryParse(options.Key1, NumberStyles.HexNumber, formatProvider, out key1)) { Console.WriteLine("ERROR: key 1 is of wrong format."); return(CommandLine.Parser.DefaultExitCodeFail); } } else { key1 = CgssCipher.Key1; } if (!string.IsNullOrWhiteSpace(options.Key2)) { if (!uint.TryParse(options.Key2, NumberStyles.HexNumber, formatProvider, out key2)) { Console.WriteLine("ERROR: key 2 is of wrong format."); return(CommandLine.Parser.DefaultExitCodeFail); } } else { key2 = CgssCipher.Key2; } using (var inputFileStream = File.Open(options.InputFileName, FileMode.Open, FileAccess.Read)) { using (var outputFileStream = File.Open(options.OutputFileName, FileMode.Create, FileAccess.Write)) { var decodeParams = DecodeParams.CreateDefault(); decodeParams.Key1 = key1; decodeParams.Key2 = key2; var audioParams = AudioParams.CreateDefault(); audioParams.InfiniteLoop = options.InfiniteLoop; audioParams.SimulatedLoopCount = options.SimulatedLoopCount; audioParams.OutputWaveHeader = options.OutputWaveHeader; using (var hcaStream = new HcaAudioStream(inputFileStream, decodeParams, audioParams)) { var read = 1; var dataBuffer = new byte[1024]; while (read > 0) { read = hcaStream.Read(dataBuffer, 0, dataBuffer.Length); if (read > 0) { outputFileStream.Write(dataBuffer, 0, read); } } } } } return(0); }
public static LiveMusicWaveStream FromHcaStream(Stream stream, DecodeParams decodeParams) { return(new LiveMusicWaveStream(stream, decodeParams)); }
public static LiveMusicWaveStream FromAcbStream(Stream stream, string acbFileName, DecodeParams decodeParams) { return(new LiveMusicWaveStream(stream, acbFileName, decodeParams)); }
public static void DecodeUsmFiles(FileInfo filename) { var volume = 1F; var mode = 16; var loop = 0; var ciphKey1 = 0x92EBF464; uint ciphKey2 = 0x7E896318; var path = Directory.GetCurrentDirectory(); var cridCommands = " -a 92EBF464 -b 7E896318 -v -n \"" + filename.FullName + "\""; Console.WriteLine(filename.Name + " - 解密m2v文件..."); var process = new Process { StartInfo = { FileName = path + @"\crid.exe", Arguments = cridCommands, UseShellExecute = true, CreateNoWindow = true } }; process.Start(); process.WaitForExit(); var af = new CriUsmStream(filename.FullName); var option = new MpegStream.DemuxOptionsStruct { ExtractAudio = true, SplitAudioStreams = true }; af.DemultiplexStreams(option); foreach (var hcafile in new DirectoryInfo(filename.DirectoryName).GetFiles("*.bin", SearchOption.AllDirectories)) { if (!hcafile.Name.Contains(filename.Name.Substring(0, filename.Name.Length - 4))) { continue; } using (var inputFileStream = File.Open(hcafile.FullName, FileMode.Open, FileAccess.Read)) { Console.WriteLine(hcafile.Name + " - 解密hca..."); using (var outputFileStream = File.Open( filename.DirectoryName + @"\" + filename.Name.Substring(0, filename.Name.Length - 4) + @".demux\" + hcafile.Name.Substring(0, hcafile.Name.Length - 4) + ".wav", FileMode.Create, FileAccess.Write)) { var decodeParams = DecodeParams.CreateDefault(); decodeParams.Key1 = ciphKey1; decodeParams.Key2 = ciphKey2; decodeParams.KeyModifier = 0; var audioParams = AudioParams.CreateDefault(); audioParams.InfiniteLoop = AudioParams.Default.InfiniteLoop; audioParams.SimulatedLoopCount = AudioParams.Default.SimulatedLoopCount; audioParams.OutputWaveHeader = true; using (var hcaStream = new HcaAudioStream(inputFileStream, decodeParams, audioParams)) { var read = 1; var dataBuffer = new byte[1024]; while (read > 0) { read = hcaStream.Read(dataBuffer, 0, dataBuffer.Length); if (read > 0) { outputFileStream.Write(dataBuffer, 0, read); } } } } } File.Delete(hcafile.FullName); } var m2vfiles = new DirectoryInfo(filename.DirectoryName + @"\" + filename.Name.Substring(0, filename.Name.Length - 4) + @".demux\") .GetFiles("*.m2v", SearchOption.AllDirectories); var m2vfile = m2vfiles[0]; var wavfiles = new DirectoryInfo(filename.DirectoryName + @"\" + filename.Name.Substring(0, filename.Name.Length - 4) + @".demux\") .GetFiles("*.wav", SearchOption.AllDirectories); var wavefile = wavfiles[0]; var ffmpegCommands = "-i " + "\"" + m2vfile.FullName + "\"" + " -i " + "\"" + wavefile.FullName + "\"" + " -c:v copy -c:a aac -strict experimental " + "\"" + filename.DirectoryName + @"\" + filename.Name.Substring(0, filename.Name.Length - 4) + @".demux\" + filename.Name.Substring(0, filename.Name.Length - 4) + "_final.mp4" + "\""; Console.WriteLine(filename.Name + " - 合并m2v、wav文件..."); var process2 = new Process { StartInfo = { FileName = path + @"\ffmpeg.exe", Arguments = ffmpegCommands, UseShellExecute = true, CreateNoWindow = true } }; process2.Start(); process2.WaitForExit(); }