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); }
public List <IUndoRedo> PasteCues() { List <IUndoRedo> undos = new List <IUndoRedo>(); if (!CanPasteCues()) { return(undos); } ACB_File tempAcb = ACB_File.LoadFromClipboard(); //Check if cues exist in current ACB. If they do, then generate new GUIDs for them (duplication mode) if (AcbFile.Cues.Any(x => tempAcb.Cues.Any(y => y.InstanceGuid == x.InstanceGuid))) { tempAcb.NewInstanceGuids(); } foreach (var cue in tempAcb.Cues) { undos.AddRange(AcbFile.CopyCue((int)cue.ID, tempAcb)); } Refresh(); undos.Add(new UndoActionDelegate(this, "Refresh", true)); return(undos); }
private static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: AcbUnzip <Input ACB File>"); return; } var fileName = args[0]; var fileInfo = new FileInfo(fileName); var fullDirPath = Path.Combine(fileInfo.DirectoryName ?? string.Empty, string.Format(DirTemplate, fileInfo.Name)); if (!Directory.Exists(fullDirPath)) { Directory.CreateDirectory(fullDirPath); } using (var acb = AcbFile.FromFile(fileName)) { var fileNames = acb.GetFileNames(); foreach (var s in fileNames) { var extractName = Path.Combine(fullDirPath, s); using (var fs = new FileStream(extractName, FileMode.Create, FileAccess.Write)) { using (var source = acb.OpenDataStream(s)) { WriteFile(source, fs); } } Console.WriteLine(s); } } }
public void UndoableRandomizeCueIds() { var undos = AcbFile.RandomizeCueIds(); Refresh(); undos.Add(new UndoActionDelegate(this, nameof(Refresh), true)); UndoManager.Instance.AddUndo(new CompositeUndo(undos, "Randomize Cue IDs")); }
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 async void CopyCues() { List <Cue_Wrapper> selectedCues = dataGrid.SelectedItems.Cast <Cue_Wrapper>().ToList(); if (selectedCues != null) { AcbFile.CopyCues(selectedCues); } }
private static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: AcbUnzip <Input ACB File>"); return; } var fileName = args[0]; var fileInfo = new FileInfo(fileName); 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(fileName)) { var archivedEntryNames = acb.GetFileNames(); for (var i = 0; i < archivedEntryNames.Length; ++i) { var isCueNonEmpty = archivedEntryNames[i] != null; var s = archivedEntryNames[i] ?? AcbFile.GetSymbolicFileNameFromCueId((uint)i); var extractName = Path.Combine(baseExtractDirPath, s); try { using (var source = isCueNonEmpty ? acb.OpenDataStream(s) : acb.OpenDataStream((uint)i)) { using (var fs = new FileStream(extractName, FileMode.Create, FileAccess.Write, FileShare.Write)) { WriteFile(source, fs); } } Console.WriteLine("Extracted from cue: {0}", s); } catch (Exception ex) { PrintColoredErrorMessage(ex.Message); } } if (acb.InternalAwb != null) { var internalDirPath = Path.Combine(baseExtractDirPath, "internal"); ExtractAllBinaries(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)) { ExtractAllBinaries(externalDirPath, acb.ExternalAwb, fs, false); } } } }
private bool CanPasteOnCue() { if (!IsCueSelected() || !IsFileLoaded()) { return(false); } if (AcbFile.CanPasteCues() || AcbFile.CanPasteAction() || AcbFile.CanPasteTrack()) { return(true); } return(false); }
static void Main(string[] args) { Console.WriteLine("ACB Tool by CaptainSwag101\n" + "Version 1.0.0, built on 2020-08-03\n"); if (args.Length != 2) { Console.WriteLine("ERROR: Invalid number of parameters. Please provide only an ACB and AWB path, respectively."); return; } AcbFile loadedAcb = new AcbFile(); string loadedAcbPath = args[0]; loadedAcb.Load(loadedAcbPath); AwbFile loadedAwb = new AwbFile(); string loadedAwbPath = args[1]; loadedAwb.Load(loadedAwbPath); FileInfo info = new FileInfo(loadedAcbPath); string outputDir = info.DirectoryName + Path.DirectorySeparatorChar + info.Name.Substring(0, info.Name.Length - info.Extension.Length); Directory.CreateDirectory(outputDir); //using FileStream fs = new FileStream(info.FullName + "_cuenames.txt", FileMode.Create); foreach (var cue in loadedAcb.Cues) { //fs.Write(Encoding.ASCII.GetBytes(cue.Value + '\n')); short audioKey = (short)loadedAcb.Cues.Keys.ToList().IndexOf(cue.Key); if (loadedAwb.AudioData.ContainsKey(audioKey)) { string outFilePath = outputDir + Path.DirectorySeparatorChar + cue.Value; byte[] audioData = loadedAwb.AudioData[audioKey]; // Guess output file extension if (audioData[0] == 0x80 && audioData[1] == 0x00) { outFilePath += ".adx"; } else if (audioData[0] == (byte)'H' && audioData[1] == (byte)'C' && (char)audioData[2] == (byte)'A') { outFilePath += ".hca"; } using FileStream audioFile = new FileStream(outFilePath, FileMode.Create); audioFile.Write(audioData); } } //fs.Flush(); }
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(); }
private static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: AcbUnzip <Input ACB File>"); return; } var fileName = args[0]; var fileInfo = new FileInfo(fileName); var fullDirPath = Path.Combine(fileInfo.DirectoryName, string.Format(DirTemplate, fileInfo.Name)); if (!Directory.Exists(fullDirPath)) { Directory.CreateDirectory(fullDirPath); } using (var acb = AcbFile.FromFile(fileName)) { var archivedEntryNames = acb.GetFileNames(); for (var i = 0; i < archivedEntryNames.Length; ++i) { var isCueNonEmpty = archivedEntryNames[i] != null; var s = archivedEntryNames[i] ?? AcbFile.GetSymbolicFileNameFromCueId((uint)i); var extractName = Path.Combine(fullDirPath, s); try { using (var source = isCueNonEmpty ? acb.OpenDataStream(s) : acb.OpenDataStream((uint)i)) { using (var fs = new FileStream(extractName, FileMode.Create, FileAccess.Write)) { WriteFile(source, fs); } } Console.WriteLine(s); } catch (Exception ex) { var origForeground = ConsoleColor.Gray; try { origForeground = Console.ForegroundColor; } catch { } try { Console.ForegroundColor = ConsoleColor.Red; } catch { } Console.WriteLine(ex.Message); try { Console.ForegroundColor = origForeground; } catch { } } } } }
//File Drop (messy duplication, for now...) private async void DataGrid_Drop(object sender, DragEventArgs e) { e.Handled = true; try { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] droppedFilePaths = e.Data.GetData(DataFormats.FileDrop, true) as string[]; foreach (string droppedFile in droppedFilePaths) { switch (System.IO.Path.GetExtension(droppedFile)) { case ".wav": case ".mp3": case ".wma": case ".aac": case ".hca": AddCueForm form = new AddCueForm(Application.Current.MainWindow, droppedFile, true); while (!form.IsDone) { await Task.Delay(50); } if (form.Finished) { if (form.AddTrack) { AcbFile.UndoableAddCue(form.CueName, form.ReferenceType, form.HcaBytes, form.Streaming, form.Loop, false); } else { AcbFile.UndoableAddCue(form.CueName, form.ReferenceType, false); } } break; default: MessageBox.Show(String.Format("The filetype of the dropped file ({0}) is not supported.", System.IO.Path.GetExtension(droppedFilePaths[0])), "File Drop", MessageBoxButton.OK, MessageBoxImage.Error); break; } } } } catch (Exception ex) { MessageBox.Show(String.Format("The dropped file could not be opened.\n\nThe reason given by the system: {0}", ex.Message), "File Drop", MessageBoxButton.OK, MessageBoxImage.Error); } }
private async void PasteCues() { if (Clipboard.ContainsData(ACB_File.CLIPBOARD_ACB_CUES)) { AcbFile.UndoablePasteCues(); } else if (Clipboard.ContainsData(ACB_File.CLIPBOARD_ACB_TRACK)) { AcbFile.UndoablePasteTrack(GetSelectedCue()); } else if (Clipboard.ContainsData(ACB_File.CLIPBOARD_ACB_ACTION)) { AcbFile.UndoablePasteAction(GetSelectedCue()); } }
static void Main(string[] args) { AcbFile loadedAcb = new AcbFile(); string loadedAcbPath = @"D:\Games\Persona Modding\AcbEditor\bgm.acb"; //string loadedAcbPath = @"D:\Games\SteamLibrary\steamapps\common\Danganronpa V3 Killing Harmony\data\win\game_resident\game_resident\JINGLE.acb"; //string loadedAcbPath = @"D:\Games\SteamLibrary\steamapps\common\Danganronpa V3 Killing Harmony\data\win\game_resident\voice_resident_ENG\VOICE_ENG.acb"; loadedAcb.Load(loadedAcbPath); AwbFile loadedAwb = new AwbFile(); string loadedAwbPath = @"D:\Games\Persona Modding\AcbEditor\bgm.awb"; //string loadedAwbPath = @"D:\Games\SteamLibrary\steamapps\common\Danganronpa V3 Killing Harmony\data\win\sound\JINGLE.awb"; //string loadedAwbPath = @"D:\Games\SteamLibrary\steamapps\common\Danganronpa V3 Killing Harmony\data\win\sound\VOICE_ENG.awb"; loadedAwb.Load(loadedAwbPath); FileInfo info = new FileInfo(loadedAcbPath); string outputDir = info.DirectoryName + Path.DirectorySeparatorChar + info.Name.Substring(0, info.Name.Length - info.Extension.Length); Directory.CreateDirectory(outputDir); foreach (var cue in loadedAcb.Cues) { if (loadedAwb.AudioData.ContainsKey((short)loadedAcb.Cues.Keys.ToList().IndexOf(cue.Key))) { string outFilePath = outputDir + Path.DirectorySeparatorChar + cue.Value; byte[] audioData = loadedAwb.AudioData[(short)loadedAcb.Cues.Keys.ToList().IndexOf(cue.Key)]; // Guess output file extension if (audioData[0] == 0x80 && audioData[1] == 0x00) { outFilePath += ".adx"; } else if (audioData[0] == (byte)'H' && audioData[1] == (byte)'C' && (char)audioData[2] == (byte)'A') { outFilePath += ".hca"; } using FileStream audioFile = new FileStream(outFilePath, FileMode.Create); audioFile.Write(audioData); } } }
public static bool Check(Stream stream, string acbFileName, string hcaName) { try { using (var acb = AcbFile.FromStream(stream, acbFileName, false)) { if (!acb.FileExists(hcaName)) { return(false); } try { using (var acbStream = acb.OpenDataStream(hcaName)) { return(HcaDecoder.IsHcaStream(acbStream)); } } catch (HcaException) { return(false); } } } catch (Exception) { return(false); } }
public List <IUndoRedo> PasteAction(Cue_Wrapper cue) { List <IUndoRedo> undos = new List <IUndoRedo>(); if (!CanPasteAction()) { return(undos); } CopiedAction action = (CopiedAction)Clipboard.GetData(ACB_File.CLIPBOARD_ACB_ACTION); if (action != null && cue != null) { undos.AddRange(AcbFile.AddActionToCue(cue.CueRef, action)); } cue.Refresh(); undos.Add(new UndoActionDelegate(cue, "Refresh", true)); return(undos); }
public List <IUndoRedo> PasteTrack(Cue_Wrapper cue) { List <IUndoRedo> undos = new List <IUndoRedo>(); if (!CanPasteTrack()) { return(undos); } CopiedTrack track = (CopiedTrack)Clipboard.GetData(ACB_File.CLIPBOARD_ACB_TRACK); if (track != null && cue != null) { undos.AddRange(AcbFile.AddTrackToCue(cue.CueRef, track.TrackBytes, track.Streaming, track.Loop, track.encodeType)); } cue.Refresh(); undos.Add(new UndoActionDelegate(cue, "Refresh", true)); return(undos); }
public List <IUndoRedo> AddCue(string name, ReferenceType type, byte[] trackBytes, bool streaming, bool loop, bool is3Dsound, EncodeType encodeType, out int cueId) { List <IUndoRedo> undos = new List <IUndoRedo>(); ACB_Cue acbCue; undos.AddRange(AcbFile.AddCue(name, type, trackBytes, streaming, loop, encodeType, out acbCue)); if (is3Dsound) { AcbFile.Add3dDefToCue(acbCue); } Cue_Wrapper wrapper = new Cue_Wrapper(acbCue, this); Cues.Add(wrapper); undos.Add(new UndoableListAdd <Cue_Wrapper>(Cues, wrapper, "")); undos.Add(GetRefreshDelegate()); cueId = (int)acbCue.ID; return(undos); }
private async void AddNewCue() { AddCueForm form = new AddCueForm(Application.Current.MainWindow, string.Format("cue_{0}", AcbFile.AcbFile.GetFreeCueId())); form.ShowDialog(); while (!form.IsDone) { await Task.Delay(50); } if (form.Finished) { if (form.AddTrack) { AcbFile.UndoableAddCue(form.CueName, form.ReferenceType, form.HcaBytes, form.Streaming, form.Loop, form.Is3DSound); } else { AcbFile.UndoableAddCue(form.CueName, form.ReferenceType, form.Is3DSound); } } }
private static void ExtractAllBinaries(string extractDir, Afs2Archive archive, Stream dataStream, bool isInternal) { if (!Directory.Exists(extractDir)) { Directory.CreateDirectory(extractDir); } var afsSource = isInternal ? "internal" : "external"; foreach (var entry in archive.Files) { var record = entry.Value; var extractFileName = AcbFile.GetSymbolicFileNameFromCueId(record.CueId); var extractFilePath = Path.Combine(extractDir, extractFileName); using (var fs = File.Open(extractFilePath, FileMode.Create, FileAccess.Write, FileShare.Write)) { using (var fileData = AcbHelper.ExtractToNewStream(dataStream, record.FileOffsetAligned, (int)record.FileLength)) { WriteFile(fileData, fs); } } Console.WriteLine("Extracted from {0} AFS: #{1} (offset={2} size={3})", afsSource, record.CueId, record.FileOffsetAligned, record.FileLength); } }
private async void RandomizeCueIDs() { AcbFile.UndoableRandomizeCueIds(); }
private async void DeleteCue() { List <Cue_Wrapper> selectedCues = dataGrid.SelectedItems.Cast <Cue_Wrapper>().ToList(); AcbFile.UndoableDeleteCues(selectedCues); }
// 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); }