////////////////////////////////////////////////////////////////////// // //@return true / if instruction was NOP // ////////////////////////////////////////////////////////////////////// public bool RunOneInstruction(bool bDebugEnabled) { if (m_started || m_runOnce || m_runToStepOver) { bool bCanRun = bDebugEnabled ? DebugFunctions.Z80Form().CanStep() : true; if (bCanRun && (m_curInstruction == null || m_curInstructionCurCycle >= m_curInstructionNbCycles)) { if (m_interruptsMgr.Update()) { return(true); } else { byte opcode = 0; opcode = GameBoy.Ram.ReadByteAt(m_PC); m_curInstruction = m_decoder.GetNextInstruction(); if (m_curInstruction == null) { ThrowNullInstructionException(opcode, m_PC, bDebugEnabled); return(true); } if (m_runOnce) { m_runOnce = false; m_curInstructionCurCycle = m_curInstructionNbCycles; } if (bDebugEnabled) { DebugFunctions.CallStackForm().AddToCallstack(); } ushort oldPc = m_PC; m_PC = m_curInstruction.Exec(m_PC); m_curInstructionNbCycles = m_curInstruction.GetCurNbCycles(oldPc); m_curInstructionCurCycle = 4; GameBoy.Cpu.IncInstructionNumber(); if (m_runToStepOver && opcode == 0xC9) { m_runToStepOver = false; Stop(); } } } else { if (!m_halted) { //on avance 4 cycles par 4 cycles car le timer est a 1Mhz, donc x4 pour les 4Mhz de la GB m_curInstructionCurCycle += 4; } } return(true); } return(false); }
////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// private void ThrowNullInstructionException(byte opcode, ushort pc, bool bDebugEnabled) { GameBoy.Cpu.Stop(); if (bDebugEnabled) { DebugFunctions.CallStackForm().AddToCallstack(); } string message = String.Format(" Wrong instruction, cannot be decoded (0x{0:x2}), PC = 0x{1:x4}", opcode, pc); string caption = "Error"; MessageBoxButtons buttons = MessageBoxButtons.OK; DialogResult result; result = MessageBox.Show(message, caption, buttons); }
////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// public bool Update() { if (!m_interruptStarted) { if (GameBoy.Cpu.IMEStatus()) { for (int i = 0; i < (int)e_interrupt.__max_interrupts__; i++) { if (IsEnabled((e_interrupt)i) && IsRequested((e_interrupt)i)) { Reset_IF((e_interrupt)i); Reset_IME(); //save current PC adress GameBoy.Cpu.SP -= 0x02; GameBoy.Ram.WriteUshortAt(GameBoy.Cpu.SP, GameBoy.Cpu.PC); //jump to interrupt adress GameBoy.Cpu.PC = e_interrupts_startAdr[i]; if (DebugFunctions.CallStackForm() != null) { DebugFunctions.CallStackForm().AddInterruptToCallstack(i); } if (GameBoy.Cpu.IsHalted()) { GameBoy.Cpu.ResumeFromHalt(); } m_interruptStarted = true; m_interruptCurCycle = 4; return(true); } } } } else { m_interruptCurCycle += 4; if (m_interruptCurCycle >= INTERRUPT_NB_CYCLES) { m_interruptStarted = false; m_interruptCurCycle = 0; return(true); } } return(false); }