Rewrite GB interrupt handling to properly document the trigger sequence.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-08-18 09:49:06 +01:00
parent 039545bd08
commit 0457dffba4
3 changed files with 45 additions and 2 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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;