Skip to content

Instantly share code, notes, and snippets.

@reitowo
Created December 15, 2023 18:38
Show Gist options
  • Save reitowo/17f1e10c392c4aa0104a6cc1f8281858 to your computer and use it in GitHub Desktop.
Save reitowo/17f1e10c392c4aa0104a6cc1f8281858 to your computer and use it in GitHub Desktop.
Parse Warframe Languages.bin (v35)
Dictionary<string, List<string>> ParseLanguageBin(string fileName) {
var subtitleDict = new Dictionary<string, List<string>>();
using var file = File.OpenRead(fileName);
using var reader = new BinaryReader(file);
var hash = reader.ReadBytes(16);
var version = reader.ReadInt32();
var unkA = reader.ReadInt32();
var unkB = reader.ReadInt32();
var langCodes = new List<string>();
var langCount = reader.ReadInt32();
for (var i = 0; i < langCount; i++) {
var lang = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadInt32()));
langCodes.Add(lang);
}
while (reader.BaseStream.Position != reader.BaseStream.Length) {
var contentSize = reader.ReadInt32();
var zstdDict = reader.ReadBytes(contentSize);
var unk0 = reader.ReadInt32();
using var options = new DecompressionOptions(zstdDict, new Dictionary<ZSTD_dParameter, int>() {
{ (ZSTD_dParameter)1000, 1 }
});
using var decompressor = new Decompressor(options);
for (var k = 0; k < unk0; ++k) {
var s1Len = reader.ReadInt32();
var s1 = Encoding.UTF8.GetString(reader.ReadBytes(s1Len));
// Console.WriteLine($"{reader.BaseStream.Position} {reader.BaseStream.Length} {s1}");
var s2Len = reader.ReadInt32();
var s2Bytes = reader.ReadBytes(s2Len);
var unk1 = reader.ReadInt32(); // array 1 len
for (var i = 0; i < unk1; ++i) {
var s3Len = reader.ReadInt32();
var s3Bytes = reader.ReadBytes(s3Len); // not null terminate
var s3 = Encoding.UTF8.GetString(s3Bytes);
var s2Skip = reader.ReadInt32();
var s2Take = reader.ReadUInt16();
var s2Flag = reader.ReadUInt16();
var s2Slice = s2Bytes.AsSpan(s2Skip, s2Take).ToArray();
var s2 = Encoding.UTF8.GetString(s2Slice);
if ((s2Flag & 0x200) != 0) {
using var br = new BinaryReader(new MemoryStream(s2Slice));
var dstLen = br.Read7BitEncodedInt();
var srcBuf = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position));
var dst = new byte[dstLen];
decompressor.Unwrap(srcBuf, dst, false);
s2 = Encoding.UTF8.GetString(dst);
}
// Console.WriteLine($"{s1} {s3} {s2Flag:X4} {s2Take} {s2Skip} {s2Bytes.Length} {zstdDict.Length} {s2}");
subtitleDict.TryAdd(s3, []);
subtitleDict[s3].Add(s2);
}
}
}
return subtitleDict;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment