Пример #1
0
        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();
        }
Пример #3
0
        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();
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
                    }
                }
            }
        }
Пример #7
0
        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);
        }
Пример #8
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;
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        // 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);
        }
Пример #11
0
        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);
        }
Пример #12
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);
        }
Пример #13
0
 public static LiveMusicWaveStream FromHcaStream(Stream stream, DecodeParams decodeParams)
 {
     return(new LiveMusicWaveStream(stream, decodeParams));
 }
Пример #14
0
 public static LiveMusicWaveStream FromAcbStream(Stream stream, string acbFileName, DecodeParams decodeParams)
 {
     return(new LiveMusicWaveStream(stream, acbFileName, decodeParams));
 }
Пример #15
0
        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();
        }