/GeckoDotNET/Gecko dNet/MemSearch.cs

http://geckowii.googlecode.com/ · C# · 1654 lines · 1034 code · 207 blank · 413 comment · 227 complexity · 8cd7d93bd47056a434b4d96ede72a914 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5. using System.Windows.Forms;
  6. using Ionic.Zip;
  7. using FTDIUSBGecko;
  8. namespace GeckoApp
  9. {
  10. public enum SearchSize
  11. {
  12. Bit8,
  13. Bit16,
  14. Bit32,
  15. Single
  16. }
  17. public enum SearchType
  18. {
  19. Exact,
  20. Unknown,
  21. Old,
  22. Diff
  23. }
  24. public enum ComparisonType
  25. {
  26. Equal,
  27. NotEqual,
  28. Lower,
  29. LowerEqual,
  30. Greater,
  31. GreaterEqual,
  32. DifferentBy,
  33. DifferentByLess,
  34. DifferentByMore
  35. }
  36. public class SearchComparisonInfo
  37. {
  38. public ComparisonType comparisonType;
  39. public UInt32 value;
  40. public SearchType searchType;
  41. public SearchComparisonInfo()
  42. {
  43. comparisonType = ComparisonType.Equal;
  44. value = 0;
  45. searchType = SearchType.Exact;
  46. }
  47. public SearchComparisonInfo(ComparisonType ctype, UInt32 searchValue, SearchType stype)
  48. {
  49. comparisonType = ctype;
  50. value = searchValue;
  51. searchType = stype;
  52. }
  53. }
  54. [Serializable()]
  55. public class SearchResult
  56. {
  57. private UInt32 PAddress;
  58. private UInt32 PValue;
  59. private UInt32 POldValue;
  60. public UInt32 address { get { return PAddress; } }
  61. public UInt32 value { get { return PValue; } }
  62. public UInt32 oldValue { get { return POldValue; } }
  63. public SearchResult(UInt32 address,UInt32 value,UInt32 old)
  64. {
  65. PAddress = address;
  66. PValue = value;
  67. POldValue = old;
  68. }
  69. }
  70. public class DumpRange
  71. {
  72. public UInt32 rangeLength;
  73. public UInt32 streamOffset;
  74. private UInt32 PStartAddress;
  75. private UInt32 PEndAddress;
  76. public UInt32 startAddress
  77. {
  78. get
  79. {
  80. return PStartAddress;
  81. }
  82. set
  83. {
  84. PStartAddress = value;
  85. }
  86. }
  87. public UInt32 endAddress {
  88. get
  89. {
  90. return PEndAddress;
  91. }
  92. set
  93. {
  94. PEndAddress = value;
  95. }
  96. }
  97. public DumpRange()
  98. {
  99. }
  100. public DumpRange(UInt32 startAddress)
  101. {
  102. PStartAddress = startAddress;
  103. }
  104. public DumpRange(UInt32 startAddress, UInt32 endAddress)
  105. {
  106. PStartAddress = startAddress;
  107. PEndAddress = endAddress;
  108. }
  109. }
  110. public struct StringResult
  111. {
  112. public String SAddress;
  113. public String SValue;
  114. public String SOldValue;
  115. }
  116. public class MemSearch
  117. {
  118. const int pageSize = 256;
  119. //private List<SearchResult> resList;
  120. private List<UInt32> resultAddressList;
  121. private SearchSize sSize;
  122. private int cPage;
  123. private int cPages;
  124. private int oldSelectedRow;
  125. private bool InitialSearch;
  126. public SearchSize searchSize
  127. { get { return sSize; } }
  128. private bool UnknownStart;
  129. private UInt32 UnknownLAddress;
  130. private UInt32 UnknownHAddress;
  131. private USBGecko gecko;
  132. private DataGridView gView;
  133. private Button prvButton;
  134. private Button nxButton;
  135. private Label resLab;
  136. private NumericUpDown pageUpDown;
  137. private MemoryStream orgStream;
  138. private MemoryStream cmpStream;
  139. public Dump oldDump;
  140. public Dump newDump;
  141. private Dump undoDump;
  142. private List<UInt32> undoList;
  143. private int dumpNum;
  144. public int DumpNum
  145. {
  146. get { return dumpNum; }
  147. }
  148. private SearchHistoryManager searchHistory;
  149. private bool NewSearch = true;
  150. private ExceptionHandler exceptionHandling;
  151. private bool PBlockDump;
  152. private UInt32 PTotalBlockSize;
  153. private UInt32 PBlocksDumpedSize;
  154. private int PBlockID;
  155. private int PBlockCount;
  156. private UInt32 PBlockStart;
  157. private UInt32 PBlockEnd;
  158. private String displayType;
  159. public String DisplayType
  160. {
  161. get { return displayType; }
  162. set { displayType = value; }
  163. }
  164. public bool blockDump
  165. { get { return PBlockDump; } }
  166. public UInt32 totalBlockSize
  167. { get { return PTotalBlockSize; } }
  168. public UInt32 blocksDumpedSize
  169. { get { return PBlocksDumpedSize; } }
  170. public int blockID
  171. { get { return PBlockID; } }
  172. public int blockCount
  173. { get { return PBlockCount; } }
  174. public UInt32 blockStart
  175. { get { return PBlockStart; } }
  176. public UInt32 blockEnd
  177. { get { return PBlockEnd; } }
  178. public MemSearch(USBGecko uGecko,DataGridView uGView,Button uPrvButton,Button uNxButton,
  179. Label UResLab, NumericUpDown UPageUpDown, ExceptionHandler UEHandler)
  180. {
  181. exceptionHandling = UEHandler;
  182. gecko = uGecko;
  183. gView = uGView;
  184. prvButton = uPrvButton;
  185. nxButton = uNxButton;
  186. resLab = UResLab;
  187. pageUpDown = UPageUpDown;
  188. pageUpDown.ValueChanged += UpDownValueChanged;
  189. nxButton.Click += nextPage;
  190. prvButton.Click += previousPage;
  191. //resList = new List<SearchResult>();
  192. resultAddressList = new List<uint>();
  193. undoList = new List<uint>();
  194. PBlockDump = false;
  195. dumpNum = 0;
  196. searchHistory = new SearchHistoryManager();
  197. }
  198. void UpDownValueChanged(object sender, EventArgs e)
  199. {
  200. cPage = Convert.ToInt32(pageUpDown.Value) - 1;
  201. PrintPageAlt();
  202. }
  203. //private void PrintPage()
  204. //{
  205. // // Make sure we don't go before the first page...
  206. // if (cPage <= 0)
  207. // {
  208. // cPage = 0;
  209. // prvButton.Enabled = false;
  210. // }
  211. // else
  212. // {
  213. // // Only enable previous button if current page is > 0
  214. // prvButton.Enabled = true;
  215. // }
  216. // // ...or after the last page
  217. // if (cPage >= cPages - 1)
  218. // {
  219. // cPage = cPages - 1;
  220. // if (cPage < 0) cPage = 0;
  221. // nxButton.Enabled = false;
  222. // }
  223. // else
  224. // {
  225. // // Only enable next button if there are multiple pages and we aren't on the last page
  226. // nxButton.Enabled = (cPages > 1);
  227. // }
  228. // resLab.Text = resList.Count.ToString() + " results (page "
  229. // + (cPage + 1).ToString() + "/"
  230. // + cPages.ToString() + ")";
  231. // int i = 0;
  232. // String addr, value, oldv, diff;
  233. // int strLength;
  234. // switch (sSize)
  235. // {
  236. // case SearchSize.Bit8: strLength = 2; break;
  237. // case SearchSize.Bit16: strLength = 4; break;
  238. // default: strLength = 8; break;
  239. // }
  240. // //gView.Rows.Clear();
  241. // int start = cPage * pageSize;
  242. // int end = Math.Min(cPage * pageSize + pageSize, resList.Count);
  243. // int count = end - start;
  244. // if (count < gView.Rows.Count)
  245. // {
  246. // gView.Rows.Clear();
  247. // }
  248. // int addCount = count - gView.Rows.Count;
  249. // if (addCount > 0)
  250. // {
  251. // gView.Rows.Add(addCount);
  252. // }
  253. // for (int j = start; j < end; j++)
  254. // {
  255. // SearchResult result = resList[j];
  256. // addr = fixString(Convert.ToString(result.address, 16).ToUpper(), 8);
  257. // if (displayType == "Hex")
  258. // {
  259. // value = fixString(Convert.ToString(result.value, 16).ToUpper(), strLength);
  260. // oldv = fixString(Convert.ToString(result.oldValue, 16).ToUpper(), strLength);
  261. // diff = fixString(Convert.ToString(result.value - result.oldValue, 16).ToUpper(), strLength);
  262. // }
  263. // else if (displayType == "Dec")
  264. // {
  265. // value = ((int)result.value).ToString();
  266. // oldv = ((int)result.oldValue).ToString();
  267. // diff = ((int)(result.value - result.oldValue)).ToString();
  268. // }
  269. // else
  270. // {
  271. // value = GlobalFunctions.UIntToSingle(result.value).ToString("g5");
  272. // oldv = GlobalFunctions.UIntToSingle(result.oldValue).ToString("g5");
  273. // diff = GlobalFunctions.UIntToSingle(result.value - result.oldValue).ToString("g5");
  274. // }
  275. // gView.Rows[i].Cells[0].Value = addr;
  276. // if (!InitialSearch)
  277. // {
  278. // gView.Rows[i].Cells[1].Value = oldv;
  279. // gView.Rows[i].Cells[3].Value = diff;
  280. // }
  281. // else
  282. // {
  283. // gView.Rows[i].Cells[1].Value = "";
  284. // gView.Rows[i].Cells[3].Value = "";
  285. // }
  286. // gView.Rows[i].Cells[2].Value = value;
  287. // i++;
  288. // }
  289. //}
  290. private void PrintPageAlt()
  291. {
  292. // Make sure we don't go before the first page...
  293. if (cPage <= 0)
  294. {
  295. cPage = 0;
  296. prvButton.Enabled = false;
  297. }
  298. else
  299. {
  300. // Only enable previous button if current page is > 0
  301. prvButton.Enabled = true;
  302. }
  303. // ...or after the last page
  304. if (cPage >= cPages - 1)
  305. {
  306. cPage = cPages - 1;
  307. if (cPage < 0) cPage = 0;
  308. nxButton.Enabled = false;
  309. }
  310. else
  311. {
  312. // Only enable next button if there are multiple pages and we aren't on the last page
  313. nxButton.Enabled = (cPages > 1);
  314. }
  315. resLab.Text = resultAddressList.Count.ToString() + " results ("
  316. + cPages.ToString() + " pages)";
  317. int i = 0;
  318. String addr, value, oldv, diff;
  319. int strLength;
  320. switch (sSize)
  321. {
  322. case SearchSize.Bit8: strLength = 2; break;
  323. case SearchSize.Bit16: strLength = 4; break;
  324. default: strLength = 8; break;
  325. }
  326. int searchBytes = strLength / 2;
  327. //gView.Rows.Clear();
  328. int start = cPage * pageSize;
  329. int end = Math.Min(cPage * pageSize + pageSize, resultAddressList.Count);
  330. int count = end - start;
  331. if (count < gView.Rows.Count)
  332. {
  333. gView.Rows.Clear();
  334. }
  335. int addCount = count - gView.Rows.Count;
  336. if (addCount > 0)
  337. {
  338. gView.Rows.Add(addCount);
  339. }
  340. for (int j = start; j < end; j++)
  341. {
  342. SearchResult result;
  343. if (oldDump == null)
  344. {
  345. result = new SearchResult(resultAddressList[j],
  346. newDump.ReadAddress(resultAddressList[j], searchBytes),
  347. 0);
  348. }
  349. else
  350. {
  351. result = new SearchResult(resultAddressList[j],
  352. newDump.ReadAddress(resultAddressList[j], searchBytes),
  353. oldDump.ReadAddress(resultAddressList[j], searchBytes));
  354. }
  355. addr = fixString(Convert.ToString(result.address, 16).ToUpper(), 8);
  356. if (displayType == "Hex")
  357. {
  358. value = fixString(Convert.ToString(result.value, 16).ToUpper(), strLength);
  359. oldv = fixString(Convert.ToString(result.oldValue, 16).ToUpper(), strLength);
  360. diff = fixString(Convert.ToString(result.value - result.oldValue, 16).ToUpper(), strLength);
  361. }
  362. else if (displayType == "Dec")
  363. {
  364. value = ((int)result.value).ToString();
  365. oldv = ((int)result.oldValue).ToString();
  366. diff = ((int)(result.value - result.oldValue)).ToString();
  367. }
  368. else
  369. {
  370. float floatVal = GlobalFunctions.UIntToSingle(result.value);
  371. float floatOldVal = GlobalFunctions.UIntToSingle(result.oldValue);
  372. value = floatVal.ToString("g5");
  373. oldv = floatOldVal.ToString("g5");
  374. diff = (floatVal - floatOldVal).ToString("g5");
  375. }
  376. gView.Rows[i].Cells[0].Value = addr;
  377. if (InitialSearch)
  378. {
  379. gView.Rows[i].Cells[1].Value = "";
  380. gView.Rows[i].Cells[3].Value = "";
  381. }
  382. else if (resultAddressList[i] < oldDump.StartAddress || resultAddressList[i] > oldDump.EndAddress - searchBytes)
  383. {
  384. gView.Rows[i].Cells[1].Value = "N/A";
  385. gView.Rows[i].Cells[3].Value = "N/A";
  386. }
  387. else
  388. {
  389. gView.Rows[i].Cells[1].Value = oldv;
  390. gView.Rows[i].Cells[3].Value = diff;
  391. }
  392. gView.Rows[i].Cells[2].Value = value;
  393. i++;
  394. }
  395. }
  396. private void nextPage(object sender, EventArgs e)
  397. {
  398. //cPage++;
  399. //PrintPage();
  400. // Add 2, 1 because we're going to the next page,
  401. // and another because the upDown is 1-based instead of 0-based like cPage
  402. pageUpDown.Value = Convert.ToDecimal(cPage + 2);
  403. }
  404. private void previousPage(object sender, EventArgs e)
  405. {
  406. //cPage--;
  407. //PrintPage();
  408. // Since cPage is 0-based, we don't need to subtract 1
  409. pageUpDown.Value = Convert.ToDecimal(cPage);
  410. }
  411. private String fixString(String input, int length)
  412. {
  413. String parse = input;
  414. if (parse.Length > length)
  415. parse =
  416. parse.Substring(parse.Length - length, length);
  417. while (parse.Length < length)
  418. parse = "0" + parse;
  419. return parse;
  420. }
  421. public UInt32 GetAddress(int index)
  422. {
  423. return resultAddressList[cPage * pageSize + index];
  424. }
  425. public StringResult GetResult(int index)
  426. {
  427. UInt32 resultAddress = GetAddress(index);
  428. int strLength;
  429. switch (sSize)
  430. {
  431. case (SearchSize.Bit8): strLength = 2; break;
  432. case (SearchSize.Bit16): strLength = 4; break;
  433. default: strLength = 8; break;
  434. }
  435. StringResult result;
  436. result.SAddress = fixString(Convert.ToString(resultAddress, 16).ToUpper(), 8);
  437. result.SValue = fixString(Convert.ToString(newDump.ReadAddress32(resultAddress), 16).ToUpper(), strLength);
  438. if (oldDump != null)
  439. {
  440. result.SOldValue = fixString(Convert.ToString(oldDump.ReadAddress32(resultAddress), 16).ToUpper(), strLength);
  441. }
  442. else
  443. {
  444. result.SOldValue = "";
  445. }
  446. return result;
  447. }
  448. public UInt32 GetNewValueFromAddress(UInt32 resultAddress)
  449. {
  450. return newDump.ReadAddress(resultAddress, 4);
  451. }
  452. public static UInt32 ReadStream(Stream input, int blength)
  453. {
  454. Byte[] buffer = new Byte[blength];
  455. UInt32 result;
  456. input.Read(buffer, 0, blength);
  457. switch(blength)
  458. {
  459. case 1: result = (UInt32)buffer[0]; break;
  460. case 2: result = (UInt32)ByteSwap.Swap((UInt16)BitConverter.ToUInt16(buffer, 0)); break;
  461. default: result = (UInt32)ByteSwap.Swap(BitConverter.ToUInt32(buffer, 0)); break;
  462. }
  463. return result;
  464. }
  465. private void PerformBlockSearch(Dump blockDump, List<DumpRange> dumpranges)
  466. {
  467. PBlockDump = true;
  468. PTotalBlockSize = 0;
  469. PBlocksDumpedSize = 0;
  470. for (int i = 0; i < dumpranges.Count; i++)
  471. PTotalBlockSize += dumpranges[i].rangeLength;
  472. PBlockCount = dumpranges.Count;
  473. // This is only here to satisfy the for loop condition, dump sets this to false too
  474. gecko.CancelDump = false;
  475. //Stream backupStream = blockDump.getOutputStream();
  476. //Stream[] streams = { stream, backupStream };
  477. //Stream[] streams = { stream };
  478. //stream.Seek(0, SeekOrigin.Begin);
  479. for (int i = 0; i < dumpranges.Count && !gecko.CancelDump; i++)
  480. {
  481. PBlockID = i + 1;
  482. PBlockStart = dumpranges[i].startAddress;
  483. PBlockEnd = dumpranges[i].endAddress;
  484. // Seek in the seek-able stream...
  485. //stream.Seek(dumpranges[i].streamOffset, SeekOrigin.Begin);
  486. //int fillCount = (int)(dumpranges[i].streamOffset - backupStream.Position);
  487. //byte[] zeroes = new byte[fillCount];
  488. // ZipOutputStream can't seek, so fill with zeroes
  489. //backupStream.Write(zeroes, 0, fillCount);
  490. //gecko.Dump(dumpranges[i].startAddress, dumpranges[i].endAddress, streams);
  491. SafeDump(dumpranges[i].startAddress, dumpranges[i].endAddress, blockDump);
  492. PBlocksDumpedSize += dumpranges[i].rangeLength;
  493. }
  494. //backupStream.Dispose();
  495. PBlockDump = false;
  496. }
  497. private List<DumpRange> FindDumpRanges(UInt32 startAddress, Byte valueLength, int lowIndex, int highIndex)
  498. {
  499. const UInt32 blockSize = 0x3E000;
  500. List<DumpRange> dumpranges = new List<DumpRange>();
  501. UInt32 lastAddress;
  502. if (resultAddressList.Count > 0)
  503. {
  504. lastAddress = resultAddressList[lowIndex];
  505. }
  506. else
  507. {
  508. lastAddress = startAddress;
  509. }
  510. DumpRange addRange = new DumpRange(lastAddress);
  511. addRange.streamOffset = lastAddress - startAddress;
  512. // Check from lowIndex to highIndex in resultAddressList for dump ranges
  513. for (int i = lowIndex + 1; i <= highIndex; i++)
  514. {
  515. if (resultAddressList[i] >= lastAddress + blockSize)
  516. {
  517. addRange.endAddress = lastAddress + valueLength;
  518. addRange.rangeLength =
  519. addRange.endAddress - addRange.startAddress;
  520. dumpranges.Add(addRange);
  521. lastAddress = resultAddressList[i];
  522. addRange = new DumpRange(lastAddress);
  523. addRange.streamOffset = lastAddress - startAddress;
  524. }
  525. lastAddress = resultAddressList[i];
  526. }
  527. addRange.endAddress = lastAddress + valueLength;
  528. addRange.rangeLength =
  529. addRange.endAddress - addRange.startAddress;
  530. dumpranges.Add(addRange);
  531. return dumpranges;
  532. }
  533. private bool Compare(UInt32 given, UInt32 loExpected, UInt32 hiExpected, bool useHigh,
  534. ComparisonType cType, UInt32 diffBy, bool floatCompare)
  535. {
  536. if (floatCompare)
  537. {
  538. Single givenSingle = GlobalFunctions.UIntToSingle(given),
  539. loExpectedSingle = GlobalFunctions.UIntToSingle(loExpected),
  540. diffBySingle = GlobalFunctions.UIntToSingle(diffBy);
  541. // Bail if any of the inputs are Not a Number
  542. if (Single.IsNaN(givenSingle) || Single.IsNaN(loExpectedSingle) || Single.IsNaN(diffBySingle))
  543. {
  544. return false;
  545. }
  546. switch (cType)
  547. {
  548. case ComparisonType.Equal: return (givenSingle == loExpectedSingle);
  549. case ComparisonType.NotEqual: return (givenSingle != loExpectedSingle);
  550. case ComparisonType.Greater: return (givenSingle > loExpectedSingle);
  551. case ComparisonType.GreaterEqual: return (givenSingle >= loExpectedSingle);
  552. case ComparisonType.Lower: return (givenSingle < loExpectedSingle);
  553. case ComparisonType.LowerEqual: return (givenSingle <= loExpectedSingle);
  554. case ComparisonType.DifferentBy: return (loExpectedSingle - diffBySingle == givenSingle || loExpectedSingle + diffBySingle == givenSingle);
  555. case ComparisonType.DifferentByLess: return (loExpectedSingle - diffBySingle < givenSingle && givenSingle < loExpectedSingle + diffBySingle);
  556. case ComparisonType.DifferentByMore: return (givenSingle < loExpectedSingle - diffBySingle || givenSingle > loExpectedSingle + diffBySingle);
  557. default: return (givenSingle == loExpectedSingle);
  558. }
  559. }
  560. else if (useHigh)
  561. {
  562. switch (cType)
  563. {
  564. case ComparisonType.Equal: return (given >= loExpected && given <= hiExpected);
  565. case ComparisonType.NotEqual: return (given < loExpected || given > hiExpected);
  566. case ComparisonType.Greater: return (given > hiExpected);
  567. case ComparisonType.GreaterEqual: return (given >= hiExpected);
  568. case ComparisonType.Lower: return (given < loExpected);
  569. case ComparisonType.LowerEqual: return (given <= loExpected);
  570. default: return (given >= loExpected && given <= hiExpected);
  571. }
  572. }
  573. else
  574. {
  575. switch (cType)
  576. {
  577. case ComparisonType.Equal: return (given == loExpected);
  578. case ComparisonType.NotEqual: return (given != loExpected);
  579. case ComparisonType.Greater: return (given > loExpected);
  580. case ComparisonType.GreaterEqual: return (given >= loExpected);
  581. case ComparisonType.Lower: return (given < loExpected);
  582. case ComparisonType.LowerEqual: return (given <= loExpected);
  583. case ComparisonType.DifferentBy: return (loExpected - diffBy == given || loExpected + diffBy == given);
  584. // Are these right? How are they supposed to work?
  585. // Would ByLess with given 6 and expected 8 with diffBy 3 be true...
  586. // 8 - 3 = 5 < 6 OR 8 + 3 = 11 > 6 (shouldn't this be and?)
  587. // ByMore, using DiffBy 1 should be true...
  588. // 8 - 1 = 7 > 6 AND 8 + 1 = 9 < 6 (shouldn't this be or?)
  589. // I'm changing these because I'm pretty sure I'm right...
  590. case ComparisonType.DifferentByLess: return (loExpected - diffBy < given && given < loExpected + diffBy);
  591. case ComparisonType.DifferentByMore: return (given < loExpected - diffBy || given > loExpected + diffBy);
  592. default: return (given == loExpected);
  593. }
  594. }
  595. }
  596. //private bool CompareRefactored(UInt32 given, UInt32 loExpected, List<SearchComparisonInfo> comparisons, bool floatCompare, SearchType sType)
  597. private bool CompareRefactored(UInt32 newDumpVal, UInt32 oldDumpVal, UInt32 UndoDumpVal, List<SearchComparisonInfo> comparisons, bool floatCompare)
  598. {
  599. bool success = true;
  600. int others = 0; // 0 = did not run, -1 = ran and failed, 1 = ran and succeeded
  601. int GT = 0;
  602. int LT = 0;
  603. bool reverseGTLT = false;
  604. UInt32 GTValue = 0, LTValue = 0;
  605. foreach (SearchComparisonInfo comp in comparisons)
  606. {
  607. UInt32 LHS = newDumpVal;
  608. UInt32 RHS = comp.value;
  609. SearchType sType = comp.searchType;
  610. if (sType == SearchType.Unknown)
  611. {
  612. RHS = oldDumpVal;
  613. }
  614. else if (sType == SearchType.Old)
  615. {
  616. RHS = UndoDumpVal;
  617. }
  618. else if (sType == SearchType.Diff)
  619. {
  620. LHS = newDumpVal - oldDumpVal;
  621. }
  622. success = CompareRefactored(LHS, RHS, comp.comparisonType, comp.value, floatCompare);
  623. if (comp.comparisonType == ComparisonType.Equal)
  624. {
  625. // If any individual equals comparisons succeed, win immediately
  626. if (success) return true;
  627. }
  628. else if (comp.comparisonType == ComparisonType.GreaterEqual || comp.comparisonType == ComparisonType.Greater)
  629. {
  630. // Store this in case we need to do a reverseGTLT
  631. GTValue = comp.value;
  632. // Indicate both that we tested (by being non-zero) and success (positive/negative)
  633. if (success) GT = 1;
  634. else GT = -1;
  635. // If some LT test before us ran, and we're reversed, take note
  636. if (LT != 0 && GTValue > LTValue)
  637. {
  638. reverseGTLT = true;
  639. }
  640. }
  641. else if (comp.comparisonType == ComparisonType.Lower || comp.comparisonType == ComparisonType.LowerEqual)
  642. {
  643. LTValue = comp.value;
  644. if (success) LT = 1;
  645. else LT = -1;
  646. if (GT != 0 && GTValue > LTValue)
  647. {
  648. reverseGTLT = true;
  649. }
  650. }
  651. else
  652. {
  653. // all other comparisons must all be true
  654. // therefore, any failed fails them all
  655. // as long as we didn't fail yet, and we are succeeding, note that we ran and were successful
  656. // however, if we ever fail once, then it will fail forever
  657. if (others != -1 && success) others = 1;
  658. else others = -1;
  659. }
  660. }
  661. // if we got here, none of the equals have succeeded
  662. // if any of the others are ever false, fail
  663. if (others < 0) return false;
  664. // if at least one LT or GT are true, we have some more checks to do...
  665. if (LT > 0 || GT > 0)
  666. {
  667. // if it was a reversed GTLT, then only one must be true
  668. // if it wasn't reversed, then both must not fail
  669. if (reverseGTLT)
  670. {
  671. return true;
  672. }
  673. else
  674. {
  675. return LT > -1 && GT > -1;
  676. }
  677. }
  678. // if we got this far, then there were no GT/LT checks, or neither passed
  679. // any failed GT/LT checks fail the compare, but untested checks can continue
  680. if (LT < 0 || GT < 0) return false;
  681. // Now there are no GT/LT checks, pass or fail
  682. // if there was any successful others tests, succeed, otherwise no tests ever succeeded
  683. return (others > 0);
  684. }
  685. private bool CompareRefactored(UInt32 given, UInt32 loExpected, ComparisonType cType, UInt32 diffBy, bool floatCompare)
  686. {
  687. if (floatCompare)
  688. {
  689. Single givenSingle = GlobalFunctions.UIntToSingle(given),
  690. loExpectedSingle = GlobalFunctions.UIntToSingle(loExpected),
  691. diffBySingle = GlobalFunctions.UIntToSingle(diffBy);
  692. // Fail if any of the inputs are Not a Number
  693. if (Single.IsNaN(givenSingle) || Single.IsNaN(loExpectedSingle) || Single.IsNaN(diffBySingle))
  694. {
  695. return false;
  696. }
  697. switch (cType)
  698. {
  699. case ComparisonType.Equal: return (givenSingle == loExpectedSingle);
  700. case ComparisonType.NotEqual: return (givenSingle != loExpectedSingle);
  701. case ComparisonType.Greater: return (givenSingle > loExpectedSingle);
  702. case ComparisonType.GreaterEqual: return (givenSingle >= loExpectedSingle);
  703. case ComparisonType.Lower: return (givenSingle < loExpectedSingle);
  704. case ComparisonType.LowerEqual: return (givenSingle <= loExpectedSingle);
  705. case ComparisonType.DifferentBy: return (loExpectedSingle - diffBySingle == givenSingle || loExpectedSingle + diffBySingle == givenSingle);
  706. case ComparisonType.DifferentByLess: return (loExpectedSingle - diffBySingle < givenSingle && givenSingle < loExpectedSingle + diffBySingle);
  707. case ComparisonType.DifferentByMore: return (givenSingle < loExpectedSingle - diffBySingle || givenSingle > loExpectedSingle + diffBySingle);
  708. default: return (givenSingle == loExpectedSingle);
  709. }
  710. }
  711. else
  712. {
  713. switch (cType)
  714. {
  715. case ComparisonType.Equal: return (given == loExpected);
  716. case ComparisonType.NotEqual: return (given != loExpected);
  717. case ComparisonType.Greater: return (given > loExpected);
  718. case ComparisonType.GreaterEqual: return (given >= loExpected);
  719. case ComparisonType.Lower: return (given < loExpected);
  720. case ComparisonType.LowerEqual: return (given <= loExpected);
  721. case ComparisonType.DifferentBy: return (loExpected - diffBy == given || loExpected + diffBy == given);
  722. // Are these right? How are they supposed to work?
  723. // Would ByLess with given 6 and expected 8 with diffBy 3 be true...
  724. // 8 - 3 = 5 < 6 OR 8 + 3 = 11 > 6 (shouldn't this be and?)
  725. // ByMore, using DiffBy 1 should be true...
  726. // 8 - 1 = 7 > 6 AND 8 + 1 = 9 < 6 (shouldn't this be or?)
  727. // I'm changing these because I'm pretty sure I'm right...
  728. case ComparisonType.DifferentByLess: return (loExpected - diffBy < given && given < loExpected + diffBy);
  729. case ComparisonType.DifferentByMore: return (given < loExpected - diffBy || given > loExpected + diffBy);
  730. default: return (given == loExpected);
  731. }
  732. }
  733. }
  734. private void FindPairs(UInt32 sAddress, UInt32 eAddress, Byte valSize, out UInt32 firstAddress, out UInt32 lastAddress, out int firstAddressIndex, out int lastAddressIndex)
  735. {
  736. // TODO what is this function doing?
  737. firstAddress = sAddress;
  738. lastAddress = eAddress;
  739. firstAddressIndex = 0;
  740. lastAddressIndex = resultAddressList.Count - 1;
  741. for (int i = 0; i < resultAddressList.Count; i++)
  742. {
  743. if (sAddress <= resultAddressList[i])
  744. {
  745. firstAddress = resultAddressList[i];
  746. firstAddressIndex = i;
  747. break;
  748. }
  749. }
  750. for (int i = resultAddressList.Count - 1; i >= 0; i--)
  751. {
  752. if (eAddress >= resultAddressList[i] + valSize)
  753. {
  754. lastAddress = resultAddressList[i] + valSize;
  755. lastAddressIndex = i;
  756. break;
  757. }
  758. }
  759. }
  760. public void Reset()
  761. {
  762. NewSearch = true;
  763. InitialSearch = false;
  764. nxButton.Enabled = false;
  765. prvButton.Enabled = false;
  766. resLab.Text = "";
  767. //resList.Clear();
  768. resultAddressList.Clear();
  769. undoList.Clear();
  770. gView.Rows.Clear();
  771. if (newDump != null)
  772. {
  773. //newDump.dumpStream.Close();
  774. //newDump.dumpStream.Dispose();
  775. newDump = null;
  776. }
  777. if (oldDump != null)
  778. {
  779. //oldDump.dumpStream.Close();
  780. //oldDump.dumpStream.Dispose();
  781. oldDump = null;
  782. }
  783. if (undoDump != null)
  784. {
  785. //undoDump.dumpStream.Close();
  786. //undoDump.dumpStream.Dispose();
  787. undoDump = null;
  788. }
  789. dumpNum = 0;
  790. }
  791. public bool Search(UInt32 sAddress, UInt32 eAddress, UInt32 lValue, UInt32 hValue,
  792. bool useHValue, SearchType sType, SearchSize sSize, ComparisonType cType,
  793. UInt32 differentBy)
  794. {
  795. PBlockDump = false;
  796. resLab.Text = "Searching";
  797. Byte bufferlength = 0;
  798. switch (sSize)
  799. {
  800. case (SearchSize.Bit8): bufferlength = 1; break;
  801. case (SearchSize.Bit16): bufferlength = 2; break;
  802. default: bufferlength = 4; break;
  803. }
  804. bool floatCompare = sSize == SearchSize.Single;
  805. int oldSortedColumn = 0;
  806. SortOrder oldSortOrder = SortOrder.Ascending;
  807. SearchResultComparer comparer = new SearchResultComparer();
  808. // Search process requires list to be in order by address
  809. // We will restore the sort order afterward
  810. if (gView.SortedColumn != null)
  811. {
  812. oldSortedColumn = gView.SortedColumn.Index;
  813. oldSortOrder = gView.SortOrder;
  814. }
  815. if (oldSortedColumn != 0 || oldSortOrder != SortOrder.Ascending)
  816. {
  817. comparer.sortedColumn = 0;
  818. comparer.descending = false;
  819. resultAddressList.Sort(comparer);
  820. }
  821. // Do we need to do this? Clearing the grid view makes it suck...
  822. //gView.Rows.Clear();
  823. this.sSize = sSize;
  824. // Pause Gecko - while changing blocks during block search
  825. // the game will sometimes move forward a few frames
  826. //bool WasRunning = (gecko.status() == WiiStatus.Running);
  827. //bool WTF = WasRunning;
  828. //while (WTF)
  829. //{
  830. // gecko.Pause();
  831. // System.Threading.Thread.Sleep(100);
  832. // // Sometimes, the game doesn't actually pause...
  833. // // So loop repeatedly until it does!
  834. // WTF = (gecko.status() == WiiStatus.Running);
  835. //}
  836. //gecko.SafePause();
  837. bool doBlockSearch = false;
  838. bool doCompare = false;
  839. Dump searchDump;
  840. UInt32 dumpStart, dumpEnd, dumpOffset;
  841. dumpStart = sAddress;
  842. dumpEnd = eAddress;
  843. dumpOffset = 0;
  844. if (NewSearch || (UnknownStart && sType == SearchType.Exact))
  845. {
  846. // if an unknown search is followed by an exact search, it should be treated as an initial search
  847. InitialSearch = true;
  848. dumpNum = 0;
  849. // Dispose of any old dumps and lists
  850. if (newDump != null)
  851. {
  852. //newDump.dumpStream.Dispose();
  853. newDump = null;
  854. }
  855. resultAddressList.Clear();
  856. if (oldDump != null)
  857. {
  858. //oldDump.dumpStream.Dispose();
  859. oldDump = null;
  860. }
  861. // only do compares if it's an exact search
  862. if (sType == SearchType.Exact)
  863. {
  864. doCompare = true;
  865. }
  866. else
  867. {
  868. // Otherwise, it's an unknown search
  869. UnknownLAddress = sAddress;
  870. UnknownHAddress = eAddress;
  871. UnknownStart = true;
  872. NewSearch = false; // I don't think we need this...
  873. }
  874. }
  875. else
  876. {
  877. // This is a second search...
  878. InitialSearch = false;
  879. doCompare = true; // will always do a comparison
  880. if (UnknownStart)
  881. {
  882. // if it's the search after an unknown search, check every address
  883. // although double-check the start and end addresses, just in case they changed
  884. dumpStart = Math.Max(UnknownLAddress, sAddress);
  885. dumpEnd = Math.Min(UnknownHAddress, eAddress);
  886. dumpOffset = dumpStart - UnknownLAddress;
  887. }
  888. else
  889. {
  890. // otherwise, do a block search to avoid transferring useless data
  891. doBlockSearch = true;
  892. }
  893. }
  894. // Clear out any old dumps before caching the current dumps
  895. if (undoDump != null)
  896. {
  897. //undoDump.dumpStream.Dispose();
  898. }
  899. undoDump = oldDump;
  900. oldDump = newDump;
  901. if (undoList != resultAddressList)
  902. {
  903. undoList.Clear();
  904. }
  905. undoList = resultAddressList;
  906. // Dump the contents of memory for the search, by either using a full dump or a block-search-dump
  907. try
  908. {
  909. if (doBlockSearch)
  910. {
  911. UInt32 startAddress, endAddress;
  912. int startAddressIndex, endAddressIndex;
  913. FindPairs(sAddress, eAddress, bufferlength, out startAddress, out endAddress, out startAddressIndex, out endAddressIndex);
  914. List<DumpRange> dumpRanges = FindDumpRanges(startAddress, bufferlength, startAddressIndex, endAddressIndex);
  915. //orgStream = new MemoryStream((int)(fAddr - sAddr));
  916. newDump = new Dump(startAddress, endAddress, dumpNum);
  917. PerformBlockSearch(newDump, dumpRanges);
  918. //newDump.WriteStreamToDisk();
  919. }
  920. else
  921. {
  922. newDump = new Dump(dumpStart, dumpEnd, dumpNum);
  923. gecko.Dump(newDump);
  924. }
  925. }
  926. catch (EUSBGeckoException e)
  927. {
  928. exceptionHandling.HandleException(e);
  929. }
  930. if (doCompare)
  931. {
  932. // The "original stream" is always the one we just read from the USB Gecko
  933. //Stream originalStream, compareStream;
  934. //originalStream = newDump.dumpStream;
  935. //compareStream = newDump.dumpStream;
  936. //// dumpOffset is 0 if sType = exact
  937. //originalStream.Seek(dumpOffset, SeekOrigin.Begin);
  938. // if sType != exact, compare against the previous dump
  939. if (sType != SearchType.Exact && sType != SearchType.Diff)
  940. {
  941. //compareStream = oldDump.dumpStream;
  942. //compareStream.Seek(0, SeekOrigin.Begin);
  943. hValue = 0;
  944. useHValue = false;
  945. }
  946. UInt32 val, cmpVal;
  947. // assume that it's exact and change it if not
  948. cmpVal = lValue;
  949. if (resultAddressList.Count > 0)
  950. {
  951. // We have a working list so we will only check the values in that list
  952. // Create a temporary list to write to while we read from the old one
  953. List<UInt32> tempAddressList = new List<uint>();
  954. foreach (UInt32 compareAddress in resultAddressList)
  955. {
  956. val = newDump.ReadAddress(compareAddress, bufferlength);
  957. if (sType == SearchType.Unknown)
  958. {
  959. cmpVal = oldDump.ReadAddress(compareAddress, bufferlength);
  960. }
  961. else if (sType == SearchType.Old)
  962. {
  963. cmpVal = undoDump.ReadAddress(compareAddress, bufferlength);
  964. }
  965. else if (sType == SearchType.Diff)
  966. {
  967. val = val - oldDump.ReadAddress(compareAddress, bufferlength);
  968. }
  969. if (Compare(val, cmpVal, hValue, useHValue, cType, differentBy, floatCompare))
  970. {
  971. tempAddressList.Add(compareAddress);
  972. }
  973. }
  974. // Copy the temporary list over
  975. resultAddressList = tempAddressList;
  976. }
  977. else
  978. {
  979. for (UInt32 i = newDump.StartAddress; i < newDump.EndAddress; i += bufferlength)
  980. {
  981. //// There are no pre-existing addresses to compare to! compare all addresses
  982. //while (originalStream.Position + bufferlength < originalStream.Length)
  983. //{
  984. // val = ReadStream(originalStream, bufferlength);
  985. // This will either happen on the very first search if it is specific,
  986. // or the second search if the first search was unknown
  987. // In either case, there cannot be an Old or Diff passed in
  988. val = newDump.ReadAddress(i, bufferlength);
  989. if (sType != SearchType.Exact)
  990. {
  991. //cmpVal = ReadStream(compareStream, bufferlength);
  992. cmpVal = oldDump.ReadAddress(i, bufferlength);
  993. }
  994. if (Compare(val, cmpVal, hValue, useHValue, cType, differentBy, floatCompare))
  995. {
  996. resultAddressList.Add(i);
  997. }
  998. }
  999. }
  1000. }
  1001. //SearchHistoryItem item = new SearchHistoryItem();
  1002. //item.searchDump = newDump;
  1003. //item.resultsList = resultAddressList;
  1004. //DateTime startTime = Logger.WriteLineTimedStarted("serializing search items");
  1005. //searchHistory.SaveSearchBackground(dumpNum, resultAddressList, newDump);
  1006. ////item.WriteCompressedZipBackground("foo.zip");
  1007. //Logger.WriteLineTimedFinished("serializing search items", startTime);
  1008. //startTime = Logger.WriteLineTimedStarted("deserializing search items");
  1009. ////item.ReadCompressedZip("foo.zip");
  1010. //Dump testDump = searchHistory.LoadSearchDump(dumpNum);
  1011. //List<UInt32> testList = searchHistory.LoadSearchList(dumpNum);
  1012. //Logger.WriteLineTimedFinished("deserializing search items", startTime);
  1013. if (UnknownStart && !InitialSearch)
  1014. {
  1015. // clear UnknownStart if InitialSearch is false
  1016. UnknownStart = false;
  1017. }
  1018. dumpNum++;
  1019. //if (NewSearch || (UnknownStart && sType == SearchType.Exact))
  1020. //{
  1021. // bool abort = false;
  1022. // InitialSearch = true;
  1023. // //orgStream = new MemoryStream((int)(eAddress - sAddress));
  1024. // Dump myDump = new Dump(sAddress, eAddress);
  1025. // resList.Clear();
  1026. // resultAddressList.Clear();
  1027. // try
  1028. // {
  1029. // gecko.CancelDump = false;
  1030. // //gecko.Dump(sAddress, eAddress, orgStream);
  1031. // gecko.Dump(myDump);
  1032. // orgStream = myDump.dumpStream;
  1033. // FileStream foo = new FileStream(Environment.CurrentDirectory + @"\searchdumps\dump0.ful", FileMode.Create);
  1034. // orgStream.WriteTo(foo);
  1035. // foo.Close();
  1036. // foo.Dispose();
  1037. // oldDump = null;
  1038. // newDump = myDump;
  1039. // orgStream.Seek(0, SeekOrigin.Begin);
  1040. // if (!gecko.CancelDump)
  1041. // {
  1042. // if (sType == SearchType.Exact)
  1043. // {
  1044. // // orgStream.Seek(0, SeekOrigin.Begin);
  1045. // UInt32 val;
  1046. // while (orgStream.Position + bufferlength < orgStream.Length)
  1047. // {
  1048. // val = ReadStream(orgStream, bufferlength);
  1049. // if (Compare(val, lValue, hValue, useHValue, cType, differentBy, floatCompare))
  1050. // {
  1051. // //resList.Add(new SearchResult(sAddress + (UInt32)orgStream.Position - bufferlength, val, 0));
  1052. // resultAddressList.Add(sAddress + (UInt32)orgStream.Position - bufferlength);
  1053. // }
  1054. // }
  1055. // }
  1056. // else
  1057. // {
  1058. // UnknownLAddress = sAddress;
  1059. // UnknownHAddress = eAddress;
  1060. // UnknownStart = true;
  1061. // NewSearch = false;
  1062. // abort = true;
  1063. // }
  1064. // }
  1065. // orgStream = null;
  1066. // }
  1067. // catch (EUSBGeckoException e)
  1068. // {
  1069. // Reset();
  1070. // exceptionHandling.HandleException(e);
  1071. // abort = true;
  1072. // }
  1073. //}
  1074. //else
  1075. //{
  1076. // InitialSearch = false;
  1077. // try
  1078. // {
  1079. // // This branch is only executed once, the search after an unknown search
  1080. // if (UnknownStart)
  1081. // {
  1082. // UnknownStart = false;
  1083. // UInt32 sAddr = Math.Max(UnknownLAddress, sAddress);
  1084. // UInt32 fAddr = Math.Min(UnknownHAddress, eAddress);
  1085. // UInt32 offset = sAddr - UnknownLAddress;
  1086. // cmpStream = new MemoryStream((int)(fAddr - sAddr));
  1087. // try
  1088. // {
  1089. // gecko.CancelDump = false;
  1090. // gecko.Dump(sAddr, fAddr, cmpStream);
  1091. // if (!gecko.CancelDump)
  1092. // {
  1093. // orgStream.Seek(offset, SeekOrigin.Begin);
  1094. // cmpStream.Seek(0, SeekOrigin.Begin);
  1095. // UInt32 oldValue, newValue;
  1096. // while (cmpStream.Position + bufferlength < cmpStream.Length)
  1097. // {
  1098. // newValue = ReadStream(cmpStream, bufferlength);
  1099. // oldValue = ReadStream(orgStream, bufferlength);
  1100. // if (Compare(newValue, oldValue, 0, false, cType, differentBy, floatCompare))
  1101. // resList.Add(new SearchResult(sAddr + (UInt32)cmpStream.Position - bufferlength, newValue, oldValue));
  1102. // }
  1103. // }
  1104. // else
  1105. // {
  1106. // UnknownStart = true;
  1107. // NewSearch = false;
  1108. // return true;
  1109. // }
  1110. // }
  1111. // finally
  1112. // {
  1113. // cmpStream.Close();
  1114. // cmpStream = null;
  1115. // }
  1116. // }
  1117. // else
  1118. // {
  1119. // UInt32 sAddr, fAddr;
  1120. // UInt32 cmpV = lValue;
  1121. // bool useUpper = useHValue;
  1122. // bool lastV = false;
  1123. // List<SearchResult> tempList = new List<SearchResult>();
  1124. // if (sType == SearchType.Unknown)
  1125. // {
  1126. // useUpper = false;
  1127. // lastV = true;
  1128. // }
  1129. // int lV, hV;
  1130. // FindPairs(sAddress, eAddress, bufferlength, out sAddr, out fAddr, out lV, out hV);
  1131. // orgStream = new MemoryStream((int)(fAddr - sAddr));
  1132. // //Insert block based search here
  1133. // PerformBlockSearch(sAddr, fAddr, bufferlength, lV, hV, orgStream);
  1134. // //gecko.Dump(sAddr, fAddr, orgStream);
  1135. // //end
  1136. // UInt32 val;
  1137. // // Compare the two dumps
  1138. // for (int i = lV; i <= hV && !gecko.CancelDump; i++)
  1139. // {
  1140. // if (lastV)
  1141. // cmpV = resList[i].value;
  1142. // orgStream.Seek(resList[i].address - sAddr, SeekOrigin.Begin);
  1143. // val = ReadStream(orgStream, bufferlength);
  1144. // if (Compare(val, cmpV, hValue, useUpper, cType, differentBy, floatCompare))
  1145. // tempList.Add(
  1146. // new SearchResult(sAddr + (UInt32)orgStream.Position - bufferlength, val, resList[i].value));
  1147. // }
  1148. // // If this was canceled, don't update the results list
  1149. // if (!gecko.CancelDump)
  1150. // {
  1151. // resList.Clear();
  1152. // resList = null;
  1153. // resList = tempList;
  1154. // }
  1155. // }
  1156. // }
  1157. // catch (EUSBGeckoException e)
  1158. // {
  1159. // Reset();
  1160. // exceptionHandling.HandleException(e);
  1161. // return false;
  1162. // }
  1163. //}
  1164. //// If we were running, go back to running
  1165. //// If we *weren't* running, *don't* go back to running
  1166. //if (WasRunning)
  1167. //{
  1168. // gecko.SafeResume();
  1169. //}
  1170. //if (orgStream != null)
  1171. //{
  1172. // orgStream.Close();
  1173. //}
  1174. //orgStream = null;
  1175. //if (resList.Count == 0 && resultAddressList.Count == 0)
  1176. if (resultAddressList.Count == 0 && !UnknownStart)
  1177. {
  1178. NewSearch = true;
  1179. nxButton.Enabled = false;
  1180. prvButton.Enabled = false;
  1181. resLab.Text = "No results found";
  1182. Reset();
  1183. return false;
  1184. }
  1185. NewSearch = false;
  1186. //int PageCount = resList.Count / 256;
  1187. //if (resList.Count % 256 != 0) PageCount++;
  1188. //cPage = 0;
  1189. //cPages = PageCount;
  1190. //PrintPage();
  1191. UpdateGridViewPage(true);
  1192. return true;
  1193. }
  1194. public bool SearchRefactored(UInt32 sAddress, UInt32 eAddress, List<SearchComparisonInfo> comparisons, SearchSize searchSize)
  1195. {
  1196. PBlockDump = false;
  1197. resLab.Text = "Searching";
  1198. Byte bufferlength = 0;
  1199. switch (searchSize)
  1200. {
  1201. case (SearchSize.Bit8): bufferlength = 1; break;
  1202. case (SearchSize.Bit16): bufferlength = 2; break;
  1203. default: bufferlength = 4; break;
  1204. }
  1205. this.sSize = searchSize;
  1206. bool floatCompare = searchSize == SearchSize.Single;
  1207. int oldSortedColumn = 0;
  1208. SortOrder oldSortOrder = SortOrder.Ascending;
  1209. SearchResultComparer comparer = new SearchResultComparer();
  1210. // Search process requires list to be in order by address
  1211. // We will restore the sort order afterward
  1212. if (gView.SortedColumn != null)
  1213. {
  1214. oldSortedColumn = gView.SortedColumn.Index;
  1215. oldSortOrder = gView.SortOrder;
  1216. }
  1217. if (oldSortedColumn != 0 || oldSortOrder != SortOrder.Ascending)
  1218. {
  1219. comparer.sortedColumn = 0;
  1220. comparer.descending = false;
  1221. resultAddressList.Sort(comparer);
  1222. }
  1223. SearchType sType = comparisons[0].searchType;
  1224. bool doBlockSearch = false;
  1225. bool doCompare = false;
  1226. Dump searchDump;
  1227. UInt32 dumpStart, dumpEnd, dumpOffset;
  1228. dumpStart = sAddress;
  1229. dumpEnd = eAddress;
  1230. dumpOffset = 0;
  1231. if (NewSearch || (UnknownStart && sType == SearchType.Exact))
  1232. {
  1233. // if an unknown search is followed by an exact search, it should be treated as an initial search
  1234. InitialSearch = true;
  1235. dumpNum = 0;
  1236. // Dispose of any old dumps and lists
  1237. if (newDump != null)
  1238. {
  1239. //newDump.dumpStream.Dispose();
  1240. newDump = null;
  1241. }
  1242. resultAddressList.Clear();
  1243. if (oldDump != null)
  1244. {
  1245. //oldDump.dumpStream.Dispose();
  1246. oldDump = null;
  1247. }
  1248. // only do compares if it's an exact search
  1249. if (sType == SearchType.Exact)
  1250. {
  1251. doCompare = true;
  1252. }
  1253. else
  1254. {
  1255. // Otherwise, it's an unknown search
  1256. UnknownLAddress = sAddress;
  1257. UnknownHAddress = eAddress;
  1258. UnknownStart = true;
  1259. NewSearch = false; // I don't think we need this...
  1260. }
  1261. }
  1262. else
  1263. {
  1264. // This is a second search...
  1265. InitialSearch = false;
  1266. doCompare = true; // will always do a comparison
  1267. if (UnknownStart)
  1268. {
  1269. // if it's the search after an unknown search, check every address
  1270. // although double-check the start and end addresses, just in case they changed
  1271. dumpStart = Math.Max(UnknownLAddress, sAddress);
  1272. dumpEnd = Math.Min(UnknownHAddress, eAddress);
  1273. dumpOffset = dumpStart - UnknownLAddress;
  1274. }
  1275. else
  1276. {
  1277. // otherwise, do a block search to avoid transferring useless data
  1278. doBlockSearch = true;
  1279. }
  1280. }
  1281. // Clear out any old dumps before caching the current dumps
  1282. undoDump = oldDump;
  1283. oldDump = newDump;
  1284. undoList = resultAddressList;
  1285. // Dump the contents of memory for the search, by either using a full dump or a block-search-dump
  1286. if (doBlockSearch)
  1287. {
  1288. UInt32 startAddress, endAddress;
  1289. int startAddressIndex, endAddressIndex;
  1290. FindPairs(dumpStart, dumpEnd, bufferlength, out startAddress, out endAddress, out startAddressIndex, out endAddressIndex);
  1291. List<DumpRange> dumpRanges = FindDumpRanges(startAddress, bufferlength, startAddressIndex, endAddressIndex);
  1292. newDump = new Dump(startAddress, endAddress, dumpNum);
  1293. PerformBlockSearch(newDump, dumpRanges);
  1294. }
  1295. else
  1296. {
  1297. newDump = new Dump(dumpStart, dumpEnd, dumpNum);
  1298. SafeDump(dumpStart, dumpEnd, newDump);
  1299. }
  1300. if (doCompare)
  1301. {
  1302. UInt32 val, cmpVal;
  1303. // assume that it's exact and change it if not
  1304. cmpVal = comparisons[0].value;
  1305. if (resultAddressList.Count > 0)
  1306. {
  1307. // We have a working list so we will only check the values in that list
  1308. // Create a temporary list to write to while we read from the old one
  1309. List<UInt32> tempAddressList = new List<uint>();
  1310. foreach (UInt32 compareAddress in resultAddressList)
  1311. {
  1312. UInt32 newDumpVal = newDump.ReadAddress(compareAddress, bufferlength);
  1313. UInt32 oldDumpVal = oldDump.ReadAddress(compareAddress, bufferlength);
  1314. UInt32 UndoDumpVal;
  1315. if (undoDump != null)
  1316. {
  1317. UndoDumpVal = undoDump.ReadAddress(compareAddress, bufferlength);
  1318. }
  1319. else
  1320. {
  1321. UndoDumpVal = oldDumpVal;
  1322. }
  1323. if (CompareRefactored(newDumpVal, oldDumpVal, UndoDumpVal, comparisons, floatCompare))
  1324. {
  1325. tempAddressList.Add(compareAddress);
  1326. }
  1327. }
  1328. // Copy the temporary list over
  1329. resultAddressList = tempAddressList;
  1330. }
  1331. else
  1332. {
  1333. for (UInt32 i = newDump.StartAddress; i < newDump.EndAddress; i += bufferlength)
  1334. {
  1335. // There are no pre-existing addresses to compare to! compare all addresses
  1336. // This will either happen on the very first search if it is specific,
  1337. // or the second search if the first search was unknown
  1338. // In either case, there cannot be an Old or Diff passed in
  1339. UInt32 newDumpVal = newDump.ReadAddress(i, bufferlength);
  1340. UInt32 oldDumpVal = newDumpVal;
  1341. UInt32 UndoDumpVal = newDumpVal;
  1342. if (sType != SearchType.Exact)
  1343. {
  1344. oldDumpVal = oldDump.ReadAddress(i, bufferlength);
  1345. UndoDumpVal = oldDumpVal;
  1346. }
  1347. //if (Compare(val, cmpVal, hValue, useHValue, cType, differentBy, floatCompare))
  1348. if (CompareRefactored(newDumpVal, oldDumpVal, UndoDumpVal, comparisons, floatCompare))
  1349. {
  1350. resultAddressList.Add(i);
  1351. }
  1352. }
  1353. }
  1354. }
  1355. if (UnknownStart && !InitialSearch)
  1356. {
  1357. // clear UnknownStart if InitialSearch is false
  1358. UnknownStart = false;
  1359. }
  1360. dumpNum++;
  1361. if (resultAddressList.Count == 0 && !UnknownStart)
  1362. {
  1363. DialogResult result = MessageBox.Show(null, "No search results!\n\nTo undo, press Yes\nTo restart, press No", "No search results!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
  1364. bool UndoSuccess = false;
  1365. if (result == DialogResult.Yes)
  1366. {
  1367. UndoSuccess = UndoSearch();
  1368. if (!UndoSuccess)
  1369. {
  1370. MessageBox.Show("Could not undo! Restarting search");
  1371. }
  1372. }
  1373. if (!UndoSuccess)
  1374. {
  1375. NewSearch = true;
  1376. nxButton.Enabled = false;
  1377. prvButton.Enabled = false;
  1378. resLab.Text = "No results found";
  1379. Reset();
  1380. return false;
  1381. }
  1382. }
  1383. NewSearch = false;
  1384. UpdateGridViewPage(true);
  1385. return true;
  1386. }
  1387. public void SafeDump(UInt32 startdump, UInt32 enddump, Dump memdump)
  1388. {
  1389. bool finished = false;
  1390. while (!finished)
  1391. {
  1392. try
  1393. {
  1394. gecko.Dump(startdump, enddump, memdump);
  1395. finished = true;
  1396. }
  1397. catch (EUSBGeckoException e)
  1398. {
  1399. exceptionHandling.HandleException(e);
  1400. if (startdump == memdump.ReadCompletedAddress)
  1401. {
  1402. // failed to get any more data; something is probably really wrong so let's just quit
  1403. finished = true;
  1404. }
  1405. else
  1406. {
  1407. startdump = memdump.ReadCompletedAddress;
  1408. }
  1409. }
  1410. }
  1411. }
  1412. public bool UndoSearch()
  1413. {
  1414. if (newDump == null || oldDump == null || undoDump == null)
  1415. {
  1416. return false;
  1417. }
  1418. //newDump.dumpStream.Dispose();
  1419. newDump = oldDump;
  1420. oldDump = undoDump;
  1421. undoDump = null;
  1422. resultAddressList.Clear();
  1423. resultAddressList = new List<uint>(undoList);
  1424. UpdateGridViewPage(true);
  1425. return true;
  1426. }
  1427. public bool SaveSearch(string path)
  1428. {
  1429. return SaveSearch(path, true);
  1430. }
  1431. public bool SaveSearch(string path, bool compressed)
  1432. {
  1433. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializeResults = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  1434. if (!compressed)
  1435. {
  1436. FileStream resultFile = new FileStream(path, FileMode.Create);
  1437. serializeResults.Serialize(resultFile, sSize);
  1438. //serializeResults.Serialize(resultFile, resList);
  1439. // TODO SAVING SEARCHES TO FILE
  1440. resultFile.Close();
  1441. return true;
  1442. }
  1443. ZipOutputStream resultStream = new ZipOutputStream(path);
  1444. resultStream.CompressionLevel = Ionic.Zlib.CompressionLevel.BestSpeed;
  1445. resultStream.PutNextEntry("ResList");
  1446. // good first guess
  1447. //MemoryStream resultStream = new MemoryStream(12 * resList.Count);