public static int GfxFVFOffset(int fvfFlags, int a2) { int result = 0; if (a2 != 0x2) { result += 12; if (a2 != 0x10) { if ((fvfFlags & 0x10) != 0 /*D3DFVF_NORMAL*/ ) { result = 24; } if ((fvfFlags & 0x20) != 0 /*D3DFVF_PSIZE*/ ) { result += 4; } if (a2 != 0x40) { if ((fvfFlags & 0x40) != 0 /*D3DFVF_DIFFUSE*/ ) { result += 4; } if ((fvfFlags & 0x80) != 0 /*D3DFVF_SPECULAR*/ ) { result += 4; } if (a2 != 0x100) { result += 8; } } } } return result / 4; } static int[] GfxBaseFVFSizes = { 0, 0, 12, 0, 16, 0, 16, 0, 20, 0, 24, 0, 28, 0, 32, 0 }; public static int GfxFVFSize(int fvfFlags) { int result = GfxBaseFVFSizes[fvfFlags & 0xF]; if ((fvfFlags & 0x10) != 0 /*D3DFVF_NORMAL*/ ) { result += 12; } if ((fvfFlags & 0x20) != 0 /*D3DFVF_PSIZE*/ ) { result += 4; } if ((fvfFlags & 0x40) != 0 /*D3DFVF_DIFFUSE*/ ) { result += 4; } if ((fvfFlags & 0x80) != 0 /*D3DFVF_SPECULAR*/ ) { result += 4; } if ((fvfFlags & 0x100) != 0) // 0x100 { result += 8; } if ((fvfFlags & 0x200) != 0) // 0x200 { result += 8; } return result / 4; } public class GfxPacket { public int Type; public float[] Vertices; public int[] Indices; } public class ModStatic { public int Fvf; public List Packets; public List ShaderIndices; } public static ModStatic ReadModStatic(BinaryReader reader) { var result = new ModStatic(); var packetCount = reader.ReadInt32(); if ((packetCount & 0x80) != 0) { packetCount &= 0x7F; result.Fvf = reader.ReadInt32(); result.ShaderIndices = reader.ReadBytes(packetCount).Select(x => (int) x).ToList(); } else { var expectedVertices = reader.ReadInt32(); var expectedIndices = reader.ReadInt32(); var expectedPackets = reader.ReadInt32(); var fvf = reader.ReadInt32(); result.Fvf = fvf; result.Packets = new List(); result.ShaderIndices = new List(); var fvfOffset = GfxFVFOffset(fvf, 0x40); var fvfSize = GfxFVFSize(fvf); var totalVerts = 0; var totalIndices = 0; for (int i = 0; i < packetCount; ++i) { var stripCount = reader.ReadInt32(); result.ShaderIndices.Add(reader.ReadInt32()); for (int j = 0; j < stripCount; ++j) { var type = reader.ReadInt32(); var vertCount = reader.ReadInt32(); var verts = new float[fvfSize * vertCount]; for (int k = 0; k < vertCount; ++k) { for (int l = 0; l < fvfSize; ++l) { verts[(k * fvfSize) + l] = reader.ReadSingle(); } if ((fvf & 0x40) != 0) { verts[(k * fvfSize) + fvfOffset] = SwapEndian(verts[(k * fvfSize) + fvfOffset]); } } var indicesCount = reader.ReadInt32(); var indices = new int[indicesCount]; for (int k = 0; k < indices.Length; ++k) { indices[k] = reader.ReadUInt16(); } result.Packets.Add(new GfxPacket { Type = type, Vertices = verts, Indices = indices }); totalVerts += vertCount; totalIndices += indicesCount; } } Console.WriteLine("Verts: {0,3} (expected {1,3})", totalVerts, expectedVertices); Console.WriteLine("Indices: {0,3} (expected {1,3})", totalIndices, expectedIndices); Console.WriteLine("Packets: {0,3} (expected {1,3})", packetCount, expectedPackets); } return result; }