mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-24 06:29:42 +00:00
Rewrite GB interrupt handling to properly document the trigger sequence.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
039545bd08
commit
0457dffba4
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user