From 308edb6c3c210cd5b35a20cbfe37969560d2ad53 Mon Sep 17 00:00:00 2001
From: Li
Date: Wed, 7 Sep 2022 17:38:41 +1200
Subject: [PATCH] Add support for reading RCO symbol files (.rcd)
---
CXMLCli/CXMLBuilder.cs | 17 +-
CXMLCli/CXMLCli.csproj | 1 +
CXMLCli/CXMLCli.csproj.user | 3 +-
CXMLCli/CXMLReader.cs | 1626 +++++++++++++++++------------------
CXMLCli/CXMLSymbols.cs | 88 ++
CXMLCli/GimConv.cs | 52 +-
CXMLCli/Program.cs | 229 +++--
CXMLCli/Tools.cs | 5 +-
8 files changed, 1086 insertions(+), 935 deletions(-)
create mode 100644 CXMLCli/CXMLSymbols.cs
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)