private protected override void WriteTypeData(BinaryWriterEx bw) { bw.WriteInt32(0); bw.WriteSByte(BreakTerm); bw.WriteSByte(NetSyncType); bw.WriteInt16(0); bw.WriteInt16(InitAnimID); bw.WriteInt16(UnkT0E); bw.WriteInt32(UnkT10); bw.WriteInt32(0); bw.WriteInt32(0); }
private protected override void WriteTypeData(BinaryWriterEx bw) { bw.WriteByte(MaxNum); bw.WriteSByte(GenType); bw.WriteInt16(LimitNum); bw.WriteInt16(MinGenNum); bw.WriteInt16(MaxGenNum); bw.WriteSingle(MinInterval); bw.WriteSingle(MaxInterval); bw.WriteByte(InitialSpawnCount); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.WriteSingle(UnkT14); bw.WriteSingle(UnkT18); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32s(SpawnPointIndices); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32s(SpawnPartIndices); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); }
internal void WriteValue(BinaryWriterEx bw, object value) { switch (Type) { case ParamType.aob: bw.WriteBytes((byte[])value); break; case ParamType.b: bw.WriteBoolean((bool)value); break; case ParamType.u8: case ParamType.x8: bw.WriteByte((byte)value); break; case ParamType.s8: bw.WriteSByte((sbyte)value); break; case ParamType.u16: case ParamType.x16: bw.WriteUInt16((ushort)value); break; case ParamType.s16: bw.WriteInt16((short)value); break; case ParamType.u32: case ParamType.x32: bw.WriteUInt32((uint)value); break; case ParamType.s32: bw.WriteInt32((int)value); break; case ParamType.u64: case ParamType.x64: bw.WriteUInt64((ulong)value); break; case ParamType.s64: bw.WriteInt64((long)value); break; case ParamType.f32: bw.WriteSingle((float)value); break; case ParamType.f64: bw.WriteDouble((double)value); break; default: throw new Exception($"Invalid ParamTemplate ParamType: {Type.ToString()}"); } }
internal void Write(BinaryWriterEx bw, GameType game) { if (game == GameType.BB) { bw.WriteInt32(RagdollParamID); bw.WriteInt16(DamageAnimID); bw.WriteByte(NPCPartGroupIndex); bw.WriteByte(Unknown); bw.WriteSByte(UnknownBB); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(0); } else { bw.WriteInt16((short)RagdollParamID); bw.WriteInt16(DamageAnimID); bw.WriteByte(NPCPartGroupIndex); bw.WriteByte(Unknown); bw.WriteByte(0); bw.WriteByte(0); if (game == GameType.DS3) { bw.WriteInt64(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 WriteValue(BinaryWriterEx bw, object value) { switch (Type) { case ParamType.aob: bw.WriteBytes((byte[])value); break; case ParamType.b: bw.WriteBoolean((bool)value); break; case ParamType.u8: case ParamType.x8: bw.WriteByte(Convert.ToByte(value)); break; case ParamType.s8: bw.WriteSByte(Convert.ToSByte(value)); break; case ParamType.u16: case ParamType.x16: bw.WriteUInt16(Convert.ToUInt16(value)); break; case ParamType.s16: bw.WriteInt16(Convert.ToInt16(value)); break; case ParamType.u32: case ParamType.x32: bw.WriteUInt32(Convert.ToUInt32(value)); break; case ParamType.s32: bw.WriteInt32(Convert.ToInt32(value)); break; case ParamType.u64: case ParamType.x64: bw.WriteUInt64(Convert.ToUInt64(value)); break; case ParamType.s64: bw.WriteInt64(Convert.ToInt64(value)); break; case ParamType.f32: bw.WriteSingle(Convert.ToSingle(value)); break; case ParamType.f64: bw.WriteDouble(Convert.ToDouble(value)); break; default: throw new Exception($"Invalid ParamTemplate ParamType: {Type.ToString()}"); } }
/// <summary> /// Packs an enumeration of arg values into a byte array for use in an instruction. /// </summary> public void PackArgs(IEnumerable <object> args, bool bigEndian = false) { using (var ms = new MemoryStream()) { var bw = new BinaryWriterEx(bigEndian, ms); foreach (object arg in args) { switch (arg) { case byte ub: bw.WriteByte(ub); break; case ushort us: bw.Pad(2); bw.WriteUInt16(us); break; case uint ui: bw.Pad(4); bw.WriteUInt32(ui); break; case sbyte sb: bw.WriteSByte(sb); break; case short ss: bw.Pad(2); bw.WriteInt16(ss); break; case int si: bw.Pad(4); bw.WriteInt32(si); break; case float f: bw.Pad(4); bw.WriteSingle(f); break; case long sl: bw.Pad(8); bw.WriteInt64(sl); break; default: throw new NotSupportedException($"Unsupported argument type: {arg.GetType()}"); } } ArgData = bw.FinishBytes(); } }
private void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.WriteASCII("BHD5"); bw.WriteSByte((sbyte)(BigEndian ? 0 : -1)); bw.WriteBoolean(Unk05); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(1); bw.ReserveInt32("FileSize"); bw.WriteInt32(Buckets.Count); bw.ReserveInt32("BucketsOffset"); if (Format >= Game.DarkSouls2) { bw.WriteInt32(Salt.Length); bw.WriteASCII(Salt); } bw.FillInt32("BucketsOffset", (int)bw.Position); for (int i = 0; i < Buckets.Count; i++) { Buckets[i].Write(bw, i); } for (int i = 0; i < Buckets.Count; i++) { Buckets[i].WriteFileHeaders(bw, Format, i); } for (int i = 0; i < Buckets.Count; i++) { for (int j = 0; j < Buckets[i].Count; j++) { Buckets[i][j].WriteHashAndKey(bw, Format, i, j); } } bw.FillInt32("FileSize", (int)bw.Position); }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.ReserveInt32("FileSize"); bw.WriteInt16((short)(FormatVersion >= 200 ? 0xFF : 0x30)); bw.WriteInt16(DataVersion); bw.WriteInt16((short)Fields.Count); if (FormatVersion == 101) { bw.WriteInt16(0x8C); } else if (FormatVersion == 102) { bw.WriteInt16(0xAC); } else if (FormatVersion == 103) { bw.WriteInt16(0x6C); } else if (FormatVersion == 104) { bw.WriteInt16(0xB0); } else if (FormatVersion == 201) { bw.WriteInt16(0xD0); } else if (FormatVersion == 202) { bw.WriteInt16(0x68); } if (FormatVersion >= 202) { bw.WriteInt32(0); bw.ReserveInt64("ParamTypeOffset"); bw.WriteInt64(0); bw.WriteInt64(0); bw.WriteInt32(0); } else { bw.WriteFixStr(ParamType, 0x20, (byte)(FormatVersion >= 200 ? 0x00 : 0x20)); } bw.WriteSByte((sbyte)(BigEndian ? -1 : 0)); bw.WriteBoolean(Unicode); bw.WriteInt16(FormatVersion); if (FormatVersion >= 200) { bw.WriteInt64(0x38); } for (int i = 0; i < Fields.Count; i++) { Fields[i].Write(bw, this, i); } if (FormatVersion >= 202) { bw.FillInt64("ParamTypeOffset", bw.Position); bw.WriteShiftJIS(ParamType, true); } long fieldStringsStart = bw.Position; var sharedStringOffsets = new Dictionary <string, long>(); for (int i = 0; i < Fields.Count; i++) { Fields[i].WriteStrings(bw, this, i, sharedStringOffsets); } if (FormatVersion >= 104 && FormatVersion < 202) { long fieldStringsLength = bw.Position - fieldStringsStart; if (fieldStringsLength % 0x10 != 0) { bw.WritePattern((int)(0x10 - fieldStringsLength % 0x10), 0x00); } } else { if (FormatVersion >= 202 && bw.Position % 0x10 == 0) { bw.WritePattern(0x10, 0x00); } bw.Pad(0x10); } bw.FillInt32("FileSize", (int)bw.Position); }
internal void Write(BinaryWriterEx bw, List <LayoutMember> layout, float uvFactor) { foreach (LayoutMember member in layout) { switch (member.Semantic) { case LayoutSemantic.Position: if (member.Type == LayoutType.Float3) { bw.WriteVector3(Position); } else if (member.Type == LayoutType.Float4) { bw.WriteVector3(Position); bw.WriteSingle(0); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.BoneWeights: if (member.Type == LayoutType.Byte4A) { for (int i = 0; i < 4; i++) { bw.WriteSByte((sbyte)Math.Round(BoneWeights[i] * sbyte.MaxValue)); } } else if (member.Type == LayoutType.Byte4C) { for (int i = 0; i < 4; i++) { bw.WriteSByte((sbyte)Math.Round(BoneWeights[i] * sbyte.MaxValue)); } } else if (member.Type == LayoutType.UVPair) { for (int i = 0; i < 4; i++) { bw.WriteInt16((short)Math.Round(BoneWeights[i] * short.MaxValue)); } } else if (member.Type == LayoutType.Short4toFloat4A) { for (int i = 0; i < 4; i++) { bw.WriteInt16((short)Math.Round(BoneWeights[i] * short.MaxValue)); } } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.BoneIndices: if (member.Type == LayoutType.Byte4B) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)BoneIndices[i]); } } else if (member.Type == LayoutType.ShortBoneIndices) { for (int i = 0; i < 4; i++) { bw.WriteUInt16((ushort)BoneIndices[i]); } } else if (member.Type == LayoutType.Byte4E) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)BoneIndices[i]); } } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.Normal: if (member.Type == LayoutType.Float3) { bw.WriteSingle(Normal.X); bw.WriteSingle(Normal.Y); bw.WriteSingle(Normal.Z); } else if (member.Type == LayoutType.Float4) { bw.WriteVector4(Normal); } else if (member.Type == LayoutType.Byte4A) { bw.WriteByte((byte)Math.Round(Normal.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4B) { bw.WriteByte((byte)Math.Round(Normal.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4C) { bw.WriteByte((byte)Math.Round(Normal.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.W * 127 + 127)); } else if (member.Type == LayoutType.Short4toFloat4A) { bw.WriteInt16((short)Math.Round(Normal.X * 32767)); bw.WriteInt16((short)Math.Round(Normal.Y * 32767)); bw.WriteInt16((short)Math.Round(Normal.Z * 32767)); bw.WriteInt16((short)Math.Round(Normal.W * 32767)); } else if (member.Type == LayoutType.Short4toFloat4B) { bw.WriteUInt16((ushort)Math.Round(Normal.X * 32767 + 32767)); bw.WriteUInt16((ushort)Math.Round(Normal.Y * 32767 + 32767)); bw.WriteUInt16((ushort)Math.Round(Normal.Z * 32767 + 32767)); bw.WriteUInt16((ushort)Math.Round(Normal.W * 32767 + 32767)); } else if (member.Type == LayoutType.Byte4E) { bw.WriteByte((byte)Math.Round(Normal.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Normal.W * 127 + 127)); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.UV: Vector3 uv = uvQueue.Dequeue() * uvFactor; if (member.Type == LayoutType.Float2) { bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); } else if (member.Type == LayoutType.Float3) { bw.WriteVector3(uv); } else if (member.Type == LayoutType.Float4) { bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); uv = uvQueue.Dequeue() * uvFactor; bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); } else if (member.Type == LayoutType.Byte4A) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Byte4B) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Short2toFloat2) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Byte4C) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.UV) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.UVPair) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); uv = uvQueue.Dequeue() * uvFactor; bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Short4toFloat4B) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); bw.WriteInt16((short)Math.Round(uv.Z)); bw.WriteInt16(0); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.Tangent: Vector4 tangent = tangentQueue.Dequeue(); if (member.Type == LayoutType.Float4) { bw.WriteVector4(tangent); } else if (member.Type == LayoutType.Byte4A) { bw.WriteByte((byte)Math.Round(tangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4B) { bw.WriteByte((byte)Math.Round(tangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4C) { bw.WriteByte((byte)Math.Round(tangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.W * 127 + 127)); } else if (member.Type == LayoutType.Short4toFloat4A) { bw.WriteInt16((short)Math.Round(tangent.X * 32767)); bw.WriteInt16((short)Math.Round(tangent.Y * 32767)); bw.WriteInt16((short)Math.Round(tangent.Z * 32767)); bw.WriteInt16((short)Math.Round(tangent.W * 32767)); } else if (member.Type == LayoutType.Byte4E) { bw.WriteByte((byte)Math.Round(tangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(tangent.W * 127 + 127)); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.Bitangent: if (member.Type == LayoutType.Byte4A) { bw.WriteByte((byte)Math.Round(Bitangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4B) { bw.WriteByte((byte)Math.Round(Bitangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4C) { bw.WriteByte((byte)Math.Round(Bitangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.W * 127 + 127)); } else if (member.Type == LayoutType.Byte4E) { bw.WriteByte((byte)Math.Round(Bitangent.X * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Y * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.Z * 127 + 127)); bw.WriteByte((byte)Math.Round(Bitangent.W * 127 + 127)); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; case LayoutSemantic.VertexColor: FLVER.VertexColor color = colorQueue.Dequeue(); if (member.Type == LayoutType.Float4) { bw.WriteSingle(color.R); bw.WriteSingle(color.G); bw.WriteSingle(color.B); bw.WriteSingle(color.A); } else if (member.Type == LayoutType.Byte4A) { bw.WriteByte((byte)Math.Round(color.A * 255)); bw.WriteByte((byte)Math.Round(color.R * 255)); bw.WriteByte((byte)Math.Round(color.G * 255)); bw.WriteByte((byte)Math.Round(color.B * 255)); } else if (member.Type == LayoutType.Byte4C) { bw.WriteByte((byte)Math.Round(color.R * 255)); bw.WriteByte((byte)Math.Round(color.G * 255)); bw.WriteByte((byte)Math.Round(color.B * 255)); bw.WriteByte((byte)Math.Round(color.A * 255)); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } break; default: throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } }
internal void Write(BinaryWriterEx bw, List <CustomData> allCustomData, List <long> customDataValueOffsets) { bw.WriteFixStrW(Name, 0x40, 0x00); bw.WriteUInt32((uint)Type); bw.WriteInt32(Type == DataType.Color ? 3 : 0); int length = -1; if (Type == DataType.String) { length = SFEncoding.UTF16.GetByteCount((string)Value + '\0'); if (length % 0x10 != 0) { length += 0x10 - length % 0x10; } } else if (Type == DataType.Custom) { length = ((byte[])Value).Length; if (length % 4 != 0) { throw new InvalidDataException($"Unexpected custom data custom length: {length}"); } } else if (Type == DataType.Color) { length = 4; } long valueOffset = bw.Position; switch (Type) { case DataType.Bool: bw.WriteBoolean((bool)Value); break; case DataType.SByte: bw.WriteSByte((sbyte)Value); break; case DataType.Byte: bw.WriteByte((byte)Value); break; case DataType.Short: bw.WriteInt16((short)Value); break; case DataType.Int: bw.WriteInt32((int)Value); break; case DataType.UInt: bw.WriteUInt32((uint)Value); break; case DataType.Float: bw.WriteSingle((float)Value); break; case DataType.String: case DataType.Custom: case DataType.Color: bw.WriteInt32(length); break; default: throw new NotImplementedException($"Unimplemented custom data type: {Type}"); } if (Type == DataType.Bool || Type == DataType.SByte || Type == DataType.Byte) { bw.WriteByte(0); bw.WriteInt16(0); } else if (Type == DataType.Short) { bw.WriteInt16(0); } // This is probably wrong for the 64-bit format bw.WriteInt32(0); bw.ReserveInt32($"SequencesOffset[{allCustomData.Count}]"); bw.WriteInt32(Sequences.Count); bw.WriteInt32(0); bw.WriteInt32(0); if (Type == DataType.String) { bw.WriteFixStrW((string)Value, length, 0x00); } else if (Type == DataType.Custom) { bw.WriteBytes((byte[])Value); } else if (Type == DataType.Color) { var color = (Color)Value; valueOffset = bw.Position; bw.WriteByte(color.R); bw.WriteByte(color.G); bw.WriteByte(color.B); bw.WriteByte(0); } allCustomData.Add(this); customDataValueOffsets.Add(valueOffset); }
internal void WriteCells(BinaryWriterEx bw, int i, Layout layout) { bw.FillInt64($"RowOffset{i}", bw.Position); for (int j = 0; j < layout.Count; j++) { Cell cell = Cells[j]; Layout.Entry entry = layout[j]; CellType type = entry.Type; object value = cell.Value; if (entry.Name != cell.Name || type != cell.Type) { throw new FormatException("Layout does not match cells."); } if (type == CellType.s8) { bw.WriteSByte((sbyte)value); } else if (type == CellType.u8 || type == CellType.x8) { bw.WriteByte((byte)value); } else if (type == CellType.s16) { bw.WriteInt16((short)value); } else if (type == CellType.u16 || type == CellType.x16) { bw.WriteUInt16((ushort)value); } else if (type == CellType.s32) { bw.WriteInt32((int)value); } else if (type == CellType.u32 || type == CellType.x32) { bw.WriteUInt32((uint)value); } else if (type == CellType.f32) { bw.WriteSingle((float)value); } else if (type == CellType.dummy8) { bw.WriteBytes((byte[])value); } else if (type == CellType.fixstr) { bw.WriteFixStr((string)value, entry.Size); } else if (type == CellType.fixstrW) { bw.WriteFixStrW((string)value, entry.Size); } else if (type == CellType.b8) { byte b = 0; int k; for (k = 0; k < 8; k++) { if (j + k >= layout.Count || layout[j + k].Type != CellType.b8) { break; } if ((bool)Cells[j + k].Value) { b |= (byte)(1 << k); } } j += k - 1; bw.WriteByte(b); } else if (type == CellType.b32) { byte[] b = new byte[4]; int k; for (k = 0; k < 32; k++) { if (j + k >= layout.Count || layout[j + k].Type != CellType.b32) { break; } if ((bool)Cells[j + k].Value) { b[k / 8] |= (byte)(1 << (k % 8)); } } j += k - 1; bw.WriteBytes(b); } } }
internal void Write(BinaryWriterEx bw) { long start = bw.Position; bw.ReserveInt64("NameOffset"); bw.WriteUInt32((uint)Type); bw.WriteInt32(ID); bw.WriteInt32(modelIndex); bw.WriteInt32(0); bw.ReserveInt64("PlaceholderOffset"); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.WriteVector3(Scale); bw.WriteUInt32(DrawGroup1); bw.WriteUInt32(DrawGroup2); bw.WriteUInt32(DrawGroup3); bw.WriteUInt32(DrawGroup4); bw.WriteUInt32(DispGroup1); bw.WriteUInt32(DispGroup2); bw.WriteUInt32(DispGroup3); bw.WriteUInt32(DispGroup4); bw.WriteInt32(UnkF01); bw.WriteInt32(UnkF02); bw.WriteInt32(UnkF03); bw.WriteInt32(UnkF04); bw.WriteInt32(UnkF05); bw.WriteInt32(UnkF06); bw.WriteInt32(UnkF07); bw.WriteInt32(UnkF08); bw.WriteInt32(UnkF09); bw.WriteInt32(UnkF10); bw.WriteInt32(UnkF11); bw.WriteInt32(UnkF12); bw.WriteInt32(UnkF13); bw.WriteInt32(UnkF14); bw.WriteInt32(UnkF15); bw.WriteInt32(UnkF16); bw.WriteInt32(UnkF17); bw.WriteInt32(UnkF18); bw.WriteInt32(0); bw.ReserveInt64("BaseDataOffset"); bw.ReserveInt64("TypeDataOffset"); bw.ReserveInt64("UnkOffset1"); bw.ReserveInt64("UnkOffset2"); bw.FillInt64("NameOffset", bw.Position - start); bw.WriteUTF16(Name, true); if (Placeholder == null) { bw.FillInt64("PlaceholderOffset", 0); } else { bw.FillInt64("PlaceholderOffset", bw.Position - start); bw.WriteUTF16(Placeholder, true); } bw.Pad(8); bw.FillInt64("BaseDataOffset", bw.Position - start); bw.WriteInt32(EventEntityID); bw.WriteSByte(LightID); bw.WriteSByte(FogID); bw.WriteSByte(ScatterID); bw.WriteSByte(LensFlareID); bw.WriteInt32(0); bw.WriteSByte(LanternID); bw.WriteSByte(LodParamID); bw.WriteSByte(UnkB0E); bw.WriteBoolean(IsShadowDest); bw.WriteBoolean(IsShadowOnly); bw.WriteBoolean(DrawByReflectCam); bw.WriteBoolean(DrawOnlyReflectCam); bw.WriteBoolean(UseDepthBiasFloat); bw.WriteBoolean(DisablePointLightEffect); bw.WriteByte(UnkB15); bw.WriteByte(UnkB16); bw.WriteByte(UnkB17); bw.WriteInt32(UnkB18); bw.WriteInt32(UnkB1C); bw.WriteInt32(UnkB20); bw.WriteInt32(UnkB24); bw.WriteInt32(UnkB28); bw.WriteInt32(-1); bw.WriteInt32(UnkB30); bw.WriteInt32(UnkB34); bw.WriteInt32(UnkB38); bw.WriteInt32(0); bw.FillInt64("TypeDataOffset", bw.Position - start); if (UnkOffset1Delta == 0) { bw.FillInt64("UnkOffset1", 0); } else { bw.FillInt64("UnkOffset1", bw.Position - start + UnkOffset1Delta); } if (UnkOffset2Delta == 0) { bw.FillInt64("UnkOffset2", 0); } else { bw.FillInt64("UnkOffset2", bw.Position - start + UnkOffset2Delta); } WriteSpecific(bw); }
internal void WriteDefaultValue(BinaryWriterEx bw) { if (ValueToAssert != null) { WriteAssertValue(bw); } else if (DefaultValue == null) { switch (Type) { case ParamType.aob: for (int i = 0; i < AobLength; i++) { bw.WriteByte(0); } break; case ParamType.b: case ParamType.u8: case ParamType.x8: bw.WriteByte(0); break; case ParamType.s8: bw.WriteSByte(0); break; case ParamType.u16: case ParamType.x16: bw.WriteUInt16(0); break; case ParamType.s16: bw.WriteInt16(0); break; case ParamType.u32: case ParamType.x32: bw.WriteUInt32(0); break; case ParamType.s32: bw.WriteInt32(0); break; case ParamType.u64: case ParamType.x64: bw.WriteUInt64(0); break; case ParamType.s64: bw.WriteInt64(0); break; case ParamType.f32: bw.WriteSingle(0); break; case ParamType.f64: bw.WriteDouble(0); break; default: throw new Exception($"Invalid ParamTemplate ParamType: {Type.ToString()}"); } } else { switch (Type) { case ParamType.aob: var assertAob = (byte[])DefaultValue; bw.WriteBytes(assertAob); break; case ParamType.b: case ParamType.u8: case ParamType.x8: bw.WriteByte((byte)DefaultValue); break; case ParamType.s8: bw.WriteSByte((sbyte)DefaultValue); break; case ParamType.u16: case ParamType.x16: bw.WriteUInt16((ushort)DefaultValue); break; case ParamType.s16: bw.WriteInt16((short)DefaultValue); break; case ParamType.u32: case ParamType.x32: bw.WriteUInt32((uint)DefaultValue); break; case ParamType.s32: bw.WriteInt32((int)DefaultValue); break; case ParamType.u64: case ParamType.x64: bw.WriteUInt64((ulong)DefaultValue); break; case ParamType.s64: bw.WriteInt64((long)DefaultValue); break; case ParamType.f32: bw.WriteSingle((float)DefaultValue); break; case ParamType.f64: bw.WriteDouble((double)DefaultValue); break; default: throw new Exception($"Invalid ParamTemplate ParamType: {Type.ToString()}"); } } }
/// <summary> /// Serializes file data to a stream. /// </summary> protected override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.ReserveInt32("FileSize"); bw.WriteInt16((short)(Version >= 201 ? 0xFF : 0x30)); bw.WriteInt16(Unk06); bw.WriteInt16((short)Fields.Count); if (Version == 101) { bw.WriteInt16(0x8C); } else if (Version == 102) { bw.WriteInt16(0xAC); } else if (Version == 103) { bw.WriteInt16(0x6C); } else if (Version == 104) { bw.WriteInt16(0xB0); } else if (Version == 201) { bw.WriteInt16(0xD0); } bw.WriteFixStr(ParamType, 0x20, (byte)(Version >= 201 ? 0x00 : 0x20)); bw.WriteSByte((sbyte)(BigEndian ? -1 : 0)); bw.WriteBoolean(Unicode); bw.WriteInt16(Version); if (Version >= 201) { bw.WriteInt64(0x38); } for (int i = 0; i < Fields.Count; i++) { Fields[i].Write(bw, this, i); } long descriptionsStart = bw.Position; for (int i = 0; i < Fields.Count; i++) { Fields[i].WriteDescription(bw, this, i); } if (Version >= 104) { long descriptionsLength = bw.Position - descriptionsStart; if (descriptionsLength % 0x10 != 0) { bw.WritePattern((int)(0x10 - descriptionsLength % 0x10), 0x00); } } else { bw.Pad(0x10); } bw.FillInt32("FileSize", (int)bw.Position); }
internal void WriteCells(BinaryWriterEx bw, byte format2D, int index) { if ((format2D & 0x7F) < 4) { bw.FillUInt32($"RowOffset{index}", (uint)bw.Position); } else { bw.FillInt64($"RowOffset{index}", bw.Position); } int bitOffset = -1; PARAMDEF.DefType bitType = PARAMDEF.DefType.u8; uint bitValue = 0; for (int i = 0; i < Cells.Count; i++) { Cell cell = Cells[i]; object value = cell.Value; PARAMDEF.Field field = cell.Def; PARAMDEF.DefType type = field.DisplayType; if (type == PARAMDEF.DefType.s8) { bw.WriteSByte((sbyte)value); } else if (type == PARAMDEF.DefType.s16) { bw.WriteInt16((short)value); } else if (type == PARAMDEF.DefType.s32) { bw.WriteInt32((int)value); } else if (type == PARAMDEF.DefType.f32) { bw.WriteSingle((float)value); } else if (type == PARAMDEF.DefType.fixstr) { bw.WriteFixStr((string)value, field.ArrayLength); } else if (type == PARAMDEF.DefType.fixstrW) { bw.WriteFixStrW((string)value, field.ArrayLength * 2); } else if (ParamUtil.IsBitType(type)) { if (field.BitSize == -1) { if (type == PARAMDEF.DefType.u8) { bw.WriteByte((byte)value); } else if (type == PARAMDEF.DefType.u16) { bw.WriteUInt16((ushort)value); } else if (type == PARAMDEF.DefType.u32) { bw.WriteUInt32((uint)value); } else if (type == PARAMDEF.DefType.dummy8) { bw.WriteBytes((byte[])value); } } else { if (bitOffset == -1) { bitOffset = 0; bitType = type == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : type; bitValue = 0; } uint shifted = 0; if (bitType == PARAMDEF.DefType.u8) { shifted = (byte)value; } else if (bitType == PARAMDEF.DefType.u16) { shifted = (ushort)value; } else if (bitType == PARAMDEF.DefType.u32) { shifted = (uint)value; } // Shift left first to clear any out-of-range bits shifted = shifted << (32 - field.BitSize) >> (32 - field.BitSize - bitOffset); bitValue |= shifted; bitOffset += field.BitSize; bool write = false; if (i == Cells.Count - 1) { write = true; } else { PARAMDEF.Field nextField = Cells[i + 1].Def; PARAMDEF.DefType nextType = nextField.DisplayType; int bitLimit = ParamUtil.GetBitLimit(bitType); if (!ParamUtil.IsBitType(nextType) || nextField.BitSize == -1 || bitOffset + nextField.BitSize > bitLimit || (nextType == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : nextType) != bitType) { write = true; } } if (write) { bitOffset = -1; if (bitType == PARAMDEF.DefType.u8) { bw.WriteByte((byte)bitValue); } else if (bitType == PARAMDEF.DefType.u16) { bw.WriteUInt16((ushort)bitValue); } else if (bitType == PARAMDEF.DefType.u32) { bw.WriteUInt32(bitValue); } } } } else { throw new NotImplementedException($"Unsupported field type: {type}"); } } }
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); } }
private static void WriteSByteNorm(BinaryWriterEx bw, float value) => bw.WriteSByte((sbyte)Math.Round(value * 127));
internal void Write(BinaryWriterEx bw, BufferLayout layout, int vertexSize, int version) { var tangentQueue = new Queue <Vector4>(Tangents); var colorQueue = new Queue <Color>(Colors); var uvQueue = new Queue <Vector3>(UVs); float uvFactor = 1024; foreach (BufferLayout.Member member in layout) { switch (member.Semantic) { case BufferLayout.MemberSemantic.Position: if (member.Type == BufferLayout.MemberType.Float3) { bw.WriteVector3(Position); } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.BoneWeights: if (member.Type == BufferLayout.MemberType.Byte4C) { for (int i = 0; i < 4; i++) { bw.WriteSByte((sbyte)(BoneWeights[i] * sbyte.MaxValue)); } } else if (member.Type == BufferLayout.MemberType.Short4toFloat4A) { for (int i = 0; i < 4; i++) { bw.WriteInt16((short)(BoneWeights[i] * short.MaxValue)); } } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.BoneIndices: if (member.Type == BufferLayout.MemberType.Byte4B) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)BoneIndices[i]); } } else if (member.Type == BufferLayout.MemberType.ShortBoneIndices) { for (int i = 0; i < 4; i++) { bw.WriteUInt16((ushort)BoneIndices[i]); } } else if (member.Type == BufferLayout.MemberType.Byte4E) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)BoneIndices[i]); } } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.Normal: if (member.Type == BufferLayout.MemberType.Float4) { bw.WriteVector4(Normal); } else if (member.Type == BufferLayout.MemberType.Byte4A) { bw.WriteByte((byte)(Normal.X * 127 + 127)); bw.WriteByte((byte)(Normal.Y * 127 + 127)); bw.WriteByte((byte)(Normal.Z * 127 + 127)); bw.WriteByte((byte)(Normal.W * 127 + 127)); } else if (member.Type == BufferLayout.MemberType.Byte4B) { bw.WriteByte((byte)(Normal.X * 127 + 127)); bw.WriteByte((byte)(Normal.Y * 127 + 127)); bw.WriteByte((byte)(Normal.Z * 127 + 127)); bw.WriteByte((byte)(Normal.W * 127 + 127)); } else if (member.Type == BufferLayout.MemberType.Byte4C) { bw.WriteByte((byte)(Normal.X * 127 + 127)); bw.WriteByte((byte)(Normal.Y * 127 + 127)); bw.WriteByte((byte)(Normal.Z * 127 + 127)); bw.WriteByte((byte)(Normal.W * 127 + 127)); } else if (member.Type == BufferLayout.MemberType.Short4toFloat4B) { bw.WriteInt16((short)(Normal.X * 32767 + 32767)); bw.WriteInt16((short)(Normal.Y * 32767 + 32767)); bw.WriteInt16((short)(Normal.Z * 32767 + 32767)); bw.WriteInt16((short)(Normal.W * 32767 + 32767)); } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.UV: Vector3 uv = uvQueue.Dequeue() * uvFactor; if (member.Type == BufferLayout.MemberType.Float2) { bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); } else if (member.Type == BufferLayout.MemberType.Float3) { bw.WriteVector3(uv); } else if (member.Type == BufferLayout.MemberType.Byte4A) { bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); } else if (member.Type == BufferLayout.MemberType.Byte4B) { bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); } else if (member.Type == BufferLayout.MemberType.Short2toFloat2) { bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); } else if (member.Type == BufferLayout.MemberType.Byte4C) { bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); } else if (member.Type == BufferLayout.MemberType.UV) { bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); } else if (member.Type == BufferLayout.MemberType.UVPair) { bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); uv = uvQueue.Dequeue() * uvFactor; bw.WriteInt16((short)uv.X); bw.WriteInt16((short)uv.Y); } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.Tangent: Vector4 tangent = tangentQueue.Dequeue(); if (member.Type == BufferLayout.MemberType.Byte4A) { bw.WriteByte((byte)(tangent.X * 127 + 127)); bw.WriteByte((byte)(tangent.Y * 127 + 127)); bw.WriteByte((byte)(tangent.Z * 127 + 127)); bw.WriteByte((byte)(tangent.W * 127 + 127)); } else if (member.Type == BufferLayout.MemberType.Byte4B) { bw.WriteByte((byte)(tangent.X * 127 + 127)); bw.WriteByte((byte)(tangent.Y * 127 + 127)); bw.WriteByte((byte)(tangent.Z * 127 + 127)); bw.WriteByte((byte)(tangent.W * 127 + 127)); } else if (member.Type == BufferLayout.MemberType.Byte4C) { bw.WriteByte((byte)(tangent.X * 127 + 127)); bw.WriteByte((byte)(tangent.Y * 127 + 127)); bw.WriteByte((byte)(tangent.Z * 127 + 127)); bw.WriteByte((byte)(tangent.W * 127 + 127)); } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.UnknownVector4A: if (member.Type == BufferLayout.MemberType.Byte4B) { bw.WriteBytes(UnknownVector4); } else if (member.Type == BufferLayout.MemberType.Byte4C) { bw.WriteBytes(UnknownVector4); } else { throw new NotImplementedException(); } break; case BufferLayout.MemberSemantic.VertexColor: Color color = colorQueue.Dequeue(); if (member.Type == BufferLayout.MemberType.Float4) { bw.WriteSingle(color.R); bw.WriteSingle(color.G); bw.WriteSingle(color.B); bw.WriteSingle(color.A); } else if (member.Type == BufferLayout.MemberType.Byte4A) { bw.WriteByte((byte)(color.A * 255)); bw.WriteByte((byte)(color.R * 255)); bw.WriteByte((byte)(color.G * 255)); bw.WriteByte((byte)(color.B * 255)); } else if (member.Type == BufferLayout.MemberType.Byte4C) { bw.WriteByte((byte)(color.R * 255)); bw.WriteByte((byte)(color.G * 255)); bw.WriteByte((byte)(color.B * 255)); bw.WriteByte((byte)(color.A * 255)); } else { throw new NotImplementedException(); } break; default: throw new NotImplementedException(); } } }
internal void Write(BinaryWriterEx bw) { long start = bw.Position; bw.ReserveInt64("DescOffset"); bw.ReserveInt64("NameOffset"); bw.WriteInt32(ModelLocalID); bw.WriteUInt32((uint)Type); bw.WriteInt32(ID); bw.WriteInt32(modelIndex); bw.ReserveInt64("PlaceholderOffset"); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.WriteVector3(Scale); bw.WriteUInt32s(DrawGroups); bw.WriteUInt32s(DispGroups); bw.WriteUInt32s(BackreadGroups); bw.WriteInt32(UnkFA4); bw.ReserveInt64("BaseDataOffset"); bw.ReserveInt64("TypeDataOffset"); bw.ReserveInt64("UnkOffset1"); bw.ReserveInt64("UnkOffset2"); bw.FillInt64("DescOffset", bw.Position - start); bw.WriteUTF16(Description, true); bw.FillInt64("NameOffset", bw.Position - start); bw.WriteUTF16(Name, true); if (Placeholder == null) { bw.FillInt64("PlaceholderOffset", 0); } else { bw.FillInt64("PlaceholderOffset", bw.Position - start); bw.WriteUTF16(Placeholder, true); } bw.Pad(8); bw.FillInt64("BaseDataOffset", bw.Position - start); bw.WriteInt32(EventEntityID); bw.WriteSByte(OldLightID); bw.WriteSByte(OldFogID); bw.WriteSByte(OldScatterID); bw.WriteSByte(OldLensFlareID); bw.WriteInt32(0); bw.WriteSByte(OldLanternID); bw.WriteSByte(OldLodParamID); bw.WriteSByte(UnkB0E); bw.WriteBoolean(OldIsShadowDest); bw.FillInt64("TypeDataOffset", bw.Position - start); if (UnkOffset1Delta == 0) { bw.FillInt64("UnkOffset1", 0); } else { bw.FillInt64("UnkOffset1", bw.Position - start + UnkOffset1Delta); } if (UnkOffset2Delta == 0) { bw.FillInt64("UnkOffset2", 0); } else { bw.FillInt64("UnkOffset2", bw.Position - start + UnkOffset2Delta); } WriteSpecific(bw); }
internal void Write(BinaryWriterEx bw, List <LayoutMember> layout, float uvFactor) { foreach (LayoutMember member in layout) { if (member.Semantic == LayoutSemantic.Position) { if (member.Type == LayoutType.Float3) { bw.WriteVector3(Position); } else if (member.Type == LayoutType.Float4) { bw.WriteVector3(Position); bw.WriteSingle(0); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.BoneWeights) { if (member.Type == LayoutType.Byte4A) { for (int i = 0; i < 4; i++) { bw.WriteSByte((sbyte)Math.Round(BoneWeights[i] * 127)); } } else if (member.Type == LayoutType.Byte4C) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)Math.Round(BoneWeights[i] * 255)); } } else if (member.Type == LayoutType.UVPair) { for (int i = 0; i < 4; i++) { bw.WriteInt16((short)Math.Round(BoneWeights[i] * 32767)); } } else if (member.Type == LayoutType.Short4toFloat4A) { for (int i = 0; i < 4; i++) { bw.WriteInt16((short)Math.Round(BoneWeights[i] * 32767)); } } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.BoneIndices) { if (member.Type == LayoutType.Byte4B) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)BoneIndices[i]); } } else if (member.Type == LayoutType.ShortBoneIndices) { for (int i = 0; i < 4; i++) { bw.WriteUInt16((ushort)BoneIndices[i]); } } else if (member.Type == LayoutType.Byte4E) { for (int i = 0; i < 4; i++) { bw.WriteByte((byte)BoneIndices[i]); } } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.Normal) { if (member.Type == LayoutType.Float3) { bw.WriteVector3(Normal); } else if (member.Type == LayoutType.Float4) { bw.WriteVector3(Normal); bw.WriteSingle(NormalW); } else if (member.Type == LayoutType.Byte4A) { WriteByteNormVector3(bw, Normal); bw.WriteByte((byte)NormalW); } else if (member.Type == LayoutType.Byte4B) { WriteByteNormVector3(bw, Normal); bw.WriteByte((byte)NormalW); } else if (member.Type == LayoutType.Byte4C) { WriteByteNormVector3(bw, Normal); bw.WriteByte((byte)NormalW); } else if (member.Type == LayoutType.Short4toFloat4A) { WriteShortNormVector3(bw, Normal); bw.WriteInt16((short)NormalW); } else if (member.Type == LayoutType.Short4toFloat4B) { WriteUShortNormVector3(bw, Normal); bw.WriteInt16((short)NormalW); } else if (member.Type == LayoutType.Byte4E) { WriteByteNormVector3(bw, Normal); bw.WriteByte((byte)NormalW); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.UV) { Vector3 uv = uvQueue.Dequeue() * uvFactor; if (member.Type == LayoutType.Float2) { bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); } else if (member.Type == LayoutType.Float3) { bw.WriteVector3(uv); } else if (member.Type == LayoutType.Float4) { bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); uv = uvQueue.Dequeue() * uvFactor; bw.WriteSingle(uv.X); bw.WriteSingle(uv.Y); } else if (member.Type == LayoutType.Byte4A) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Byte4B) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Short2toFloat2) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Byte4C) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.UV) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.UVPair) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); uv = uvQueue.Dequeue() * uvFactor; bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); } else if (member.Type == LayoutType.Short4toFloat4B) { bw.WriteInt16((short)Math.Round(uv.X)); bw.WriteInt16((short)Math.Round(uv.Y)); bw.WriteInt16((short)Math.Round(uv.Z)); bw.WriteInt16(0); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.Tangent) { Vector4 tangent = tangentQueue.Dequeue(); if (member.Type == LayoutType.Float4) { bw.WriteVector4(tangent); } else if (member.Type == LayoutType.Byte4A) { WriteByteNormVector4(bw, tangent); } else if (member.Type == LayoutType.Byte4B) { WriteByteNormVector4(bw, tangent); } else if (member.Type == LayoutType.Byte4C) { WriteByteNormVector4(bw, tangent); } else if (member.Type == LayoutType.Short4toFloat4A) { WriteShortNormVector4(bw, tangent); } else if (member.Type == LayoutType.Byte4E) { WriteByteNormVector4(bw, tangent); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.Bitangent) { if (member.Type == LayoutType.Byte4A) { WriteByteNormVector4(bw, Bitangent); } else if (member.Type == LayoutType.Byte4B) { WriteByteNormVector4(bw, Bitangent); } else if (member.Type == LayoutType.Byte4C) { WriteByteNormVector4(bw, Bitangent); } else if (member.Type == LayoutType.Byte4E) { WriteByteNormVector4(bw, Bitangent); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else if (member.Semantic == LayoutSemantic.VertexColor) { VertexColor color = colorQueue.Dequeue(); if (member.Type == LayoutType.Float4) { color.WriteFloatRGBA(bw); } else if (member.Type == LayoutType.Byte4A) { color.WriteByteARGB(bw); } else if (member.Type == LayoutType.Byte4C) { color.WriteByteRGBA(bw); } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } else { throw new NotImplementedException($"Write not implemented for {member.Type} {member.Semantic}."); } } }