diff --git a/LR35902/inc/Bus.h b/LR35902/inc/Bus.h index 9646053..8de1f62 100644 --- a/LR35902/inc/Bus.h +++ b/LR35902/inc/Bus.h @@ -1,6 +1,7 @@ #pragma once #include "Memory.h" +#include "Processor.h" namespace EightBit { class Bus : public Memory { @@ -75,12 +76,25 @@ namespace EightBit { BOOT_DISABLE = 0x50, }; + // IF and IE flags + enum Interrupts { + VerticalBlank = Processor::Bit0, // VBLANK + DisplayControlStatus = Processor::Bit1, // LCDC Status + TimerOverflow = Processor::Bit2, // Timer Overflow + SerialTransfer = Processor::Bit3, // Serial Transfer + Keypad = Processor::Bit3 // Hi-Lo of P10-P13 + }; + Bus(); void reset(); virtual void clear() override; + void triggerInterrupt(int cause) { + writeRegister(IF, readRegister(IF) | cause); + } + void writeRegister(int offset, uint8_t content) { return Memory::write(BASE + offset, content); } diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index 2b06c25..f706850 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -29,8 +29,7 @@ namespace EightBit { void di(); void ei(); - int interrupt(uint8_t value); - + int run(int limit); virtual int execute(uint8_t opcode); int step(); @@ -163,6 +162,8 @@ namespace EightBit { static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0); + int interrupt(uint8_t value); + void executeCB(int x, int y, int z, int p, int q); void executeOther(int x, int y, int z, int p, int q); diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index e431d04..aca8bd7 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -330,6 +330,34 @@ void EightBit::LR35902::ccf(uint8_t& a, uint8_t& f) { #pragma endregion Miscellaneous instructions +int EightBit::LR35902::run(int limit) { + int current = 0; + do { + auto interruptEnable = m_bus.readRegister(Bus::IE); + auto interruptFlags = m_bus.readRegister(Bus::IF); + + auto masked = (IME() ? interruptEnable : 0) & interruptFlags; + if (masked) + m_bus.writeRegister(Bus::IF, 0); + + if (masked & Bus::Interrupts::VerticalBlank) { + current += interrupt(0x40); + } else if (masked & Bus::Interrupts::DisplayControlStatus) { + current += interrupt(0x48); + } else if (masked & Bus::Interrupts::TimerOverflow) { + current += interrupt(0x50); + } else if (masked & Bus::Interrupts::SerialTransfer) { + current += interrupt(0x58); + } else if (masked & Bus::Interrupts::Keypad) { + current += interrupt(0x60); + } else { + current += step(); + } + + } while (current < limit); + return current; +} + int EightBit::LR35902::step() { ExecutingInstruction.fire(*this); m_prefixCB = false;