diff --git a/DataTool/FindLogic/Combo.cs b/DataTool/FindLogic/Combo.cs index 8364d460..2b424965 100644 --- a/DataTool/FindLogic/Combo.cs +++ b/DataTool/FindLogic/Combo.cs @@ -671,19 +671,35 @@ public static ComboInfo Find(ComboInfo info, ulong guid, DictionaryTank ShaderCode, file type 087 public class teShaderCode { /// ShaderCode Header - [StructLayout(LayoutKind.Sequential, Pack = 4)] + [StructLayout(LayoutKind.Explicit)] public struct ShaderCodeHeader { + /// Shader type flags + [FieldOffset(8)] public Enums.teSHADER_TYPE ShaderType; // 36 -> 8 /// Offset to data - public long DataOffset; // 0 - - /// Offset to unknown data - public long OffsetB; // 8 - - public uint UnknownFF; // 16 - - /// Unknown data count - public uint StreamOutDescCount; // 20 - + [FieldOffset(112)] public long DataOffset; // 0 -> 112 /// Size of compressed DXBC data - public int CompressedSize; // 24 - + [FieldOffset(132)] public int CompressedSize; // 24 -> 132 /// Size of decompressed DXBC data - public int UncompressedSize; // 28 - - public uint Unknown; // 32 - - /// Shader type - public Enums.teSHADER_TYPE ShaderType; // 36 - - // etc + [FieldOffset(136)] public int UncompressedSize; // 28 -> 136 } /// Header Data diff --git a/TankLib/teShaderGroup.cs b/TankLib/teShaderGroup.cs index ec480633..ec367b0d 100644 --- a/TankLib/teShaderGroup.cs +++ b/TankLib/teShaderGroup.cs @@ -1,36 +1,18 @@ using System.IO; using System.Runtime.InteropServices; +using TankLib.Helpers; namespace TankLib { /// Tank ShaderGroup, file type 085 public class teShaderGroup { - [StructLayout(LayoutKind.Sequential, Pack = 4)] + [StructLayout(LayoutKind.Explicit)] public struct GroupHeader { + /// Number of entries for both ShadersOffset and InstancesOffset + [FieldOffset(100)] public int NumShaders; // 64 -> 76 -> 100 + /// ShaderCode array offset + [FieldOffset(104)] public long ShadersOffset; // na -> 104 /// ShaderInstance array offset - public long InstanceOffset; // 0 - - public long HashOffset; // 8 - public long FlagsOffset; // 16 - - public long NewIdk; // n/a -> 24 - - public long OffsetD; // 24 -> 32 - public long OffsetE; // 32 -> 40 - - /// teShaderSource that this group was generated from - /// 088 GUID - public teResourceGUID SourceGUID; // 40 -> 48 - - /// A virtual reference. Usage unknown - /// 00F GUID - public teResourceGUID CacheGUID; // 48 -> 56 - - public ulong Flags; // 56 -> 64 - - public int NumIdk; // n/a -> 72 - public int NumShaders; // 64 -> 76 - - // ... + [FieldOffset(120)] public long InstancesOffset; // 0 -> 100 } [StructLayout(LayoutKind.Sequential, Pack = 4)] @@ -54,17 +36,15 @@ public struct ShaderUnk { /// Header Data public GroupHeader Header; - /// ShaderInstances + /// teShaderCode GUIDs (087) + public teResourceGUID[] Shaders; + + /// teShaderInstance info GUIDs (040) public teResourceGUID[] Instances; /// Flags that are used to select the correct ShaderInstance pair based on parameters public ulong[] InstanceFlags; - /// - /// ShaderInstance "hashes". Used to identify instances in 088 groups. - /// - public uint[] Hashes; - public ShaderQuality[] ShaderQualities; public ShaderUnk[] ShaderUnks; @@ -89,43 +69,27 @@ public teShaderGroup(BinaryReader reader) { private void Read(BinaryReader reader) { Header = reader.Read(); - if (Header.InstanceOffset > 0) { - reader.BaseStream.Position = Header.InstanceOffset; - Instances = reader.ReadArray(Header.NumShaders); - } - - if (Header.HashOffset > 0) { - reader.BaseStream.Position = Header.HashOffset; - Hashes = reader.ReadArray(Header.NumShaders); + if (Header.ShadersOffset > 0) { + reader.BaseStream.Position = Header.ShadersOffset; + Shaders = reader.ReadArray(Header.NumShaders); } - if (Header.FlagsOffset > 0) { - reader.BaseStream.Position = Header.FlagsOffset; - InstanceFlags = reader.ReadArray(Header.NumShaders); - } - - { - reader.BaseStream.Position = 72; - ShaderQualities = reader.ReadArray(5); - - reader.BaseStream.Position = 104; - ShaderUnks = reader.ReadArray(5); + if (Header.InstancesOffset > 0) { + reader.BaseStream.Position = Header.InstancesOffset; + Instances = reader.ReadArray(Header.NumShaders); } } /// + /// DEPRECATED: teShaderGroup used to store a hash to match with a specific teShaderInstance. This mapping has since been broken as + /// teShaderGroup now holds guids to both teShaderInstance and teShaderCode mapping them with a simple positional index instead. /// Get a ShaderInstance GUID from a "hash" /// /// Mostly used on 088 groups /// "Hash" associated with a specific ShaderInstance /// public teResourceGUID GetShaderByHash(uint hash) { - if (Hashes == null) return (teResourceGUID) 0; - for (int i = 0; i < Header.NumShaders; i++) { - if (Hashes[i] == hash) { - return Instances[i]; - } - } + Logger.Error("teShaderGroup", $"GetShaderByHash doesn't work any longer for {hash:X16}, see documentation on GetShaderByHash."); return (teResourceGUID) 0; } }