cxml-decompiler/AppInfoCli/CXMLBuilder.cs

685 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 = "";
Int32 Version;
FileStream InfoFile;
MemoryStream TreeTable;
MemoryStream StringIDTable;
MemoryStream IntIDTable;
MemoryStream StringTable;
MemoryStream CharTable;
MemoryStream HashIDTable;
MemoryStream IntArrayTable;
MemoryStream FloatArrayTable;
MemoryStream FileTable;
Boolean IsInitalized = false;
public Boolean HashStrings = false;
BinaryWriter bInfoFile;
BinaryWriter bTreeTable;
BinaryWriter bIntIDTable;
BinaryWriter bFloatArrayTable;
BinaryWriter bIntArrayTable;
BinaryWriter bHashIDTable;
BinaryWriter bStringIDTable;
String SilicaTypingInformation = "";
public void Init(string XMLFile, string CxmlFile)
{
GetSilicaTypingInformation(XMLFile);
MagicNumber = GetTypingInformation("MAGIC");
Version = Int32.Parse(GetTypingInformation("VERSION"), CultureInfo.InvariantCulture);
InfoFile = File.Open(CxmlFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
InfoFile.SetLength(0);
TreeTable = new MemoryStream();
StringIDTable = new MemoryStream();
IntIDTable = new MemoryStream();
StringTable = new MemoryStream();
CharTable = new MemoryStream();
HashIDTable = new MemoryStream();
IntArrayTable = new MemoryStream();
FloatArrayTable = new MemoryStream();
FileTable = new MemoryStream();
bInfoFile = new BinaryWriter(InfoFile);
bTreeTable = new BinaryWriter(TreeTable);
bIntIDTable = new BinaryWriter(IntIDTable);
bFloatArrayTable = new BinaryWriter(FloatArrayTable);
bIntArrayTable = new BinaryWriter(IntArrayTable);
bHashIDTable = new BinaryWriter(HashIDTable);
bStringIDTable = new BinaryWriter(StringIDTable);
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 IntTableEntry
{
public int offset;
public int value;
}
public class StringIDTableEntry
{
public int offset;
public string value;
public int loopbackOffset;
}
public class IntIDTableEntry
{
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> CharTableEntries = new List<StringTableEntry>();
List<IntTableEntry> HashIdTableEntries = new List<IntTableEntry>();
List<Int32> IntArrayTableEntries = new List<Int32>();
List<Single> FloatArrayTableEntries = new List<Single>();
List<StringTableEntry> FileTableEntries = new List<StringTableEntry>();
List<StringIDTableEntry> StringIDTableEntries = new List<StringIDTableEntry>();
List<IntIDTableEntry> IntIDTableEntries = new List<IntIDTableEntry>();
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 AddGetIntIdTable(int value, int loopbackPtr)
{
foreach (IntIDTableEntry entry in IntIDTableEntries)
{
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 = IntIDTable.Position;
IntIDTable.Seek(entry.offset, SeekOrigin.Begin);
bIntIDTable.Write(loopbackPtr);
IntIDTable.Seek(position1, SeekOrigin.Begin);
return entry.offset;
}
}
IntIDTableEntry ent = new IntIDTableEntry();
ent.value = value;
ent.loopbackOffset = loopbackPtr;
ent.offset = Convert.ToInt32(IntIDTable.Position);
IntIDTableEntries.Add(ent);
bIntIDTable.Write((int)loopbackPtr);
bIntIDTable.Write((int)value);
return ent.offset;
}
public int AddGetStringIdTable(string value, int loopbackPtr)
{
foreach (StringIDTableEntry entry in StringIDTableEntries)
{
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 = StringIDTable.Position;
StringIDTable.Seek(entry.offset, SeekOrigin.Begin);
bStringIDTable.Write(loopbackPtr);
StringIDTable.Seek(position1, SeekOrigin.Begin);
return entry.offset;
}
}
StringIDTableEntry ent = new StringIDTableEntry();
ent.value = value;
ent.loopbackOffset = loopbackPtr;
ent.offset = Convert.ToInt32(StringIDTable.Position);
StringIDTableEntries.Add(ent);
bStringIDTable.Write(loopbackPtr);
Tools.WriteStringToStream(StringIDTable, value);
StringIDTable.WriteByte(0x00);
if (loopbackPtr != -1)
{
Align(StringIDTable, 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)
{
bFloatArrayTable.Write((float)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)
{
bIntArrayTable.Write((int)i);
IntArrayTableEntries.Add(i);
}
return offset;
}
public int AddGetHashIdTable(int value)
{
foreach (IntTableEntry entry in HashIdTableEntries)
if (entry.value == value)
return entry.offset/4;
IntTableEntry ent = new IntTableEntry();
ent.value = value;
ent.offset = Convert.ToInt32(HashIDTable.Position);
HashIdTableEntries.Add(ent);
bHashIDTable.Write((int)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 AddGetCharTable(string elementName)
{
foreach (StringTableEntry entry in CharTableEntries)
if (entry.name == elementName)
return entry.offset;
StringTableEntry ent = new StringTableEntry();
ent.name = elementName;
ent.offset = Convert.ToInt32(CharTable.Position)/2;
CharTableEntries.Add(ent);
Tools.WriteUtf16StringToStream(CharTable, elementName);
CharTable.WriteByte(0x00);
CharTable.WriteByte(0x00);
return ent.offset;
}
public AttributeType DetermineType(string ElementName, string AttributeName)
{
return (AttributeType)Int32.Parse(GetTypingInformation(ElementName + ":" + AttributeName), CultureInfo.InvariantCulture);
}
public void WriteAttribute(XmlAttribute attribute, MemoryStream WorkRam, BinaryWriter bWorkRam, string ElementName)
{
int AttributePtr = AddGetStringTable(attribute.Name);
AttributeType Type = DetermineType(ElementName, attribute.Name);
bWorkRam.Write(AttributePtr);
bWorkRam.Write((int)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);
bWorkRam.Write((int)intWrite);
bWorkRam.Write((int)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);
bWorkRam.Write((float)FloatValue);
bWorkRam.Write((int)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;
bWorkRam.Write(StringOffset);
bWorkRam.Write(StringLen);
Console.WriteLine("String: " + attribute.Value);
break;
case AttributeType.TYPE_CHAR:
int CharOffset = AddGetCharTable(attribute.Value);
int CharLen = Encoding.Unicode.GetBytes(attribute.Value).Length;
bWorkRam.Write(CharOffset);
bWorkRam.Write(CharLen);
Console.WriteLine("Char: " + attribute.Value);
break;
case AttributeType.TYPE_HASH_ID:
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 = AddGetHashIdTable(hashId);
int HashTableSize = 4;
bWorkRam.Write(HashTableOffset);
bWorkRam.Write(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;
bWorkRam.Write(IntArrayOffset);
bWorkRam.Write(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;
bWorkRam.Write(FloatArrayOffset);
bWorkRam.Write(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;
bWorkRam.Write(FilePtr);
bWorkRam.Write(FileSz);
Console.WriteLine("Reading File: " + fPath);
break;
case AttributeType.TYPE_ID_STRING_LOOPBACK:
int StringIdTableOffset = AddGetStringIdTable(attribute.Value, Convert.ToInt32(TreeTable.Position));
bWorkRam.Write(StringIdTableOffset);
bWorkRam.Write((int)0x00);
Console.WriteLine("String Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")");
Console.WriteLine("Loopback ID String: " + StringIdTableOffset + " sz: 0");
break;
case AttributeType.TYPE_ID_STRING:
StringIdTableOffset = AddGetStringIdTable(attribute.Value, -1);
bWorkRam.Write(StringIdTableOffset);
bWorkRam.Write((int)0x00);
Console.WriteLine("ID String: " + StringIdTableOffset + " sz: 0");
break;
case AttributeType.TYPE_ID_INT_LOOPBACK:
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 = AddGetIntIdTable(hash, Convert.ToInt32(TreeTable.Position));
bWorkRam.Write(IntIdTableOffset);
bWorkRam.Write((int)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_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);
IntIdTableOffset = AddGetIntIdTable(hash, -1);
bWorkRam.Write(IntIdTableOffset);
bWorkRam.Write((int)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;
bWorkRam.Write(ElementPtr);
bWorkRam.Write(NumAttributes);
bWorkRam.Write(ParentPtr);
bWorkRam.Write(PrevSibling);
bWorkRam.Write(NextSibling);
bWorkRam.Write(FirstChild);
bWorkRam.Write(LastChild);
foreach (XmlAttribute attribute in node.Attributes)
{
WriteAttribute(attribute, WorkRam, bWorkRam, 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);
bTreeTable.Write(ElementPtr);
bTreeTable.Write(NumAttributes);
bTreeTable.Write(ParentPtr);
bTreeTable.Write(PrevSibling);
bTreeTable.Write(NextSibling);
bTreeTable.Write(FirstChild);
bTreeTable.Write(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();
StringIDTable.Close();
IntIDTable.Close();
StringTable.Close();
CharTable.Close();
HashIDTable.Close();
IntArrayTable.Close();
FloatArrayTable.Close();
FileTable.Close();
bTreeTable.Close();
bIntIDTable.Close();
bFloatArrayTable.Close();
bIntArrayTable.Close();
bHashIDTable.Close();
TreeTableEntries.Clear();
StringTableEntries.Clear();
CharTableEntries.Clear();
HashIdTableEntries.Clear();
IntArrayTableEntries.Clear();
FloatArrayTableEntries.Clear();
FileTableEntries.Clear();
StringIDTableEntries.Clear();
IntIDTableEntries.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);
bInfoFile.Write((Int32)Version);
byte[] headerPlaceholder = new byte[0x48];
InfoFile.Write(headerPlaceholder, 0x00, headerPlaceholder.Length);
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 StringIdOffset = Convert.ToInt32(InfoFile.Position);
int StringIdSize = Convert.ToInt32(StringIDTable.Length);
Align(StringIDTable, 0x10);
StringIDTable.Seek(0x00, SeekOrigin.Begin);
StringIDTable.CopyTo(InfoFile);
int IntIdOffset = Convert.ToInt32(InfoFile.Position);
int IntIdSize = Convert.ToInt32(IntIDTable.Length);
Align(IntIDTable, 0x10);
IntIDTable.Seek(0x00, SeekOrigin.Begin);
IntIDTable.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 CharTableOffset = Convert.ToInt32(InfoFile.Position);
int CharTableSize = Convert.ToInt32(CharTable.Length);
Align(CharTable, 0x10);
CharTable.Seek(0x00, SeekOrigin.Begin);
CharTable.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 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);
bInfoFile.Write(TreeTableOffset);
bInfoFile.Write(TreeTableSize);
bInfoFile.Write(StringIdOffset);
bInfoFile.Write(StringIdSize);
bInfoFile.Write(IntIdOffset);
bInfoFile.Write(IntIdSize);
bInfoFile.Write(StringTableOffset);
bInfoFile.Write(StringTableSize);
bInfoFile.Write(CharTableOffset);
bInfoFile.Write(CharTableSize);
bInfoFile.Write(HashIdTableOffset);
bInfoFile.Write(HashIdTableSize);
bInfoFile.Write(IntArrayTableOffset);
bInfoFile.Write(IntArrayTableSize);
bInfoFile.Write(FloatArrayTableOffset);
bInfoFile.Write(FloatArrayTableSize);
bInfoFile.Write(FileTableOffset);
bInfoFile.Write(FileTableSize);
Term();
}
}
}