cxml-decompiler/CXMLCli/CXMLReader.cs

906 lines
34 KiB
C#

using Ionic.Zlib;
using General;
using CXML;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Globalization;
namespace CXMLDecompiler
{
class CXMLReader
{
private bool _checkMagicNumber()
{
String Magic = Tools.ReadStringAt(InfoFile, 0x00);
MagicNumber = Magic.Substring(0,4);
if (Magic.StartsWith("PSMA")) // PlayStation Mobile "app.info"
{
return true;
}
else if(Magic.StartsWith("RCOF")) // Vita/Ps4/Ps3 RCO
{
return true;
}
else if (Magic.StartsWith("RCSF")) // Found inside RCO
{
return true;
}
else if (Magic.StartsWith("P3TF")) // ps3 theme file
{
return true;
}
else if (Magic.StartsWith("CXML")) // cxml.py default
{
return true;
}
else if (Magic.StartsWith("TEST")) // ps3 cxml tools example
{
return true;
}
else
{
return false;
}
}
String MainDir = "";
String FileDir = "";
String XMLFilename = "";
String MagicNumber = "";
List<TypingInformation> SilicaTypingInformationList = new List<TypingInformation>();
String MagicReplacePattern = Tools.GenerateReplacePattern();
String SilicaTypingInformation = "SilicaTypingInformation{{[[";
FileStream InfoFile;
MemoryStream TreeTable;
MemoryStream IDTable;
MemoryStream HashIDTable;
MemoryStream StringTable;
MemoryStream WStringTable;
MemoryStream HashTable;
MemoryStream IntArrayTable;
MemoryStream FloatArrayTable;
MemoryStream FileTable;
Tools tools;
Boolean IsInitalized = false;
CXML.Version FileVersion;
public Endianness FileEndainness = Endianness.LITTLE_ENDIAN;
List<LoopbackHandler> FileList = new List<LoopbackHandler>();
XmlWriter XMLWriter;
public bool ps3 = false;
public bool ProcessFiles = false;
public bool WaitExit = false;
public bool NoRecursive = false;
public void Init(string path, bool CheckMagic = true, bool forcePs3 = false, Endianness forceEndainness = Endianness.UNCHANGED)
{
InfoFile = File.Open(path, FileMode.Open, FileAccess.Read);
bool MagicValid = _checkMagicNumber();
if (CheckMagic)
{
if (!MagicValid)
{
throw new Exception("Incorrect magic number.");
}
}
// This is a bit of a hack, but what can you do?
FileVersion = ReadVersionEnum();
if (FileVersion == CXML.Version.PS3)
{
ps3 = true;
FileEndainness = Endianness.BIG_ENDIAN;
}
else
{
FileEndainness = Endianness.LITTLE_ENDIAN;
}
if (forcePs3)
ps3 = true;
if (forceEndainness != Endianness.UNCHANGED)
FileEndainness = forceEndainness;
tools = new Tools(FileEndainness == Endianness.BIG_ENDIAN);
TreeTable = Tools.ByteToStream(GetTreeTable());
StringTable = Tools.ByteToStream(GetStringTable());
IntArrayTable = Tools.ByteToStream(GetIntArrayTable());
FloatArrayTable = Tools.ByteToStream(GetFloatArrayTable());
IDTable = Tools.ByteToStream(GetIDTable());
FileTable = Tools.ByteToStream(GetFileTable());
// psvita, ps4 exclusive
if (!ps3)
{
HashTable = Tools.ByteToStream(GetHashTable());
HashIDTable = Tools.ByteToStream(GetHashIDTable());
WStringTable = Tools.ByteToStream(GetWStringTable());
}
else
{
HashTable = new MemoryStream();
HashIDTable = new MemoryStream();
WStringTable = new MemoryStream();
}
MainDir = Path.GetFileNameWithoutExtension(path);
FileDir = Path.Combine(MainDir, "files");
XMLFilename = Path.GetFileNameWithoutExtension(path) + ".xml";
IsInitalized = true;
return;
}
public void Term()
{
InfoFile.Close();
TreeTable.Close();
IDTable.Close();
HashIDTable.Close();
StringTable.Close();
WStringTable.Close();
HashTable.Close();
IntArrayTable.Close();
FloatArrayTable.Close();
FileTable.Close();
FileList.Clear();
IsInitalized = false;
}
public int GetTreeTableOffset()
{
return tools.ReadIntAt(InfoFile,0x8);
}
public int GetTreeTableSize()
{
return tools.ReadIntAt(InfoFile, 0xC);
}
public int GetIDTableOffset()
{
return tools.ReadIntAt(InfoFile, 0x10);
}
public int GetIDTableSize()
{
return tools.ReadIntAt(InfoFile, 0x14);
}
public int GetHashIDTableOffset()
{
return tools.ReadIntAt(InfoFile, 0x18);
}
public int GetHashIDTableSize()
{
return tools.ReadIntAt(InfoFile, 0x1C);
}
public int GetStringTableOffset()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x18);
else
return tools.ReadIntAt(InfoFile, 0x20);
}
public int GetStringTableSize()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x1C);
else
return tools.ReadIntAt(InfoFile, 0x24);
}
public int GetWStringTableOffset()
{
return tools.ReadIntAt(InfoFile, 0x28);
}
public int GetWStringTableSize()
{
return tools.ReadIntAt(InfoFile, 0x2C);
}
public int GetHashTableOffset()
{
return tools.ReadIntAt(InfoFile, 0x30);
}
public int GetHashTableSize()
{
return tools.ReadIntAt(InfoFile, 0x34);
}
public int GetIntArrayTableOffset()
{
if(ps3)
return tools.ReadIntAt(InfoFile, 0x20);
else
return tools.ReadIntAt(InfoFile, 0x38);
}
public int GetIntArrayTableSize()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x24);
else
return tools.ReadIntAt(InfoFile, 0x3C);
}
public int GetFloatArrayTableOffset()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x28);
else
return tools.ReadIntAt(InfoFile, 0x40);
}
public int GetFloatArrayTableSize()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x2C);
else
return tools.ReadIntAt(InfoFile, 0x44);
}
public int GetFileTableOffset()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x30);
else
return tools.ReadIntAt(InfoFile, 0x48);
}
public int GetFileTableSize()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x34);
else
return tools.ReadIntAt(InfoFile, 0x4C);
}
public byte[] GetTreeTable()
{
int TableOffset = GetTreeTableOffset();
int TableSize = GetTreeTableSize();
InfoFile.Seek(TableOffset, SeekOrigin.Begin);
byte[] Table = new byte[TableSize];
InfoFile.Read(Table, 0x00, TableSize);
return Table;
}
public byte[] GetIDTable()
{
int IDOffset = GetIDTableOffset();
int IDTableSize = GetIDTableSize();
InfoFile.Seek(IDOffset, SeekOrigin.Begin);
byte[] IDTable = new byte[IDTableSize];
InfoFile.Read(IDTable, 0x00, IDTableSize);
return IDTable;
}
public byte[] GetHashIDTable()
{
int HashIDTableOffset = GetHashIDTableOffset();
int HashIDTableSize = GetHashIDTableSize();
InfoFile.Seek(HashIDTableOffset, SeekOrigin.Begin);
byte[] HashIDTable = new byte[HashIDTableSize];
InfoFile.Read(HashIDTable, 0x00, HashIDTableSize);
return HashIDTable;
}
public byte[] GetStringTable()
{
int StringTableOffset = GetStringTableOffset();
int StringTableSize = GetStringTableSize();
InfoFile.Seek(StringTableOffset, SeekOrigin.Begin);
byte[] StringTable = new byte[StringTableSize];
InfoFile.Read(StringTable, 0x00, StringTableSize);
return StringTable;
}
public byte[] GetWStringTable()
{
int CharTableOffset = GetWStringTableOffset();
int CharTableSize = GetWStringTableSize();
InfoFile.Seek(CharTableOffset, SeekOrigin.Begin);
byte[] CharTable = new byte[CharTableSize];
InfoFile.Read(CharTable, 0x00, CharTableSize);
return CharTable;
}
public byte[] GetHashTable()
{
int HashTableOffset = GetHashTableOffset();
int HashTableSize = GetHashTableSize();
InfoFile.Seek(HashTableOffset, SeekOrigin.Begin);
byte[] HashTable = new byte[HashTableSize];
InfoFile.Read(HashTable, 0x00, HashTableSize);
return HashTable;
}
public byte[] GetIntArrayTable()
{
int IntArrayTableOffset = GetIntArrayTableOffset();
int IntArrayTableSize = GetIntArrayTableSize();
InfoFile.Seek(IntArrayTableOffset, SeekOrigin.Begin);
byte[] IntArrayTable = new byte[IntArrayTableSize];
InfoFile.Read(IntArrayTable, 0x00, IntArrayTableSize);
return IntArrayTable;
}
public byte[] GetFloatArrayTable()
{
int FloatArrayTableOffset = GetFloatArrayTableOffset();
int FloatArrayTableSize = GetFloatArrayTableSize();
InfoFile.Seek(FloatArrayTableOffset, SeekOrigin.Begin);
byte[] FloatArrayTable = new byte[FloatArrayTableSize];
InfoFile.Read(FloatArrayTable, 0x00, FloatArrayTableSize);
return FloatArrayTable;
}
public byte[] GetFileTable()
{
int DataOffset = GetFileTableOffset();
int DataLength = GetFileTableSize();
InfoFile.Seek(DataOffset, SeekOrigin.Begin);
byte[] FileTable = new byte[DataLength];
InfoFile.Read(FileTable, 0x00, DataLength);
return FileTable;
}
public CXML.Version ReadVersionEnum()
{
try
{
return (CXML.Version)ReadVersionInt();
}
catch (Exception)
{
return CXML.Version.UNKNOWN;
}
}
public int ReadVersionInt()
{
return Tools.ReadLittleEndainIntAt(InfoFile, 0x4);
}
public void AddTypingInfo(string key, object value)
{
foreach(TypingInformation tInfo in SilicaTypingInformationList)
{
if(tInfo.key == key)
{
if (tInfo.value.ToString() != value.ToString())
throw new Exception("Very Weird CXML");
return;
}
}
TypingInformation typingInfo = new TypingInformation();
typingInfo.key = key;
typingInfo.value = value.ToString();
SilicaTypingInformationList.Add(typingInfo);
}
public void Align(Stream s, int align)
{
int size = Convert.ToInt32(s.Position);
if (size % align != 0)
{
int totalAlign = (align - (size % align));
for (int i = 0; i < totalAlign; i++)
{
s.Seek(0x1, SeekOrigin.Current);
}
}
}
public void GotoEnd()
{
InfoFile.Seek(GetFileTableOffset(), SeekOrigin.Begin);
InfoFile.Seek(GetFileTableSize(), SeekOrigin.Current);
Align(InfoFile, 0x10);
}
public void DecompileCXML(String CXMLFile)
{
if (!IsInitalized)
Init(CXMLFile);
if (Directory.Exists(MainDir))
Directory.Delete(MainDir, true);
if (!Directory.Exists(FileDir))
Directory.CreateDirectory(FileDir);
XmlWriterSettings XMLSettings = new XmlWriterSettings();
XMLSettings.Indent = true;
XMLSettings.Encoding = Encoding.UTF8;
string XMLPath = Path.Combine(MainDir, XMLFilename);
StreamWriter sw = new StreamWriter(new MemoryStream(), Encoding.UTF8);
XMLWriter = XmlWriter.Create(sw, XMLSettings);
XMLWriter.WriteStartDocument();
XMLWriter.WriteComment(MagicReplacePattern);
AddTypingInfo("MAGIC", MagicNumber);
AddTypingInfo("VERSION", "0x"+ReadVersionInt().ToString("X"));
AddTypingInfo("ENDAINESS", FileEndainness.ToString());
AddTypingInfo("PS3", ps3 ? "true" : "false");
ReadElements();
XMLWriter.WriteEndDocument();
XMLWriter.Flush();
XMLWriter.Close();
GotoEnd();
int bytesRemaining = Convert.ToInt32(InfoFile.Length - InfoFile.Position);
if (bytesRemaining > 0) // Some RCS files have unexplainable random XML Data at the end of them, Dont ask me. im just the messanger
{
Console.WriteLine(bytesRemaining.ToString("X8", CultureInfo.InvariantCulture) + " Excess Bytes Found, Shoving it in SilicaTypingInformation.");
byte[] ExcessData = new byte[bytesRemaining];
InfoFile.Read(ExcessData, 0x00, bytesRemaining);
byte[] Compressed = ZlibStream.CompressBuffer(ExcessData);
string base64 = Convert.ToBase64String(Compressed).Replace("=", "*");
AddTypingInfo("EXCESS", base64);
}
for(int i = 0; i < SilicaTypingInformationList.Count; i++)
{
TypingInformation tinfo = SilicaTypingInformationList[i];
SilicaTypingInformation += tinfo.key + "=" + tinfo.value;
if(i+1 != SilicaTypingInformationList.Count)
{
SilicaTypingInformation += ",";
}
}
SilicaTypingInformation += "]]}}SilicaTypingInformation";
byte[] XMLBytes = new byte[sw.BaseStream.Length];
sw.Flush();
sw.BaseStream.Seek(0x00, SeekOrigin.Begin);
sw.BaseStream.Read(XMLBytes, 0x00, XMLBytes.Length);
sw.Close();
string XMLData = Encoding.UTF8.GetString(XMLBytes);
// Resolve Replace Patterns
XMLData = XMLData.Replace(MagicReplacePattern, SilicaTypingInformation);
foreach(LoopbackHandler lpHandler in FileList)
{
if (lpHandler.ReplacePattern != null && lpHandler.OldFileName != null)
{
string replacePattern = lpHandler.ReplacePattern;
string oldName = lpHandler.OldFileName;
string extension = Path.GetExtension(oldName);
string folderPath = Path.GetDirectoryName(oldName);
byte[] fileData = lpHandler.FileData;
if (lpHandler.FileName != null)
{
string newPath = Path.ChangeExtension(Path.Combine(folderPath, lpHandler.FileName), extension);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
if (!File.Exists(newPath))
{
File.WriteAllBytes(newPath, fileData);
string xmlRelNewPath = newPath.Substring(Tools.GetRootFolder(newPath).Length + 1);
Console.WriteLine("Resolved " + replacePattern + " => " + xmlRelNewPath);
XMLData = XMLData.Replace(replacePattern, xmlRelNewPath);
}
if (ProcessFiles)
ProcessFile(newPath);
}
else
{
Console.WriteLine("Unable to resolve: " + oldName);
if (!File.Exists(oldName))
File.WriteAllBytes(oldName, fileData);
if (ProcessFiles)
ProcessFile(oldName);
}
}
}
File.WriteAllText(XMLPath, XMLData);
Term();
}
public void ProcessFile(String FileName)
{
String Extension = Path.GetExtension(FileName);
if (Extension == ".rcs") // Recursive Decompile, remove this if statement to remove RCS processing
{
if (NoRecursive)
return;
Console.WriteLine("Decompiling " + Path.GetFileName(FileName));
string DirectoryName = Path.Combine(FileDir, "converted", "RCStoXML", Path.GetFileNameWithoutExtension(FileName));
if (!Directory.Exists(DirectoryName))
Directory.CreateDirectory(DirectoryName);
try
{
CXMLReader cxmlParser = new CXMLReader();
cxmlParser.Init(FileName);
cxmlParser.ProcessFiles = this.ProcessFiles;
cxmlParser.MainDir = DirectoryName;
cxmlParser.FileDir = Path.Combine(cxmlParser.MainDir, "files");
cxmlParser.DecompileCXML(FileName);
}
catch (Exception) { };
}
if (Extension == ".vag") //Remove this IF statment if you dont want VAG Conversion.
{
Console.WriteLine("Decoding: " + Path.GetFileName(FileName));
byte[] WaveData = VAG.VAGAudio.Vag2Wav(FileName);
String WaveName = Path.GetFileNameWithoutExtension(FileName) + "-" + VAG.VAGAudio.GetFilename(FileName) + ".wav";
String DirectoryName = Path.Combine(FileDir , "converted", "VAGtoWAV");
if (!Directory.Exists(DirectoryName))
Directory.CreateDirectory(DirectoryName);
File.WriteAllBytes(Path.Combine(DirectoryName, WaveName), WaveData);
Console.WriteLine("Decoded file written to: " + WaveName);
}
if (Extension == ".gim") //Remove this IF statement if you dont want GIM Conversion.
{
if (File.Exists(Path.Combine("GimConv", "GimConv.exe")))
{
String DirectoryName = Path.Combine(FileDir, "converted", "GIMtoPNG");
if (!Directory.Exists(DirectoryName))
Directory.CreateDirectory(DirectoryName);
Console.WriteLine("Decoding GIM.");
Process Proc = new Process();
Proc.StartInfo.FileName = Path.Combine("GimConv", "GimConv.exe");
Proc.StartInfo.Arguments = "\"" + Path.GetFileName(FileName) + "\" -o \"" + Path.Combine(Environment.CurrentDirectory, DirectoryName, Path.GetFileName(Path.ChangeExtension(FileName, "png"))) + "\"";
Proc.StartInfo.RedirectStandardOutput = true;
Proc.StartInfo.RedirectStandardError = true;
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(FileName);
Proc.Start();
Proc.WaitForExit();
Console.WriteLine(Proc.StandardOutput.ReadToEnd());
Console.WriteLine("Done!");
}
}
if (Extension == ".z")
{
Console.WriteLine("Decompressing " + FileName);
Byte[] FileData = File.ReadAllBytes(FileName);
Byte[] DecompressedData = ZlibStream.UncompressBuffer(FileData);
Extension = Tools.GetFileExtension(DecompressedData);
String DirectoryName = Path.Combine(FileDir, "decompressed");
if (!Directory.Exists(DirectoryName))
Directory.CreateDirectory(DirectoryName);
String DecompressedFilename = Path.Combine(DirectoryName, Path.ChangeExtension(Path.GetFileNameWithoutExtension(FileName), Extension));
Console.WriteLine("Decompressed file written to: " + DecompressedFilename);
File.WriteAllBytes(DecompressedFilename, DecompressedData);
ProcessFile(DecompressedFilename);
}
}
public void RegisterFile(Int64 ElementPtr, String NewName, Boolean FileEntry, String ReplacePattern=null, byte[] FileData=null, String IdealName=null)
{
Console.WriteLine("Adding Entry for Loopback: 0x" + ElementPtr.ToString("X8", CultureInfo.InvariantCulture) + " (" + NewName + ")");
for(int i = 0; i < FileList.Count; i++)
{
if(FileList[i].FilePointer == ElementPtr)
{
if (FileEntry)
{
if (FileList[i].OldFileName != null)
break;
FileList[i].OldFileName = NewName;
FileList[i].FileName = IdealName;
return;
}
else
{
FileList[i].FileName = NewName;
return;
}
}
}
LoopbackHandler lpHandler = new LoopbackHandler();
if (FileEntry)
{
lpHandler.OldFileName = NewName;
lpHandler.FileName = IdealName;
lpHandler.FileData = FileData;
lpHandler.ReplacePattern = ReplacePattern;
}
else
{
lpHandler.FileName = NewName;
}
lpHandler.FilePointer = ElementPtr;
FileList.Add(lpHandler);
return;
}
public AttributeType ReadAttributeType(Stream ms)
{
if(!ps3)
{
AttributeType type = (AttributeType)tools.ReadInt32(ms);
return type;
}
else
{
AttributeTypePs3 type = (AttributeTypePs3)tools.ReadInt32(ms);
return (AttributeType)Enum.Parse(typeof(AttributeType), type.ToString());
}
}
public void ReadAttribute(String ElementName = "", Int64 ElementPtr = 0)
{
int AttributePtr = tools.ReadInt32(TreeTable);
AttributeType Type = ReadAttributeType(TreeTable);
String AttributeName = Tools.ReadStringAt(StringTable, AttributePtr);
object AttributeValue = "";
Console.WriteLine("AttributeType: " + Type.ToString() + " - "+ TreeTable.Position.ToString());
switch (Type)
{
case AttributeType.TYPE_INT:
AttributeValue = tools.ReadInt32(TreeTable);
int sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Int - Value: " + AttributeValue.ToString() + " sz:" + sz);
break;
case AttributeType.TYPE_FLOAT:
Double FloatValue = (Double)tools.ReadSingle(TreeTable);
string FloatStr = FloatValue.ToString("G9", CultureInfo.InvariantCulture);
if (!FloatStr.Contains("."))
FloatStr += ".0";
AttributeValue = FloatStr;
sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Float: " + AttributeValue.ToString() + " sz:" + sz);
break;
case AttributeType.TYPE_STRING:
int StringOffset = tools.ReadInt32(TreeTable);
int StringLen = tools.ReadInt32(TreeTable);
byte[] StringBytes = new byte[StringLen];
StringTable.Seek(StringOffset, 0x00);
StringTable.Read(StringBytes, 0x00, StringLen);
AttributeValue = Encoding.UTF8.GetString(StringBytes);
Console.WriteLine("String: " + AttributeValue);
break;
case AttributeType.TYPE_WSTRING:
int WStrOffset = tools.ReadInt32(TreeTable) * 2;
int WStrLen = tools.ReadInt32(TreeTable);
byte[] WStrBytes = new byte[WStrLen];
WStringTable.Seek(WStrOffset, 0x00);
WStringTable.Read(WStrBytes, 0x00, WStrLen);
AttributeValue = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(Encoding.Unicode.GetString(WStrBytes)));
Console.WriteLine("WString: " + AttributeValue);
break;
case AttributeType.TYPE_HASH:
int HashTableOffset = tools.ReadInt32(TreeTable);
int HashTableSize = tools.ReadInt32(TreeTable);
HashTable.Seek(HashTableOffset * 4, SeekOrigin.Begin);
int Hash = tools.ReadInt32(HashTable);
AttributeValue = Hash.ToString("X8", CultureInfo.InvariantCulture);
Console.WriteLine("Hash: " + AttributeValue.ToString() + " sz: " + HashTableSize);
break;
case AttributeType.TYPE_INTEGER_ARRAY:
int IntArrayOffset = tools.ReadInt32(TreeTable);
int IntArraySize = tools.ReadInt32(TreeTable);
IntArrayTable.Seek(IntArrayOffset*4, SeekOrigin.Begin);
List<int> IntList = new List<int>();
for (int i = 0; i < IntArraySize; i++)
{
int IntValue = tools.ReadInt32(IntArrayTable);
IntList.Add(IntValue);
}
int[] IntArray = IntList.ToArray();
AttributeValue = String.Join(",", IntArray);
Console.WriteLine("Int Array: " + AttributeValue.ToString());
break;
case AttributeType.TYPE_FLOAT_ARRAY:
int FloatArrayOffset = tools.ReadInt32(TreeTable);
int FloatArraySize = tools.ReadInt32(TreeTable);
FloatArrayTable.Seek(FloatArrayOffset*4, SeekOrigin.Begin);
List<string> StrList = new List<string>();
for(int i = 0; i < FloatArraySize; i++)
{
FloatValue = (Double)tools.ReadSingle(FloatArrayTable);
FloatStr = FloatValue.ToString("G9", CultureInfo.InvariantCulture);
if (!FloatStr.Contains("."))
FloatStr += ".0";
StrList.Add(FloatStr);
}
string[] StrArray = StrList.ToArray();
AttributeValue = String.Join(", ", StrArray);
Console.WriteLine("Float Array: " + AttributeValue.ToString());
break;
case AttributeType.TYPE_FILE:
int FilePtr = tools.ReadInt32(TreeTable);
int FileSz = tools.ReadInt32(TreeTable);
Byte[] FileData = new Byte[FileSz];
FileTable.Seek(FilePtr, SeekOrigin.Begin);
FileTable.Read(FileData, 0, FileSz);
String FileHash = Tools.GenerateHash(FileData);
String FileSmallHash = Tools.GenerateShortHash(FileData);
String Extension = Tools.GetFileExtension(FileData);
String FileName = Path.Combine(FileDir, "original", FilePtr.ToString("X", CultureInfo.InvariantCulture) + "-" + FileHash + Extension);
String IdealName = ElementName + "-" + AttributeName + "-" + FileSmallHash + Extension;
String ReplacePattern = Tools.GenerateReplacePattern();
//File.WriteAllBytes(FileName, FileData);
RegisterFile(ElementPtr, FileName, true, ReplacePattern, FileData, IdealName);
AttributeValue = ReplacePattern;
break;
case AttributeType.TYPE_ID_REF:
int StringIdTableOffset = tools.ReadInt32(TreeTable);
IDTable.Seek(StringIdTableOffset, SeekOrigin.Begin);
int LoopbackPtr = tools.ReadInt32(IDTable);
int StringPtr = tools.ReadIntAt(TreeTable, LoopbackPtr);
string LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
Console.WriteLine("Loopback: " + LoopbackAttribute +" "+ LoopbackPtr.ToString("X")+" ("+ElementPtr.ToString("X")+")");
AttributeValue = Tools.ReadString(IDTable);
RegisterFile(LoopbackPtr, AttributeValue.ToString(), false);
sz = tools.ReadInt32(TreeTable);
Console.WriteLine("ID Ref: " + StringIdTableOffset + " sz: " + sz);
break;
case AttributeType.TYPE_ID:
StringIdTableOffset = tools.ReadInt32(TreeTable);
IDTable.Seek(StringIdTableOffset + 4, SeekOrigin.Begin);
AttributeValue = Tools.ReadString(IDTable);
sz = tools.ReadInt32(TreeTable);
Console.WriteLine("ID : " + StringIdTableOffset + " sz: " + sz);
break;
case AttributeType.TYPE_ID_HASH_REF:
int IntIdTableOffset = tools.ReadInt32(TreeTable);
HashIDTable.Seek(IntIdTableOffset, SeekOrigin.Begin);
LoopbackPtr = tools.ReadInt32(HashIDTable);
StringPtr = tools.ReadIntAt(TreeTable, LoopbackPtr);
int IDValue = tools.ReadInt32(HashIDTable);
LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
Console.WriteLine("Int Loopback: " + LoopbackAttribute + " " + LoopbackPtr.ToString("X", CultureInfo.InvariantCulture) + " (" + ElementPtr.ToString("X") + ")");
AttributeValue = IDValue.ToString("X8", CultureInfo.InvariantCulture);
RegisterFile(LoopbackPtr, AttributeValue.ToString(), false);
sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Hash Ref: " + IntIdTableOffset + " sz: " + sz);
break;
case AttributeType.TYPE_ID_HASH:
IntIdTableOffset = tools.ReadInt32(TreeTable);
HashIDTable.Seek(IntIdTableOffset + 4, SeekOrigin.Begin);
IDValue = tools.ReadInt32(HashIDTable);
AttributeValue = IDValue.ToString("X8", CultureInfo.InvariantCulture);
sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Hash Id: " + IntIdTableOffset + " sz: " + sz);
break;
case AttributeType.TYPE_NONE:
default:
new NotImplementedException("UNKNOWN TYPE @ " + TreeTable.Position);
break;
};
AddTypingInfo(ElementName + ":" + AttributeName, Type.ToString());
Console.WriteLine(AttributeName + "=" + AttributeValue.ToString());
XMLWriter.WriteAttributeString(AttributeName, AttributeValue.ToString());
XMLWriter.Flush();
}
public void ReadElements()
{
Int64 ElementLocation = TreeTable.Position;
int ElementPtr = tools.ReadInt32(TreeTable);
int NumAttributes = tools.ReadInt32(TreeTable);
int ParentPtr = tools.ReadInt32(TreeTable);
int PrevSibling = tools.ReadInt32(TreeTable);
int NextSibling = tools.ReadInt32(TreeTable);
int FirstChild = tools.ReadInt32(TreeTable);
int LastChild = tools.ReadInt32(TreeTable);
String ElementName = Tools.ReadStringAt(StringTable, ElementPtr);
Console.WriteLine("Creating Element: " + ElementName);
Console.WriteLine("Attribute Count: " + NumAttributes);
Console.WriteLine("ParentPtr: " + ParentPtr);
Console.WriteLine("PrevSibling: " + PrevSibling);
Console.WriteLine("NextSibling: " + NextSibling);
Console.WriteLine("FirstChild: " + FirstChild);
Console.WriteLine("LastChild: " + LastChild);
XMLWriter.WriteStartElement(ElementName);
if(NumAttributes > 0)
{
for (int i = 0; i < NumAttributes; i++)
{
ReadAttribute(ElementName, ElementLocation);
}
}
if (FirstChild != -1)
{
TreeTable.Seek(FirstChild, SeekOrigin.Begin);
ReadElements();
}
XMLWriter.WriteEndElement();
XMLWriter.Flush();
if (NextSibling != -1)
{
TreeTable.Seek(NextSibling, SeekOrigin.Begin);
ReadElements();
}
}
}
};