/[RomCheater]/trunk/RomCheater/Docking/UI/UIMemoryViewer.cs
ViewVC logotype

Contents of /trunk/RomCheater/Docking/UI/UIMemoryViewer.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 323 - (show annotations) (download)
Thu Jun 7 16:33:41 2012 UTC (8 years, 5 months ago) by william
File size: 25023 byte(s)
+ add event for being able to subscribe to PEReader updates

1 //#define DISABLE_GETFIRSTNONZEROBYTE_ONUPDATE_ACCEPTEDPROCESS // when defined will not call GetFirstNonZeroByte() when AcceptedProcess is updated and is not null
2 //#define DISABLE_GETFIRSTNONZERO_BYTE // when defined will make GetFirstNonZeroByte() an empty void method
3 using System;
4 using System.Collections.Generic;
5 using System.ComponentModel;
6 using System.Drawing;
7 using System.Data;
8 using System.Linq;
9 using System.Text;
10 using System.Windows.Forms;
11 using Be.Windows.Forms;
12 using RomCheater.Logging;
13 using RomCheater.PluginFramework.Interfaces;
14 using System.Diagnostics;
15 using Sojaner.MemoryScanner.MemoryProviers;
16 using System.Runtime.InteropServices;
17 using RomCheater.PluginFramework.Events;
18 using Sojaner.MemoryScanner;
19
20 namespace RomCheater.Docking.UI
21 {
22 public partial class UIMemoryViewer : UserControl,
23 IAcceptsPlugin<IConfigPlugin>,
24 IAcceptsProcess<Process>,
25 IAcceptsProcessAndConfig,
26 IAcceptsMemoryRange,
27 IBrowseMemoryRegion,
28 IAcceptPEData
29 {
30 public UIMemoryViewer()
31 {
32 InitializeComponent();
33 SetStyle(ControlStyles.UserPaint, true);
34 SetStyle(ControlStyles.DoubleBuffer, true);
35 SetStyle(ControlStyles.AllPaintingInWmPaint, true);
36 SetStyle(ControlStyles.ResizeRedraw, true);
37 //this.OnPCSX2ProcessCallback = new UIEvents.PCSX2ProcessCallback(this.PCSX2ProcessCallback);
38 //if (this.OnPCSX2ProcessCallback != null) { this.OnPCSX2ProcessCallback.Invoke(out procdata); }
39 this.UpdateEnabled = false;
40 txtData.BytesPerLine = (int)max_address_width;
41 txtData.UseFixedBytesPerLine = true;
42 txtData.StringViewVisible = true;
43 ramScroll.Minimum = (int)MemoryRangeStart;
44 for (int i = MemoryRangeStart; i < (MemoryRangeStart + max_ram_view); i += max_address_width) { ramScroll.Maximum += (int)max_address_width; }
45 ramScroll.Value = ramScroll.Minimum;
46 this.CanChangeUpdateInterval = false;
47
48
49 lblAddressMarker.Text = "";
50 for (uint i = 0; i < max_address_width; i++)
51 {
52 lblAddressMarker.Text = lblAddressMarker.Text + string.Format("{0:X2} ", i);
53 }
54 this.AcceptedPlugin = null; this.AcceptedProcess = null;
55
56 txtAddresses.MouseWheel += new MouseEventHandler(txtAddresses_MouseWheel);
57 txtData.MouseWheel += new MouseEventHandler(txtData_MouseWheel);
58 }
59
60 private void GetFirstNonZeroByte()
61 {
62 #if !DISABLE_GETFIRSTNONZERO_BYTE
63 if (!DesignMode)
64 {
65 GenericMemoryProvider provider = new GenericMemoryProvider((IAcceptsProcessAndConfig)this);
66 provider.OpenProvider();
67 int addr = 0;
68 provider.ReadFirstNonZeroByte(MemoryRangeStart, MemoryRangeSize, out addr);
69 provider.CloseProvider();
70 GotoAddress(addr);
71 }
72 #endif
73 }
74 #region IBrowseMemoryRegion
75 public bool BrowseMemoryRegion(int MemoryRegion)
76 {
77 try
78 {
79 if (!((MemoryRangeStart <= MemoryRegion) && (MemoryRegion <= (MemoryRangeStart + MemoryRangeSize)))) { return false; }
80 GotoAddress(MemoryRegion);
81 return true;
82 }
83 catch(Exception ex)
84 {
85 logger.Error.WriteLine("UIMemoryViewer.BrowseMemoryRegion(int MemoryRegion): Failed to Browse Memory Region: 0x{0:x8}", MemoryRegion);
86 logger.Error.WriteLine(ex.ToString());
87 return false;
88 }
89 }
90 #endregion
91 #region IAcceptsProcess<Process> Members
92 private Process _AcceptedProcess;
93 public Process AcceptedProcess
94 {
95 get { return _AcceptedProcess; }
96 set
97 {
98 _AcceptedProcess = value;
99 update_timer.Enabled = (value != null);
100 UpdateEnabled = update_timer.Enabled;
101 #if !DISABLE_GETFIRSTNONZEROBYTE_ONUPDATE_ACCEPTEDPROCESS
102 if (value != null)
103 GetFirstNonZeroByte();
104 #endif
105 }
106 }
107 #endregion
108 #region IAcceptsPlugin<IConfigPlugin> Members
109 public IConfigPlugin AcceptedPlugin { get; set; }
110 #endregion
111 #region IAcceptsMemoryRange members
112 public int MemoryRangeStart { get { return MemorySizeConstants.MinimumAddress; } set { } }
113 public uint MemoryRangeSize { get { if (MemoryRangeStart > 0) { return (uint)(MemorySizeConstants.MaximumAddress - MemoryRangeStart); } return MemorySizeConstants.MaximumAddress; } set { } }
114 #endregion
115 #region IAcceptPEData members
116 private PEReader.PEData peData { get; set; }
117 public void SetPEViewerData(PEReader.PEData peData) { this.peData = peData; }
118 #endregion
119 public void GotoTop() { this.CURRENT_TOP_ADDR = 0; }
120 public void GotoBottom() { uint size = (uint)MemoryRangeSize; this.CURRENT_TOP_ADDR = (int)((size - 1) - max_ram_view); }
121 public void GotoAddress(int addr) { this.CURRENT_TOP_ADDR = (int)(addr & 0xFFFFFFF0); }
122 private bool _UpdateEnabled;
123 public bool UpdateEnabled
124 {
125 get { return _UpdateEnabled; }
126 set
127 {
128 _UpdateEnabled = value;
129 if (value) { this.update_timer.Enabled = true; }
130 else { this.update_timer.Enabled = false; }
131 }
132 }
133 private bool _CanChangeUpdateInterval;
134 public bool CanChangeUpdateInterval
135 {
136 get { return _CanChangeUpdateInterval; }
137 set { _CanChangeUpdateInterval = value; }
138 }
139
140 public int UpdateInterval
141 {
142 get { return this.update_timer.Interval; }
143 set { if (CanChangeUpdateInterval) this.update_timer.Interval = value; }
144 }
145 private string AddressList = "";
146 private string AsciiData = "";
147 private byte[] RamData = new byte[] { };
148
149 const int max_address_width = 16;
150 static int max_ram_view = max_address_width * 27;
151
152 static int small_scroll_change = max_address_width * 1; // scrolls one line (when you clikc the up or down arrows)
153 static int medium_scroll_change = max_ram_view / 2; // scrolls half a page
154 static int large_scroll_change = max_ram_view; // scrolls a full page
155 private int _CURRENT_TOP_ADDR;
156 int CURRENT_TOP_ADDR
157 {
158 get { return _CURRENT_TOP_ADDR; }
159 set { txthexGoto.Value = _CURRENT_TOP_ADDR = value; }
160 }
161 //uint CURRENT_BOITTOM_ADDR() { return CURRENT_TOP_ADDR + max_ram_view; }
162 private void UpdateMaxRamView()
163 {
164 if (this.IsDisposed) return;
165 Graphics g = this.CreateGraphics();
166 Size size = g.MeasureString("00", txtData.Font).ToSize();
167 int ByteHeight = size.Height;
168 int TotalHeight = txtData.Height;
169 int NumberOfBytes = (int)((TotalHeight / ByteHeight) * max_address_width);
170 int byte_width = (max_address_width * 2);
171 max_ram_view = NumberOfBytes + (byte_width);
172 }
173 private void btnGotoAddress_Click(object sender, EventArgs e)
174 {
175 this.GotoAddress(txthexGoto.ToInt32());
176 }
177
178 private void btnEditBytes_Click(object sender, EventArgs e)
179 {
180 bool reenable = false;
181 if (this.UpdateEnabled) reenable = true;
182 this.UpdateEnabled = false;
183 ByteEditor editor = new ByteEditor((txtData.ByteProvider as DynamicByteProvider).Bytes.ToArray(), this.CURRENT_TOP_ADDR);
184 editor.ShowDialog();
185 if (editor.BytesEdited)
186 {
187 //DynamicByteProvider _DynamicByteProvider = new DynamicByteProvider(editor.AsBytes);
188 //txtData.ByteProvider = _DynamicByteProvider;
189 //_DynamicByteProvider.Changed += new EventHandler(HexResourceViewerBytes_Changed);
190 this.WriteCurrentBytes(this.CURRENT_TOP_ADDR, editor.AsBytes);
191 }
192 this.UpdateEnabled = reenable;
193 }
194 private bool ForceUpdate = false;
195 private bool ShouldUpdateResults()
196 {
197 //if (ResultsUpdateWorkerThread.IsBusy) { return false; }
198 if (ForceUpdate) return true;
199 //else if (TextIsBeingSelected) return false;
200 //else if (NonHandledKeysAreBeingPressed) return false;
201 else if (this.UpdateEnabled) return true;
202 else { return false; }
203 }
204 private void UpdateGui(bool force)
205 {
206 if (AcceptedProcess == null) { return; }
207 if (AcceptedPlugin == null) { return; }
208
209 if (!this.ShouldUpdateResults()) { return; }// this.Logger.LogDebugMessage(string.Format("ShouldUpdateResults() -> returning false")); return; }
210 this.UpdateMaxRamView();
211 //if (!force)
212 //{
213 if (!ResultsUpdateWorkerThread.IsBusy)
214 ResultsUpdateWorkerThread.RunWorkerAsync();
215 //}
216 //else
217 //{
218 // while (!ResultsUpdateWorkerThread.IsBusy) { ResultsUpdateWorkerThread.CancelAsync(); Application.DoEvents(); }
219 // ResultsUpdateWorkerThread.RunWorkerAsync();
220 //}
221 }
222 private void UpdateGui()
223 {
224 this.UpdateGui(false);
225 }
226 private byte[] GetMemory()
227 {
228 byte[] data = new byte[] { };
229 try
230 {
231 GenericMemoryProvider provider = new GenericMemoryProvider((IAcceptsProcessAndConfig)this);
232 provider.OpenProvider();
233 int bytesReadSize;
234 provider.ReadProcessMemory(CURRENT_TOP_ADDR, (uint)max_ram_view, out bytesReadSize, out data);
235 try
236 {
237 provider.CloseProvider();
238 }
239 catch (SEHException ex)
240 {
241 logger.Error.WriteLine("UIMemoryViewer.GetMemory(): SEHException: (0x{0:x8} {1}", ex.ErrorCode, ex.Message);
242 logger.Error.WriteLine(ex.ToString());
243 }
244 catch (Exception ex)
245 {
246 logger.Error.WriteLine("UIMemoryViewer.GetMemory(): Exception: {0}", ex.Message);
247 logger.Error.WriteLine(ex.ToString());
248 }
249 }
250 catch (Exception ex)
251 {
252 logger.Error.WriteLine("{0}.GetMemory():{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString());
253 }
254 finally
255 {
256 if (data.Length == 0)
257 {
258 data = new byte[max_ram_view];
259 for (int i = 0; i < data.Length; i++) { data[i] = 0x0; }
260 }
261 }
262 return data;
263 }
264 private void UpdateMemroyView() { this.UpdateMemroyView(this.CURRENT_TOP_ADDR); }
265 private void UpdateMemroyView(int address)
266 {
267 try
268 {
269 if (AcceptedProcess == null) { return; }
270 if (AcceptedPlugin == null) { return; }
271
272 byte[] data = GetMemory();
273 try
274 {
275 RamData = data;
276
277
278 AddressList = "";
279 AsciiData = "";
280 // write the addreses out
281 for (int i = address; i < (address + max_ram_view); i += max_address_width)
282 {
283 AddressList = AddressList + string.Format("{0:X8}:\n", i);
284 }
285 //// write out the ascii data
286 StringBuilder builder = new StringBuilder();
287 for (int i = address; i < (address + max_ram_view); i += max_address_width)
288 {
289 try
290 {
291 for (int j = 0; j < max_address_width; j++)
292 {
293 int current_addr = i + j;
294 if (current_addr >= MemoryRangeSize) break;
295 byte ascii_value_raw = data[j];
296 char ascii_value = (char)data[j];
297 if (ascii_value_raw >= 0x20 && ascii_value_raw <= 0x7e)
298 {
299 builder.Append(ascii_value.ToString());
300 }
301 else
302 {
303 builder.Append(".");
304 }
305 }
306 builder.AppendLine();
307 }
308 catch (Exception ex)
309 {
310 logger.Error.WriteLine("{0}.UpdateMemroyView().BuildingAsciiString:{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString());
311 return;
312 }
313 }
314 AsciiData = builder.ToString();
315
316
317 }
318 catch (Exception ex)
319 {
320 logger.Error.WriteLine("{0}.UpdateMemroyView():{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString());
321 return;
322 }
323 }
324 catch (Exception ex) { logger.Error.WriteLine("{0}.UpdateMemroyView():{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString()); }
325 }
326 //private void HexResourceViewerBytes_Changed(object sender, System.EventArgs e)
327 //{
328 // this.WriteCurrentBytes();
329 //}
330 private void WriteCurrentBytes(int start_address, byte[] data)
331 {
332 try
333 {
334 if (AcceptedProcess == null) { return; }
335 if (AcceptedPlugin == null) { return; }
336 // Byte changed
337 //byte[] data = (txtData.ByteProvider as DynamicByteProvider).Bytes.ToArray();
338 GenericMemoryProvider provider = new GenericMemoryProvider((IAcceptsProcessAndConfig)this);
339 provider.OpenProvider();
340 int bytesReadSize;
341
342 for (int i = 0; i < data.Length; i ++)
343 {
344 int addr = (int)(start_address + i);
345 byte data_to_write = data[i];
346 provider.WriteProcessMemory(addr, data_to_write, out bytesReadSize);
347 }
348 provider.CloseProvider();
349 }
350 catch (Exception ex) { logger.Error.WriteLine("{0}.WriteCurrentBytes():{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString()); }
351 }
352
353 private void update_timer_Tick(object sender, EventArgs e) { this.UpdateGui(); }
354 private void ResultsUpdateWorkerThread_DoWork(object sender, DoWorkEventArgs e) { try { this.UpdateMemroyView(); } catch (Exception ex) { logger.Error.WriteLine("{0}.ResultsUpdateWorkerThread_DoWork():{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString()); } }
355 private void ResultsUpdateWorkerThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
356 {
357 try
358 {
359 txtAddresses.Clear(); txtAddresses.Text = AddressList;
360 //txtAscii.Clear(); txtAscii.Text = AsciiData;
361 //this.Logger.LogDebugMessage(string.Format("RunWorkerCompeleted() -> Memory Size: {0}0x{2:X8}{1}", "{", "}", RamData.Length));
362 DynamicByteProvider _DynamicByteProvider = new DynamicByteProvider(RamData);
363 txtData.ByteProvider = _DynamicByteProvider;
364 //_DynamicByteProvider.Changed += new EventHandler(HexResourceViewerBytes_Changed);
365 }
366 catch (ObjectDisposedException) { } // ignore errors aobut disposed objects (usually only happens when the parent closes)
367 catch (Exception ex) { logger.Error.WriteLine("{0}.ResultsUpdateWorkerThread_RunWorkerCompleted():{1}{2}", this.GetType().Name, System.Environment.NewLine, ex.ToString()); }
368 }
369 private void Handle_KeyDown(object sender, KeyEventArgs e)
370 {
371 //isScrolling = false;
372 //bool reenable = false;
373 //if (this.UpdateEnabled) reenable = true;
374 //this.UpdateEnabled = false;
375
376 this.UpdateMaxRamView();
377 int ORIGINAL_ADDR = this.CURRENT_TOP_ADDR;
378
379 ////if (e.Type == ScrollEventType.EndScroll) return;
380 //uint size = max_ram_view;
381
382 bool haveModifier = false;
383 switch (e.Modifiers)
384 {
385 case Keys.Control:
386 switch (e.KeyCode)
387 {
388 case Keys.Home:
389 this.CURRENT_TOP_ADDR = 0; //NonHandledKeysAreBeingPressed = false;
390 break;
391 case Keys.End:
392 this.CURRENT_TOP_ADDR = (int)((MemoryRangeSize - 1) - max_ram_view); //NonHandledKeysAreBeingPressed = false;
393 break;
394 default:
395 //NonHandledKeysAreBeingPressed = true;
396 break;
397 }
398 break;
399 }
400
401 if (!haveModifier)
402 {
403 switch (e.KeyCode)
404 {
405 case Keys.Up:
406 if (this.CURRENT_TOP_ADDR == 0 && (this.CURRENT_TOP_ADDR - small_scroll_change > this.CURRENT_TOP_ADDR))
407 {
408 this.CURRENT_TOP_ADDR = ORIGINAL_ADDR;
409 }
410 else
411 {
412 this.CURRENT_TOP_ADDR -= (int)small_scroll_change; //NonHandledKeysAreBeingPressed = false;
413 }
414 break;
415 case Keys.Down:
416 this.CURRENT_TOP_ADDR += (int)small_scroll_change; //NonHandledKeysAreBeingPressed = false;
417 break;
418 case Keys.PageUp:
419 if (this.CURRENT_TOP_ADDR == 0 && (this.CURRENT_TOP_ADDR - large_scroll_change > this.CURRENT_TOP_ADDR))
420 {
421 this.CURRENT_TOP_ADDR = ORIGINAL_ADDR;
422 }
423 else
424 {
425 this.CURRENT_TOP_ADDR -= (int)(large_scroll_change); //NonHandledKeysAreBeingPressed = false;
426 }
427 break;
428 case Keys.PageDown:
429 this.CURRENT_TOP_ADDR += (int)(large_scroll_change); //NonHandledKeysAreBeingPressed = false;
430 break;
431 default:
432 //NonHandledKeysAreBeingPressed = true;
433 break;
434 }
435 }
436 if (this.CURRENT_TOP_ADDR < MemoryRangeStart) this.CURRENT_TOP_ADDR = MemoryRangeStart;
437 //if (this.CURRENT_TOP_ADDR >= VTLB_VADDR_SIZE) this.CURRENT_TOP_ADDR = (size - 1) - max_ram_view;
438 if (this.CURRENT_TOP_ADDR + max_ram_view >= MemoryRangeSize) this.CURRENT_TOP_ADDR = (int)(MemoryRangeSize - max_ram_view);
439
440 //this.UpdateEnabled = reenable;
441 }
442
443 private void UIMemoryViewer_KeyDown(object sender, KeyEventArgs e) { this.Handle_KeyDown(sender, e); }
444 private void txtAddresses_KeyDown(object sender, KeyEventArgs e) { this.Handle_KeyDown(sender, e); }
445 private void txtData_KeyDown(object sender, KeyEventArgs e) { this.Handle_KeyDown(sender, e); }
446
447 private void ramScroll_Scroll(object sender, ScrollEventArgs e) { this.Handle_Scroll(sender, e); }
448
449 private ScrollEventArgs GetMouseWheelScrollChange(int WheelDelta)
450 {
451 ScrollEventArgs args = new ScrollEventArgs(ScrollEventType.SmallIncrement,1);
452 if (WheelDelta < 0)
453 {
454 //// negative: scroll down
455 //// SmallDecrement -or- LargeDecrement
456 //if (WheelDelta <= small_scroll_change)
457 //{
458 // args = new ScrollEventArgs(ScrollEventType.SmallDecrement,(int)small_scroll_change);
459 //}
460 //if (WheelDelta > small_scroll_change && WheelDelta <= large_scroll_change)
461 //{
462 // args = new ScrollEventArgs(ScrollEventType.LargeDecrement, (int)large_scroll_change);
463 //}
464 args = new ScrollEventArgs(ScrollEventType.SmallIncrement, 1);
465 }
466 else
467 {
468 //// positive: scroll up
469 //// SmallIncrement -or- LargeIncrement
470 //if (WheelDelta <= small_scroll_change)
471 //{
472 // args = new ScrollEventArgs(ScrollEventType.SmallIncrement, (int)small_scroll_change);
473 //}
474 //if (WheelDelta > small_scroll_change && WheelDelta <= large_scroll_change)
475 //{
476 // args = new ScrollEventArgs(ScrollEventType.LargeIncrement, (int)large_scroll_change);
477 //}
478 args = new ScrollEventArgs(ScrollEventType.SmallDecrement, 1);
479 }
480 return args;
481 }
482
483 void txtAddresses_MouseWheel(object sender, MouseEventArgs e) { this.Handle_Scroll(sender, GetMouseWheelScrollChange(e.Delta)); }
484 void txtData_MouseWheel(object sender, MouseEventArgs e) { this.Handle_Scroll(sender, GetMouseWheelScrollChange(e.Delta)); }
485
486
487 private void Handle_Scroll(object sender, ScrollEventArgs e)
488 {
489 //isScrolling = true;
490 //bool reenable = false;
491 //if (this.UpdateEnabled) reenable = true;
492 //this.UpdateEnabled = false;
493
494 this.UpdateMaxRamView();
495 int ORIGINAL_ADDR = this.CURRENT_TOP_ADDR;
496 //uint size = MemorySize;
497 if (e.Type == ScrollEventType.EndScroll) return;
498
499 switch (e.Type)
500 {
501 case ScrollEventType.SmallDecrement:
502 if (this.CURRENT_TOP_ADDR == 0 && ((this.CURRENT_TOP_ADDR - small_scroll_change) > this.CURRENT_TOP_ADDR))
503 {
504 this.CURRENT_TOP_ADDR = ORIGINAL_ADDR;
505 }
506 else
507 {
508 this.CURRENT_TOP_ADDR -= (small_scroll_change);
509 }
510 break;
511 case ScrollEventType.SmallIncrement:
512 this.CURRENT_TOP_ADDR += (small_scroll_change);
513 break;
514
515 case ScrollEventType.LargeDecrement:
516 if (this.CURRENT_TOP_ADDR == 0 && ((this.CURRENT_TOP_ADDR - large_scroll_change) > this.CURRENT_TOP_ADDR))
517 {
518 this.CURRENT_TOP_ADDR = ORIGINAL_ADDR;
519 }
520 else
521 {
522 this.CURRENT_TOP_ADDR -= (large_scroll_change);
523 }
524 break;
525 case ScrollEventType.LargeIncrement:
526 this.CURRENT_TOP_ADDR += (large_scroll_change);
527 break;
528 case ScrollEventType.ThumbPosition:
529 //this.CURRENT_TOP_ADDR = (uint)e.NewValue;
530 //break;
531 default:
532 this.CURRENT_TOP_ADDR = (int)(e.NewValue & 0xFFFFFFF0);
533 break;
534 }
535 if (this.CURRENT_TOP_ADDR < 0) this.CURRENT_TOP_ADDR = 0;
536 //if (this.CURRENT_TOP_ADDR >= VTLB_VADDR_SIZE) this.CURRENT_TOP_ADDR = VTLB_VADDR_SIZE - max_ram_view;
537 //if (this.CURRENT_TOP_ADDR < 0 || this.CURRENT_TOP_ADDR >= VTLB_VADDR_SIZE) this.CURRENT_TOP_ADDR = ORIGINAL_ADDR;
538 if (this.CURRENT_TOP_ADDR + max_ram_view >= MemoryRangeSize) this.CURRENT_TOP_ADDR = (int)(MemoryRangeSize - max_ram_view);
539 //this.UpdateEnabled = reenable;
540 //isScrolling = false;
541 }
542
543 }
544 }

  ViewVC Help
Powered by ViewVC 1.1.22