Skip to content

Commit

Permalink
Improved reach variant converter
Browse files Browse the repository at this point in the history
  • Loading branch information
craftycodie committed Aug 9, 2024
1 parent 66885ca commit 48b658f
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 25 deletions.
33 changes: 32 additions & 1 deletion WarthogInc/BlfFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public void AddChunk(IBLFChunk chunk)
chunks.Add(chunk.GetName(), chunk);
}

public void RemoveChunk<T>() where T : IBLFChunk, new()
{
IBLFChunk chunk = new T();
chunks.Remove(chunk.GetName());
}

public T GetChunk<T>() where T : IBLFChunk, new() {
IBLFChunk chunk = new T();
return (T)chunks[chunk.GetName()];
Expand Down Expand Up @@ -128,7 +134,7 @@ public static byte[] ComputeHash(string path)
return ComputeHash(path, halo3salt);
}

private static byte[] fake_hash = Convert.FromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
private static readonly byte[] fake_hash = Convert.FromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

public static byte[] ComputeHash(string path, byte[] salt)
{
Expand Down Expand Up @@ -167,5 +173,30 @@ public static byte[] ComputeHash(string path, byte[] salt)
return fake_hash;
}
}

public static byte[] ComputeHash(byte[] data)
{
return ComputeHash(data, halo3salt);
}

