internal override void Write(BinaryWriterEx bw, int id) { long start = bw.Position; bw.ReserveVarint("NameOffset"); bw.WriteByte((byte)Type); bw.WriteByte(0); bw.WriteInt16((short)id); if (bw.VarintLong) { bw.WriteInt32(0); } bw.ReserveVarint("TypeDataOffset"); bw.WriteVarint(0); bw.FillVarint("NameOffset", bw.Position - start); bw.WriteUTF16(MSB.ReambiguateName(Name), true); bw.Pad(bw.VarintSize); if (HasTypeData) { bw.FillVarint("TypeDataOffset", bw.Position - start); WriteTypeData(bw); } else { bw.FillVarint("TypeDataOffset", 0); } }
internal override void Write(BinaryWriterEx bw) { bool bigEndian = Format == EMEVD.Game.DarkSouls1BE; bool is64Bit = Format >= EMEVD.Game.Bloodborne; bw.WriteASCII("ELD\0"); bw.WriteBoolean(bigEndian); bw.WriteSByte((sbyte)(is64Bit ? -1 : 0)); bw.WriteByte(0); bw.WriteByte(0); bw.BigEndian = bigEndian; bw.VarintLong = is64Bit; bw.WriteInt16(0x65); bw.WriteInt16(0xCC); bw.ReserveInt32("FileSize"); bw.WriteVarint(Events.Count); bw.ReserveVarint("EventsOffset"); bw.WriteVarint(0); bw.ReserveVarint("Offset2"); bw.WriteVarint(0); bw.ReserveVarint("Offset3"); bw.ReserveVarint("StringsLength"); bw.ReserveVarint("StringsOffset"); if (!is64Bit) { bw.WriteInt32(0); bw.WriteInt32(0); } bw.FillVarint("EventsOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Events[i].Write(bw, Format, i); } bw.FillVarint("Offset2", bw.Position); bw.FillVarint("Offset3", bw.Position); long stringsOffset = bw.Position; bw.FillVarint("StringsOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Events[i].WriteName(bw, i, stringsOffset); } if ((bw.Position - stringsOffset) % 0x10 > 0) { bw.WritePattern(0x10 - (int)(bw.Position - stringsOffset) % 0x10, 0x00); } bw.FillVarint("StringsLength", bw.Position - stringsOffset); bw.FillInt32("FileSize", (int)bw.Position); }
internal void WriteDisposOffsets(BinaryWriterEx bw, Dictionary <Disposition, long> offsetsByDispos, int cutIndex, int timelineIndex) { bw.FillVarint($"DisposOffsetsOffset[{cutIndex}:{timelineIndex}]", bw.Position); foreach (Disposition dispos in Dispositions) { bw.WriteVarint(offsetsByDispos[dispos]); } }
internal void WriteCustomData(BinaryWriterEx bw, int cutIndex, int timelineIndex, List <CustomData> allCustomData, List <long> customDataValueOffsets) { bw.FillVarint($"TimelineCustomDataOffset[{cutIndex}:{timelineIndex}]", bw.Position); foreach (CustomData customData in CustomData) { customData.Write(bw, allCustomData, customDataValueOffsets); } }
internal void WriteTimelines(BinaryWriterEx bw, MQBVersion version, int cutIndex) { bw.FillVarint($"TimelinesOffset{cutIndex}", bw.Position); for (int i = 0; i < Timelines.Count; i++) { Timelines[i].Write(bw, version, cutIndex, i); } }
internal override void Write(BinaryWriterEx bw, int id) { long start = bw.Position; bw.ReserveVarint("NameOffset"); bw.WriteByte((byte)Type); bw.WriteByte(0); bw.WriteInt16((short)id); bw.WriteInt16(ModelIndex); bw.WriteInt16(0); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.WriteVector3(Scale); bw.WriteUInt32s(DrawGroups); bw.WriteInt32(Unk44); bw.WriteInt32(Unk48); bw.WriteInt32(Unk4C); bw.WriteInt32(Unk50); bw.WriteUInt32s(DispGroups); bw.WriteInt32(Unk64); bw.WriteInt32(0); bw.WriteByte(Unk6C); bw.WriteByte(0); bw.WriteByte(Unk6E); bw.WriteByte(0); bw.ReserveVarint("TypeDataOffset"); if (bw.VarintLong) { bw.WriteInt64(0); } long nameStart = bw.Position; int namePad = bw.VarintLong ? 0x20 : 0x2C; bw.FillVarint("NameOffset", nameStart - start); bw.WriteUTF16(MSB.ReambiguateName(Name), true); if (bw.Position - nameStart < namePad) { bw.Position += namePad - (bw.Position - nameStart); } bw.Pad(bw.VarintSize); bw.FillVarint("TypeDataOffset", bw.Position - start); WriteTypeData(bw); }
internal virtual void Write(BinaryWriterEx bw, List <T> entries) { bw.WriteInt32(Version); if (bw.VarintLong) { bw.WriteInt32(entries.Count + 1); bw.ReserveVarint("ParamNameOffset"); } else { bw.ReserveVarint("ParamNameOffset"); bw.WriteInt32(entries.Count + 1); } for (int i = 0; i < entries.Count; i++) { bw.ReserveVarint($"EntryOffset{i}"); } bw.ReserveVarint("NextParamOffset"); bw.FillVarint("ParamNameOffset", bw.Position); bw.WriteUTF16(Name, true); bw.Pad(bw.VarintSize); int index = 0; Type type = null; for (int i = 0; i < entries.Count; i++) { if (type != entries[i].GetType()) { type = entries[i].GetType(); index = 0; } bw.FillVarint($"EntryOffset{i}", bw.Position); entries[i].Write(bw, index); bw.Pad(bw.VarintSize); index++; } }
internal void WriteInstructions(BinaryWriterEx bw, Game format, Offsets offsets, int eventIndex) { long instrsOffset = Instructions.Count > 0 ? bw.Position - offsets.Instructions : -1; bw.FillVarint($"Event{eventIndex}InstrsOffset", instrsOffset); for (int i = 0; i < Instructions.Count; i++) { Instructions[i].Write(bw, format, eventIndex, i); } }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { Entries entries; entries.Models = Models.GetEntries(); entries.Events = Events.GetEntries(); entries.Regions = Regions.GetEntries(); entries.Parts = Parts.GetEntries(); entries.BoneNames = new List <BoneName>(); Lookups lookups; lookups.Models = MakeNameLookup(entries.Models); lookups.Parts = MakeNameLookup(entries.Parts); lookups.Collisions = MakeNameLookup(Parts.Collisions); lookups.BoneNames = new Dictionary <string, int>(); foreach (Part part in entries.Parts) { part.GetIndices(lookups); } foreach (PartPose pose in PartPoses) { pose.GetIndices(lookups, entries); } bw.BigEndian = Format == MSBFormat.DarkSouls2BE; bw.VarintLong = Format == MSBFormat.DarkSouls2Scholar; if (Format == MSBFormat.DarkSouls2Scholar) { MSB.WriteHeader(bw); } Models.Write(bw, entries.Models); bw.FillVarint("NextParamOffset", bw.Position); Events.Write(bw, entries.Events); bw.FillVarint("NextParamOffset", bw.Position); Regions.Write(bw, entries.Regions); bw.FillVarint("NextParamOffset", bw.Position); new RouteParam().Write(bw, new List <Entry>()); bw.FillVarint("NextParamOffset", bw.Position); new LayerParam().Write(bw, new List <Entry>()); bw.FillVarint("NextParamOffset", bw.Position); Parts.Write(bw, entries.Parts); bw.FillVarint("NextParamOffset", bw.Position); new MapstudioPartsPose().Write(bw, PartPoses); bw.FillVarint("NextParamOffset", bw.Position); new MapstudioBoneName().Write(bw, entries.BoneNames); bw.FillVarint("NextParamOffset", 0); }
internal override void Write(BinaryWriterEx bw, int id) { long start = bw.Position; bw.ReserveVarint("NameOffset"); bw.WriteInt32(EventID); bw.WriteByte((byte)Type); bw.WriteByte(0); bw.WriteInt16((short)id); bw.ReserveVarint("TypeDataOffset"); if (!bw.VarintLong) { bw.WriteInt32(0); bw.WriteInt32(0); } bw.FillVarint("NameOffset", bw.Position - start); bw.WriteUTF16(Name, true); bw.Pad(bw.VarintSize); bw.FillVarint("TypeDataOffset", bw.Position - start); WriteTypeData(bw); }
internal override void Write(BinaryWriterEx bw, int index) { long start = bw.Position; bw.WriteInt16(PartIndex); bw.WriteInt16((short)Bones.Count); if (bw.VarintLong) { bw.WriteInt32(0); } bw.ReserveVarint("BonesOffset"); bw.FillVarint("BonesOffset", bw.Position - start); foreach (Bone bone in Bones) { bone.Write(bw); } }
internal void WriteName(BinaryWriterEx bw, int index, long stringsOffset) { bw.FillVarint($"Event{index}NameOffset", bw.Position - stringsOffset); bw.WriteUTF16(Name, true); }
protected override void Write(BinaryWriterEx bw) { bool bigEndian = Format == Game.DarkSouls1BE; bool is64Bit = Format >= Game.Bloodborne; bool unk06 = Format >= Game.DarkSouls3; bool unk07 = Format >= Game.Sekiro; int version = Format < Game.DarkSouls3 ? 0xCC : 0xCD; var layers = new List <uint>(); foreach (Event evt in Events) { foreach (Instruction inst in evt.Instructions) { if (inst.Layer.HasValue && !layers.Contains(inst.Layer.Value)) { layers.Add(inst.Layer.Value); } } } bw.WriteASCII("EVD\0"); bw.WriteBoolean(bigEndian); bw.WriteSByte((sbyte)(is64Bit ? -1 : 0)); bw.WriteBoolean(unk06); bw.WriteSByte((sbyte)(unk07 ? -1 : 0)); bw.BigEndian = bigEndian; bw.VarintLong = is64Bit; bw.WriteInt32(version); bw.ReserveInt32("FileSize"); Offsets offsets = default; bw.WriteVarint(Events.Count); bw.ReserveVarint("EventsOffset"); bw.WriteVarint(Events.Sum(e => e.Instructions.Count)); bw.ReserveVarint("InstructionsOffset"); bw.WriteVarint(0); bw.ReserveVarint("Offset3"); bw.WriteVarint(layers.Count); bw.ReserveVarint("LayersOffset"); bw.WriteVarint(Events.Sum(e => e.Parameters.Count)); bw.ReserveVarint("ParametersOffset"); bw.WriteVarint(LinkedFileOffsets.Count); bw.ReserveVarint("LinkedFilesOffset"); bw.ReserveVarint("ArgumentsLength"); bw.ReserveVarint("ArgumentsOffset"); bw.WriteVarint(StringData.Length); bw.ReserveVarint("StringsOffset"); if (!is64Bit) { bw.WriteInt32(0); } offsets.Events = bw.Position; bw.FillVarint("EventsOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Events[i].Write(bw, Format, i); } offsets.Instructions = bw.Position; bw.FillVarint("InstructionsOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Events[i].WriteInstructions(bw, Format, offsets, i); } bw.FillVarint("Offset3", bw.Position); offsets.Layers = bw.Position; bw.FillVarint("LayersOffset", bw.Position); var layerOffsets = new Dictionary <uint, long>(layers.Count); foreach (uint layer in layers) { layerOffsets[layer] = bw.Position - offsets.Layers; Layer.Write(bw, layer); } for (int i = 0; i < Events.Count; i++) { Event evt = Events[i]; for (int j = 0; j < evt.Instructions.Count; j++) { evt.Instructions[j].FillLayerOffset(bw, Format, i, j, layerOffsets); } } offsets.Arguments = bw.Position; bw.FillVarint("ArgumentsOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Event evt = Events[i]; for (int j = 0; j < evt.Instructions.Count; j++) { evt.Instructions[j].WriteArgs(bw, Format, offsets, i, j); } } if ((bw.Position - offsets.Arguments) % 0x10 > 0) { bw.WritePattern(0x10 - (int)(bw.Position - offsets.Arguments) % 0x10, 0x00); } bw.FillVarint("ArgumentsLength", bw.Position - offsets.Arguments); offsets.Parameters = bw.Position; bw.FillVarint("ParametersOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Events[i].WriteParameters(bw, Format, offsets, i); } offsets.LinkedFiles = bw.Position; bw.FillVarint("LinkedFilesOffset", bw.Position); foreach (long offset in LinkedFileOffsets) { bw.WriteVarint((int)offset); } offsets.Strings = bw.Position; bw.FillVarint("StringsOffset", bw.Position); bw.WriteBytes(StringData); bw.FillInt32("FileSize", (int)bw.Position); }
protected override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.VarintLong = Version == MQBVersion.DarkSouls2Scholar; bw.WriteASCII("MQB "); bw.WriteSByte((sbyte)(BigEndian ? -1 : 0)); bw.WriteByte(0); bw.WriteSByte((sbyte)(Version == MQBVersion.DarkSouls2Scholar ? -1 : 0)); bw.WriteByte(0); bw.WriteUInt32((uint)Version); switch (Version) { case MQBVersion.DarkSouls2: bw.WriteInt32(0x14); break; case MQBVersion.DarkSouls2Scholar: bw.WriteInt32(0x28); break; case MQBVersion.Bloodborne: bw.WriteInt32(0x20); break; case MQBVersion.DarkSouls3: bw.WriteInt32(0x24); break; default: throw new NotImplementedException($"Missing header size for version {Version}."); } bw.ReserveVarint("ResourcePathsOffset"); if (Version == MQBVersion.DarkSouls2Scholar) { bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); } else if (Version >= MQBVersion.Bloodborne) { bw.WriteInt32(1); bw.WriteInt32(0); bw.WriteInt32(0); if (Version >= MQBVersion.DarkSouls3) { bw.WriteInt32(0); } } bw.WriteFixStrW(Name, 0x40, 0x00); bw.WriteSingle(Framerate); bw.WriteInt32(Resources.Count); bw.WriteInt32(Cuts.Count); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); var allCustomData = new List <CustomData>(); var customDataValueOffsets = new List <long>(); for (int i = 0; i < Resources.Count; i++) { Resources[i].Write(bw, i, allCustomData, customDataValueOffsets); } var offsetsByDispos = new Dictionary <Disposition, long>(); for (int i = 0; i < Cuts.Count; i++) { Cuts[i].Write(bw, Version, offsetsByDispos, i, allCustomData, customDataValueOffsets); } for (int i = 0; i < Cuts.Count; i++) { Cuts[i].WriteTimelines(bw, Version, i); } for (int i = 0; i < Cuts.Count; i++) { Cuts[i].WriteTimelineCustomData(bw, i, allCustomData, customDataValueOffsets); } for (int i = 0; i < Cuts.Count; i++) { Cuts[i].WriteDisposOffsets(bw, offsetsByDispos, i); } bw.FillVarint("ResourcePathsOffset", bw.Position); for (int i = 0; i < Resources.Count; i++) { bw.ReserveVarint($"ResourcePathOffset{i}"); } bw.WriteUTF16(ResourceDirectory, true); for (int i = 0; i < Resources.Count; i++) { if (Resources[i].Path == null) { bw.FillVarint($"ResourcePathOffset{i}", 0); } else { bw.FillVarint($"ResourcePathOffset{i}", bw.Position); bw.WriteUTF16(Resources[i].Path, true); } } // I know this is weird, but trust me. if (Version >= MQBVersion.Bloodborne) { bw.WriteInt16(0); bw.Pad(4); } for (int i = 0; i < allCustomData.Count; i++) { allCustomData[i].WriteSequences(bw, i, customDataValueOffsets[i]); } for (int i = 0; i < allCustomData.Count; i++) { allCustomData[i].WriteSequencePoints(bw, i); } }
internal void Write(BinaryWriterEx bw, NGPVersion version) { long start = bw.Position; bw.WriteInt32(Unk00); bw.ReserveInt32("MeshLength"); bw.WriteInt32(Unk08); if (version == NGPVersion.Scholar) { bw.WriteInt32(0); } bw.WriteVector3(BoundingBoxMin); bw.WriteVector3(BoundingBoxMax); bw.WriteInt32(Vertices.Count); bw.WriteInt16((short)Faces.Count); bw.WriteInt16((short)Struct4s.Count); bw.WriteInt16(Unk30); bw.WriteInt16(Unk32); bw.WriteByte(1); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); if (version == NGPVersion.Scholar) { bw.WriteInt64(0); } bw.ReserveVarint("VerticesOffset"); bw.ReserveVarint("Struct2sOffset"); bw.ReserveVarint("FacesOffset"); bw.ReserveVarint("Struct4sOffset"); bw.ReserveVarint("Struct5sOffset"); bw.ReserveVarint("Struct6sOffset"); bw.FillVarint("VerticesOffset", bw.Position); foreach (Vector3 vertex in Vertices) { bw.WriteVector3(vertex); } bw.Pad(bw.VarintSize); bw.FillVarint("Struct2sOffset", bw.Position); foreach (int struct2 in Struct2s) { bw.WriteInt32(struct2); } bw.Pad(bw.VarintSize); bw.FillVarint("FacesOffset", bw.Position); foreach (Face face in Faces) { face.Write(bw); } bw.Pad(bw.VarintSize); bw.FillVarint("Struct4sOffset", bw.Position); foreach (Struct4 struct4 in Struct4s) { struct4.Write(bw); } bw.Pad(bw.VarintSize); bw.FillVarint("Struct5sOffset", bw.Position); short index = 0; Struct5Root.Write(bw, ref index); bw.Pad(bw.VarintSize); bw.FillVarint("Struct6sOffset", bw.Position); index = 0; int faceIndexIndex = 0; Struct5Root.WriteFaceIndices(bw, ref index, ref faceIndexIndex); bw.Pad(bw.VarintSize); bw.FillInt32("MeshLength", (int)(bw.Position - start)); }
protected override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.VarintLong = Version == NGPVersion.Scholar; bw.WriteASCII("NVG2"); bw.WriteUInt16((ushort)Version); bw.WriteInt16(0); bw.WriteInt32(Meshes.Count); bw.WriteInt32(StructAs.Count); bw.WriteInt32(StructBs.Count); bw.WriteInt32(StructCs.Count); bw.WriteInt32(StructDs.Count); bw.WriteInt32(Unk1C); bw.ReserveVarint("OffsetA"); bw.ReserveVarint("OffsetB"); bw.ReserveVarint("OffsetC"); bw.ReserveVarint("OffsetD"); for (int i = 0; i < Meshes.Count; i++) { bw.ReserveVarint($"MeshOffset{i}"); } void writeMeshes() { for (int i = 0; i < Meshes.Count; i++) { bw.Pad(bw.VarintSize); bw.FillVarint($"MeshOffset{i}", bw.Position); Meshes[i].Write(bw, Version); } } if (Version == NGPVersion.Vanilla) { writeMeshes(); } bw.Pad(bw.VarintSize); bw.FillVarint("OffsetA", bw.Position); foreach (StructA structA in StructAs) { structA.Write(bw); } bw.Pad(bw.VarintSize); bw.FillVarint("OffsetB", bw.Position); foreach (StructB structB in StructBs) { structB.Write(bw); } bw.Pad(bw.VarintSize); bw.FillVarint("OffsetC", bw.Position); bw.WriteInt32s(StructCs); bw.Pad(bw.VarintSize); bw.FillVarint("OffsetD", bw.Position); bw.WriteInt16s(StructDs); if (Version == NGPVersion.Scholar) { writeMeshes(); } }