@@ -82,14 +82,14 @@ public struct TexHeader
82
82
public ushort Depth ;
83
83
84
84
public byte MipCount ;
85
- public bool MipFlag ;
85
+ public byte MipFlag ;
86
86
87
87
public byte ArraySize ;
88
88
89
89
// 3 Ints, representing which MipMaps to use at each LoD level.
90
- uint [ ] LoDMips ;
90
+ public uint [ ] LoDMips ;
91
91
92
- uint [ ] MipMapOffsets ;
92
+ public uint [ ] MipMapOffsets ;
93
93
94
94
/// <summary>
95
95
/// Reads a .tex file header (80 bytes) from the given stream.
@@ -111,7 +111,7 @@ internal static TexHeader ReadTexHeader(BinaryReader br, long offset = -1)
111
111
112
112
header . Depth = br . ReadUInt16 ( ) ;
113
113
header . MipCount = br . ReadByte ( ) ;
114
- header . MipFlag = ( header . MipCount & 8 ) > 0 ;
114
+ header . MipFlag = ( byte ) ( header . MipCount >> 4 ) ;
115
115
header . MipCount = ( byte ) ( header . MipCount & 0xF ) ;
116
116
header . ArraySize = br . ReadByte ( ) ;
117
117
@@ -128,6 +128,39 @@ internal static TexHeader ReadTexHeader(BinaryReader br, long offset = -1)
128
128
}
129
129
return header ;
130
130
}
131
+
132
+ /// <summary>
133
+ /// Writes a .tex file header from this.
134
+ /// </summary>
135
+ /// <returns>Byte array containing the header data.</returns>
136
+ internal byte [ ] ToBytes ( )
137
+ {
138
+ if ( this . LoDMips [ 1 ] < this . LoDMips [ 0 ] || this . LoDMips [ 2 ] < this . LoDMips [ 1 ] )
139
+ throw new InvalidOperationException ( "LoDMips is not in non-descending order." ) ;
140
+ if ( this . LoDMips [ 2 ] >= this . MipCount )
141
+ throw new InvalidOperationException ( "All LoDMips must be strictly lesser than MipCount." ) ;
142
+ if ( this . MipFlag > 15 )
143
+ throw new InvalidOperationException ( "MipFlag must be strictly lesser than 16." ) ;
144
+ if ( this . MipCount > 13 )
145
+ throw new InvalidOperationException ( "MipCount must be strictly lesser than 14." ) ;
146
+
147
+ var res = new byte [ _TexHeaderSize ] ;
148
+ var bw = new BinaryWriter ( new MemoryStream ( res , true ) ) ;
149
+ bw . Write ( this . Attributes ) ;
150
+ bw . Write ( this . TextureFormat ) ;
151
+ bw . Write ( this . Width ) ;
152
+ bw . Write ( this . Height ) ;
153
+ bw . Write ( this . Depth ) ;
154
+ bw . Write ( ( byte ) ( ( this . MipFlag << 4 ) | this . MipCount ) ) ;
155
+ bw . Write ( this . ArraySize ) ;
156
+ foreach ( var x in this . LoDMips )
157
+ bw . Write ( x ) ;
158
+ foreach ( var x in this . MipMapOffsets )
159
+ bw . Write ( x ) ;
160
+
161
+ Debug . Assert ( bw . BaseStream . Position == _TexHeaderSize , "Data was not fully written." ) ;
162
+ return res ;
163
+ }
131
164
}
132
165
133
166
@@ -1244,13 +1277,21 @@ public static async Task<byte[]> CompressTexFile(BinaryReader br, uint lengthInc
1244
1277
var uncompLength = lengthIncludingHeader - _TexHeaderSize ;
1245
1278
1246
1279
1247
- br . BaseStream . Seek ( offset , SeekOrigin . Begin ) ;
1280
+ br . BaseStream . Seek ( offset + _TexHeaderSize , SeekOrigin . Begin ) ;
1248
1281
1249
1282
// Type 4 Header
1250
1283
newTex . AddRange ( Dat . MakeType4DatHeader ( ( XivTexFormat ) header . TextureFormat , ddsParts , ( int ) uncompLength , header . Width , header . Height ) ) ;
1251
1284
1252
1285
// Texture file header.
1253
- newTex . AddRange ( br . ReadBytes ( ( int ) _TexHeaderSize ) ) ;
1286
+ // CompressDDSBody call above alters individual mipmap sizes, ending up changing the offsets.
1287
+ // Calculate those again here.
1288
+ header . MipMapOffsets [ 0 ] = _TexHeaderSize ;
1289
+ for ( var i = 1 ; i < header . MipCount ; i ++ )
1290
+ header . MipMapOffsets [ i ] = header . MipMapOffsets [ i - 1 ] + ( uint ) ddsParts [ i - 1 ] . Count ;
1291
+ header . LoDMips [ 0 ] = Math . Min ( header . MipCount - 1u , header . LoDMips [ 0 ] ) ;
1292
+ header . LoDMips [ 1 ] = Math . Min ( header . MipCount - 1u , Math . Max ( header . LoDMips [ 0 ] , header . LoDMips [ 1 ] ) ) ;
1293
+ header . LoDMips [ 2 ] = Math . Min ( header . MipCount - 1u , Math . Max ( header . LoDMips [ 1 ] , header . LoDMips [ 2 ] ) ) ;
1294
+ newTex . AddRange ( header . ToBytes ( ) ) ;
1254
1295
1255
1296
// Compressed pixel data.
1256
1297
foreach ( var mip in ddsParts )
0 commit comments