Tool dedicated to isohacking for Xenosaga on Playstation 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

576 lines
22 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using Hack.Xenosaga.Common;
  9. using Hack.Tools.Common;
  10. using Hack.Tools.Pointers;
  11. using Hack.Tools.Table;
  12. namespace Hack.Xenosaga.Process
  13. {
  14. public class Scripts
  15. {
  16. #region Private methods
  17. private static Table loadTable(string tblName, Encoding encode)
  18. {
  19. Table tbl = new Table(encode);
  20. tbl.Load(tblName);
  21. if (tblName == Variables.tblCard)
  22. {
  23. tbl.Remove("2C");
  24. tbl.Remove("27");
  25. }
  26. return tbl;
  27. }
  28. #region card.dat
  29. private static bool extractCard(string filename, Encoding encode)
  30. {
  31. int nbBlocs = 0;
  32. try
  33. {
  34. Trace.Write("Extract card.dat : ");
  35. Directory.CreateDirectory(Variables.dirExtract);
  36. Directory.CreateDirectory(Variables.dirInsert);
  37. using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open)))
  38. {
  39. cTblPointers tblPt = new cTblPointers();
  40. Table tbl = new Table(encode);
  41. tbl.Load(Variables.tblCard);
  42. nbBlocs = br.ReadInt32();
  43. br.BaseStream.Seek(0x10, SeekOrigin.Begin);
  44. // Get all pointers
  45. for (int i = 0; i < nbBlocs; i++)
  46. {
  47. for (int j = 0; j < 6; j++)
  48. br.ReadUInt32();
  49. tblPt.add(br.BaseStream.Position, br.ReadUInt32());
  50. tblPt.add(br.BaseStream.Position, br.ReadUInt32());
  51. br.ReadUInt32();
  52. }
  53. using (StreamWriter sw = new StreamWriter(Variables.dirExtract + Path.GetFileName(filename) + ".txt", false, encode))
  54. {
  55. // Extracting text from pointers
  56. foreach (Pointers pt in tblPt.ListPointers)
  57. {
  58. br.BaseStream.Seek((long)pt.Value, SeekOrigin.Begin);
  59. sw.Write(string.Format(pt.Format, pt.Adress, pt.Num));
  60. sw.Write(br.BytesToStringWithTable(tbl));
  61. }
  62. }
  63. }
  64. Trace.WriteLine("OK");
  65. }
  66. catch (Exception ex)
  67. {
  68. Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
  69. return false;
  70. }
  71. return true;
  72. }
  73. private static bool insertCard(string filename, Encoding encode)
  74. {
  75. int nbBlocs = 0;
  76. try
  77. {
  78. Trace.Write("Insert card.dat : ");
  79. using (BinaryReader brIn = new BinaryReader(File.Open(filename, FileMode.Open)))
  80. using (MemoryStream ms = new MemoryStream())
  81. {
  82. cTblPointers tblPt = new cTblPointers();
  83. Table tbl = loadTable(Variables.tblCard, encode);
  84. nbBlocs = brIn.ReadInt32();
  85. ms.Write(BitConverter.GetBytes(nbBlocs), 0, 4);
  86. for (int i = 0; i < 12; i++)
  87. ms.WriteByte(brIn.ReadByte());
  88. for (int i = 0; i < nbBlocs; i++)
  89. {
  90. for (int j = 0; j < 9; j++)
  91. ms.Write(BitConverter.GetBytes(brIn.ReadUInt32()), 0, 4);
  92. }
  93. using (BinaryReader brTxt = new BinaryReader(File.Open(Variables.dirInsert + filename + ".txt", FileMode.Open), encode))
  94. {
  95. string line = "";
  96. int sizeMax = tbl.ValueMaxSize;
  97. if (tblPt.SizeFormat > tbl.ValueMaxSize)
  98. sizeMax = tblPt.SizeFormat;
  99. long pos = 0;
  100. while (pos < brTxt.BaseStream.Length)
  101. {
  102. brTxt.BaseStream.Seek(pos, SeekOrigin.Begin);
  103. if (brTxt.BaseStream.Length - pos < sizeMax)
  104. sizeMax = (int)(brTxt.BaseStream.Length - pos);
  105. line = brTxt.BytestoString(encode, sizeMax);
  106. int adress, num;
  107. if (tblPt.textIsPointerInfo(line))
  108. {
  109. tblPt.getInfoPt(line, out adress, out num);
  110. tblPt.add(adress, (ulong)ms.Position, 2, (int)typeEndian.LITTLE, num);
  111. pos += tblPt.SizeFormat;
  112. }
  113. else
  114. {
  115. stElement stResult = tbl.FindKeyFromValue(line.ToCharArray());
  116. switch (stResult.type)
  117. {
  118. case typeEntries.NORMAL:
  119. case typeEntries.ENDBLOCK:
  120. ms.Write(stResult.keyBytes, 0, stResult.keySize);
  121. break;
  122. case typeEntries.PARAM:
  123. break;
  124. case typeEntries.NOT_FOUND:
  125. Trace.WriteLine(string.Format("ERROR : Unknown character {0} in {1}", line.Substring(0, 1), line));
  126. return false;
  127. }
  128. pos += stResult.valueSize;
  129. }
  130. }
  131. }
  132. // Write pointer in file
  133. tblPt.insertPointersToFile(ms);
  134. Directory.CreateDirectory(Variables.dirPack);
  135. using (FileStream fs = new FileStream(Variables.dirPack + filename, FileMode.Create))
  136. {
  137. ms.Position = 0;
  138. ms.CopyTo(fs);
  139. }
  140. }
  141. Trace.WriteLine("OK");
  142. return true;
  143. }
  144. catch (Exception ex)
  145. {
  146. Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
  147. return false;
  148. }
  149. }
  150. #endregion
  151. #region evtitem.dat
  152. public static bool extractEvtitem(string filename, Encoding encode)
  153. {
  154. int numBloc = 0;
  155. int sizeBloc = 128;
  156. long pos = 0;
  157. try
  158. {
  159. Trace.Write("Extract evtitem.dat : ");
  160. Directory.CreateDirectory(Variables.dirExtract);
  161. Directory.CreateDirectory(Variables.dirInsert);
  162. using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open)))
  163. {
  164. Table tbl = new Table(encode);
  165. tbl.Load(Variables.tblEvtItem);
  166. using (StreamWriter sw = new StreamWriter(Variables.dirExtract + Path.GetFileName(filename) + ".txt", false, encode))
  167. {
  168. while (br.PeekChar() != 0)
  169. {
  170. sw.Write(string.Format("[{0:d4}]\n", numBloc));
  171. // Read object name
  172. sw.Write(tbl.BytesToString(br));
  173. // Read object description
  174. sw.Write(tbl.BytesToString(br));
  175. pos += sizeBloc;
  176. numBloc++;
  177. br.BaseStream.Position = pos;
  178. }
  179. }
  180. }
  181. Trace.WriteLine("OK");
  182. }
  183. catch (Exception ex)
  184. {
  185. Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
  186. return false;
  187. }
  188. return true;
  189. }
  190. private static bool insertEvtitem(string filename, Encoding encode)
  191. {
  192. string name = Path.GetFileName(filename);
  193. int sizeBloc = 128;
  194. try
  195. {
  196. Trace.Write("Insert evtitem.dat : ");
  197. using (BinaryReader brOriginalDatFile = new BinaryReader(File.Open(filename, FileMode.Open)))
  198. using (MemoryStream ms = new MemoryStream())
  199. {
  200. cTblPointers tblPt = new cTblPointers();
  201. Table tbl = loadTable(Variables.tblEvtItem, encode);
  202. Dictionary<string, byte[]> bytes = tbl.StringToBytesArray(Variables.dirInsert + name + ".txt", new Regex(@"\[(.{4})\]\n"));
  203. foreach (KeyValuePair<string, byte[]> b in bytes)
  204. {
  205. if (b.Value.Length > sizeBloc)
  206. throw new Exception(string.Format("Bloc [{0}] too long : {1}/{2}!", b.Key, b.Value.Length, sizeBloc));
  207. ms.Write(b.Value, 0, b.Value.Length);
  208. ms.Padding(sizeBloc);
  209. }
  210. Directory.CreateDirectory(Variables.dirPack);
  211. using (FileStream fs = new FileStream(Variables.dirPack + name, FileMode.Create))
  212. {
  213. ms.Position = 0;
  214. ms.CopyTo(fs);
  215. }
  216. }
  217. Trace.WriteLine("OK");
  218. return true;
  219. }
  220. catch (Exception ex)
  221. {
  222. Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
  223. return false;
  224. }
  225. }
  226. #endregion
  227. #region *.evt
  228. private static bool decompilEvt(string nameFile, MemoryStream ms, string nameTable)
  229. {
  230. Encoding encode = new UTF8Encoding(false);
  231. using (BinaryReader br = new BinaryReader(ms))
  232. {
  233. JavaClass jc = new JavaClass();
  234. jc.load(br);
  235. Dictionary<int, byte[]> dictBytes = jc.getConstantsBytes();
  236. if (dictBytes.Count > 0)
  237. {
  238. using (StreamWriter sw = new StreamWriter(Variables.dirExtract + nameFile + ".txt", false, encode))
  239. {
  240. Table tbl = loadTable(nameTable, Encoding.Default);
  241. foreach (KeyValuePair<int, byte[]> bytes in dictBytes)
  242. {
  243. sw.Write(string.Format("[{0:X4}]\n", bytes.Key));
  244. if (bytes.Value != null)
  245. sw.Write(tbl.BytesToString(bytes.Value));
  246. }
  247. }
  248. }
  249. }
  250. return true;
  251. }
  252. private static bool extractEvt(string pathName, Encoding encode)
  253. {
  254. try
  255. {
  256. Trace.Write(string.Format("Extract {0} : ", pathName));
  257. evtClass evtFile = new evtClass(pathName);
  258. string nameTable = Variables.tblEvtBox;
  259. if (Path.GetFileName(pathName).Substring(0, 3).ToUpper() == "SCE")
  260. nameTable = Variables.tblEvtVideo;
  261. Directory.CreateDirectory(Variables.dirExtract);
  262. Directory.CreateDirectory(Variables.dirInsert);
  263. foreach (evtClass.stFile file in evtFile.listFiles)
  264. {
  265. using (MemoryStream ms = new MemoryStream())
  266. {
  267. ms.Write(file.file, 0, (int)file.fileLength);
  268. ms.Position = 0;
  269. decompilEvt(file.name, ms, nameTable);
  270. }
  271. }
  272. Trace.WriteLine("OK");
  273. return true;
  274. }
  275. catch (Exception ex)
  276. {
  277. Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
  278. return false;
  279. }
  280. }
  281. private static bool insertEvt(string pathName, Encoding encode)
  282. {
  283. try
  284. {
  285. Trace.Write(string.Format("Insert {0} : ", pathName));
  286. using (BinaryReader br = new BinaryReader(File.Open(pathName, FileMode.Open)))
  287. {
  288. evtClass origEvt = new evtClass(br);
  289. Table tbl;
  290. if (Path.GetFileName(pathName).Substring(0, 3).ToUpper() == "SCE")
  291. tbl = loadTable(Variables.tblEvtVideo, Encoding.Default);
  292. else
  293. tbl = loadTable(Variables.tblEvtBox, Encoding.Default);
  294. using (MemoryStream destEvt = new MemoryStream())
  295. {
  296. destEvt.Write(BitConverter.GetBytes(origEvt.id), 0, 4);
  297. destEvt.Write(BitConverter.GetBytes(origEvt.unkAdr4), 0, 2);
  298. destEvt.Write(BitConverter.GetBytes(origEvt.unkAdr6), 0, 2);
  299. destEvt.Position = 16;
  300. destEvt.Write(BitConverter.GetBytes(origEvt.unkAdr16), 0, 2);
  301. destEvt.Write(BitConverter.GetBytes(origEvt.nbFiles), 0, 2);
  302. destEvt.Position = 16 * origEvt.nbFiles + 20;
  303. using (MemoryStream msIndex = new MemoryStream())
  304. using (MemoryStream msName = new MemoryStream())
  305. {
  306. msName.WriteByte(0);
  307. msName.WriteByte(0);
  308. foreach (evtClass.stFile classFile in origEvt.listFiles)
  309. {
  310. msIndex.Write(BitConverter.GetBytes(msName.Position), 0, 4);
  311. msIndex.Write(BitConverter.GetBytes(classFile.nameLength), 0, 4);
  312. msIndex.Write(BitConverter.GetBytes(destEvt.Position), 0, 4);
  313. msName.Write(encode.GetBytes(classFile.name), 0, (int)classFile.nameLength);
  314. msName.WriteByte(0);
  315. if (File.Exists(Variables.dirInsert + classFile.name + ".txt"))
  316. {
  317. Dictionary<string, byte[]> list = tbl.StringToBytesArray(Variables.dirInsert + classFile.name + ".txt", new Regex(@"\[(.{4})\]\n"));
  318. JavaClass jc = new JavaClass();
  319. using (MemoryStream msFile = new MemoryStream())
  320. {
  321. msFile.Write(classFile.file, 0, (int)classFile.fileLength);
  322. msFile.Position = 0;
  323. using (BinaryReader brFile = new BinaryReader(msFile))
  324. {
  325. br.BaseStream.Position = 0;
  326. jc.load(brFile);
  327. }
  328. }
  329. Dictionary<int, byte[]> dictBytes = jc.getConstantsBytes();
  330. if (dictBytes.Count > 0)
  331. {
  332. string pt = "";
  333. foreach (KeyValuePair<int, byte[]> bytes in dictBytes)
  334. {
  335. pt = string.Format("{0:X4}", bytes.Key);
  336. if (dictBytes.ContainsKey(Convert.ToInt32(pt, 16)) && list[pt] != null)
  337. {
  338. if (list[pt].Length >= 255)
  339. throw new Exception("Line too long (254 characters max)!");
  340. jc.setConstantsBytes(bytes.Key, list[pt]);
  341. }
  342. }
  343. }
  344. MemoryStream newFile = jc.compilClass(classFile);
  345. msIndex.Write(BitConverter.GetBytes(newFile.Length), 0, 4);
  346. destEvt.Write(newFile.ToArray(), 0, (int)newFile.Length);
  347. }
  348. else
  349. {
  350. msIndex.Write(BitConverter.GetBytes(classFile.fileLength), 0, 4);
  351. destEvt.Write(classFile.file, 0, (int)classFile.fileLength);
  352. }
  353. destEvt.Padding();
  354. }
  355. long posName = destEvt.Position;
  356. // Write filename table
  357. msName.Write(BitConverter.GetBytes(0x2E), 0, 2, 0);
  358. //msName.Write(BitConverter.GetBytes(msName.Length-2), 0, 2, 0);
  359. msName.Position = 0;
  360. destEvt.Write(BitConverter.GetBytes(posName), 0, 4, 12);
  361. destEvt.Write(msName.ToArray(), 0, (int)msName.Length);
  362. destEvt.Write(BitConverter.GetBytes(destEvt.Length), 0, 4, 8);
  363. // Write index of files
  364. destEvt.Position = 20;
  365. msIndex.Position = 0;
  366. for (int i = 0; i < origEvt.nbFiles; i++)
  367. {
  368. destEvt.Write(BitConverter.GetBytes(msIndex.Read() + posName), 0, 4);
  369. destEvt.Write(BitConverter.GetBytes(msIndex.Read()), 0, 4);
  370. destEvt.Write(BitConverter.GetBytes(msIndex.Read()), 0, 4);
  371. destEvt.Write(BitConverter.GetBytes(msIndex.Read()), 0, 4);
  372. }
  373. }
  374. Directory.CreateDirectory(Variables.dirPack);
  375. using (FileStream fs = new FileStream(Variables.dirPack + Path.GetFileName(pathName), FileMode.Create))
  376. {
  377. destEvt.Position = 0;
  378. fs.Write(destEvt.ToArray(), 0, (int)destEvt.Length);
  379. }
  380. }
  381. }
  382. Trace.WriteLine("OK");
  383. return true;
  384. }
  385. catch (Exception ex)
  386. {
  387. Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
  388. return false;
  389. }
  390. }
  391. #endregion
  392. #endregion
  393. #region Public methods
  394. public static void extract(string pathName, Encoding encode)
  395. {
  396. bool result;
  397. if (File.Exists(pathName))
  398. {
  399. if (Path.GetFileName(pathName) == "card.dat")
  400. result = extractCard(pathName, encode);
  401. if (Path.GetFileName(pathName) == "evtitem.dat")
  402. result = extractEvtitem(pathName, encode);
  403. if (Path.GetExtension(pathName) == ".evt")
  404. result = extractEvt(pathName, encode);
  405. }
  406. else if (Directory.Exists(pathName))
  407. {
  408. var listFiles = Directory
  409. .EnumerateFiles(pathName)
  410. .Where(file => file.ToLower().EndsWith("dat") || file.ToLower().EndsWith("evt"))
  411. .ToList();
  412. foreach (string file in listFiles)
  413. {
  414. if (Path.GetFileName(file) == "card.dat")
  415. result = extractCard(file.ToLower(), encode);
  416. else if (Path.GetFileName(file) == "evtitem.dat")
  417. result = extractEvtitem(file.ToLower(), encode);
  418. else if (Path.GetExtension(file) == ".evt")
  419. result = extractEvt(file.ToLower(), encode);
  420. }
  421. }
  422. else
  423. Trace.WriteLine("Unknown file or directory");
  424. }
  425. public static void insert(string pathName, Encoding encode)
  426. {
  427. bool result;
  428. if (File.Exists(pathName))
  429. {
  430. if (Path.GetFileName(pathName).ToLower() == "card.dat")
  431. result = insertCard(pathName, encode);
  432. if (Path.GetFileName(pathName).ToLower() == "evtitem.dat")
  433. result = insertEvtitem(pathName, encode);
  434. if (Path.GetExtension(pathName).ToLower() == ".evt")
  435. result = insertEvt(pathName, encode);
  436. }
  437. else if (Directory.Exists(pathName))
  438. {
  439. var listFiles = Directory
  440. .EnumerateFiles(pathName)
  441. .Where(file => file.ToLower().EndsWith("dat") || file.ToLower().EndsWith("evt"))
  442. .ToList();
  443. foreach (string file in listFiles)
  444. {
  445. if (Path.GetFileName(file).ToLower() == "card.dat")
  446. result = insertCard(file.ToLower(), encode);
  447. else if (Path.GetFileName(file).ToLower() == "evtitem.dat")
  448. result = insertEvtitem(file.ToLower(), encode);
  449. else if (Path.GetExtension(file).ToLower() == ".evt")
  450. result = insertEvt(file.ToLower(), encode);
  451. }
  452. }
  453. else
  454. Trace.WriteLine("Unknown file of directory");
  455. }
  456. #endregion
  457. }
  458. }