Skip to content

Commit a2ae3e5

Browse files
committed
shader stuff
1 parent 97483f9 commit a2ae3e5

3 files changed

Lines changed: 225 additions & 61 deletions

File tree

CathodeLib/Scripts/CATHODE/Models.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ public class Component
628628
public List<LOD> LODs = new List<LOD>();
629629

630630
//Storing some unknown info about LV426 stuff (Pt1 and Pt2 respectively)
631+
//I think these are just garbage values that got dumped by accident
631632
public int UnkLv426Pt1 = 0;
632633
public int UnkLv426Pt2 = 0;
633634

CathodeLib/Scripts/CATHODE/Shaders.cs

Lines changed: 113 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
using System.Collections.Generic;
44
using System.IO;
55
using System.Runtime.InteropServices;
6+
using static CATHODE.LEGACY.ShadersPAK;
67

78
namespace CATHODE
89
{
910
/* DATA/ENV/PRODUCTION/x/RENDERABLE/LEVEL_SHADERS_DX11.PAK & LEVEL_SHADERS_DX11_BIN.PAK & LEVEL_SHADERS_DX11_IDX_REMAP.PAK */
1011
public class Shaders : CathodeFile
1112
{
13+
public List<Shader> Entries = new List<Shader>();
1214
public static new Implementation Implementation = Implementation.NONE;
1315
public Shaders(string path) : base(path) { }
1416

@@ -25,71 +27,132 @@ override protected bool LoadInternal()
2527
if (!File.Exists(_filepathBIN)) return false;
2628
if (!File.Exists(_filepathIDX)) return false;
2729

28-
using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepathBIN)))
30+
List<Utilities.PAKContent> content = Utilities.ReadPAK(_filepathBIN, FileIdentifiers.SHADER_DATA);
31+
for (int i = 0; i < content.Count; i++)
2932
{
30-
reader.BaseStream.Position = 4; //skip magic
31-
if ((FileIdentifiers)reader.ReadInt32() != FileIdentifiers.ASSET_FILE) return false;
32-
if ((FileIdentifiers)reader.ReadInt32() != FileIdentifiers.SHADER_DATA) return false;
33-
int binEntryCount = reader.ReadInt32();
34-
if (BigEndianUtils.ReadInt32(reader) != binEntryCount) return false;
35-
36-
//Skip rest of the main header
37-
reader.BaseStream.Position = 32;
38-
39-
//Pull each entry's individual header
40-
List<CathodeShaderHeader> _header = new List<CathodeShaderHeader>();
41-
for (int i = 0; i < binEntryCount; i++)
42-
{
43-
CathodeShaderHeader newStringEntry = new CathodeShaderHeader();
44-
reader.BaseStream.Position += 8; //skip blanks
45-
46-
newStringEntry.FileLength = reader.ReadInt32();
47-
newStringEntry.FileLengthWithPadding = reader.ReadInt32();
48-
newStringEntry.FileOffset = reader.ReadInt32();
49-
50-
reader.BaseStream.Position += 8; //skip blanks
51-
52-
newStringEntry.StringPart1 = reader.ReadBytes(4);
53-
newStringEntry.FileIndex = reader.ReadInt32(); //potentially actually int8 or int16 not 32
54-
55-
reader.BaseStream.Position += 8; //skip blanks
33+
if (content[i].BinIndex != i) return false;
5634

57-
newStringEntry.StringPart2 = reader.ReadBytes(4);
58-
59-
//TEMP: For now I'm just setting the filename to be the index... need to work out how the _BIN relates to the initial .PAK to get names, etc
60-
newStringEntry.FileName = newStringEntry.FileIndex + ".DXBC";
61-
//END OF TEMP
62-
63-
_header.Add(newStringEntry);
64-
}
65-
int endOfHeaders = (int)reader.BaseStream.Position;
66-
67-
//Pull each entry's file content
68-
foreach (CathodeShaderHeader shaderEntry in _header)
35+
using (BinaryReader reader = new BinaryReader(new MemoryStream(content[i].Data)))
6936
{
70-
reader.BaseStream.Position = shaderEntry.FileOffset + endOfHeaders;
71-
shaderEntry.FileContent = reader.ReadBytes(shaderEntry.FileLength);
37+
7238
}
7339
}
7440

75-
using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepathIDX)))
41+
//Read the index remapping pak (this is actually just an incrementing count lol)
42+
content = Utilities.ReadPAK(_filepathIDX, FileIdentifiers.SHADER_DATA);
43+
for (int i = 0; i < content.Count; i++)
7644
{
45+
if (content[i].BinIndex != i) return false;
7746

47+
using (BinaryReader reader = new BinaryReader(new MemoryStream(content[i].Data)))
48+
{
49+
int index = reader.ReadInt32();
50+
if (index != i) return false;
51+
}
7852
}
7953

