/// <summary> /// Serializes file data to a stream. /// </summary> protected 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 override void Write(BinaryWriterEx bw, int id) { long start = bw.Position; bw.ReserveInt32("NameOffset"); bw.WriteUInt32((uint)Type); bw.WriteInt32(id); bw.WriteInt32(ModelIndex); bw.ReserveInt32("SibOffset"); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.WriteVector3(Scale); bw.WriteUInt32s(DrawGroups); bw.WriteUInt32s(DispGroups); bw.ReserveInt32("EntityDataOffset"); bw.ReserveInt32("TypeDataOffset"); bw.WriteInt32(0); long stringsStart = bw.Position; bw.FillInt32("NameOffset", (int)(bw.Position - start)); bw.WriteShiftJIS(ReambiguateName(Name), true); bw.FillInt32("SibOffset", (int)(bw.Position - start)); bw.WriteShiftJIS(Placeholder, true); bw.Pad(4); if (bw.Position - stringsStart < 0x14) { bw.WritePattern((int)(0x14 - (bw.Position - stringsStart)), 0x00); } bw.FillInt32("EntityDataOffset", (int)(bw.Position - start)); bw.WriteInt32(EntityID); bw.WriteByte(LightID); bw.WriteByte(FogID); bw.WriteByte(ScatterID); bw.WriteByte(LensFlareID); bw.WriteByte(ShadowID); bw.WriteByte(DofID); bw.WriteByte(ToneMapID); bw.WriteByte(ToneCorrectID); bw.WriteByte(LanternID); bw.WriteByte(LodParamID); bw.WriteByte(0); bw.WriteByte(IsShadowSrc); bw.WriteByte(IsShadowDest); bw.WriteByte(IsShadowOnly); bw.WriteByte(DrawByReflectCam); bw.WriteByte(DrawOnlyReflectCam); bw.WriteByte(UseDepthBiasFloat); bw.WriteByte(DisablePointLightEffect); bw.WriteByte(0); bw.WriteByte(0); bw.FillInt32("TypeDataOffset", (int)(bw.Position - start)); }
internal void Write(BinaryWriterEx bw, FLVERHeader header) { foreach (GXItem item in this) { item.Write(bw, header); } bw.WriteInt32(int.MaxValue); bw.WriteInt32(100); bw.WriteInt32(TerminatorLength + 0xC); bw.WritePattern(TerminatorLength, 0x00); }
internal void Write(BinaryWriterEx bw, BTPBVersion version) { bw.WriteInt16s(Coefficients); bw.WriteInt16(LightMask); bw.WriteInt16(Unk1A); if (version >= BTPBVersion.Bloodborne) { bw.WriteVector3(Position); bw.WritePattern(0x20, 0x00); } }
internal override void Write(BinaryWriterEx bw, int index) { long start = bw.Position; bw.ReserveInt64("NameOffset"); bw.WriteInt16(Unk08); bw.WriteByte((byte)Type); bw.WriteByte((byte)Shape.Type); bw.WriteInt16((short)index); bw.WriteInt16(Unk0E); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.ReserveInt64("UnkOffsetA"); bw.ReserveInt64("UnkOffsetB"); bw.WriteInt32(-1); bw.WritePattern(0x24, 0x00); bw.ReserveInt64("ShapeDataOffset"); bw.ReserveInt64("TypeDataOffset"); bw.WriteInt64(0); bw.WriteInt64(0); bw.FillInt64("NameOffset", bw.Position - start); bw.WriteUTF16(Name, true); bw.Pad(4); bw.FillInt64("UnkOffsetA", bw.Position - start); bw.WriteInt32(0); bw.FillInt64("UnkOffsetB", bw.Position - start); bw.WriteInt32(0); bw.Pad(8); if (Shape.HasShapeData) { bw.FillInt64("ShapeDataOffset", bw.Position - start); Shape.WriteShapeData(bw); } else { bw.FillInt64("ShapeDataOffset", 0); } if (HasTypeData) { bw.FillInt64("TypeDataOffset", bw.Position - start); WriteTypeData(bw); } else { bw.FillInt64("TypeDataOffset", 0); } }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(UnkT00); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt16s(WalkRegionIndices); for (int i = 0; i < 5; i++) { WREntries[i].Write(bw); } bw.WritePattern(0x14, 0x00); }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteSingle(UnkT00); bw.WriteSingle(Compare); bw.WriteByte(UnkT08); bw.WriteByte(UnkT09); bw.WriteInt16(UnkT0A); bw.WritePattern(0x18, 0x00); bw.WriteInt32(UnkT24); bw.WriteSingle(UnkT28); bw.WriteSingle(UnkT2C); bw.WriteInt32(0); }
private protected override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(0); bw.WriteSingle(UnkT04); bw.WriteSingle(UnkT08); bw.WriteSingle(UnkT0C); bw.WriteInt32(0); bw.WriteSingle(UnkT14); bw.WriteSingle(UnkT18); bw.WriteInt32(0); bw.WriteSingle(UnkT20); bw.WriteRGBA(ColorT24); bw.WritePattern(0x18, 0x00); }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(UnkT00); bw.WriteSingle(UnkT04); bw.WriteSingle(UnkT08); bw.WriteSingle(UnkT0C); bw.WriteInt32(UnkT10); bw.WriteRGBA(ColorT14); bw.WriteSingle(UnkT18); bw.WriteInt32(UnkT1C); bw.WriteSingle(UnkT20); bw.WriteRGBA(ColorT24); bw.WritePattern(0x18, 0x00); }
internal void Write(BinaryWriterEx bw, int index) { bw.WriteVector3(Position); bw.ReserveInt32($"BoneName{index}"); bw.WriteVector3(Rotation); bw.WriteInt16(ParentIndex); bw.WriteInt16(ChildIndex); bw.WriteVector3(Scale); bw.WriteInt16(NextSiblingIndex); bw.WriteInt16(PreviousSiblingIndex); bw.WriteVector3(BoundingBoxMin); bw.WriteInt32(Unk3C); bw.WriteVector3(BoundingBoxMax); bw.WritePattern(0x34, 0x00); }
internal override void Write(BinaryWriterEx bw, int id) { long start = bw.Position; bw.ReserveInt64("NameOffset"); bw.WriteInt32(Unk08); bw.WriteInt32(Unk0C); bw.WriteUInt32((uint)Type); bw.WriteInt32(id); bw.WritePattern(0x68, 0x00); bw.FillInt64("NameOffset", bw.Position - start); bw.WriteUTF16(Name, true); bw.Pad(8); }
private protected override void WriteTypeData(BinaryWriterEx bw) { bw.WriteByte(UnkT00); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.WriteRGBA(ColorT04); bw.WriteSingle(UnkT08); bw.WriteSingle(UnkT0C); bw.WriteSingle(UnkT10); bw.WriteByte(UnkT14); bw.WriteByte(UnkT15); bw.WriteByte(UnkT16); bw.WritePattern(0x11, 0x00); }
internal void Write(BinaryWriterEx bw, PARAMDEF def, int index) { if (def.Unicode) { bw.WriteFixStrW(DisplayName, 0x40, (byte)(def.Version >= 104 ? 0x00 : 0x20)); } else { bw.WriteFixStr(DisplayName, 0x40, (byte)(def.Version >= 104 ? 0x00 : 0x20)); } byte padding = (byte)(def.Version >= 201 ? 0x00 : 0x20); bw.WriteFixStr(DisplayType.ToString(), 8, padding); bw.WriteFixStr(DisplayFormat, 8, padding); bw.WriteSingle(Default); bw.WriteSingle(Minimum); bw.WriteSingle(Maximum); bw.WriteSingle(Increment); bw.WriteInt32((int)EditFlags); bw.WriteInt32(ByteCount); if (def.Version >= 201) { bw.ReserveInt64($"DescriptionOffset{index}"); } else { bw.ReserveInt32($"DescriptionOffset{index}"); } bw.WriteFixStr(InternalType, 0x20, padding); if (def.Version >= 102) { bw.WriteFixStr(InternalName, 0x20, padding); } if (def.Version >= 104) { bw.WriteInt32(SortID); } if (def.Version >= 201) { bw.WritePattern(0x1C, 0x00); } }
internal void Write(BinaryWriterEx bw, int index) { bw.WriteInt32(index); bw.WriteInt32(Version); bw.ReserveInt32("SectionLength"); bw.WriteInt32(Count); long start = bw.Position; WriteEntries(bw); if (bw.Position % 0x10 != 0) { bw.WritePattern(0x10 - (int)bw.Position % 0x10, 0xFF); } bw.FillInt32("SectionLength", (int)(bw.Position - start)); }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(TreasurePartIndex); bw.WriteInt32(0); bw.WriteInt32(ItemLotID); bw.WritePattern(0x24, 0xFF); bw.WriteInt32(ActionButtonID); bw.WriteInt32(PickupAnimID); bw.WriteBoolean(InChest); bw.WriteBoolean(StartDisabled); bw.WriteInt16(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); }
internal void Write(BinaryWriterEx bw, FLVERHeader header) { if (header.Version < 0x20010) { this[0].Write(bw, header); } else { foreach (GXItem item in this) { item.Write(bw, header); } bw.WriteInt32(TerminatorID); bw.WriteInt32(100); bw.WriteInt32(TerminatorLength + 0xC); bw.WritePattern(TerminatorLength, 0x00); } }
internal override void Write(BinaryWriterEx bw) { bw.BigEndian = false; bw.WriteInt32(2); bw.WriteInt32(Version); bw.WriteInt32(Lights.Count); bw.ReserveInt32("NamesLength"); bw.WriteInt32(0); bw.WriteInt32(Version == 16 ? 0xE8 : (LongOffsets ? 0xC8 : 0xC0)); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); long namesStart = bw.Position; var nameOffsets = new List <long>(Lights.Count); foreach (Light entry in Lights) { long nameOffset = bw.Position - namesStart; nameOffsets.Add(nameOffset); bw.WriteUTF16(entry.Name, true); if (nameOffset % 0x10 != 0) { bw.WritePattern((int)(0x10 - (nameOffset % 0x10)), 0x00); } } bw.FillInt32("NamesLength", (int)(bw.Position - namesStart)); for (int i = 0; i < Lights.Count; i++) { Lights[i].Write(bw, nameOffsets[i], Version, LongOffsets); } }
internal override void Write(BinaryWriterEx bw, int id) { long start = bw.Position; bw.ReserveInt32("NameOffset"); bw.WriteUInt32((uint)Type); bw.WriteInt32(id); bw.WriteInt32(ModelIndex); bw.ReserveInt32("SibOffset"); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.WriteVector3(Scale); bw.WriteUInt32s(DrawGroups); bw.WriteUInt32s(DispGroups); bw.ReserveInt32("EntityDataOffset"); bw.ReserveInt32("TypeDataOffset"); bw.WriteInt32(0); bw.WriteInt32(0); long stringsStart = bw.Position; bw.FillInt32("NameOffset", (int)(bw.Position - start)); bw.WriteShiftJIS(MSB.ReambiguateName(Name), true); bw.FillInt32("SibOffset", (int)(bw.Position - start)); bw.WriteShiftJIS(SibPath, true); bw.Pad(4); if (bw.Position - stringsStart < 0x10) { bw.WritePattern((int)(0x10 - (bw.Position - stringsStart)), 0x00); } bw.FillInt32("EntityDataOffset", (int)(bw.Position - start)); WriteEntityData(bw); bw.FillInt32("TypeDataOffset", (int)(bw.Position - start)); WriteTypeData(bw); }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.VarintLong = LongFormat; bw.WriteInt32(1); bw.WriteInt32(0); bw.WriteInt32(Entries.Count); bw.ReserveInt32("StringsLength"); bw.WriteBoolean(BigEndian); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(LongFormat ? 0x28 : 0x1C); bw.WritePattern(0x24, 0x00); long stringsStart = bw.Position; var stringOffsets = new List <long>(Entries.Count * 2); foreach (Entry entry in Entries) { long partNameOffset = bw.Position - stringsStart; stringOffsets.Add(partNameOffset); bw.WriteUTF16(entry.PartName, true); bw.PadRelative(stringsStart, 8); // This padding is not consistent, but it's the best I can do long materialNameOffset = bw.Position - stringsStart; stringOffsets.Add(materialNameOffset); bw.WriteUTF16(entry.MaterialName, true); bw.PadRelative(stringsStart, 8); } bw.FillInt32("StringsLength", (int)(bw.Position - stringsStart)); for (int i = 0; i < Entries.Count; i++) { Entries[i].Write(bw, stringOffsets[i * 2], stringOffsets[i * 2 + 1]); } }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt16(UnkT00); bw.WriteInt16(-1); bw.WriteSingle(UnkT04); bw.WriteSingle(UnkT08); bw.WriteRGBA(ColorT0C); bw.WriteRGBA(ColorT10); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteSingle(UnkT1C); bw.WriteSingle(UnkT20); bw.WriteRGBA(ColorT24); bw.WriteRGBA(ColorT28); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteRGBA(ColorT34); bw.WriteRGBA(ColorT38); bw.WriteRGBA(ColorT3C); bw.WriteSingle(UnkT40); bw.WriteInt32(UnkT44); bw.WritePattern(0x38, 0x00); }
private protected override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(UnkT00); bw.WriteInt32(UnkT04); bw.WriteInt32(UnkT08); bw.WriteInt32(UnkT0C); bw.WriteByte(UnkT10); bw.WriteByte(UnkT11); bw.WriteByte(UnkT12); bw.WriteByte(UnkT13); bw.WriteByte(UnkT14); bw.WriteByte(UnkT15); bw.WriteByte(0); bw.WriteByte(UnkT17); bw.WriteInt32(UnkT18); bw.WriteInt32(UnkT1C); bw.WriteInt32(UnkT20); bw.WriteInt16(0); bw.WriteByte(UnkT26); bw.WriteByte(UnkT27); bw.WriteInt32(UnkT28); bw.WriteByte(UnkT2C); bw.WriteByte(0); bw.WriteInt16(UnkT2E); bw.WriteInt32(UnkT30); bw.WriteByte(0); bw.WriteByte(UnkT35); bw.WriteInt16(UnkT36); bw.WriteInt32(0); bw.WriteInt32(UnkT3C); bw.WriteByte(UnkT40); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(UnkT44); bw.WritePattern(0x10, 0x00); }
private protected override void WriteTypeData(BinaryWriterEx bw) { bw.WriteByte(UnkT00); bw.WriteByte(0); bw.WriteInt16(-1); bw.WriteSingle(UnkT04); bw.WriteSingle(UnkT08); bw.WriteRGBA(ColorT0C); bw.WriteRGBA(ColorT10); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteSingle(UnkT1C); bw.WriteSingle(UnkT20); bw.WriteRGBA(ColorT24); bw.WriteRGBA(ColorT28); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteRGBA(ColorT34); bw.WriteRGBA(ColorT38); bw.WriteRGBA(ColorT3C); bw.WriteSingle(UnkT40); bw.WriteByte(UnkT44); bw.WritePattern(0x3B, 0x00); }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(UnkT00); bw.WriteInt32(UnkT04); bw.WritePattern(0x18, 0x00); }
internal override void Write(BinaryWriterEx bw) { if (layout == null) { throw new InvalidOperationException("Params cannot be written without a layout."); } Rows.Sort((r1, r2) => r1.ID.CompareTo(r2.ID)); bw.BigEndian = BigEndian; void WriteFormat() { bw.WriteByte((byte)(BigEndian ? 0xFF : 0x00)); bw.WriteByte(Format2D); bw.WriteByte(Format2E); bw.WriteByte(Format2F); } // DeS, DS1 if ((Format2D & 0x7F) < 3) { bw.ReserveUInt32("StringsOffset"); bw.ReserveUInt16("DataStart"); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteFixStr(ID, 0x20, 0x20); WriteFormat(); } // DS2 else if ((Format2D & 0x7F) == 3) { bw.ReserveUInt32("StringsOffset"); bw.WriteInt16(0); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteFixStr(ID, 0x20, 0x20); WriteFormat(); bw.ReserveUInt32("DataStart"); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); } // SotFS, BB else if ((Format2D & 0x7F) == 4) { bw.ReserveUInt32("StringsOffset"); bw.WriteInt16(0); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteFixStr(ID, 0x20, 0x00); WriteFormat(); bw.ReserveInt64("DataStart"); bw.WriteInt64(0); } // DS3, SDT else { bw.ReserveUInt32("StringsOffset"); bw.WriteInt16(0); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteInt32(0); bw.ReserveInt64("IDOffset"); bw.WritePattern(0x14, 0x00); WriteFormat(); bw.ReserveInt64("DataStart"); bw.WriteInt64(0); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteHeader(bw, Format2D, i); } if ((Format2D & 0x7F) < 3) { bw.FillUInt16("DataStart", (ushort)bw.Position); } else if ((Format2D & 0x7F) == 3) { bw.FillUInt32("DataStart", (uint)bw.Position); } else { bw.FillInt64("DataStart", bw.Position); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteCells(bw, Format2D, i, layout); } bw.FillUInt32("StringsOffset", (uint)bw.Position); if ((Format2D & 0x7F) > 4) { bw.FillInt64("IDOffset", bw.Position); bw.WriteASCII(ID, true); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteName(bw, Format2D, i); } }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { bool bigEndian; int unk00, unk04, groupSize, probeSize; if (Version == BTPBVersion.DarkSouls2LE || Version == BTPBVersion.DarkSouls2BE) { bigEndian = Version == BTPBVersion.DarkSouls2BE; unk00 = 2; unk04 = 1; groupSize = 0x40; probeSize = 0x1C; } else if (Version == BTPBVersion.Bloodborne) { bigEndian = false; unk00 = 2; unk04 = 1; groupSize = 0x48; probeSize = 0x48; } else if (Version == BTPBVersion.DarkSouls3) { bigEndian = false; unk00 = 3; unk04 = 0; groupSize = 0x98; probeSize = 0x48; } else { throw new NotImplementedException($"Write is apparently not supported for BTPB version {Version}."); } bw.BigEndian = bigEndian; bw.VarintLong = Version >= BTPBVersion.Bloodborne; bw.WriteInt32(unk00); bw.WriteInt32(unk04); bw.WriteInt32(Groups.Count); bw.ReserveInt32("DataLength"); bw.WriteBoolean(bigEndian); bw.WritePattern(3, 0x00); bw.WriteInt32(groupSize); bw.WriteInt32(probeSize); bw.WriteVector3(Unk1C); bw.WriteVector3(Unk28); bw.WriteInt64(0); long[] nameOffsets = new long[Groups.Count]; long[] probesOffsets = new long[Groups.Count]; long dataStart = bw.Position; for (int i = 0; i < Groups.Count; i++) { Groups[i].WriteData(bw, Version, dataStart, out nameOffsets[i], out probesOffsets[i]); } bw.FillInt32("DataLength", (int)(bw.Position - dataStart)); for (int i = 0; i < Groups.Count; i++) { Groups[i].Write(bw, Version, nameOffsets[i], probesOffsets[i]); } }
internal override void WriteTypeData(BinaryWriterEx bw) { bw.WriteRGBA(Color); bw.WritePattern(0x24, 0x00); }
internal override void Write(BinaryWriterEx bw) { bw.WriteASCII("EVD\0"); if (Game == GameType.DS1) { bw.WriteUInt32(0); bw.WriteUInt32(0xCC); } else if (Game == GameType.BB) { bw.WriteUInt32(0xFF00); bw.WriteUInt32(0xCC); } else if (Game == GameType.DS3) { bw.WriteUInt32(0x1FF00); bw.WriteUInt32(0xCD); } void ReserveIntW(string name, bool?isWide = null) { if (isWide ?? Game != GameType.DS1) { bw.ReserveInt64(name); } else { bw.ReserveInt32(name); } } void FillIntW(string name, long value, bool?isWide = null) { if (isWide ?? Game != GameType.DS1) { bw.FillInt64(name, value); } else { bw.FillInt32(name, (int)value); } } void WriteIntW(long value, bool?isWide = null) { if (isWide ?? Game != GameType.DS1) { bw.WriteInt64(value); } else { bw.WriteInt32((int)value); } } if (Game == GameType.BB) { bw.ReserveInt64("FileLength"); } else { bw.ReserveInt32("FileLength"); } WriteIntW(Events.Count); ReserveIntW("EventsOffset"); ReserveIntW("InstructionsCount"); ReserveIntW("InstructionsOffset"); //Dummy count. Always empty. WriteIntW(0); // Same as EventLayersOffset because it's always empty. ReserveIntW("DummiesOffset"); ReserveIntW("EventLayersCount"); ReserveIntW("EventLayersOffset"); ReserveIntW("ParametersCount"); ReserveIntW("ParametersOffset"); WriteIntW(LinkedFileStringIndices.Count); ReserveIntW("LinkedFilesOffset"); ReserveIntW("ArgsBlockSize"); ReserveIntW("ArgsBlockOffset"); ReserveIntW("StringsBlockSize"); ReserveIntW("StringsBlockOffset"); if (Game == GameType.DS1) { bw.WriteInt32(0); } // Events FillIntW("EventsOffset", bw.Position); for (int i = 0; i < Events.Count; i++) { Events[i].Write(bw, Game, i); } // Instructions long instructionsOffset = bw.Position; FillIntW("InstructionsOffset", instructionsOffset); long instructionsCount = 0; for (int i = 0; i < Events.Count; i++) { FillIntW($"EventInstructionsOffset{i}", bw.Position - instructionsOffset); for (int j = 0; j < Events[i].Instructions.Count; j++) { Events[i].Instructions[j].Write(bw, Game, i, j); } instructionsCount += Events[i].Instructions.Count; } FillIntW("InstructionsCount", instructionsCount); // Dummies FillIntW("DummiesOffset", bw.Position); // EventLayers long eventLayersOffset = bw.Position; FillIntW("EventLayersOffset", eventLayersOffset); long eventLayersCount = 0; for (int i = 0; i < Events.Count; i++) { for (int j = 0; j < Events[i].Instructions.Count; j++) { if (Events[i].Instructions[j].Layer != null) { if (Game == GameType.DS3) { bw.FillInt64($"InstructionLayerOffset{i}:{j}", bw.Position - eventLayersOffset); } else { bw.FillInt32($"InstructionLayerOffset{i}:{j}", (int)(bw.Position - eventLayersOffset)); } Events[i].Instructions[j].Layer.Write(bw, Game); eventLayersCount++; } } } FillIntW("EventLayersCount", eventLayersCount); // Args long argsBlockOffset = bw.Position; FillIntW("ArgsBlockOffset", argsBlockOffset); for (int i = 0; i < Events.Count; i++) { for (int j = 0; j < Events[i].Instructions.Count; j++) { if (Events[i].Instructions[j].Args.Length > 0) { bw.FillInt32($"InstructionArgsOffset{i}:{j}", (int)(bw.Position - argsBlockOffset)); bw.WriteBytes(Events[i].Instructions[j].Args); //bw.Pad(4); } } } if (Game == GameType.DS1) { if ((bw.Position - argsBlockOffset) % 16 > 0) { bw.WritePattern(16 - (int)(bw.Position - argsBlockOffset) % 16, 0x00); } } else { bw.Pad(16); } FillIntW("ArgsBlockSize", bw.Position - argsBlockOffset); // Parameters long parametersOffset = bw.Position; FillIntW("ParametersOffset", parametersOffset); long parametersCount = 0; for (int i = 0; i < Events.Count; i++) { if (Events[i].Parameters.Count > 0) { if (Game == GameType.DS3) { bw.FillInt64($"EventParametersOffset{i}", bw.Position - parametersOffset); } else { bw.FillInt32($"EventParametersOffset{i}", (int)(bw.Position - parametersOffset)); } for (int j = 0; j < Events[i].Parameters.Count; j++) { Events[i].Parameters[j].Write(bw, Game); } parametersCount += Events[i].Parameters.Count; } } FillIntW("ParametersCount", parametersCount); // Linked Files FillIntW("LinkedFilesOffset", bw.Position); for (int i = 0; i < LinkedFileStringIndices.Count; i++) { ReserveIntW($"LinkedFileStringOffset{i}"); } // Strings FillIntW("StringsBlockOffset", bw.Position); long stringsStartOffset = bw.Position; List <long> stringTableOffsets = new List <long>(); for (int i = 0; i < StringTable.Count; i++) { stringTableOffsets.Add(bw.Position - stringsStartOffset); bw.WriteUTF16(StringTable[i], terminate: true); } FillIntW("StringsBlockSize", bw.Position - stringsStartOffset); // Linked Files - Second Pass for (int i = 0; i < LinkedFileStringIndices.Count; i++) { FillIntW($"LinkedFileStringOffset{i}", stringTableOffsets[LinkedFileStringIndices[i]]); } if (Game == GameType.BB) { bw.FillInt64("FileLength", bw.Position); } else { bw.FillInt32("FileLength", (int)bw.Position); } }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { if (AppliedParamdef == null) { throw new InvalidOperationException("Params cannot be written without applying a paramdef."); } bw.BigEndian = BigEndian; void WriteFormat() { bw.WriteByte((byte)(BigEndian ? 0xFF : 0x00)); bw.WriteByte(Format2D); bw.WriteByte(Format2E); bw.WriteByte(Format2F); } // DeS, DS1 if ((Format2D & 0x7F) < 3) { bw.ReserveUInt32("StringsOffset"); bw.ReserveUInt16("DataStart"); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteFixStr(ParamType, 0x20, (byte)((Format2D & 0x7F) < 2 ? 0x20 : 0x00)); WriteFormat(); } // DS2 else if ((Format2D & 0x7F) == 3) { bw.ReserveUInt32("StringsOffset"); bw.WriteInt16(0); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteFixStr(ParamType, 0x20, 0x20); WriteFormat(); bw.ReserveUInt32("DataStart"); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); } // SotFS, BB else if ((Format2D & 0x7F) == 4) { bw.ReserveUInt32("StringsOffset"); bw.WriteInt16(0); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteFixStr(ParamType, 0x20, 0x00); WriteFormat(); bw.ReserveInt64("DataStart"); bw.WriteInt64(0); } // DS3, SDT else { bw.ReserveUInt32("StringsOffset"); bw.WriteInt16(0); bw.WriteInt16(Unk06); bw.WriteInt16(Unk08); bw.WriteUInt16((ushort)Rows.Count); bw.WriteInt32(0); bw.ReserveInt64("IDOffset"); bw.WritePattern(0x14, 0x00); WriteFormat(); bw.ReserveInt64("DataStart"); bw.WriteInt64(0); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteHeader(bw, Format2D, i); } if ((Format2D & 0x7F) < 2) { bw.WritePattern(0x20, 0x00); } if ((Format2D & 0x7F) < 3) { bw.FillUInt16("DataStart", (ushort)bw.Position); } else if ((Format2D & 0x7F) == 3) { bw.FillUInt32("DataStart", (uint)bw.Position); } else { bw.FillInt64("DataStart", bw.Position); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteCells(bw, Format2D, i); } bw.FillUInt32("StringsOffset", (uint)bw.Position); if ((Format2D & 0x7F) > 4) { bw.FillInt64("IDOffset", bw.Position); bw.WriteASCII(ParamType, true); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteName(bw, Format2D, Format2E, i); } // DeS and BB sometimes (but not always) include some useless padding here }
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); }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { if (AppliedParamdef == null) { throw new InvalidOperationException("Params cannot be written without applying a paramdef."); } bw.BigEndian = BigEndian; bw.ReserveUInt32("StringsOffset"); if (Format2D.HasFlag(FormatFlags1.Flag01) && Format2D.HasFlag(FormatFlags1.IntDataOffset) || Format2D.HasFlag(FormatFlags1.LongDataOffset)) { bw.WriteInt16(0); } else { bw.ReserveUInt16("DataStart"); } bw.WriteInt16(Unk06); bw.WriteInt16(ParamdefDataVersion); bw.WriteUInt16((ushort)Rows.Count); if (Format2D.HasFlag(FormatFlags1.OffsetParamType)) { bw.WriteInt32(0); bw.ReserveInt64("ParamTypeOffset"); bw.WritePattern(0x14, 0x00); } else { // This padding heuristic isn't completely accurate, not that it matters bw.WriteFixStr(ParamType, 0x20, (byte)(Format2D.HasFlag(FormatFlags1.Flag01) ? 0x20 : 0x00)); } bw.WriteByte((byte)(BigEndian ? 0xFF : 0x00)); bw.WriteByte((byte)Format2D); bw.WriteByte((byte)Format2E); bw.WriteByte(ParamdefFormatVersion); if (Format2D.HasFlag(FormatFlags1.Flag01) && Format2D.HasFlag(FormatFlags1.IntDataOffset)) { bw.ReserveUInt32("DataStart"); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); } else if (Format2D.HasFlag(FormatFlags1.LongDataOffset)) { bw.ReserveInt64("DataStart"); bw.WriteInt64(0); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteHeader(bw, this, i); } // This is probably pretty stupid if (Format2D == FormatFlags1.Flag01) { bw.WritePattern(0x20, 0x00); } if (Format2D.HasFlag(FormatFlags1.Flag01) && Format2D.HasFlag(FormatFlags1.IntDataOffset)) { bw.FillUInt32("DataStart", (uint)bw.Position); } else if (Format2D.HasFlag(FormatFlags1.LongDataOffset)) { bw.FillInt64("DataStart", bw.Position); } else { bw.FillUInt16("DataStart", (ushort)bw.Position); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteCells(bw, this, i); } bw.FillUInt32("StringsOffset", (uint)bw.Position); if (Format2D.HasFlag(FormatFlags1.OffsetParamType)) { bw.FillInt64("ParamTypeOffset", bw.Position); bw.WriteASCII(ParamType, true); } for (int i = 0; i < Rows.Count; i++) { Rows[i].WriteName(bw, this, i); } // DeS and BB sometimes (but not always) include some useless padding here }