/// <summary> /// /// </summary> private void SaveFighterAnimationFile() { // rendering files not loaded if (string.IsNullOrEmpty(AJFilePath)) { return; } // make sure okay to overwrite if (MessageBox.Show($"Is it okay to overwrite {AJFilePath}?", "Save Animation File Changes?", MessageBoxButtons.YesNoCancel) != DialogResult.Yes) { return; } // collect used symbols from all actions var usedSymbols = AllActions.Select(e => e.Symbol); // generate new aj file Dictionary <string, Tuple <int, int> > animOffsets = new Dictionary <string, Tuple <int, int> >(); using (MemoryStream ajBuffer = new MemoryStream()) using (BinaryWriterExt w = new BinaryWriterExt(ajBuffer)) { // collect used symbols foreach (var sym in usedSymbols) { if (sym != null) { if (SymbolToAnimation.ContainsKey(sym) && !animOffsets.ContainsKey(sym)) { // write animation var anim = SymbolToAnimation[sym]; animOffsets.Add(sym, new Tuple <int, int>((int)ajBuffer.Position, anim.Length)); w.Write(anim); w.Align(0x20, 0xFF); } else if (!animOffsets.ContainsKey(sym)) { // animation not found MessageBox.Show($"\"{sym}\" animation not found", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); animOffsets.Add(sym, new Tuple <int, int>(0, 0)); } } } // dump to file File.WriteAllBytes(AJFilePath, ajBuffer.ToArray()); } int index = 0; foreach (var a in AllActions) { // don't write subroutines if (a.Subroutine) { continue; } // get embedded script var ftcmd = new SBM_FighterCommand(); ftcmd._s = _node.Accessor._s.GetEmbeddedStruct(0x18 * index, ftcmd.TrimmedSize); // update symbol name ftcmd.Name = a.Symbol; if (a.Symbol == null) { continue; } // offset var ofst = animOffsets[a.Symbol]; // update action offset and size a.AnimOffset = ofst.Item1; a.AnimSize = ofst.Item2; // update file offset and size ftcmd.AnimationOffset = a.AnimOffset; ftcmd.AnimationSize = a.AnimSize; // resize if needed if (_node.Accessor._s.Length <= 0x18 * index + 0x18) { _node.Accessor._s.Resize(0x18 * index + 0x18); } // update script _node.Accessor._s.SetEmbededStruct(0x18 * index, ftcmd._s); index++; } MainForm.Instance.SaveDAT(); }
public static void Reconstruct(string filepath, string animPath, string directory, string rootName) { var path = Path.GetDirectoryName(directory); HSDRawFile file = new HSDRawFile(); HSDRootNode root = new HSDRootNode(); root.Name = rootName; var ftData = new SBM_FighterData(); root.Data = ftData; file.Roots.Add(root); var prop = root.Data.GetType().GetProperties().ToList(); foreach (var f in Directory.GetFiles(directory)) { if (f.EndsWith(".dat")) { HSDRawFile chunk = new HSDRawFile(f); Console.WriteLine(f + " " + chunk.Roots.Count); var property = prop.Find(e => e.Name == chunk.Roots[0].Name); if (property != null) { var newt = Activator.CreateInstance(property.PropertyType); { var dset = newt as HSDAccessor; if (dset != null) { dset._s = chunk.Roots[0].Data._s; } } property.SetValue(root.Data, newt); } } else if (f.EndsWith(".ini")) { SBM_CommonFighterAttributes attr = new SBM_CommonFighterAttributes(); using (StreamReader r = new StreamReader(new FileStream(f, FileMode.Open))) { foreach (var v in attr.GetType().GetProperties()) { if (v.Name.Equals("TrimmedSize")) { continue; } var line = r.ReadLine().Split('='); if (line.Length < 2 || line[0] != v.Name) { throw new InvalidDataException("Invalid Attribute " + string.Join("=", line)); } if (v.PropertyType == typeof(int)) { v.SetValue(attr, int.Parse(line[1].Trim())); } if (v.PropertyType == typeof(float)) { v.SetValue(attr, float.Parse(line[1].Trim())); } } } ftData.Attributes = attr; } else if (f.EndsWith(".txt")) { XmlSerializer writer = new XmlSerializer(typeof(ScriptFile)); var script = (ScriptFile)writer.Deserialize(new FileStream(f, FileMode.Open)); Dictionary <string, Tuple <int, int> > animationToOffset = new Dictionary <string, Tuple <int, int> >(); List <SBM_FighterCommand> SubActions = new List <SBM_FighterCommand>(); Dictionary <SBM_FighterCommand, string> subActionToScript = new Dictionary <SBM_FighterCommand, string>(); Dictionary <string, HSDStruct> stringToStruct = new Dictionary <string, HSDStruct>(); using (BinaryWriter w = new BinaryWriter(new FileStream(animPath, FileMode.Create))) { foreach (var s in script.Actions) { SBM_FighterCommand subaction = new SBM_FighterCommand(); subaction.Flags = (uint)s.flags; if (s.animation_name != null) { if (!stringToStruct.ContainsKey(s.animation_name)) { var namestruct = new HSDStruct(); byte[] data = new byte[s.animation_name.Length + 1]; var bytes = UTF8Encoding.UTF8.GetBytes(s.animation_name); for (int i = 0; i < s.animation_name.Length; i++) { data[i] = bytes[i]; } namestruct.SetData(data); stringToStruct.Add(s.animation_name, namestruct); } subaction._s.SetReferenceStruct(0, stringToStruct[s.animation_name]); //subaction.Name = s.animation_name; if (!animationToOffset.ContainsKey(s.animation_name)) { if (File.Exists(path + "\\Animations\\" + s.animation_name + ".dat")) { var data = File.ReadAllBytes(path + "\\Animations\\" + s.animation_name + ".dat"); animationToOffset.Add(s.animation_name, new Tuple <int, int>((int)w.BaseStream.Position, data.Length)); w.Write(data); if (w.BaseStream.Length % 0x20 != 0) { var padd = new byte[0x20 - (w.BaseStream.Position % 0x20)]; for (int i = 0; i < padd.Length; i++) { padd[i] = 0xFF; } w.Write(padd); } } else { throw new FileNotFoundException("Could not find animation " + path + "\\Animations\\" + s.animation_name + ".dat"); } } subaction.AnimationOffset = animationToOffset[s.animation_name].Item1; subaction.AnimationSize = animationToOffset[s.animation_name].Item2; } if (s.script != null) { ActionCompiler.Compile(s.script); subActionToScript.Add(subaction, s.script); } SubActions.Add(subaction); } } ftData.FighterCommandTable = new SBM_FighterCommandTable(); ActionCompiler.LinkStructs(); ftData.FighterCommandTable.Commands = SubActions.ToArray(); Console.WriteLine("recompiled count " + ftData.FighterCommandTable._s.GetSubStructs().Count); } } file.Save(filepath); }