ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/RomCheater/Docking/UI/UIMemoryViewer.cs
Revision: 285
Committed: Tue Jun 5 01:54:33 2012 UTC (11 years, 8 months ago) by william
File size: 23735 byte(s)
Log Message:
+ search wip

File Contents

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