private void RepairCss() { if (enCssFile.Cues.Count == jpnCssFile.Cues.Count) { return; } ACB_File main = (enCssFile.Cues.Count > jpnCssFile.Cues.Count) ? enCssFile : jpnCssFile; ACB_File second = (enCssFile.Cues.Count > jpnCssFile.Cues.Count) ? jpnCssFile : enCssFile; while (main.Cues.Count > second.Cues.Count) { if (main.Cues.Count <= second.Cues.Count) { break; } int newCueId = second.GetFreeCueId(); ACB_Cue cueToCopy = main.GetCue(newCueId); if (cueToCopy != null) { second.CopyCue(newCueId, main); } else { break; } } }
private void InstallCss() { foreach (var enCue in musicPackage.Cues.Where(x => x.Name.Contains("_en"))) { string[] nameSplit = enCue.Name.Split('_'); if (nameSplit.Length != 2) { throw new InvalidDataException($"Cannot parse the name for cue \"{enCue.Name}\", ID: {enCue.ID}. For installing new CSS voices, the name must include the alias and language, formated like this:\ntheAlias_en (for English)\ntheAlias_jpn (for Japanese)."); } string alias = nameSplit[0]; ACB_Cue jpnCue = musicPackage.Cues.FirstOrDefault(x => x.Name == $"{alias}_jpn"); //Use English cue if no Japanese one was supplied if (jpnCue == null) { jpnCue = enCue; } //Get waveform to install, rather than just installing the cue directly (which could break compat with xv2ins if that cue does something it doesnt like) var enWaveforms = musicPackage.GetWaveformsFromCue(enCue); var jpnWaveforms = musicPackage.GetWaveformsFromCue(jpnCue); if (enWaveforms.Count != 1 || jpnWaveforms.Count != 1) { throw new InvalidDataException("Invalid number of tracks on cue (there must be 1). CSS voice install failed."); } byte[] enHca = musicPackage.GetAfs2Entry(enWaveforms[0].AwbId)?.bytes; byte[] jpnHca = musicPackage.GetAfs2Entry(jpnWaveforms[0].AwbId)?.bytes; //Install new cue bool reusing; int cueId = AssignCommonCssCueId(out reusing); ACB_Cue newEnCue; ACB_Cue newJpnCue; //ACB settings enCssFile.ReuseTrackCommand = true; enCssFile.ReuseSequenceCommand = true; enCssFile.AllowSharedAwbEntries = false; jpnCssFile.ReuseTrackCommand = true; jpnCssFile.ReuseSequenceCommand = true; jpnCssFile.AllowSharedAwbEntries = false; if (reusing) { newEnCue = enCssFile.GetCue(cueId); newJpnCue = jpnCssFile.GetCue(cueId); newEnCue.Name = $"LB_NEW_VOICE_{cueId}"; newJpnCue.Name = $"LB_NEW_VOICE_{cueId}"; enCssFile.ReplaceTrackOnCue(enCssFile.GetCue(cueId), enHca, true, EncodeType.HCA); jpnCssFile.ReplaceTrackOnCue(jpnCssFile.GetCue(cueId), jpnHca, true, EncodeType.HCA); } else { //Add cues enCssFile.AddCue($"LB_NEW_VOICE_{cueId}", cueId, ReferenceType.Sequence, enHca, true, false, EncodeType.HCA, out newEnCue); jpnCssFile.AddCue($"LB_NEW_VOICE_{cueId}", cueId, ReferenceType.Sequence, jpnHca, true, false, EncodeType.HCA, out newJpnCue); } //Set binding install.bindingManager.AddAlias(cueId, alias); //Add tracker entries GeneralInfo.Tracker.AddID(CSS_VOICE_EN_PATH, Sections.ACB_Cue, cueId.ToString()); GeneralInfo.Tracker.AddID(CSS_VOICE_JPN_PATH, Sections.ACB_Cue, cueId.ToString()); } }