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<string, byte[]> bytes = tbl.StringToBytesArray(Variables.dirInsert + name + ".txt", new Regex(@"\[(.{4})\]\n"));
|
|
|
|
foreach (KeyValuePair<string, byte[]> 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<int, byte[]> 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<int, byte[]> 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<string, byte[]> 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<int, byte[]> dictBytes = jc.getConstantsBytes();
|
|
|
|
if (dictBytes.Count > 0)
|
|
{
|
|
string pt = "";
|
|
foreach (KeyValuePair<int, byte[]> 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
|
|
}
|
|
}
|