public ILValue(object o, GM_Type type) { if (o is short) { this.Value = (int)((short)o); } else if (type == GM_Type.String) { this.ValueText = GMCodeUtil.EscapeString(o as string); } else { this.Value = o; } Type = type; }
void WriteOperand(ITextOutput output, bool escapeString = true) { if (Operand == null) { output.Write("%NULL_OPERAND%"); } else if (Operand is ILLabel) { output.Write((Operand as ILLabel).Name); } else if (escapeString) { if (Operand is string) { output.Write(GMCodeUtil.EscapeString((string)Operand)); } else if (Operand is ILValue) { ILValue val = Operand as ILValue; if (escapeString && val.Type == GM_Type.String) { output.Write(val.ValueText); } else { output.Write(val.ToString()); } } else { output.Write(Operand.ToString()); } } else { output.Write(Operand.ToString()); } }
public ILValue(string i) { this.Value = i; Type = GM_Type.String; this.ValueText = GMCodeUtil.EscapeString(i as string); }
// I had multipul passes on this so trying to combine it all to do one pass public static SortedList <int, Instruction> Dissasemble(BinaryReader r, long length, List <string> StringList, List <string> InstanceList = null) { if (r == null) { throw new ArgumentNullException("stream"); } if (r.BaseStream.CanRead != true) { throw new IOException("Cannot read stream"); } int pc = 0; long lastpc = r.BaseStream.Length / 4; SortedList <int, Instruction> list = new SortedList <int, Instruction>(); Dictionary <int, Label> labels = new Dictionary <int, Label>(); Dictionary <int, Label> pushEnviroment = new Dictionary <int, Label>(); List <Instruction> branches = new List <Instruction>(); Func <Instruction, int, Label> GiveInstructionALabel = (Instruction inst, int laddress) => { Label label; if (!labels.TryGetValue(laddress, out label)) { labels.Add(laddress, label = new Label(laddress)); } inst.Operand = label; branches.Add(inst); // add it to the branches to handle latter return(label); }; Instruction prev = null; StringBuilder sb = new StringBuilder(50); while (r.BaseStream.Position < length) { Instruction i = DissasembleFromReader(pc, r); pc += i.Size; switch (i.Code) { case GMCode.Pushenv: { Label endOfEnviroment = GiveInstructionALabel(i, i.Extra + 1); // skip the pop i.Operand = endOfEnviroment; pushEnviroment.Add(i.Address, endOfEnviroment); branches.Add(i); } break; case GMCode.Popenv: { Label endOfEnviroment; if (pushEnviroment.TryGetValue(i.Extra - 1, out endOfEnviroment)) { i.Operand = GiveInstructionALabel(i, i.Extra - 1); // not a break, set the label BACK to the push as we are simulating a loop } else { foreach (Instruction ii in list.Values.Reverse()) { if (ii.Code == GMCode.Pushenv) { i.Operand = GiveInstructionALabel(i, ii.Address); // we want to make these continues break; } } } branches.Add(i); Debug.Assert(i.Operand != null); } break; case GMCode.Bf: case GMCode.Bt: case GMCode.B: GiveInstructionALabel(i, i.Extra); break; case GMCode.Push: if (i.Types[0] == GM_Type.Var) { // i.Operand = StringList[(int)i.Operand]; Don't want to touch as it might sb.Clear(); sb.Append(GMCodeUtil.lookupInstance(i.Extra, InstanceList)); sb.Append('.'); sb.Append(StringList[(int)i.Operand & 0xFFFFF]); i.OperandText = sb.ToString(); } else if (i.Types[0] == GM_Type.String) { i.Operand = StringList[(int)i.Operand]; i.OperandText = GMCodeUtil.EscapeString(i.Operand as string); } break; case GMCode.Pop: // technicaly pop is always a var, but eh //i.Operand = StringList[(int)i.Operand]; Don't do it this wa as we might need to find out of its an array sb.Clear(); sb.Append(GMCodeUtil.lookupInstance(i.Extra, InstanceList)); sb.Append('.'); sb.Append(StringList[(int)i.Operand & 0xFFFFF]); i.OperandText = sb.ToString(); break; case GMCode.Call: i.OperandText = StringList[(int)i.Operand]; i.Operand = i.OperandText; break; } i.Previous = prev; if (prev == null) { prev = i; } else { prev.Next = i; } list.Add(i.Address, i); } if (list.Count == 0) { return(list); // return list, its empty } Instruction last = list.Last().Value; if (last.Code != GMCode.Exit || last.Code != GMCode.Ret) { int address = last.Address + last.Size; list.Add(address, new Instruction(address, GMCode.Exit)); } // must be done for graph and in case we have a branch that goes right outside. Its implied in any event foreach (var i in branches) { Label l = i.Operand as Label; if (l.Origin == null) // Link the label { l.Origin = list[l.Address]; list[l.Address].Label = l; } } return(list); }