Add support for ps3 cxml

This commit is contained in:
Li 2022-06-19 16:29:29 +12:00
parent a6fcc971a9
commit 0aa6de7b9c
8 changed files with 681 additions and 467 deletions

55
CXMLCli/CXML.cs Normal file
View File

@ -0,0 +1,55 @@
using System;
namespace CXML
{
public enum AttributeTypePs3
{
TYPE_NONE = 0,
TYPE_INT = 1,
TYPE_FLOAT = 2,
TYPE_STRING = 3,
TYPE_INTEGER_ARRAY = 4,
TYPE_FLOAT_ARRAY = 5,
TYPE_FILE = 6,
TYPE_ID_REF = 7,
TYPE_ID = 8,
};
public enum AttributeType
{
TYPE_NONE = 0,
TYPE_INT = 1,
TYPE_FLOAT = 2,
TYPE_STRING = 3,
TYPE_WSTRING = 4,
TYPE_HASH = 5,
TYPE_INTEGER_ARRAY = 6,
TYPE_FLOAT_ARRAY = 7,
TYPE_FILE = 8,
TYPE_ID_REF = 9,
TYPE_ID = 10,
TYPE_ID_HASH_REF = 11,
TYPE_ID_HASH = 12
};
enum Version
{
PS3 = 0x10010000,
PSVITA = 0x110,
PSM = 0x100,
UNKNOWN
};
public class TypingInformation
{
public string key;
public string value;
}
public class LoopbackHandler
{
public String FileName;
public String OldFileName;
public String ReplacePattern;
public byte[] FileData;
public Int64 FilePointer;
}
}

View File

