700 lines
28 KiB
C#
700 lines
28 KiB
C#
using CXML;
|
|
using General;
|
|
using Ionic.Zlib;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Xml;
|
|
|
|
namespace CXMLDecompiler
|
|
{
|
|
class CXMLBuilder
|
|
{
|
|
String MainDir = "";
|
|
String XMLFilename = "";
|
|
String MagicNumber = "";
|
|
|
|
Endainness FileEndainness;
|
|
bool ps3;
|
|
Tools tools;
|
|
|
|
Int32 Version;
|
|
FileStream InfoFile;
|
|
|
|
MemoryStream TreeTable;
|
|
MemoryStream IDTable;
|
|
MemoryStream HashIDTable;
|
|
MemoryStream StringTable;
|
|
MemoryStream WStringTable;
|
|
MemoryStream HashTable;
|
|
MemoryStream IntArrayTable;
|
|
MemoryStream FloatArrayTable;
|
|
MemoryStream FileTable;
|
|
|
|
Boolean IsInitalized = false;
|
|
public Boolean HashStrings = false;
|
|
|
|
|
|
String SilicaTypingInformation = "";
|
|
public void Init(string XMLFile, string CxmlFile)
|
|
{
|
|
GetSilicaTypingInformation(XMLFile);
|
|
MagicNumber = GetTypingInformation("MAGIC");
|
|
Version = Int32.Parse(GetTypingInformation("VERSION").Replace("0x", ""), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
|
|
|
|
// Determine filetype.
|
|
FileEndainness = (Endainness)Enum.Parse(typeof(Endainness), GetTypingInformation("ENDAINESS"));
|
|
ps3 = GetTypingInformation("PS3") == "true";
|
|
tools = new Tools((FileEndainness == Endainness.BIG_ENDAIN));
|
|
|
|
InfoFile = File.Open(CxmlFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
|
|
InfoFile.SetLength(0);
|
|
|
|
TreeTable = new MemoryStream();
|
|
IDTable = new MemoryStream();
|
|
StringTable = new MemoryStream();
|
|
IntArrayTable = new MemoryStream();
|
|
FloatArrayTable = new MemoryStream();
|
|
FileTable = new MemoryStream();
|
|
|
|
WStringTable = new MemoryStream();
|
|
HashIDTable = new MemoryStream();
|
|
HashTable = new MemoryStream();
|
|
|
|
|
|
XMLFilename = XMLFile;
|
|
MainDir = Path.GetDirectoryName(XMLFilename);
|
|
|
|
IsInitalized = true;
|
|
|
|
return;
|
|
}
|
|
public void GetSilicaTypingInformation(string XmlFileName)
|
|
{
|
|
if (XmlFileName.Contains("<!--SilicaTypingInformation{{[[")){
|
|
Console.WriteLine("XML Does not contain SilicaTypingInformation\nABORTING!");
|
|
Environment.Exit(0);
|
|
}
|
|
|
|
string SearchFor = "<!--SilicaTypingInformation{{[[";
|
|
string SearchFor2 = "]]}}SilicaTypingInformation-->";
|
|
string xmlData = File.ReadAllText(XmlFileName);
|
|
int ind1 = xmlData.IndexOf(SearchFor);
|
|
xmlData = xmlData.Substring(ind1 + SearchFor.Length);
|
|
int ind2 = xmlData.IndexOf(SearchFor2);
|
|
xmlData = xmlData.Substring(0, ind2);
|
|
SilicaTypingInformation = xmlData;
|
|
}
|
|
public string GetTypingInformation(string Key)
|
|
{
|
|
string[] typeinf = SilicaTypingInformation.Split(',');
|
|
foreach(string type in typeinf)
|
|
{
|
|
string[] keyValuePair = type.Split('=');
|
|
if (keyValuePair[0] == Key)
|
|
return keyValuePair[1];
|
|
}
|
|
return "0";
|
|
}
|
|
public class StringTableEntry
|
|
{
|
|
public int offset;
|
|
public string name;
|
|
}
|
|
public class HashTableEntry
|
|
{
|
|
public int offset;
|
|
public int value;
|
|
}
|
|
public class IDTableEntry
|
|
{
|
|
public int offset;
|
|
public string value;
|
|
public int loopbackOffset;
|
|
}
|
|
public class HashIDTableEntry
|
|
{
|
|
public int offset;
|
|
public int value;
|
|
public int loopbackOffset;
|
|
}
|
|
|
|
public class TreeTableEntry
|
|
{
|
|
public int offset;
|
|
public XmlNode node;
|
|
}
|
|
List<TreeTableEntry> TreeTableEntries = new List<TreeTableEntry>();
|
|
List<StringTableEntry> StringTableEntries = new List<StringTableEntry>();
|
|
List<StringTableEntry> WStringTableEntries = new List<StringTableEntry>();
|
|
List<HashTableEntry> HashTableEntries = new List<HashTableEntry>();
|
|
List<Int32> IntArrayTableEntries = new List<Int32>();
|
|
List<Single> FloatArrayTableEntries = new List<Single>();
|
|
List<StringTableEntry> FileTableEntries = new List<StringTableEntry>();
|
|
List<IDTableEntry> IDTableEntries = new List<IDTableEntry>();
|
|
List<HashIDTableEntry> HashIDTableEntries = new List<HashIDTableEntry>();
|
|
public int AddGetTreeTable(XmlNode node)
|
|
{
|
|
if (!(node.NodeType == XmlNodeType.Element || node.NodeType == XmlNodeType.EndElement || node.NodeType == XmlNodeType.Attribute))
|
|
return -1;
|
|
foreach (TreeTableEntry entry in TreeTableEntries)
|
|
if (entry.node == node)
|
|
return entry.offset;
|
|
|
|
TreeTableEntry ent = new TreeTableEntry();
|
|
ent.node = node;
|
|
ent.offset = Convert.ToInt32(TreeTable.Position);
|
|
TreeTableEntries.Add(ent);
|
|
WriteElement(node);
|
|
|
|
return ent.offset;
|
|
}
|
|
|
|
public int AddGetHashIdTable(int value, int loopbackPtr)
|
|
{
|
|
foreach (HashIDTableEntry entry in HashIDTableEntries)
|
|
{
|
|
|
|
if (entry.loopbackOffset == loopbackPtr && loopbackPtr != -1)
|
|
{
|
|
return entry.offset;
|
|
}
|
|
else if (entry.value == value)
|
|
{
|
|
if (loopbackPtr == -1)
|
|
return entry.offset;
|
|
entry.loopbackOffset = loopbackPtr;
|
|
long position1 = HashIDTable.Position;
|
|
HashIDTable.Seek(entry.offset, SeekOrigin.Begin);
|
|
tools.WriteInt32(HashIDTable, loopbackPtr);
|
|
HashIDTable.Seek(position1, SeekOrigin.Begin);
|
|
return entry.offset;
|
|
}
|
|
}
|
|
HashIDTableEntry ent = new HashIDTableEntry();
|
|
ent.value = value;
|
|
ent.loopbackOffset = loopbackPtr;
|
|
ent.offset = Convert.ToInt32(HashIDTable.Position);
|
|
HashIDTableEntries.Add(ent);
|
|
|
|
tools.WriteInt32(HashIDTable, loopbackPtr);
|
|
tools.WriteInt32(HashIDTable, value);
|
|
|
|
return ent.offset;
|
|
}
|
|
public int AddGetIdTable(string value, int loopbackPtr)
|
|
{
|
|
foreach (IDTableEntry entry in IDTableEntries)
|
|
{
|
|
if (entry.loopbackOffset == loopbackPtr && loopbackPtr != -1)
|
|
{
|
|
return entry.offset;
|
|
}
|
|
else if (entry.value == value)
|
|
{
|
|
if (loopbackPtr == -1)
|
|
return entry.offset;
|
|
entry.loopbackOffset = loopbackPtr;
|
|
long position1 = IDTable.Position;
|
|
IDTable.Seek(entry.offset, SeekOrigin.Begin);
|
|
tools.WriteInt32(IDTable, loopbackPtr);
|
|
IDTable.Seek(position1, SeekOrigin.Begin);
|
|
return entry.offset;
|
|
}
|
|
}
|
|
IDTableEntry ent = new IDTableEntry();
|
|
ent.value = value;
|
|
ent.loopbackOffset = loopbackPtr;
|
|
ent.offset = Convert.ToInt32(IDTable.Position);
|
|
IDTableEntries.Add(ent);
|
|
|
|
tools.WriteInt32(IDTable, loopbackPtr);
|
|
Tools.WriteStringToStream(IDTable, value);
|
|
IDTable.WriteByte(0x00);
|
|
|
|
|
|
if (loopbackPtr != -1 && !ps3)
|
|
{
|
|
Align(IDTable, 4);
|
|
}
|
|
|
|
return ent.offset;
|
|
}
|
|
public int AddGetFileTable(byte[] value, string filename)
|
|
{
|
|
foreach (StringTableEntry entry in FileTableEntries)
|
|
if (entry.name == filename)
|
|
return entry.offset;
|
|
|
|
StringTableEntry ent = new StringTableEntry();
|
|
ent.name = filename;
|
|
ent.offset = Convert.ToInt32(FileTable.Position);
|
|
FileTableEntries.Add(ent);
|
|
|
|
FileTable.Write(value, 0x00, value.Length);
|
|
Align(FileTable, 0x10);
|
|
|
|
return ent.offset;
|
|
}
|
|
public int AddGetFloatArrayTable(float[] value)
|
|
{
|
|
float[] Test = new float[value.Length];
|
|
float[] TestAgainst = FloatArrayTableEntries.ToArray();
|
|
for (int i = 0; i < TestAgainst.Length; i += 1)
|
|
{
|
|
if (i + value.Length > TestAgainst.Length)
|
|
break;
|
|
Array.ConstrainedCopy(TestAgainst, i, Test, 0, value.Length);
|
|
if(value.SequenceEqual(Test))
|
|
return i;
|
|
}
|
|
int offset = Convert.ToInt32(FloatArrayTable.Position) / 4;
|
|
|
|
foreach (float i in value)
|
|
{
|
|
tools.WriteSingle(FloatArrayTable, i);
|
|
FloatArrayTableEntries.Add(i);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
public int AddGetIntArrayTable(int[] value)
|
|
{
|
|
int[] Test = new int[value.Length];
|
|
int[] TestAgainst = IntArrayTableEntries.ToArray();
|
|
for (int i = 0; i < TestAgainst.Length; i += 1)
|
|
{
|
|
if (i + value.Length > TestAgainst.Length)
|
|
break;
|
|
Array.ConstrainedCopy(TestAgainst, i, Test, 0, value.Length);
|
|
if (value.SequenceEqual(Test))
|
|
return i;
|
|
}
|
|
int offset = Convert.ToInt32(IntArrayTable.Position) / 4;
|
|
|
|
foreach (int i in value)
|
|
{
|
|
tools.WriteInt32(IntArrayTable, i);
|
|
IntArrayTableEntries.Add(i);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
public int AddGetHashTable(int value)
|
|
{
|
|
foreach (HashTableEntry entry in HashTableEntries)
|
|
if (entry.value == value)
|
|
return entry.offset/4;
|
|
|
|
HashTableEntry ent = new HashTableEntry();
|
|
ent.value = value;
|
|
ent.offset = Convert.ToInt32(HashTable.Position);
|
|
HashTableEntries.Add(ent);
|
|
|
|
tools.WriteInt32(HashTable, value);
|
|
|
|
return ent.offset/4;
|
|
}
|
|
public int AddGetStringTable(string elementName)
|
|
{
|
|
foreach(StringTableEntry entry in StringTableEntries)
|
|
if (entry.name == elementName)
|
|
return entry.offset;
|
|
|
|
StringTableEntry ent = new StringTableEntry();
|
|
ent.name = elementName;
|
|
ent.offset = Convert.ToInt32(StringTable.Position);
|
|
StringTableEntries.Add(ent);
|
|
|
|
Tools.WriteStringToStream(StringTable, elementName);
|
|
StringTable.WriteByte(0x00);
|
|
|
|
return ent.offset;
|
|
}
|
|
public int AddGetWstringTable(string elementName)
|
|
{
|
|
foreach (StringTableEntry entry in WStringTableEntries)
|
|
if (entry.name == elementName)
|
|
return entry.offset;
|
|
|
|
StringTableEntry ent = new StringTableEntry();
|
|
ent.name = elementName;
|
|
ent.offset = Convert.ToInt32(WStringTable.Position)/2;
|
|
WStringTableEntries.Add(ent);
|
|
|
|
Tools.WriteUtf16StringToStream(WStringTable, elementName);
|
|
WStringTable.WriteByte(0x00);
|
|
WStringTable.WriteByte(0x00);
|
|
|
|
return ent.offset;
|
|
}
|
|
public int ConvertAttributeTypeToInt(AttributeType type)
|
|
{
|
|
if (!ps3)
|
|
return (int) type;
|
|
else
|
|
return (int) (AttributeTypePs3)Enum.Parse(typeof(AttributeTypePs3), type.ToString());
|
|
}
|
|
public AttributeType DetermineType(string ElementName, string AttributeName)
|
|
{
|
|
return (AttributeType)Enum.Parse(typeof(AttributeType), GetTypingInformation(ElementName + ":" + AttributeName));
|
|
}
|
|
public void WriteAttribute(XmlAttribute attribute, MemoryStream WorkRam, string ElementName)
|
|
{
|
|
int AttributePtr = AddGetStringTable(attribute.Name);
|
|
AttributeType Type = DetermineType(ElementName, attribute.Name);
|
|
tools.WriteInt32(WorkRam, AttributePtr);
|
|
tools.WriteInt32(WorkRam, ConvertAttributeTypeToInt(Type));
|
|
Console.WriteLine("AttributeType: " + Type.ToString());
|
|
switch (Type)
|
|
{
|
|
case AttributeType.TYPE_NONE:
|
|
Console.WriteLine("UNSUPPORTED TYPE @ " + TreeTable.Position);
|
|
Console.ReadKey();
|
|
break;
|
|
case AttributeType.TYPE_INT:
|
|
int intWrite = Int32.Parse(attribute.Value, CultureInfo.InvariantCulture);
|
|
tools.WriteInt32(WorkRam, intWrite);
|
|
tools.WriteInt32(WorkRam, 0x00);
|
|
Console.WriteLine("Int - Value: " + intWrite.ToString());
|
|
break;
|
|
case AttributeType.TYPE_FLOAT:
|
|
float FloatValue = Single.Parse(attribute.Value.Substring(0, attribute.Value.Length - 1), CultureInfo.InvariantCulture);
|
|
tools.WriteSingle(WorkRam, FloatValue);
|
|
tools.WriteInt32(WorkRam, 0x00);
|
|
Console.WriteLine("Float - Value: " + FloatValue.ToString());
|
|
break;
|
|
case AttributeType.TYPE_STRING:
|
|
int StringOffset = AddGetStringTable(attribute.Value);
|
|
int StringLen = Encoding.UTF8.GetBytes(attribute.Value).Length;
|
|
tools.WriteInt32(WorkRam, StringOffset);
|
|
tools.WriteInt32(WorkRam, StringLen);
|
|
Console.WriteLine("String: " + attribute.Value);
|
|
break;
|
|
case AttributeType.TYPE_WSTRING:
|
|
int WStringOffset = AddGetWstringTable(attribute.Value);
|
|
int WStringLength = Encoding.Unicode.GetBytes(attribute.Value).Length;
|
|
tools.WriteInt32(WorkRam, WStringOffset);
|
|
tools.WriteInt32(WorkRam, WStringLength);
|
|
Console.WriteLine("WString: " + attribute.Value);
|
|
break;
|
|
case AttributeType.TYPE_HASH:
|
|
int hashId = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
|
|
if (HashStrings)
|
|
hashId = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
|
|
int HashTableOffset = AddGetHashTable(hashId);
|
|
int HashTableSize = 4;
|
|
tools.WriteInt32(WorkRam, HashTableOffset);
|
|
tools.WriteInt32(WorkRam, HashTableSize);
|
|
Console.WriteLine("Hash ID Offset:" + HashTableOffset.ToString() + " size: " + HashTableSize);
|
|
break;
|
|
case AttributeType.TYPE_INTEGER_ARRAY:
|
|
string[] arr = attribute.Value.Replace("[", "").Replace("]", "").Replace(" ", "").Split(',');
|
|
int[] intArr = new int[arr.Length];
|
|
for (int i = 0; i < intArr.Length; i++)
|
|
intArr[i] = Int32.Parse(arr[i], CultureInfo.InvariantCulture);
|
|
|
|
int IntArrayOffset = AddGetIntArrayTable(intArr);
|
|
int IntArraySize = intArr.Length;
|
|
tools.WriteInt32(WorkRam, IntArrayOffset);
|
|
tools.WriteInt32(WorkRam, IntArraySize);
|
|
|
|
Console.WriteLine("Int Array: " + attribute.Value);
|
|
break;
|
|
case AttributeType.TYPE_FLOAT_ARRAY:
|
|
arr = attribute.Value.Replace("[", "").Replace("]", "").Replace(" ", "").Replace("f", "").Split(',');
|
|
float[] floatArr = new float[arr.Length];
|
|
for (int i = 0; i < floatArr.Length; i++)
|
|
floatArr[i] = Single.Parse(arr[i], CultureInfo.InvariantCulture);
|
|
|
|
int FloatArrayOffset = AddGetFloatArrayTable(floatArr);
|
|
int FloatArraySize = floatArr.Length;
|
|
tools.WriteInt32(WorkRam, FloatArrayOffset);
|
|
tools.WriteInt32(WorkRam, FloatArraySize);
|
|
|
|
Console.WriteLine("Float Array: " + attribute.Value);
|
|
break;
|
|
case AttributeType.TYPE_FILE:
|
|
string fPath = Path.Combine(MainDir, attribute.Value);
|
|
byte[] data = File.ReadAllBytes(fPath);
|
|
int FilePtr = AddGetFileTable(data, Path.Combine(Environment.CurrentDirectory, fPath));
|
|
int FileSz = data.Length;
|
|
tools.WriteInt32(WorkRam, FilePtr);
|
|
tools.WriteInt32(WorkRam, FileSz);
|
|
Console.WriteLine("Reading File: " + fPath);
|
|
break;
|
|
case AttributeType.TYPE_ID_REF:
|
|
int IdTableOffset = AddGetIdTable(attribute.Value, Convert.ToInt32(TreeTable.Position));
|
|
tools.WriteInt32(WorkRam, IdTableOffset);
|
|
tools.WriteInt32(WorkRam, 0x00);
|
|
Console.WriteLine("String Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")");
|
|
Console.WriteLine("Loopback ID String: " + IdTableOffset + " sz: 0");
|
|
break;
|
|
case AttributeType.TYPE_ID:
|
|
IdTableOffset = AddGetIdTable(attribute.Value, -1);
|
|
tools.WriteInt32(WorkRam, IdTableOffset);
|
|
tools.WriteInt32(WorkRam, 0x00);
|
|
Console.WriteLine("ID String: " + IdTableOffset + " sz: 0");
|
|
break;
|
|
case AttributeType.TYPE_ID_HASH_REF:
|
|
int hash = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
if (HashStrings)
|
|
hash = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
int IntIdTableOffset = AddGetHashIdTable(hash, Convert.ToInt32(TreeTable.Position));
|
|
tools.WriteInt32(WorkRam, IntIdTableOffset);
|
|
tools.WriteInt32(WorkRam, 0x00);
|
|
Console.WriteLine("Int Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")");
|
|
Console.WriteLine("Loopback ID Int: " + IntIdTableOffset + " sz: 0");
|
|
break;
|
|
case AttributeType.TYPE_ID_HASH:
|
|
hash = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
if (HashStrings)
|
|
hash = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
IntIdTableOffset = AddGetHashIdTable(hash, -1);
|
|
|
|
tools.WriteInt32(WorkRam, IntIdTableOffset);
|
|
tools.WriteInt32(WorkRam, 0x00);
|
|
Console.WriteLine("Int Id: " + IntIdTableOffset + " sz: 0");
|
|
break;
|
|
default:
|
|
Console.WriteLine("UNKNOWN TYPE @ " + TreeTable.Position);
|
|
Console.ReadKey();
|
|
break;
|
|
}
|
|
Console.WriteLine(attribute.Name + "=" + attribute.Value);
|
|
}
|
|
public void WriteElement(XmlNode node)
|
|
{
|
|
MemoryStream WorkRam = new MemoryStream();
|
|
//BinaryWriter bWorkRam = new BinaryWriter(WorkRam);
|
|
int ElementPtr = AddGetStringTable(node.Name);
|
|
int NumAttributes = 0;
|
|
int ParentPtr = -1;
|
|
int PrevSibling = -1;
|
|
int NextSibling = -1;
|
|
|
|
int FirstChild = -1;
|
|
int LastChild = -1;
|
|
long Position = TreeTable.Position;
|
|
tools.WriteInt32(WorkRam, ElementPtr);
|
|
tools.WriteInt32(WorkRam, NumAttributes);
|
|
tools.WriteInt32(WorkRam, ParentPtr);
|
|
tools.WriteInt32(WorkRam, PrevSibling);
|
|
tools.WriteInt32(WorkRam, NextSibling);
|
|
tools.WriteInt32(WorkRam, FirstChild);
|
|
tools.WriteInt32(WorkRam, LastChild);
|
|
|
|
foreach (XmlAttribute attribute in node.Attributes)
|
|
{
|
|
WriteAttribute(attribute, WorkRam, node.Name);
|
|
}
|
|
|
|
|
|
WorkRam.Seek(0x00, SeekOrigin.Begin);
|
|
WorkRam.CopyTo(TreeTable);
|
|
|
|
foreach (XmlNode childNode in node.ChildNodes)
|
|
{
|
|
if(childNode != null)
|
|
AddGetTreeTable(childNode);
|
|
}
|
|
// Rewrite header now
|
|
|
|
if (node.Attributes != null)
|
|
NumAttributes = node.Attributes.Count;
|
|
if (node.ParentNode != null)
|
|
ParentPtr = AddGetTreeTable(node.ParentNode);
|
|
if (node.PreviousSibling != null)
|
|
PrevSibling = AddGetTreeTable(node.PreviousSibling);
|
|
if (node.NextSibling != null)
|
|
NextSibling = AddGetTreeTable(node.NextSibling);
|
|
if (node.FirstChild != null)
|
|
FirstChild = AddGetTreeTable(node.FirstChild);
|
|
if (node.LastChild != null)
|
|
LastChild = AddGetTreeTable(node.LastChild);
|
|
|
|
long Position2 = TreeTable.Position;
|
|
TreeTable.Seek(Position, SeekOrigin.Begin);
|
|
tools.WriteInt32(TreeTable, ElementPtr);
|
|
tools.WriteInt32(TreeTable, NumAttributes);
|
|
tools.WriteInt32(TreeTable, ParentPtr);
|
|
tools.WriteInt32(TreeTable, PrevSibling);
|
|
tools.WriteInt32(TreeTable, NextSibling);
|
|
tools.WriteInt32(TreeTable, FirstChild);
|
|
tools.WriteInt32(TreeTable, LastChild);
|
|
TreeTable.Seek(Position2, SeekOrigin.Begin);
|
|
}
|
|
|
|
public void Align(Stream s, int align)
|
|
{
|
|
|
|
int size = Convert.ToInt32(s.Length);
|
|
|
|
if (size % align != 0)
|
|
{
|
|
int totalAlign = (align - (size % align));
|
|
for (int i = 0; i < totalAlign; i++)
|
|
{
|
|
s.WriteByte(0x00);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Term()
|
|
{
|
|
InfoFile.Close();
|
|
TreeTable.Close();
|
|
IDTable.Close();
|
|
HashIDTable.Close();
|
|
StringTable.Close();
|
|
WStringTable.Close();
|
|
HashTable.Close();
|
|
IntArrayTable.Close();
|
|
FloatArrayTable.Close();
|
|
FileTable.Close();
|
|
|
|
|
|
TreeTableEntries.Clear();
|
|
StringTableEntries.Clear();
|
|
WStringTableEntries.Clear();
|
|
HashTableEntries.Clear();
|
|
IntArrayTableEntries.Clear();
|
|
FloatArrayTableEntries.Clear();
|
|
FileTableEntries.Clear();
|
|
IDTableEntries.Clear();
|
|
HashIDTableEntries.Clear();
|
|
|
|
IsInitalized = false;
|
|
}
|
|
|
|
public void BuildCXML(string XmlFile, string CxmlFile)
|
|
{
|
|
if (!IsInitalized)
|
|
Init(XmlFile, CxmlFile);
|
|
Console.WriteLine("Magic Number: " + MagicNumber);
|
|
Console.WriteLine("Version: " + Version.ToString("X"));
|
|
|
|
XmlDocument XMLFile = new XmlDocument();
|
|
XMLFile.Load(XmlFile);
|
|
|
|
Tools.WriteStringToStream(InfoFile, MagicNumber);
|
|
Tools.WriteLittleEndainInt(InfoFile, Version);
|
|
byte[] headerPlaceholder;
|
|
if (!ps3)
|
|
headerPlaceholder = new byte[0x48];
|
|
else
|
|
headerPlaceholder = new byte[0x30];
|
|
|
|
InfoFile.Write(headerPlaceholder, 0x00, headerPlaceholder.Length);
|
|
Align(InfoFile, 0x10);
|
|
|
|
foreach (XmlNode childNode in XMLFile.ChildNodes)
|
|
{
|
|
AddGetTreeTable(childNode);
|
|
}
|
|
|
|
int TreeTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int TreeTableSize = Convert.ToInt32(TreeTable.Length);
|
|
Align(TreeTable, 0x10);
|
|
TreeTable.Seek(0x00, SeekOrigin.Begin);
|
|
TreeTable.CopyTo(InfoFile);
|
|
|
|
|
|
int IdTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int IdTableSize = Convert.ToInt32(IDTable.Length);
|
|
Align(IDTable, 0x10);
|
|
IDTable.Seek(0x00, SeekOrigin.Begin);
|
|
IDTable.CopyTo(InfoFile);
|
|
|
|
int HashIdTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int HashIdTableSize = Convert.ToInt32(HashIDTable.Length);
|
|
Align(HashIDTable, 0x10);
|
|
HashIDTable.Seek(0x00, SeekOrigin.Begin);
|
|
HashIDTable.CopyTo(InfoFile);
|
|
|
|
int StringTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int StringTableSize = Convert.ToInt32(StringTable.Length);
|
|
Align(StringTable, 0x10);
|
|
StringTable.Seek(0x00, SeekOrigin.Begin);
|
|
StringTable.CopyTo(InfoFile);
|
|
|
|
int WStringTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int WStringTableSize = Convert.ToInt32(WStringTable.Length);
|
|
Align(WStringTable, 0x10);
|
|
WStringTable.Seek(0x00, SeekOrigin.Begin);
|
|
WStringTable.CopyTo(InfoFile);
|
|
|
|
int HashTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int HashTableSize = Convert.ToInt32(HashTable.Length);
|
|
Align(HashTable, 0x10);
|
|
HashTable.Seek(0x00, SeekOrigin.Begin);
|
|
HashTable.CopyTo(InfoFile);
|
|
|
|
int IntArrayTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int IntArrayTableSize = Convert.ToInt32(IntArrayTable.Length);
|
|
Align(IntArrayTable, 0x10);
|
|
IntArrayTable.Seek(0x00, SeekOrigin.Begin);
|
|
IntArrayTable.CopyTo(InfoFile);
|
|
|
|
int FloatArrayTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int FloatArrayTableSize = Convert.ToInt32(FloatArrayTable.Length);
|
|
Align(FloatArrayTable, 0x10);
|
|
FloatArrayTable.Seek(0x00, SeekOrigin.Begin);
|
|
FloatArrayTable.CopyTo(InfoFile);
|
|
|
|
int FileTableOffset = Convert.ToInt32(InfoFile.Position);
|
|
int FileTableSize = Convert.ToInt32(FileTable.Length);
|
|
Align(FileTable, 0x10);
|
|
FileTable.Seek(0x00, SeekOrigin.Begin);
|
|
FileTable.CopyTo(InfoFile);
|
|
|
|
string excessData = GetTypingInformation("EXCESS");
|
|
if (excessData != "0")
|
|
{
|
|
Console.WriteLine("Excess Data Found, Writing to end.");
|
|
byte[] ExcessData = Convert.FromBase64String(excessData.Replace("*", "="));
|
|
InfoFile.Read(ExcessData, 0x00, ExcessData.Length);
|
|
byte[] UnCompressed = ZlibStream.UncompressBuffer(ExcessData);
|
|
InfoFile.Write(UnCompressed, 0x00, UnCompressed.Length);
|
|
}
|
|
|
|
InfoFile.Seek(0x8, SeekOrigin.Begin);
|
|
tools.WriteInt32(InfoFile, TreeTableOffset);
|
|
tools.WriteInt32(InfoFile, TreeTableSize);
|
|
tools.WriteInt32(InfoFile, IdTableOffset);
|
|
tools.WriteInt32(InfoFile, IdTableSize);
|
|
|
|
if (!ps3)
|
|
{
|
|
tools.WriteInt32(InfoFile, HashIdTableOffset);
|
|
tools.WriteInt32(InfoFile, HashIdTableSize);
|
|
}
|
|
|
|
tools.WriteInt32(InfoFile, StringTableOffset);
|
|
tools.WriteInt32(InfoFile, StringTableSize);
|
|
|
|
if (!ps3)
|
|
{
|
|
tools.WriteInt32(InfoFile, WStringTableOffset);
|
|
tools.WriteInt32(InfoFile, WStringTableSize);
|
|
tools.WriteInt32(InfoFile, HashTableOffset);
|
|
tools.WriteInt32(InfoFile, HashTableSize);
|
|
}
|
|
|
|
tools.WriteInt32(InfoFile, IntArrayTableOffset);
|
|
tools.WriteInt32(InfoFile, IntArrayTableSize);
|
|
tools.WriteInt32(InfoFile, FloatArrayTableOffset);
|
|
tools.WriteInt32(InfoFile, FloatArrayTableSize);
|
|
tools.WriteInt32(InfoFile, FileTableOffset);
|
|
tools.WriteInt32(InfoFile, FileTableSize);
|
|
|
|
Term();
|
|
}
|
|
}
|
|
}
|