ArchiveWorker.cs 7.1 KB

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