Skip to content

Commit cf875b4

Browse files
authored
Merge pull request #74 from Soreepeong/patch-1
Recalculate mipmap offsets after regeneration
2 parents 675de17 + da7c137 commit cf875b4

File tree

1 file changed

+47
-6
lines changed
  • xivModdingFramework/Textures/FileTypes

1 file changed

+47
-6
lines changed

xivModdingFramework/Textures/FileTypes/Tex.cs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ public struct TexHeader
8282
public ushort Depth;
8383

8484
public byte MipCount;
85-
public bool MipFlag;
85+
public byte MipFlag;
8686

8787
public byte ArraySize;
8888

8989
// 3 Ints, representing which MipMaps to use at each LoD level.
90-
uint[] LoDMips;
90+
public uint[] LoDMips;
9191

92-
uint[] MipMapOffsets;
92+
public uint[] MipMapOffsets;
9393

9494
/// <summary>
9595
/// Reads a .tex file header (80 bytes) from the given stream.
@@ -111,7 +111,7 @@ internal static TexHeader ReadTexHeader(BinaryReader br, long offset = -1)
111111

112112
header.Depth = br.ReadUInt16();
113113
header.MipCount = br.ReadByte();
114-
header.MipFlag = (header.MipCount & 8) > 0;
114+
header.MipFlag = (byte)(header.MipCount >> 4);
115115
header.MipCount = (byte)(header.MipCount & 0xF);
116116
header.ArraySize = br.ReadByte();
117117

@@ -128,6 +128,39 @@ internal static TexHeader ReadTexHeader(BinaryReader br, long offset = -1)
128128
}
129129
return header;
130130
}
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+
}
131164
}
132165

133166

@@ -1244,13 +1277,21 @@ public static async Task<byte[]> CompressTexFile(BinaryReader br, uint lengthInc
12441277
var uncompLength = lengthIncludingHeader - _TexHeaderSize;
12451278

12461279

1247-
br.BaseStream.Seek(offset, SeekOrigin.Begin);
1280+
br.BaseStream.Seek(offset + _TexHeaderSize, SeekOrigin.Begin);
12481281

12491282
// Type 4 Header
12501283
newTex.AddRange(Dat.MakeType4DatHeader((XivTexFormat)header.TextureFormat, ddsParts, (int)uncompLength, header.Width, header.Height));
12511284

12521285
// 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());
12541295

12551296
// Compressed pixel data.
12561297
foreach (var mip in ddsParts)

0 commit comments

Comments
 (0)