mirror of
https://github.com/libretro/Mesen.git
synced 2025-02-08 18:16:24 +00:00
Basic (probably incorrect) IRQ support (Fixes sound in Dragon Quest 1)
This commit is contained in:
parent
617f5ead23
commit
9048c206be
@ -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);
|
||||
|
||||
|
23
Core/CPU.cpp
23
Core/CPU.cpp
@ -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;
|
||||
|
19
Core/CPU.h
19
Core/CPU.h
@ -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; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user