public static byte[] ComputeHash(byte[] data, byte[] salt)
{

var memoryStream = new MemoryStream();
var blfFileOut = new BitStream<StreamByteStream>(new StreamByteStream(memoryStream));
foreach (byte saltByte in salt)
{
blfFileOut.Write(saltByte, 8);
}
foreach (byte blfByte in data)
{
blfFileOut.Write(blfByte, 8);
}
memoryStream.Flush();

byte[] saltedBlf = memoryStream.ToArray();
memoryStream.Close();
return new SHA1Managed().ComputeHash(saltedBlf);
}
}
}
4 changes: 2 additions & 2 deletions WarthogInc/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ class Program
{
static void Main(string[] args)
{
if (args.Length == 3 & args[0] == "reach_variant")
if (args.Length == 3 & args[0] == "reach_variants")
{
ReachGvarConverter.ConvertMpvrFolder(args[1], args[2]);
ReachVariantConverter.ConvertVariantFolder(args[1], args[2]);
}
else if (args.Length == 4)
{
Expand Down
182 changes: 160 additions & 22 deletions WarthogInc/ReachGvarConverter.cs → WarthogInc/ReachVariantConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SunriseBlfTool
{
public class ReachGvarConverter
public class ReachVariantConverter
{
class NoConversionNecessaryException : Exception
{
Expand Down Expand Up @@ -73,6 +74,45 @@ public void WriteChunk(ref BitStream<StreamByteStream> hoppersStream)
}
}

class FakeChdr : IBLFChunk
{
public FakeChdr()
{

}


public ushort GetAuthentication()
{
return 1;
}

public uint GetLength()
{
return 0x2C0;
}

public string GetName()
{
return "chdr";
}

public ushort GetVersion()
{
return 10;
}

public void ReadChunk(ref BitStream<StreamByteStream> hoppersStream)
{
//
}

public void WriteChunk(ref BitStream<StreamByteStream> hoppersStream)
{
//
}
}

class MpvrChunk : IBLFChunk
{
public byte[] gametypeData;
Expand Down Expand Up @@ -116,18 +156,74 @@ public void WriteChunk(ref BitStream<StreamByteStream> hoppersStream)
}
}

public static BlfFile CreateGvarFile(byte[] gvarData)
class MvarChunk : IBLFChunk
{
BlfFile blfFile = new BlfFile();
blfFile.AddChunk(new Author()
{
buildName = "blftool mcc mpvr",
buildNumber = 12065,
shellVersion = "",
unknown40 = "",
});
blfFile.AddChunk(new GvarChunk(gvarData));
return blfFile;
public byte[] mapHash;
public byte[] mapData;

public MvarChunk()
{

}

public MvarChunk(byte[] mapData)
{
this.mapData = mapData;
}


public ushort GetAuthentication()
{
return 1;
}

public uint GetLength()
{
var ms = new BitStream<StreamByteStream>(new StreamByteStream(new MemoryStream()));
WriteChunk(ref ms);
return (uint)ms.NextByteIndex;
}

public string GetName()
{
return "mvar";
}

public ushort GetVersion()
{
return 31;
}

public void ReadChunk(ref BitStream<StreamByteStream> hoppersStream)
{
mapHash = new byte[20];
for (uint i = 0; i < 20; i++)
{
mapHash[i] = hoppersStream.Read<byte>(8);
}

uint length = hoppersStream.Read<uint>(32);
mapData = new byte[length];
for (uint i = 0; i < length; i++)
{
mapData[i] = hoppersStream.Read<byte>(8);
}
}

public void WriteChunk(ref BitStream<StreamByteStream> hoppersStream)
{
foreach (byte b in mapHash)
{
hoppersStream.Write(b, 8);
}

hoppersStream.Write(mapData.Length, 32);

foreach (byte _byte in mapData)
{
hoppersStream.Write(_byte, 8);
}
}
}

class ConversionChunkNameMap : AbstractBlfChunkNameMap
Expand All @@ -144,6 +240,8 @@ private void RegisterChunks()
RegisterChunk<Author>();
RegisterChunk<GvarChunk>();
RegisterChunk<MpvrChunk>();
RegisterChunk<MvarChunk>();
RegisterChunk<FakeChdr>();
}

public override string GetVersion()
Expand All @@ -154,14 +252,54 @@ public override string GetVersion()

static AbstractBlfChunkNameMap chunkNameMap = new ConversionChunkNameMap();

public static void ConvertMpvrToGvar(string inputPath, string outputPath)
public static void ConvertVariant(string inputPath, string outputPath)
{
try
{
BlfFile mpvrFile = new BlfFile();
mpvrFile.ReadFile(inputPath, chunkNameMap);
BlfFile converted = CreateGvarFile(mpvrFile.GetChunk<MpvrChunk>().gametypeData);
converted.WriteFile(outputPath);
BlfFile blfFile = new BlfFile();
blfFile.ReadFile(inputPath, chunkNameMap);

BlfFile convertedBlf = new BlfFile();
convertedBlf.AddChunk(new Author()
{
buildName = "blftool variant",
buildNumber = 12065,
shellVersion = "",
unknown40 = "",
});

if (blfFile.HasChunk<MpvrChunk>())
{
convertedBlf.AddChunk(new GvarChunk(blfFile.GetChunk<MpvrChunk>().gametypeData));
}

if (blfFile.HasChunk<MvarChunk>())
{
convertedBlf.AddChunk(blfFile.GetChunk<MvarChunk>());
}

string fileName = Path.GetFileName(outputPath);
if (!fileName.Contains("."))
{
IBLFChunk convertedChunk = null;
// if there's no extension, make one.
if (convertedBlf.HasChunk<GvarChunk>())
{
convertedChunk = convertedBlf.GetChunk<GvarChunk>();
}
if (convertedBlf.HasChunk<MvarChunk>())
{
convertedChunk = convertedBlf.GetChunk<MvarChunk>();
}

if (convertedChunk != null)
{
outputPath = outputPath + $"_{convertedChunk.GetVersion().ToString("D3")}.bin";
}
}

convertedBlf.WriteFile(outputPath);

}
catch (NoConversionNecessaryException)
{
Expand All @@ -170,25 +308,25 @@ public static void ConvertMpvrToGvar(string inputPath, string outputPath)
}
}

public static void ConvertMpvrFolder(string inputPath, string outputPath)
public static void ConvertVariantFolder(string inputPath, string outputPath)
{
int succeededCount = 0;
foreach (string filePath in Directory.EnumerateFiles(inputPath))
{
string fileName = Path.GetFileName(filePath);


if (!File.Exists(filePath))
{
Console.WriteLine("Warning: Tried to convert a non-existent file somehow - " + fileName);
continue;
}
if (!filePath.EndsWith("_054.bin"))
if (fileName.EndsWith(".bak"))
{
Console.WriteLine("Skipping non-variant file - " + fileName);
continue;
Console.WriteLine("Skipping .bak file " + fileName);
}

ConvertMpvrToGvar(filePath, outputPath + Path.DirectorySeparatorChar + fileName);
ConvertVariant(filePath, outputPath + Path.DirectorySeparatorChar + fileName.Replace(".mvar", ".bin"));
Console.WriteLine("Successfully converted file: " + fileName);
succeededCount++;
}
Expand Down

0 comments on commit 48b658f

Please sign in to comment.