Improve some stuffs

This commit is contained in:
SilicaAndPina 2019-05-07 07:06:18 -07:00
parent 2379bf30e7
commit 15bb8ac5b4
7 changed files with 195 additions and 171 deletions

BIN
.vs/AppInfoParser/v15/.suo Normal file

Binary file not shown.

View File

@ -2,5 +2,5 @@
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/></startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup>
</configuration>

View File

@ -28,13 +28,12 @@ namespace CXML
TYPE_ID_INT
};
class Parser
class CXMLParser
{
private bool DECODE_VAG = true;
private bool DECODE_GIM = true;
private static bool _checkMagicNumber()
{
String Magic = Tools.ReadStringAt(InfoFile, 0x00);
if (Magic.StartsWith("PSMA"))
@ -54,6 +53,12 @@ namespace CXML
return false;
}
}
private static string _lastFileName = "";
static String MainDir = "";
static String FileDir = "";
static String XMLFilename = "";
static FileStream InfoFile;
@ -73,12 +78,13 @@ namespace CXML
static BinaryReader bFloatArrayTable;
static BinaryReader bIntArrayTable;
static BinaryReader bStylesIDTable;
static BinaryReader bStringIDTable;
static XmlWriter XMLFile;
public static void Init(string Path, bool CheckMagic = true)
public static void Init(string path, bool CheckMagic = true)
{
InfoFile = File.Open(Path, FileMode.Open, FileAccess.Read);
InfoFile = File.Open(path, FileMode.Open, FileAccess.Read);
if(CheckMagic)
{
if (!_checkMagicNumber())
@ -104,6 +110,17 @@ namespace CXML
bFloatArrayTable = new BinaryReader(FloatArrayTable);
bIntArrayTable = new BinaryReader(IntArrayTable);
bStylesIDTable = new BinaryReader(StylesIDTable);
bStringIDTable = new BinaryReader(StringIDTable);
MainDir = Path.GetFileNameWithoutExtension(path);
FileDir = Path.Combine(MainDir, "files");
XMLFilename = Path.GetFileNameWithoutExtension(path) + ".xml";
if (Directory.Exists(MainDir))
Directory.Delete(MainDir, true);
if (!Directory.Exists(FileDir))
Directory.CreateDirectory(FileDir);
return;
}
@ -310,17 +327,19 @@ namespace CXML
public static void DecompileCXML(String CXMLFile, bool force = false)
{
if(Directory.Exists("files"))
Directory.Delete("files", true);
Directory.CreateDirectory(MainDir);
Term();
Init(CXMLFile,force);
XmlWriterSettings XMLSettings = new XmlWriterSettings();
XMLSettings.Indent = true;
XMLFile = XmlWriter.Create(Path.GetFileNameWithoutExtension(CXMLFile)+".xml", XMLSettings);
XMLFile = XmlWriter.Create(Path.Combine(MainDir, XMLFilename), XMLSettings);
XMLFile.WriteStartDocument();
ReadElement();
ReadElements();
XMLFile.WriteEndDocument();
XMLFile.Flush();
@ -331,25 +350,25 @@ namespace CXML
public static void ProcessFile(String FileName)
{
String Extension = Path.GetExtension(FileName);
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";
if (!Directory.Exists("files/converted/VAGtoWAV"))
Directory.CreateDirectory("files/converted/VAGtoWAV");
if (!Directory.Exists(FileDir+"/converted/VAGtoWAV"))
Directory.CreateDirectory(FileDir + "/converted/VAGtoWAV");
File.WriteAllBytes("files/converted/VAGtoWAV/" + WaveName, WaveData);
File.WriteAllBytes(FileDir + "/converted/VAGtoWAV/" + 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("GimConv/GimConv.exe"))
{
if (!Directory.Exists("files/converted"))
Directory.CreateDirectory("files/converted/GIMtoPNG");
if (!Directory.Exists(FileDir + "/converted/GIMtoPNG"))
Directory.CreateDirectory(FileDir + "/converted/GIMtoPNG");
Console.WriteLine("Decoding GIM.");
@ -359,7 +378,7 @@ namespace CXML
Proc.StartInfo.RedirectStandardOutput = true;
Proc.StartInfo.RedirectStandardError = true;
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory() + "/files/decompressed";
Proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(FileName);
Proc.Start();
Proc.WaitForExit();
Console.WriteLine(Proc.StandardOutput.ReadToEnd());
@ -368,7 +387,24 @@ namespace CXML
}
}
if (Extension == ".zlib")
{
Console.WriteLine("Decompressing " + FileName);
Byte[] FileData = File.ReadAllBytes(FileName);
Byte[] DecompressedData = ZlibStream.UncompressBuffer(FileData);
Extension = Tools.GetFileExtension(DecompressedData);
if (!Directory.Exists(FileDir + "/decompressed"))
Directory.CreateDirectory(FileDir + "/decompressed");
String DecompressedFilename = FileDir + "/decompressed /" + Path.GetFileNameWithoutExtension(FileName) + Extension;
Console.WriteLine("Decompressed file written to: " + DecompressedFilename);
File.WriteAllBytes(DecompressedFilename, DecompressedData);
ProcessFile(DecompressedFilename);
}
}
public static void ReadAttribute(String ElementName = "")
{
@ -377,6 +413,7 @@ namespace CXML
String AttributeName = Tools.ReadStringAt(StringTable, AttributePtr);
object AttributeValue = "";
Console.WriteLine("AttributeType: " + Type.ToString() + " - "+ TreeTable.Position.ToString());
switch (Type)
{
@ -463,9 +500,6 @@ namespace CXML
FileTable.Seek(FilePtr, SeekOrigin.Begin);
FileTable.Read(FileData, 0, FileSz);
if (!Directory.Exists("files"))
Directory.CreateDirectory("files");
int count = 0;
string CounterStr = count.ToString();
do
@ -474,25 +508,15 @@ namespace CXML
CounterStr = count.ToString();
if (count == 0)
CounterStr = "";
FileName = "files/" + ElementName + "-" + AttributeName + CounterStr + Extension;
FileName = Path.Combine(FileDir , ElementName , AttributeName + CounterStr + Extension);
count++;
}
while (File.Exists(FileName));
Console.WriteLine("Writing: " + FileName);
if(Path.GetExtension(FileName) == ".zlib")
{
Console.WriteLine("Decompressing " + FileName);
Byte[] DecompressedData = ZlibStream.UncompressBuffer(FileData);
String Extension = Tools.GetFileExtension(DecompressedData);
if (!Directory.Exists("files/decompressed"))
Directory.CreateDirectory("files/decompressed");
String DecompressedFilename = "files/decompressed/" + ElementName + "-" + AttributeName + CounterStr + Extension;
Console.WriteLine("Decompressed file written to: " + DecompressedFilename);
File.WriteAllBytes(DecompressedFilename, DecompressedData);
ProcessFile(DecompressedFilename);
}
if (!Directory.Exists(Path.GetDirectoryName(FileName)))
Directory.CreateDirectory(Path.GetDirectoryName(FileName));
File.WriteAllBytes(FileName, FileData);
ProcessFile(FileName);
@ -501,7 +525,16 @@ namespace CXML
break;
case AttributeType.TYPE_ID_STRING_LOOPBACK:
int StringIdTableOffset = bTreeTable.ReadInt32();
AttributeValue = Tools.ReadStringAt(StringIDTable, StringIdTableOffset + 0x4);
StringIDTable.Seek(StringIdTableOffset, SeekOrigin.Begin);
int LoopbackPtr = bStringIDTable.ReadInt32();
int StringPtr = Tools.ReadIntAt(TreeTable, LoopbackPtr);
string LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
Console.WriteLine("Loopback: " + LoopbackAttribute);
AttributeValue = Tools.ReadString(StringIDTable);
TreeTable.Seek(4, SeekOrigin.Current);
break;
case AttributeType.TYPE_ID_STRING:
@ -511,14 +544,18 @@ namespace CXML
case AttributeType.TYPE_ID_INT_LOOPBACK:
int IntIdTableOffset = bTreeTable.ReadInt32();
IntIDTable.Seek(IntIdTableOffset, SeekOrigin.Begin);
int Loopback = bIntIDTable.ReadInt32();
LoopbackPtr = bIntIDTable.ReadInt32();
StringPtr = Tools.ReadIntAt(TreeTable, LoopbackPtr);
int IDValue = bIntIDTable.ReadInt32();
int StringPtr = Tools.ReadIntAt(TreeTable, Loopback);
String LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
LoopbackAttribute = Tools.ReadStringAt(StringTable, StringPtr);
Console.WriteLine("Loopback: " + LoopbackAttribute);
AttributeValue = IDValue.ToString("X8");
TreeTable.Seek(4, SeekOrigin.Current);
break;
case AttributeType.TYPE_ID_INT:
@ -540,7 +577,7 @@ namespace CXML
XMLFile.Flush();
}
public static void ReadElement()
public static void ReadElements()
{
int ElementPtr = bTreeTable.ReadInt32();
@ -577,7 +614,7 @@ namespace CXML
if (FirstChild != -1)
{
TreeTable.Seek(FirstChild, SeekOrigin.Begin);
ReadElement();
ReadElements();
}
@ -587,7 +624,7 @@ namespace CXML
if (NextSibling != -1)
{
TreeTable.Seek(NextSibling, SeekOrigin.Begin);
ReadElement();
ReadElements();
}
}

View File

@ -8,7 +8,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>CXMLDecompiler</RootNamespace>
<AssemblyName>CXMLDecompiler</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>

View File

@ -9,6 +9,8 @@ namespace CXMLCli
{
static void Main(string[] args)
{
//args = "src20.vag -iv".Split(' ');
bool Check = true;
if (args.Length == 0)
@ -49,7 +51,7 @@ namespace CXMLCli
return;
}
CXML.Parser.Init(path, Check);
CXML.CXMLParser.Init(path, Check);
if (ArgsFull.Contains("-f") || ArgsFull.Contains("--force"))
@ -65,66 +67,66 @@ namespace CXMLCli
if (ArgsFull.Contains("-tt") || ArgsFull.Contains("--dump-tree"))
{
Console.WriteLine("Dumping tree table.");
File.WriteAllBytes("tree-table.bin", CXML.Parser.GetTreeTable());
File.WriteAllBytes("tree-table.bin", CXML.CXMLParser.GetTreeTable());
}
if (ArgsFull.Contains("-ist") || ArgsFull.Contains("--dump-string-id"))
{
Console.WriteLine("Dumping string ID table.");
File.WriteAllBytes("string-id-table.bin", CXML.Parser.GetStringIDTable());
File.WriteAllBytes("string-id-table.bin", CXML.CXMLParser.GetStringIDTable());
}
if (ArgsFull.Contains("-iit") || ArgsFull.Contains("--dump-int-id"))
{
Console.WriteLine("Dumping int ID table.");
File.WriteAllBytes("int-id-table.bin", CXML.Parser.GetIntIDTable());
File.WriteAllBytes("int-id-table.bin", CXML.CXMLParser.GetIntIDTable());
}
if (ArgsFull.Contains("-st") || ArgsFull.Contains("--dump-string"))
{
Console.WriteLine("Dumping string table.");
File.WriteAllBytes("string-table.bin",CXML.Parser.GetStringTable());
File.WriteAllBytes("string-table.bin",CXML.CXMLParser.GetStringTable());
}
if (ArgsFull.Contains("-ct") || ArgsFull.Contains("--dump-char"))
{
Console.WriteLine("Dumping char table.");
File.WriteAllBytes("char-table.bin", CXML.Parser.GetCharTable());
File.WriteAllBytes("char-table.bin", CXML.CXMLParser.GetCharTable());
}
if (ArgsFull.Contains("-sit") || ArgsFull.Contains("--dump-style-id"))
{
Console.WriteLine("Dumping style ID table.");
File.WriteAllBytes("style-id-table.bin", CXML.Parser.GetStyleIDTable());
File.WriteAllBytes("style-id-table.bin", CXML.CXMLParser.GetStyleIDTable());
}
if (ArgsFull.Contains("-iat") || ArgsFull.Contains("--dump-int-array"))
{
Console.WriteLine("Dumping int array table.");
File.WriteAllBytes("int-array-table.bin", CXML.Parser.GetIntArrayTable());
File.WriteAllBytes("int-array-table.bin", CXML.CXMLParser.GetIntArrayTable());
}
if (ArgsFull.Contains("-fat") || ArgsFull.Contains("--dump-float-array"))
{
Console.WriteLine("Dumping float array table.");
File.WriteAllBytes("float-array-table.bin", CXML.Parser.GetFloatArrayTable());
File.WriteAllBytes("float-array-table.bin", CXML.CXMLParser.GetFloatArrayTable());
}
if (ArgsFull.Contains("-ft") || ArgsFull.Contains("--dump-tree"))
{
Console.WriteLine("Dumping file table.");
File.WriteAllBytes("file-table.bin", CXML.Parser.GetTreeTable());
File.WriteAllBytes("file-table.bin", CXML.CXMLParser.GetTreeTable());
}
if (ArgsFull.Contains("-d") || ArgsFull.Contains("--decompile") || args.Length == 1)
{
Console.WriteLine("Decompiling.");
CXML.Parser.DecompileCXML(path, Check);
CXML.CXMLParser.DecompileCXML(path, Check);
Console.WriteLine("\n\nDECOMPILATION COMPLETE!");
Console.ReadKey();
}

View File

@ -54,10 +54,6 @@ namespace General
{
return ".zlib";
}
else if (IsGim(Bytes))
{
return ".gim";
}
else if (IsRcf(Bytes))
{
return ".rcs";
@ -70,6 +66,10 @@ namespace General
{
return ".vag";
}
else if (IsGim(Bytes))
{
return ".gim";
}
else
{
return ".bin";
@ -196,18 +196,38 @@ namespace General
return i;
}
public static int ReadBigEndainIntAt(Stream ms, int location)
{
long ogPos = ms.Position;
ms.Seek(location, SeekOrigin.Begin);
int i = ReadBigEndainInt(ms);
ms.Seek(ogPos, SeekOrigin.Begin);
return i;
}
public static int ReadBigEndainInt(Stream ms)
{
byte[] IntBytes = new byte[4];
ms.Read(IntBytes, 0x00, 4);
IntBytes = IntBytes.Reverse().ToArray();
int i = BitConverter.ToInt32(IntBytes, 0x00);
return i;
}
public static String ReadString(Stream ms, int limit = -1)
{
int i = 0xFF;
int counter = 0;
MemoryStream StringStream = new MemoryStream();
do
{
i = ms.ReadByte();
if (i == 0 && i != limit)
if (i == 0 || counter == limit)
break;
StringStream.WriteByte((byte)i);
counter += 1;
}
while (true);

View File

@ -13,7 +13,7 @@ namespace VAG
{
class VAGAudio
{
static int[,] HEVAGCoeffTable = new int[,]
private static int[,] HEVAGCoeffTable = new int[,]
{
{ 0, 0, 0, 0 },
{ 7680, 0, 0, 0 },
@ -144,7 +144,6 @@ namespace VAG
{ 13064, -4075, -2824, 1877 },
{ 5333, 2999, 775, -1132 },
};
private static byte[] WriteWaveHeader(byte[] PCMData, int channels, int samplerate)
{
MemoryStream ms = new MemoryStream();
@ -161,8 +160,8 @@ namespace VAG
bw.Write((short)1);
bw.Write((short)channels);
bw.Write(samplerate);
bw.Write(samplerate * channels * 2);
bw.Write((short)(channels * 2));
bw.Write((samplerate * 16 * channels)/8);
bw.Write((short)(16 * channels));
bw.Write((short)16);
Tools.WriteStringToStream(ms, "data");
@ -172,72 +171,76 @@ namespace VAG
ms.Seek(0x00, SeekOrigin.Begin);
return ms.ToArray();
}
public static FileStream VagStream;
public static void Init(string VagFile)
{
VagStream = new FileStream(VagFile, FileMode.Open, FileAccess.Read);
if (Tools.ReadStringAt(VagStream, 0x00) != "VAGp")
throw new Exception("Not a VAG file.");
}
public static byte[] Vag2Wav(string VagFile)
{
byte[] FileData = File.ReadAllBytes(VagFile);
if(Tools.IsVAG(FileData))
{
byte[] PCMData = DecodePCM(FileData);
byte[] WAVData = WriteWaveHeader(PCMData, GetChannels(VagFile), GetSampleRate(VagFile));
return WAVData;
}
throw new Exception("Not a VAG file.");
Init(VagFile);
byte[] PCMData = DecodePCM();
byte[] WAVData = WriteWaveHeader(PCMData, 1, GetSampleRate());
return WAVData;
}
public static int GetChannels(string VagFile)
public static int GetChannels()
{
FileStream VagStream = new FileStream(VagFile, FileMode.Open, FileAccess.Read);
VagStream.Seek(0x1E, SeekOrigin.Begin);
int ChannelCount = VagStream.ReadByte();
if (ChannelCount == 0)
ChannelCount = 1; //Its most likely mono...
VagStream.Close();
if (ChannelCount >= 2)
ChannelCount = 2;
else
ChannelCount = 1;
return ChannelCount;
}
public static string GetFilename(string VagFile)
{
FileStream VagStream = new FileStream(VagFile, FileMode.Open, FileAccess.Read);
String FileName = Tools.ReadStringAt(VagStream, 0x20);
VagStream.Close();
return FileName;
return Tools.ReadStringAt(VagStream, 0x20);
}
public static int GetSampleRate(String VagFile)
public static int GetSampleRate()
{
FileStream VagStream = new FileStream(VagFile, FileMode.Open, FileAccess.Read);
VagStream.Seek(0x12, SeekOrigin.Begin);
return Tools.ReadBigEndainIntAt(VagStream, 0x10);
}
//IDK Either, ask sony why they didnt just use an int16
int SampleRate = VagStream.ReadByte() * 256 + VagStream.ReadByte();
VagStream.Close();
return SampleRate;
public static int GetWaveformDataSize()
{
return Tools.ReadBigEndainIntAt(VagStream, 0x0C);
}
public static byte[] DecodePCM(byte[] VagFile)
public static byte[] DecodePCM()
{
int Hist = 0;
int Hist2 = 0;
int Hist3 = 0;
int Hist4 = 0;
MemoryStream VagStream = Tools.ByteToStream(VagFile);
int FileSize = GetWaveformDataSize() - 0x40;
int Channels = GetChannels();
bool IsStereo = (Channels > 1);
BinaryReader VagReader = new BinaryReader(VagStream);
MemoryStream PCMStream = new MemoryStream();
BinaryWriter PCMWriter = new BinaryWriter(PCMStream);
VagStream.Seek(0x40, SeekOrigin.Begin);
while (VagStream.Position < VagStream.Length)
{
while (VagStream.Position < FileSize)
{
byte DecodingCoefficent = VagReader.ReadByte();
int ShiftBy = DecodingCoefficent & 0xf;
int PredictNr = DecodingCoefficent >> 0x4;
@ -254,97 +257,59 @@ namespace VAG
}
else
{
for (int i = 0; i < 14; i++)
{
//First Byte:
byte ADPCMData = VagReader.ReadByte();
int SampleFlags = ADPCMData & 0xF;
int Coefficent;
int Sample;
if (SampleFlags > 7)
short Sample;
for(int ii = 0; ii <= 1; ii++)
{
SampleFlags -= 16;
if (SampleFlags > 7)
{
SampleFlags -= 16;
}
if (PredictNr < 128)
{
Coefficent = Hist * HEVAGCoeffTable[PredictNr, 0] + Hist2 * HEVAGCoeffTable[PredictNr, 1] + Hist3 * HEVAGCoeffTable[PredictNr, 2] + Hist4 * HEVAGCoeffTable[PredictNr, 3];
}
else
{
Coefficent = 0;
}
Sample = (short)(Coefficent / 32 + (SampleFlags << 20 - ShiftBy) + 128 >> 8);
PCMWriter.Write(Sample);
Hist4 = Hist3;
Hist3 = Hist2;
Hist2 = Hist;
Hist = Sample;
SampleFlags = ADPCMData >> 4;
}
if (PredictNr < 128)
{
Coefficent = Hist * HEVAGCoeffTable[PredictNr, 0] + Hist2 * HEVAGCoeffTable[PredictNr, 1] + Hist3 * HEVAGCoeffTable[PredictNr, 2] + Hist4 * HEVAGCoeffTable[PredictNr, 3];
}
else
{
Coefficent = 0;
}
Sample = Coefficent / 32 + (SampleFlags << 20 - ShiftBy) + 128 >> 8;
//Apparently unchecked(short) isnt good enough?
//I guess it cant be modulo?
//IDK im just doing what i saw in the decompiled code.
if (Sample > 32767)
{
Sample = 32767;
}
else if (Sample < -32768)
{
Sample = -32768;
}
PCMWriter.Write((short)Sample);
//Second Byte:
Hist4 = Hist3;
Hist3 = Hist2;
Hist2 = Hist;
Hist = Sample;
SampleFlags = ADPCMData >> 4;
if (SampleFlags > 7)
{
SampleFlags -= 16;
}
if (PredictNr < 128)
{
Coefficent = Hist * HEVAGCoeffTable[PredictNr, 0] + Hist2 * HEVAGCoeffTable[PredictNr, 1] + Hist3 * HEVAGCoeffTable[PredictNr, 2] + Hist4 * HEVAGCoeffTable[PredictNr, 3];
}
else
{
Coefficent = 0;
}
Sample = Coefficent / 32 + (SampleFlags << 20 - ShiftBy) + 128 >> 8;
if (Sample > 32767)
{
Sample = 32767;
}
else if (Sample < -32768)
{
Sample = -32768;
}
PCMWriter.Write((short)Sample);
Hist4 = Hist3;
Hist3 = Hist2;
Hist2 = Hist;
Hist = Sample;
}
}
/*
* Arg im mad because i know how to get left/right channels
* But i have no idea how to combine them
* So lets just get one and call it a day.
*/
if (IsStereo)
VagStream.Seek(16, SeekOrigin.Current);
}
PCMStream.Seek(0x00, SeekOrigin.Begin);
byte[] PCMData = PCMStream.ToArray();
VagReader.Close();
VagStream.Close();
PCMWriter.Close();
PCMStream.Close();