public static void ToFilename(string name, BACFile bac, BCMFile bcm) { bac.Scripts.Remove(Script.NullScript); bac.VFXScripts.Remove(Script.NullScript); bac.Scripts = new ObservableCollection <Script>(bac.Scripts.OrderBy(x => x.Index)); bac.VFXScripts = new ObservableCollection <Script>(bac.VFXScripts.OrderBy(x => x.Index)); using (var ms = new MemoryStream()) using (var outFile = new BinaryWriter(ms)) { outFile.Write(1128350243); outFile.Write(2686974); outFile.Write(65537); outFile.Write((short)(bac.Scripts.Last().Index + 1)); if (bac.VFXScripts.Count > 0) { outFile.Write((short)(bac.VFXScripts.Last().Index + 1)); } else { outFile.Write((short)0); } outFile.Write(bac.HitboxTable.Last().Index + 1); int OffsetOffset = (int)outFile.BaseStream.Position; outFile.Write(0); outFile.Write(0); outFile.Write(0); outFile.Write(0); outFile.Write(0); foreach (ObservableCollection <float> list in bac.UnknownFloatData) { foreach (float entry in list) { outFile.Write(entry); } } /* Scripts */ int ScriptOffset = (int)outFile.BaseStream.Position; for (int i = 0; i < bac.Scripts.Last().Index + 1; i++) { outFile.Write(0); } /* VFX Scripts */ int VFXScriptOffset = (int)outFile.BaseStream.Position; if (bac.VFXScripts.Count != 0) { for (int i = 0; i < bac.VFXScripts.Last().Index + 1; i++) { outFile.Write(0); } } else { VFXScriptOffset = 0; } /* Script Name Offsets */ int ScriptNameOffset = (int)outFile.BaseStream.Position; for (int i = 0; i < bac.Scripts.Last().Index + 1; i++) { outFile.Write(0); } /* VFX Script Name Offsets */ int VFXScriptNameOffset = (int)outFile.BaseStream.Position; if (bac.VFXScripts.Count == 0) { VFXScriptNameOffset = 0; } else { for (int i = 0; i < bac.VFXScripts.Last().Index + 1; i++) { outFile.Write(0); } } /* Hitbox Table */ int HitboxTableOffset = (int)outFile.BaseStream.Position; for (int i = 0; i < bac.HitboxTable.Last().Index + 1; i++) { outFile.Write(0); } outFile.BaseStream.Seek(0, SeekOrigin.End); foreach (Script script in bac.Scripts) { int tmp = (int)outFile.BaseStream.Position; writeScript(bac, bcm, outFile, script); outFile.BaseStream.Seek(ScriptOffset + script.Index * 4); outFile.Write(tmp); outFile.Seek(0, SeekOrigin.End); } foreach (Script script in bac.VFXScripts) { int tmp = (int)outFile.BaseStream.Position; writeScript(bac, bcm, outFile, script); outFile.BaseStream.Seek(VFXScriptOffset + script.Index * 4); outFile.Write(tmp); outFile.Seek(0, SeekOrigin.End); } /* Hitbox Table */ foreach (HitBoxDataset dataset in bac.HitboxTable) { int tmp = (int)outFile.BaseStream.Position; outFile.BaseStream.Seek(HitboxTableOffset + dataset.Index * 4); outFile.Write(tmp); outFile.Seek(0, SeekOrigin.End); foreach (HitBoxData data in dataset.Data) { outFile.Write(data.Damage); outFile.Write(data.Stun); outFile.Write((ushort)data.Effect); if (data.OnHit != null) { outFile.Write((short)(data.OnHit.Index - HitBoxData.getIndexOffset(data.Effect))); } else { outFile.Write((short)-1); } //0x8 outFile.Write(data.SelfHitstop); outFile.Write(data.SelfShaking); outFile.Write(data.TgtHitstop); outFile.Write(data.TgtShaking); //0x10 outFile.Write(data.HitGFX); outFile.Write(data.Unknown1); outFile.Write((short)data.Unused); //0x18 outFile.Write(data.HitGFX2); outFile.Write((int)data.Unused2); outFile.Write((short)data.Unused3); //0x20 outFile.Write(data.HitSFX); outFile.Write(data.HitSFX2); outFile.Write(data.TgtSFX); outFile.Write(data.ArcadeScore); outFile.Write(data.SelfMeter); outFile.Write(data.TgtMeter); outFile.Write(data.JuggleStart); outFile.Write(data.TgtAnimTime); outFile.Write((int)data.MiscFlag); outFile.Write(data.VelX); outFile.Write(data.VelY); outFile.Write(data.VelZ); outFile.Write(data.PushbackDist); outFile.Write(data.AccX); outFile.Write(data.AccY); outFile.Write(data.AccZ); } } /* Script Names+Offsets */ List <string> strings = new List <string>(); int index = 0; foreach (Script tmp in bac.Scripts) { while (index != tmp.Index) { strings.Add(null); index++; } index++; if (tmp.Name != "null") { strings.Add(tmp.Name); } else { strings.Add(null); } } Util.writeStringTable(outFile, ScriptNameOffset, strings); strings.Clear(); index = 0; foreach (Script tmp in bac.VFXScripts) { while (index != tmp.Index) { strings.Add(null); index++; } index++; strings.Add(tmp.Name); } Util.writeStringTable(outFile, VFXScriptNameOffset, strings); outFile.BaseStream.Seek(0x14); outFile.Write(ScriptOffset); outFile.Write(VFXScriptOffset); outFile.Write(ScriptNameOffset); outFile.Write(VFXScriptNameOffset); outFile.Write(HitboxTableOffset); using (var fs = File.Create(name)) { ms.WriteTo(fs); } } }
public static BACFile FromFilename(string name, BCMFile bcm) { using (var fs = File.OpenRead(name)) using (var tracker = new TrackingStream(fs)) using (var inFile = new BinaryReader(tracker)) { AELogger.Log(AELogger.O_SEPARATOR, false); tracker.SetLabel("Header"); if (new String(inFile.ReadChars(4)) != "#BAC") { throw new IOException("Not a valid BAC file"); } tracker.IgnoreBytes(8); inFile.BaseStream.Seek(12); ushort ScriptCount = inFile.ReadUInt16(); ushort VFXScriptCount = inFile.ReadUInt16(); uint HitboxTableSize = inFile.ReadUInt32(); int ScriptOffset = inFile.ReadInt32(); int VFXScriptOffset = inFile.ReadInt32(); int ScriptNameOffset = inFile.ReadInt32(); int VFXScriptNameOffset = inFile.ReadInt32(); int HitboxTableOffset = inFile.ReadInt32(); AELogger.Log("Header done, reading floats"); var bac = new BACFile(); for (int i = 0; i < 0x1c; i++) { var list = new ObservableCollection <float>(); for (int j = 0; j < 6; j++) { list.Add(inFile.ReadSingle()); } bac.UnknownFloatData.Add(list); } AELogger.Log("floats done, reading scripts"); for (int i = 0; i < ScriptCount; i++) { bac.Scripts.Add(new Script(i)); } for (int i = 0; i < VFXScriptCount; i++) { bac.VFXScripts.Add(new Script(i)); } for (int i = 0; i < HitboxTableSize; i++) { bac.HitboxTable.Add(new HitBoxDataset(i)); } //Link BCM if (bcm != null) { foreach (BCM.Move move in bcm.Moves) { if (move.ScriptIndex != -1) { move.Script = bac.Scripts[move.ScriptIndex]; } } } //Read Scripts readScripts(inFile, bac.Scripts, bcm, ScriptCount, ScriptOffset, ScriptNameOffset, bac); readScripts(inFile, bac.VFXScripts, bcm, VFXScriptCount, VFXScriptOffset, VFXScriptNameOffset, bac); AELogger.Log("scripts done, reading hitboxtable"); //Read Hitbox Table for (int i = 0; i < HitboxTableSize; i++) { tracker.SetLabel("HitboxTable#" + i.ToString()); inFile.BaseStream.Seek(HitboxTableOffset + i * 4); inFile.BaseStream.Seek(inFile.ReadUInt32()); if (inFile.BaseStream.Position == 0) { continue; } var dataset = bac.HitboxTable[i]; LoadedHitBoxCount = i; for (int j = 0; j < 12; j++) { HitBoxData data = new HitBoxData(j); dataset.Data.Add(data); data.Damage = inFile.ReadInt16(); data.Stun = inFile.ReadInt16(); data.Effect = (HitBoxData.HitBoxEffect)inFile.ReadUInt16(); Util.LogUnkEnum(data.Effect, "Hitbox #" + dataset.Index, "hitboxdataset", j); var index = inFile.ReadInt16() + HitBoxData.getIndexOffset(data.Effect); if (index > -1) { data.OnHit = bac.Scripts.Where(x => x.Index == index).First(); } else { data.OnHit = new Script(index); if (index <= -1) { AELogger.Log("negative index " + index + " in hitboxdata #" + i); } } data.SelfHitstop = inFile.ReadUInt16(); data.SelfShaking = inFile.ReadUInt16(); data.TgtHitstop = inFile.ReadUInt16(); data.TgtShaking = inFile.ReadUInt16(); data.HitGFX = inFile.ReadInt16(); data.Unknown1 = inFile.ReadInt32(); data.Unused = (Unused16)inFile.ReadInt16(); data.HitGFX2 = inFile.ReadInt16(); data.Unused2 = (Unused32)inFile.ReadInt32(); data.Unused3 = (Unused16)inFile.ReadInt16(); data.HitSFX = inFile.ReadInt16(); data.HitSFX2 = inFile.ReadInt16(); data.TgtSFX = inFile.ReadInt16(); data.ArcadeScore = inFile.ReadUInt16(); data.SelfMeter = inFile.ReadInt16(); data.TgtMeter = inFile.ReadInt16(); data.JuggleStart = inFile.ReadInt16(); data.TgtAnimTime = inFile.ReadInt16(); data.MiscFlag = (HitBoxData.MiscFlags)inFile.ReadInt32(); data.VelX = inFile.ReadSingle(); data.VelY = inFile.ReadSingle(); data.VelZ = inFile.ReadSingle(); data.PushbackDist = inFile.ReadSingle(); data.AccX = inFile.ReadSingle(); data.AccY = inFile.ReadSingle(); data.AccZ = inFile.ReadSingle(); } } AELogger.Log("hitbox done"); List <HitBoxDataset> nullHitboxData = bac.HitboxTable.Where(x => x.Data.Count() == 0).ToList(); foreach (HitBoxDataset tmp in nullHitboxData) { bac.HitboxTable.Remove(tmp); } FilterScripts(bac.Scripts); FilterScripts(bac.VFXScripts); AELogger.Log(AELogger.O_SEPARATOR, false); return(bac); } }