@ -16,15 +16,20 @@ namespace CXMLDecompiler
String MainDir = ""; String MainDir = "";
String XMLFilename = ""; String XMLFilename = "";
String MagicNumber = ""; String MagicNumber = "";
Endainness FileEndainness;
bool ps3;
Tools tools;
Int32 Version; Int32 Version;
FileStream InfoFile; FileStream InfoFile;
MemoryStream TreeTable; MemoryStream TreeTable;
MemoryStream StringIDTable; MemoryStream IDTable;
MemoryStream IntIDTable;
MemoryStream StringTable;
MemoryStream CharTable;
MemoryStream HashIDTable; MemoryStream HashIDTable;
MemoryStream StringTable;
MemoryStream WStringTable;
MemoryStream HashTable;
MemoryStream IntArrayTable; MemoryStream IntArrayTable;
MemoryStream FloatArrayTable; MemoryStream FloatArrayTable;
MemoryStream FileTable; MemoryStream FileTable;
@ -32,41 +37,34 @@ namespace CXMLDecompiler
Boolean IsInitalized = false; Boolean IsInitalized = false;
public Boolean HashStrings = false; public Boolean HashStrings = false;
BinaryWriter bInfoFile;
BinaryWriter bTreeTable;
BinaryWriter bIntIDTable;
BinaryWriter bFloatArrayTable;
BinaryWriter bIntArrayTable;
BinaryWriter bHashIDTable;
BinaryWriter bStringIDTable;
String SilicaTypingInformation = ""; String SilicaTypingInformation = "";
public void Init(string XMLFile, string CxmlFile) public void Init(string XMLFile, string CxmlFile)
{ {
GetSilicaTypingInformation(XMLFile); GetSilicaTypingInformation(XMLFile);
MagicNumber = GetTypingInformation("MAGIC"); MagicNumber = GetTypingInformation("MAGIC");
Version = Int32.Parse(GetTypingInformation("VERSION"), CultureInfo.InvariantCulture); Version = Int32.Parse(GetTypingInformation("VERSION").Replace("0x", ""), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
// Determine filetype.
FileEndainness = (Endainness)Enum.Parse(typeof(Endainness), GetTypingInformation("ENDAINESS"));
ps3 = GetTypingInformation("PS3") == "true";
tools = new Tools((FileEndainness == Endainness.BIG_ENDAIN));
InfoFile = File.Open(CxmlFile, FileMode.OpenOrCreate, FileAccess.ReadWrite); InfoFile = File.Open(CxmlFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
InfoFile.SetLength(0); InfoFile.SetLength(0);
TreeTable = new MemoryStream(); TreeTable = new MemoryStream();
StringIDTable = new MemoryStream(); IDTable = new MemoryStream();
IntIDTable = new MemoryStream();
StringTable = new MemoryStream(); StringTable = new MemoryStream();
CharTable = new MemoryStream();
HashIDTable = new MemoryStream();
IntArrayTable = new MemoryStream(); IntArrayTable = new MemoryStream();
FloatArrayTable = new MemoryStream(); FloatArrayTable = new MemoryStream();
FileTable = new MemoryStream(); FileTable = new MemoryStream();
bInfoFile = new BinaryWriter(InfoFile); WStringTable = new MemoryStream();
bTreeTable = new BinaryWriter(TreeTable); HashIDTable = new MemoryStream();
bIntIDTable = new BinaryWriter(IntIDTable); HashTable = new MemoryStream();
bFloatArrayTable = new BinaryWriter(FloatArrayTable);
bIntArrayTable = new BinaryWriter(IntArrayTable);
bHashIDTable = new BinaryWriter(HashIDTable);
bStringIDTable = new BinaryWriter(StringIDTable);
XMLFilename = XMLFile; XMLFilename = XMLFile;
MainDir = Path.GetDirectoryName(XMLFilename); MainDir = Path.GetDirectoryName(XMLFilename);
@ -106,18 +104,18 @@ namespace CXMLDecompiler
public int offset; public int offset;
public string name; public string name;
} }
public class IntTableEntry public class HashTableEntry
{ {
public int offset; public int offset;
public int value; public int value;
} }
public class StringIDTableEntry public class IDTableEntry
{ {
public int offset; public int offset;
public string value; public string value;
public int loopbackOffset; public int loopbackOffset;
} }
public class IntIDTableEntry public class HashIDTableEntry
{ {
public int offset; public int offset;
public int value; public int value;
@ -131,13 +129,13 @@ namespace CXMLDecompiler
} }
List<TreeTableEntry> TreeTableEntries = new List<TreeTableEntry>(); List<TreeTableEntry> TreeTableEntries = new List<TreeTableEntry>();
List<StringTableEntry> StringTableEntries = new List<StringTableEntry>(); List<StringTableEntry> StringTableEntries = new List<StringTableEntry>();
List<StringTableEntry> CharTableEntries = new List<StringTableEntry>(); List<StringTableEntry> WStringTableEntries = new List<StringTableEntry>();
List<IntTableEntry> HashIdTableEntries = new List<IntTableEntry>(); List<HashTableEntry> HashTableEntries = new List<HashTableEntry>();
List<Int32> IntArrayTableEntries = new List<Int32>(); List<Int32> IntArrayTableEntries = new List<Int32>();
List<Single> FloatArrayTableEntries = new List<Single>(); List<Single> FloatArrayTableEntries = new List<Single>();
List<StringTableEntry> FileTableEntries = new List<StringTableEntry>(); List<StringTableEntry> FileTableEntries = new List<StringTableEntry>();
List<StringIDTableEntry> StringIDTableEntries = new List<StringIDTableEntry>(); List<IDTableEntry> IDTableEntries = new List<IDTableEntry>();
List<IntIDTableEntry> IntIDTableEntries = new List<IntIDTableEntry>(); List<HashIDTableEntry> HashIDTableEntries = new List<HashIDTableEntry>();
public int AddGetTreeTable(XmlNode node) public int AddGetTreeTable(XmlNode node)
{ {
if (!(node.NodeType == XmlNodeType.Element || node.NodeType == XmlNodeType.EndElement || node.NodeType == XmlNodeType.Attribute)) if (!(node.NodeType == XmlNodeType.Element || node.NodeType == XmlNodeType.EndElement || node.NodeType == XmlNodeType.Attribute))
@ -155,9 +153,9 @@ namespace CXMLDecompiler
return ent.offset; return ent.offset;
} }
public int AddGetIntIdTable(int value, int loopbackPtr) public int AddGetHashIdTable(int value, int loopbackPtr)
{ {
foreach (IntIDTableEntry entry in IntIDTableEntries) foreach (HashIDTableEntry entry in HashIDTableEntries)
{ {
if (entry.loopbackOffset == loopbackPtr && loopbackPtr != -1) if (entry.loopbackOffset == loopbackPtr && loopbackPtr != -1)
@ -169,27 +167,27 @@ namespace CXMLDecompiler
if (loopbackPtr == -1) if (loopbackPtr == -1)
return entry.offset; return entry.offset;
entry.loopbackOffset = loopbackPtr; entry.loopbackOffset = loopbackPtr;
long position1 = IntIDTable.Position; long position1 = HashIDTable.Position;
IntIDTable.Seek(entry.offset, SeekOrigin.Begin); HashIDTable.Seek(entry.offset, SeekOrigin.Begin);
bIntIDTable.Write(loopbackPtr); tools.WriteInt32(HashIDTable, loopbackPtr);
IntIDTable.Seek(position1, SeekOrigin.Begin); HashIDTable.Seek(position1, SeekOrigin.Begin);
return entry.offset; return entry.offset;
} }
} }
IntIDTableEntry ent = new IntIDTableEntry(); HashIDTableEntry ent = new HashIDTableEntry();
ent.value = value; ent.value = value;
ent.loopbackOffset = loopbackPtr; ent.loopbackOffset = loopbackPtr;
ent.offset = Convert.ToInt32(IntIDTable.Position); ent.offset = Convert.ToInt32(HashIDTable.Position);
IntIDTableEntries.Add(ent); HashIDTableEntries.Add(ent);
bIntIDTable.Write((int)loopbackPtr); tools.WriteInt32(HashIDTable, loopbackPtr);
bIntIDTable.Write((int)value); tools.WriteInt32(HashIDTable, value);
return ent.offset; return ent.offset;
} }
public int AddGetStringIdTable(string value, int loopbackPtr) public int AddGetIdTable(string value, int loopbackPtr)
{ {
foreach (StringIDTableEntry entry in StringIDTableEntries) foreach (IDTableEntry entry in IDTableEntries)
{ {
if (entry.loopbackOffset == loopbackPtr && loopbackPtr != -1) if (entry.loopbackOffset == loopbackPtr && loopbackPtr != -1)
{ {
@ -200,27 +198,27 @@ namespace CXMLDecompiler
if (loopbackPtr == -1) if (loopbackPtr == -1)
return entry.offset; return entry.offset;
entry.loopbackOffset = loopbackPtr; entry.loopbackOffset = loopbackPtr;
long position1 = StringIDTable.Position; long position1 = IDTable.Position;
StringIDTable.Seek(entry.offset, SeekOrigin.Begin); IDTable.Seek(entry.offset, SeekOrigin.Begin);
bStringIDTable.Write(loopbackPtr); tools.WriteInt32(IDTable, loopbackPtr);
StringIDTable.Seek(position1, SeekOrigin.Begin); IDTable.Seek(position1, SeekOrigin.Begin);
return entry.offset; return entry.offset;
} }
} }
StringIDTableEntry ent = new StringIDTableEntry(); IDTableEntry ent = new IDTableEntry();
ent.value = value; ent.value = value;
ent.loopbackOffset = loopbackPtr; ent.loopbackOffset = loopbackPtr;
ent.offset = Convert.ToInt32(StringIDTable.Position); ent.offset = Convert.ToInt32(IDTable.Position);
StringIDTableEntries.Add(ent); IDTableEntries.Add(ent);
bStringIDTable.Write(loopbackPtr); tools.WriteInt32(IDTable, loopbackPtr);
Tools.WriteStringToStream(StringIDTable, value); Tools.WriteStringToStream(IDTable, value);
StringIDTable.WriteByte(0x00); IDTable.WriteByte(0x00);
if (loopbackPtr != -1) if (loopbackPtr != -1 && !ps3)
{ {
Align(StringIDTable, 4); Align(IDTable, 4);
} }
return ent.offset; return ent.offset;
@ -257,7 +255,7 @@ namespace CXMLDecompiler
foreach (float i in value) foreach (float i in value)
{ {
bFloatArrayTable.Write((float)i); tools.WriteSingle(FloatArrayTable, i);
FloatArrayTableEntries.Add(i); FloatArrayTableEntries.Add(i);
} }
@ -279,24 +277,24 @@ namespace CXMLDecompiler
foreach (int i in value) foreach (int i in value)
{ {
bIntArrayTable.Write((int)i); tools.WriteInt32(IntArrayTable, i);
IntArrayTableEntries.Add(i); IntArrayTableEntries.Add(i);
} }
return offset; return offset;
} }
public int AddGetHashIdTable(int value) public int AddGetHashTable(int value)
{ {
foreach (IntTableEntry entry in HashIdTableEntries) foreach (HashTableEntry entry in HashTableEntries)
if (entry.value == value) if (entry.value == value)
return entry.offset/4; return entry.offset/4;
IntTableEntry ent = new IntTableEntry(); HashTableEntry ent = new HashTableEntry();
ent.value = value; ent.value = value;
ent.offset = Convert.ToInt32(HashIDTable.Position); ent.offset = Convert.ToInt32(HashTable.Position);
HashIdTableEntries.Add(ent); HashTableEntries.Add(ent);
bHashIDTable.Write((int)value); tools.WriteInt32(HashTable, value);
return ent.offset/4; return ent.offset/4;
} }
@ -316,34 +314,40 @@ namespace CXMLDecompiler
return ent.offset; return ent.offset;
} }
public int AddGetCharTable(string elementName) public int AddGetWstringTable(string elementName)
{ {
foreach (StringTableEntry entry in CharTableEntries) foreach (StringTableEntry entry in WStringTableEntries)
if (entry.name == elementName) if (entry.name == elementName)
return entry.offset; return entry.offset;
StringTableEntry ent = new StringTableEntry(); StringTableEntry ent = new StringTableEntry();
ent.name = elementName; ent.name = elementName;
ent.offset = Convert.ToInt32(CharTable.Position)/2; ent.offset = Convert.ToInt32(WStringTable.Position)/2;
CharTableEntries.Add(ent); WStringTableEntries.Add(ent);
Tools.WriteUtf16StringToStream(CharTable, elementName); Tools.WriteUtf16StringToStream(WStringTable, elementName);
CharTable.WriteByte(0x00); WStringTable.WriteByte(0x00);
CharTable.WriteByte(0x00); WStringTable.WriteByte(0x00);
return ent.offset; return ent.offset;
} }
public int ConvertAttributeTypeToInt(AttributeType type)
{
if (!ps3)
return (int) type;
else
return (int) (AttributeTypePs3)Enum.Parse(typeof(AttributeTypePs3), type.ToString());
}
public AttributeType DetermineType(string ElementName, string AttributeName) public AttributeType DetermineType(string ElementName, string AttributeName)
{ {
return (AttributeType)Int32.Parse(GetTypingInformation(ElementName + ":" + AttributeName), CultureInfo.InvariantCulture); return (AttributeType)Enum.Parse(typeof(AttributeType), GetTypingInformation(ElementName + ":" + AttributeName));
} }
public void WriteAttribute(XmlAttribute attribute, MemoryStream WorkRam, BinaryWriter bWorkRam, string ElementName) public void WriteAttribute(XmlAttribute attribute, MemoryStream WorkRam, string ElementName)
{ {
int AttributePtr = AddGetStringTable(attribute.Name); int AttributePtr = AddGetStringTable(attribute.Name);
AttributeType Type = DetermineType(ElementName, attribute.Name); AttributeType Type = DetermineType(ElementName, attribute.Name);
bWorkRam.Write(AttributePtr); tools.WriteInt32(WorkRam, AttributePtr);
bWorkRam.Write((int)Type); tools.WriteInt32(WorkRam, ConvertAttributeTypeToInt(Type));
Console.WriteLine("AttributeType: " + Type.ToString()); Console.WriteLine("AttributeType: " + Type.ToString());
switch (Type) switch (Type)
{ {
@ -353,40 +357,40 @@ namespace CXMLDecompiler
break; break;
case AttributeType.TYPE_INT: case AttributeType.TYPE_INT:
int intWrite = Int32.Parse(attribute.Value, CultureInfo.InvariantCulture); int intWrite = Int32.Parse(attribute.Value, CultureInfo.InvariantCulture);
bWorkRam.Write((int)intWrite); tools.WriteInt32(WorkRam, intWrite);
bWorkRam.Write((int)0x00); tools.WriteInt32(WorkRam, 0x00);
Console.WriteLine("Int - Value: " + intWrite.ToString()); Console.WriteLine("Int - Value: " + intWrite.ToString());
break; break;
case AttributeType.TYPE_FLOAT: case AttributeType.TYPE_FLOAT:
float FloatValue = Single.Parse(attribute.Value.Substring(0, attribute.Value.Length - 1), CultureInfo.InvariantCulture); float FloatValue = Single.Parse(attribute.Value.Substring(0, attribute.Value.Length - 1), CultureInfo.InvariantCulture);
bWorkRam.Write((float)FloatValue); tools.WriteSingle(WorkRam, FloatValue);
bWorkRam.Write((int)0x00); tools.WriteInt32(WorkRam, 0x00);
Console.WriteLine("Float - Value: " + FloatValue.ToString()); Console.WriteLine("Float - Value: " + FloatValue.ToString());
break; break;
case AttributeType.TYPE_STRING: case AttributeType.TYPE_STRING:
int StringOffset = AddGetStringTable(attribute.Value); int StringOffset = AddGetStringTable(attribute.Value);
int StringLen = Encoding.UTF8.GetBytes(attribute.Value).Length; int StringLen = Encoding.UTF8.GetBytes(attribute.Value).Length;
bWorkRam.Write(StringOffset); tools.WriteInt32(WorkRam, StringOffset);
bWorkRam.Write(StringLen); tools.WriteInt32(WorkRam, StringLen);
Console.WriteLine("String: " + attribute.Value); Console.WriteLine("String: " + attribute.Value);
break; break;
case AttributeType.TYPE_CHAR: case AttributeType.TYPE_WSTRING:
int CharOffset = AddGetCharTable(attribute.Value); int WStringOffset = AddGetWstringTable(attribute.Value);
int CharLen = Encoding.Unicode.GetBytes(attribute.Value).Length; int WStringLength = Encoding.Unicode.GetBytes(attribute.Value).Length;
bWorkRam.Write(CharOffset); tools.WriteInt32(WorkRam, WStringOffset);
bWorkRam.Write(CharLen); tools.WriteInt32(WorkRam, WStringLength);
Console.WriteLine("Char: " + attribute.Value); Console.WriteLine("WString: " + attribute.Value);
break; break;
case AttributeType.TYPE_HASH_ID: case AttributeType.TYPE_HASH:
int hashId = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture); int hashId = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
if (HashStrings) if (HashStrings)
hashId = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture); hashId = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
int HashTableOffset = AddGetHashIdTable(hashId); int HashTableOffset = AddGetHashTable(hashId);
int HashTableSize = 4; int HashTableSize = 4;
bWorkRam.Write(HashTableOffset); tools.WriteInt32(WorkRam, HashTableOffset);
bWorkRam.Write(HashTableSize); tools.WriteInt32(WorkRam, HashTableSize);
Console.WriteLine("Hash ID Offset:" + HashTableOffset.ToString() + " size: " + HashTableSize); Console.WriteLine("Hash ID Offset:" + HashTableOffset.ToString() + " size: " + HashTableSize);
break; break;
case AttributeType.TYPE_INTEGER_ARRAY: case AttributeType.TYPE_INTEGER_ARRAY:
@ -397,8 +401,8 @@ namespace CXMLDecompiler
int IntArrayOffset = AddGetIntArrayTable(intArr); int IntArrayOffset = AddGetIntArrayTable(intArr);
int IntArraySize = intArr.Length; int IntArraySize = intArr.Length;
bWorkRam.Write(IntArrayOffset); tools.WriteInt32(WorkRam, IntArrayOffset);
bWorkRam.Write(IntArraySize); tools.WriteInt32(WorkRam, IntArraySize);
Console.WriteLine("Int Array: " + attribute.Value); Console.WriteLine("Int Array: " + attribute.Value);
break; break;
@ -410,8 +414,8 @@ namespace CXMLDecompiler
int FloatArrayOffset = AddGetFloatArrayTable(floatArr); int FloatArrayOffset = AddGetFloatArrayTable(floatArr);
int FloatArraySize = floatArr.Length; int FloatArraySize = floatArr.Length;
bWorkRam.Write(FloatArrayOffset); tools.WriteInt32(WorkRam, FloatArrayOffset);
bWorkRam.Write(FloatArraySize); tools.WriteInt32(WorkRam, FloatArraySize);
Console.WriteLine("Float Array: " + attribute.Value); Console.WriteLine("Float Array: " + attribute.Value);
break; break;
@ -420,41 +424,41 @@ namespace CXMLDecompiler
byte[] data = File.ReadAllBytes(fPath); byte[] data = File.ReadAllBytes(fPath);
int FilePtr = AddGetFileTable(data, Path.Combine(Environment.CurrentDirectory, fPath)); int FilePtr = AddGetFileTable(data, Path.Combine(Environment.CurrentDirectory, fPath));
int FileSz = data.Length; int FileSz = data.Length;
bWorkRam.Write(FilePtr); tools.WriteInt32(WorkRam, FilePtr);
bWorkRam.Write(FileSz); tools.WriteInt32(WorkRam, FileSz);
Console.WriteLine("Reading File: " + fPath); Console.WriteLine("Reading File: " + fPath);
break; break;
case AttributeType.TYPE_ID_STRING_LOOPBACK: case AttributeType.TYPE_ID_REF:
int StringIdTableOffset = AddGetStringIdTable(attribute.Value, Convert.ToInt32(TreeTable.Position)); int IdTableOffset = AddGetIdTable(attribute.Value, Convert.ToInt32(TreeTable.Position));
bWorkRam.Write(StringIdTableOffset); tools.WriteInt32(WorkRam, IdTableOffset);
bWorkRam.Write((int)0x00); tools.WriteInt32(WorkRam, 0x00);
Console.WriteLine("String Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")"); Console.WriteLine("String Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")");
Console.WriteLine("Loopback ID String: " + StringIdTableOffset + " sz: 0"); Console.WriteLine("Loopback ID String: " + IdTableOffset + " sz: 0");
break; break;
case AttributeType.TYPE_ID_STRING: case AttributeType.TYPE_ID:
StringIdTableOffset = AddGetStringIdTable(attribute.Value, -1); IdTableOffset = AddGetIdTable(attribute.Value, -1);
bWorkRam.Write(StringIdTableOffset); tools.WriteInt32(WorkRam, IdTableOffset);
bWorkRam.Write((int)0x00); tools.WriteInt32(WorkRam, 0x00);
Console.WriteLine("ID String: " + StringIdTableOffset + " sz: 0"); Console.WriteLine("ID String: " + IdTableOffset + " sz: 0");
break; break;
case AttributeType.TYPE_ID_INT_LOOPBACK: case AttributeType.TYPE_ID_HASH_REF:
int hash = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture); int hash = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
if (HashStrings) if (HashStrings)
hash = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture); hash = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
int IntIdTableOffset = AddGetIntIdTable(hash, Convert.ToInt32(TreeTable.Position)); int IntIdTableOffset = AddGetHashIdTable(hash, Convert.ToInt32(TreeTable.Position));
bWorkRam.Write(IntIdTableOffset); tools.WriteInt32(WorkRam, IntIdTableOffset);
bWorkRam.Write((int)0x00); tools.WriteInt32(WorkRam, 0x00);
Console.WriteLine("Int Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")"); Console.WriteLine("Int Loopback: " + ElementName + " " + TreeTable.Position.ToString("X") + " (" + TreeTable.Position.ToString("X") + ")");
Console.WriteLine("Loopback ID Int: " + IntIdTableOffset + " sz: 0"); Console.WriteLine("Loopback ID Int: " + IntIdTableOffset + " sz: 0");
break; break;
case AttributeType.TYPE_ID_INT: case AttributeType.TYPE_ID_HASH:
hash = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture); hash = Int32.Parse(attribute.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
if (HashStrings) if (HashStrings)
hash = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture); hash = Int32.Parse(Tools.GenerateShortHash(Encoding.UTF8.GetBytes(attribute.Value)), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
IntIdTableOffset = AddGetIntIdTable(hash, -1); IntIdTableOffset = AddGetHashIdTable(hash, -1);
bWorkRam.Write(IntIdTableOffset); tools.WriteInt32(WorkRam, IntIdTableOffset);
bWorkRam.Write((int)0x00); tools.WriteInt32(WorkRam, 0x00);
Console.WriteLine("Int Id: " + IntIdTableOffset + " sz: 0"); Console.WriteLine("Int Id: " + IntIdTableOffset + " sz: 0");
break; break;
default: default:
@ -467,7 +471,7 @@ namespace CXMLDecompiler
public void WriteElement(XmlNode node) public void WriteElement(XmlNode node)
{ {
MemoryStream WorkRam = new MemoryStream(); MemoryStream WorkRam = new MemoryStream();
BinaryWriter bWorkRam = new BinaryWriter(WorkRam); //BinaryWriter bWorkRam = new BinaryWriter(WorkRam);
int ElementPtr = AddGetStringTable(node.Name); int ElementPtr = AddGetStringTable(node.Name);
int NumAttributes = 0; int NumAttributes = 0;
int ParentPtr = -1; int ParentPtr = -1;
@ -477,17 +481,17 @@ namespace CXMLDecompiler
int FirstChild = -1; int FirstChild = -1;
int LastChild = -1; int LastChild = -1;
long Position = TreeTable.Position; long Position = TreeTable.Position;
bWorkRam.Write(ElementPtr); tools.WriteInt32(WorkRam, ElementPtr);
bWorkRam.Write(NumAttributes); tools.WriteInt32(WorkRam, NumAttributes);
bWorkRam.Write(ParentPtr); tools.WriteInt32(WorkRam, ParentPtr);
bWorkRam.Write(PrevSibling); tools.WriteInt32(WorkRam, PrevSibling);
bWorkRam.Write(NextSibling); tools.WriteInt32(WorkRam, NextSibling);
bWorkRam.Write(FirstChild); tools.WriteInt32(WorkRam, FirstChild);
bWorkRam.Write(LastChild); tools.WriteInt32(WorkRam, LastChild);
foreach (XmlAttribute attribute in node.Attributes) foreach (XmlAttribute attribute in node.Attributes)
{ {
WriteAttribute(attribute, WorkRam, bWorkRam, node.Name); WriteAttribute(attribute, WorkRam, node.Name);
} }
@ -515,14 +519,14 @@ namespace CXMLDecompiler
LastChild = AddGetTreeTable(node.LastChild); LastChild = AddGetTreeTable(node.LastChild);
long Position2 = TreeTable.Position; long Position2 = TreeTable.Position;
TreeTable.Seek(Position, SeekOrigin.Begin); TreeTable.Seek(Position, SeekOrigin.Begin);
bTreeTable.Write(ElementPtr); tools.WriteInt32(TreeTable, ElementPtr);
bTreeTable.Write(NumAttributes); tools.WriteInt32(TreeTable, NumAttributes);
bTreeTable.Write(ParentPtr); tools.WriteInt32(TreeTable, ParentPtr);
bTreeTable.Write(PrevSibling); tools.WriteInt32(TreeTable, PrevSibling);
bTreeTable.Write(NextSibling); tools.WriteInt32(TreeTable, NextSibling);
bTreeTable.Write(FirstChild); tools.WriteInt32(TreeTable, FirstChild);
bTreeTable.Write(LastChild); tools.WriteInt32(TreeTable, LastChild);
TreeTable.Seek(Position2, SeekOrigin.Begin); TreeTable.Seek(Position2, SeekOrigin.Begin);
} }
@ -545,30 +549,25 @@ namespace CXMLDecompiler
{ {
InfoFile.Close(); InfoFile.Close();
TreeTable.Close(); TreeTable.Close();
StringIDTable.Close(); IDTable.Close();
IntIDTable.Close();
StringTable.Close();
CharTable.Close();
HashIDTable.Close(); HashIDTable.Close();
StringTable.Close();
WStringTable.Close();
HashTable.Close();
IntArrayTable.Close(); IntArrayTable.Close();
FloatArrayTable.Close(); FloatArrayTable.Close();
FileTable.Close(); FileTable.Close();
bTreeTable.Close();
bIntIDTable.Close();
bFloatArrayTable.Close();
bIntArrayTable.Close();
bHashIDTable.Close();
TreeTableEntries.Clear(); TreeTableEntries.Clear();
StringTableEntries.Clear(); StringTableEntries.Clear();
CharTableEntries.Clear(); WStringTableEntries.Clear();
HashIdTableEntries.Clear(); HashTableEntries.Clear();
IntArrayTableEntries.Clear(); IntArrayTableEntries.Clear();
FloatArrayTableEntries.Clear(); FloatArrayTableEntries.Clear();
FileTableEntries.Clear(); FileTableEntries.Clear();
StringIDTableEntries.Clear(); IDTableEntries.Clear();
IntIDTableEntries.Clear(); HashIDTableEntries.Clear();
IsInitalized = false; IsInitalized = false;
} }
@ -584,11 +583,17 @@ namespace CXMLDecompiler
XMLFile.Load(XmlFile); XMLFile.Load(XmlFile);
Tools.WriteStringToStream(InfoFile, MagicNumber); Tools.WriteStringToStream(InfoFile, MagicNumber);
bInfoFile.Write((Int32)Version); Tools.WriteLittleEndainInt(InfoFile, Version);
byte[] headerPlaceholder = new byte[0x48]; byte[] headerPlaceholder;
if (!ps3)
headerPlaceholder = new byte[0x48];
else
headerPlaceholder = new byte[0x30];
InfoFile.Write(headerPlaceholder, 0x00, headerPlaceholder.Length); InfoFile.Write(headerPlaceholder, 0x00, headerPlaceholder.Length);
Align(InfoFile, 0x10);
foreach(XmlNode childNode in XMLFile.ChildNodes) foreach (XmlNode childNode in XMLFile.ChildNodes)
{ {
AddGetTreeTable(childNode); AddGetTreeTable(childNode);
} }
@ -600,29 +605,11 @@ namespace CXMLDecompiler
TreeTable.CopyTo(InfoFile); TreeTable.CopyTo(InfoFile);
int StringIdOffset = Convert.ToInt32(InfoFile.Position); int IdTableOffset = Convert.ToInt32(InfoFile.Position);
int StringIdSize = Convert.ToInt32(StringIDTable.Length); int IdTableSize = Convert.ToInt32(IDTable.Length);
Align(StringIDTable, 0x10); Align(IDTable, 0x10);
StringIDTable.Seek(0x00, SeekOrigin.Begin); IDTable.Seek(0x00, SeekOrigin.Begin);
StringIDTable.CopyTo(InfoFile); IDTable.CopyTo(InfoFile);
int IntIdOffset = Convert.ToInt32(InfoFile.Position);
int IntIdSize = Convert.ToInt32(IntIDTable.Length);
Align(IntIDTable, 0x10);
IntIDTable.Seek(0x00, SeekOrigin.Begin);
IntIDTable.CopyTo(InfoFile);
int StringTableOffset = Convert.ToInt32(InfoFile.Position);
int StringTableSize = Convert.ToInt32(StringTable.Length);
Align(StringTable, 0x10);
StringTable.Seek(0x00, SeekOrigin.Begin);
StringTable.CopyTo(InfoFile);
int CharTableOffset = Convert.ToInt32(InfoFile.Position);
int CharTableSize = Convert.ToInt32(CharTable.Length);
Align(CharTable, 0x10);
CharTable.Seek(0x00, SeekOrigin.Begin);
CharTable.CopyTo(InfoFile);
int HashIdTableOffset = Convert.ToInt32(InfoFile.Position); int HashIdTableOffset = Convert.ToInt32(InfoFile.Position);
int HashIdTableSize = Convert.ToInt32(HashIDTable.Length); int HashIdTableSize = Convert.ToInt32(HashIDTable.Length);
@ -630,6 +617,24 @@ namespace CXMLDecompiler
HashIDTable.Seek(0x00, SeekOrigin.Begin); HashIDTable.Seek(0x00, SeekOrigin.Begin);
HashIDTable.CopyTo(InfoFile); HashIDTable.CopyTo(InfoFile);
int StringTableOffset = Convert.ToInt32(InfoFile.Position);
int StringTableSize = Convert.ToInt32(StringTable.Length);
Align(StringTable, 0x10);
StringTable.Seek(0x00, SeekOrigin.Begin);
StringTable.CopyTo(InfoFile);
int WStringTableOffset = Convert.ToInt32(InfoFile.Position);
int WStringTableSize = Convert.ToInt32(WStringTable.Length);
Align(WStringTable, 0x10);
WStringTable.Seek(0x00, SeekOrigin.Begin);
WStringTable.CopyTo(InfoFile);
int HashTableOffset = Convert.ToInt32(InfoFile.Position);
int HashTableSize = Convert.ToInt32(HashTable.Length);
Align(HashTable, 0x10);
HashTable.Seek(0x00, SeekOrigin.Begin);
HashTable.CopyTo(InfoFile);
int IntArrayTableOffset = Convert.ToInt32(InfoFile.Position); int IntArrayTableOffset = Convert.ToInt32(InfoFile.Position);
int IntArrayTableSize = Convert.ToInt32(IntArrayTable.Length); int IntArrayTableSize = Convert.ToInt32(IntArrayTable.Length);
Align(IntArrayTable, 0x10); Align(IntArrayTable, 0x10);
@ -659,24 +664,34 @@ namespace CXMLDecompiler
} }
InfoFile.Seek(0x8, SeekOrigin.Begin); InfoFile.Seek(0x8, SeekOrigin.Begin);
bInfoFile.Write(TreeTableOffset); tools.WriteInt32(InfoFile, TreeTableOffset);
bInfoFile.Write(TreeTableSize); tools.WriteInt32(InfoFile, TreeTableSize);
bInfoFile.Write(StringIdOffset); tools.WriteInt32(InfoFile, IdTableOffset);
bInfoFile.Write(StringIdSize); tools.WriteInt32(InfoFile, IdTableSize);
bInfoFile.Write(IntIdOffset);
bInfoFile.Write(IntIdSize); if (!ps3)
bInfoFile.Write(StringTableOffset); {
bInfoFile.Write(StringTableSize); tools.WriteInt32(InfoFile, HashIdTableOffset);
bInfoFile.Write(CharTableOffset); tools.WriteInt32(InfoFile, HashIdTableSize);
bInfoFile.Write(CharTableSize); }
bInfoFile.Write(HashIdTableOffset);
bInfoFile.Write(HashIdTableSize); tools.WriteInt32(InfoFile, StringTableOffset);
bInfoFile.Write(IntArrayTableOffset); tools.WriteInt32(InfoFile, StringTableSize);
bInfoFile.Write(IntArrayTableSize);
bInfoFile.Write(FloatArrayTableOffset); if (!ps3)
bInfoFile.Write(FloatArrayTableSize); {
bInfoFile.Write(FileTableOffset); tools.WriteInt32(InfoFile, WStringTableOffset);
bInfoFile.Write(FileTableSize); tools.WriteInt32(InfoFile, WStringTableSize);
tools.WriteInt32(InfoFile, HashTableOffset);
tools.WriteInt32(InfoFile, HashTableSize);
}
tools.WriteInt32(InfoFile, IntArrayTableOffset);
tools.WriteInt32(InfoFile, IntArrayTableSize);
tools.WriteInt32(InfoFile, FloatArrayTableOffset);
tools.WriteInt32(InfoFile, FloatArrayTableSize);
tools.WriteInt32(InfoFile, FileTableOffset);
tools.WriteInt32(InfoFile, FileTableSize);
Term(); Term();
} }

