private void CssUninstall() { acbFile = (ACB_File)uninstall.GetParsedFile <ACB_File>(file.filePath, false); acbFile.CleanTablesOnSave = false; //Too slow on CS_ALL Section section = file.GetSection(Sections.ACB_Cue); foreach (string id in section.IDs) { uint intId; if (uint.TryParse(id, out intId)) { ACB_Cue cue = acbFile.Cues.FirstOrDefault(x => x.ID == intId); if (cue != null) { //Mark cue as free, in same manner as xv2ins cue.Name = "X2_FREE"; var waveforms = acbFile.GetWaveformsFromCue(cue); if (waveforms.Count == 1) { var awbEntry = acbFile.GetAfs2Entry(waveforms[0].AwbId); if (awbEntry != null) { awbEntry.bytes = Properties.Resources.silence; } } } } } /* * //Removed. As above, this is too slow to do on CS_ALL * * //Delete all trailing free cues * for (int i = acbFile.Cues.Count - 1; i >= 0; i--) * { * if(acbFile.Cues[i].Name == "X2_FREE") * { * acbFile.Cues.RemoveAt(i); * } * 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()); } }