Created
August 24, 2011 22:07
-
-
Save OrigamiTech/1169399 to your computer and use it in GitHub Desktop.
Unpacker for the GLB files found in DemonStar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
namespace LibDemonstar | |
{ | |
public static class GLB | |
{ | |
private const string MAGIC = "GLB2.0\0\0"; | |
private const string NAME_SPACE_START = "START"; | |
private const string NAME_SPACE_END = "END"; | |
private const string NAME_SPACE_CHAR = ":"; | |
public static void Unpack(string file) | |
{ | |
using(FileStream fsIn = new FileStream(file, FileMode.Open, FileAccess.Read)) | |
{ | |
string magic = Common.ReadAsciiString(fsIn, 8); | |
if(magic != MAGIC) | |
throw new Exception("Bad magic constant."); | |
Console.WriteLine(magic); | |
uint descriptor_count = Common.ReadUint(fsIn); | |
Console.WriteLine(descriptor_count.ToString("X8")); | |
string output_dir = file + ".unpack"; | |
if(!Directory.Exists(output_dir)) | |
Directory.CreateDirectory(output_dir); | |
descriptor[] descriptors = new descriptor[descriptor_count]; | |
for(uint i = 0; i < descriptor_count; i++) | |
{ | |
descriptors[i] = new descriptor(); | |
descriptors[i].zeroed = Common.ReadUint(fsIn); | |
descriptors[i].offset = Common.ReadUint(fsIn); | |
descriptors[i].length = Common.ReadUint(fsIn); | |
descriptors[i].name = Common.ReadAsciiString(fsIn, 16); | |
} | |
string full_name_space = ""; | |
int file_array_index = 0; | |
for(uint i = 0; i < descriptor_count; i++) | |
{ | |
Console.WriteLine(descriptors[i].name + "|" + descriptors[i].zeroed.ToString("X8") + "|" + descriptors[i].offset.ToString("X8") + "|" + descriptors[i].length.ToString("X8")); | |
// if it's a namespace descriptor | |
if(descriptors[i].length == 0 && Common.StripNullChars(descriptors[i].name).EndsWith(NAME_SPACE_CHAR)) | |
{ | |
string name_space = ""; | |
if(descriptors[i].name.StartsWith(NAME_SPACE_END)) | |
{ | |
name_space = descriptors[i].name.Substring(NAME_SPACE_END.Length, descriptors[i].name.IndexOf(NAME_SPACE_CHAR) - NAME_SPACE_END.Length); | |
if(full_name_space.EndsWith(name_space + "/")) | |
full_name_space = full_name_space.Substring(0, full_name_space.Length - (name_space + "/").Length); | |
} | |
else | |
{ | |
if(descriptors[i].name.StartsWith(NAME_SPACE_START)) | |
{ | |
name_space = descriptors[i].name.Substring(NAME_SPACE_START.Length, descriptors[i].name.IndexOf(NAME_SPACE_CHAR) - NAME_SPACE_START.Length); | |
} | |
else | |
{ | |
name_space = descriptors[i].name.Substring(0, descriptors[i].name.IndexOf(NAME_SPACE_CHAR)); | |
} | |
full_name_space += name_space + "/"; | |
Console.WriteLine("NAMESPACE " + name_space); | |
} | |
} | |
// if it's a file descriptor | |
else | |
{ | |
string output_dir_with_name_space = Path.Combine(output_dir, full_name_space); | |
if(!Directory.Exists(output_dir_with_name_space)) | |
Directory.CreateDirectory(output_dir_with_name_space); | |
string output_file = Path.Combine(output_dir_with_name_space, Common.StripNullChars(descriptors[i].name)); | |
if(i > 0) | |
{ | |
if(descriptors[i].name == descriptors[i - 1].name) | |
{ | |
file_array_index++; | |
output_file += "[" + file_array_index.ToString() + "]"; | |
} | |
else | |
{ | |
file_array_index = 0; | |
} | |
} | |
if(i < descriptor_count - 1 && file_array_index ==0) | |
{ | |
if(descriptors[i].name == descriptors[i + 1].name) | |
{ | |
output_file += "[" + file_array_index.ToString() + "]"; | |
} | |
} | |
using(FileStream fsOut = new FileStream(output_file, FileMode.Create, FileAccess.Write)) | |
{ | |
if(descriptors[i].length != 0) | |
{ | |
fsIn.Position = descriptors[i].offset; | |
int BUFFER_LEN = 1024; | |
byte[] buffer = new byte[BUFFER_LEN]; | |
int count = 0; | |
uint total = 0; | |
while(total < descriptors[i].length) | |
{ | |
count = fsIn.Read(buffer, 0, descriptors[i].length - total < BUFFER_LEN ? (int)(descriptors[i].length - total) : BUFFER_LEN); | |
fsOut.Write(buffer, 0, count); | |
total += (uint)count; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
private struct descriptor | |
{ | |
public uint zeroed; | |
public uint offset; | |
public uint length; | |
public string name; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment