public static void GenerateClass(MemoryObject obj) { var cts = new CancellationTokenSource(); var ct = cts.Token; var dialog = new MemoryObjectClassGeneratorDialog(); dialog.HeaderText = "Generating class..."; dialog.StatusText = ""; dialog.ProgressPercentage = 0; dialog.Closed += (s, e) => cts.Cancel(); var task = new Task <StringBuilder>(() => { var type = obj.GetType(); var size = type.SizeOf(); string hexFormat = "X" + Math.Max(2, size.ToString("X").Length); var sb = new StringBuilder(); sb.AppendLine(string.Format("public class {0} : MemoryObject", type.Name)); sb.AppendLine("{"); int offset = 0; while (offset < size && !ct.IsCancellationRequested) { Execute.OnUIThreadAsync(() => { dialog.ProgressPercentage = 100d * offset / size; dialog.StatusText = string.Format("Scanning {0} / {1}", offset, size); }); var ctx = new TypeMatchContext(obj, offset); if (false || ctx.TryAsList() || ctx.TryAsAllocator() || ctx.TryAsBasicAllocator() || ctx.TryAsMap() || ctx.TryAsVector() || ctx.TryAsZeroInt32() || // Anything that might be valid if first 4 bytes are zero must be above this check! ctx.TryAsUIReference() || ctx.TryAsSno() || ctx.TryAsRefString() || ctx.TryAsText() || ctx.TryAsFloat() || ctx.TryAsPointer() || false) { if (ctx.Name == null) { ctx.Name = ctx.FieldType; } } else { ctx.Prefix = "_"; ctx.FieldType = "int"; ctx.Name = ""; ctx.FieldSize = sizeof(int); ctx.Comment = ctx.Read <int>(0x00).ToString(); } string line = string.Format("\t/* 0x{5:X8} */ public {0} {1}x{2}{3} {{ get {{ return Read<{0}>(0x{2}); }} }}{4}", ctx.FieldType, ctx.Prefix, ctx.Offset.ToString(hexFormat), ctx.Name == string.Empty ? string.Empty : ("_" + ctx.Name + ctx.Postfix), string.IsNullOrEmpty(ctx.Comment) ? string.Empty : " // " + ctx.Comment, ctx.MemoryObject.Address + ctx.Offset); sb.AppendLine(line); offset += ctx.FieldSize; } sb.AppendLine("}"); return(sb); }, ct); task.ContinueWith(t => { var sb = t.Result; Execute.OnUIThread(() => { dialog.Close(); var menu = new ContextMenu(); var item = new MenuItem { Header = "Copy to clipboard" }; item.Click += (s, e) => Clipboard.SetText(sb.ToString()); menu.Items.Add(item); new Window() { Content = new ScrollViewer { Content = new TextBox { IsReadOnly = true, Text = sb.ToString(), FontFamily = new FontFamily("Consolas"), ContextMenu = menu } } }.ShowDialog(); }); }); task.Start(); dialog.ShowDialog(); }
private void PreProcess(ref IMethodCallMessage msg) { if (msg.MethodName.StartsWith("get_")) { PropertyInfo property = _target.GetType().GetProperty(msg.MethodName.Substring(4)); var attribute = property.GetCustomAttribute <AddressAttribute>(); if (property.CanWrite && attribute != null) { ProcessMemory mem = _target.Memory[attribute.Address]; if (property.PropertyType == typeof(int)) { property.SetValue(_target, mem.AsInteger()); } if (property.PropertyType == typeof(byte)) { property.SetValue(_target, mem.AsByte()); } if (property.PropertyType == typeof(byte[])) { property.SetValue(_target, mem.AsBytes(attribute.Length)); } if (property.PropertyType == typeof(float)) { property.SetValue(_target, mem.AsFloat()); } if (property.PropertyType == typeof(short)) { property.SetValue(_target, mem.AsShort()); } if (property.PropertyType == typeof(string)) { property.SetValue(_target, mem.AsString(attribute.Length)); } if (property.PropertyType.IsSubclassOf(typeof(MemoryObject))) { property.SetValue(_target, Activator.CreateInstance(property.PropertyType, mem.AsPointer())); } } } if (msg.MethodName.StartsWith("set_")) { PropertyInfo property = _target.GetType().GetProperty(msg.MethodName.Substring(4)); var attribute = property.GetCustomAttribute <AddressAttribute>(); if (property.CanWrite && attribute != null) { ProcessMemory mem = _target.Memory[attribute.Address]; if (property.PropertyType == typeof(int)) { mem.Set((int)msg.GetArg(0)); } if (property.PropertyType == typeof(byte)) { mem.Set((byte)msg.GetArg(0)); } if (property.PropertyType == typeof(byte[])) { mem.Set((byte[])msg.GetArg(0)); } if (property.PropertyType == typeof(float)) { mem.Set((float)msg.GetArg(0)); } if (property.PropertyType == typeof(short)) { mem.Set((short)msg.GetArg(0)); } if (property.PropertyType == typeof(string)) { mem.Set((string)msg.GetArg(0)); } if (property.PropertyType.IsSubclassOf(typeof(MemoryObject))) { object value = msg.GetArg(0); if (value != null) { var other = value as MemoryObject; mem.Set(other.Memory.Address); } } } } }
public TypeMatchContext(MemoryObject obj, int offset) { MemoryObject = obj; Size = obj.GetType().SizeOf(); Offset = offset; }