80-
using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath)))
54+
content = Utilities.ReadPAK(_filepath, FileIdentifiers.SHADER_DATA);
55+
for (int i = 0; i < content.Count; i++)
8156
{
82-
reader.BaseStream.Position += 4; //Skip unused
83-
if ((FileIdentifiers)reader.ReadInt32() != FileIdentifiers.ASSET_FILE) return false;
84-
if ((FileIdentifiers)reader.ReadInt32() != FileIdentifiers.SHADER_DATA) return false;
85-
int pakEntryCount = reader.ReadInt32();
86-
if (BigEndianUtils.ReadInt32(reader) != pakEntryCount) return false;
57+
using (BinaryReader reader = new BinaryReader(new MemoryStream(content[i].Data)))
58+
{
59+
reader.BaseStream.Position = 8; //0x7725BBA4, 36, 1
60+
61+
int textureCount = reader.ReadInt16();
62+
int[] cstCounts = new int[5];
63+
for (int x = 0; x < 5; x++) cstCounts[x] = reader.ReadInt32();
64+
int textureLinkCount = reader.ReadInt16();
65+
string name = Utilities.ReadString(reader.ReadBytes(40));
66+
ShaderCategory category = (ShaderCategory)reader.ReadInt16();
67+
68+
// Index 0: 0x04: seems to be metal. 0x01: seems to be non-metal. But it has many exceptions so maybe check renderdoc.
69+
// Index 1: ParallaxMap? It seems to be either 0x30 and 0x80 for the most part, sometimes it combines both into 0xB0.
70+
// Index 2: Lower part of this byte is NormalMap0 related! 0x04 means it has normal map 0. No hits for 1, 2 or 8 yet.
71+
// 0x03 is a thing, but not normal map. What is it? Can be 0x07 where it has normal map and both the 0x03 thing.
72+
// 0x0C is also a thing (8 and 4), so it has normal map and something else?
73+
// I'm gonna say 0x03 means DiffuseMap1.
74+
// Index 3: 0x04 Not OcclusionTint. (NormalMap0 + NormalMap0UVMultiplier + NormalMap0Strength?)
75+
// Index 4: Seems to tell me about AO. If 4, then it has AO tint. If 1 it has AO texture.
76+
// Index 6: Seems to tell me about Dirt/OpacityNoise.
77+
// 0x19 (0001 1001): has opacity noise and dirt maps.
78+
// 0x38 (0011 1000): has dirt map.
79+
// 0x39 (0011 1001): has opacity noise and dirt maps.
80+
// Index 10: First half, only found 4, and it seems to be something included in all (Diffuse0 as well?).
81+
// Seems like the least significant bit enables/disables opacity noise?
82+
int[] flags = new int[20];
83+
for (int x = 0; x < 20; x++) flags[x] = reader.ReadByte();
84+
85+
int unk = reader.ReadInt32();
86+
87+
int entryCount = reader.ReadInt16();
88+
for (int x = 0; x < entryCount; x++)
89+
{
90+
int unk1 = reader.ReadInt16();
91+
int unk2 = reader.ReadInt32();
92+
}
93+
94+
for (int x = 0; x < textureCount; x++)
95+
{
96+
int unk1 = reader.ReadByte();
97+
int unk2 = reader.ReadByte();
98+
int[] unk3 = new int[16];
99+
for (int z = 0; z < 16; z++) unk3[z] = reader.ReadInt16();
100+
float unk4 = reader.ReadSingle();
101+
int unk5 = reader.ReadInt16();
102+
float unk6 = reader.ReadSingle();
103+
}
104+
105+
for (int x = 0; x < textureCount; x++)
106+
{
107+
int unk1 = reader.ReadByte();
108+
}
109+
110+
int[][] cstLinks = new int[5][];
111+
for (int x = 0; x < 5; x++)
112+
{
113+
cstLinks[x] = new int[cstCounts[x]];
114+
for (int z = 0; z < cstCounts[x]; z++)
115+
{
116+
cstLinks[x][z] = reader.ReadByte();
117+
}
118+
}
119+
120+
int[] textureLinks = new int[textureLinkCount];
121+
for (int x = 0; x < textureLinkCount; x++)
122+
{
123+
textureLinks[x] = reader.ReadByte();
124+
}
125+
126+
int vertexShader = reader.ReadInt32();
127+
int pixelShader = reader.ReadInt32();
128+
int hullShader = reader.ReadInt32();
129+
int domainShader = reader.ReadInt32();
130+
131+
//Interestingly, seems like neither of these are used
132+
int geometryShader = reader.ReadInt32();
133+
int computeShader = reader.ReadInt32();
134+
}
87135
}
136+
88137
return true;
89138
}
90139

