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 + Path.GetFileName(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 evtitem.dat public static bool extractEvtitem(string filename, Encoding encode) { int numBloc = 0; int sizeBloc = 128; long pos = 0; try { Trace.Write("Extract evtitem.dat : "); Directory.CreateDirectory(Variables.dirExtract); Directory.CreateDirectory(Variables.dirInsert); using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open))) { Table tbl = new Table(encode); tbl.Load(Variables.tblEvtItem); using (StreamWriter sw = new StreamWriter(Variables.dirExtract + Path.GetFileName(filename) + ".txt", false, encode)) { while (br.PeekChar() != 0) { sw.Write(string.Format("[{0:d4}]\n", numBloc)); // Read object name sw.Write(tbl.BytesToString(br)); // Read object description sw.Write(tbl.BytesToString(br)); pos += sizeBloc; numBloc++; br.BaseStream.Position = pos; } } } Trace.WriteLine("OK"); } catch (Exception ex) { Trace.WriteLine(string.Format("ERROR : {0}", ex.Message)); return false; } return true; } private static bool insertEvtitem(string filename, Encoding encode) { string name = Path.GetFileName(filename); int sizeBloc = 128; try { Trace.Write("Insert evtitem.dat : "); using (BinaryReader brOriginalDatFile = new BinaryReader(File.Open(filename, FileMode.Open))) using (MemoryStream ms = new MemoryStream()) { cTblPointers tblPt = new cTblPointers(); Table tbl = loadTable(Variables.tblEvtItem, encode); Dictionary bytes = tbl.StringToBytesArray(Variables.dirInsert + name + ".txt", new Regex(@"\[(.{4})\]\n")); foreach (KeyValuePair b in bytes) { if (b.Value.Length > sizeBloc) throw new Exception(string.Format("Bloc [{0}] too long : {1}/{2}!", b.Key, b.Value.Length, sizeBloc)); ms.Write(b.Value, 0, b.Value.Length); ms.Padding(sizeBloc); } Directory.CreateDirectory(Variables.dirPack); using (FileStream fs = new FileStream(Variables.dirPack + name, 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, string nameTable) { Encoding encode = new UTF8Encoding(false); using (BinaryReader br = new BinaryReader(ms)) { JavaClass jc = new JavaClass(); jc.load(br); Dictionary dictBytes = jc.getConstantsBytes(); if (dictBytes.Count > 0) { using (StreamWriter sw = new StreamWriter(Variables.dirExtract + nameFile + ".txt", false, encode)) { Table tbl = loadTable(nameTable, 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 bool extractEvt(string pathName, Encoding encode) { try { Trace.Write(string.Format("Extract {0} : ", pathName)); evtClass evtFile = new evtClass(pathName); string nameTable = Variables.tblEvtBox; if (Path.GetFileName(pathName).Substring(0, 3).ToUpper() == "SCE") nameTable = Variables.tblEvtVideo; 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, nameTable); } } 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.Write(string.Format("Insert {0} : ", pathName)); using (BinaryReader br = new BinaryReader(File.Open(pathName, FileMode.Open))) { evtClass origEvt = new evtClass(br); Table tbl; if (Path.GetFileName(pathName).Substring(0, 3).ToUpper() == "SCE") tbl = loadTable(Variables.tblEvtVideo, Encoding.Default); else tbl = loadTable(Variables.tblEvtBox, 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) { if (list[pt].Length >= 255) throw new Exception("Line too long (254 characters max)!"); 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); } destEvt.Padding(); } long posName = destEvt.Position; // Write filename table msName.Write(BitConverter.GetBytes(0x2E), 0, 2, 0); //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, 4, 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); } } Directory.CreateDirectory(Variables.dirPack); 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.GetFileName(pathName) == "evtitem.dat") result = extractEvtitem(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.GetFileName(file) == "evtitem.dat") result = extractEvtitem(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).ToLower() == "card.dat") result = insertCard(pathName, encode); if (Path.GetFileName(pathName).ToLower() == "evtitem.dat") result = insertEvtitem(pathName, encode); if (Path.GetExtension(pathName).ToLower() == ".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).ToLower() == "card.dat") result = insertCard(file.ToLower(), encode); else if (Path.GetFileName(file).ToLower() == "evtitem.dat") result = insertEvtitem(file.ToLower(), encode); else if (Path.GetExtension(file).ToLower() == ".evt") result = insertEvt(file.ToLower(), encode); } } else Trace.WriteLine("Unknown file of directory"); } #endregion } }