Search.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. namespace OpenVIII.Search
  7. {
  8. public class Search
  9. {
  10. #region Fields
  11. public List<Tuple<string, string, long>> Results = new List<Tuple<string, string, long>>();
  12. private static readonly Memory.Archive[] ArchiveList = {
  13. Memory.Archives.A_MENU,
  14. Memory.Archives.A_MAIN,
  15. Memory.Archives.A_FIELD, // need support for file in two archives.
  16. Memory.Archives.A_MAGIC,
  17. Memory.Archives.A_WORLD,
  18. Memory.Archives.A_BATTLE,
  19. };
  20. private static readonly string[] Files = new string[]
  21. {
  22. Path.Combine(Memory.FF8Dir,"FF8_EN.exe"),
  23. //Path.Combine(Memory.FF8DIR,"AF3DN.P"),
  24. //Path.Combine(Memory.FF8DIR,"AF4DN.P")
  25. };
  26. private readonly byte[] _s;
  27. private readonly string[] _skipExtension = {
  28. ".tim",
  29. ".tex",
  30. ".obj"
  31. };
  32. #endregion Fields
  33. #region Constructors
  34. public Search(FF8String searchstring)
  35. {
  36. _s = searchstring;
  37. foreach (var a in ArchiveList)
  38. {
  39. var aw = ArchiveWorker.Load(a);
  40. var lof = aw.GetListOfFiles();
  41. foreach (var f in lof)
  42. {
  43. var ext = Path.GetExtension(f);
  44. if (_skipExtension.Any(x => ext != null && x.IndexOf(ext, StringComparison.OrdinalIgnoreCase) >= 0)) continue;
  45. Debug.WriteLine($"Searching {f}, in {a} for {searchstring}");
  46. //byte[] bf = aw.GetBinaryFile(f);
  47. //SearchBin(bf, a.ToString(), f);
  48. using (var br = new BinaryReader(new MemoryStream(aw.GetBinaryFile(f))))
  49. {
  50. SearchBin(br, a.ToString(), f);
  51. }
  52. }
  53. }
  54. foreach (var a in Files)
  55. {
  56. Debug.WriteLine($"Searching {a}, for {searchstring}");
  57. using (var br = new BinaryReader(File.OpenRead(a))) //new FileStream(a, FileMode.Open, FileAccess.Read, FileShare.None, 65536)))//
  58. {
  59. br.BaseStream.Seek(0, SeekOrigin.Begin);
  60. //byte[] bf = br.ReadBytes((int)br.BaseStream.Length);
  61. //SearchBin(bf, a, "");
  62. SearchBin(br, a, "");
  63. }
  64. }
  65. }
  66. #endregion Constructors
  67. #region Methods
  68. /// <summary>
  69. /// Less Slow search.
  70. /// </summary>
  71. /// <param name="bf">buffer</param>
  72. /// <param name="a">file/archive it's searching</param>
  73. /// <param name="f">sub file</param>
  74. public void SearchBin(BinaryReader br, string a, string f)
  75. {
  76. long offset;
  77. while ((offset = br.BaseStream.Position) < br.BaseStream.Length)
  78. {
  79. var pos = 0;
  80. foreach (var i in _s)
  81. {
  82. if (br.ReadByte() == i)
  83. {
  84. pos++;
  85. }
  86. else break;
  87. }
  88. if (pos == _s.Length)
  89. {
  90. Debug.WriteLine($"Found a match at: offset {offset:X}");
  91. Results.Add(new Tuple<string, string, long>(a, f, offset));
  92. }
  93. }
  94. }
  95. /// <summary>
  96. /// Slow AF search.
  97. /// </summary>
  98. /// <param name="bf">buffer</param>
  99. /// <param name="a">file/archive it's searching</param>
  100. /// <param name="f">sub file</param>
  101. public void SearchBin(byte[] bf, string a, string f)
  102. {
  103. var i = 0;
  104. do
  105. {
  106. i = Array.FindIndex(bf, i, bf.Length - i, x => x == _s[0]);
  107. if (i < 0) continue;
  108. var full = bf.Skip(i).Take(_s.Length).ToArray();
  109. if (full.SequenceEqual(_s))
  110. {
  111. Debug.WriteLine($"Found a match at: offset {i:X}");
  112. Results.Add(new Tuple<string, string, long>(a, f, i));
  113. }
  114. i++;
  115. }
  116. while (i > 0);
  117. }
  118. #endregion Methods
  119. }
  120. }