91140
override protected bool SaveInternal()
92141
{
142+
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepathBIN)))
143+
{
144+
145+
}
146+
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepathIDX)))
147+
{
148+
writer.BaseStream.SetLength(0);
149+
writer.Write(0);
150+
writer.Write((int)FileIdentifiers.ASSET_FILE);
151+
writer.Write((int)FileIdentifiers.MODEL_DATA);
152+
writer.Write(Entries.Count);
153+
writer.Write(Entries.Count);
154+
writer.Write(new byte[12]);
155+
}
93156
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath)))
94157
{
95158

@@ -99,7 +162,7 @@ override protected bool SaveInternal()
99162
#endregion
100163

101164
#region STRUCTURES
102-
public class CathodeShaderHeader
165+
public class Shader
103166
{
104167
public string FileName = ""; //The name of the file in the shader archive (unsure how to get this right now with the weird _BIN/PAK way of working)
105168

@@ -111,6 +174,7 @@ public class CathodeShaderHeader
111174

112175
public byte[] FileContent; //The content for the file
113176

177+
//I think this is just garbage that got dumped by accident
114178
public byte[] StringPart1; //4 bytes that look like they're part of a filepath
115179
public byte[] StringPart2; //4 bytes that look like they're part of a filepath
116180
}

CathodeLib/Scripts/Utilities.cs

Lines changed: 111 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using CATHODE;
12
using CATHODE.Scripting;
23
using System;
34
using System.Collections.Generic;
@@ -193,46 +194,144 @@ public static uint AnimationHashedString(string str)
193194

194195
return hash;
195196
}
197+
198+
//Read a PAK
199+
public static List<PAKContent> ReadPAK(string path, FileIdentifiers type)
200+
{
201+
List<PAKContent> content = new List<PAKContent>();
202+
bool e = type == FileIdentifiers.MODEL_DATA;
203+
204+
using (BinaryReader reader = new BinaryReader(File.OpenRead(path)))
205+
{
206+
reader.BaseStream.Position += 4;
207+
if ((FileIdentifiers)BigEndianUtils.ReadInt32(reader, e) != FileIdentifiers.ASSET_FILE) return null;
208+
if ((FileIdentifiers)BigEndianUtils.ReadInt32(reader, e) != type) return null;
209+
int entryCount = BigEndianUtils.ReadInt32(reader, e);
210+
int entryCountActual = BigEndianUtils.ReadInt32(reader, e);
211+
reader.BaseStream.Position += 12;
212+
213+
int endOfHeaders = 32 + (entryCountActual * 48);
214+
215+
List<OffsetPair> info = new List<OffsetPair>();
216+
for (int i = 0; i < entryCount; i++)
217+
{
218+
reader.BaseStream.Position += 8;
219+
int length = BigEndianUtils.ReadInt32(reader, e);
220+
reader.BaseStream.Position += 4;
221+
int offset = BigEndianUtils.ReadInt32(reader, e);
222+
reader.BaseStream.Position += 12;
223+
int binIndex = BigEndianUtils.ReadInt32(reader, e);
224+
reader.BaseStream.Position += 12;
225+
226+
info.Add(new OffsetPair() { GlobalOffset = offset + endOfHeaders, EntryCount = length });
227+
content.Add(new PAKContent() { BinIndex = binIndex });
228+
}
229+
230+
for (int i = 0; i < entryCount; i++)
231+
{
232+
reader.BaseStream.Position = info[i].GlobalOffset;
233+
content[i].Data = reader.ReadBytes(info[i].EntryCount);
234+
}
235+
}
236+
237+
return content;
238+
}
239+
240+
//Write a PAK
241+
public static void WritePAK(string path, FileIdentifiers type, List<PAKContent> content)
242+
{
243+
bool e = type == FileIdentifiers.MODEL_DATA;
244+
245+
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(path)))
246+
{
247+
//Write content
248+
int contentOffset = 32 + (content.Count * 48);
249+
writer.BaseStream.SetLength(contentOffset);
250+
writer.BaseStream.Position = contentOffset;
251+
List<int> offsets = new List<int>();
252+
List<int> lengths = new List<int>();
253+
for (int i = 0; i < content.Count; i++)
254+
{
255+
offsets.Add((int)writer.BaseStream.Position - contentOffset);
256+
writer.Write(content[i].Data);
257+
lengths.Add((int)writer.BaseStream.Position - contentOffset - offsets[offsets.Count - 1]);
258+
}
259+
260+
//Write model headers
261+
writer.BaseStream.Position = 32;
262+
for (int i = 0; i < content.Count; i++)
263+
{
264+
writer.Write(new byte[8]);
265+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)lengths[i]) : BitConverter.GetBytes((Int32)lengths[i]));
266+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)lengths[i]) : BitConverter.GetBytes((Int32)lengths[i]));
267+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)offsets[i]) : BitConverter.GetBytes((Int32)offsets[i]));
268+
269+
writer.Write(new byte[5]);
270+
writer.Write(type == FileIdentifiers.MODEL_DATA ? new byte[2] { 0x01, 0x01 } : new byte[2]);
271+
writer.Write(new byte[5]);
272+
273+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)content[i].BinIndex) : BitConverter.GetBytes((Int32)content[i].BinIndex));
274+
writer.Write(new byte[12]);
275+
}
276+
277+
//Write header
278+
writer.BaseStream.Position = 0;
279+
writer.Write(new byte[4]);
280+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)FileIdentifiers.ASSET_FILE) : BitConverter.GetBytes((Int32)FileIdentifiers.ASSET_FILE));
281+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)FileIdentifiers.MODEL_DATA) : BitConverter.GetBytes((Int32)FileIdentifiers.MODEL_DATA));
282+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)content.Count) : BitConverter.GetBytes((Int32)content.Count));
283+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)content.Count) : BitConverter.GetBytes((Int32)content.Count));
284+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)16) : BitConverter.GetBytes((Int32)16));
285+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)1) : BitConverter.GetBytes((Int32)1));
286+
writer.Write(e ? BigEndianUtils.FlipEndian((Int32)1) : BitConverter.GetBytes((Int32)1));
287+
}
288+
}
289+
290+
public class PAKContent
291+
{
292+
public int BinIndex;
293+
public byte[] Data;
294+
}
196295
}
197296

