diff --git a/Hack.Xenosaga/App.config b/Hack.Xenosaga/App.config
new file mode 100644
index 0000000..8227adb
--- /dev/null
+++ b/Hack.Xenosaga/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Hack.Xenosaga/Common/Extension.cs b/Hack.Xenosaga/Common/Extension.cs
new file mode 100644
index 0000000..3df801f
--- /dev/null
+++ b/Hack.Xenosaga/Common/Extension.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hack.Xenosaga.Common
+{
+ public static class Extension
+ {
+ ///
+ /// Ecrit un bloc d'octet dans le flux actuel en utilisant des données lues dans une mémoire tampon (la position du flux actuel reste inchangée).
+ ///
+ /// Mémoire tamon dans laquelle lire les données
+ /// Dans buffer, offset d'octet de base zéro d'où commencer la copie des octets dans le flux actuel
+ /// Nombre maximal d'octets à écrire
+ /// Position dans le flux actuel où écrire les données
+ public static void Write(this MemoryStream ms, byte[] buffer, int offset, int count, long position)
+ {
+ long pos = ms.Position;
+
+ ms.Position = position;
+
+ ms.Write(buffer, offset, count);
+
+ ms.Position = pos;
+ }
+
+ ///
+ /// Lit une séquence de 4 octets à partir du flux actuel et avance la position dans le flux du nombre d'octets lus.
+ ///
+ /// Valeur lue
+ public static UInt32 Read(this MemoryStream ms)
+ {
+ UInt32 value = 0;
+
+ for (int i = 0; i < 4; i++)
+ value += (UInt32)(ms.ReadByte() << (i * 8) );
+
+ return value;
+ }
+ }
+}
diff --git a/Hack.Xenosaga/Common/Functions.cs b/Hack.Xenosaga/Common/Functions.cs
index 8f67690..59bfc4b 100644
--- a/Hack.Xenosaga/Common/Functions.cs
+++ b/Hack.Xenosaga/Common/Functions.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Text;
@@ -9,17 +10,20 @@ namespace Hack.Xenosaga.Common
public static void usage()
{
Trace.WriteLine("");
- Trace.WriteLine("xenosaga [regroup]");
+ Trace.WriteLine("xenosaga [encode/regroup]");
Trace.WriteLine(" option : -l = List files from index");
Trace.WriteLine(" -u = Unpack files from index");
Trace.WriteLine(" -p = Pack files from index");
+ Trace.WriteLine(" -e = Extract text from file");
Trace.WriteLine(" file : Index file (the first one of each decade : xenosaga.00, xenosaga.10, xenosaga.20...)");
- Trace.WriteLine(" regroup : true to regroup all files in only one (ex: 11, 12, 13 in 11) ; false or empty (default) to keep the same system of increment files");
+ Trace.WriteLine(" encode : (-e) Encoding of the output/input file (ANSI( default), ASCII, UTF8, UNICODE)");
+ Trace.WriteLine(" regroup : (-p) true to pack all files in only one (ex: 11, 12, 13 in 11) ; false or empty (default) to keep the same system of increment files");
}
public static bool CheckArgs(string[] args, out Variables.stArgs listArgs)
{
listArgs = new Variables.stArgs();
+ List listActions = new List() { "-l", "-p", "-u", "-e", "-i" };
Trace.Write("Checking arguments : ");
@@ -29,13 +33,13 @@ namespace Hack.Xenosaga.Common
return false;
}
- if (args[0] != "-l" && args[0] != "-p" && args[0] != "-u" && args[0] != "-e")
+ if (!listActions.Contains(args[0]))
{
Trace.WriteLine("Incorrect parameter - unknown ");
return false;
}
- if (!File.Exists(args[1]))
+ if (!File.Exists(args[1]) && !Directory.Exists(args[1]))
{
Trace.WriteLine("Incorrect parameter - unknown ");
return false;
@@ -46,11 +50,39 @@ namespace Hack.Xenosaga.Common
Trace.WriteLine("Incorrect parameter - unknown ");
return false;
}
+ if ((args.Length == 3 && (args[0] == "-e" || args[0] == "-i")) && (args[2] != "ANSI" && args[2] != "ASCII" && args[2] != "UTF8" && args[2] != "UNICODE"))
+ {
+ Trace.WriteLine("Incorrect parameter - unknown ");
+ return false;
+ }
listArgs.option = args[0];
listArgs.filename = args[1];
if (args.Length == 3 && listArgs.option == "-p")
listArgs.regroup = args[2] == "true" ? true : false;
+ listArgs.encode = args.Length == 2 ? Encoding.Default : null;
+ if (args.Length == 3 && (listArgs.option == "-e" || listArgs.option == "-i"))
+ {
+ switch (args[2])
+ {
+ case "ASCII":
+ listArgs.encode = Encoding.ASCII;
+ break;
+
+ case "UTF8":
+ listArgs.encode = Encoding.UTF8;
+ break;
+
+ case "UNICODE":
+ listArgs.encode = Encoding.Unicode;
+ break;
+
+ case "ANSI":
+ default:
+ listArgs.encode = Encoding.Default;
+ break;
+ }
+ }
Trace.WriteLine("OK");
@@ -88,5 +120,15 @@ namespace Hack.Xenosaga.Common
}
}
+ public static void Padding(MemoryStream ms)
+ {
+ long size = ms.Length;
+
+ while (size % 4 != 0)
+ {
+ ms.WriteByte(0);
+ size++;
+ }
+ }
}
}
diff --git a/Hack.Xenosaga/Common/Variables.cs b/Hack.Xenosaga/Common/Variables.cs
index c402772..84265e5 100644
--- a/Hack.Xenosaga/Common/Variables.cs
+++ b/Hack.Xenosaga/Common/Variables.cs
@@ -1,4 +1,5 @@
-
+using System.Text;
+
namespace Hack.Xenosaga.Common
{
public class Variables
@@ -7,6 +8,7 @@ namespace Hack.Xenosaga.Common
{
public string option;
public string filename;
+ public Encoding encode;
public bool regroup;
}
@@ -14,8 +16,9 @@ namespace Hack.Xenosaga.Common
public const string dirExtract = "02-EXTRACT/";
public const string dirInsert = "03-INSERT/";
public const string dirPack = "04-PACK/";
+ public const string dirFinal = "05-FINAL/";
public const string tblCard = "TABLES/card_ANSI.tbl";
-
+ public const string tblEvt = "TABLES/evt_ANSI.tbl";
}
}
diff --git a/Hack.Xenosaga/Hack.Xenosaga.csproj b/Hack.Xenosaga/Hack.Xenosaga.csproj
index b930f31..9e63fb2 100644
--- a/Hack.Xenosaga/Hack.Xenosaga.csproj
+++ b/Hack.Xenosaga/Hack.Xenosaga.csproj
@@ -39,14 +39,9 @@
Hack.Xenosaga.Xenosaga
-
- Include\cCalculation.dll
-
-
- Include\cPointers.dll
-
-
- Include\cTable.dll
+
+ False
+ ..\..\Hack.Tools\Build\bin\Debug\Hack.Tools.dll
@@ -57,9 +52,11 @@
+
+
diff --git a/Hack.Xenosaga/Process/JavaClass.cs b/Hack.Xenosaga/Process/JavaClass.cs
new file mode 100644
index 0000000..59d33f1
--- /dev/null
+++ b/Hack.Xenosaga/Process/JavaClass.cs
@@ -0,0 +1,1977 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using Hack.Tools.Common;
+
+namespace Hack.Xenosaga.Process
+{
+ public class evtClass
+ {
+ public struct stFile
+ {
+ public UInt32 namePos;
+ public UInt32 nameLength;
+ public UInt32 filePos;
+ public UInt32 fileLength;
+ public string name;
+ public byte[] file;
+ }
+
+ public UInt32 id { get; private set; }
+ public UInt16 unkAdr4 { get; private set; }
+ public UInt16 unkAdr6 { get; private set; }
+ public int fileSize { get; private set; }
+ public int adrNames { get; private set; }
+ public UInt16 unkAdr16 { get; private set; }
+ public int nbFiles { get; private set; }
+ public List listFiles { get; private set; }
+
+ #region Constructors
+
+ public evtClass()
+ { }
+
+ public evtClass(string pathName)
+ {
+ init(pathName);
+ }
+
+ public evtClass(BinaryReader br)
+ {
+ init(br);
+ }
+
+ ~evtClass()
+ { }
+
+ #endregion
+
+ #region Privates methods
+
+ private byte[] readFileBytes(BinaryReader br, long pos, int size)
+ {
+ byte[] file;
+ long posSave = br.BaseStream.Position;
+
+ br.BaseStream.Position = pos;
+
+ file = br.ReadBytes(size);
+
+ br.BaseStream.Position = posSave;
+
+ return file;
+ }
+
+ private string readFileName(BinaryReader br, long pos, int size)
+ {
+ string name = "";
+ long posSave = br.BaseStream.Position;
+
+ br.BaseStream.Position = pos;
+
+ name = br.BytestoStringAscii(size);
+
+ br.BaseStream.Position = posSave;
+
+ return name;
+
+ }
+
+ #endregion
+
+ #region Publics methods
+
+ ///
+ /// Init an evt file (archive)
+ ///
+ /// Path of the file
+ ///
+ public bool init(string pathName)
+ {
+ bool result = true;
+
+ using (BinaryReader br = new BinaryReader(File.Open(pathName, FileMode.Open)))
+ {
+ result = init(br);
+ }
+
+ return result;
+ }
+
+ ///
+ /// Init an evt file (archive)
+ ///
+ /// BinaryReader of the file
+ ///
+ public bool init(BinaryReader br)
+ {
+ listFiles = new List();
+
+ id = br.ReadUInt32();
+ if (id != 0x30304C46)
+ {
+ Trace.WriteLine("ERROR : Not a valid evt file");
+ return false;
+ }
+
+ unkAdr4 = br.ReadUInt16();
+ unkAdr6 = br.ReadUInt16();
+ fileSize = br.ReadInt32();
+ adrNames = br.ReadInt32();
+ unkAdr16 = br.ReadUInt16();
+ nbFiles = br.ReadInt16();
+
+ for (int i = 0; i < nbFiles; i++)
+ {
+ stFile st = new stFile();
+
+ st.namePos = br.ReadUInt32();
+ st.nameLength = br.ReadUInt32();
+ st.name = readFileName(br, (long)st.namePos, (int)st.nameLength);
+
+ st.filePos = br.ReadUInt32();
+ st.fileLength = br.ReadUInt32();
+ st.file = readFileBytes(br, (long)st.filePos, (int)st.fileLength);
+
+ listFiles.Add(st);
+ }
+
+ return true;
+ }
+
+ #endregion
+ }
+
+ public class JavaClass
+ {
+ public interface iCONSTANT
+ {
+ byte tag { get; set; }
+ }
+
+ private class CONSTANT_Class_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 name_index;
+
+ public CONSTANT_Class_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Fieldref_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 class_index;
+ public Int16 name_and_type_index;
+
+ public CONSTANT_Fieldref_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Methodref_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 class_index;
+ public Int16 name_and_type_index;
+
+ public CONSTANT_Methodref_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_InterfaceMethodref_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 class_index;
+ public Int16 name_and_type_index;
+
+ public CONSTANT_InterfaceMethodref_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_String_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 string_index;
+
+ public CONSTANT_String_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Integer_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int32 bytes;
+
+ public CONSTANT_Integer_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Float_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int32 bytes;
+
+ public CONSTANT_Float_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Long_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int32 high_bytes;
+ public Int32 low_bytes;
+
+ public CONSTANT_Long_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Double_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int32 high_bytes;
+ public Int32 low_bytes;
+
+ public CONSTANT_Double_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_NameAndType_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 name_index;
+ public Int16 descriptor_index;
+
+ public CONSTANT_NameAndType_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_Utf8_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 length { get; set; }
+ public byte[] bytes { get; set; }
+
+ public CONSTANT_Utf8_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_MethodHandle_info : iCONSTANT
+ {
+ private byte _tag;
+ public byte reference_kind;
+ public Int16 reference_index;
+
+ public CONSTANT_MethodHandle_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_MethodType_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 descriptor_index;
+
+ public CONSTANT_MethodType_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private class CONSTANT_InvokeDynamic_info : iCONSTANT
+ {
+ private byte _tag;
+ public Int16 bootstrap_method_attr_index;
+ public Int16 name_and_type_index;
+
+ public CONSTANT_InvokeDynamic_info(byte tag)
+ {
+ _tag = tag;
+ }
+
+ public byte tag { get { return _tag; } set { _tag = value; } }
+ }
+
+ private struct stField
+ {
+ public Int16 access_flags;
+ public Int16 name_index;
+ public Int16 descriptor_index;
+ public Int16 attributes_count;
+ public Dictionary attributes;
+ }
+
+ private struct stMethod
+ {
+ public Int16 access_flags;
+ public Int16 name_index;
+ public Int16 descriptor_index;
+ public Int16 attributes_count;
+ public Dictionary attributes;
+ }
+
+ private struct stAttribut
+ {
+ public Int16 attribute_name_index;
+ public long attribute_length;
+ public byte[] info;
+ public List infoString;
+ }
+
+ private struct stOpcode
+ {
+ public byte opcode;
+ public string name;
+ public string type;
+ public string src_t;
+ public string dst_t;
+ public int value;
+ public int value2;
+ public int index;
+ public int count;
+ public int zero;
+ public int jumptarget;
+ public int dim;
+ }
+
+ private byte[] magic;
+ private Int16 minor_version;
+ private Int16 major_version;
+ private Int16 constant_pool_count;
+ private Dictionary constant_pool;
+ private Int16 access_flags;
+ private Int16 this_class;
+ private Int16 super_class;
+ private Int16 interfaces_count;
+ private List interfaces;
+ private Int16 fields_count;
+ private Dictionary fields;
+ private Int16 methods_count;
+ private Dictionary methods;
+ private Int16 attributes_count;
+ private Dictionary attributes;
+
+ //---------------------------------------------------------------------
+
+ #region Constructors
+
+ public JavaClass()
+ { }
+
+ ~JavaClass()
+ { }
+
+ #endregion
+
+ //---------------------------------------------------------------------
+
+ #region Compilation
+
+ private void compilConstants(BinaryWriter bw)
+ {
+ foreach (KeyValuePair constant in constant_pool)
+ {
+ bw.Write(constant.Value.tag);
+
+ switch (constant.Value.tag)
+ {
+ case 1:
+ CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stUtf8.length, 2), 0, 2);
+ bw.Write(stUtf8.bytes);
+ break;
+
+ case 3:
+ CONSTANT_Integer_info stInteger = (CONSTANT_Integer_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stInteger.bytes), 0, 4);
+ break;
+
+ case 4:
+ CONSTANT_Float_info stFloat = (CONSTANT_Float_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stFloat.bytes), 0, 4);
+ break;
+
+ case 5:
+ CONSTANT_Long_info stLong = (CONSTANT_Long_info)constant.Value;
+ bw.Write(stLong.high_bytes);
+ bw.Write(stLong.low_bytes);
+ break;
+
+ case 6:
+ CONSTANT_Double_info stDouble = (CONSTANT_Double_info)constant.Value;
+ bw.Write(stDouble.high_bytes);
+ bw.Write(stDouble.low_bytes);
+ break;
+
+ case 7:
+ CONSTANT_Class_info stClass = (CONSTANT_Class_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stClass.name_index, 2), 0, 2);
+ break;
+
+ case 8:
+ CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stString.string_index, 2), 0, 2);
+ break;
+
+ case 9:
+ CONSTANT_Fieldref_info stFieldref = (CONSTANT_Fieldref_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stFieldref.class_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(stFieldref.name_and_type_index, 2), 0, 2);
+ break;
+
+ case 10:
+ CONSTANT_Methodref_info stMethodref = (CONSTANT_Methodref_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stMethodref.class_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(stMethodref.name_and_type_index, 2), 0, 2);
+ break;
+
+ case 11:
+ CONSTANT_InterfaceMethodref_info stInterfaceMethodref = (CONSTANT_InterfaceMethodref_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stInterfaceMethodref.class_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(stInterfaceMethodref.name_and_type_index, 2), 0, 2);
+ break;
+
+ case 12:
+ CONSTANT_NameAndType_info stNameAndType = (CONSTANT_NameAndType_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stNameAndType.name_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(stNameAndType.descriptor_index, 2), 0, 2);
+ break;
+
+ case 15:
+ CONSTANT_MethodHandle_info stMethodHandle = (CONSTANT_MethodHandle_info)constant.Value;
+ bw.Write(stMethodHandle.reference_kind);
+ bw.Write(IntToByteArrayBE(stMethodHandle.reference_index, 2), 0, 2);
+ break;
+
+ case 16:
+ CONSTANT_MethodType_info stMethodType = (CONSTANT_MethodType_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stMethodType.descriptor_index, 2), 0, 2);
+ break;
+
+ case 18:
+ CONSTANT_InvokeDynamic_info stInvokeDynamic = (CONSTANT_InvokeDynamic_info)constant.Value;
+ bw.Write(IntToByteArrayBE(stInvokeDynamic.bootstrap_method_attr_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(stInvokeDynamic.name_and_type_index, 2), 0, 2);
+ break;
+ }
+ }
+ }
+
+ private void compilInterfaces(BinaryWriter bw)
+ {
+ foreach (Int16 index in interfaces)
+ {
+ bw.Write(IntToByteArrayBE(index, 2), 0, 2);
+ }
+ }
+
+ private void compilFields(BinaryWriter bw)
+ {
+ foreach (KeyValuePair field in fields)
+ {
+ bw.Write(IntToByteArrayBE(field.Value.access_flags, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(field.Value.name_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(field.Value.descriptor_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(field.Value.attributes_count, 2), 0, 2);
+
+ if (field.Value.attributes_count > 0)
+ {
+ foreach (KeyValuePair attribut in field.Value.attributes)
+ {
+ bw.Write(IntToByteArrayBE(attribut.Value.attribute_name_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE((int)attribut.Value.attribute_length, 2), 0, 2);
+ bw.Write(attribut.Value.info);
+ }
+ }
+ }
+ }
+
+ private void compilMethods(BinaryWriter bw)
+ {
+ foreach (KeyValuePair method in methods)
+ {
+ bw.Write(IntToByteArrayBE(method.Value.access_flags, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(method.Value.name_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(method.Value.descriptor_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(method.Value.attributes_count, 2), 0, 2);
+
+ if (method.Value.attributes_count > 0)
+ {
+ foreach (KeyValuePair attribut in method.Value.attributes)
+ {
+ bw.Write(IntToByteArrayBE(attribut.Value.attribute_name_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE((int)attribut.Value.attribute_length, 4), 0, 4);
+
+ if (attribut.Value.attribute_length > 0)
+ bw.Write(attribut.Value.info);
+ }
+ }
+ }
+ }
+
+ private void compilAttributes(BinaryWriter bw)
+ {
+ foreach (KeyValuePair attribut in attributes)
+ {
+ bw.Write(IntToByteArrayBE(attribut.Value.attribute_name_index, 2), 0, 2);
+ bw.Write(IntToByteArrayBE((int)attribut.Value.attribute_length, 4), 0, 4);
+
+ if (attribut.Value.attribute_length > 0)
+ bw.Write(attribut.Value.info);
+ }
+ }
+
+ #endregion
+
+ #region Get data
+
+ private string getConstantValue(Int16 index, bool replace = false)
+ {
+ string value = "";
+
+ byte tag = constant_pool[index].tag;
+
+ switch (tag)
+ {
+ case 1:
+ CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant_pool[index];
+
+ if (stUtf8.length > 0)
+ {
+ if (replace)
+ value = Encoding.UTF8.GetString(stUtf8.bytes).Replace("\n", "\\n");
+ else
+ value = Encoding.UTF8.GetString(stUtf8.bytes);
+ }
+ break;
+
+ case 3:
+ CONSTANT_Integer_info stInteger = (CONSTANT_Integer_info)constant_pool[index];
+
+ value = string.Format("{0:D}", stInteger.bytes);
+ break;
+
+ case 4:
+ CONSTANT_Float_info stFloat = (CONSTANT_Float_info)constant_pool[index];
+
+ value = BitConverter.ToSingle(BitConverter.GetBytes(stFloat.bytes), 0).ToString();
+ break;
+
+ case 5:
+ CONSTANT_Long_info stLong = (CONSTANT_Long_info)constant_pool[index];
+
+ value = (((long)stLong.high_bytes << 32) + stLong.low_bytes).ToString();
+ break;
+
+ case 6:
+ CONSTANT_Double_info stDouble = (CONSTANT_Double_info)constant_pool[index];
+
+ value = BitConverter.ToDouble(BitConverter.GetBytes(((long)stDouble.high_bytes << 32) + stDouble.low_bytes), 0).ToString();
+ break;
+
+ case 7:
+ CONSTANT_Class_info stClass = (CONSTANT_Class_info)constant_pool[index];
+
+ value = getConstantValue(stClass.name_index);
+ break;
+
+ case 8:
+ CONSTANT_String_info stString = (CONSTANT_String_info)constant_pool[index];
+
+ value = getConstantValue(stString.string_index);
+ break;
+
+ case 9:
+ CONSTANT_Fieldref_info stFieldref = (CONSTANT_Fieldref_info)constant_pool[index];
+
+ value = getConstantValue(stFieldref.class_index) + getConstantValue(stFieldref.name_and_type_index);
+ break;
+
+ case 10:
+ CONSTANT_Methodref_info stMethodref = (CONSTANT_Methodref_info)constant_pool[index];
+
+ value = getConstantValue(stMethodref.class_index) + getConstantValue(stMethodref.name_and_type_index);
+ break;
+
+ case 11:
+ CONSTANT_InterfaceMethodref_info stInterfaceMethodref = (CONSTANT_InterfaceMethodref_info)constant_pool[index];
+
+ value = getConstantValue(stInterfaceMethodref.class_index) + getConstantValue(stInterfaceMethodref.name_and_type_index);
+ break;
+
+ case 12:
+ CONSTANT_NameAndType_info stNameAndType = (CONSTANT_NameAndType_info)constant_pool[index];
+
+ value = getConstantValue(stNameAndType.name_index) + getConstantValue(stNameAndType.descriptor_index);
+ break;
+
+ case 15:
+ CONSTANT_MethodHandle_info stMethodHandle = (CONSTANT_MethodHandle_info)constant_pool[index];
+
+ value = getConstantValue(stMethodHandle.reference_index);
+ break;
+
+ case 16:
+ CONSTANT_MethodType_info stMethodType = (CONSTANT_MethodType_info)constant_pool[index];
+
+ value = getConstantValue(stMethodType.descriptor_index);
+ break;
+
+ case 18:
+ CONSTANT_InvokeDynamic_info stInvokeDynamic = (CONSTANT_InvokeDynamic_info)constant_pool[index];
+
+ value = getConstantValue(stInvokeDynamic.bootstrap_method_attr_index) + getConstantValue(stInvokeDynamic.name_and_type_index);
+ break;
+ }
+
+ return value;
+ }
+
+ private byte[] getConstantBytes(Int16 index)
+ {
+ byte tag = constant_pool[index].tag;
+
+ switch (tag)
+ {
+ case 1:
+ CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant_pool[index];
+
+ if (stUtf8.length > 0)
+ return stUtf8.bytes;
+ break;
+ }
+
+ return null;
+ }
+
+ #endregion
+
+ #region Read data
+
+ private void readConstants(BinaryReader br)
+ {
+ constant_pool = new Dictionary();
+
+ constant_pool_count = br.ReadInt16BE();
+ constant_pool_count--;
+
+ for (int i = 1; i < constant_pool_count+1; i++)
+ {
+ byte tag = br.ReadByte();
+
+ switch (tag)
+ {
+ case 1:
+ CONSTANT_Utf8_info cUtf8 = new CONSTANT_Utf8_info(tag);
+ cUtf8.length = br.ReadInt16BE();
+ if (cUtf8.length > 0)
+ cUtf8.bytes = br.ReadBytes(cUtf8.length);
+ constant_pool.Add(i, cUtf8);
+ break;
+
+ case 3:
+ CONSTANT_Integer_info cInteger = new CONSTANT_Integer_info(tag);
+ cInteger.bytes = br.ReadInt32BE();
+ constant_pool.Add(i, cInteger);
+ break;
+
+ case 4:
+ CONSTANT_Float_info cFloat = new CONSTANT_Float_info(tag);
+ cFloat.bytes = br.ReadInt32BE();
+ constant_pool.Add(i, cFloat);
+ break;
+
+ case 5:
+ CONSTANT_Long_info cLong = new CONSTANT_Long_info(tag);
+ cLong.high_bytes = br.ReadInt32BE();
+ cLong.low_bytes = br.ReadInt32BE();
+ constant_pool.Add(i, cLong);
+ break;
+
+ case 6:
+ CONSTANT_Double_info cDouble = new CONSTANT_Double_info(tag);
+ cDouble.high_bytes = br.ReadInt32BE();
+ cDouble.low_bytes = br.ReadInt32BE();
+ constant_pool.Add(i, cDouble);
+ break;
+
+ case 7:
+ CONSTANT_Class_info cClass = new CONSTANT_Class_info(tag);
+ cClass.name_index = br.ReadInt16BE();
+ constant_pool.Add(i, cClass);
+ break;
+
+ case 8:
+ CONSTANT_String_info cString = new CONSTANT_String_info(tag);
+ cString.string_index = br.ReadInt16BE();
+ constant_pool.Add(i, cString);
+ break;
+
+ case 9:
+ CONSTANT_Fieldref_info cFieldref = new CONSTANT_Fieldref_info(tag);
+ cFieldref.class_index = br.ReadInt16BE();
+ cFieldref.name_and_type_index = br.ReadInt16BE();
+ constant_pool.Add(i, cFieldref);
+ break;
+
+ case 10:
+ CONSTANT_Methodref_info cMethodref = new CONSTANT_Methodref_info(tag);
+ cMethodref.class_index = br.ReadInt16BE();
+ cMethodref.name_and_type_index = br.ReadInt16BE();
+ constant_pool.Add(i, cMethodref);
+ break;
+
+ case 11:
+ CONSTANT_InterfaceMethodref_info cInterfaceMethodref = new CONSTANT_InterfaceMethodref_info(tag);
+ cInterfaceMethodref.class_index = br.ReadInt16BE();
+ cInterfaceMethodref.name_and_type_index = br.ReadInt16BE();
+ constant_pool.Add(i, cInterfaceMethodref);
+ break;
+
+ case 12:
+ CONSTANT_NameAndType_info cNameAndType = new CONSTANT_NameAndType_info(tag);
+ cNameAndType.name_index = br.ReadInt16BE();
+ cNameAndType.descriptor_index = br.ReadInt16BE();
+ constant_pool.Add(i, cNameAndType);
+ break;
+
+ case 15:
+ CONSTANT_MethodHandle_info cMethodHandle = new CONSTANT_MethodHandle_info(tag);
+ cMethodHandle.reference_kind = br.ReadByte();
+ cMethodHandle.reference_index = br.ReadInt16BE();
+ constant_pool.Add(i, cMethodHandle);
+ break;
+
+ case 16:
+ CONSTANT_MethodType_info cMethodType = new CONSTANT_MethodType_info(tag);
+ cMethodType.descriptor_index = br.ReadInt16BE();
+ constant_pool.Add(i, cMethodType);
+ break;
+
+ case 18:
+ CONSTANT_InvokeDynamic_info cInvokeDynamic = new CONSTANT_InvokeDynamic_info(tag);
+ cInvokeDynamic.bootstrap_method_attr_index = br.ReadInt16BE();
+ cInvokeDynamic.name_and_type_index = br.ReadInt16BE();
+ constant_pool.Add(i, cInvokeDynamic);
+ break;
+
+ default:
+ Console.WriteLine("(EE) ERREUR code inconnu : {0:X2}", tag);
+ break;
+ }
+ }
+ }
+
+ private void readInterfaces(BinaryReader br)
+ {
+ interfaces = new List();
+
+ interfaces_count = br.ReadInt16BE();
+
+ for (int i = 0; i < interfaces_count; i++)
+ interfaces.Add(br.ReadInt16BE());
+ }
+
+ private void readFields(BinaryReader br)
+ {
+ fields = new Dictionary();
+
+ fields_count = br.ReadInt16BE();
+
+ for (int i = 0; i < fields_count; i++)
+ {
+ stField st = new stField();
+
+ st.access_flags = br.ReadInt16BE();
+ st.name_index = br.ReadInt16BE();
+ st.descriptor_index = br.ReadInt16BE();
+ st.attributes_count = br.ReadInt16BE();
+
+ if (st.attributes_count > 0)
+ {
+ st.attributes = new Dictionary();
+
+ for (int j = 0; j < st.attributes_count; j++)
+ {
+ stAttribut stA = new stAttribut();
+
+ readAttributes(br, ref stA);
+
+ st.attributes.Add(j + 1, stA);
+ }
+ }
+
+ fields.Add(i + 1, st);
+ }
+ }
+
+ private void readMethods(BinaryReader br)
+ {
+ methods = new Dictionary();
+
+ methods_count = br.ReadInt16BE();
+
+ for (int i = 0; i < methods_count; i++)
+ {
+ stMethod st = new stMethod();
+
+ st.access_flags = br.ReadInt16BE();
+ st.name_index = br.ReadInt16BE();
+ st.descriptor_index = br.ReadInt16BE();
+ st.attributes_count = br.ReadInt16BE();
+
+ if (st.attributes_count > 0)
+ {
+ st.attributes = new Dictionary();
+
+ for (int j = 0; j < st.attributes_count; j++)
+ {
+ stAttribut stA = new stAttribut();
+
+ readAttributes(br, ref stA);
+
+ st.attributes.Add(j + 1, stA);
+ }
+ }
+
+ methods.Add(i + 1, st);
+ }
+
+ }
+
+ private void readAttributes(BinaryReader br)
+ {
+ attributes = new Dictionary();
+
+ attributes_count = br.ReadInt16BE();
+
+ for (int i = 0; i < attributes_count; i++)
+ {
+ stAttribut st = new stAttribut();
+
+ readAttributes(br, ref st);
+
+ attributes.Add(i + 1, st);
+ }
+ }
+
+ private void readAttributes(BinaryReader br, ref stAttribut st)
+ {
+ st.attribute_name_index = br.ReadInt16BE();
+ st.attribute_length = br.ReadInt32BE();
+
+ if (st.attribute_length > 0)
+ {
+ st.info = new byte[st.attribute_length];
+ st.info = br.ReadBytes((int)st.attribute_length);
+ }
+ }
+
+ private int readBytes(byte[] bytes, int nb, ref int num)
+ {
+ int value = 0;
+
+ for (int i = 0; i < nb; i++)
+ value = value * 0x100 + bytes[num++];
+
+ return value;
+ }
+
+ #endregion
+
+ #region Print data
+
+ // NOT FINISH //
+ private void printBytecodeCode(StreamWriter sw, byte[] bytes)
+ {
+ List list = new List();
+ string[] s;
+ byte temp;
+ int num = 0;
+ stOpcode st;
+
+ sw.Write(string.Format("max_stack = {0:X4}\n", readBytes(bytes, 2, ref num)));
+ sw.Write(string.Format("{0,60} = {1:X4}\n", "max_locals", readBytes(bytes, 2, ref num)));
+ sw.Write(string.Format("{0,61} = {1:X8}\n", "code_length", readBytes(bytes, 4, ref num)));
+
+
+ while (num < bytes.Length - 8)
+ {
+ st = new stOpcode();
+ st.opcode = bytes[num++];
+ byte op = st.opcode;
+
+ sw.Write(string.Format("{0,52:X2} ", op));
+
+ if (op == 0x00)
+ //st.name = "NOP";
+ sw.Write("NOP\n");
+ else if (op == 0x01)
+ //st.name = "CONSTNULL";
+ sw.Write("CONSTNULL\n");
+ else if (op <= 11)
+ {
+ sw.Write("CONST (");
+ //st.name = "CONST";
+ if (op <= 0x08)
+ {
+ sw.Write(string.Format("I = {0}", op - 3));
+ //st.type = "I";
+ //st.value = op - 3;
+ }
+ else if (op <= 0x0A)
+ {
+ sw.Write(string.Format("L = {0}", op - 9));
+ //st.type = "L";
+ //st.value = op - 9;
+ }
+ else if (op <= 0x0D)
+ {
+ sw.Write(string.Format("F = {0}", op - 0x0B));
+ //st.type = "F";
+ //st.value = op - 0x0B;
+ }
+ else if (op <= 0x0F)
+ {
+ sw.Write(string.Format("D = {0}", op - 0x0E));
+ //st.type = "D";
+ //st.value = op - 0x0E;
+ }
+ else if (op == 0x10)
+ {
+ sw.Write(string.Format("I = {0}", bytes[num++]));
+ //st.type = "I";
+ //st.value = bytes[num++];
+ }
+ else
+ {
+ sw.Write(string.Format("I = {0}", readBytes(bytes, 2, ref num)));
+ //st.type = "I";
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ }
+ sw.Write(")\n");
+ }
+ else if (op == 0x12)
+ {
+ sw.Write(string.Format("LDC ({0} = 1)\n", bytes[num++].ToString()));
+ //st.name = "LDC";
+ //st.type = bytes[num++].ToString();
+ //st.value = 1;
+ }
+ else if (op == 0x13)
+ {
+ sw.Write(string.Format("LDC ({0} = 1)\n", readBytes(bytes, 2, ref num).ToString()));
+ //st.name = "LDC";
+ //st.type = (bytes[num++] * 0x100 + bytes[num++]).ToString();
+ //st.value = 1;
+ }
+ else if (op == 0x14)
+ {
+ sw.Write(string.Format("LDC ({0} = 2)\n", readBytes(bytes, 2, ref num).ToString()));
+ //st.name = "LDC";
+ //st.type = (bytes[num++] * 0x100 + bytes[num++]).ToString();
+ //st.value = 2;
+ }
+ else if (op <= 0x2D)
+ {
+ s = new string[] { "I", "L", "F", "D", "A" };
+ sw.Write("LOAD (");
+ if (op <= 0x19)
+ {
+ temp = (byte)(op - 0x15);
+ //st.type = s[temp];
+ //st.value = bytes[num++];
+ sw.Write(string.Format("type={0} value={1}", s[temp], bytes[num++]));
+ }
+ else
+ {
+ temp = (byte)(op - 0x1A);
+ //st.type = s[temp/4];
+ //st.value = temp % 4;
+ sw.Write(string.Format("type={0} value={1}", s[temp / 4], temp % 4));
+ }
+ sw.Write(")\n");
+ s = null;
+ }
+ else if (op <= 0x35)
+ {
+ s = new string[] { "I", "L", "F", "D", "A", "B", "C", "S" };
+ if (s[op - 0x2E] != "A")
+ {
+ sw.Write(string.Format("ARRLOAD (type={0})\n", s[op - 0x2E]));
+ //st.type = s[op - 0x2E];
+ //st.name = "ARRLOAD";
+ }
+ else
+ sw.Write("ARRLOAD_OBJ\n");
+ //st.name = "ARRLOAD_OBJ";
+ s = null;
+ }
+ else if (op <= 0x4E)
+ {
+ s = new string[] { "I", "L", "F", "D", "A" };
+ //st.name = "STORE";
+ sw.Write("STORE");
+ if (op <= 0x3A)
+ {
+ sw.Write(string.Format(" (type={0} value={1})\n", s[op - 0x36], bytes[num++]));
+ //st.type = s[op - 0x36];
+ //st.value = bytes[num++];
+ }
+ else
+ {
+ temp = (byte)(op - 0x3B);
+ sw.Write(string.Format(" (type={0} value={1})\n", s[temp / 4], temp % 4));
+ //st.type = s[temp / 4];
+ //st.value = temp % 4;
+ }
+ s = null;
+ }
+ else if (op <= 0x56)
+ {
+ s = new string[] { "I", "L", "F", "D", "A", "B", "C", "S" };
+ if (s[op - 0x4F] != "A")
+ {
+ sw.Write(string.Format("ARRSTORE (type={0})\n", s[op - 0x4F]));
+ //st.type = s[op - 0x4F];
+ //st.name = "ARRSTORE";
+ }
+ else
+ sw.Write("ARRSTORE_OBJ\n");
+ //st.name = "ARRSTORE_OBJ";
+ s = null;
+ }
+ else if (op == 0x57)
+ sw.Write("POP\n");
+ // st.name = "POP";
+ else if (op == 0x58)
+ sw.Write("POP2\n");
+ // st.name = "POP2";
+ else if (op == 0x59)
+ sw.Write("DUP\n");
+ // st.name = "DUP";
+ else if (op == 0x5A)
+ sw.Write("DUPX1\n");
+ // st.name = "DUPX1";
+ else if (op == 0x5B)
+ sw.Write("DUPX2\n");
+ // st.name = "DUPX2";
+ else if (op == 0x5C)
+ sw.Write("DUP2\n");
+ // st.name = "DUP2";
+ else if (op == 0x5D)
+ sw.Write("DUP2X1\n");
+ // st.name = "DUP2X1";
+ else if (op == 0x5E)
+ sw.Write("DUP2X2\n");
+ // st.name = "DUP2X2";
+ else if (op == 0x5F)
+ sw.Write("SWAP\n");
+ // st.name = "SWAP";
+ else if (op <= 0x77)
+ {
+ s = new string[] { "I", "L", "F", "D" };
+ temp = (byte)(op - 0x60);
+ switch (temp / 4)
+ {
+ case 0:
+ sw.Write("ADD");
+ //st.name = "ADD";
+ break;
+ case 1:
+ sw.Write("SUB");
+ //st.name = "SUB";
+ break;
+ case 2:
+ sw.Write("MUL");
+ //st.name = "MUL";
+ break;
+ case 3:
+ sw.Write("DIV");
+ //st.name = "DIV";
+ break;
+ case 4:
+ sw.Write("REM");
+ //st.name = "REM";
+ break;
+ case 5:
+ sw.Write("NEG");
+ //st.name = "NEG";
+ break;
+ }
+ sw.Write(string.Format(" (type={0})\n", s[temp % 4]));
+ //st.type = s[temp % 4];
+ s = null;
+ }
+ else if (op <= 0x83)
+ {
+ temp = (byte)(op - 0x78);
+ switch (temp / 2)
+ {
+ case 0:
+ sw.Write("SHL");
+ //st.name = "SHL";
+ break;
+ case 1:
+ sw.Write("SHR");
+ //st.name = "SHR";
+ break;
+ case 2:
+ sw.Write("USHR");
+ //st.name = "USHR";
+ break;
+ case 3:
+ sw.Write("AND");
+ //st.name = "AND";
+ break;
+ case 4:
+ sw.Write("OR");
+ //st.name = "OR";
+ break;
+ case 5:
+ sw.Write("WOR");
+ //st.name = "WOR";
+ break;
+ }
+ if (temp % 2 == 0)
+ sw.Write(" (type=I)\n");
+ //st.type = "I";
+ else
+ sw.Write(" (type=L)\n");
+ //st.type = "L";
+ }
+ else if (op == 0x84)
+ {
+ sw.Write(string.Format("IINC (type={0} value={1})\n", bytes[num++].ToString(), bytes[num++]));
+ //st.name = "IINC";
+ //st.type = bytes[num++].ToString();
+ //st.value = bytes[num++];
+ }
+ else if (op <= 0x90)
+ {
+ s = new string[] { "I", "I", "I", "L", "L", "L", "F", "F", "F", "D", "D", "D" };
+ string[] s2 = new string[] { "L", "F", "D", "I", "F", "D", "I", "L", "D", "I", "L", "F" };
+ sw.Write(string.Format("CONVERT ({0} -> {1})\n", s[op - 0x85], s2[op - 0x85]));
+ //st.name = "CONVERT";
+ //st.src_t = s[op - 0x85];
+ //st.dst_t = s2[op - 0x85];
+ s = null;
+ s2 = null;
+ }
+ else if (op <= 0x93)
+ {
+ sw.Write("TRUNCATE");
+ //st.name = "TRUNCATE";
+ switch (op - 0x91)
+ {
+ case 0:
+ sw.Write(" (type=B)\n");
+ //st.type = "B";
+ break;
+ case 1:
+ sw.Write(" (type=C)\n");
+ //st.type = "C";
+ break;
+ case 2:
+ sw.Write(" (type=S)\n");
+ //st.type = "S";
+ break;
+ }
+ }
+ else if (op == 0x94)
+ sw.Write("LCMP\n");
+ //st.name = "LCMP";
+ else if (op <= 0x98)
+ {
+ sw.Write("FCMP");
+ //st.name = "FCMP";
+ temp = (byte)(op - 0x95);
+ if (temp / 2 == 0)
+ sw.Write(" (type=F");
+ //st.type = "F";
+ else
+ sw.Write(" (type=D");
+ //st.type = "D";
+
+ if (temp % 2 == 0)
+ sw.Write(" value=-1)\n");
+ //st.value = -1;
+ else
+ sw.Write(" value=1)\n");
+ //st.value = 1;
+ }
+ else if (op <= 0x9E)
+ {
+ st.name = "IF_I";
+ switch (op - 0x99)
+ {
+ case 0:
+ st.type = "eq";
+ break;
+ case 1:
+ st.type = "ne";
+ break;
+ case 2:
+ st.type = "lt";
+ break;
+ case 3:
+ st.type = "ge";
+ break;
+ case 4:
+ st.type = "gt";
+ break;
+ case 5:
+ st.type = "le";
+ break;
+ }
+ sw.Write(string.Format("IF_I (type={0} value={1})\n", st.type, readBytes(bytes, 2, ref num)));
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ }
+ else if (op <= 0xA4)
+ {
+ st.name = "IF_ICMP";
+ switch (op - 0x9F)
+ {
+ case 0:
+ st.type = "eq";
+ break;
+ case 1:
+ st.type = "ne";
+ break;
+ case 2:
+ st.type = "lt";
+ break;
+ case 3:
+ st.type = "ge";
+ break;
+ case 4:
+ st.type = "gt";
+ break;
+ case 5:
+ st.type = "le";
+ break;
+ }
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ sw.Write(string.Format("IF_ICMP (type={0} value={1})\n", st.type, readBytes(bytes, 2, ref num)));
+ }
+ else if (op <= 0xA6)
+ {
+ st.name = "IF_ACMP";
+ switch (op - 0xA5)
+ {
+ case 0:
+ st.type = "eq";
+ break;
+ case 1:
+ st.type = "ne";
+ break;
+ }
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ sw.Write(string.Format("IF_ACMP (type={0} value={1})\n", st.type, readBytes(bytes, 2, ref num)));
+ }
+ else if (op == 0xA7)
+ {
+ st.name = "GOTO";
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ sw.Write(string.Format("GOTO (value={0})\n", readBytes(bytes, 2, ref num)));
+ }
+ else if (op == 0xA8)
+ {
+ st.name = "JSR";
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ sw.Write(string.Format("JSR (value={0})\n", readBytes(bytes, 2, ref num)));
+ }
+ else if (op == 0xA9)
+ {
+ st.name = "RET";
+ //st.value = bytes[num++];
+ sw.Write(string.Format("RET (value={0})\n", bytes[num++]));
+ }
+ else if (op == 0xAA)
+ {
+ st.name = "SWITCH";
+ sw.Write("SWITCH");
+ readBytes(bytes, (3 - num) % 4, ref num);
+ sw.Write(" (default={0}", readBytes(bytes, 4, ref num));
+ int low = readBytes(bytes, 4, ref num);
+ int high = readBytes(bytes, 4, ref num);
+ for (int i = 0; i < high - low + 1; i++)
+ sw.Write(string.Format(" offset={0}", readBytes(bytes, 4, ref num)));
+ sw.Write("\n");
+ //st.default = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
+ //st.low = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
+ //st.high = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
+ //st.offset = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
+
+ }
+ else if (op == 0xAB)
+ {
+ st.name = "SWITCH";
+ sw.Write("SWITCH");
+ readBytes(bytes, (3 - num) % 4, ref num);
+ sw.Write(" (default={0}", readBytes(bytes, 4, ref num));
+ int numpairs = readBytes(bytes, 4, ref num);
+ for (int i = 0; i < numpairs + 1; i++)
+ sw.Write(string.Format(" offset={0}", readBytes(bytes, 4, ref num)));
+ sw.Write("\n");
+ }
+ else if (op <= 0xB1)
+ {
+ st.name = "RETURN";
+ switch (op - 0xAC)
+ {
+ case 0:
+ st.type = "I";
+ break;
+ case 1:
+ st.type = "L";
+ break;
+ case 2:
+ st.type = "F";
+ break;
+ case 3:
+ st.type = "D";
+ break;
+ case 4:
+ st.type = "A";
+ break;
+ case 5:
+ st.type = "None";
+ break;
+ }
+ }
+ else if (op == 0xB2)
+ sw.Write("GETSTATIC\n");
+ //st.name = "GETSTATIC";
+ else if (op == 0xB3)
+ sw.Write("PUTSTATIC\n");
+ //st.name = "PUTSTATIC";
+ else if (op == 0xB4)
+ sw.Write("GETFIELD\n");
+ //st.name = "GETFIELD";
+ else if (op == 0xB5)
+ sw.Write("PUTFIELD\n");
+ //st.name = "PUTFIELD";
+ else if (op == 0xB6)
+ sw.Write("INVOKEVIRTUAL\n");
+ //st.name = "INVOKEVIRTUAL";
+ else if (op == 0xB7)
+ sw.Write("INVOKESPECIAL\n");
+ //st.name = "INVOKESPECIAL";
+ else if (op == 0xB8)
+ sw.Write("INVOKESTATIC\n");
+ //st.name = "INVOKESTATIC";
+ else if (op == 0xB9)
+ {
+ sw.Write(string.Format("INVOKEINTERFACE (index={0} count={1} zero={2})\n", readBytes(bytes, 2, ref num), bytes[num++], bytes[num++]));
+ //st.name = "INVOKEINTERFACE";
+ //st.index = bytes[num++] * 0x100 + bytes[num++];
+ //st.count = bytes[num++];
+ //st.zero = bytes[num++];
+ }
+ else if (op == 0xBA)
+ {
+ sw.Write(string.Format("INVOKEDYNAMIC (index={0} zero={1})\n", readBytes(bytes, 2, ref num), readBytes(bytes, 2, ref num)));
+ //st.name = "INVOKEDYNAMIC";
+ //st.index = bytes[num++] * 0x100 + bytes[num++];
+ //st.zero = bytes[num++] * 0x100 + bytes[num++];
+ }
+ else if (op == 0xBB)
+ sw.Write("NEW\n");
+ //st.name = "NEW";
+ else if (op == 0xBC)
+ {
+ sw.Write(string.Format("NEWARRAY"));
+ temp = bytes[num++];
+ //st.name = "NEWARRAY";
+ switch (temp)
+ {
+ case 4:
+ sw.Write(" (Bool)");
+ //st.type = "Bool";
+ break;
+ case 5:
+ sw.Write(" (C)");
+ //st.type = "C";
+ break;
+ case 6:
+ sw.Write(" (F)");
+ //st.type = "F";
+ break;
+ case 7:
+ sw.Write(" (D)");
+ //st.type = "D";
+ break;
+ case 8:
+ sw.Write(" (B)");
+ //st.type = "B";
+ break;
+ case 9:
+ sw.Write(" (S)");
+ //st.type = "S";
+ break;
+ case 10:
+ sw.Write(" (I)");
+ //st.type = "I";
+ break;
+ case 11:
+ sw.Write(" (L)");
+ //st.type = "L";
+ break;
+ }
+ sw.Write("\n");
+ }
+ else if (op == 0xBD)
+ sw.Write("ANEWARRAY\n");
+ //st.name = "ANEWARRAY";
+ else if (op == 0xBE)
+ sw.Write("ARRLEN\n");
+ //st.name = "ARRLEN";
+ else if (op == 0xBF)
+ sw.Write("THROW\n");
+ //st.name = "THROW";
+ else if (op == 0xC0)
+ sw.Write("CHECKCAST\n");
+ //st.name = "CHECKCAST";
+ else if (op == 0xC1)
+ sw.Write("INSTANCEOF\n");
+ //st.name = "INSTANCEOF";
+ else if (op == 0xC2)
+ sw.Write("MONENTER\n");
+ //st.name = "MONENTER";
+ else if (op == 0xC3)
+ sw.Write("MONEXIT\n");
+ //st.name = "MONEXIT";
+ else if (op == 0xC4)
+ {
+ byte b = bytes[num++];
+ if (b >= 0x15 && b < 0x1A)
+ {
+ sw.Write("LOAD (");
+ //st.name = "LOAD";
+ switch (b - 0x15)
+ {
+ case 0:
+ sw.Write("I = ");
+ //st.type = "I";
+ break;
+ case 1:
+ sw.Write("L = ");
+ //st.type = "L";
+ break;
+ case 2:
+ sw.Write("F = ");
+ //st.type = "F";
+ break;
+ case 3:
+ sw.Write("D = ");
+ //st.type = "D";
+ break;
+ case 4:
+ sw.Write("A = ");
+ //st.type = "A";
+ break;
+ }
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ sw.Write(string.Format("{0})\n", readBytes(bytes, 2, ref num)));
+ }
+ else if (b >= 0x36 && b < 0x3B)
+ {
+ sw.Write("STORE (");
+ //st.name = "STORE";
+ switch (b - 0x36)
+ {
+ case 0:
+ sw.Write("I = ");
+ //st.type = "I";
+ break;
+ case 1:
+ sw.Write("L = ");
+ //st.type = "L";
+ break;
+ case 2:
+ sw.Write("F = ");
+ //st.type = "F";
+ break;
+ case 3:
+ sw.Write("D = ");
+ //st.type = "D";
+ break;
+ case 4:
+ sw.Write("A = ");
+ //st.type = "A";
+ break;
+ }
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ sw.Write(string.Format("{0})\n", readBytes(bytes, 2, ref num)));
+ }
+ else if (b == 0xA9)
+ {
+ sw.Write(string.Format("RET ({0})\n", readBytes(bytes, 2, ref num)));
+ //st.name = "RET";
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ }
+ else if (b == 0x84)
+ {
+ sw.Write(string.Format("IINC ({0} {1})\n", readBytes(bytes, 2, ref num), readBytes(bytes, 2, ref num)));
+ //st.name = "IINC";
+ //st.value = bytes[num++] * 0x100 + bytes[num++];
+ //st.value2 = bytes[num++] * 0x100 + bytes[num++];
+ }
+ }
+ else if (op == 0xC5)
+ {
+ sw.Write(string.Format("MULTINEWARRAY (index={0} dim={1})\n", readBytes(bytes, 2, ref num), bytes[num++]));
+ //st.name = "MULTINEWARRAY";
+ //st.index = bytes[num++] * 0x100 + bytes[num++];
+ //st.dim = bytes[num++];
+ }
+ else if (op <= 0xC7)
+ {
+ sw.Write("IF_A (");
+ //st.name = "IF_A";
+ if (op - 0xC6 == 0)
+ sw.Write(string.Format("eq -> {0})\n", readBytes(bytes, 2, ref num)));
+ //st.type = "eq";
+ else if (op - 0xC6 == 1)
+ sw.Write(string.Format("ne -> {0})\n", readBytes(bytes, 2, ref num)));
+ //st.type = "ne";
+ //st.jumptarget = bytes[num++] * 0x100 + bytes[num++];
+ }
+ else if (op == 0xC8)
+ {
+ sw.Write(string.Format("GOTO ({0})\n", readBytes(bytes, 4, ref num)));
+ //st.name = "GOTO";
+ //st.value = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
+ }
+ else if (op == 0xC9)
+ {
+ sw.Write(string.Format("JSR ({0})\n", readBytes(bytes, 4, ref num)));
+ //st.name = "JSR";
+ //st.value = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
+ }
+ else
+ Console.WriteLine("Bytecode inconnu : {0:X2}", op);
+
+ list.Add(st);
+ }
+ }
+
+ private void printBytecodeSourceFile(StreamWriter sw, byte[] bytes)
+ {
+ int num = 0;
+
+ sw.Write(string.Format("sourcefile_index = {0:X4}", readBytes(bytes, 2, ref num)));
+ }
+
+ private void printBytecodeInnerClass(StreamWriter sw, byte[] bytes)
+ {
+ int num = 0;
+ int nbClass = readBytes(bytes, 2, ref num);
+
+ sw.Write(string.Format("number_of_classes = {0:X4}\n", nbClass));
+
+ for (int i = 0; i < nbClass; i++)
+ {
+ sw.Write(string.Format("{0,34:D4} : inner_class_info_index = {1:X4}\n", i + 1, readBytes(bytes, 2, ref num)));
+ sw.Write(string.Format("{0,59} = {1:X4}\n", "outer_class_info_index", readBytes(bytes, 2, ref num)));
+ sw.Write(string.Format("{0,53} = {1:X4}\n", "inner_name_index", readBytes(bytes, 2, ref num)));
+ sw.Write(string.Format("{0,61} = {1:X4}\n", "inner_class_access_flags", readBytes(bytes, 2, ref num)));
+ }
+ }
+
+ #endregion
+
+ private byte[] IntToByteArrayBE(int value, int size = 4)
+ {
+ byte[] bytes = BitConverter.GetBytes(value);
+
+ Array.Reverse(bytes, 0, size);
+
+ return bytes;
+ }
+
+ //---------------------------------------------------------------------
+
+ public void load(BinaryReader br)
+ {
+ magic = new byte[4];
+ magic = br.ReadBytes(4);
+
+ minor_version = br.ReadInt16BE();
+ major_version = br.ReadInt16BE();
+
+ readConstants(br);
+
+ access_flags = br.ReadInt16BE();
+ this_class = br.ReadInt16BE();
+ super_class = br.ReadInt16BE();
+
+ readInterfaces(br);
+ readFields(br);
+ readMethods(br);
+ readAttributes(br);
+ }
+
+ public Dictionary getConstantsValue()
+ {
+ Dictionary dict = new Dictionary();
+
+ foreach (KeyValuePair constant in constant_pool)
+ {
+ if (constant.Value.tag == 8)
+ {
+ CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
+
+ dict[constant.Key] = getConstantValue(stString.string_index);
+ }
+ }
+
+ return dict;
+ }
+
+ public Dictionary getConstantsBytes()
+ {
+ Dictionary dict = new Dictionary();
+
+ foreach (KeyValuePair constant in constant_pool)
+ {
+ if (constant.Value.tag == 8)
+ {
+ CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
+
+ dict[constant.Key] = getConstantBytes(stString.string_index);
+ }
+ }
+
+ return dict;
+ }
+
+ public MemoryStream compilClass(evtClass.stFile originalFile)
+ {
+ MemoryStream ms = new MemoryStream();
+
+ using (BinaryWriter bw = new BinaryWriter(ms, Encoding.Default, true))
+ {
+ bw.Write(this.magic);
+ bw.Write(IntToByteArrayBE(this.minor_version, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(this.major_version, 2), 0, 2);
+
+ bw.Write(IntToByteArrayBE(this.constant_pool_count+1, 2), 0, 2);
+ compilConstants(bw);
+
+ bw.Write(IntToByteArrayBE(this.access_flags, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(this.this_class, 2), 0, 2);
+ bw.Write(IntToByteArrayBE(this.super_class, 2), 0, 2);
+
+ bw.Write(IntToByteArrayBE(this.interfaces_count, 2), 0, 2);
+ compilInterfaces(bw);
+
+ bw.Write(IntToByteArrayBE(this.fields_count, 2), 0, 2);
+ compilFields(bw);
+
+ bw.Write(IntToByteArrayBE(this.methods_count, 2), 0, 2);
+ compilMethods(bw);
+
+ bw.Write(IntToByteArrayBE(this.attributes_count, 2), 0, 2);
+ compilAttributes(bw);
+ }
+
+ return ms;
+ }
+
+ public void setConstantsBytes(int id, byte[] bytes)
+ {
+ if (constant_pool.ContainsKey(id))
+ {
+ if (constant_pool[id].tag == 8)
+ {
+ CONSTANT_String_info stString = (CONSTANT_String_info)constant_pool[id];
+
+ setConstantsBytes(stString.string_index, bytes);
+ }
+ else if (constant_pool[id].tag == 1)
+ {
+ CONSTANT_Utf8_info stUTF8 = (CONSTANT_Utf8_info)constant_pool[id];
+
+ stUTF8.bytes = new byte[bytes.Length];
+ Array.Copy(bytes, 0, stUTF8.bytes, 0, bytes.Length);
+ //stUTF8.bytes[bytes.Length] = 0;
+ }
+ }
+ }
+
+ public void writeConstants(StreamWriter sw)
+ {
+ sw.Write(string.Format("[CONSTANTS : {0}]\n", constant_pool_count));
+
+ foreach (KeyValuePair constant in constant_pool)
+ {
+ sw.Write(string.Format("{0:X4} : {1:D2} ", constant.Key, constant.Value.tag));
+
+ switch (constant.Value.tag)
+ {
+ case 1:
+ CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X4} ", "Utf8", stUtf8.length));
+ if (stUtf8.length > 0)
+ sw.Write(Encoding.UTF8.GetString(stUtf8.bytes).Replace("\n", "\\n"));
+ sw.Write("\n");
+ break;
+
+ case 3:
+ CONSTANT_Integer_info stInteger = (CONSTANT_Integer_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X8} ({1})\n", "Integer", stInteger.bytes));
+ break;
+
+ case 4:
+ CONSTANT_Float_info stFloat = (CONSTANT_Float_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X8} ({2})\n", "Float", stFloat.bytes, BitConverter.ToSingle(BitConverter.GetBytes(stFloat.bytes), 0)));
+ break;
+
+ case 5:
+ CONSTANT_Long_info stLong = (CONSTANT_Long_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X8} {2:X8}\n", "Long", stLong.high_bytes, stLong.low_bytes));
+ break;
+
+ case 6:
+ CONSTANT_Double_info stDouble = (CONSTANT_Double_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X8} {2:X8}\n", "Double", stDouble.high_bytes, stDouble.low_bytes));
+ break;
+
+ case 7:
+ CONSTANT_Class_info stClass = (CONSTANT_Class_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "Class", stClass.name_index, getConstantValue(stClass.name_index)));
+ break;
+
+ case 8:
+ CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "String", stString.string_index, getConstantValue(stString.string_index)));
+ break;
+
+ case 9:
+ CONSTANT_Fieldref_info stFieldref = (CONSTANT_Fieldref_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "Fieldref", stFieldref.class_index, getConstantValue(stFieldref.class_index)));
+ sw.Write(string.Format("{0,31}{1,-9:X4} ({2})\n", " ", stFieldref.name_and_type_index, getConstantValue(stFieldref.name_and_type_index)));
+ break;
+
+ case 10:
+ CONSTANT_Methodref_info stMethodref = (CONSTANT_Methodref_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "Methodref", stMethodref.class_index, getConstantValue(stMethodref.class_index)));
+ sw.Write(string.Format("{0,31}{1,-9:X4} ({2})\n", " ", stMethodref.name_and_type_index, getConstantValue(stMethodref.name_and_type_index)));
+ break;
+
+ case 11:
+ CONSTANT_InterfaceMethodref_info stInterfaceMethodref = (CONSTANT_InterfaceMethodref_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X4} {2:X4}\n", "InterfaceMethodref", stInterfaceMethodref.class_index, stInterfaceMethodref.name_and_type_index));
+ break;
+
+ case 12:
+ CONSTANT_NameAndType_info stNameAndType = (CONSTANT_NameAndType_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "NameAndType", stNameAndType.name_index, getConstantValue(stNameAndType.name_index)));
+ sw.Write(string.Format("{0,31}{1,-9:X4} ({2})\n", " ", stNameAndType.descriptor_index, getConstantValue(stNameAndType.descriptor_index)));
+ break;
+
+ case 15:
+ CONSTANT_MethodHandle_info stMethodHandle = (CONSTANT_MethodHandle_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X2} {2:X4}\n", "MethodHandle", stMethodHandle.reference_kind, stMethodHandle.reference_index));
+ break;
+
+ case 16:
+ CONSTANT_MethodType_info stMethodType = (CONSTANT_MethodType_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X4}\n", "MethodType", stMethodType.descriptor_index));
+ break;
+
+ case 18:
+ CONSTANT_InvokeDynamic_info stInvokeDynamic = (CONSTANT_InvokeDynamic_info)constant.Value;
+
+ sw.Write(string.Format("{0,-18} : {1:X4} {2:X4}\n", "InvokeDynamic", stInvokeDynamic.bootstrap_method_attr_index, stInvokeDynamic.name_and_type_index));
+ break;
+ }
+ }
+ sw.Write("\n");
+ }
+
+ public void writeInterfaces(StreamWriter sw)
+ {
+ sw.Write(string.Format("[INTERFACES : {0}]\n", interfaces_count));
+
+ int num = 1;
+ foreach (Int16 index in interfaces)
+ {
+ sw.Write(string.Format("{0:D4} : {1:X4} ({2})\n", num, index, getConstantValue(index)));
+ num++;
+ }
+ sw.Write("\n");
+ }
+
+ public void writeFields(StreamWriter sw)
+ {
+ sw.Write(string.Format("[FIELDS : {0}]\n", fields_count));
+
+ foreach (KeyValuePair field in fields)
+ {
+ sw.Write(string.Format("{0:D4} : access_flags = {1:X4}\n", field.Key, field.Value.access_flags));
+ sw.Write(string.Format(" name_index = {0:X4} ({1})\n", field.Value.name_index, getConstantValue(field.Value.name_index)));
+ sw.Write(string.Format(" descriptor_index = {0:X4} ({1})\n", field.Value.descriptor_index, getConstantValue(field.Value.descriptor_index)));
+ sw.Write(string.Format(" attributes_count = {0:X4}\n", field.Value.attributes_count));
+
+ if (field.Value.attributes_count > 0)
+ {
+ foreach (KeyValuePair attribut in field.Value.attributes)
+ {
+ sw.Write(string.Format(" attributes ({0:D4}) : attribute_name_index = {1:X4} ({2})\n", attribut.Key, attribut.Value.attribute_name_index, getConstantValue(attribut.Value.attribute_name_index)));
+ sw.Write(string.Format(" attribute_length = {0:X8}\n", attribut.Value.attribute_length));
+
+ sw.Write(" info = ");
+ for (int i = 0; i < attribut.Value.attribute_length; i++)
+ sw.Write(string.Format("{0:X2} ", attribut.Value.info[i]));
+
+ sw.Write("\n");
+ }
+ }
+ }
+ sw.Write("\n");
+ }
+
+ public void writeMethods(StreamWriter sw)
+ {
+ sw.Write(string.Format("[METHODS : {0}]\n", methods_count));
+
+ foreach (KeyValuePair method in methods)
+ {
+ sw.Write(string.Format("{0:D4} : access_flags = {1:X4}\n", method.Key, method.Value.access_flags));
+ sw.Write(string.Format(" name_index = {0:X4} ({1})\n", method.Value.name_index, getConstantValue(method.Value.name_index)));
+ sw.Write(string.Format(" descriptor_index = {0:X4} ({1})\n", method.Value.descriptor_index, getConstantValue(method.Value.descriptor_index)));
+ sw.Write(string.Format(" attributes_count = {0:X4}\n", method.Value.attributes_count));
+
+ if (method.Value.attributes_count > 0)
+ {
+ foreach (KeyValuePair attribut in method.Value.attributes)
+ {
+ sw.Write(string.Format(" attributes ({0:D4}) : attribute_name_index = {1:X4} ({2})\n", attribut.Key, attribut.Value.attribute_name_index, getConstantValue(attribut.Value.attribute_name_index)));
+ sw.Write(string.Format(" attribute_length = {0:X8}\n", attribut.Value.attribute_length));
+
+ if (attribut.Value.attribute_length > 0)
+ {
+ sw.Write(string.Format("{0,31} = ", "info"));
+ switch (attribut.Value.attribute_name_index)
+ {
+ case 0x121:
+ printBytecodeCode(sw, attribut.Value.info);
+ break;
+ case 0x12A:
+ printBytecodeInnerClass(sw, attribut.Value.info);
+ break;
+ case 0x145:
+ printBytecodeSourceFile(sw, attribut.Value.info);
+ break;
+ }
+ //for (int i = 0; i < attribut.Value.attribute_length; i++)
+ // sw.Write(string.Format("{0:X2} ", attribut.Value.info[i]));
+
+ sw.Write("\n");
+ }
+ }
+ }
+ }
+ sw.Write("\n");
+ }
+
+ public void writeAttributes(StreamWriter sw)
+ {
+ sw.Write(string.Format("[ATTRIBUTS : {0}]\n", attributes_count));
+
+ foreach (KeyValuePair attribut in attributes)
+ {
+ sw.Write(string.Format("{0:D4} : attribute_name_index = {1:X4} ({2})\n", attribut.Key, attribut.Value.attribute_name_index, getConstantValue(attribut.Value.attribute_name_index)));
+ sw.Write(string.Format(" attribute_length = {0:X8}\n", attribut.Value.attribute_length));
+
+ if (attribut.Value.attribute_length > 0)
+ {
+ sw.Write(" info = ");
+ switch (attribut.Value.attribute_name_index)
+ {
+ case 0x121:
+ printBytecodeCode(sw, attribut.Value.info);
+ break;
+ case 0x12A:
+ printBytecodeInnerClass(sw, attribut.Value.info);
+ break;
+ case 0x145:
+ printBytecodeSourceFile(sw, attribut.Value.info);
+ break;
+ }
+ //for (int i = 0; i < attribut.Value.attribute_length; i++)
+ // sw.Write(string.Format("{0:X2} ", attribut.Value.info[i]));
+
+ sw.Write("\n");
+ }
+ }
+ sw.Write("\n");
+ }
+ }
+}
diff --git a/Hack.Xenosaga/Process/Scripts.cs b/Hack.Xenosaga/Process/Scripts.cs
new file mode 100644
index 0000000..0f707f4
--- /dev/null
+++ b/Hack.Xenosaga/Process/Scripts.cs
@@ -0,0 +1,472 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using Hack.Xenosaga.Common;
+using Hack.Tools.Common;
+using Hack.Tools.Pointers;
+using Hack.Tools.Table;
+
+namespace Hack.Xenosaga.Process
+{
+ public class Scripts
+ {
+ #region Private methods
+
+ private static Table loadTable(string tblName, Encoding encode)
+ {
+ Table tbl = new Table(encode);
+ tbl.Load(tblName);
+
+ if (tblName == Variables.tblCard)
+ {
+ tbl.Remove("2C");
+ tbl.Remove("27");
+ }
+
+ return tbl;
+ }
+
+ #region card.dat
+
+ private static bool extractCard(string filename, Encoding encode)
+ {
+ int nbBlocs = 0;
+
+ try
+ {
+ Trace.Write("Extract card.dat : ");
+
+ Directory.CreateDirectory(Variables.dirExtract);
+ Directory.CreateDirectory(Variables.dirInsert);
+
+ using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open)))
+ {
+ cTblPointers tblPt = new cTblPointers();
+ Table tbl = new Table(encode);
+ tbl.Load(Variables.tblCard);
+
+ nbBlocs = br.ReadInt32();
+
+ br.BaseStream.Seek(0x10, SeekOrigin.Begin);
+
+ // Get all pointers
+ for (int i = 0; i < nbBlocs; i++)
+ {
+ for (int j = 0; j < 6; j++)
+ br.ReadUInt32();
+
+ tblPt.add(br.BaseStream.Position, br.ReadUInt32());
+ tblPt.add(br.BaseStream.Position, br.ReadUInt32());
+
+ br.ReadUInt32();
+ }
+
+ using (StreamWriter sw = new StreamWriter(Variables.dirExtract + filename + ".txt", false, encode))
+ {
+ // Extracting text from pointers
+ foreach (Pointers pt in tblPt.ListPointers)
+ {
+ br.BaseStream.Seek((long)pt.Value, SeekOrigin.Begin);
+
+ sw.Write(string.Format(pt.Format, pt.Adress, pt.Num));
+ sw.Write(br.BytesToStringWithTable(tbl));
+ }
+ }
+ }
+
+ Trace.WriteLine("OK");
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool insertCard(string filename, Encoding encode)
+ {
+ int nbBlocs = 0;
+
+ try
+ {
+ Trace.Write("Insert card.dat : ");
+
+ using (BinaryReader brIn = new BinaryReader(File.Open(filename, FileMode.Open)))
+ using (MemoryStream ms = new MemoryStream())
+ {
+ cTblPointers tblPt = new cTblPointers();
+ Table tbl = loadTable(Variables.tblCard, encode);
+
+ nbBlocs = brIn.ReadInt32();
+ ms.Write(BitConverter.GetBytes(nbBlocs), 0, 4);
+
+ for (int i = 0; i < 12; i++)
+ ms.WriteByte(brIn.ReadByte());
+
+ for (int i = 0; i < nbBlocs; i++)
+ {
+ for (int j = 0; j < 9; j++)
+ ms.Write(BitConverter.GetBytes(brIn.ReadUInt32()), 0, 4);
+ }
+
+ using (BinaryReader brTxt = new BinaryReader(File.Open(Variables.dirInsert + filename + ".txt", FileMode.Open), encode))
+ {
+ string line = "";
+ int sizeMax = tbl.ValueMaxSize;
+
+ if (tblPt.SizeFormat > tbl.ValueMaxSize)
+ sizeMax = tblPt.SizeFormat;
+
+ long pos = 0;
+ while (pos < brTxt.BaseStream.Length)
+ {
+ brTxt.BaseStream.Seek(pos, SeekOrigin.Begin);
+
+ if (brTxt.BaseStream.Length - pos < sizeMax)
+ sizeMax = (int)(brTxt.BaseStream.Length - pos);
+
+ line = brTxt.BytestoString(encode, sizeMax);
+
+ int adress, num;
+ if (tblPt.textIsPointerInfo(line))
+ {
+ tblPt.getInfoPt(line, out adress, out num);
+ tblPt.add(adress, (ulong)ms.Position, 2, (int)typeEndian.LITTLE, num);
+ pos += tblPt.SizeFormat;
+ }
+ else
+ {
+ stElement stResult = tbl.FindKeyFromValue(line.ToCharArray());
+
+ switch (stResult.type)
+ {
+ case typeEntries.NORMAL:
+ case typeEntries.ENDBLOCK:
+ ms.Write(stResult.keyBytes, 0, stResult.keySize);
+ break;
+
+ case typeEntries.PARAM:
+ break;
+
+ case typeEntries.NOT_FOUND:
+ Trace.WriteLine(string.Format("ERROR : Unknown character {0} in {1}", line.Substring(0, 1), line));
+ return false;
+ }
+
+ pos += stResult.valueSize;
+ }
+ }
+ }
+
+ // Write pointer in file
+ tblPt.insertPointersToFile(ms);
+
+ Directory.CreateDirectory(Variables.dirPack);
+ using (FileStream fs = new FileStream(Variables.dirPack + filename, FileMode.Create))
+ {
+ ms.Position = 0;
+ ms.CopyTo(fs);
+ }
+ }
+
+ Trace.WriteLine("OK");
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region *.evt
+
+ private static bool decompilEvt(string nameFile, MemoryStream ms)
+ {
+ Encoding encode = new UTF8Encoding(false);
+
+ using (BinaryReader br = new BinaryReader(ms))
+ {
+ JavaClass jc = new JavaClass();
+
+ jc.load(br);
+
+ //using (StreamWriter sw = new StreamWriter("ST0210_constantes.txt"))
+ //{
+ // jc.writeConstants(sw);
+ //}
+
+ Dictionary dictBytes = jc.getConstantsBytes();
+
+ if (dictBytes.Count > 0)
+ {
+ using (StreamWriter sw = new StreamWriter(Variables.dirExtract + nameFile + ".txt", false, encode))
+ {
+ Table tbl = loadTable(Variables.tblEvt, Encoding.Default);
+
+ foreach (KeyValuePair bytes in dictBytes)
+ {
+ sw.Write(string.Format("[{0:X4}]\n", bytes.Key));
+
+ if (bytes.Value != null)
+ sw.Write(tbl.BytesToString(bytes.Value));
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static MemoryStream compilEvt(evtClass.stFile file)
+ {
+ MemoryStream ms = new MemoryStream();
+ using (BinaryReader br = new BinaryReader(ms))
+ {
+ JavaClass jc = new JavaClass();
+
+ jc.load(br);
+
+
+ }
+
+ return ms;
+ }
+
+ private static bool extractEvt(string pathName, Encoding encode)
+ {
+ try
+ {
+ Trace.Write(string.Format("Extract {0} : ", pathName));
+
+ evtClass evtFile = new evtClass(pathName);
+
+ Directory.CreateDirectory(Variables.dirExtract);
+ Directory.CreateDirectory(Variables.dirInsert);
+
+ foreach (evtClass.stFile file in evtFile.listFiles)
+ {
+ using (MemoryStream ms = new MemoryStream())
+ {
+ ms.Write(file.file, 0, (int)file.fileLength);
+ ms.Position = 0;
+
+ decompilEvt(file.name, ms);
+ }
+ }
+
+ Trace.WriteLine("OK");
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
+ return false;
+ }
+ }
+
+ private static bool insertEvt(string pathName, Encoding encode)
+ {
+ try
+ {
+ Trace.WriteLine(string.Format("Insert {0} : ", pathName));
+
+ using (BinaryReader br = new BinaryReader(File.Open(pathName, FileMode.Open)))
+ {
+ evtClass origEvt = new evtClass(br);
+
+ Table tbl = loadTable(Variables.tblEvt, Encoding.Default);
+
+ using (MemoryStream destEvt = new MemoryStream())
+ {
+ destEvt.Write(BitConverter.GetBytes(origEvt.id), 0, 4);
+ destEvt.Write(BitConverter.GetBytes(origEvt.unkAdr4), 0, 2);
+ destEvt.Write(BitConverter.GetBytes(origEvt.unkAdr6), 0, 2);
+
+ destEvt.Position = 16;
+ destEvt.Write(BitConverter.GetBytes(origEvt.unkAdr16), 0, 2);
+ destEvt.Write(BitConverter.GetBytes(origEvt.nbFiles), 0, 2);
+
+ destEvt.Position = 16 * origEvt.nbFiles + 20;
+
+ using (MemoryStream msIndex = new MemoryStream())
+ using (MemoryStream msName = new MemoryStream())
+ {
+ msName.WriteByte(0);
+ msName.WriteByte(0);
+
+ foreach (evtClass.stFile classFile in origEvt.listFiles)
+ {
+ msIndex.Write(BitConverter.GetBytes(msName.Position), 0, 4);
+ msIndex.Write(BitConverter.GetBytes(classFile.nameLength), 0, 4);
+ msIndex.Write(BitConverter.GetBytes(destEvt.Position), 0, 4);
+ msName.Write(encode.GetBytes(classFile.name), 0, (int)classFile.nameLength);
+ msName.WriteByte(0);
+
+ if (File.Exists(Variables.dirInsert + classFile.name + ".txt"))
+ {
+ Dictionary list = tbl.StringToBytesArray(Variables.dirInsert + classFile.name + ".txt", new Regex(@"\[(.{4})\]\n"));
+ JavaClass jc = new JavaClass();
+
+ using (MemoryStream msFile = new MemoryStream())
+ {
+ msFile.Write(classFile.file, 0, (int)classFile.fileLength);
+ msFile.Position = 0;
+
+ using (BinaryReader brFile = new BinaryReader(msFile))
+ {
+ br.BaseStream.Position = 0;
+ jc.load(brFile);
+ }
+ }
+
+ Dictionary dictBytes = jc.getConstantsBytes();
+
+ if (dictBytes.Count > 0)
+ {
+ string pt = "";
+ foreach (KeyValuePair bytes in dictBytes)
+ {
+ pt = string.Format("{0:X4}", bytes.Key);
+
+ if (dictBytes.ContainsKey(Convert.ToInt32(pt, 16)) && list[pt] != null)
+ jc.setConstantsBytes(bytes.Key, list[pt]);
+ }
+ }
+
+ MemoryStream newFile = jc.compilClass(classFile);
+
+ msIndex.Write(BitConverter.GetBytes(newFile.Length), 0, 4);
+ destEvt.Write(newFile.ToArray(), 0, (int)newFile.Length);
+ }
+ else
+ {
+ msIndex.Write(BitConverter.GetBytes(classFile.fileLength), 0, 4);
+ destEvt.Write(classFile.file, 0, (int)classFile.fileLength);
+ }
+
+ Functions.Padding(destEvt);
+ }
+
+ long posName = destEvt.Position;
+
+ // Write filename table
+ msName.Write(BitConverter.GetBytes(msName.Length-2), 0, 2, 0);
+ msName.Position = 0;
+
+ destEvt.Write(BitConverter.GetBytes(posName), 0, 4, 12);
+ destEvt.Write(msName.ToArray(), 0, (int)msName.Length);
+ destEvt.Write(BitConverter.GetBytes(destEvt.Length), 0, 2, 8);
+
+ // Write index of files
+ destEvt.Position = 20;
+ msIndex.Position = 0;
+ for (int i = 0; i < origEvt.nbFiles; i++)
+ {
+ destEvt.Write(BitConverter.GetBytes(msIndex.Read() + posName), 0, 4);
+ destEvt.Write(BitConverter.GetBytes(msIndex.Read()), 0, 4);
+ destEvt.Write(BitConverter.GetBytes(msIndex.Read()), 0, 4);
+ destEvt.Write(BitConverter.GetBytes(msIndex.Read()), 0, 4);
+ }
+ }
+
+ using (FileStream fs = new FileStream(Variables.dirPack + Path.GetFileName(pathName), FileMode.Create))
+ {
+ destEvt.Position = 0;
+ fs.Write(destEvt.ToArray(), 0, (int)destEvt.Length);
+ }
+ }
+ }
+
+ Trace.WriteLine("OK");
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
+ return false;
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Public methods
+
+ public static void extract(string pathName, Encoding encode)
+ {
+ bool result;
+
+ if (File.Exists(pathName))
+ {
+ if (Path.GetFileName(pathName) == "card.dat")
+ result = extractCard(pathName, encode);
+
+ if (Path.GetExtension(pathName) == ".evt")
+ result = extractEvt(pathName, encode);
+ }
+ else if (Directory.Exists(pathName))
+ {
+ var listFiles = Directory
+ .EnumerateFiles(pathName)
+ .Where(file => file.ToLower().EndsWith("dat") || file.ToLower().EndsWith("evt"))
+ .ToList();
+
+ foreach (string file in listFiles)
+ {
+ if (Path.GetFileName(file) == "card.dat")
+ result = extractCard(file.ToLower(), encode);
+ else if (Path.GetExtension(file) == ".evt")
+ result = extractEvt(file.ToLower(), encode);
+ }
+ }
+ else
+ Trace.WriteLine("Unknown file or directory");
+ }
+
+ public static void insert(string pathName, Encoding encode)
+ {
+ bool result;
+
+ if (File.Exists(pathName))
+ {
+ if (Path.GetFileName(pathName) == "card.dat")
+ result = insertCard(pathName, encode);
+
+ if (Path.GetExtension(pathName) == ".evt")
+ result = insertEvt(pathName, encode);
+ }
+ else if (Directory.Exists(pathName))
+ {
+ var listFiles = Directory
+ .EnumerateFiles(pathName)
+ .Where(file => file.ToLower().EndsWith("dat") || file.ToLower().EndsWith("evt"))
+ .ToList();
+
+ foreach (string file in listFiles)
+ {
+ if (Path.GetFileName(file) == "card.dat")
+ result = insertCard(file.ToLower(), encode);
+ else if (Path.GetExtension(file) == ".evt")
+ result = insertEvt(file.ToLower(), encode);
+ }
+ }
+ else
+ Trace.WriteLine("Unknown file of directory");
+ }
+
+ #endregion
+ }
+}
diff --git a/Hack.Xenosaga/Process/Unpack.cs b/Hack.Xenosaga/Process/Unpack.cs
index 2938cf0..6c4ed92 100644
--- a/Hack.Xenosaga/Process/Unpack.cs
+++ b/Hack.Xenosaga/Process/Unpack.cs
@@ -8,6 +8,8 @@ namespace Hack.Xenosaga.Process
{
class Unpack
{
+ public enum EnumSource { ISO_FILE, PACK_DIR, UNPACK_DIR };
+
private static BinaryWriter _bw;
private const string _listExtension = ".lst";
private const string _copyright = "Hacked by BahaBulle (c)2016\0";
@@ -193,18 +195,18 @@ namespace Hack.Xenosaga.Process
return size;
}
- private static int findFile(pathElement entry, string numberFile)
+ private static EnumSource findFile(pathElement entry, string numberFile)
{
// Check if the file is in the INSERT directory
- if (File.Exists(Variables.dirInsert + entry.Name))
- return 1;
+ if (File.Exists(Variables.dirPack + entry.Name))
+ return EnumSource.PACK_DIR;
// Check if the file is in the UNPACK directory
if (File.Exists(Variables.dirUnpack + numberFile + entry.FullPath))
- return 2;
+ return EnumSource.UNPACK_DIR;
// Otherwise, get the file from iso files
- return -1;
+ return EnumSource.ISO_FILE;
}
#endregion
@@ -359,8 +361,8 @@ namespace Hack.Xenosaga.Process
Trace.WriteLine("Inserting files");
Trace.Indent();
- string s_pathname = string.Format("{0}{1}.", Variables.dirPack, fileNameBase);
- Directory.CreateDirectory(Variables.dirPack);
+ string s_pathname = string.Format("{0}{1}.", Variables.dirFinal, fileNameBase);
+ Directory.CreateDirectory(Variables.dirFinal);
foreach (pathElement entryPath in index.getEntries())
{
@@ -368,15 +370,15 @@ namespace Hack.Xenosaga.Process
{
long size = 0;
- int idFile = findFile(entryPath, string.Format("{0:D2}", numFileIndex));
+ EnumSource idFile = findFile(entryPath, string.Format("{0:D2}", numFileIndex));
- if (idFile == 1 || idFile == 2)
+ if (idFile == EnumSource.PACK_DIR || idFile == EnumSource.UNPACK_DIR)
{
- if (idFile == 1)
+ if (idFile == EnumSource.PACK_DIR)
{
- Trace.WriteLine(string.Format("From {0} : file {1}", Variables.dirInsert, entryPath.FullPath));
+ Trace.WriteLine(string.Format("From {0} : file {1}", Variables.dirPack, entryPath.FullPath));
- filename = Variables.dirInsert + entryPath.Name;
+ filename = Variables.dirPack + entryPath.Name;
}
else
{
diff --git a/Hack.Xenosaga/Xenosaga.cs b/Hack.Xenosaga/Xenosaga.cs
index 66491ba..5cfabd1 100644
--- a/Hack.Xenosaga/Xenosaga.cs
+++ b/Hack.Xenosaga/Xenosaga.cs
@@ -22,15 +22,23 @@ namespace Hack.Xenosaga
switch (listArgs.option)
{
case "-l":
- Unpack.listFiles(listArgs.filename);
+ Unpack.listFiles(listArgs.filename.ToLower());
break;
case "-p":
- Unpack.packIsoFiles(listArgs.filename, listArgs.regroup);
+ Unpack.packIsoFiles(listArgs.filename.ToLower(), listArgs.regroup);
break;
case "-u":
- Unpack.unpackIsoFiles(listArgs.filename);
+ Unpack.unpackIsoFiles(listArgs.filename.ToLower());
+ break;
+
+ case "-e":
+ Scripts.extract(listArgs.filename.ToLower(), listArgs.encode);
+ break;
+
+ case "-i":
+ Scripts.insert(listArgs.filename.ToLower(), listArgs.encode);
break;
}
}
diff --git a/README.md b/README.md
index a221376..78c4402 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@ xenosaga <option> <file> [regroup]
option : -l = List files from index
-u = Unpack files from index
-p = Pack files from index
+ -e = Extract text from file
file : Index file (the first one of each decade : xenosaga.00, xenosaga.10, xenosaga.20...)
- regroup : true to regroup all files in only one (ex: 11, 12, 13 in 11) ; false or empty (default) to keep the same system of increment files
+ regroup : true to pack all files in only one (ex: 11, 12, 13 in 11) ; false or empty (default) to keep the same system of increment files
\ No newline at end of file