using CXMLDecompiler; 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 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) { foreach(string arg in args) { 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) { // 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); bool windows32S = Environment.OSVersion.Platform.Equals(PlatformID.Win32S); bool windowsCE = Environment.OSVersion.Platform.Equals(PlatformID.WinCE); if (windowsNT || windows32 || windows32S || windowsCE) { 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!"); } if (args.Length == 0) { Console.WriteLine("-- CXML Decompiler --"); Console.WriteLine("Required Arguments:"); 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"); Console.WriteLine("\t-cc --compress Compress back to .Z File"); Console.WriteLine("\t-f --force Dont check magic number."); Console.WriteLine("\t-dt --dump-tables Dump ALL tables."); Console.WriteLine("\t-tt --dump-tree Dump tree table."); Console.WriteLine("\t-idt --dump-id Dump id 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-wt --dump-wstring Dump wstring table."); Console.WriteLine("\t-ht --dump-hash Dump hash 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-ft --dump-file Dump file table."); Console.WriteLine("\t-le --little-endian Decode ints as Little Endian"); Console.WriteLine("\t-be --big-endian Decode ints as Big Endian"); Console.WriteLine("\t-ps3 --playstation-3 Use the old CXML Format used back on PS3."); Console.WriteLine("\t-p --process-files Process Extracted Files"); Console.WriteLine("\t-nr --no-recursive Do not recursively decompile .RCS to XML"); 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-s --symbols Use Symbol File (.rcd)"); Console.WriteLine("Example Decompile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " -i common_resource.rco -o common_resource.xml -d -p"); Console.WriteLine("Example Compile: " + Path.GetFileName(Assembly.GetEntryAssembly().Location) + " -i common_resource.xml -o common_resource.rco -c"); return 0; } if (args.Length == 1) { 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(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(args, "-be") || HasArg(args, "--big-endian")) { FileEndianness = Endianness.LITTLE_ENDIAN; } if (HasArg(args, "-ps3") || HasArg(args, "--playstation-3")) { ForcePs3 = true; } if (HasArg(args, "-iv") || HasArg(args, "--is-vag")) { byte[] WaveData = VAG.VAGAudio.Vag2Wav(InputFilePath); Console.WriteLine("Writing "+ OutputFilePath); File.WriteAllBytes(OutputFilePath, WaveData); return 0; } if (HasArg(args, "-f") || HasArg(args, "--force")) { Check = false; } if (HasArg(args, "-dc") || HasArg(args, "--decompress")) { Console.WriteLine("Decompressing " + InputFilePath); Byte[] FileData = File.ReadAllBytes(InputFilePath); Byte[] DecompressedData = ZlibStream.UncompressBuffer(FileData); string Extension = Tools.GetFileExtension(DecompressedData); File.WriteAllBytes(OutputFilePath, DecompressedData); return 0; } if (HasArg(args, "-cc") || HasArg(args, "--compress")) { Console.WriteLine("Compressing " + InputFilePath); Byte[] FileData = File.ReadAllBytes(InputFilePath); Byte[] CompressedData = ZlibStream.CompressBuffer(FileData); string Extension = Tools.GetFileExtension(CompressedData); File.WriteAllBytes(OutputFilePath, CompressedData); return 0; } CXMLReader cxmlParser = new CXMLReader(); if(!HasArg(args, "-c") && !HasArg(args, "--compile")) // If not Compiling { 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(args, "-tt") || HasArg(args, "--dump-tree")) { Console.WriteLine("Dumping tree table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "tree-table.bin"), cxmlParser.GetTreeTable()); } if (HasArg(args, "-idt") || HasArg(args, "--dump-id")) { Console.WriteLine("Dumping ID table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "id-table.bin"), cxmlParser.GetIDTable()); } if (HasArg(args, "-iht") || HasArg(args, "--dump-hash-id")) { Console.WriteLine("Dumping hash ID table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "hash-id-table.bin"), cxmlParser.GetHashIDTable()); } if (HasArg(args, "-st") || HasArg(args, "--dump-string")) { Console.WriteLine("Dumping string table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "string-table.bin"),cxmlParser.GetStringTable()); } if (HasArg(args, "-wt") || HasArg(args, "--dump-wstring")) { Console.WriteLine("Dumping wstring table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "wstring-table.bin"), cxmlParser.GetWStringTable()); } if (HasArg(args, "-ht") || HasArg(args, "--dump-hash")) { Console.WriteLine("Dumping hash table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "hash-table.bin"), cxmlParser.GetHashTable()); } if (HasArg(args, "-iat") || HasArg(args, "--dump-int-array")) { Console.WriteLine("Dumping int array table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "int-array-table.bin"), cxmlParser.GetIntArrayTable()); } if (HasArg(args, "-fat") || HasArg(args, "--dump-float-array")) { Console.WriteLine("Dumping float array table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "float-array-table.bin"), cxmlParser.GetFloatArrayTable()); } if (HasArg(args, "-ft") || HasArg(args, "--dump-tree")) { Console.WriteLine("Dumping file table."); File.WriteAllBytes(Path.Combine(GetTablesFolder(), "file-table.bin"), cxmlParser.GetFileTable()); } if (HasArg(args, "-p") || HasArg(args, "--process-files")) { cxmlParser.ProcessFiles = true; } if (HasArg(args, "-w") || HasArg(args, "--wait-exit")) { WaitExit = true; } if (HasArg(args, "-nr") || HasArg(args, "--no-recursive")) { cxmlParser.NoRecursive = true; } 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(InputFilePath, OutputFilePath); Console.WriteLine("\n\nDECOMPILATION COMPLETE!"); if(WaitExit) Console.ReadKey(); } else if (HasArg(args, "-c") || HasArg(args, "--compile")) { Console.WriteLine("Compiling: " + InputFilePath); CXMLBuilder builder = new CXMLBuilder(); builder.BuildCXML(InputFilePath, OutputFilePath); Console.WriteLine("\n\nCOMPILATION COMPLETE!"); if (WaitExit) Console.ReadKey(); } return 0; } } }