public Instruction(Int32 _instruction) { this.Raw = _instruction; this.Opcode = Instruction.GetOpcode(_instruction); this.Argument = (byte)((_instruction >> 16) & 0xFF); this.Data = (Int16)(_instruction & 0xFFFF); }
public InstructionDefinition(LOpcode _opcode) { this.Opcode = new LOpcode[] { _opcode }; }
public void Parse(Game _game) { // Parse all instructions while (this.Reader.BaseStream.Position < this.Reader.BaseStream.Length) { this.BranchTable[this.Reader.BaseStream.Position] = this.Instructions.Count; Int32 _instructionGet = this.Reader.ReadInt32(); LOpcode _opcodeGet = Instruction.GetOpcode(_instructionGet); if (Instruction.Ignore.Contains(_opcodeGet) == false) { if (Instruction.Mapping.ContainsKey(_opcodeGet) == true) { this.Instructions.Add(Instruction.Mapping[_opcodeGet](_instructionGet, _game, this, this.Reader)); } else { throw new Exception(String.Format("Could not find instruction mapping for {0} at {1} in {2}", _opcodeGet, this.Reader.BaseStream.Position, this.Name)); } } } // Map out branching & environments for (int i = 0; i < this.Instructions.Count; i++) { switch (this.Instructions[i].Opcode) { case LOpcode.b: case LOpcode.bt: case LOpcode.bf: { Instructions.Branch _instructionBranch = this.Instructions[i] as Instructions.Branch; if (this.BranchTable.ContainsKey(_instructionBranch.Offset) == true) { _instructionBranch.Jump = this.BranchTable[_instructionBranch.Offset] - 1; } else { _instructionBranch.Jump = this.Instructions.Count; } break; } case LOpcode.pushenv: { Instructions.PushEnvironment _instructionEnv = this.Instructions[i] as Instructions.PushEnvironment; if (this.BranchTable.ContainsKey(_instructionEnv.Offset) == true) { _instructionEnv.Jump = this.BranchTable[_instructionEnv.Offset]; } else { _instructionEnv.Jump = this.Instructions.Count; } break; } case LOpcode.popenv: { Instructions.PopEnvironment _instructionEnv = this.Instructions[i] as Instructions.PopEnvironment; if (this.BranchTable.ContainsKey(_instructionEnv.Offset) == true) { _instructionEnv.Jump = this.BranchTable[_instructionEnv.Offset]; } else { _instructionEnv.Jump = this.Instructions.Count; } break; } } } // Check for arrays for (int i = 0; i < this.Instructions.Count; i++) { switch (this.Instructions[i].Opcode) { case LOpcode.setowner: { // Find next pop instruction for (int j = i; j < this.Instructions.Count; j++) { if (this.Instructions[j].Opcode == LOpcode.pop) { this.Instructions.RemoveAt(--i); // push.i <id> break; } else if (this.Instructions[j].Opcode == LOpcode.call) { Instructions.Call _instructionGet = this.Instructions[j] as Instructions.Call; if (_instructionGet.FunctionName == "@@NewGMLArray@@") { this.Instructions.RemoveAt(--i); break; } } } break; } } } #if (!DEBUG) // Print out finalized bytecode string _bytecodeOutput = this.Name + "\n"; for (int i = 0; i < this.Instructions.Count; i++) { _bytecodeOutput += String.Format("[{1}] - {0}", this.Instructions[i].Opcode, this.Instructions[i].Raw.ToString("X")); switch (this.Instructions[i].Opcode) { case LOpcode.b: { Instructions.Branch _instructionGet = this.Instructions[i] as Instructions.Branch; _bytecodeOutput += String.Format("(Goto={0}:{1})", this.Instructions[_instructionGet.Jump].Opcode, _instructionGet.Jump); break; } case LOpcode.call: { Instructions.Call _instructionGet = this.Instructions[i] as Instructions.Call; _bytecodeOutput += String.Format("(Function={0})", _instructionGet.FunctionName); break; } case LOpcode.pop: { Instructions.Pop _instructionGet = this.Instructions[i] as Instructions.Pop; _bytecodeOutput += String.Format("(Variable={0}, Scope={1})", _instructionGet.Variable.Name, _instructionGet.Data); break; } case LOpcode.push: { Instructions.Push _instructionGet = this.Instructions[i] as Instructions.Push; switch (_instructionGet.Type) { case LArgumentType.Variable: { _bytecodeOutput += String.Format("(Variable={0})", _instructionGet.Variable.Name); break; } default: { _bytecodeOutput += String.Format("(Value={0})", _instructionGet.Value.Value); break; } } break; } case LOpcode.pushb: { Instructions.PushBuiltin _instructionGet = this.Instructions[i] as Instructions.PushBuiltin; _bytecodeOutput += String.Format("(Variable={0})", _instructionGet.Variable); break; } case LOpcode.pushi: { Instructions.PushImmediate _instructionGet = this.Instructions[i] as Instructions.PushImmediate; _bytecodeOutput += String.Format("(Value={0})", _instructionGet.Value.Value); break; } } _bytecodeOutput += "\n"; } Console.WriteLine(_bytecodeOutput); // Print out decompiled bytecode try { Console.WriteLine("{0}:\n---\n{1}\n---", this.Name, Runner.Debug.Decompiler.Decompile(this.Instructions)); } catch (Exception e) { Console.WriteLine("Failed to decompile {0}: {1}", this.Name, e.Message); } #endif }