ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/RomCheater/Docking/UI/UIMemoryViewer.cs
Revision: 206
Committed: Thu May 31 09:31:57 2012 UTC (11 years, 6 months ago) by william
File size: 22622 byte(s)
Log Message:
+ add support for memory view to accept a memory address externally

File Contents

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