private Instruction InterruptHandler(Interrupts interrupt) { // Handle interrupt with a CALL instruction to the interrupt handler Instruction instruction = new Instruction(); instruction.OpCode = 0xCD; // CALL! byte lowOpcode = (byte)instruction.OpCode; instruction.Length = CPUInstructionLengths.Get(lowOpcode); instruction.Literal = this.interruptHandlers[(Interrupts)interrupt]; instruction.Ticks = CPUInstructionPreClocks.Get(lowOpcode); instruction.Name = CPUInstructionNames.Get(lowOpcode); instruction.Description = CPUInstructionDescriptions.Get(lowOpcode); // Disable interrupts during interrupt handling and clear the current one this._interruptController.InterruptMasterEnable = false; byte IF = this._memory.LowLevelRead((ushort)MMR.IF); IF &= (byte)~(byte)interrupt; this._memory.LowLevelWrite((ushort)MMR.IF, IF); return instruction; }
/// <summary> /// Sets the initial values for the cpu registers and memory mapped registers. /// This is the equivalent to run the BIOS rom. /// </summary> internal void Reset() { // Reset the clock state _state.Clock = 0; _state.Halted = false; _state.HaltLoad = false; _state.Stopped = false; // Magic CPU initial values (after bios execution). _state.Registers.A = 1; _state.Registers.BC = 0x0013; _state.Registers.DE = 0x00D8; _state.Registers.HL = 0x014D; _state.Registers.PC = 0x0100; _state.Registers.SP = 0xFFFE; // We restart the timer _state.DivCounter = 0xABFF; _state.TimaCounter = 0; _state.TacCounter = 0; _state.TacMask = 0; _state.TmaValue = 0; // Initialize memory mapped registers this._memory.LowLevelWrite(0xFF04, 0xAB); // DIV this._memory.LowLevelWrite(0xFF05, 0x00); // TIMA this._memory.LowLevelWrite(0xFF06, 0x00); // TMA this._memory.LowLevelWrite(0xFF07, 0x00); // TAC this._memory.LowLevelWrite(0xFF10, 0x80); // NR10 this._memory.LowLevelWrite(0xFF11, 0xBF); // NR11 this._memory.LowLevelWrite(0xFF12, 0xF3); // NR12 this._memory.LowLevelWrite(0xFF14, 0xBF); // NR14 this._memory.LowLevelWrite(0xFF16, 0x3F); // NR21 this._memory.LowLevelWrite(0xFF17, 0x00); // NR22 this._memory.LowLevelWrite(0xFF19, 0xBF); // NR24 this._memory.LowLevelWrite(0xFF1A, 0x7F); // NR30 this._memory.LowLevelWrite(0xFF1B, 0xFF); // NR31 this._memory.LowLevelWrite(0xFF1C, 0x9F); // NR32 this._memory.LowLevelWrite(0xFF1E, 0xBF); // NR33 this._memory.LowLevelWrite(0xFF20, 0xFF); // NR41 this._memory.LowLevelWrite(0xFF21, 0x00); // NR42 this._memory.LowLevelWrite(0xFF22, 0x00); // NR43 this._memory.LowLevelWrite(0xFF23, 0xBF); // NR30 this._memory.LowLevelWrite(0xFF24, 0x77); // NR50 this._memory.LowLevelWrite(0xFF25, 0xF3); // NR51 this._memory.LowLevelWrite(0xFF26, 0xF1); // NR52 GB: 0xF1, SGB: 0xF0 this._memory.LowLevelWrite(0xFF40, 0x91); // LCDC this._memory.LowLevelWrite(0xFF42, 0x00); // SCY this._memory.LowLevelWrite(0xFF43, 0x00); // SCX this._memory.LowLevelWrite(0xFF45, 0x00); // LYC this._memory.LowLevelWrite(0xFF47, 0xFC); // BGP this._memory.LowLevelWrite(0xFF48, 0xFF); // OBP0 this._memory.LowLevelWrite(0xFF49, 0xFF); // OBP1 this._memory.LowLevelWrite(0xFF4A, 0x00); // WY this._memory.LowLevelWrite(0xFF4B, 0x00); // WX this._memory.LowLevelWrite(0xFFFF, 0x00); // IE _state.CurrentInstruction = new Instruction(); _exportInstruction = new Instruction(); }
internal void Reset() { _disInstructions = new List<IInstruction>(); _disVisitedAddresses = new HashSet<ushort>(); _disAddressToVisit = new Stack<ushort>(); _disassembledMatrix = new byte[0xFFFF][]; for (int i = 0; i < 0xFFFF; ++i) { _disassembledMatrix[i] = new byte[5]; } _tempInstruction = new Instruction(); }
/// <summary> /// Fetches and Decodes an instruction /// </summary> /// <param name="instruction"> /// As FetchAndDecode gets called *several* times a frame (and many times during /// disassembly), it is better to have a pre-allocated instruction and to replace /// the values, instead of getting the overhead of allocating a new Instrucion /// everytime. /// </param> /// <param name="instructionAddress"></param> /// <param name="haltLoad"></param> /// <returns></returns> internal Instruction FetchAndDecode(ref Instruction instruction, ushort instructionAddress, bool haltLoad = false) { instruction.Address = instructionAddress; byte opcode = this._memory.LowLevelRead(instructionAddress); instruction.OpCode = opcode; if (instruction.OpCode != 0xCB) { instruction.CB = false; byte lowOpcode = (byte)instruction.OpCode; if (_instructionHistogram[lowOpcode] < ushort.MaxValue) _instructionHistogram[lowOpcode]++; // Normal instructions instruction.Length = CPUInstructionLengths.Get(lowOpcode); // Extract literal if (instruction.Length == 2) { // 8 bit literal instruction.Operands[0] = this._memory.LowLevelRead((ushort)(instructionAddress + 1)); if (haltLoad) { instruction.Operands[0] = opcode; } instruction.Literal = (byte)instruction.Operands[0]; } else if (instruction.Length == 3) { // 16 bit literal, little endian instruction.Operands[0] = this._memory.LowLevelRead((ushort)(instructionAddress + 2)); instruction.Operands[1] = this._memory.LowLevelRead((ushort)(instructionAddress + 1)); if (haltLoad) { instruction.Operands[1] = instruction.Operands[0]; instruction.Operands[0] = opcode; } instruction.Literal = (byte)instruction.Operands[1]; instruction.Literal += (ushort)(instruction.Operands[0] << 8); } instruction.Ticks = CPUInstructionPreClocks.Get(lowOpcode); instruction.Name = CPUInstructionNames.Get(lowOpcode); instruction.Description = CPUInstructionDescriptions.Get(lowOpcode); } else { instruction.CB = true; // CB instructions block instruction.OpCode <<= 8; if (!haltLoad) { instruction.OpCode += this._memory.LowLevelRead((ushort)(instructionAddress + 1)); } else { instruction.OpCode += 0xCB; // The first byte is duplicated } byte lowOpcode = (byte)instruction.OpCode; if (_cbInstructionHistogram[lowOpcode] < ushort.MaxValue) { _cbInstructionHistogram[lowOpcode]++; } instruction.Length = CPUCBInstructionLengths.Get(lowOpcode); // There is no literal in CB instructions! //instruction.Lambda = this.CBInstructionLambdas[lowOpcode]; instruction.Ticks = CPUCBInstructionPreClocks.Get(lowOpcode); instruction.Name = CPUCBInstructionNames.Get(lowOpcode); instruction.Description = CPUCBInstructionDescriptions.Get(lowOpcode); } // NOTE(Cristian): On haltLoad (HALT with IME disabled), the next byte after the HALT opcode // is "duplicated". This is a hardware bug. if (haltLoad) { instruction.Length--; } return instruction; }
public IInstruction FetchAndDecode(ushort address) { Instruction inst = new Instruction(); _cpu.FetchAndDecode(ref inst, address); return inst; }