NESHawk: fix interaction between RDY and NMI/IRQ

This commit is contained in:
alyosha-tas 2021-12-27 08:04:27 -05:00
parent 638c759aa0
commit b45b552b9d
6 changed files with 15 additions and 49 deletions

View File

@ -581,7 +581,10 @@ namespace BizHawk.Emulation.Cores.Components.M6502
} }
} }
Fetch1_Real(); mi = 0;
opcode = VOP_Fetch1_NoInterrupt;
Fetch1_Real();
} }
private void Fetch1_Real() private void Fetch1_Real()

View File

@ -746,7 +746,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
// when called due to empty bueffer while DMC running, there is no delay // when called due to empty bueffer while DMC running, there is no delay
nes.cpu.RDY = false; nes.cpu.RDY = false;
nes.dmc_dma_exec = true; nes.dmc_dma_exec = true;
nes.DMC_just_started = true;
if (fill_glitch_2) if (fill_glitch_2)
{ {

View File

@ -447,15 +447,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public byte oam_dma_byte; public byte oam_dma_byte;
public bool dmc_dma_exec = false; public bool dmc_dma_exec = false;
public bool dmc_realign; public bool dmc_realign;
public bool IRQ_delay;
public bool reread_trigger; public bool reread_trigger;
public int do_the_reread_2002, do_the_reread_2007, do_the_reread_cont_1, do_the_reread_cont_2; public int do_the_reread_2002, do_the_reread_2007, do_the_reread_cont_1, do_the_reread_cont_2;
public int reread_opp_4016, reread_opp_4017; public int reread_opp_4016, reread_opp_4017;
public byte DB; //old data bus values from previous reads public byte DB; //old data bus values from previous reads
// DMA's delay IRQ's by one cycle after finished, but allow them on the same cycle if just started
public bool DMC_just_started;
public bool OAM_just_started;
public bool ppu_nmi;
internal void RunCpuOne() internal void RunCpuOne()
{ {
@ -514,8 +509,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
apu.DMC_RDY_check = -1; apu.DMC_RDY_check = -1;
} }
if (!dmc_dma_exec) { DMC_just_started = true; }
cpu.RDY = false; cpu.RDY = false;
dmc_dma_exec = true; dmc_dma_exec = true;
apu.dmc_dma_countdown--; apu.dmc_dma_countdown--;
@ -586,37 +579,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
// dmc dma end // dmc dma end
///////////////////////////// /////////////////////////////
apu.RunOneFirst(); apu.RunOneFirst();
if (cpu.RDY && !IRQ_delay) cpu.IRQ = _irq_apu || Board.IrqSignal;
// DMC was started in the APU, but in this case it only lasts 1 cycle and is then aborted, so put this here
// TODO: should this clock controllers?
if (apu.dmc.fill_glitch_2)
{ {
cpu.IRQ = _irq_apu || Board.IrqSignal; apu.dmc_dma_countdown = -1;
if (ppu_nmi) dmc_dma_exec = false;
{ apu.dmc.fill_glitch_2 = false;
cpu.NMI = ppu_nmi;
ppu_nmi = false;
}
}
else if (OAM_just_started || DMC_just_started)
{
cpu.IRQ = _irq_apu || Board.IrqSignal;
if (ppu_nmi)
{
cpu.NMI = ppu_nmi;
ppu_nmi = false;
}
OAM_just_started = false;
DMC_just_started = false;
// DMC was started in the APU, but in this case it only lasts 1 cycle and is then aborted, so put this here
// TODO: should this clock controllers?
if (apu.dmc.fill_glitch_2)
{
apu.dmc_dma_countdown = -1;
dmc_dma_exec = false;
apu.dmc.fill_glitch_2 = false;
}
} }
cpu.ExecuteOne(); cpu.ExecuteOne();
@ -644,12 +616,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
reread_trigger = false; reread_trigger = false;
} }
IRQ_delay = false;
if (!cpu.RDY && !dmc_dma_exec && !oam_dma_exec) if (!cpu.RDY && !dmc_dma_exec && !oam_dma_exec)
{ {
cpu.RDY = true; cpu.RDY = true;
IRQ_delay = true;
} }
} }
@ -843,7 +812,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
oam_dma_exec = true; oam_dma_exec = true;
cpu.RDY = false; cpu.RDY = false;
oam_dma_index = 0; oam_dma_index = 0;
OAM_just_started = true;
} }
} }
break; break;

View File

@ -29,7 +29,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync(nameof(oam_dma_byte), ref oam_dma_byte); ser.Sync(nameof(oam_dma_byte), ref oam_dma_byte);
ser.Sync(nameof(dmc_dma_exec), ref dmc_dma_exec); ser.Sync(nameof(dmc_dma_exec), ref dmc_dma_exec);
ser.Sync(nameof(dmc_realign), ref dmc_realign); ser.Sync(nameof(dmc_realign), ref dmc_realign);
ser.Sync(nameof(IRQ_delay), ref IRQ_delay);
ser.Sync(nameof(reread_trigger), ref reread_trigger); ser.Sync(nameof(reread_trigger), ref reread_trigger);
ser.Sync(nameof(do_the_reread_2002), ref do_the_reread_2002); ser.Sync(nameof(do_the_reread_2002), ref do_the_reread_2002);
ser.Sync(nameof(do_the_reread_2007), ref do_the_reread_2007); ser.Sync(nameof(do_the_reread_2007), ref do_the_reread_2007);
@ -37,9 +36,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync(nameof(do_the_reread_cont_2), ref do_the_reread_cont_2); ser.Sync(nameof(do_the_reread_cont_2), ref do_the_reread_cont_2);
ser.Sync(nameof(reread_opp_4016), ref reread_opp_4016); ser.Sync(nameof(reread_opp_4016), ref reread_opp_4016);
ser.Sync(nameof(reread_opp_4017), ref reread_opp_4017); ser.Sync(nameof(reread_opp_4017), ref reread_opp_4017);
ser.Sync(nameof(OAM_just_started), ref OAM_just_started);
ser.Sync(nameof(DMC_just_started), ref DMC_just_started);
ser.Sync(nameof(ppu_nmi), ref ppu_nmi);
// VS related // VS related
ser.Sync("VS", ref _isVS); ser.Sync("VS", ref _isVS);

View File

@ -423,7 +423,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
NMI_PendingInstructions--; NMI_PendingInstructions--;
if (NMI_PendingInstructions <= 0) if (NMI_PendingInstructions <= 0)
{ {
nes.ppu_nmi = true; nes.cpu.NMI = true;
} }
} }
} }

View File

@ -175,7 +175,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
} }
else if (ppur.status.cycle == (3 + NMI_offset) && ppur.status.sl == 241 + preNMIlines) else if (ppur.status.cycle == (3 + NMI_offset) && ppur.status.sl == 241 + preNMIlines)
{ {
if (nmi_destiny) { nes.ppu_nmi = true; } if (nmi_destiny) { nes.cpu.NMI = true; }
nes.Board.AtVsyncNmi(); nes.Board.AtVsyncNmi();
} }