Skip to content

Commit 223a936

Browse files
authored
Merge pull request #28 from lmcintyre/texfix
Fix on both ends (create, import) of TT for uncompressed Tex sizes
2 parents d870525 + c4b3c25 commit 223a936

File tree

5 files changed

+110
-14
lines changed

5 files changed

+110
-14
lines changed

xivModdingFramework/Cache/XivCache.cs

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
44
using System.Data.SQLite;
@@ -15,6 +15,7 @@
1515
using xivModdingFramework.Items.Interfaces;
1616
using xivModdingFramework.Models.FileTypes;
1717
using xivModdingFramework.Mods;
18+
using xivModdingFramework.Mods.DataContainers;
1819
using xivModdingFramework.Resources;
1920
using xivModdingFramework.SqPack.FileTypes;
2021

@@ -31,7 +32,7 @@ public static class XivCache
3132
private static GameInfo _gameInfo;
3233
private static DirectoryInfo _dbPath;
3334
private static DirectoryInfo _rootCachePath;
34-
public static readonly Version CacheVersion = new Version("1.0.2.1");
35+
public static readonly Version CacheVersion = new Version("1.0.2.2");
3536
private const string dbFileName = "mod_cache.db";
3637
private const string rootCacheFileName = "item_sets.db";
3738
private const string creationScript = "CreateCacheDB.sql";
@@ -187,7 +188,11 @@ public static void SetGameInfo(GameInfo gameInfo = null, bool enableCacheWorker
187188
var reason = CacheNeedsRebuild();
188189
if (reason != CacheRebuildReason.CacheOK && !_REBUILDING)
189190
{
190-
RebuildCache(reason);
191+
var ver =
192+
reason == CacheRebuildReason.CacheVersionUpdate
193+
? new Version(GetMetaValue("cache_version")) : CacheVersion;
194+
195+
RebuildCache(ver, reason);
191196
}
192197
}
193198

@@ -277,7 +282,7 @@ private static CacheRebuildReason CacheNeedsRebuild()
277282
/// help ensure it's never accidentally called
278283
/// without an await.
279284
/// </summary>
280-
public static void RebuildCache(CacheRebuildReason reason = CacheRebuildReason.ManualRequest)
285+
public static void RebuildCache(Version previousVersion, CacheRebuildReason reason = CacheRebuildReason.ManualRequest)
281286
{
282287
CacheWorkerEnabled = false;
283288
_REBUILDING = true;
@@ -309,7 +314,13 @@ public static void RebuildCache(CacheRebuildReason reason = CacheRebuildReason.M
309314
tasks.Add(RebuildFurnitureCache());
310315
tasks.Add(BuildModdedItemDependencies());
311316

312-
await Task.WhenAll(tasks);
317+
// This was originally running only if the reason was cache update,
318+
// but if the cache gets messed up in one way or another, and has to
319+
// rebuild on a new TT version for any reason other than CacheUpdate
320+
// or whatever, it will prevent the migration from occurring properly
321+
tasks.Add(MigrateCache(previousVersion));
322+
323+
await Task.WhenAll(tasks);
313324

314325
var post = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
315326

@@ -451,7 +462,47 @@ private static void CreateCache()
451462
}
452463
}
453464

465+
private static async Task MigrateCache(Version lastCacheVersion) {
466+
467+
// Tex file fix migration
468+
// This technically has nothing to do with the cache version,
469+
// but I think this is one of the only places that this can go
470+
if (lastCacheVersion < new Version(1, 0, 2, 2)) {
471+
var m = new Modding(_gameInfo.GameDirectory);
472+
var modList = m.GetModList();
473+
foreach (var mod in modList.Mods) {
474+
if (mod.data.dataType != 4) continue;
475+
476+
var datNum = (int)((mod.data.modOffset / 8) & 0x0F) / 2;
477+
var dat = XivDataFiles.GetXivDataFile(mod.datFile);
454478

479+
var datPath = $"{_gameInfo.GameDirectory}/{dat.GetDataFileName()}{Dat.DatExtension}{datNum}";
480+
481+
int uncompressedSize = -1;
482+
long seekTo = Dat.OffsetCorrection(datNum, mod.data.modOffset) + 8;
483+
484+
// Seek to and read the uncompressed texture size catching any exceptions
485+
// because we handle further processing with the initial value of -1
486+
try
487+
{
488+
using var reader = new BinaryReader(File.OpenRead(datPath));
489+
reader.BaseStream.Position = seekTo;
490+
491+
uncompressedSize = reader.ReadInt32();
492+
} catch (Exception) {}
493+
494+
// If we read an uncompressed size, seek to the same position and write the fixed uncompressed texture size
495+
if (uncompressedSize != -1)
496+
{
497+
using var writer = new BinaryWriter(File.OpenWrite(datPath));
498+
writer.BaseStream.Position = seekTo;
499+
500+
var tmp = BitConverter.GetBytes(uncompressedSize + 80);
501+
writer.Write(tmp);
502+
}
503+
}
504+
}
505+
}
455506

456507
/// <summary>
457508
/// Populate the ui table.

xivModdingFramework/Helpers/ProblemChecker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public Task PerformStartOver(DirectoryInfo backupsDirectory, IProgress<string> p
258258

259259
await Task.Run(async () =>
260260
{
261-
XivCache.RebuildCache();
261+
XivCache.RebuildCache(XivCache.CacheVersion);
262262
});
263263
}
264264
});

