mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-12 08:29:50 +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
|
#pragma once
|
||||||
|
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
|
#include "Processor.h"
|
||||||
|
|
||||||
namespace EightBit {
|
namespace EightBit {
|
||||||
class Bus : public Memory {
|
class Bus : public Memory {
|
||||||
@ -75,12 +76,25 @@ namespace EightBit {
|
|||||||
BOOT_DISABLE = 0x50,
|
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();
|
Bus();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
virtual void clear() override;
|
virtual void clear() override;
|
||||||
|
|
||||||
|
void triggerInterrupt(int cause) {
|
||||||
|
writeRegister(IF, readRegister(IF) | cause);
|
||||||
|
}
|
||||||
|
|
||||||
void writeRegister(int offset, uint8_t content) {
|
void writeRegister(int offset, uint8_t content) {
|
||||||
return Memory::write(BASE + offset, content);
|
return Memory::write(BASE + offset, content);
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,7 @@ namespace EightBit {
|
|||||||
void di();
|
void di();
|
||||||
void ei();
|
void ei();
|
||||||
|
|
||||||
int interrupt(uint8_t value);
|
int run(int limit);
|
||||||
|
|
||||||
virtual int execute(uint8_t opcode);
|
virtual int execute(uint8_t opcode);
|
||||||
int step();
|
int step();
|
||||||
|
|
||||||
@ -163,6 +162,8 @@ namespace EightBit {
|
|||||||
|
|
||||||
static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
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 executeCB(int x, int y, int z, int p, int q);
|
||||||
void executeOther(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
|
#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() {
|
int EightBit::LR35902::step() {
|
||||||
ExecutingInstruction.fire(*this);
|
ExecutingInstruction.fire(*this);
|
||||||
m_prefixCB = false;
|
m_prefixCB = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user