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 override void Write(BinaryWriterEx bw) { long start = bw.Position; bw.ReserveInt64("NameOffset"); bw.WriteUInt32((uint)Type); bw.WriteInt32(ID); bw.WriteUInt32((uint)Shape.Type); bw.WriteVector3(Position); bw.WriteVector3(Rotation); bw.WriteInt32(Unk2C); bw.ReserveInt64("BaseDataOffset1"); bw.ReserveInt64("BaseDataOffset2"); bw.WriteInt32(-1); bw.WriteInt32(MapStudioLayer); bw.ReserveInt64("ShapeDataOffset"); bw.ReserveInt64("BaseDataOffset3"); bw.ReserveInt64("TypeDataOffset"); bw.FillInt64("NameOffset", bw.Position - start); bw.WriteUTF16(Name, true); bw.Pad(4); bw.FillInt64("BaseDataOffset1", bw.Position - start); bw.WriteInt16((short)UnkA.Length); bw.WriteInt16s(UnkA); bw.Pad(4); bw.FillInt64("BaseDataOffset2", bw.Position - start); bw.WriteInt16((short)UnkB.Length); bw.WriteInt16s(UnkB); bw.Pad(8); if (Shape.HasShapeData) { bw.FillInt64("ShapeDataOffset", bw.Position - start); Shape.WriteShapeData(bw); } else { bw.FillInt64("ShapeDataOffset", 0); } bw.FillInt64("BaseDataOffset3", bw.Position - start); bw.WriteInt32(UnkC00); bw.WriteInt32(UnkC04); if (HasTypeData) { if (Type == RegionType.Region23 || Type == RegionType.PartsGroup || Type == RegionType.AutoDrawGroup) { bw.Pad(8); } bw.FillInt64("TypeDataOffset", bw.Position - start); WriteTypeData(bw); } else { bw.FillInt64("TypeDataOffset", 0); } bw.Pad(8); }
private static void CompressDCXEDGE(byte[] data, BinaryWriterEx bw) { int chunkCount = data.Length / 0x10000; if (data.Length % 0x10000 > 0) { chunkCount++; } bw.WriteASCII("DCX\0"); bw.WriteInt32(0x10000); bw.WriteInt32(0x18); bw.WriteInt32(0x24); bw.WriteInt32(0x24); bw.WriteInt32(0x50 + chunkCount * 0x10); bw.WriteASCII("DCS\0"); bw.WriteInt32(data.Length); bw.ReserveInt32("CompressedSize"); bw.WriteASCII("DCP\0"); bw.WriteASCII("EDGE"); bw.WriteInt32(0x20); bw.WriteInt32(0x9000000); bw.WriteInt32(0x10000); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0x00100100); long dcaStart = bw.Position; bw.WriteASCII("DCA\0"); bw.ReserveInt32("DCASize"); long egdtStart = bw.Position; bw.WriteASCII("EgdT"); bw.WriteInt32(0x00010100); bw.WriteInt32(0x24); bw.WriteInt32(0x10); bw.WriteInt32(0x10000); bw.WriteInt32(data.Length % 0x10000); bw.ReserveInt32("EGDTSize"); bw.WriteInt32(chunkCount); bw.WriteInt32(0x100000); for (int i = 0; i < chunkCount; i++) { bw.WriteInt32(0); bw.ReserveInt32($"ChunkOffset{i}"); bw.ReserveInt32($"ChunkSize{i}"); bw.ReserveInt32($"ChunkCompressed{i}"); } bw.FillInt32("DCASize", (int)(bw.Position - dcaStart)); bw.FillInt32("EGDTSize", (int)(bw.Position - egdtStart)); int compressedSize = 0; for (int i = 0; i < chunkCount; i++) { int chunkSize = 0x10000; if (i == chunkCount - 1) { chunkSize = data.Length % 0x10000; } byte[] chunk; using (MemoryStream cmpStream = new MemoryStream()) using (MemoryStream dcmpStream = new MemoryStream(data, i * 0x10000, chunkSize)) { DeflateStream dfltStream = new DeflateStream(cmpStream, CompressionMode.Compress); dcmpStream.CopyTo(dfltStream); dfltStream.Close(); chunk = cmpStream.ToArray(); } if (chunk.Length < chunkSize) { bw.FillInt32($"ChunkCompressed{i}", 1); } else { bw.FillInt32($"ChunkCompressed{i}", 0); chunk = data; } compressedSize += chunk.Length; bw.FillInt32($"ChunkOffset{i}", (int)bw.Position); bw.FillInt32($"ChunkSize{i}", chunk.Length); bw.WriteBytes(chunk); bw.Pad(0x10); } bw.FillInt32("CompressedSize", compressedSize); }
internal override void Write(BinaryWriterEx bw) { bw.WriteASCII("TAE "); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0); bw.WriteByte(0xFF); bw.WriteInt32(0x1000C); bw.ReserveInt32("FileSize"); bw.WriteInt64(0x40); bw.WriteInt64(1); bw.WriteInt64(0x50); bw.WriteInt64(0x80); bw.WriteInt64(0x15); bw.WriteInt64(0); bw.WriteBytes(Flags); bw.WriteInt64(1); bw.WriteInt32(ID); bw.WriteInt32(Animations.Count); bw.ReserveInt64("AnimsOffset"); bw.ReserveInt64("AnimGroupsOffset"); bw.WriteInt64(0xA0); bw.WriteInt64(Animations.Count); bw.ReserveInt64("FirstAnimOffset"); bw.WriteInt64(1); bw.WriteInt64(0x90); bw.WriteInt32(ID); bw.WriteInt32(ID); bw.WriteInt64(0x50); bw.WriteInt64(0); bw.WriteInt64(0xB0); bw.ReserveInt64("SkeletonName"); bw.ReserveInt64("SibName"); bw.WriteInt64(0); bw.WriteInt64(0); bw.FillInt64("SkeletonName", bw.Position); bw.WriteUTF16(SkeletonName, true); bw.Pad(0x10); bw.FillInt64("SibName", bw.Position); bw.WriteUTF16(SibName, true); bw.Pad(0x10); Animations.Sort((a1, a2) => a1.ID.CompareTo(a2.ID)); bw.FillInt64("AnimsOffset", bw.Position); var animOffsets = new List <long>(Animations.Count); for (int i = 0; i < Animations.Count; i++) { animOffsets.Add(bw.Position); Animations[i].WriteHeader(bw, i); } bw.FillInt64("AnimGroupsOffset", bw.Position); bw.ReserveInt64("AnimGroupsCount"); bw.ReserveInt64("AnimGroupsOffset"); int groupCount = 0; long groupStart = bw.Position; for (int i = 0; i < Animations.Count; i++) { int firstIndex = i; bw.WriteInt32((int)Animations[i].ID); while (i < Animations.Count - 1 && Animations[i + 1].ID == Animations[i].ID + 1) { i++; } bw.WriteInt32((int)Animations[i].ID); bw.WriteInt64(animOffsets[firstIndex]); groupCount++; } bw.FillInt64("AnimGroupsCount", groupCount); if (groupCount == 0) { bw.FillInt64("AnimGroupsOffset", 0); } else { bw.FillInt64("AnimGroupsOffset", groupStart); } bw.FillInt64("FirstAnimOffset", bw.Position); for (int i = 0; i < Animations.Count; i++) { Animations[i].WriteBody(bw, i); } for (int i = 0; i < Animations.Count; i++) { Animations[i].WriteAnimFile(bw, i); long timeStart = bw.Position; Animations[i].WriteTimes(bw, i); var eventHeaderOffsets = Animations[i].WriteEventHeaders(bw, i, timeStart); Animations[i].WriteEventData(bw, i); Animations[i].WriteEventGroupHeaders(bw, i); Animations[i].WriteEventGroupData(bw, i, eventHeaderOffsets); } bw.FillInt32("FileSize", (int)bw.Position); }
private static void WriteMarker(BinaryWriterEx bw, byte marker) { bw.WriteByte(marker); bw.Pad(4); }
internal void Write(BinaryWriterEx bw, List <File> files) { bw.BigEndian = BigEndian; bw.WriteASCII("BHF4"); bw.WriteBoolean(Flag1); bw.WriteBoolean(Flag2); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(0x10000); bw.WriteInt32(files.Count); bw.WriteInt64(0x40); bw.WriteASCII(Timestamp); if (Format == 0x0C || Format == 0x30) { bw.WriteInt64(0x18); } else if (Format == 0x2E || Format == 0x74) { bw.WriteInt64(0x24); } else if (Format == 0x3E) { bw.WriteInt64(0x28); } bw.WriteInt64(0); bw.WriteBoolean(Unicode); bw.WriteByte(Format); bw.WriteByte(Extended); bw.WriteByte(0); bw.WriteInt32(0); if (Extended == 4) { bw.ReserveInt64("HashGroups"); } else { bw.WriteInt64(0); } for (int i = 0; i < files.Count; i++) { FileHeader.Write(bw, files[i], i, Format); } for (int i = 0; i < files.Count; i++) { File file = files[i]; bw.FillInt32($"FileName{i}", (int)bw.Position); if (Unicode) { bw.WriteUTF16(file.Name, true); } else { bw.WriteShiftJIS(file.Name, true); } } if (Extended == 4) { uint groupCount = 0; for (uint p = (uint)files.Count / 7; p <= 100000; p++) { if (Util.IsPrime(p)) { groupCount = p; break; } } if (groupCount == 0) { throw new InvalidOperationException("Hash group count not determined in BXF4."); } var hashLists = new List <PathHash> [groupCount]; for (int i = 0; i < groupCount; i++) { hashLists[i] = new List <PathHash>(); } for (int i = 0; i < files.Count; i++) { var pathHash = new PathHash(i, files[i].Name); uint group = pathHash.Hash % groupCount; hashLists[group].Add(pathHash); } for (int i = 0; i < groupCount; i++) { hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash)); } var hashGroups = new List <HashGroup>(); var pathHashes = new List <PathHash>(); int count = 0; foreach (List <PathHash> hashList in hashLists) { int index = count; foreach (PathHash pathHash in hashList) { pathHashes.Add(pathHash); count++; } hashGroups.Add(new HashGroup(index, count - index)); } bw.Pad(0x8); bw.FillInt64("HashGroups", bw.Position); bw.ReserveInt64("PathHashes"); bw.WriteUInt32(groupCount); bw.WriteInt32(0x00080810); foreach (HashGroup hashGroup in hashGroups) { hashGroup.Write(bw); } // No padding after section 1 bw.FillInt64("PathHashes", bw.Position); foreach (PathHash pathHash in pathHashes) { pathHash.Write(bw); } } }
/// <summary> /// Writes BND4 data to a BinaryWriterEx. /// </summary> internal override void Write(BinaryWriterEx bw) { bw.BigEndian = BigEndian; bw.WriteASCII("BND4"); bw.WriteBoolean(Flag1); bw.WriteBoolean(Flag2); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(0x10000); bw.WriteInt32(Files.Count); bw.WriteInt64(0x40); bw.WriteFixStr(Timestamp, 8); bw.WriteInt64(Binder.FileHeaderSize(Format)); bw.ReserveInt64("DataStart"); bw.WriteBoolean(Unicode); bw.WriteByte((byte)Format); bw.WriteByte(Extended); bw.WriteByte(0); bw.WriteInt32(0); if (Extended == 4) { bw.ReserveInt64("HashGroups"); } else { bw.WriteInt64(0); } for (int i = 0; i < Files.Count; i++) { WriteFile(Files[i], bw, i, Format); } if (Binder.HasName(Format)) { for (int i = 0; i < Files.Count; i++) { BinderFile file = Files[i]; bw.FillUInt32($"FileName{i}", (uint)bw.Position); if (Unicode) { bw.WriteUTF16(file.Name, true); } else { bw.WriteShiftJIS(file.Name, true); } } } if (Extended == 4) { uint groupCount = 0; for (uint p = (uint)Files.Count / 7; p <= 100000; p++) { if (SFUtil.IsPrime(p)) { groupCount = p; break; } } if (groupCount == 0) { throw new InvalidOperationException("Hash group count not determined in BND4."); } var hashLists = new List <PathHash> [groupCount]; for (int i = 0; i < groupCount; i++) { hashLists[i] = new List <PathHash>(); } for (int i = 0; i < Files.Count; i++) { var pathHash = new PathHash(i, Files[i].Name); uint group = pathHash.Hash % groupCount; hashLists[group].Add(pathHash); } for (int i = 0; i < groupCount; i++) { hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash)); } var hashGroups = new List <HashGroup>(); var pathHashes = new List <PathHash>(); int count = 0; foreach (List <PathHash> hashList in hashLists) { int index = count; foreach (PathHash pathHash in hashList) { pathHashes.Add(pathHash); count++; } hashGroups.Add(new HashGroup(index, count - index)); } bw.Pad(0x8); bw.FillInt64("HashGroups", bw.Position); bw.ReserveInt64("PathHashes"); bw.WriteUInt32(groupCount); bw.WriteInt32(0x00080810); foreach (HashGroup hashGroup in hashGroups) { hashGroup.Write(bw); } // No padding after section 1 bw.FillInt64("PathHashes", bw.Position); foreach (PathHash pathHash in pathHashes) { pathHash.Write(bw); } } bw.FillInt64("DataStart", bw.Position); for (int i = 0; i < Files.Count; i++) { BinderFile file = Files[i]; if (file.Bytes.LongLength > 0) { bw.Pad(0x10); } bw.FillUInt32($"FileData{i}", (uint)bw.Position); int compressedSize = file.Bytes.Length; if (Binder.IsCompressed(file.Flags)) { if (Format == Binder.Format.x2E) { byte[] bytes = DCX.Compress(file.Bytes, DCX.Type.DemonsSoulsEDGE); bw.WriteBytes(bytes); compressedSize = bytes.Length; } else { compressedSize = SFUtil.WriteZlib(bw, 0x9C, file.Bytes); } } else { bw.WriteBytes(file.Bytes); } bw.FillInt64($"CompressedSize{i}", compressedSize); } }
/// <summary> /// Writes FLVER data to a BinaryWriterEx. /// </summary> internal override void Write(BinaryWriterEx bw) { bw.BigEndian = Header.BigEndian; bw.WriteASCII("FLVER\0"); bw.WriteASCII(Header.BigEndian ? "B\0" : "L\0"); bw.WriteInt32(Header.Version); bw.ReserveInt32("DataOffset"); bw.ReserveInt32("DataSize"); bw.WriteInt32(Dummies.Count); bw.WriteInt32(Materials.Count); bw.WriteInt32(Bones.Count); bw.WriteInt32(Meshes.Count); bw.WriteInt32(Meshes.Sum(m => m.VertexBuffers.Count)); bw.WriteVector3(Header.BoundingBoxMin); bw.WriteVector3(Header.BoundingBoxMax); int trueFaceCount = 0; int totalFaceCount = 0; foreach (Mesh mesh in Meshes) { bool allowPrimitiveRestarts = mesh.Vertices.Count < ushort.MaxValue; foreach (FaceSet faceSet in mesh.FaceSets) { faceSet.AddFaceCounts(allowPrimitiveRestarts, ref trueFaceCount, ref totalFaceCount); } } bw.WriteInt32(trueFaceCount); bw.WriteInt32(totalFaceCount); byte vertexIndicesSize = 0; if (Header.Version < 0x20013) { vertexIndicesSize = 16; foreach (Mesh mesh in Meshes) { foreach (FaceSet fs in mesh.FaceSets) { vertexIndicesSize = (byte)Math.Max(vertexIndicesSize, fs.GetVertexIndexSize()); } } } bw.WriteByte(vertexIndicesSize); bw.WriteBoolean(Header.Unicode); bw.WriteBoolean(Header.Unk4A); bw.WriteByte(0); bw.WriteInt32(Header.Unk4C); bw.WriteInt32(Meshes.Sum(m => m.FaceSets.Count)); bw.WriteInt32(BufferLayouts.Count); bw.WriteInt32(Materials.Sum(m => m.Textures.Count)); bw.WriteByte(Header.Unk5C); bw.WriteByte(Header.Unk5D); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(Header.Unk68); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); foreach (Dummy dummy in Dummies) { dummy.Write(bw, Header); } for (int i = 0; i < Materials.Count; i++) { Materials[i].Write(bw, i); } for (int i = 0; i < Bones.Count; i++) { Bones[i].Write(bw, i); } for (int i = 0; i < Meshes.Count; i++) { Meshes[i].Write(bw, i); } int faceSetIndex = 0; foreach (Mesh mesh in Meshes) { for (int i = 0; i < mesh.FaceSets.Count; i++) { int indexSize = vertexIndicesSize; if (indexSize == 0) { indexSize = mesh.FaceSets[i].GetVertexIndexSize(); } mesh.FaceSets[i].Write(bw, Header, indexSize, faceSetIndex + i); } faceSetIndex += mesh.FaceSets.Count; } int vertexBufferIndex = 0; foreach (Mesh mesh in Meshes) { for (int i = 0; i < mesh.VertexBuffers.Count; i++) { mesh.VertexBuffers[i].Write(bw, Header, vertexBufferIndex + i, i, BufferLayouts, mesh.Vertices.Count); } vertexBufferIndex += mesh.VertexBuffers.Count; } for (int i = 0; i < BufferLayouts.Count; i++) { BufferLayouts[i].Write(bw, i); } int textureIndex = 0; for (int i = 0; i < Materials.Count; i++) { Materials[i].WriteTextures(bw, i, textureIndex); textureIndex += Materials[i].Textures.Count; } if (Header.Version >= 0x2001A) { SekiroUnk.Write(bw); } bw.Pad(0x10); for (int i = 0; i < BufferLayouts.Count; i++) { BufferLayouts[i].WriteMembers(bw, i); } bw.Pad(0x10); for (int i = 0; i < Meshes.Count; i++) { Meshes[i].WriteBoundingBox(bw, i, Header); } bw.Pad(0x10); int boneIndicesStart = (int)bw.Position; for (int i = 0; i < Meshes.Count; i++) { Meshes[i].WriteBoneIndices(bw, i, boneIndicesStart); } bw.Pad(0x10); faceSetIndex = 0; for (int i = 0; i < Meshes.Count; i++) { bw.FillInt32($"MeshFaceSetIndices{i}", (int)bw.Position); for (int j = 0; j < Meshes[i].FaceSets.Count; j++) { bw.WriteInt32(faceSetIndex + j); } faceSetIndex += Meshes[i].FaceSets.Count; } bw.Pad(0x10); vertexBufferIndex = 0; for (int i = 0; i < Meshes.Count; i++) { bw.FillInt32($"MeshVertexBufferIndices{i}", (int)bw.Position); for (int j = 0; j < Meshes[i].VertexBuffers.Count; j++) { bw.WriteInt32(vertexBufferIndex + j); } vertexBufferIndex += Meshes[i].VertexBuffers.Count; } bw.Pad(0x10); var gxOffsets = new List <int>(); foreach (GXList gxList in GXLists) { gxOffsets.Add((int)bw.Position); gxList.Write(bw, Header); } for (int i = 0; i < Materials.Count; i++) { Materials[i].FillGXOffset(bw, i, gxOffsets); } bw.Pad(0x10); textureIndex = 0; for (int i = 0; i < Materials.Count; i++) { Material material = Materials[i]; material.WriteStrings(bw, Header, i); for (int j = 0; j < material.Textures.Count; j++) { material.Textures[j].WriteStrings(bw, Header, textureIndex + j); } textureIndex += material.Textures.Count; } bw.Pad(0x10); for (int i = 0; i < Bones.Count; i++) { Bones[i].WriteStrings(bw, Header, i); } int alignment = Header.Version <= 0x2000E ? 0x20 : 0x10; bw.Pad(alignment); if (Header.Version == 0x2000F || Header.Version == 0x20010) { bw.Pad(0x20); } int dataStart = (int)bw.Position; bw.FillInt32("DataOffset", dataStart); faceSetIndex = 0; vertexBufferIndex = 0; for (int i = 0; i < Meshes.Count; i++) { Mesh mesh = Meshes[i]; for (int j = 0; j < mesh.FaceSets.Count; j++) { int indexSize = vertexIndicesSize; if (indexSize == 0) { indexSize = mesh.FaceSets[j].GetVertexIndexSize(); } bw.Pad(alignment); mesh.FaceSets[j].WriteVertices(bw, indexSize, faceSetIndex + j, dataStart); } faceSetIndex += mesh.FaceSets.Count; foreach (FLVER.Vertex vertex in mesh.Vertices) { vertex.PrepareWrite(); } for (int j = 0; j < mesh.VertexBuffers.Count; j++) { bw.Pad(alignment); mesh.VertexBuffers[j].WriteBuffer(bw, vertexBufferIndex + j, BufferLayouts, mesh.Vertices, dataStart, Header); } foreach (FLVER.Vertex vertex in mesh.Vertices) { vertex.FinishWrite(); } vertexBufferIndex += mesh.VertexBuffers.Count; } bw.Pad(alignment); bw.FillInt32("DataSize", (int)bw.Position - dataStart); if (Header.Version == 0x2000F || Header.Version == 0x20010) { bw.Pad(0x20); } }
internal void Write(BinaryWriterEx bw) { bw.WriteInt32(0); bw.WriteInt32(Unk04); bw.WriteInt32(4); bw.WriteInt32(4); WriteMarker(bw, 0xA3); bw.WriteShiftJISLengthPrefixed(Name, 0xA3); bw.WriteShiftJISLengthPrefixed(Type.ToString().ToLower(), 0x04); bw.WriteInt32(1); bw.WriteInt32(0); bw.ReserveInt32("ValueSize"); int valueStart = (int)bw.Position; if (Type == ParamType.Bool) { bw.WriteByte(0); } else if (Type == ParamType.Int || Type == ParamType.Int2) { bw.WriteByte(1); } else if (Type == ParamType.Float || Type == ParamType.Float2 || Type == ParamType.Float3 || Type == ParamType.Float4) { bw.WriteByte(2); } bw.WriteByte(0x10); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(1); if (Type == ParamType.Bool) { WriteMarker(bw, 0xC0); } else if (Type == ParamType.Int || Type == ParamType.Int2) { WriteMarker(bw, 0xC5); } else if (Type == ParamType.Float || Type == ParamType.Float2 || Type == ParamType.Float3 || Type == ParamType.Float4) { WriteMarker(bw, 0xCA); } if (Type == ParamType.Bool || Type == ParamType.Float || Type == ParamType.Int) { bw.WriteInt32(1); } else if (Type == ParamType.Float2 || Type == ParamType.Int2) { bw.WriteInt32(2); } else if (Type == ParamType.Float3) { bw.WriteInt32(3); } else if (Type == ParamType.Float4) { bw.WriteInt32(4); } if (Type == ParamType.Int) { bw.WriteInt32((int)Value); } else if (Type == ParamType.Int2) { bw.WriteInt32s((int[])Value); } else if (Type == ParamType.Bool) { bw.WriteBoolean((bool)Value); } else if (Type == ParamType.Float) { bw.WriteSingle((float)Value); } else if (Type == ParamType.Float2) { bw.WriteSingles((float[])Value); } else if (Type == ParamType.Float3) { bw.WriteSingles((float[])Value); } else if (Type == ParamType.Float4) { bw.WriteSingles((float[])Value); } bw.FillInt32("ValueSize", (int)bw.Position - valueStart); bw.WriteByte(4); bw.Pad(4); bw.WriteInt32(0); }
protected override void Write(BinaryWriterEx bw) { bw.WriteASCII("FXR\0"); bw.WriteInt16(0); bw.WriteUInt16((ushort)Version); bw.WriteInt32(1); bw.WriteInt32(ID); bw.ReserveInt32("Section1Offset"); bw.WriteInt32(1); bw.ReserveInt32("Section2Offset"); bw.WriteInt32(Section1Tree.Section2s.Count); bw.ReserveInt32("Section3Offset"); bw.ReserveInt32("Section3Count"); bw.ReserveInt32("Section4Offset"); bw.ReserveInt32("Section4Count"); bw.ReserveInt32("Section5Offset"); bw.ReserveInt32("Section5Count"); bw.ReserveInt32("Section6Offset"); bw.ReserveInt32("Section6Count"); bw.ReserveInt32("Section7Offset"); bw.ReserveInt32("Section7Count"); bw.ReserveInt32("Section8Offset"); bw.ReserveInt32("Section8Count"); bw.ReserveInt32("Section9Offset"); bw.ReserveInt32("Section9Count"); bw.ReserveInt32("Section10Offset"); bw.ReserveInt32("Section10Count"); bw.ReserveInt32("Section11Offset"); bw.ReserveInt32("Section11Count"); bw.WriteInt32(1); bw.WriteInt32(0); if (Version == FXRVersion.Sekiro) { bw.ReserveInt32("Section12Offset"); bw.WriteInt32(Section12s.Count); bw.ReserveInt32("Section13Offset"); bw.WriteInt32(Section13s.Count); bw.ReserveInt32("Section14Offset"); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); } bw.FillInt32("Section1Offset", (int)bw.Position); Section1Tree.Write(bw); bw.Pad(0x10); bw.FillInt32("Section2Offset", (int)bw.Position); Section1Tree.WriteSection2s(bw); bw.Pad(0x10); bw.FillInt32("Section3Offset", (int)bw.Position); List <Section2> section2s = Section1Tree.Section2s; var section3s = new List <Section3>(); for (int i = 0; i < section2s.Count; i++) { section2s[i].WriteSection3s(bw, i, section3s); } bw.FillInt32("Section3Count", section3s.Count); bw.Pad(0x10); bw.FillInt32("Section4Offset", (int)bw.Position); var section4s = new List <Section4>(); Section4Tree.Write(bw, section4s); Section4Tree.WriteSection4s(bw, section4s); bw.FillInt32("Section4Count", section4s.Count); bw.Pad(0x10); bw.FillInt32("Section5Offset", (int)bw.Position); int section5Count = 0; for (int i = 0; i < section4s.Count; i++) { section4s[i].WriteSection5s(bw, i, ref section5Count); } bw.FillInt32("Section5Count", section5Count); bw.Pad(0x10); bw.FillInt32("Section6Offset", (int)bw.Position); section5Count = 0; var section6s = new List <FFXDrawEntityHost>(); for (int i = 0; i < section4s.Count; i++) { section4s[i].WriteSection6s(bw, i, ref section5Count, section6s); } bw.FillInt32("Section6Count", section6s.Count); bw.Pad(0x10); bw.FillInt32("Section7Offset", (int)bw.Position); var section7s = new List <FFXProperty>(); for (int i = 0; i < section6s.Count; i++) { section6s[i].WriteSection7s(bw, i, section7s); } bw.FillInt32("Section7Count", section7s.Count); bw.Pad(0x10); bw.FillInt32("Section8Offset", (int)bw.Position); var section8s = new List <Section8>(); for (int i = 0; i < section7s.Count; i++) { section7s[i].WriteSection8s(bw, i, section8s); } bw.FillInt32("Section8Count", section8s.Count); bw.Pad(0x10); bw.FillInt32("Section9Offset", (int)bw.Position); var section9s = new List <Section9>(); for (int i = 0; i < section8s.Count; i++) { section8s[i].WriteSection9s(bw, i, section9s); } bw.FillInt32("Section9Count", section9s.Count); bw.Pad(0x10); bw.FillInt32("Section10Offset", (int)bw.Position); var section10s = new List <Section10>(); for (int i = 0; i < section6s.Count; i++) { section6s[i].WriteSection10s(bw, i, section10s); } bw.FillInt32("Section10Count", section10s.Count); bw.Pad(0x10); bw.FillInt32("Section11Offset", (int)bw.Position); int section11Count = 0; for (int i = 0; i < section3s.Count; i++) { section3s[i].WriteSection11s(bw, i, ref section11Count); } for (int i = 0; i < section6s.Count; i++) { section6s[i].WriteSection11s(bw, i, ref section11Count); } for (int i = 0; i < section7s.Count; i++) { section7s[i].WriteSection11s(bw, i, ref section11Count); } for (int i = 0; i < section8s.Count; i++) { section8s[i].WriteSection11s(bw, i, ref section11Count); } for (int i = 0; i < section9s.Count; i++) { section9s[i].WriteSection11s(bw, i, ref section11Count); } for (int i = 0; i < section10s.Count; i++) { section10s[i].WriteSection11s(bw, i, ref section11Count); } bw.FillInt32("Section11Count", section11Count); bw.Pad(0x10); if (Version == FXRVersion.Sekiro) { bw.FillInt32("Section12Offset", (int)bw.Position); bw.WriteInt32s(Section12s); bw.Pad(0x10); bw.FillInt32("Section13Offset", (int)bw.Position); bw.WriteInt32s(Section13s); bw.Pad(0x10); bw.FillInt32("Section14Offset", (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); }