View File

@ -93,10 +93,10 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CXML.cs" />
<Compile Include="CXMLReader.cs" /> <Compile Include="CXMLReader.cs" />
<Compile Include="CXMLBuilder.cs" /> <Compile Include="CXMLBuilder.cs" />
<Compile Include="GimConv.cs" /> <Compile Include="GimConv.cs" />
<Compile Include="LoopbackHandler.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tools.cs" /> <Compile Include="Tools.cs" />

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<StartArguments>sample\sample.xml sample2.cxml --compile</StartArguments>
<StartWorkingDirectory>C:\Users\User\Documents\git\cxml-decompiler\CXMLCli\bin\x64\Debug</StartWorkingDirectory>
</PropertyGroup>
</Project>

View File

@ -1,5 +1,6 @@
using Ionic.Zlib; using Ionic.Zlib;
using General; using General;
using CXML;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -7,46 +8,35 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using System.Globalization; using System.Globalization;
namespace CXML namespace CXMLDecompiler
{ {
class CXMLReader
enum AttributeType
{ {
TYPE_NONE,
TYPE_INT,
TYPE_FLOAT,
TYPE_STRING,
TYPE_CHAR,
TYPE_HASH_ID,
TYPE_INTEGER_ARRAY,
TYPE_FLOAT_ARRAY,
TYPE_FILE,
TYPE_ID_STRING_LOOPBACK,
TYPE_ID_STRING,
TYPE_ID_INT_LOOPBACK,
TYPE_ID_INT
};
class CXMLParser
{
private bool _checkMagicNumber() private bool _checkMagicNumber()
{ {
String Magic = Tools.ReadStringAt(InfoFile, 0x00); String Magic = Tools.ReadStringAt(InfoFile, 0x00);
MagicNumber = Magic.Substring(0,4); MagicNumber = Magic.Substring(0,4);
if (Magic.StartsWith("PSMA")) if (Magic.StartsWith("PSMA")) // PlayStation Mobile "app.info"
{ {
return true; return true;
} }
else if(Magic.StartsWith("RCOF")) else if(Magic.StartsWith("RCOF")) // Vita/Ps4/Ps3 RCO
{ {
return true; return true;
} }
else if (Magic.StartsWith("RCSF")) else if (Magic.StartsWith("RCSF")) // Found inside RCO
{
return true;
}
else if (Magic.StartsWith("CXML")) // cxml.py default
{
return true;
}
else if (Magic.StartsWith("TEST")) // ps3 cxml tools example
{ {
return true; return true;
} }
@ -54,13 +44,9 @@ namespace CXML
{ {
return false; return false;
} }
} }
public class TypingInformation
{
public string key;
public string value;
}
String MainDir = ""; String MainDir = "";
String FileDir = ""; String FileDir = "";
String XMLFilename = ""; String XMLFilename = "";
@ -73,32 +59,32 @@ namespace CXML
FileStream InfoFile; FileStream InfoFile;
MemoryStream TreeTable; MemoryStream TreeTable;
MemoryStream StringIDTable; MemoryStream IDTable;
MemoryStream IntIDTable;
MemoryStream StringTable;
MemoryStream CharTable;
MemoryStream HashIDTable; MemoryStream HashIDTable;
MemoryStream StringTable;
MemoryStream WStringTable;
MemoryStream HashTable;
MemoryStream IntArrayTable; MemoryStream IntArrayTable;
MemoryStream FloatArrayTable; MemoryStream FloatArrayTable;
MemoryStream FileTable; MemoryStream FileTable;
Tools tools;
Boolean IsInitalized = false; Boolean IsInitalized = false;
BinaryReader bTreeTable; CXML.Version FileVersion;
BinaryReader bIntIDTable;
BinaryReader bFloatArrayTable; public Endainness FileEndainness = Endainness.LITTLE_ENDAIN;
BinaryReader bIntArrayTable;
BinaryReader bHashIDTable;
BinaryReader bStringIDTable;
List<LoopbackHandler> FileList = new List<LoopbackHandler>(); List<LoopbackHandler> FileList = new List<LoopbackHandler>();
XmlWriter XMLWriter; XmlWriter XMLWriter;
public bool ps3 = false;
public bool ProcessFiles = false; public bool ProcessFiles = false;
public bool WaitExit = false; public bool WaitExit = false;
public bool NoRecursive = false; public bool NoRecursive = false;
public void Init(string path, bool CheckMagic = true) public void Init(string path, bool CheckMagic = true, bool forcePs3 = false, Endainness forceEndainness = Endainness.UNCHANGED)
{ {
InfoFile = File.Open(path, FileMode.Open, FileAccess.Read); InfoFile = File.Open(path, FileMode.Open, FileAccess.Read);
bool MagicValid = _checkMagicNumber(); bool MagicValid = _checkMagicNumber();
@ -110,24 +96,47 @@ namespace CXML
} }
} }
// This is a bit of a hack, but what can you do?
FileVersion = ReadVersionEnum();
if (FileVersion == CXML.Version.PS3)
{
ps3 = true;
FileEndainness = Endainness.BIG_ENDAIN;
}
else
{
FileEndainness = Endainness.LITTLE_ENDAIN;
}
if (forcePs3)
ps3 = true;
if (forceEndainness != Endainness.UNCHANGED)
FileEndainness = forceEndainness;
tools = new Tools(FileEndainness == Endainness.BIG_ENDAIN);
TreeTable = Tools.ByteToStream(GetTreeTable()); TreeTable = Tools.ByteToStream(GetTreeTable());
StringIDTable = Tools.ByteToStream(GetStringIDTable());
IntIDTable = Tools.ByteToStream(GetIntIDTable());
StringTable = Tools.ByteToStream(GetStringTable()); StringTable = Tools.ByteToStream(GetStringTable());
CharTable = Tools.ByteToStream(GetCharTable());
HashIDTable = Tools.ByteToStream(GetHashIDTable());
IntArrayTable = Tools.ByteToStream(GetIntArrayTable()); IntArrayTable = Tools.ByteToStream(GetIntArrayTable());
FloatArrayTable = Tools.ByteToStream(GetFloatArrayTable()); FloatArrayTable = Tools.ByteToStream(GetFloatArrayTable());
IDTable = Tools.ByteToStream(GetIDTable());
FileTable = Tools.ByteToStream(GetFileTable()); FileTable = Tools.ByteToStream(GetFileTable());
bTreeTable = new BinaryReader(TreeTable); // psvita, ps4 exclusive
bIntIDTable = new BinaryReader(IntIDTable); if (!ps3)
bFloatArrayTable = new BinaryReader(FloatArrayTable); {
bIntArrayTable = new BinaryReader(IntArrayTable); HashTable = Tools.ByteToStream(GetHashTable());
bHashIDTable = new BinaryReader(HashIDTable); HashIDTable = Tools.ByteToStream(GetHashIDTable());
bStringIDTable = new BinaryReader(StringIDTable); WStringTable = Tools.ByteToStream(GetWStringTable());
}
else
{
HashTable = new MemoryStream();
HashIDTable = new MemoryStream();
WStringTable = new MemoryStream();
}
MainDir = Path.GetFileNameWithoutExtension(path); MainDir = Path.GetFileNameWithoutExtension(path);
FileDir = Path.Combine(MainDir, "files"); FileDir = Path.Combine(MainDir, "files");
XMLFilename = Path.GetFileNameWithoutExtension(path) + ".xml"; XMLFilename = Path.GetFileNameWithoutExtension(path) + ".xml";
@ -141,113 +150,130 @@ namespace CXML
{ {
InfoFile.Close(); InfoFile.Close();
TreeTable.Close(); TreeTable.Close();
StringIDTable.Close(); IDTable.Close();
IntIDTable.Close();
StringTable.Close();
CharTable.Close();
HashIDTable.Close(); HashIDTable.Close();
StringTable.Close();
WStringTable.Close();
HashTable.Close();
IntArrayTable.Close(); IntArrayTable.Close();
FloatArrayTable.Close(); FloatArrayTable.Close();
FileTable.Close(); FileTable.Close();
bTreeTable.Close();
bIntIDTable.Close();
bFloatArrayTable.Close();
bIntArrayTable.Close();
bHashIDTable.Close();
FileList.Clear(); FileList.Clear();
IsInitalized = false; IsInitalized = false;
} }
public int GetTreeTableOffset() public int GetTreeTableOffset()
{ {
return Tools.ReadIntAt(InfoFile,0x8); return tools.ReadIntAt(InfoFile,0x8);
} }
public int GetTreeTableSize() public int GetTreeTableSize()
{ {
return Tools.ReadIntAt(InfoFile, 0xC); return tools.ReadIntAt(InfoFile, 0xC);
} }
public int GetIDStringTableOffset() public int GetIDTableOffset()
{ {
return Tools.ReadIntAt(InfoFile, 0x10); return tools.ReadIntAt(InfoFile, 0x10);
} }
public int GetIDStringTableSize() public int GetIDTableSize()
{ {
return Tools.ReadIntAt(InfoFile, 0x14); return tools.ReadIntAt(InfoFile, 0x14);
}
public int GetIDIntTableOffset()
{
return Tools.ReadIntAt(InfoFile, 0x18);
}
public int GetIDIntTableSize()
{
return Tools.ReadIntAt(InfoFile, 0x1C);
}
public int GetStringTableOffset()
{
return Tools.ReadIntAt(InfoFile, 0x20);
}
public int GetStringTableSize()
{
return Tools.ReadIntAt(InfoFile, 0x24);
}
public int GetCharTableOffset()
{
return Tools.ReadIntAt(InfoFile, 0x28);
}
public int GetCharTableSize()
{
return Tools.ReadIntAt(InfoFile, 0x2C);
} }
public int GetHashIDTableOffset() public int GetHashIDTableOffset()
{ {
return Tools.ReadIntAt(InfoFile, 0x30); return tools.ReadIntAt(InfoFile, 0x18);
} }
public int GetHashIDTableSize() public int GetHashIDTableSize()
{ {
return Tools.ReadIntAt(InfoFile, 0x34); return tools.ReadIntAt(InfoFile, 0x1C);
} }
public int GetStringTableOffset()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x18);
else
return tools.ReadIntAt(InfoFile, 0x20);
}
public int GetStringTableSize()
{
if (ps3)
return tools.ReadIntAt(InfoFile, 0x1C);
else
return tools.ReadIntAt(InfoFile, 0x24);
}
public int GetWStringTableOffset()
{
return tools.ReadIntAt(InfoFile, 0x28);
}
public int GetWStringTableSize()
{
return tools.ReadIntAt(InfoFile, 0x2C);
}
public int GetHashTableOffset()
{
return tools.ReadIntAt(InfoFile, 0x30);
}
public int GetHashTableSize()
{
return tools.ReadIntAt(InfoFile, 0x34);
}
public int GetIntArrayTableOffset() public int GetIntArrayTableOffset()
{ {
return Tools.ReadIntAt(InfoFile, 0x38); if(ps3)
return tools.ReadIntAt(InfoFile, 0x20);
else
return tools.ReadIntAt(InfoFile, 0x38);
} }
public int GetIntArrayTableSize() public int GetIntArrayTableSize()
{ {
return Tools.ReadIntAt(InfoFile, 0x3C); if (ps3)
return tools.ReadIntAt(InfoFile, 0x24);
else
return tools.ReadIntAt(InfoFile, 0x3C);
} }
public int GetFloatArrayTableOffset() public int GetFloatArrayTableOffset()
{ {
return Tools.ReadIntAt(InfoFile, 0x40); if (ps3)
return tools.ReadIntAt(InfoFile, 0x28);
else
return tools.ReadIntAt(InfoFile, 0x40);
} }
public int GetFloatArrayTableSize() public int GetFloatArrayTableSize()
{ {
return Tools.ReadIntAt(InfoFile, 0x44); if (ps3)
return tools.ReadIntAt(InfoFile, 0x2C);
else
return tools.ReadIntAt(InfoFile, 0x44);
} }
public int GetFileTableOffset() public int GetFileTableOffset()
{ {
return Tools.ReadIntAt(InfoFile, 0x48); if (ps3)
return tools.ReadIntAt(InfoFile, 0x30);
else
return tools.ReadIntAt(InfoFile, 0x48);
} }
public int GetFileTableSize() public int GetFileTableSize()
{ {
return Tools.ReadIntAt(InfoFile, 0x4C); if (ps3)
return tools.ReadIntAt(InfoFile, 0x34);
else
return tools.ReadIntAt(InfoFile, 0x4C);
} }
public byte[] GetTreeTable() public byte[] GetTreeTable()
@ -260,24 +286,24 @@ namespace CXML
return Table; return Table;
} }
public byte[] GetStringIDTable() public byte[] GetIDTable()
{ {
int IDStrTableOffset = GetIDStringTableOffset(); int IDOffset = GetIDTableOffset();
int IDStrTableSize = GetIDStringTableSize(); int IDTableSize = GetIDTableSize();
InfoFile.Seek(IDStrTableOffset, SeekOrigin.Begin); InfoFile.Seek(IDOffset, SeekOrigin.Begin);
byte[] IDStringTable = new byte[IDStrTableSize]; byte[] IDTable = new byte[IDTableSize];
InfoFile.Read(IDStringTable, 0x00, IDStrTableSize); InfoFile.Read(IDTable, 0x00, IDTableSize);
return IDStringTable; return IDTable;
} }
public byte[] GetIntIDTable() public byte[] GetHashIDTable()
{ {
int IDIntTableOffset = GetIDIntTableOffset(); int HashIDTableOffset = GetHashIDTableOffset();
int IDIntTableSize = GetIDIntTableSize(); int HashIDTableSize = GetHashIDTableSize();
InfoFile.Seek(IDIntTableOffset, SeekOrigin.Begin); InfoFile.Seek(HashIDTableOffset, SeekOrigin.Begin);
byte[] IDIntTable = new byte[IDIntTableSize]; byte[] HashIDTable = new byte[HashIDTableSize];
InfoFile.Read(IDIntTable, 0x00, IDIntTableSize); InfoFile.Read(HashIDTable, 0x00, HashIDTableSize);
return IDIntTable; return HashIDTable;
} }
public byte[] GetStringTable() public byte[] GetStringTable()
@ -290,24 +316,24 @@ namespace CXML
return StringTable; return StringTable;
} }
public byte[] GetCharTable() public byte[] GetWStringTable()
{ {
int CharTableOffset = GetCharTableOffset(); int CharTableOffset = GetWStringTableOffset();
int CharTableSize = GetCharTableSize(); int CharTableSize = GetWStringTableSize();
InfoFile.Seek(CharTableOffset, SeekOrigin.Begin); InfoFile.Seek(CharTableOffset, SeekOrigin.Begin);
byte[] CharTable = new byte[CharTableSize]; byte[] CharTable = new byte[CharTableSize];
InfoFile.Read(CharTable, 0x00, CharTableSize); InfoFile.Read(CharTable, 0x00, CharTableSize);
return CharTable; return CharTable;
} }
public byte[] GetHashIDTable() public byte[] GetHashTable()
{ {
int HashIDTableOffset = GetHashIDTableOffset(); int HashTableOffset = GetHashTableOffset();
int HashIDTableSize = GetHashIDTableSize(); int HashTableSize = GetHashTableSize();
InfoFile.Seek(HashIDTableOffset, SeekOrigin.Begin); InfoFile.Seek(HashTableOffset, SeekOrigin.Begin);
byte[] HashIDTable = new byte[HashIDTableSize]; byte[] HashTable = new byte[HashTableSize];
InfoFile.Read(HashIDTable, 0x00, HashIDTableSize); InfoFile.Read(HashTable, 0x00, HashTableSize);
return HashIDTable; return HashTable;
} }
public byte[] GetIntArrayTable() public byte[] GetIntArrayTable()
@ -339,9 +365,20 @@ namespace CXML
InfoFile.Read(FileTable, 0x00, DataLength); InfoFile.Read(FileTable, 0x00, DataLength);
return FileTable; return FileTable;
} }
public int ReadVersion() public CXML.Version ReadVersionEnum()
{
try
{
return (CXML.Version)ReadVersionInt();
}
catch (Exception)
{
return CXML.Version.UNKNOWN;
}
}
public int ReadVersionInt()
{ {
return Tools.ReadIntAt(InfoFile, 0x4); return Tools.ReadLittleEndainIntAt(InfoFile, 0x4);
} }
public void AddTypingInfo(string key, object value) public void AddTypingInfo(string key, object value)
{ {
@ -405,7 +442,9 @@ namespace CXML
XMLWriter.WriteStartDocument(); XMLWriter.WriteStartDocument();
XMLWriter.WriteComment(MagicReplacePattern); XMLWriter.WriteComment(MagicReplacePattern);
AddTypingInfo("MAGIC", MagicNumber); AddTypingInfo("MAGIC", MagicNumber);
AddTypingInfo("VERSION", ReadVersion()); AddTypingInfo("VERSION", "0x"+ReadVersionInt().ToString("X"));
AddTypingInfo("ENDAINESS", FileEndainness.ToString());
AddTypingInfo("PS3", ps3 ? "true" : "false");
ReadElements(); ReadElements();
XMLWriter.WriteEndDocument(); XMLWriter.WriteEndDocument();
XMLWriter.Flush(); XMLWriter.Flush();
@ -508,7 +547,7 @@ namespace CXML
try try
{ {
CXMLParser cxmlParser = new CXMLParser(); CXMLReader cxmlParser = new CXMLReader();
cxmlParser.Init(FileName); cxmlParser.Init(FileName);
cxmlParser.ProcessFiles = this.ProcessFiles; cxmlParser.ProcessFiles = this.ProcessFiles;
cxmlParser.MainDir = DirectoryName; cxmlParser.MainDir = DirectoryName;
@ -613,11 +652,24 @@ namespace CXML
FileList.Add(lpHandler); FileList.Add(lpHandler);
return; return;
} }
public AttributeType ReadAttributeType(Stream ms)
{
if(!ps3)
{
AttributeType type = (AttributeType)tools.ReadInt32(ms);
return type;
}
else
{
AttributeTypePs3 type = (AttributeTypePs3)tools.ReadInt32(ms);
return (AttributeType)Enum.Parse(typeof(AttributeType), type.ToString());
}
}
public void ReadAttribute(String ElementName = "", Int64 ElementPtr = 0) public void ReadAttribute(String ElementName = "", Int64 ElementPtr = 0)
{ {
int AttributePtr = bTreeTable.ReadInt32(); int AttributePtr = tools.ReadInt32(TreeTable);
AttributeType Type = (AttributeType)bTreeTable.ReadInt32(); AttributeType Type = ReadAttributeType(TreeTable);
String AttributeName = Tools.ReadStringAt(StringTable, AttributePtr); String AttributeName = Tools.ReadStringAt(StringTable, AttributePtr);
object AttributeValue = ""; object AttributeValue = "";
@ -625,24 +677,23 @@ namespace CXML
Console.WriteLine("AttributeType: " + Type.ToString() + " - "+ TreeTable.Position.ToString()); Console.WriteLine("AttributeType: " + Type.ToString() + " - "+ TreeTable.Position.ToString());
switch (Type) switch (Type)
{ {
case AttributeType.TYPE_NONE:
Console.WriteLine("UNSUPPORTED TYPE @ " + TreeTable.Position);
Console.ReadKey();
break;
case AttributeType.TYPE_INT: case AttributeType.TYPE_INT:
AttributeValue = bTreeTable.ReadInt32(); AttributeValue = tools.ReadInt32(TreeTable);
int sz = bTreeTable.ReadInt32(); int sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Int - Value: " + AttributeValue.ToString() + " sz:" + sz); Console.WriteLine("Int - Value: " + AttributeValue.ToString() + " sz:" + sz);
break; break;
case AttributeType.TYPE_FLOAT: case AttributeType.TYPE_FLOAT:
float FloatValue = bTreeTable.ReadSingle(); float FloatValue = tools.ReadSingle(TreeTable);
AttributeValue = FloatValue.ToString("G9", CultureInfo.InvariantCulture) + "f"; string FloatStr = FloatValue.ToString("G9", CultureInfo.InvariantCulture);
sz = bTreeTable.ReadInt32(); if (!FloatStr.Contains("."))
Console.WriteLine("Float - Value: " + AttributeValue.ToString() + " sz:" + sz); FloatStr += ".0";
AttributeValue = FloatStr;
sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Float: " + AttributeValue.ToString() + " sz:" + sz);
break; break;
case AttributeType.TYPE_STRING: case AttributeType.TYPE_STRING:
int StringOffset = bTreeTable.ReadInt32(); int StringOffset = tools.ReadInt32(TreeTable);
int StringLen = bTreeTable.ReadInt32(); int StringLen = tools.ReadInt32(TreeTable);
byte[] StringBytes = new byte[StringLen]; byte[] StringBytes = new byte[StringLen];
StringTable.Seek(StringOffset, 0x00); StringTable.Seek(StringOffset, 0x00);
@ -651,63 +702,66 @@ namespace CXML
AttributeValue = Encoding.UTF8.GetString(StringBytes); AttributeValue = Encoding.UTF8.GetString(StringBytes);
Console.WriteLine("String: " + AttributeValue); Console.WriteLine("String: " + AttributeValue);
break; break;
case AttributeType.TYPE_CHAR: case AttributeType.TYPE_WSTRING:
int CharOffset = bTreeTable.ReadInt32() * 2; int WStrOffset = tools.ReadInt32(TreeTable) * 2;
int CharLen = bTreeTable.ReadInt32(); int WStrLen = tools.ReadInt32(TreeTable);
byte[] CharBytes = new byte[CharLen]; byte[] WStrBytes = new byte[WStrLen];
CharTable.Seek(CharOffset, 0x00); WStringTable.Seek(WStrOffset, 0x00);
CharTable.Read(CharBytes, 0x00, CharLen); WStringTable.Read(WStrBytes, 0x00, WStrLen);
AttributeValue = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(Encoding.Unicode.GetString(CharBytes))); AttributeValue = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(Encoding.Unicode.GetString(WStrBytes)));
Console.WriteLine("Char: " + AttributeValue); Console.WriteLine("WString: " + AttributeValue);
break; break;
case AttributeType.TYPE_HASH_ID: case AttributeType.TYPE_HASH:
int HashTableOffset = bTreeTable.ReadInt32(); int HashTableOffset = tools.ReadInt32(TreeTable);
int HashTableSize = bTreeTable.ReadInt32(); int HashTableSize = tools.ReadInt32(TreeTable);
HashIDTable.Seek(HashTableOffset * 4, SeekOrigin.Begin); HashTable.Seek(HashTableOffset * 4, SeekOrigin.Begin);
Console.WriteLine("Hash ID Offset:" + HashTableOffset.ToString(CultureInfo.InvariantCulture) + " size: " + HashTableSize);
int HashId = bHashIDTable.ReadInt32(); int Hash = tools.ReadInt32(HashTable);
AttributeValue = HashId.ToString("X8", CultureInfo.InvariantCulture); AttributeValue = Hash.ToString("X8", CultureInfo.InvariantCulture);
Console.WriteLine("Hash: " + AttributeValue.ToString() + " sz: " + HashTableSize);
break; break;
case AttributeType.TYPE_INTEGER_ARRAY: case AttributeType.TYPE_INTEGER_ARRAY:
int IntArrayOffset = bTreeTable.ReadInt32(); int IntArrayOffset = tools.ReadInt32(TreeTable);
int IntArraySize = bTreeTable.ReadInt32(); int IntArraySize = tools.ReadInt32(TreeTable);
IntArrayTable.Seek(IntArrayOffset*4, SeekOrigin.Begin); IntArrayTable.Seek(IntArrayOffset*4, SeekOrigin.Begin);
List<int> IntList = new List<int>(); List<int> IntList = new List<int>();
for (int i = 0; i < IntArraySize; i++) for (int i = 0; i < IntArraySize; i++)
{ {
int IntValue = bIntArrayTable.ReadInt32(); int IntValue = tools.ReadInt32(IntArrayTable);
IntList.Add(IntValue); IntList.Add(IntValue);
} }
int[] IntArray = IntList.ToArray(); int[] IntArray = IntList.ToArray();
AttributeValue = "[" + String.Join(", ", IntArray) + "]"; AttributeValue = String.Join(",", IntArray);
Console.WriteLine("Int Array: " + AttributeValue.ToString()); Console.WriteLine("Int Array: " + AttributeValue.ToString());
break; break;
case AttributeType.TYPE_FLOAT_ARRAY: case AttributeType.TYPE_FLOAT_ARRAY:
int FloatArrayOffset = bTreeTable.ReadInt32(); int FloatArrayOffset = tools.ReadInt32(TreeTable);
int FloatArraySize = bTreeTable.ReadInt32(); int FloatArraySize = tools.ReadInt32(TreeTable);
FloatArrayTable.Seek(FloatArrayOffset*4, SeekOrigin.Begin); FloatArrayTable.Seek(FloatArrayOffset*4, SeekOrigin.Begin);
List<string> StrList = new List<string>(); List<string> StrList = new List<string>();
for(int i = 0; i < FloatArraySize; i++) for(int i = 0; i < FloatArraySize; i++)
{ {
FloatValue = bFloatArrayTable.ReadSingle(); FloatValue = tools.ReadSingle(FloatArrayTable);
StrList.Add(FloatValue.ToString("G9", CultureInfo.InvariantCulture) +"f"); FloatStr = FloatValue.ToString("G9", CultureInfo.InvariantCulture);
if (!FloatStr.Contains("."))
FloatStr += ".0";
StrList.Add(FloatStr);
} }
string[] StrArray = StrList.ToArray(); string[] StrArray = StrList.ToArray();
AttributeValue = "[" + String.Join(", ", StrArray) + "]"; AttributeValue = String.Join(", ", StrArray);
Console.WriteLine("Float Array: " + AttributeValue.ToString()); Console.WriteLine("Float Array: " + AttributeValue.ToString());
break; break;
case AttributeType.TYPE_FILE: case AttributeType.TYPE_FILE:
int FilePtr = bTreeTable.ReadInt32(); int FilePtr = tools.ReadInt32(TreeTable);
int FileSz = bTreeTable.ReadInt32(); int FileSz = tools.ReadInt32(TreeTable);
Byte[] FileData = new Byte[FileSz]; Byte[] FileData = new Byte[FileSz];
FileTable.Seek(FilePtr, SeekOrigin.Begin); FileTable.Seek(FilePtr, SeekOrigin.Begin);
@ -725,40 +779,40 @@ namespace CXML
AttributeValue = ReplacePattern; AttributeValue = ReplacePattern;
break; break;
case AttributeType.TYPE_ID_STRING_LOOPBACK: case AttributeType.TYPE_ID_REF:
int StringIdTableOffset = bTreeTable.ReadInt32(); int StringIdTableOffset = tools.ReadInt32(TreeTable);
StringIDTable.Seek(StringIdTableOffset, SeekOrigin.Begin); IDTable.Seek(StringIdTableOffset, SeekOrigin.Begin);
int LoopbackPtr = bStringIDTable.ReadInt32(); int LoopbackPtr = tools.ReadInt32(IDTable);
int StringPtr = Tools.ReadIntAt(TreeTable, LoopbackPtr); int StringPtr = tools.ReadIntAt(TreeTable, LoopbackPtr);
string LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr); string LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
Console.WriteLine("Loopback: " + LoopbackAttribute +" "+ LoopbackPtr.ToString("X")+" ("+ElementPtr.ToString("X")+")"); Console.WriteLine("Loopback: " + LoopbackAttribute +" "+ LoopbackPtr.ToString("X")+" ("+ElementPtr.ToString("X")+")");
AttributeValue = Tools.ReadString(StringIDTable); AttributeValue = Tools.ReadString(IDTable);
RegisterFile(LoopbackPtr, AttributeValue.ToString(), false); RegisterFile(LoopbackPtr, AttributeValue.ToString(), false);
sz = bTreeTable.ReadInt32(); sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Loopback ID String: " + StringIdTableOffset + " sz: " + sz); Console.WriteLine("ID Ref: " + StringIdTableOffset + " sz: " + sz);
break; break;
case AttributeType.TYPE_ID_STRING: // This is probably right, tbh case AttributeType.TYPE_ID:
StringIdTableOffset = bTreeTable.ReadInt32(); StringIdTableOffset = tools.ReadInt32(TreeTable);
StringIDTable.Seek(StringIdTableOffset + 4, SeekOrigin.Begin); IDTable.Seek(StringIdTableOffset + 4, SeekOrigin.Begin);
AttributeValue = Tools.ReadString(StringIDTable); AttributeValue = Tools.ReadString(IDTable);
sz = bTreeTable.ReadInt32(); sz = tools.ReadInt32(TreeTable);
Console.WriteLine("ID String: " + StringIdTableOffset + " sz: " + sz); Console.WriteLine("ID : " + StringIdTableOffset + " sz: " + sz);
break; break;
case AttributeType.TYPE_ID_INT_LOOPBACK: case AttributeType.TYPE_ID_HASH_REF:
int IntIdTableOffset = bTreeTable.ReadInt32(); int IntIdTableOffset = tools.ReadInt32(TreeTable);
IntIDTable.Seek(IntIdTableOffset, SeekOrigin.Begin); HashIDTable.Seek(IntIdTableOffset, SeekOrigin.Begin);
LoopbackPtr = bIntIDTable.ReadInt32(); LoopbackPtr = tools.ReadInt32(HashIDTable);
StringPtr = Tools.ReadIntAt(TreeTable, LoopbackPtr); StringPtr = tools.ReadIntAt(TreeTable, LoopbackPtr);
int IDValue = bIntIDTable.ReadInt32(); int IDValue = tools.ReadInt32(HashIDTable);
LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr); LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
Console.WriteLine("Int Loopback: " + LoopbackAttribute + " " + LoopbackPtr.ToString("X", CultureInfo.InvariantCulture) + " (" + ElementPtr.ToString("X") + ")"); Console.WriteLine("Int Loopback: " + LoopbackAttribute + " " + LoopbackPtr.ToString("X", CultureInfo.InvariantCulture) + " (" + ElementPtr.ToString("X") + ")");
@ -766,25 +820,25 @@ namespace CXML
AttributeValue = IDValue.ToString("X8", CultureInfo.InvariantCulture); AttributeValue = IDValue.ToString("X8", CultureInfo.InvariantCulture);
RegisterFile(LoopbackPtr, AttributeValue.ToString(), false); RegisterFile(LoopbackPtr, AttributeValue.ToString(), false);
sz = bTreeTable.ReadInt32(); sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Loopback Int: " + IntIdTableOffset + " sz: " + sz); Console.WriteLine("Hash Ref: " + IntIdTableOffset + " sz: " + sz);
break; break;
case AttributeType.TYPE_ID_INT: case AttributeType.TYPE_ID_HASH:
IntIdTableOffset = bTreeTable.ReadInt32(); IntIdTableOffset = tools.ReadInt32(TreeTable);
IntIDTable.Seek(IntIdTableOffset + 4, SeekOrigin.Begin); HashIDTable.Seek(IntIdTableOffset + 4, SeekOrigin.Begin);
IDValue = bIntIDTable.ReadInt32(); IDValue = tools.ReadInt32(HashIDTable);
AttributeValue = IDValue.ToString("X8", CultureInfo.InvariantCulture); AttributeValue = IDValue.ToString("X8", CultureInfo.InvariantCulture);
sz = bTreeTable.ReadInt32(); sz = tools.ReadInt32(TreeTable);
Console.WriteLine("Int Id: " + IntIdTableOffset + " sz: " + sz); Console.WriteLine("Hash Id: " + IntIdTableOffset + " sz: " + sz);
break; break;
case AttributeType.TYPE_NONE:
default: default:
Console.WriteLine("UNKNOWN TYPE @ " + TreeTable.Position); new NotImplementedException("UNKNOWN TYPE @ " + TreeTable.Position);
Console.ReadKey();
break; break;
}; };
AddTypingInfo(ElementName + ":" + AttributeName, ((int)Type).ToString(CultureInfo.InvariantCulture)); AddTypingInfo(ElementName + ":" + AttributeName, Type.ToString());
Console.WriteLine(AttributeName + "=" + AttributeValue.ToString()); Console.WriteLine(AttributeName + "=" + AttributeValue.ToString());
XMLWriter.WriteAttributeString(AttributeName, AttributeValue.ToString()); XMLWriter.WriteAttributeString(AttributeName, AttributeValue.ToString());
XMLWriter.Flush(); XMLWriter.Flush();
@ -793,15 +847,15 @@ namespace CXML
public void ReadElements() public void ReadElements()
{ {
Int64 ElementLocation = TreeTable.Position; Int64 ElementLocation = TreeTable.Position;
int ElementPtr = bTreeTable.ReadInt32(); int ElementPtr = tools.ReadInt32(TreeTable);
int NumAttributes = bTreeTable.ReadInt32(); int NumAttributes = tools.ReadInt32(TreeTable);
int ParentPtr = bTreeTable.ReadInt32(); int ParentPtr = tools.ReadInt32(TreeTable);
int PrevSibling = bTreeTable.ReadInt32(); int PrevSibling = tools.ReadInt32(TreeTable);
int NextSibling = bTreeTable.ReadInt32(); int NextSibling = tools.ReadInt32(TreeTable);
int FirstChild = bTreeTable.ReadInt32(); int FirstChild = tools.ReadInt32(TreeTable);
int LastChild = bTreeTable.ReadInt32(); int LastChild = tools.ReadInt32(TreeTable);
String ElementName = Tools.ReadStringAt(StringTable, ElementPtr); String ElementName = Tools.ReadStringAt(StringTable, ElementPtr);
Console.WriteLine("Creating Element: " + ElementName); Console.WriteLine("Creating Element: " + ElementName);

View File

@ -1,13 +0,0 @@
using System;
namespace CXML
{
public class LoopbackHandler
{
public String FileName;
public String OldFileName;
public String ReplacePattern;
public byte[] FileData;
public Int64 FilePointer;
}
}

View File

@ -48,31 +48,33 @@ namespace CXMLCli
if (args.Length == 0) if (args.Length == 0)
{ {
Console.WriteLine("-- app.info/CXML Decompiler --"); Console.WriteLine("-- CXML Decompiler --");
Console.WriteLine("I like to see girls die :3");
Console.WriteLine("Required Arguments:"); Console.WriteLine("Required Arguments:");
Console.WriteLine("\t<input_filename>"); Console.WriteLine("\t<input_filename>");
Console.WriteLine("Optional Arguments:"); Console.WriteLine("Optional Arguments:");
Console.WriteLine("\t-iv --is-vag File is HE-VAG audio and NOT CXML"); Console.WriteLine("\t-iv --is-vag File is HE-VAG audio and NOT CXML");
Console.WriteLine("\t-dc --decompress Decompress .Z File"); Console.WriteLine("\t-dc --decompress Decompress .Z File");
Console.WriteLine("\t-cc --compress Compress back to .Z File"); Console.WriteLine("\t-cc --compress Compress back to .Z File");
Console.WriteLine("\t-f --force Dont check magic number."); Console.WriteLine("\t-f --force Dont check magic number.");
Console.WriteLine("\t-dt --dump-tables Dump ALL tables."); Console.WriteLine("\t-dt --dump-tables Dump ALL tables.");
Console.WriteLine("\t-tt --dump-tree Dump tree table."); Console.WriteLine("\t-tt --dump-tree Dump tree table.");
Console.WriteLine("\t-ist --dump-string-id Dump string ID table."); Console.WriteLine("\t-idt --dump-id Dump id ID table.");
Console.WriteLine("\t-iit --dump-int-id Dump int ID table."); Console.WriteLine("\t-iht --dump-hash-id Dump hash ID table.");
Console.WriteLine("\t-st --dump-string Dump string table."); Console.WriteLine("\t-st --dump-string Dump string table.");
Console.WriteLine("\t-ct --dump-char Dump char table."); Console.WriteLine("\t-wt --dump-wstring Dump wstring table.");
Console.WriteLine("\t-hit --dump-hash-id Dump hash ID table."); Console.WriteLine("\t-ht --dump-hash Dump hash table.");
Console.WriteLine("\t-iat --dump-int-array Dump int array table."); Console.WriteLine("\t-iat --dump-int-array Dump int array table.");
Console.WriteLine("\t-fat --dump-float-array Dump float array table."); Console.WriteLine("\t-fat --dump-float-array Dump float array table.");
Console.WriteLine("\t-ft --dump-file Dump file table."); Console.WriteLine("\t-ft --dump-file Dump file table.");
Console.WriteLine("\t-p --process-files Process Extracted Files"); Console.WriteLine("\t-le --little-endain De/Encode ints as Little Endain");
Console.WriteLine("\t-nr --no-recursive Do not recursively decompile .RCS to XML"); Console.WriteLine("\t-be --big-endain De/Encode ints as Big Endain");
Console.WriteLine("\t-w --wait-exit Wait for keypress before exiting"); Console.WriteLine("\t-ps3 --playstation-3 Use the old CXML Format used back on PS3.");
Console.WriteLine("\t-d --decompile Decompile CXML to XML."); Console.WriteLine("\t-p --process-files Process Extracted Files");
Console.WriteLine("\t-c --compile Compile XML to CXML"); Console.WriteLine("\t-nr --no-recursive Do not recursively decompile .RCS to XML");
Console.WriteLine("\t-h --hash-string When Compiling, Generate new hashes"); 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 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("Example Compile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " app.xml app.info -c");
Console.WriteLine("Default functonality is to Decompile,\nThis is canceled if any other arguments passed."); Console.WriteLine("Default functonality is to Decompile,\nThis is canceled if any other arguments passed.");
@ -118,7 +120,7 @@ namespace CXMLCli
return 0; return 0;
} }
CXML.CXMLParser cxmlParser = new CXML.CXMLParser(); CXMLReader cxmlParser = new CXMLReader();
if(!HasArg(ArgsFull, "-c") && !HasArg(ArgsFull, "--compile")) if(!HasArg(ArgsFull, "-c") && !HasArg(ArgsFull, "--compile"))
{ {
Console.WriteLine("Initalizing: " + path); Console.WriteLine("Initalizing: " + path);
@ -133,7 +135,7 @@ namespace CXMLCli
if (HasArg(ArgsFull, "-dt") || HasArg(ArgsFull, "--dump-tables")) if (HasArg(ArgsFull, "-dt") || HasArg(ArgsFull, "--dump-tables"))
{ {
ArgsFull += " -tt -ist -iit -st -ct -sit -iat -fat -ft"; 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")) if (HasArg(ArgsFull, "-tt") || HasArg(ArgsFull, "--dump-tree"))
@ -143,17 +145,17 @@ namespace CXMLCli
} }
if (HasArg(ArgsFull, "-ist") || HasArg(ArgsFull, "--dump-string-id")) if (HasArg(ArgsFull, "-idt") || HasArg(ArgsFull, "--dump-id"))
{ {
Console.WriteLine("Dumping string ID table."); Console.WriteLine("Dumping ID table.");
File.WriteAllBytes("string-id-table.bin", cxmlParser.GetStringIDTable()); File.WriteAllBytes("id-table.bin", cxmlParser.GetIDTable());
} }
if (HasArg(ArgsFull, "-iit") || HasArg(ArgsFull, "--dump-int-id")) if (HasArg(ArgsFull, "-iht") || HasArg(ArgsFull, "--dump-hash-id"))
{ {
Console.WriteLine("Dumping int ID table."); Console.WriteLine("Dumping hash ID table.");
File.WriteAllBytes("int-id-table.bin", cxmlParser.GetIntIDTable()); File.WriteAllBytes("hash-id-table.bin", cxmlParser.GetHashIDTable());
} }
if (HasArg(ArgsFull, "-st") || HasArg(ArgsFull, "--dump-string")) if (HasArg(ArgsFull, "-st") || HasArg(ArgsFull, "--dump-string"))
@ -163,16 +165,16 @@ namespace CXMLCli
} }
if (HasArg(ArgsFull, "-ct") || HasArg(ArgsFull, "--dump-char")) if (HasArg(ArgsFull, "-wt") || HasArg(ArgsFull, "--dump-wstring"))
{ {
Console.WriteLine("Dumping char table."); Console.WriteLine("Dumping wstring table.");
File.WriteAllBytes("char-table.bin", cxmlParser.GetCharTable()); File.WriteAllBytes("wstring-table.bin", cxmlParser.GetWStringTable());
} }
if ((HasArg(ArgsFull, "-sit") || HasArg(ArgsFull, "--dump-style-id")) /*kept for backwards comp*/ || (HasArg(ArgsFull, "-hit") || HasArg(ArgsFull, "--dump-hash-id"))) if (HasArg(ArgsFull, "-ht") || HasArg(ArgsFull, "--dump-hash"))
{ {
Console.WriteLine("Dumping hash ID table."); Console.WriteLine("Dumping hash table.");
File.WriteAllBytes("hash-id-table.bin", cxmlParser.GetHashIDTable()); File.WriteAllBytes("hash-table.bin", cxmlParser.GetHashTable());
} }

View File

@ -6,9 +6,21 @@ using System.Security.Cryptography;
using System.Text; using System.Text;
namespace General namespace General
{ {
enum Endainness
{
LITTLE_ENDAIN,
BIG_ENDAIN,
UNCHANGED
};
class Tools class Tools
{ {
public Tools(bool bigEndain)
{
BigEndain = bigEndain;
}
public bool BigEndain = false;
public static byte[] bmp = Encoding.ASCII.GetBytes("BM"); // BMP public static byte[] bmp = Encoding.ASCII.GetBytes("BM"); // BMP
public static byte[] gif = Encoding.ASCII.GetBytes("GIF"); // GIF public static byte[] gif = Encoding.ASCII.GetBytes("GIF"); // GIF
@ -197,24 +209,59 @@ namespace General
return str; return str;
} }
public static int ReadIntAt(Stream ms, int location) public static int ReadLittleEndainIntAt(Stream ms, int location)
{ {
BinaryReader BinReader = new BinaryReader(ms);
long ogPos = ms.Position; long ogPos = ms.Position;
ms.Seek(location, SeekOrigin.Begin); ms.Seek(location, SeekOrigin.Begin);
int i = BinReader.ReadInt32(); int i = ReadLittleEndainInt(ms);
ms.Seek(ogPos, SeekOrigin.Begin);
return i;
}
public int ReadIntAt(Stream ms, int location)
{
long ogPos = ms.Position;
ms.Seek(location, SeekOrigin.Begin);
int i = ReadInt32(ms);
ms.Seek(ogPos, SeekOrigin.Begin); ms.Seek(ogPos, SeekOrigin.Begin);
return i; return i;
} }
public static bool HasBinaryContent(string content) public static bool HasBinaryContent(string content)
{ {
return content.Any(ch => char.IsControl(ch) && ch != '\r' && ch != '\n'); return content.Any(ch => char.IsControl(ch) && ch != '\r' && ch != '\n');
} }
public static int ReadInt(Stream ms)
public void WriteInt32(Stream ms, int val)
{ {
BinaryReader BinReader = new BinaryReader(ms); if (BigEndain)
int i = BinReader.ReadInt32(); WriteBigEndainInt(ms, val);
return i; else
WriteLittleEndainInt(ms, val);
}
public void WriteSingle(Stream ms, Single val)
{
if (BigEndain)
WriteBigEndainSingle(ms, val);
else
WriteLittleEndainSingle(ms, val);
}
public int ReadInt32(Stream ms)
{
if (BigEndain)
return ReadBigEndainInt(ms);
else
return ReadLittleEndainInt(ms);
}
public Single ReadSingle(Stream ms)
{
if (BigEndain)
return ReadBigEndainSingle(ms);
else
return ReadLittleEndainSingle(ms);
} }
public static int ReadBigEndainIntAt(Stream ms, int location) public static int ReadBigEndainIntAt(Stream ms, int location)
@ -225,7 +272,54 @@ namespace General
ms.Seek(ogPos, SeekOrigin.Begin); ms.Seek(ogPos, SeekOrigin.Begin);
return i; return i;
} }
public static Single ReadBigEndainSingle(Stream ms)
{
byte[] SingleBytes = new byte[4];
ms.Read(SingleBytes, 0x00, 4);
SingleBytes = SingleBytes.Reverse().ToArray();
Single val = BitConverter.ToSingle(SingleBytes, 0x00);
return val;
}
public static Single ReadLittleEndainSingle(Stream ms)
{
byte[] SingleBytes = new byte[4];
ms.Read(SingleBytes, 0x00, 4);
SingleBytes = SingleBytes.ToArray();
Single val = BitConverter.ToSingle(SingleBytes, 0x00);
return val;
}
public static void WriteLittleEndainSingle(Stream ms, Single val)
{
byte[] SingleBytes = BitConverter.GetBytes(val);
ms.Write(SingleBytes, 0x00, SingleBytes.Length);
}
public static void WriteBigEndainSingle(Stream ms, Single val)
{
byte[] SingleBytes = BitConverter.GetBytes(val);
SingleBytes = SingleBytes.Reverse().ToArray();
ms.Write(SingleBytes, 0x00, SingleBytes.Length);
}
public static void WriteLittleEndainInt(Stream ms, int val)
{
byte[] IntBytes = BitConverter.GetBytes(val);
ms.Write(IntBytes, 0x00, IntBytes.Length);
}
public static void WriteBigEndainInt(Stream ms, int val)
{
byte[] IntBytes = BitConverter.GetBytes(val);
IntBytes = IntBytes.Reverse().ToArray();
ms.Write(IntBytes, 0x00, IntBytes.Length);
}
public static int ReadLittleEndainInt(Stream ms)
{
byte[] IntBytes = new byte[4];
ms.Read(IntBytes, 0x00, 4);
IntBytes = IntBytes.ToArray();
int i = BitConverter.ToInt32(IntBytes, 0x00);
return i;
}
public static int ReadBigEndainInt(Stream ms) public static int ReadBigEndainInt(Stream ms)
{ {
byte[] IntBytes = new byte[4]; byte[] IntBytes = new byte[4];