ArchiveWorker.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Linq;
  5. namespace FF8
  6. {
  7. internal class ArchiveWorker
  8. {
  9. static uint _unpackedFileSize;
  10. static uint _locationInFs;
  11. static bool _compressed;
  12. private string _path;
  13. public string GetPath() => _path;
  14. public static string[] FileList;
  15. public ArchiveWorker(string path)
  16. {
  17. _path = MakiExtended.GetUnixFullPath(path);
  18. string root = Path.GetDirectoryName(_path);
  19. string file = Path.GetFileNameWithoutExtension(_path);
  20. string fi = MakiExtended.GetUnixFullPath($"{Path.Combine(root, file)}{Memory.Archives.B_FileIndex}");
  21. string fl = MakiExtended.GetUnixFullPath($"{Path.Combine(root, file)}{Memory.Archives.B_FileList}");
  22. if (!File.Exists(fi)) throw new Exception($"There is no {file}.fi file!\nExiting...");
  23. if (!File.Exists(fl)) throw new Exception($"There is no {file}.fl file!\nExiting...");
  24. FileList = ProduceFileLists();
  25. }
  26. private string[] ProduceFileLists() =>
  27. File.ReadAllLines(
  28. $"{Path.Combine(Path.GetDirectoryName(_path), Path.GetFileNameWithoutExtension(_path))}{Memory.Archives.B_FileList}"
  29. );
  30. public static string[] GetBinaryFileList(byte[] fl) =>System.Text.Encoding.ASCII.GetString(fl).Replace("\r", "").Replace("\0", "").Split('\n');
  31. public byte[] GetBinaryFile(string fileName) => GetBinaryFile(_path, fileName);
  32. public static byte[] GetBinaryFile(string archiveName, string fileName)
  33. {
  34. byte[] isComp = GetBin(MakiExtended.GetUnixFullPath(archiveName), fileName);
  35. if(_compressed)
  36. isComp = isComp.Skip(4).ToArray();
  37. return isComp == null ? null : _compressed ? LZSS.DecompressAllNew(isComp) : isComp;
  38. }
  39. /// <summary>
  40. /// Give me three archives as bytes uncompressed please!
  41. /// </summary>
  42. /// <param name="FI">FileIndex</param>
  43. /// <param name="FS">FileSystem</param>
  44. /// <param name="FL">FileList</param>
  45. /// <param name="filename">Filename of the file to get</param>
  46. /// <returns></returns>
  47. public static byte[] FileInTwoArchives(byte[] FI, byte[] FS, byte[] FL, string filename)
  48. {
  49. string a = filename.TrimEnd('\0');
  50. string flText = System.Text.Encoding.UTF8.GetString(FL);
  51. flText = flText.Replace(Convert.ToString(0x0d), "");
  52. int loc = -1;
  53. string[] files = flText.Split((char)0x0a);
  54. for (int i = 0; i != files.Length; i++) //check archive for filename
  55. {
  56. string testme = files[i].Substring(0, files[i].Length - 1).ToUpper().TrimEnd('\0');
  57. if (testme != a.ToUpper()) continue;
  58. loc = i;
  59. break;
  60. }
  61. if (loc == -1)
  62. {
  63. Debug.WriteLine("ArchiveWorker: NO SUCH FILE!");
  64. return null;
  65. //throw new Exception("ArchiveWorker: No such file!");
  66. }
  67. uint fsLen = BitConverter.ToUInt32(FI, loc * 12);
  68. uint fSpos = BitConverter.ToUInt32(FI, (loc * 12) + 4);
  69. bool compe = BitConverter.ToUInt32(FI, (loc * 12) + 8) != 0;
  70. byte[] file = new byte[fsLen];
  71. Array.Copy(FS, fSpos, file, 0, file.Length);
  72. return compe ? LZSS.DecompressAllNew(file) : file;
  73. }
  74. private static byte[] GetBin(string archiveName, string fileName)
  75. {
  76. if (fileName.Length < 1 || archiveName.Length < 1)
  77. throw new System.Exception("NO FILENAME OR ARCHIVE!");
  78. string archivePath = archiveName + Memory.Archives.B_FileArchive;
  79. string archiveIndexPath = archiveName + Memory.Archives.B_FileIndex;
  80. string archiveNamesPath = archiveName + Memory.Archives.B_FileList;
  81. int loc = -1;
  82. FileStream fs = new FileStream(archiveNamesPath, FileMode.Open);
  83. TextReader tr = new StreamReader(fs);
  84. string locTr = tr.ReadToEnd();
  85. tr.Dispose();
  86. fs.Close();
  87. //locTr = locTr.Replace(Convert.ToString(0x0d), "");
  88. string[] files = locTr.Split((char)0x0a);
  89. for (int i = 0; i != files.Length - 1; i++)
  90. {
  91. string testme = files[i].Substring(0, files[i].Length - 1).ToUpper();
  92. if (testme == fileName.ToUpper())
  93. {
  94. loc = i;
  95. break;
  96. }
  97. }
  98. if (loc == -1)
  99. {
  100. Debug.WriteLine("ArchiveWorker: NO SUCH FILE!");
  101. return null;
  102. //throw new Exception("ArchiveWorker: No such file!");
  103. }
  104. fs = new FileStream(archiveIndexPath, FileMode.Open);
  105. BinaryReader br = new BinaryReader(fs);
  106. fs.Seek(loc * 12, SeekOrigin.Begin);
  107. _unpackedFileSize = br.ReadUInt32(); //fs.Seek(4, SeekOrigin.Current);
  108. _locationInFs = br.ReadUInt32();
  109. _compressed = br.ReadUInt32() != 0;
  110. fs.Close();
  111. fs = new FileStream(archivePath, FileMode.Open);
  112. fs.Seek(_locationInFs, SeekOrigin.Begin);
  113. br = new BinaryReader(fs);
  114. int howMany = _compressed ? br.ReadInt32() : (int)_unpackedFileSize;
  115. byte[] temp;
  116. if (_compressed)
  117. {
  118. fs.Seek(-4, SeekOrigin.Current);
  119. temp = br.ReadBytes(howMany + 4);
  120. }
  121. else
  122. temp = br.ReadBytes(howMany);
  123. fs.Close();
  124. return temp;
  125. }
  126. public string[] GetListOfFiles() => FileList;
  127. public struct FI
  128. {
  129. public uint LengthOfUnpackedFile;
  130. public uint LocationInFS;
  131. public uint LZSS;
  132. }
  133. public FI[] GetFI()
  134. {
  135. FI[] FileIndex = new FI[FileList.Length];
  136. string flPath = $"{Path.GetDirectoryName(_path)}\\{Path.GetFileNameWithoutExtension(_path)}.fi";
  137. using (FileStream fs = new FileStream(flPath, FileMode.Open, FileAccess.Read))
  138. using (BinaryReader br = new BinaryReader(fs))
  139. for (int i = 0; i <= FileIndex.Length - 1; i++)
  140. {
  141. FileIndex[i].LengthOfUnpackedFile = br.ReadUInt32();
  142. FileIndex[i].LocationInFS = br.ReadUInt32();
  143. FileIndex[i].LZSS = br.ReadUInt32();
  144. }
  145. return FileIndex;
  146. }
  147. }
  148. }