Basic (probably incorrect) IRQ support (Fixes sound in Dragon Quest 1)

This commit is contained in:
Souryo 2014-06-24 14:28:49 -04:00
parent 617f5ead23
commit 9048c206be
3 changed files with 40 additions and 7 deletions

View File

@ -16,7 +16,7 @@ APU::APU()
_apu.output(&_buf);
_apu.dmc_reader(&APU::DMCRead);
//_apu.irq_notifier(irq_changed);
//_apu.irq_notifier(&APU::IRQChanged);
_outputBuffer = new int16_t[APU::SamplesPerFrame];
}
@ -54,6 +54,9 @@ void APU::WriteRAM(uint16_t addr, uint8_t value)
bool APU::Exec(uint32_t executedCycles)
{
if(APU::Instance->_apu.earliest_irq() == Nes_Apu::irq_waiting) {
CPU::SetIRQFlag();
}
_apu.end_frame(executedCycles);
_buf.end_frame(executedCycles);

View File

@ -4,6 +4,7 @@
uint64_t CPU::CycleCount = 0;
uint32_t CPU::CyclePenalty = 0;
bool CPU::NMIFlag = false;
bool CPU::IRQFlag = false;
CPU::CPU(MemoryManager *memoryManager) : _memoryManager(memoryManager)
{
@ -83,13 +84,20 @@ void CPU::Reset()
uint32_t CPU::Exec()
{
//static ofstream log("log.txt", ios::out | ios::binary);
uint32_t executedCycles = 0;
if(!_runNMI) {
if(!_runNMI && !_runIRQ) {
if(CPU::IRQFlag && !CheckFlag(PSFlags::Interrupt)) {
_runIRQ = true;
}
CPU::IRQFlag = false;
if(CPU::NMIFlag) {
_runNMI = true;
}
uint8_t opCode = ReadByte();
if(_opTable[opCode] != nullptr) {
//log << std::hex << (_state.PC - 1) << ": " << (short)opCode << std::endl;
(this->*_opTable[opCode])();
executedCycles = (IsPageCrossed() ? _cyclesPageCrossed[opCode] : _cycles[opCode]);
} else {
@ -97,10 +105,17 @@ uint32_t CPU::Exec()
//throw exception("Invalid opcode");
}
} else {
NMI();
_runNMI = false;
if(_runNMI) {
NMI();
_runNMI = false;
CPU::NMIFlag = false;
} else if(_runIRQ) {
IRQ();
}
_runIRQ = false;
CPU::IRQFlag = false;
executedCycles = 7;
CPU::NMIFlag = false;
}
CPU::CycleCount += executedCycles;

View File

@ -31,6 +31,10 @@ struct State
class CPU
{
private:
const uint16_t NMIVector = 0xFFFA;
const uint16_t ResetVector = 0xFFFC;
const uint16_t IRQVector = 0xFFFE;
typedef void(CPU::*Func)();
static uint64_t CycleCount;
@ -45,7 +49,9 @@ private:
MemoryManager *_memoryManager = nullptr;
static bool NMIFlag;
static bool IRQFlag;
bool _runNMI = false;
bool _runIRQ = false;
uint8_t ReadByte()
{
@ -600,14 +606,21 @@ private:
Push((uint8_t)flags);
SetFlags(PSFlags::Interrupt);
SetPC(MemoryReadWord(0xFFFE));
SetPC(MemoryReadWord(CPU::IRQVector));
}
void NMI() {
Push((uint16_t)(PC()));
Push((uint8_t)PS());
SetFlags(PSFlags::Interrupt);
SetPC(MemoryReadWord(0xFFFA));
SetPC(MemoryReadWord(CPU::NMIVector));
}
void IRQ() {
Push((uint16_t)(PC()));
Push((uint8_t)PS());
SetFlags(PSFlags::Interrupt);
SetPC(MemoryReadWord(CPU::IRQVector));
}
@ -628,6 +641,8 @@ public:
CPU::CycleCount += cycles;
}
static void SetNMIFlag() { CPU::NMIFlag = true; }
static void SetIRQFlag() { CPU::IRQFlag = true; }
void Reset();
uint32_t Exec();
State GetState() { return _state; }