コード例 #1
0
        protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractStruct, DoWorkEventArgs e)
        {
            ExtractCriAcbAwbStruct extractStruct = (ExtractCriAcbAwbStruct)pExtractStruct;

            byte[] magicBytes;
            long   awbOffset = 0;

            using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                magicBytes = ParseFile.ParseSimpleOffset(fs, 0, 4);

                this.progressStruct.Clear();

                // ACB
                if (ParseFile.CompareSegment(magicBytes, 0, CriAcbFile.SIGNATURE_BYTES))
                {
                    this.progressStruct.GenericMessage = String.Format("Processing ACB file: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine);
                    ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                    CriAcbFile acb = new CriAcbFile(fs, 0, extractStruct.IncludeCueIdInFileName);
                    acb.ExtractAll();
                }
                else if (ParseFile.CompareSegment(magicBytes, 0, CriAfs2Archive.SIGNATURE))
                {
                    this.progressStruct.GenericMessage = String.Format("Processing AWB file: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine);
                    ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                    CriAfs2Archive afs2 = new CriAfs2Archive(fs, 0);
                    afs2.ExtractAll();
                }
                else
                {
                    this.progressStruct.GenericMessage = String.Format("ACB/AWB signature not found at offset 0...scanning for AWB signature: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine);
                    ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                    awbOffset = ParseFile.GetNextOffset(fs, 0, CriAfs2Archive.SIGNATURE);

                    if (awbOffset > 0)
                    {
                        CriAfs2Archive afs2 = new CriAfs2Archive(fs, awbOffset);
                        afs2.ExtractAll();
                    }
                    else
                    {
                        this.progressStruct.GenericMessage = String.Format("File is not an ACB or AWB...skipping: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine);
                        ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);
                    }
                }
            }
        }
コード例 #2
0
ファイル: Program.cs プロジェクト: tonybonki/SonicAudioTools
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();

            if (args.Length < 1)
            {
                MessageBox.Show("This program can inject audio files into ACB files without the need of repacking their AWBs.\n\nTo start, drag and drop an ACB file to the executable.", "ACB Injector", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            try
            {
                string sourceFileName      = null;
                string sourceAudioFileName = null;
                int    waveformId          = -1;
                string destinationFileName = null;

                foreach (var arg in args)
                {
                    if (int.TryParse(arg, out int ret) && waveformId < 0)
                    {
                        waveformId = ret;
                    }

                    else if (sourceFileName == null)
                    {
                        sourceFileName = arg;
                    }

                    else if (sourceAudioFileName == null)
                    {
                        sourceAudioFileName = arg;
                    }

                    else if (destinationFileName == null)
                    {
                        destinationFileName = arg;
                    }
                }

                CriTable acbFile = new CriTable();
                acbFile.Load(sourceFileName);

                CriTable waveformTable = new CriTable();
                waveformTable.Load(acbFile.Rows[0].GetValue <byte[]>("WaveformTable"));

                var waveforms         = waveformTable.Rows.Where(x => x.GetValue <byte>("Streaming") == 0).ToList();
                var streamedWaveforms = waveformTable.Rows.Except(waveforms).ToList();

                if (streamedWaveforms.Count < 1)
                {
                    throw new InvalidDataException("This ACB file has no streamed waveforms, aka an AWB file.");
                }

                if (waveformId < 0)
                {
                    while (true)
                    {
                        using (TxtBxDialog textBoxDialog = new TxtBxDialog(
                                   streamedWaveforms.Select(x => x.GetValue <ushort>("Id")).OrderBy(x => x).Select(x => x.ToString()).ToArray()))
                        {
                            if (textBoxDialog.ShowDialog() == DialogResult.OK)
                            {
                                if (!int.TryParse(textBoxDialog.Result, out waveformId) || !streamedWaveforms.Any(x => x.GetValue <ushort>("Id") == waveformId))
                                {
                                    MessageBox.Show("Invalid waveform id.", "ACB Injector", MessageBoxButtons.OK);
                                }

                                else
                                {
                                    break;
                                }
                            }

                            else
                            {
                                return;
                            }
                        }
                    }
                }

                CriRow waveformToInject = streamedWaveforms.FirstOrDefault(
                    x => x.GetValue <ushort>("Id") == waveformId);

                int newWaveformId = (waveforms.Count > 0 ?
                                     waveforms.Max(x => x.GetValue <ushort>("Id")) : -1) + 1;

                waveformToInject["Id"]        = (ushort)newWaveformId;
                waveformToInject["Streaming"] = (byte)0;

                if (string.IsNullOrEmpty(sourceAudioFileName))
                {
                    using (OpenFileDialog openFileDialog = new OpenFileDialog
                    {
                        Title = "Select the audio file that you are going to inject",
                        InitialDirectory = Path.GetDirectoryName(sourceFileName),
                        Filter = "All Files|*.*",
                    })
                    {
                        if (openFileDialog.ShowDialog() == DialogResult.OK)
                        {
                            sourceAudioFileName = openFileDialog.FileName;
                        }

                        else
                        {
                            return;
                        }
                    }
                }

                CriAfs2Archive archive = new CriAfs2Archive();

                if (acbFile.Rows[0]["AwbFile"] is byte[] archiveData && archiveData.Length > 0)
                {
                    archive.Load(archiveData);

                    // Proof that SonicAudioLib needs a rewrite.
                    // I hate this...
                    foreach (var entry in archive)
                    {
                        var filePath = new FileInfo(
                            Path.GetTempFileName());

                        File.WriteAllBytes(filePath.FullName,
                                           archiveData.Skip((int)entry.Position).Take((int)entry.Length).ToArray());

                        entry.FilePath = filePath;
                        Junk.Add(entry.FilePath);
                    }
                }

                archive.Add(new CriAfs2Entry
                {
                    Id       = (uint)newWaveformId,
                    FilePath = new FileInfo(sourceAudioFileName)
                });

                acbFile.Rows[0]["AwbFile"] = archive.Save();

                acbFile.WriterSettings           =
                    waveformTable.WriterSettings =
                        CriTableWriterSettings.Adx2Settings;

                acbFile.Rows[0]["WaveformTable"] = waveformTable.Save();

                if (string.IsNullOrEmpty(destinationFileName))
                {
                    if (args.Length < 2)
                    {
                        using (SaveFileDialog saveFileDialog = new SaveFileDialog
                        {
                            Title = "Save ACB file",
                            InitialDirectory = Path.GetDirectoryName(sourceFileName),
                            FileName = Path.GetFileName(sourceFileName),
                            Filter = "ACB Files|*.acb",
                        })
                        {
                            if (saveFileDialog.ShowDialog() == DialogResult.OK)
                            {
                                destinationFileName = saveFileDialog.FileName;
                            }

                            else
                            {
                                return;
                            }
                        }
                    }

                    else
                    {
                        destinationFileName = sourceFileName;
                    }
                }

                acbFile.Save(destinationFileName);
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "ACB Injector", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            foreach (var junk in Junk)
            {
                junk.Delete();
            }
        }
コード例 #3
0
        static void Main(string[] args)
        {
            if (!File.Exists(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile))
            {
                Settings.Default.Reset();
                Settings.Default.Save();
            }

            if (args.Length < 1)
            {
                Console.WriteLine(Resources.Description);
                Console.ReadLine();
                return;
            }
#if !DEBUG
            try
            {
#endif
            if (args[0].EndsWith(".acb", StringComparison.OrdinalIgnoreCase))
            {
                var extractor = new DataExtractor();
                extractor.ProgressChanged += OnProgressChanged;

                extractor.BufferSize      = Settings.Default.BufferSize;
                extractor.EnableThreading = Settings.Default.EnableThreading;
                extractor.MaxThreads      = Settings.Default.MaxThreads;

                string baseDirectory       = Path.GetDirectoryName(args[0]);
                string outputDirectoryPath = Path.ChangeExtension(args[0], null);
                string extAfs2ArchivePath  = string.Empty;

                Directory.CreateDirectory(outputDirectoryPath);

                using (CriTableReader acbReader = CriTableReader.Create(args[0]))
                {
                    acbReader.Read();

                    CriAfs2Archive afs2Archive    = new CriAfs2Archive();
                    CriAfs2Archive extAfs2Archive = new CriAfs2Archive();

                    CriCpkArchive cpkArchive    = new CriCpkArchive();
                    CriCpkArchive extCpkArchive = null;

                    extAfs2ArchivePath = outputDirectoryPath + ".awb";
                    bool found = File.Exists(extAfs2ArchivePath);

                    if (!found)
                    {
                        extAfs2ArchivePath = outputDirectoryPath + "_streamfiles.awb";
                        found = File.Exists(extAfs2ArchivePath);
                    }

                    if (!found)
                    {
                        extAfs2ArchivePath = outputDirectoryPath + "_STR.awb";
                        found = File.Exists(extAfs2ArchivePath);
                    }

                    bool cpkMode = true;

                    long awbPosition = acbReader.GetPosition("AwbFile");
                    if (acbReader.GetLength("AwbFile") > 0)
                    {
                        using (SubStream afs2Stream = acbReader.GetSubStream("AwbFile"))
                        {
                            cpkMode = !CheckIfAfs2(afs2Stream);

                            if (cpkMode)
                            {
                                cpkArchive.Read(afs2Stream);
                            }

                            else
                            {
                                afs2Archive.Read(afs2Stream);
                            }
                        }
                    }

                    if (acbReader.GetLength("StreamAwbAfs2Header") > 0)
                    {
                        cpkMode = false;

                        using (SubStream extAfs2Stream = acbReader.GetSubStream("StreamAwbAfs2Header"))
                        {
                            bool utfMode = DataStream.ReadCString(extAfs2Stream, 4) == "@UTF";
                            extAfs2Stream.Seek(0, SeekOrigin.Begin);

                            if (utfMode)
                            {
                                using (CriTableReader utfAfs2HeaderReader = CriTableReader.Create(extAfs2Stream))
                                {
                                    utfAfs2HeaderReader.Read();

                                    using (SubStream extAfs2HeaderStream = utfAfs2HeaderReader.GetSubStream("Header"))
                                    {
                                        extAfs2Archive.Read(extAfs2HeaderStream);
                                    }
                                }
                            }

                            else
                            {
                                extAfs2Archive.Read(extAfs2Stream);
                            }
                        }

                        if (!found)
                        {
                            throw new FileNotFoundException("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
                        }
                    }

                    using (SubStream waveformTableStream = acbReader.GetSubStream("WaveformTable"))
                        using (CriTableReader waveformReader = CriTableReader.Create(waveformTableStream))
                        {
                            while (waveformReader.Read())
                            {
                                byte encodeType = waveformReader.GetByte("EncodeType");
                                bool streaming  = waveformReader.GetBoolean("Streaming");

                                ushort id =
                                    waveformReader.ContainsField("MemoryAwbId") ?
                                    streaming ? waveformReader.GetUInt16("StreamAwbId") : waveformReader.GetUInt16("MemoryAwbId") :
                                    waveformReader.GetUInt16("Id");

                                string outputName = id.ToString("D5");
                                if (streaming)
                                {
                                    outputName += "_streaming";
                                }

                                outputName += GetExtension(encodeType);
                                outputName  = Path.Combine(outputDirectoryPath, outputName);

                                if (streaming)
                                {
                                    if (!found)
                                    {
                                        throw new Exception("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
                                    }

                                    else if (extCpkArchive == null && cpkMode)
                                    {
                                        extCpkArchive = new CriCpkArchive();
                                        extCpkArchive.Load(extAfs2ArchivePath, Settings.Default.BufferSize);
                                    }

                                    EntryBase afs2Entry = null;

                                    if (cpkMode)
                                    {
                                        afs2Entry = extCpkArchive.GetById(id);
                                    }

                                    else
                                    {
                                        afs2Entry = extAfs2Archive.GetById(id);
                                    }

                                    extractor.Add(extAfs2ArchivePath, outputName, afs2Entry.Position, afs2Entry.Length);
                                }

                                else
                                {
                                    EntryBase afs2Entry = null;

                                    if (cpkMode)
                                    {
                                        afs2Entry = cpkArchive.GetById(id);
                                    }

                                    else
                                    {
                                        afs2Entry = afs2Archive.GetById(id);
                                    }

                                    extractor.Add(args[0], outputName, awbPosition + afs2Entry.Position, afs2Entry.Length);
                                }
                            }
                        }
                }

                extractor.Run();
            }

            else if (File.GetAttributes(args[0]).HasFlag(FileAttributes.Directory))
            {
                string baseDirectory = Path.GetDirectoryName(args[0]);
                string acbPath       = args[0] + ".acb";

                string awbPath = args[0] + "_streamfiles.awb";
                bool   found   = File.Exists(awbPath);

                if (!found)
                {
                    awbPath = args[0] + "_STR.awb";
                    found   = File.Exists(awbPath);
                }

                if (!found)
                {
                    awbPath = args[0] + ".awb";
                }

                if (!File.Exists(acbPath))
                {
                    throw new FileNotFoundException("Cannot find the .ACB file for this directory. Please ensure that the .ACB file is stored in the directory where this directory is.");
                }

                CriTable acbFile = new CriTable();
                acbFile.Load(acbPath, Settings.Default.BufferSize);

                CriAfs2Archive afs2Archive    = new CriAfs2Archive();
                CriAfs2Archive extAfs2Archive = new CriAfs2Archive();

                CriCpkArchive cpkArchive    = new CriCpkArchive();
                CriCpkArchive extCpkArchive = new CriCpkArchive();
                cpkArchive.Mode = extCpkArchive.Mode = CriCpkMode.Id;

                afs2Archive.ProgressChanged    += OnProgressChanged;
                extAfs2Archive.ProgressChanged += OnProgressChanged;
                cpkArchive.ProgressChanged     += OnProgressChanged;
                extCpkArchive.ProgressChanged  += OnProgressChanged;

                bool cpkMode = true;

                byte[] awbFile             = (byte[])acbFile.Rows[0]["AwbFile"];
                byte[] streamAwbAfs2Header = (byte[])acbFile.Rows[0]["StreamAwbAfs2Header"];

                cpkMode = !(awbFile != null && awbFile.Length >= 4 && Encoding.ASCII.GetString(awbFile, 0, 4) == "AFS2") && (streamAwbAfs2Header == null || streamAwbAfs2Header.Length == 0);

                using (CriTableReader reader = CriTableReader.Create((byte[])acbFile.Rows[0]["WaveformTable"]))
                {
                    while (reader.Read())
                    {
                        byte encodeType = reader.GetByte("EncodeType");
                        bool streaming  = reader.GetBoolean("Streaming");

                        ushort id =
                            reader.ContainsField("MemoryAwbId") ?
                            streaming ? reader.GetUInt16("StreamAwbId") : reader.GetUInt16("MemoryAwbId") :
                            reader.GetUInt16("Id");

                        string inputName = id.ToString("D5");
                        if (streaming)
                        {
                            inputName += "_streaming";
                        }

                        inputName += GetExtension(encodeType);
                        inputName  = Path.Combine(args[0], inputName);

                        if (!File.Exists(inputName))
                        {
                            throw new FileNotFoundException($"Cannot find audio file with id {id} for replacement.\nPath attempt: {inputName}");
                        }

                        if (cpkMode)
                        {
                            CriCpkEntry entry = new CriCpkEntry();
                            entry.FilePath = new FileInfo(inputName);
                            entry.Id       = id;

                            if (streaming)
                            {
                                extCpkArchive.Add(entry);
                            }

                            else
                            {
                                cpkArchive.Add(entry);
                            }
                        }

                        else
                        {
                            CriAfs2Entry entry = new CriAfs2Entry();
                            entry.FilePath = new FileInfo(inputName);
                            entry.Id       = id;

                            if (streaming)
                            {
                                extAfs2Archive.Add(entry);
                            }

                            else
                            {
                                afs2Archive.Add(entry);
                            }
                        }
                    }
                }

                acbFile.Rows[0]["AwbFile"]             = null;
                acbFile.Rows[0]["StreamAwbAfs2Header"] = null;

                if (afs2Archive.Count > 0 || cpkArchive.Count > 0)
                {
                    Console.WriteLine("Saving internal AWB...");
                    acbFile.Rows[0]["AwbFile"] = cpkMode ? cpkArchive.Save() : afs2Archive.Save();
                    Console.WriteLine();
                }

                if (extAfs2Archive.Count > 0 || extCpkArchive.Count > 0)
                {
                    Console.WriteLine("Saving external AWB...");
                    if (cpkMode)
                    {
                        extCpkArchive.Save(awbPath, Settings.Default.BufferSize);
                    }

                    else
                    {
                        extAfs2Archive.Save(awbPath, Settings.Default.BufferSize);

                        if (Encoding.UTF8.GetString(streamAwbAfs2Header, 0, 4) == "@UTF")
                        {
                            CriTable headerTable = new CriTable();
                            headerTable.Load(streamAwbAfs2Header);

                            headerTable.Rows[0]["Header"]          = extAfs2Archive.Header;
                            headerTable.WriterSettings             = CriTableWriterSettings.Adx2Settings;
                            acbFile.Rows[0]["StreamAwbAfs2Header"] = headerTable.Save();
                        }

                        else
                        {
                            acbFile.Rows[0]["StreamAwbAfs2Header"] = extAfs2Archive.Header;
                        }
                    }
                }

                acbFile.WriterSettings = CriTableWriterSettings.Adx2Settings;
                acbFile.Save(acbPath, Settings.Default.BufferSize);
            }
#if !DEBUG
        }

        catch (Exception exception)
        {
            MessageBox.Show($"{exception.Message}", "ACB Editor", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
#endif
        }