Skip to content
This repository has been archived by the owner on Apr 15, 2023. It is now read-only.

Commit

Permalink
Super hacky BLS reader changes, good thing nothing uses it!
Browse files Browse the repository at this point in the history
  • Loading branch information
Marlamin committed Apr 22, 2019
1 parent 0df3c77 commit e7ce54f
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 35 deletions.
65 changes: 54 additions & 11 deletions WoWFormatLib/FileReaders/BLSReader.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using WoWFormatLib.Structs.BLS;
using WoWFormatLib.Utils;

Expand All @@ -10,7 +12,7 @@ namespace WoWFormatLib.FileReaders
public class BLSReader
{
public BLS shaderFile;
private MemoryStream targetStream;
public MemoryStream targetStream;

public BLS LoadBLS(string filename)
{
Expand Down Expand Up @@ -72,6 +74,8 @@ public BLS LoadBLS(Stream stream)

targetStream = new MemoryStream();

shaderFile.decompressedBlocks = new List<byte[]>();

for (var i = 0; i < shaderFile.nCompressedChunks; i++)
{
var chunkStart = shaderFile.ofsCompressedData + shaderOffsets[i];
Expand All @@ -92,7 +96,7 @@ public BLS LoadBLS(Stream stream)
}
}

File.WriteAllBytes("new.bls", targetStream.ToArray());
///File.WriteAllBytes("out.bin", targetStream.ToArray());
}

// Start reading decompressed data
Expand All @@ -105,15 +109,55 @@ public BLS LoadBLS(Stream stream)
var chunkLength = shaderFile.ofsShaderBlocks[i + 1] - shaderFile.ofsShaderBlocks[i];
bin.BaseStream.Position = shaderFile.ofsShaderBlocks[i];

shaderFile.shaderBlocks[i].header = bin.Read<ShaderBlockHeader>();

// Skip non-GL shaders for now
//shaderFile.shaderBlocks[i].header = bin.Read<ShaderBlockHeader>();
var length = (int)bin.ReadUInt32();
var magic = new string(bin.ReadChars(4));
if (magic != "3SLG")
var magicFound = false;
while (!magicFound)
{
//Console.WriteLine(bin.BaseStream.Position + ": " + magic);
var rawMagic = bin.ReadBytes(4);
magic = Encoding.UTF8.GetString(rawMagic);
if(magic == "DXBC" || magic == "MTLB")
{
//File.WriteAllBytes("mtl.bin", targetStream.ToArray());
magicFound = true;
bin.BaseStream.Position -= 8;
length = bin.ReadInt32();
// Console.WriteLine("Found " + magic + " at " + bin.BaseStream.Position);
}

if (bin.BaseStream.Position == bin.BaseStream.Length)
{
return shaderFile;
}
}

//Console.WriteLine("Reading " + length);
if(length == 1)
{
Console.WriteLine("Skipping " + magic);
break;
bin.BaseStream.Position -= 24;
length = bin.ReadInt32();
bin.BaseStream.Position += 20;
length = length - 20;
}
shaderFile.decompressedBlocks.Add(bin.ReadBytes(length));

if(length == 1)
{
File.WriteAllBytes("out2.bin", targetStream.ToArray());
}
/*Console.WriteLine(magic);
while (magic != "DXBC" && magic != "MTLB")
{
magic = new string(bin.ReadChars(4));
Console.WriteLine(magic);
}
Console.WriteLine("Found " + magic + " at " + (bin.BaseStream.Position - 4));
*/

/*
bin.BaseStream.Position -= 4;
var GLSL3start = bin.BaseStream.Position;
Expand Down Expand Up @@ -234,7 +278,7 @@ public BLS LoadBLS(Stream stream)
}
bin.BaseStream.Position += header.variableStringsSize;

*/
// Padding up to 4 bytes
for (var p = 0; p < 4; p++)
{
Expand All @@ -246,12 +290,11 @@ public BLS LoadBLS(Stream stream)

if (bin.BaseStream.Position != shaderFile.ofsShaderBlocks[i + 1])
{
Console.WriteLine("!!! Didn't end up at next shader (" + shaderFile.ofsShaderBlocks[i + 1] + "), there might be unread data at " + bin.BaseStream.Position + "!");
//Console.WriteLine("!!! Didn't end up at next shader (" + shaderFile.ofsShaderBlocks[i + 1] + "), there might be unread data at " + bin.BaseStream.Position + "!");
}
}
}


