diff --git a/CXMLCli/CXMLBuilder.cs b/CXMLCli/CXMLBuilder.cs index dc90a4a..ac5683d 100644 --- a/CXMLCli/CXMLBuilder.cs +++ b/CXMLCli/CXMLBuilder.cs @@ -35,7 +35,6 @@ namespace CXMLDecompiler MemoryStream FileTable; Boolean IsInitalized = false; - public Boolean HashStrings = false; String SilicaTypingInformation = ""; @@ -378,11 +377,7 @@ namespace CXMLDecompiler 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 hashId = Int32.Parse(CXMLSymbols.LookupId(attribute.Value), NumberStyles.HexNumber, CultureInfo.InvariantCulture); int HashTableOffset = AddGetHashTable(hashId); int HashTableSize = 4; tools.WriteInt32(WorkRam, HashTableOffset); @@ -438,9 +433,7 @@ namespace CXMLDecompiler Console.WriteLine("ID : " + 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 hash = Int32.Parse(CXMLSymbols.LookupId(attribute.Value), NumberStyles.HexNumber, CultureInfo.InvariantCulture); int HashIdTableOffset = AddGetHashIdTable(hash, Convert.ToInt32(TreeTable.Position)); tools.WriteInt32(WorkRam, HashIdTableOffset); tools.WriteInt32(WorkRam, 0x00); @@ -448,9 +441,7 @@ namespace CXMLDecompiler Console.WriteLine("Hash ID REF offset: " + HashIdTableOffset + " 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); + hash = Int32.Parse(CXMLSymbols.LookupId(attribute.Value), NumberStyles.HexNumber, CultureInfo.InvariantCulture); HashIdTableOffset = AddGetHashIdTable(hash, -1); tools.WriteInt32(WorkRam, HashIdTableOffset); @@ -468,7 +459,7 @@ namespace CXMLDecompiler 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; diff --git a/CXMLCli/CXMLCli.csproj b/CXMLCli/CXMLCli.csproj index d50b2b6..5ff76d5 100644 --- a/CXMLCli/CXMLCli.csproj +++ b/CXMLCli/CXMLCli.csproj @@ -96,6 +96,7 @@ + diff --git a/CXMLCli/CXMLCli.csproj.user b/CXMLCli/CXMLCli.csproj.user index 6f7e643..5bbaa95 100644 --- a/CXMLCli/CXMLCli.csproj.user +++ b/CXMLCli/CXMLCli.csproj.user @@ -1,7 +1,8 @@  - PvrResource.cxml -ps3 -le -f -d + + C:\Users\Li\Documents\git\cxml-decompiler\CXMLCli\bin\x64\Debug \ No newline at end of file diff --git a/CXMLCli/CXMLReader.cs b/CXMLCli/CXMLReader.cs index f84bdd1..3086cb6 100644 --- a/CXMLCli/CXMLReader.cs +++ b/CXMLCli/CXMLReader.cs @@ -1,107 +1,105 @@ -using Ionic.Zlib; -using General; +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; +using System.Collections.Generic; +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; - } +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 SilicaTypingInformationList = new List(); - - 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 FileList = new List(); - - 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(); + + + String MainDir = ""; + String FileDir = ""; + String XMLFilename = ""; + String MagicNumber = ""; + + List SilicaTypingInformationList = new List(); + + 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 FileList = new List(); + + XmlWriter XMLWriter; + + public bool ps3 = false; + public bool ProcessFiles = false; + public bool NoRecursive = false; + public void Init(string path, string outPath, 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; @@ -110,265 +108,265 @@ namespace CXMLDecompiler 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) + } + + 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(); + 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); + MainDir = Path.GetDirectoryName(outPath); + FileDir = Path.Combine(MainDir, Path.GetFileNameWithoutExtension(outPath) + "_files"); + XMLFilename = Path.GetFileName(outPath); + + IsInitalized = true; + + return; } - 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() + + public void Term() { - if (ps3) - return tools.ReadIntAt(InfoFile, 0x30); - else - return tools.ReadIntAt(InfoFile, 0x48); - } - - public int GetFileTableSize() + 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() { - if (ps3) - return tools.ReadIntAt(InfoFile, 0x34); + 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, 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; - } + 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 @@ -379,116 +377,110 @@ namespace CXMLDecompiler { 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(); - + } + 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, String XMLOutputFile) + { + + if (!IsInitalized) + Init(CXMLFile, XMLOutputFile); + + 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) + Console.WriteLine("Resolving Patterns ..."); + XMLData = XMLData.Replace(MagicReplacePattern, SilicaTypingInformation); + + foreach (LoopbackHandler lpHandler in FileList) { if (lpHandler.ReplacePattern != null && lpHandler.OldFileName != null) { @@ -504,158 +496,146 @@ namespace CXMLDecompiler string newPath = Path.ChangeExtension(Path.Combine(folderPath, lpHandler.FileName), extension); - if (!Directory.Exists(folderPath)) - Directory.CreateDirectory(folderPath); + if (!Directory.Exists(Path.GetDirectoryName(newPath))) + Directory.CreateDirectory(Path.GetDirectoryName(newPath)); - 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); - } + File.WriteAllBytes(newPath, fileData); + string XMLRelNewPath = Path.Combine(Path.GetFileName(FileDir), "original", Path.GetFileName(newPath)); + 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 (!Directory.Exists(Path.GetDirectoryName(oldName))) + Directory.CreateDirectory(Path.GetDirectoryName(oldName)); + + File.WriteAllBytes(oldName, fileData); + + string xmlRelNewPath = Path.Combine(Path.GetFileName(FileDir), "original", Path.GetFileName(oldName)); + Console.WriteLine("Resolved " + replacePattern + " => " + xmlRelNewPath); + XMLData = XMLData.Replace(replacePattern, xmlRelNewPath); + 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; - } + } + + } + + 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"); + if (!Directory.Exists(DirectoryName)) + Directory.CreateDirectory(DirectoryName); + + try + { + string outputXML = Path.ChangeExtension(Path.GetFileNameWithoutExtension(FileName), ".xml"); + CXMLReader cxmlParser = new CXMLReader(); + cxmlParser.Init(FileName, Path.Combine(DirectoryName, outputXML)); + cxmlParser.ProcessFiles = this.ProcessFiles; + cxmlParser.DecompileCXML(FileName, outputXML); + } + 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") + { + String DirectoryName = Path.Combine(FileDir, "converted", "GIMtoPNG"); + + if (!Directory.Exists(DirectoryName)) + Directory.CreateDirectory(DirectoryName); + + String OutputGim = Path.Combine(DirectoryName, Path.GetFileName(Path.ChangeExtension(FileName, "png"))); + GimConv.ConvertGimToPng(FileName, OutputGim); + } + 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) @@ -668,238 +648,236 @@ namespace CXMLDecompiler 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); + } + + 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 IntList = new List(); - - 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 StrList = new List(); - - 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); + AttributeValue = FloatStr; + sz = tools.ReadInt32(TreeTable); + Console.WriteLine("Float: " + AttributeValue.ToString() + " 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(); - } - - } - - } -}; + 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 = CXMLSymbols.LookupKey(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 IntList = new List(); + + 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 StrList = new List(); + + 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(); + + 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 = CXMLSymbols.LookupKey(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 = CXMLSymbols.LookupKey(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(); + } + + } + + } +}; diff --git a/CXMLCli/CXMLSymbols.cs b/CXMLCli/CXMLSymbols.cs new file mode 100644 index 0000000..08d70ab --- /dev/null +++ b/CXMLCli/CXMLSymbols.cs @@ -0,0 +1,88 @@ +using General; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; + +namespace CXMLDecompiler +{ + public static class CXMLSymbols + { + private static Dictionary Symbols = new Dictionary(); + + public static string LookupKey(string key) + { + if (!Symbols.ContainsKey(key.ToLowerInvariant())) + return key.ToLowerInvariant(); + else + return Symbols[key.ToLowerInvariant()]; + } + + public static string LookupId(string id) + { + foreach (KeyValuePair Symbol in Symbols) + { + if (Symbol.Value == id) + { + return Symbol.Key; + } + } + + if (id.Length == 8) + { + try + { + Int32.Parse(id, NumberStyles.HexNumber); + return id; + } + catch (Exception) { }; + } + + + return Tools.GenerateShortHash(Encoding.UTF8.GetBytes(id)); + + } + + public static void Init(string SymbolFile) + { + string[] lines = File.ReadAllText(SymbolFile).Replace("\r", "").Split('\n'); + + foreach(string line in lines) + { + if (line.StartsWith("#")) + continue; + if (line == "") + continue; + + if(line.Contains(' ')) + { + string key = ""; + string id = ""; + + foreach (string opt in line.Split(' ')) + { + if (opt.Contains(":")) + { + string[] kv = opt.Split(':'); + if (kv[0].ToLowerInvariant().StartsWith("key")) + key = kv[1]; + if (kv[0].ToLowerInvariant().StartsWith("id")) + id = kv[1]; + } + } + + if (key.Contains("(")) + key = key.Substring(0, key.IndexOf("(")); + if (id.Contains(",")) + id = id.Substring(0, id.IndexOf(",")); + + Console.WriteLine("Reading Symbol .. key: " + key + " id: " + id); + + Symbols.Add(key.ToLowerInvariant(), id); + } + } + } + } +} diff --git a/CXMLCli/GimConv.cs b/CXMLCli/GimConv.cs index 23ebefd..542a069 100644 --- a/CXMLCli/GimConv.cs +++ b/CXMLCli/GimConv.cs @@ -1,15 +1,46 @@ using Ionic.Zip; using System; +using System.Diagnostics; using System.IO; using System.Net; - +using System.Reflection; + namespace CXMLDecompiler { class GimConv - { + { + + public static string GIMCONV_FOLDER = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "GimConv"); static WebClient wc = new WebClient(); static bool DownloadCompleted = true; + + public static void ConvertGimToPng(string inputGim, string outputGim) + { + if (HasGimConv()) + { + if (!Path.IsPathRooted(inputGim)) + inputGim = Path.Combine(Environment.CurrentDirectory, inputGim); + + if (!Path.IsPathRooted(outputGim)) + outputGim = Path.Combine(Environment.CurrentDirectory, outputGim); + + Console.WriteLine("Decoding GIM."); + Process Proc = new Process(); + Proc.StartInfo.FileName = Path.Combine(GIMCONV_FOLDER, "GimConv.exe"); + Proc.StartInfo.Arguments = "\"" + inputGim + "\" -o \"" + outputGim + "\""; + Proc.StartInfo.RedirectStandardOutput = true; + Proc.StartInfo.RedirectStandardError = true; + Proc.StartInfo.UseShellExecute = false; + Proc.Start(); + Proc.WaitForExit(); + Console.Write(Proc.StandardOutput.ReadToEnd()); + } + } + public static bool HasGimConv() + { + return File.Exists(Path.Combine(GIMCONV_FOLDER, "GimConv.exe")); + } public static void DownloadGimConv() { wc.DownloadProgressChanged += Wc_DownloadProgressChanged; @@ -25,24 +56,27 @@ namespace CXMLDecompiler Console.Write("\r\n"); MemoryStream zipStream = new MemoryStream(e.Result); ZipFile zip = ZipFile.Read(zipStream); - foreach(ZipEntry zEntry in zip.Entries) + foreach(ZipEntry zEntry in zip.Entries) // Read downloaded zip and extract stuff relating to GimConv . { string filename = Path.GetFileName(zEntry.FileName); - if (filename == "msvcp71.dll" || filename == "msvcr71.dll" || zEntry.FileName.Contains("GimConv")) + if (filename == "msvcp71.dll" || filename == "msvcr71.dll" || zEntry.FileName.Contains("GimConv")) // if it is a required DLL or inside the GimConv folder { string outputFilename = zEntry.FileName; - if (outputFilename.Contains("GimConv")) - outputFilename = outputFilename.Substring(outputFilename.IndexOf("GimConv")); - else - outputFilename = Path.Combine("GimConv", filename); + if (outputFilename.Contains("GimConv")) // if the filename is inside the GimConv folder + outputFilename = outputFilename.Substring(outputFilename.IndexOf("GimConv") + "GimConv".Length); // Extract filename after the "GimConv/" part + outputFilename = outputFilename.Replace("/", "\\"); + outputFilename = Path.Combine(GIMCONV_FOLDER, outputFilename); // set output path to GimConv folder Console.WriteLine("Extracting: " + outputFilename); + + // If folder is directory, create it if (zEntry.IsDirectory) { Directory.CreateDirectory(outputFilename); continue; } + // Extract the file to output path FileStream fs = File.Open(outputFilename, FileMode.CreateNew, FileAccess.ReadWrite); zEntry.Extract(fs); fs.Close(); @@ -51,7 +85,7 @@ namespace CXMLDecompiler zip.Dispose(); zipStream.Dispose(); - File.AppendAllText("GimConv\\GimConv.cfg", "option -psvrgba8888 {\r\n format_endian = little\r\n format_style = psp\r\n image_format = rgba8888\r\n pixel_order = normal\r\n pixel_channel = rgba\r\n limit_image_width = 4096\r\n limit_image_height = 4096\r\n}\r\noption -psvindex4 {\r\n format_endian = little\r\n format_style = psp\r\n image_format = index4\r\n pixel_order = normal\r\n pixel_channel = rgba\r\n limit_image_width = 4096\r\n limit_image_height = 4096\r\n}\r\noption -psvindex8 {\r\n format_endian = little\r\n format_style = psp\r\n image_format = index8\r\n pixel_order = normal\r\n pixel_channel = rgba\r\n limit_image_width = 4096\r\n limit_image_height = 4096\r\n}"); + File.AppendAllText(Path.Combine(GIMCONV_FOLDER, "GimConv.cfg"), "option -psvrgba8888 {\r\n format_endian = little\r\n format_style = psp\r\n image_format = rgba8888\r\n pixel_order = normal\r\n pixel_channel = rgba\r\n limit_image_width = 4096\r\n limit_image_height = 4096\r\n}\r\noption -psvindex4 {\r\n format_endian = little\r\n format_style = psp\r\n image_format = index4\r\n pixel_order = normal\r\n pixel_channel = rgba\r\n limit_image_width = 4096\r\n limit_image_height = 4096\r\n}\r\noption -psvindex8 {\r\n format_endian = little\r\n format_style = psp\r\n image_format = index8\r\n pixel_order = normal\r\n pixel_channel = rgba\r\n limit_image_width = 4096\r\n limit_image_height = 4096\r\n}"); DownloadCompleted = true; } diff --git a/CXMLCli/Program.cs b/CXMLCli/Program.cs index b295647..12b49c2 100644 --- a/CXMLCli/Program.cs +++ b/CXMLCli/Program.cs @@ -2,30 +2,59 @@ using General; using Ionic.Zlib; using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; namespace CXMLCli { class Program { - static bool HasArg(string argsfull, string argcheck) + + static string InputFilePath; + static string OutputFilePath; + static bool WaitExit = false; + static bool ForcePs3 = false; + static Endianness FileEndianness = Endianness.UNCHANGED; + static bool Check = true; + + static int ArgIndex(string[] args, string argshort, string arglong) + { + for (int i = 0; i < args.Length; i++) + { + string arg = args[i]; + if (arg.ToLowerInvariant() == argshort.ToLowerInvariant() || arg.ToLowerInvariant() == arglong.ToLowerInvariant()) + { + return i; + } + } + return -1; + } + static bool HasArg(string[] args, string argcheck) { - string[] args = argsfull.Split(' '); foreach(string arg in args) { - if(arg == argcheck) + if(arg.ToLowerInvariant() == argcheck.ToLowerInvariant()) { return true; } } - return false; } + + static string GetTablesFolder() + { + string tablesFolder = Path.GetFileNameWithoutExtension(OutputFilePath) + "_tables"; + if (!Directory.Exists(tablesFolder)) + Directory.CreateDirectory(tablesFolder); + return tablesFolder; + } static int Main(string[] args) { - // Do you have gimconv? + // Check if the user has GimConv and download it if not present + // (only do this on windows) bool windowsNT = Environment.OSVersion.Platform.Equals(PlatformID.Win32NT); bool windows32 = Environment.OSVersion.Platform.Equals(PlatformID.Win32Windows); @@ -34,23 +63,23 @@ namespace CXMLCli if (windowsNT || windows32 || windows32S || windowsCE) { - if (!File.Exists(Path.Combine("GimConv", "GimConv.exe"))) - { - GimConv.DownloadGimConv(); // Politely ask sony to give it to us. - } - } - else - { - Console.WriteLine("NOTE: GimConv is windows binary, so you cant use it on this OS!\n.GIM Decoding will be disabled!"); - } + if (!GimConv.HasGimConv()) + { + GimConv.DownloadGimConv(); // Politely ask sony to give it to us. + } + } + else + { + Console.WriteLine("NOTE: GimConv is windows binary (provided by Sony Computer Entertainment), so you cant use it on this OS!\n.GIM Decoding will be disabled!"); + } - bool Check = true; if (args.Length == 0) { Console.WriteLine("-- CXML Decompiler --"); Console.WriteLine("Required Arguments:"); - Console.WriteLine("\t"); + Console.WriteLine("\t-i --input Input file or folder"); + Console.WriteLine("\t-o --output Output file or folder"); Console.WriteLine("Optional Arguments:"); Console.WriteLine("\t-iv --is-vag File is HE-VAG audio and NOT CXML"); Console.WriteLine("\t-dc --decompress Decompress .Z File"); @@ -74,182 +103,208 @@ namespace CXMLCli Console.WriteLine("\t-w --wait-exit Wait for keypress before exiting"); Console.WriteLine("\t-d --decompile Decompile CXML to XML."); Console.WriteLine("\t-c --compile Compile XML to CXML"); - Console.WriteLine("\t-h --hash-string When Compiling, Generate new hashes"); - Console.WriteLine("Example Decompile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " app.info -d -p"); - Console.WriteLine("Example Compile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " app.xml app.info -c"); + Console.WriteLine("\t-s --symbols Use Symbol File (.rcd)"); + Console.WriteLine("Example Decompile: -i " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " common_resource.rco -o common_resource.xml -d -p"); + Console.WriteLine("Example Compile: -i " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " common_resource.xml -o common_resource.rco -c"); Console.WriteLine("Default functonality is to Decompile,\nThis is canceled if any other arguments passed."); return 0; } - String ArgsFull = String.Join(" ", args); - String ProcessFilePath = args[0]; - - bool ForcePs3 = false; - Endianness FileEndianness = Endianness.UNCHANGED; - if (args.Length == 1) { - ArgsFull += " -d -p -w"; + List argsCopy = args.ToList(); + + argsCopy.AddRange(new string[] { "--input", args[0], "--output", Path.ChangeExtension(args[0], ".xml"), "--decompile", "--process-files", "--wait-exit" }); + + if (File.Exists(Path.ChangeExtension(args[0], ".rcd"))) + argsCopy.AddRange(new string[] { "--symbols", Path.ChangeExtension(args[0], ".rcd") }); + + args = argsCopy.ToArray(); } - if (HasArg(ArgsFull, "-le") || HasArg(ArgsFull, "--little-endian")) + if(HasArg(args, "-i") || HasArg(args, "--input")) + { + int i = ArgIndex(args, "-i", "--input"); + InputFilePath = args[i + 1]; + } + else + { + Console.Error.WriteLine("Missing required -i or --input argument."); + return 1; + } + + if (HasArg(args, "-o") || HasArg(args, "--output")) + { + int i = ArgIndex(args, "-o", "--output"); + OutputFilePath = args[i + 1]; + } + else + { + Console.Error.WriteLine("Missing required -o or --output."); + return 1; + } + + if (HasArg(args, "-le") || HasArg(args, "--little-endian")) { FileEndianness = Endianness.LITTLE_ENDIAN; } - if (HasArg(ArgsFull, "-be") || HasArg(ArgsFull, "--big-endian")) + if (HasArg(args, "-be") || HasArg(args, "--big-endian")) { FileEndianness = Endianness.LITTLE_ENDIAN; } - if (HasArg(ArgsFull, "-ps3") || HasArg(ArgsFull, "--playstation-3")) + if (HasArg(args, "-ps3") || HasArg(args, "--playstation-3")) { ForcePs3 = true; } - if (HasArg(ArgsFull, "-iv") || HasArg(ArgsFull, "--is-vag")) + if (HasArg(args, "-iv") || HasArg(args, "--is-vag")) { - byte[] WaveData = VAG.VAGAudio.Vag2Wav(ProcessFilePath); - string FileName = Path.GetFileNameWithoutExtension(ProcessFilePath) + "-" + VAG.VAGAudio.GetFilename(ProcessFilePath) + ".wav"; - Console.WriteLine("Writing "+FileName); - File.WriteAllBytes(FileName, WaveData); + byte[] WaveData = VAG.VAGAudio.Vag2Wav(InputFilePath); + Console.WriteLine("Writing "+ OutputFilePath); + File.WriteAllBytes(OutputFilePath, WaveData); return 0; } - if (HasArg(ArgsFull, "-f") || HasArg(ArgsFull, "--force")) + if (HasArg(args, "-f") || HasArg(args, "--force")) { Check = false; } - if (HasArg(ArgsFull, "-dc") || HasArg(ArgsFull, "--decompress")) + if (HasArg(args, "-dc") || HasArg(args, "--decompress")) { - Console.WriteLine("Decompressing " + ProcessFilePath); - Byte[] FileData = File.ReadAllBytes(ProcessFilePath); + Console.WriteLine("Decompressing " + InputFilePath); + Byte[] FileData = File.ReadAllBytes(InputFilePath); Byte[] DecompressedData = ZlibStream.UncompressBuffer(FileData); string Extension = Tools.GetFileExtension(DecompressedData); - string OutPath = Path.ChangeExtension(ProcessFilePath, Extension); - File.WriteAllBytes(OutPath, DecompressedData); + File.WriteAllBytes(OutputFilePath, DecompressedData); return 0; } - if (HasArg(ArgsFull, "-cc") || HasArg(ArgsFull, "--compress")) + if (HasArg(args, "-cc") || HasArg(args, "--compress")) { - Console.WriteLine("Compressing " + ProcessFilePath); - Byte[] FileData = File.ReadAllBytes(ProcessFilePath); + Console.WriteLine("Compressing " + InputFilePath); + Byte[] FileData = File.ReadAllBytes(InputFilePath); Byte[] CompressedData = ZlibStream.CompressBuffer(FileData); string Extension = Tools.GetFileExtension(CompressedData); - string OutPath = Path.ChangeExtension(ProcessFilePath, Extension); - File.WriteAllBytes(OutPath, CompressedData); + File.WriteAllBytes(OutputFilePath, CompressedData); return 0; } CXMLReader cxmlParser = new CXMLReader(); - if(!HasArg(ArgsFull, "-c") && !HasArg(ArgsFull, "--compile")) + if(!HasArg(args, "-c") && !HasArg(args, "--compile")) // If not Compiling { - Console.WriteLine("Initalizing: " + ProcessFilePath); - cxmlParser.Init(ProcessFilePath, Check, ForcePs3, FileEndianness); + Console.WriteLine("Initalizing: " + InputFilePath); + cxmlParser.Init(InputFilePath, OutputFilePath, Check, ForcePs3, FileEndianness); + } + + if (HasArg(args, "-dt") || HasArg(args, "--dump-tables")) + { + List argsCopy = args.ToList(); + + argsCopy.AddRange(new string[] { "--dump-tree", "--dump-id", "--dump-hash-id", "--dump-string", "--dump-wstring", "--dump-hash", "--dump-int-array", "--dump-float-array", "--dump-file" }); + + args = argsCopy.ToArray(); } - - - if (HasArg(ArgsFull, "-dt") || HasArg(ArgsFull, "--dump-tables")) + if (HasArg(args, "-tt") || HasArg(args, "--dump-tree")) { - ArgsFull += " --dump-tree --dump-id --dump-hash-id --dump-string --dump-wstring --dump-hash --dump-int-array --dump-float-array --dump-file "; - } - if (HasArg(ArgsFull, "-tt") || HasArg(ArgsFull, "--dump-tree")) - { Console.WriteLine("Dumping tree table."); - File.WriteAllBytes("tree-table.bin", cxmlParser.GetTreeTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "tree-table.bin"), cxmlParser.GetTreeTable()); } - if (HasArg(ArgsFull, "-idt") || HasArg(ArgsFull, "--dump-id")) + if (HasArg(args, "-idt") || HasArg(args, "--dump-id")) { + Console.WriteLine("Dumping ID table."); - File.WriteAllBytes("id-table.bin", cxmlParser.GetIDTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "id-table.bin"), cxmlParser.GetIDTable()); } - if (HasArg(ArgsFull, "-iht") || HasArg(ArgsFull, "--dump-hash-id")) + if (HasArg(args, "-iht") || HasArg(args, "--dump-hash-id")) { Console.WriteLine("Dumping hash ID table."); - File.WriteAllBytes("hash-id-table.bin", cxmlParser.GetHashIDTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "hash-id-table.bin"), cxmlParser.GetHashIDTable()); } - if (HasArg(ArgsFull, "-st") || HasArg(ArgsFull, "--dump-string")) + if (HasArg(args, "-st") || HasArg(args, "--dump-string")) { Console.WriteLine("Dumping string table."); - File.WriteAllBytes("string-table.bin",cxmlParser.GetStringTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "string-table.bin"),cxmlParser.GetStringTable()); } - if (HasArg(ArgsFull, "-wt") || HasArg(ArgsFull, "--dump-wstring")) + if (HasArg(args, "-wt") || HasArg(args, "--dump-wstring")) { Console.WriteLine("Dumping wstring table."); - File.WriteAllBytes("wstring-table.bin", cxmlParser.GetWStringTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "wstring-table.bin"), cxmlParser.GetWStringTable()); } - if (HasArg(ArgsFull, "-ht") || HasArg(ArgsFull, "--dump-hash")) + if (HasArg(args, "-ht") || HasArg(args, "--dump-hash")) { Console.WriteLine("Dumping hash table."); - File.WriteAllBytes("hash-table.bin", cxmlParser.GetHashTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "hash-table.bin"), cxmlParser.GetHashTable()); } - if (HasArg(ArgsFull, "-iat") || HasArg(ArgsFull, "--dump-int-array")) + if (HasArg(args, "-iat") || HasArg(args, "--dump-int-array")) { Console.WriteLine("Dumping int array table."); - File.WriteAllBytes("int-array-table.bin", cxmlParser.GetIntArrayTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "int-array-table.bin"), cxmlParser.GetIntArrayTable()); } - if (HasArg(ArgsFull, "-fat") || HasArg(ArgsFull, "--dump-float-array")) + if (HasArg(args, "-fat") || HasArg(args, "--dump-float-array")) { Console.WriteLine("Dumping float array table."); - File.WriteAllBytes("float-array-table.bin", cxmlParser.GetFloatArrayTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "float-array-table.bin"), cxmlParser.GetFloatArrayTable()); } - - if (HasArg(ArgsFull, "-ft") || HasArg(ArgsFull, "--dump-tree")) + if (HasArg(args, "-ft") || HasArg(args, "--dump-tree")) { Console.WriteLine("Dumping file table."); - File.WriteAllBytes("file-table.bin", cxmlParser.GetFileTable()); + File.WriteAllBytes(Path.Combine(GetTablesFolder(), "file-table.bin"), cxmlParser.GetFileTable()); } - if (HasArg(ArgsFull, "-p") || HasArg(ArgsFull, "--process-files")) + if (HasArg(args, "-p") || HasArg(args, "--process-files")) { cxmlParser.ProcessFiles = true; } - if (HasArg(ArgsFull, "-w") || HasArg(ArgsFull, "--wait-exit")) + if (HasArg(args, "-w") || HasArg(args, "--wait-exit")) { - cxmlParser.WaitExit = true; + WaitExit = true; } - if (HasArg(ArgsFull, "-nr") || HasArg(ArgsFull, "--no-recursive")) + if (HasArg(args, "-nr") || HasArg(args, "--no-recursive")) { cxmlParser.NoRecursive = true; } - if (HasArg(ArgsFull, "-d") || HasArg(ArgsFull, "--decompile") && !HasArg(ArgsFull, "-dt")) + if(HasArg(args, "-s") || HasArg(args, "--symbols")) + { + int i = ArgIndex(args, "-s", "--symbols"); + CXMLSymbols.Init(args[i + 1]); + } + + if (HasArg(args, "-d") || HasArg(args, "--decompile") && !HasArg(args, "-dt")) { Console.WriteLine("Decompiling."); - cxmlParser.DecompileCXML(ProcessFilePath); + cxmlParser.DecompileCXML(InputFilePath, OutputFilePath); Console.WriteLine("\n\nDECOMPILATION COMPLETE!"); - if(cxmlParser.WaitExit) + if(WaitExit) Console.ReadKey(); } - else if (HasArg(ArgsFull, "-c") || HasArg(ArgsFull, "--compile")) + else if (HasArg(args, "-c") || HasArg(args, "--compile")) { - Console.WriteLine("Compiling: " + ProcessFilePath); + Console.WriteLine("Compiling: " + InputFilePath); CXMLBuilder builder = new CXMLBuilder(); - if (HasArg(ArgsFull, "-h") || HasArg(ArgsFull, "----hash-string")) - builder.HashStrings = true; - builder.Init(ProcessFilePath, args[1]); - builder.BuildCXML(ProcessFilePath, args[1]); + builder.BuildCXML(InputFilePath, OutputFilePath); Console.WriteLine("\n\nCOMPILATION COMPLETE!"); - if (cxmlParser.WaitExit) + if (WaitExit) Console.ReadKey(); } diff --git a/CXMLCli/Tools.cs b/CXMLCli/Tools.cs index 321022b..9b321e6 100644 --- a/CXMLCli/Tools.cs +++ b/CXMLCli/Tools.cs @@ -351,7 +351,10 @@ namespace General { SHA1 sha = SHA1.Create(); byte[] ShaBytes = sha.ComputeHash(Data); - return BitConverter.ToInt32(ShaBytes, 0).ToString("X8"); + byte[] First4 = new byte[0x4]; + Array.Copy(ShaBytes, 0, First4, 0, First4.Length); + First4 = First4.Reverse().ToArray(); + return BitConverter.ToInt32(First4, 0).ToString("X8").ToLowerInvariant(); } public static String ReadString(Stream ms, int limit = -1)