Skip to content

Commit 381fc0d

Browse files
Support patch 7.2 format stm files
1 parent d9db56d commit 381fc0d

File tree

1 file changed

+28
-23
lines changed
  • xivModdingFramework/Materials/FileTypes

1 file changed

+28
-23
lines changed

xivModdingFramework/Materials/FileTypes/STM.cs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public Half[] GetData(int offset, int dyeId = 0)
201201
}},
202202
};
203203

204-
public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate templateType)
204+
public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate templateType, bool oldFormat = false)
205205
{
206206
var arrayEnds = new List<ushort>();
207207
var start = offset;
@@ -212,9 +212,9 @@ public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate template
212212
_ItemCount = 5;
213213
}
214214

215+
var numDyes = oldFormat ? 128 : 254;
215216

216217
// This format sucks.
217-
var moreData = new List<ushort>();
218218
for (int i = 0; i < _ItemCount; i++)
219219
{
220220
arrayEnds.Add(BitConverter.ToUInt16(data, offset));
@@ -244,17 +244,17 @@ public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate template
244244
// Single entry used for everything.
245245
type = StainingTemplateArrayType.Singleton;
246246
}
247-
if(arraySize == 0)
247+
else if(arraySize == 0)
248248
{
249249
// No data.
250250
continue;
251251
}
252-
else if (arraySize < 128)
252+
else
253253
{
254254
// Indexed array, where we have [n] # of real entries,
255-
// then 128 one-byte index entries referencing those [n] entries.
255+
// then 254 one-byte index entries referencing those [n] entries.
256256
var totalBytes = (arrayEnds[x] - lastOffset) *2;
257-
var remBytes = totalBytes - 128;
257+
var remBytes = totalBytes - numDyes;
258258

259259
indexStart = start + headerSize + (lastOffset * 2) + remBytes;
260260

@@ -287,9 +287,7 @@ public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate template
287287
if(type == StainingTemplateArrayType.Indexed)
288288
{
289289
var nArray = new List<Half[]>();
290-
var indexes = new byte[128];
291-
var indexCopy = data.Skip(indexStart).Take(129).ToArray();
292-
for (int i = 0; i < 128; i++)
290+
for (int i = 0; i < numDyes; i++)
293291
{
294292
try
295293
{
@@ -321,7 +319,7 @@ public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate template
321319

322320
if (halfData.Count == 1)
323321
{
324-
for (int i = 0; i < 127; i++)
322+
for (int i = 0; i < numDyes; i++)
325323
{
326324
halfData.Add(halfData[0]);
327325
}
@@ -337,8 +335,6 @@ public StainingTemplateEntry(byte[] data, int offset, EStainingTemplate template
337335

338336
lastOffset = arrayEnds[x];
339337
}
340-
341-
var length = lastOffset;
342338
}
343339

344340
}
@@ -378,41 +374,50 @@ public StainingTemplateFile(byte[] data, EStainingTemplate templateType)
378374
TemplateType = templateType;
379375
// Get header size and # of entries.
380376
var Header = BitConverter.ToUInt16(data, 0);
377+
var Version = BitConverter.ToUInt16(data, 2);
381378
var entryCount = BitConverter.ToUInt16(data, 4);
382379
var unknown = BitConverter.ToUInt16(data, 6);
383380

381+
// Number got bigger since Patch 7.2
382+
// stainingtemplate_gud.stm (DT / non-legacy) can be distinguished by Version number
383+
// stainingtemplate.stm (EW / legacy) instead uses a janky heuristic
384+
// Once CN/KR are updated to 7.2, this logic can be removed
385+
bool oldFormat = false;
386+
if (templateType == EStainingTemplate.Dawntrail && Version < 0x201)
387+
oldFormat = true;
388+
else if (templateType == EStainingTemplate.Endwalker && (data[0x0A] != 0x00 || data[0x0B] != 0x00))
389+
oldFormat = true;
384390

385-
Dictionary<ushort, int> entryOffsets = new Dictionary<ushort, int>();
391+
Dictionary<uint, int> entryOffsets = new Dictionary<uint, int>();
386392

387-
List<ushort> keys = new List<ushort>();
388-
List<ushort> values = new List<ushort>();
389-
List<int> sizes = new List<int>();
393+
List<uint> keys = new List<uint>();
390394
var offset = 8;
391395

392396
// Read template Ids
393397
for (int i = 0; i < entryCount; i++)
394398
{
395-
var key = BitConverter.ToUInt16(data, offset);
399+
var key = oldFormat ? (uint)BitConverter.ToUInt16(data, offset) : BitConverter.ToUInt32(data, offset);
396400
entryOffsets.Add(key, 0);
397401
keys.Add(key);
398-
offset += 2;
402+
offset += oldFormat ? 2 : 4;
399403
}
400404

401-
const int _headerEntrySize = 4;
405+
const int _headerEntrySize = 8;
402406
var endOfHeader = (8 + (_headerEntrySize * entryCount));
403407

404408
for (int i = 0; i < entryCount; i++)
405409
{
406-
entryOffsets[keys[i]] = ((BitConverter.ToUInt16(data, offset) * 2) + endOfHeader);
407-
offset += 2;
410+
var rawOffset = oldFormat ? (uint)BitConverter.ToUInt16(data, offset) : BitConverter.ToUInt32(data, offset);
411+
entryOffsets[keys[i]] = (int)rawOffset * 2 + endOfHeader;
412+
offset += oldFormat ? 2 : 4;
408413
}
409414

410415

411416
var idx = 0;
412417
foreach (var kv in entryOffsets)
413418
{
414-
var entry = new StainingTemplateEntry(data, kv.Value, templateType);
415-
Templates.Add(kv.Key, entry);
419+
var entry = new StainingTemplateEntry(data, kv.Value, templateType, oldFormat);
420+
Templates.Add((ushort)kv.Key, entry);
416421
idx++;
417422
}
418423
}

0 commit comments

Comments
 (0)