Skip to content

Commit

Permalink
Merge pull request #82 from Soreepeong/fix/texheader-mipcount
Browse files Browse the repository at this point in the history
Repurpose MSB of MipLevelsCount
  • Loading branch information
NotAdam authored Apr 24, 2024
2 parents da342d2 + b64a11b commit 8520307
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
40 changes: 26 additions & 14 deletions src/Lumina/Data/Files/TexFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,9 @@ public unsafe struct TexHeader
[FieldOffset( 12 )]
public ushort Depth;

/// <summary>
/// The field has been repurposed; use <see cref="MipLevelsCount"/>.
/// </summary>
[FieldOffset( 14 )]
[Obsolete( $"Use {nameof( MipLevelsCount )} instead; the field has been repurposed as two fields." )]
public ushort MipLevels;

/// <summary>
/// Number of mipmaps in the texture.
/// </summary>
/// <remarks>There should be at least 1 and at most 13 mipmap entries; refer to the length of <see cref="OffsetToSurface"/>.</remarks>
/// <summary>The field has been repurposed; use <see cref="MipCount"/>.</summary>
[FieldOffset( 14 )]
[Obsolete( $"Use {nameof( MipCount )} instead; the field has been repurposed as two fields." )]
public byte MipLevelsCount;

/// <summary>
Expand All @@ -200,7 +191,28 @@ public unsafe struct TexHeader
/// </summary>
[FieldOffset( 28 )]
public fixed uint OffsetToSurface[13];
};

#pragma warning disable CS0618 // Type or member is obsolete

/// <summary>Number of mipmaps in the texture.</summary>
/// <remarks>There should be at least 1 and at most 13 mipmap entries; refer to the length of <see cref="OffsetToSurface"/>.</remarks>
public int MipCount {
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => MipLevelsCount & 0x7F;
set => MipLevelsCount = (byte) ( ( MipLevelsCount & 0x80 ) | ( value is >= 0 and <= 0x7F
? value
: throw new ArgumentOutOfRangeException( nameof( value ), value, "Value is out of supported range from the value type." ) ) );
}

/// <summary>An unknown boolean value that seems to have something to do with mipmap level to load.</summary>
public bool MipUnknownFlag {
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => ( MipLevelsCount & 0x80 ) != 0;
set => MipLevelsCount = (byte) (( MipLevelsCount & 0x7F ) | ( value ? 0x80 : 0 ));
}

#pragma warning restore CS0618 // Type or member is obsolete
}

/// <summary>
/// Specify preprocessing texture data for consumption in DXGI.
Expand Down Expand Up @@ -277,7 +289,7 @@ public override void LoadFile()
/// <returns>Number of bytes.</returns>
public int SliceSize( int mipmapIndex, out int width, out int height )
{
if( mipmapIndex < 0 || mipmapIndex >= Math.Max( (int) Header.MipLevelsCount, 1 ) )
if( mipmapIndex < 0 || mipmapIndex >= Math.Max( Header.MipCount, 1 ) )
throw new ArgumentOutOfRangeException( nameof( mipmapIndex ), mipmapIndex, null );

var bpp = 1 << ( (int) ( Header.Format & TextureFormat.BppMask ) >> (int) TextureFormat.BppShift );
Expand Down Expand Up @@ -313,7 +325,7 @@ public int SliceSize( int mipmapIndex, out int width, out int height )
public unsafe Span< byte > SliceSpan( int mipmapIndex, int sliceIndex, out int sliceSize, out int width, out int height )
{
sliceSize = SliceSize( mipmapIndex, out width, out height );
if( mipmapIndex < 0 || mipmapIndex >= Math.Max( (int) Header.MipLevelsCount, 1 ) )
if( mipmapIndex < 0 || mipmapIndex >= Math.Max( Header.MipCount, 1 ) )
throw new ArgumentOutOfRangeException( nameof( mipmapIndex ), mipmapIndex, null );

switch( Header.Type & Attribute.TextureTypeMask )
Expand Down
2 changes: 1 addition & 1 deletion src/Lumina/Data/Parsing/Tex/Buffers/TextureBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ public static TextureBuffer FromTextureFormat(
/// </summary>
public static unsafe TextureBuffer FromStream( TexFile.TexHeader header, LuminaBinaryReader reader )
{
var mipmapAllocations = new int[Math.Min( 13, (int)header.MipLevelsCount )];
var mipmapAllocations = new int[Math.Min( 13, header.MipCount )];
for( var i = 0; i < mipmapAllocations.Length - 1; i++ )
mipmapAllocations[ i ] = (int)( header.OffsetToSurface[ i + 1 ] - header.OffsetToSurface[ i ] );
mipmapAllocations[ ^1 ] = (int)( reader.BaseStream.Length - header.OffsetToSurface[ mipmapAllocations.Length - 1 ] );
Expand Down

0 comments on commit 8520307

Please sign in to comment.