Skip to content

Instantly share code, notes, and snippets.

@OrigamiTech
Created August 24, 2011 22:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save OrigamiTech/1169399 to your computer and use it in GitHub Desktop.
Save OrigamiTech/1169399 to your computer and use it in GitHub Desktop.
Unpacker for the GLB files found in DemonStar
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