xivModdingFramework/Mods/FileTypes/TTMP.cs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// xivModdingFramework
1+
// xivModdingFramework
22
// Copyright © 2018 Rafael Gonzalez - All Rights Reserved
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -48,9 +48,9 @@ public class TTMP
4848
".cmp", ".imc", ".eqdp", ".eqp", ".gmp", ".est"
4949
};
5050

51-
private readonly string _currentWizardTTMPVersion = "1.2w";
52-
private readonly string _currentSimpleTTMPVersion = "1.2s";
53-
private const string _minimumAssembly = "1.2.0.0";
51+
private readonly string _currentWizardTTMPVersion = "1.3w";
52+
private readonly string _currentSimpleTTMPVersion = "1.3s";
53+
private const string _minimumAssembly = "1.3.0.0";
5454

5555
private string _tempMPD, _tempMPL, _source;
5656
private readonly DirectoryInfo _modPackDirectory;
@@ -423,7 +423,7 @@ public Task<List<OriginalModPackJson>> GetOriginalModPackJsonData(DirectoryInfo
423423
/// </summary>
424424
/// <param name="modPackDirectory">The mod pack directory</param>
425425
/// <returns>The version of the mod pack as a string</returns>
426-
public string GetVersion(DirectoryInfo modPackDirectory)
426+
public static string GetVersion(DirectoryInfo modPackDirectory)
427427
{
428428
ModPackJson modPackJson = null;
429429

@@ -529,6 +529,7 @@ await Task.Run(async () =>
529529

530530
var _modding = new Modding(XivCache.GameInfo.GameDirectory);
531531
var modList = _modding.GetModList();
532+
var needsTexFix = DoesTexNeedFixing(modPackDirectory);
532533

533534
// 0 - Extract the MPD file.
534535
using (var zf = ZipFile.Read(modPackDirectory.FullName))
@@ -572,6 +573,10 @@ await Task.Run(async () =>
572573
{
573574
binaryReader.BaseStream.Seek(modJson.ModOffset, SeekOrigin.Begin);
574575
var data = binaryReader.ReadBytes(modJson.ModSize);
576+
577+
if (modJson.FullPath.EndsWith(".tex") && needsTexFix)
578+
FixupTextoolsTex(data);
579+
575580
var df = IOUtil.GetDataFileFromPath(modJson.FullPath);
576581

577582
var size = data.Length;
@@ -953,6 +958,46 @@ await Task.Run(async () =>
953958
return (count, errorCount, importErrors, seconds);
954959
}
955960

961+
/// <summary>
962+
/// Parse the version out of this modpack to determine whether or not we need
963+
/// to add 80 to the uncompressed size of the Tex files contained within.
964+
/// </summary>
965+
/// <param name="mpd">The path to the modpack.</param>
966+
/// <returns>True if we must modify tex header uncompressed sizes, false otherwise.</returns>
967+
private static bool DoesTexNeedFixing(DirectoryInfo mpd) {
968+
969+
var ver = GetVersion(mpd);
970+
if (string.IsNullOrEmpty(ver))
971+
return true;
972+
973+
var newVer = ver;
974+
975+
var lastChar = ver.Substring(ver.Length - 1)[0];
976+
if (char.IsLetter(lastChar))
977+
newVer = ver.Substring(0, ver.Length - 1);
978+
979+
double.TryParse(newVer, out var verDouble);
980+
981+
return verDouble < 1.3;
982+
}
983+
984+
/// <summary>
985+
/// Fix xivModdingFramework TEX quirks.
986+
/// </summary>
987+
/// <param name="tex">The TEX data to be fixed up.</param>
988+
public static void FixupTextoolsTex(byte[] tex) {
989+
990+
// Read the uncompressed size from the file
991+
var size = BitConverter.ToInt32(tex, 8);
992+
var newSize = size + 80;
993+
994+
byte[] buffer = BitConverter.GetBytes(newSize);
995+
tex[8] = buffer[0];
996+
tex[9] = buffer[1];
997+
tex[10] = buffer[2];
998+
tex[11] = buffer[3];
999+
}
1000+
9561001
/// <summary>
9571002
/// Gets the data type from an item path
9581003
/// </summary>

xivModdingFramework/SqPack/FileTypes/Dat.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// xivModdingFramework
1+
// xivModdingFramework
22
// Copyright © 2018 Rafael Gonzalez - All Rights Reserved
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -1266,7 +1266,7 @@ public byte[] MakeType4DatHeader(XivTexFormat format, List<short> mipPartOffsets
12661266

12671267
headerData.AddRange(BitConverter.GetBytes(headerSize + headerPadding));
12681268
headerData.AddRange(BitConverter.GetBytes(4));
1269-
headerData.AddRange(BitConverter.GetBytes(uncompressedLength));
1269+
headerData.AddRange(BitConverter.GetBytes(uncompressedLength + 80));
12701270
headerData.AddRange(BitConverter.GetBytes(0));
12711271
headerData.AddRange(BitConverter.GetBytes(0));
12721272
headerData.AddRange(BitConverter.GetBytes(newMipCount));

xivModdingFramework/xivModdingFramework.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
5-
<AssemblyVersion>1.2.0.0</AssemblyVersion>
5+
<AssemblyVersion>1.3.0.0</AssemblyVersion>
66
<Version>1.0.8</Version>
77
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
88
<LangVersion>latest</LangVersion>

0 commit comments

Comments
 (0)