Skip to content

Instantly share code, notes, and snippets.

@0x1F9F1
Last active January 28, 2018 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0x1F9F1/d3e1b440dda946f2fb807d724ed54330 to your computer and use it in GitHub Desktop.
Save 0x1F9F1/d3e1b440dda946f2fb807d724ed54330 to your computer and use it in GitHub Desktop.
ReadModStatic
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 static GfxPacket ReadBinary(BinaryReader reader, int fvf, int fvfSize, int fvfOffset)
{
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();
}
return new GfxPacket
{
Type = type,
Vertices = verts,
Indices = indices
};
}
}
public class ModStatic
{
public int Fvf;
public GfxPacket[] Packets;
public int[] ShaderIndices;
public static ModStatic ReadBinary(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).ToArray();
}
else
{
var expectedVertices = reader.ReadInt32();
var expectedIndices = reader.ReadInt32();
var expectedPackets = reader.ReadInt32();
var fvf = reader.ReadInt32();
if (expectedPackets != packetCount)
{
Console.WriteLine("Packet Count Mismatch: {0} != {1}", packetCount, expectedPackets);
packetCount = Math.Max(packetCount, expectedPackets);
}
result.Fvf = fvf;
result.Packets = new GfxPacket[packetCount];
result.ShaderIndices = new int[packetCount];
var fvfOffset = GfxFVFOffset(fvf, 0x40);
var fvfSize = GfxFVFSize(fvf);
for (int i = 0; i < packetCount; ++i)
{
var stripCount = reader.ReadInt32();
if (stripCount != 1)
{
throw new InvalidDataException(string.Format("Invalid Strip Count: {0} != 1", stripCount));
}
result.ShaderIndices[i] = reader.ReadInt32();
result.Packets[i] = GfxPacket.ReadBinary(reader, fvf, fvfSize, fvfOffset);
}
var totalVerts = result.Packets.Sum(x => x.Vertices.Length) / fvfSize;
var totalIndices = result.Packets.Sum(x => x.Indices.Length);
Console.WriteLine("Verts: {0,4} (expected {1,4})", totalVerts, expectedVertices);
Console.WriteLine("Indices: {0,4} (expected {1,4})", totalIndices, expectedIndices);
Console.WriteLine("Packets: {0,4} (expected {1,4})", packetCount, expectedPackets);
}
if (reader.BaseStream.Position != reader.BaseStream.Length)
{
Console.WriteLine("Extra Data: {0} / {1}", reader.BaseStream.Position, reader.BaseStream.Length);
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment