mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
133 lines
No EOL
4 KiB
C#
133 lines
No EOL
4 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Lumina.Data.Parsing;
|
|
using Lumina.Extensions;
|
|
|
|
namespace Penumbra.GameData.Files;
|
|
|
|
public partial class MtrlFile
|
|
{
|
|
public struct ColorSet
|
|
{
|
|
public string Name;
|
|
public ushort Index;
|
|
}
|
|
|
|
public struct Texture
|
|
{
|
|
public string Path;
|
|
public ushort Flags;
|
|
}
|
|
|
|
public struct Constant
|
|
{
|
|
public uint Id;
|
|
public uint Value;
|
|
}
|
|
|
|
public struct ShaderPackageData
|
|
{
|
|
public string Name;
|
|
public ShaderKey[] ShaderKeys;
|
|
public Constant[] Constants;
|
|
public Sampler[] Samplers;
|
|
public float[] ShaderValues;
|
|
public uint Unk;
|
|
}
|
|
|
|
|
|
public uint Version;
|
|
|
|
public Texture[] Textures;
|
|
public ColorSet[] UvColorSets;
|
|
public ColorSet[] ColorSets;
|
|
public ushort[] ColorSetData;
|
|
public ShaderPackageData ShaderPackage;
|
|
public byte[] AdditionalData;
|
|
|
|
public MtrlFile( byte[] data )
|
|
{
|
|
using var stream = new MemoryStream( data );
|
|
using var r = new BinaryReader( stream );
|
|
|
|
Version = r.ReadUInt32();
|
|
r.ReadUInt16(); // file size
|
|
var dataSetSize = r.ReadUInt16();
|
|
var stringTableSize = r.ReadUInt16();
|
|
var shaderPackageNameOffset = r.ReadUInt16();
|
|
var textureCount = r.ReadByte();
|
|
var uvSetCount = r.ReadByte();
|
|
var colorSetCount = r.ReadByte();
|
|
var additionalDataSize = r.ReadByte();
|
|
|
|
Textures = ReadTextureOffsets( r, textureCount, out var textureOffsets );
|
|
UvColorSets = ReadColorSetOffsets( r, uvSetCount, out var uvOffsets );
|
|
ColorSets = ReadColorSetOffsets( r, colorSetCount, out var colorOffsets );
|
|
|
|
var strings = r.ReadBytes( stringTableSize );
|
|
for( var i = 0; i < textureCount; ++i )
|
|
{
|
|
Textures[ i ].Path = UseOffset( strings, textureOffsets[ i ] );
|
|
}
|
|
|
|
for( var i = 0; i < uvSetCount; ++i )
|
|
{
|
|
UvColorSets[ i ].Name = UseOffset( strings, uvOffsets[ i ] );
|
|
}
|
|
|
|
for( var i = 0; i < colorSetCount; ++i )
|
|
{
|
|
ColorSets[ i ].Name = UseOffset( strings, colorOffsets[ i ] );
|
|
}
|
|
|
|
ShaderPackage.Name = UseOffset( strings, shaderPackageNameOffset );
|
|
|
|
AdditionalData = r.ReadBytes( additionalDataSize );
|
|
ColorSetData = r.ReadStructuresAsArray< ushort >( dataSetSize / 2 );
|
|
|
|
var shaderValueListSize = r.ReadUInt16();
|
|
var shaderKeyCount = r.ReadUInt16();
|
|
var constantCount = r.ReadUInt16();
|
|
var samplerCount = r.ReadUInt16();
|
|
ShaderPackage.Unk = r.ReadUInt32();
|
|
|
|
ShaderPackage.ShaderKeys = r.ReadStructuresAsArray< ShaderKey >( shaderKeyCount );
|
|
ShaderPackage.Constants = r.ReadStructuresAsArray< Constant >( constantCount );
|
|
ShaderPackage.Samplers = r.ReadStructuresAsArray< Sampler >( samplerCount );
|
|
ShaderPackage.ShaderValues = r.ReadStructuresAsArray< float >( shaderValueListSize / 4 );
|
|
}
|
|
|
|
private static Texture[] ReadTextureOffsets( BinaryReader r, int count, out ushort[] offsets )
|
|
{
|
|
var ret = new Texture[count];
|
|
offsets = new ushort[count];
|
|
for( var i = 0; i < count; ++i )
|
|
{
|
|
offsets[ i ] = r.ReadUInt16();
|
|
ret[ i ].Flags = r.ReadUInt16();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
private static ColorSet[] ReadColorSetOffsets( BinaryReader r, int count, out ushort[] offsets )
|
|
{
|
|
var ret = new ColorSet[count];
|
|
offsets = new ushort[count];
|
|
for( var i = 0; i < count; ++i )
|
|
{
|
|
offsets[ i ] = r.ReadUInt16();
|
|
ret[ i ].Index = r.ReadUInt16();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
private static string UseOffset( ReadOnlySpan< byte > strings, ushort offset )
|
|
{
|
|
strings = strings[ offset.. ];
|
|
var end = strings.IndexOf( ( byte )'\0' );
|
|
return Encoding.UTF8.GetString( strings[ ..end ] );
|
|
}
|
|
} |