return shaderFile;
}
}
Expand Down
11 changes: 11 additions & 0 deletions WoWFormatLib/FileReaders/WDTReader.cs
Expand Up @@ -11,6 +11,7 @@ public class WDTReader
{
public List<(byte, byte)> tiles = new List<(byte, byte)>();
public Dictionary<(byte, byte), MapFileDataIDs> tileFiles = new Dictionary<(byte, byte), MapFileDataIDs>();
public Dictionary<string, MapFileDataIDs> stringTileFiles = new Dictionary<string, MapFileDataIDs>();
public WDT wdtfile;

public void LoadWDT(string filename)
Expand All @@ -31,6 +32,11 @@ public void LoadWDT(uint filedataid)
{
ReadWDT(stream);
}

foreach(var entry in tileFiles)
{
stringTileFiles.Add(entry.Key.Item1 + "," + entry.Key.Item2, entry.Value);
}
}

private void ReadMAINChunk(BinaryReader bin)
Expand Down Expand Up @@ -88,6 +94,10 @@ private void ReadMAIDChunk(BinaryReader bin)
}
}
}
private MODF ReadMODFChunk(BinaryReader bin)
{
return bin.Read<MODF>();
}

private void ReadWDT(Stream wdt)
{
Expand Down Expand Up @@ -121,6 +131,7 @@ private void ReadWDT(Stream wdt)
ReadMAIDChunk(bin);
break;
case WDTChunks.MODF:
wdtfile.modf = ReadMODFChunk(bin);
break;
default:
throw new Exception(string.Format("Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunkName, position.ToString()));
Expand Down
3 changes: 1 addition & 2 deletions WoWFormatLib/Structs/BLS.struct.cs
Expand Up @@ -15,6 +15,7 @@ public struct BLS
public uint nCompressedChunks;
public uint ofsCompressedData;
public uint[] ofsShaderBlocks;
public List<byte[]> decompressedBlocks;
public ShaderBlock[] shaderBlocks;
}

Expand All @@ -33,8 +34,6 @@ public struct ShaderBlockHeader
{
public uint flags;
public uint flags2;
public uint unk0;
public uint unk1;
public uint length;
}

Expand Down
16 changes: 16 additions & 0 deletions WoWFormatLib/Structs/WDT.struct.cs
@@ -1,4 +1,5 @@
using System;
using WoWFormatLib.Utils;

namespace WoWFormatLib.Structs.WDT
{
Expand All @@ -16,9 +17,24 @@ public enum WDTChunks
public struct WDT
{
public MPHD mphd;
public MODF modf;
public MapFileDataIDs[] filedataids;
}

public struct MODF
{
public uint id;
public uint uuid;
public Vector3 position;
public Vector3 rotation;
public Vector3 upperExtents;
public Vector3 lowerExtents;
public short flags;
public short doodadSetID;
public short nameSet;
public short padding;
}

public struct MapFileDataIDs
{
public uint rootADT;
Expand Down
148 changes: 126 additions & 22 deletions WoWFormatTest/Program.cs
@@ -1,50 +1,154 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using WoWFormatLib.DBC;
using WoWFormatLib.FileReaders;
using WoWFormatLib.Utils;
using System.Security.Cryptography;
using WoWFormatLib;
using System.IO.Compression;
using System.Linq;

namespace WoWFormatLib
namespace WoWFormatTest
{
internal class Program
{
private static Dictionary<string, List<byte>> preShaderMD5Total = new Dictionary<string, List<byte>>();
private static Dictionary<string, List<byte>> postShaderMD5Total = new Dictionary<string, List<byte>>();

private static void Main(string[] args)
{
CASC.InitCasc(null, null, "wowt", CASCLib.LocaleFlags.enUS);

if (!File.Exists("listfile.txt"))
var reader = new BLSReader();
//reader.LoadBLS(File.OpenRead(@"D:\shaders\shaders_30093\unknown\\FILEDATA_1106926.bls"));
//File.WriteAllBytes("out.bin", reader.targetStream.ToArray());
foreach (var file in Directory.GetFiles(@"D:\shaders\shaders_30093\unknown", "*.bls", SearchOption.AllDirectories))
{
throw new Exception("Listfile not found!");
try
{
reader.LoadBLS(File.OpenRead(file));
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Error loading shader " + file + ": " + e.Message);
Console.ResetColor();
continue;
}
var cleanName = file;
for (var i = 0; i < reader.shaderFile.decompressedBlocks.Count; i++)
{
using (var md5 = MD5.Create())
{
var rawhash = md5.ComputeHash(reader.shaderFile.decompressedBlocks[i]);
if (!preShaderMD5Total.ContainsKey(cleanName))
{
preShaderMD5Total.Add(cleanName, new List<byte>());
}

preShaderMD5Total[cleanName].AddRange(rawhash);
}
}
}

foreach (var line in File.ReadAllLines("listfile.txt"))
var finalMD5Dict = new Dictionary<string, string>();
foreach(var shader in preShaderMD5Total)
{
if (line.EndsWith(".wdt", StringComparison.CurrentCultureIgnoreCase) && !line.Contains("_mpv") && !line.Contains("_fogs") && !line.Contains("_occ") && !line.Contains("_lgt"))
using (var md5 = MD5.Create())
{
if (!CASC.FileExists(line))
continue;

var reader = new WDTReader();
reader.LoadWDT(line);

if(reader.wdtfile.filedataids == null)
var finalHash = md5.ComputeHash(shader.Value.ToArray()).ToHexString();
if (finalMD5Dict.ContainsKey(finalHash))
{
Console.WriteLine(shader.Key + " has the same internal shaders as " + finalMD5Dict[finalHash]);
}
else
{
Console.WriteLine(line + " does not have MAID chunk");
continue;
finalMD5Dict.Add(finalHash, shader.Key);
}
}
}

foreach (var file in Directory.GetFiles(@"D:\shaders\shaders_30096\unknown", "*.bls", SearchOption.AllDirectories))
{
try
{
reader.LoadBLS(File.OpenRead(file));
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Error loading shader " + file + ": " + e.Message);
Console.ResetColor();
continue;
}

foreach(var filedataids in reader.wdtfile.filedataids)
var cleanName = file;
for (var i = 0; i < reader.shaderFile.decompressedBlocks.Count; i++)
{
using (var md5 = MD5.Create())
{
if (filedataids.rootADT != 0)
var rawhash = md5.ComputeHash(reader.shaderFile.decompressedBlocks[i]);
if (!postShaderMD5Total.ContainsKey(cleanName))
{
Console.WriteLine(line + " " + filedataids.rootADT);
postShaderMD5Total.Add(cleanName, new List<byte>());
}

postShaderMD5Total[cleanName].AddRange(rawhash);
}
}
}

if (File.Exists("matches.txt"))
{
File.Delete("matches.txt");
}

var matches = new List<string>();
Console.ForegroundColor = ConsoleColor.DarkGreen;
var preShaderCopy = finalMD5Dict.Values.ToList();
var postShaderCopy = postShaderMD5Total.Keys.ToList();
foreach (var shader in postShaderMD5Total)
{
using (var md5 = MD5.Create())
{
var finalHash = md5.ComputeHash(shader.Value.ToArray()).ToHexString();
if (finalMD5Dict.ContainsKey(finalHash))
{
matches.Add(Path.GetFileNameWithoutExtension(shader.Key).Replace("FILEDATA_", "") + ";" + Path.GetFileNameWithoutExtension(finalMD5Dict[finalHash]).Replace("FILEDATA_", ""));
preShaderCopy.Remove(finalMD5Dict[finalHash]);
postShaderCopy.Remove(shader.Key);
}
}
}

File.WriteAllLines("matches.txt", matches.ToArray());
File.WriteAllLines("leftovers-pre.txt", preShaderCopy.ToArray());
File.WriteAllLines("leftovers-post.txt", postShaderCopy.ToArray());

/*
var preShaderCount = new Dictionary<string, string>();
foreach (var shader in File.ReadAllLines("leftovers-pre.txt"))
{
reader.LoadBLS(File.OpenRead(shader));
preShaderCount.Add(shader, reader.shaderFile.nShaders + "-" + reader.shaderFile.nCompressedChunks + "-" + reader.shaderFile.decompressedBlocks[0].Length);
}
//{[D:\shaders\shaders_30093\unknown\FILEDATA_1139694.bls, 126-74-8473]
//{[D:\shaders\shaders_30096\unknown\FILEDATA_2976993.bls, 126-74-6320]}
//{[D:\shaders\shaders_30093\unknown\FILEDATA_1316520.bls, 1440-595-8441]}
//{[D:\shaders\shaders_30096\unknown\FILEDATA_2977492.bls, 1440-596-8461]}
//{[D:\shaders\shaders_30093\unknown\FILEDATA_1316520.bls, 1440-595-8441]}
//{[D:\shaders\shaders_30096\unknown\FILEDATA_2977492.bls, 1440-596-8461]
//{[D:\shaders\shaders_30096\unknown\FILEDATA_2976993.bls, 126-74-6320]
var postShaderCount = new Dictionary<string, string>();
foreach (var shader in File.ReadAllLines("leftovers-post.txt"))
{
reader.LoadBLS(File.OpenRead(shader));
postShaderCount.Add(shader, reader.shaderFile.nShaders + "-" + reader.shaderFile.nCompressedChunks + "-" + reader.shaderFile.decompressedBlocks[0].Length);
}
*/
//{[D:\shaders\shaders_30093\unknown\FILEDATA_1139630.bls, 640-287-8857]
//{[D:\shaders\shaders_30096\unknown\FILEDATA_2977414.bls, 640-287-1]

}
}
}

0 comments on commit e7ce54f

Please sign in to comment.