198297
public static class BigEndianUtils
199298
{
200-
public static Int64 ReadInt64(BinaryReader Reader)
299+
public static Int64 ReadInt64(BinaryReader Reader, bool bigEndian = true)
201300
{
202301
var data = Reader.ReadBytes(8);
203-
Array.Reverse(data);
302+
if (bigEndian) Array.Reverse(data);
204303
return BitConverter.ToInt64(data, 0);
205304
}
206-
public static UInt64 ReadUInt64(BinaryReader Reader)
305+
public static UInt64 ReadUInt64(BinaryReader Reader, bool bigEndian = true)
207306
{
208307
var data = Reader.ReadBytes(8);
209-
Array.Reverse(data);
308+
if (bigEndian) Array.Reverse(data);
210309
return BitConverter.ToUInt64(data, 0);
211310
}
212311

213-
public static Int32 ReadInt32(BinaryReader Reader)
312+
public static Int32 ReadInt32(BinaryReader Reader, bool bigEndian = true)
214313
{
215314
byte[] data = Reader.ReadBytes(4);
216-
Array.Reverse(data);
315+
if (bigEndian) Array.Reverse(data);
217316
return BitConverter.ToInt32(data, 0);
218317
}
219-
public static UInt32 ReadUInt32(BinaryReader Reader)
318+
public static UInt32 ReadUInt32(BinaryReader Reader, bool bigEndian = true)
220319
{
221320
var data = Reader.ReadBytes(4);
222-
Array.Reverse(data);
321+
if (bigEndian) Array.Reverse(data);
223322
return BitConverter.ToUInt32(data, 0);
224323
}
225324

226-
public static Int16 ReadInt16(BinaryReader Reader)
325+
public static Int16 ReadInt16(BinaryReader Reader, bool bigEndian = true)
227326
{
228327
var data = Reader.ReadBytes(2);
229-
Array.Reverse(data);
328+
if (bigEndian) Array.Reverse(data);
230329
return BitConverter.ToInt16(data, 0);
231330
}
232-
public static UInt16 ReadUInt16(BinaryReader Reader)
331+
public static UInt16 ReadUInt16(BinaryReader Reader, bool bigEndian = true)
233332
{
234333
var data = Reader.ReadBytes(2);
235-
Array.Reverse(data);
334+
if (bigEndian) Array.Reverse(data);
236335
return BitConverter.ToUInt16(data, 0);
237336
}
238337

0 commit comments

Comments
 (0)