ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/RomCheater/Docking/UI/UIMemoryViewer.cs
Revision: 202
Committed: Thu May 31 08:38:16 2012 UTC (11 years, 6 months ago) by william
File size: 21331 byte(s)
Log Message:
+ implement mouse wheel scrolling in memory viewer

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