NESHawk: Fix interaction between RDY and Branch_delay_irq bug. Fix regression in APU timing.

This commit is contained in:
alyosha-tas 2021-12-28 21:09:13 -05:00
parent 509718887a
commit 8dd98852be
2 changed files with 47 additions and 26 deletions

View File

@ -306,9 +306,9 @@ namespace BizHawk.Emulation.Cores.Components.M6502
/*ISC* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_ISC, Uop.AbsIdx_RMW_Stage7, Uop.End },
//0x100
/*VOP_Fetch1*/ new Uop[] { Uop.Fetch1 },
/*VOP_RelativeStuff*/ new Uop[] { Uop.RelBranch_Stage3, Uop.End_BranchSpecial },
/*VOP_RelativeStuff*/ new Uop[] { Uop.RelBranch_Stage3 },
/*VOP_RelativeStuff2*/ new Uop[] { Uop.RelBranch_Stage4, Uop.End },
/*VOP_RelativeStuff2*/ new Uop[] { Uop.End_SuppressInterrupt },
/*VOP_RelativeStuff3*/ new Uop[] { Uop.End_SuppressInterrupt },
//i assume these are dummy fetches.... maybe theyre just nops? supposedly these take 7 cycles so that's the only way i can make sense of it
//one of them might be the next instruction's fetch, and whatever fetch follows it.
//the interrupt would then take place if necessary, using a cached PC. but im not so sure about that.
@ -316,6 +316,8 @@ namespace BizHawk.Emulation.Cores.Components.M6502
/*VOP_IRQ*/ new Uop[] { Uop.FetchDummy, Uop.FetchDummy, Uop.PushPCH, Uop.PushPCL, Uop.PushP_IRQ, Uop.FetchPCLVector, Uop.FetchPCHVector, Uop.End_SuppressInterrupt },
/*VOP_RESET*/ new Uop[] { Uop.FetchDummy, /*Uop.FetchDummy,*/ Uop.FetchDummy, Uop.PushDummy, Uop.PushDummy, Uop.PushP_Reset, Uop.FetchPCLVector, Uop.FetchPCHVector, Uop.End_SuppressInterrupt },
/*VOP_Fetch1_NoInterrupt*/ new Uop[] { Uop.Fetch1_Real },
/*VOP_Relative_Aux1*/ new Uop[] { Uop.RelBranch_Aux1 },
/*VOP_Relative_Aux2*/ new Uop[] { Uop.FetchDummy, Uop.End }
};
/*
@ -465,10 +467,11 @@ namespace BizHawk.Emulation.Cores.Components.M6502
End,
End_ISpecial, //same as end, but preserves the iflag set by the instruction
End_BranchSpecial,
End_SuppressInterrupt,
Jam,
RelBranch_Aux1, RelBranch_Aux2
}
private void InitOpcodeHandlers()
@ -496,7 +499,7 @@ namespace BizHawk.Emulation.Cores.Components.M6502
// AbsInd_JMP_Stage4, AbsInd_JMP_Stage5,IndIdx_Stage3, IndIdx_Stage4, IndIdx_READ_Stage5, IndIdx_WRITE_Stage5,
// IndIdx_WRITE_Stage6_STA, IndIdx_WRITE_Stage6_SHA,IndIdx_READ_Stage6_LDA, IndIdx_READ_Stage6_CMP, IndIdx_READ_Stage6_ORA, IndIdx_READ_Stage6_SBC, IndIdx_READ_Stage6_ADC, IndIdx_READ_Stage6_AND, IndIdx_READ_Stage6_EOR,
// IndIdx_READ_Stage6_LAX,IndIdx_RMW_Stage5,IndIdx_RMW_Stage6, IndIdx_RMW_Stage7_SLO, IndIdx_RMW_Stage7_RLA, IndIdx_RMW_Stage7_SRE, IndIdx_RMW_Stage7_RRA, IndIdx_RMW_Stage7_ISC, IndIdx_RMW_Stage7_DCP,IndIdx_RMW_Stage8,
// End,End_ISpecial,End_BranchSpecial,End_SuppressInterrupt,
// End,End_ISpecial,End_SuppressInterrupt,
//};
}
@ -508,7 +511,9 @@ namespace BizHawk.Emulation.Cores.Components.M6502
private const int VOP_IRQ = 261;
private const int VOP_RESET = 262;
private const int VOP_Fetch1_NoInterrupt = 263;
private const int VOP_NUM = 264;
private const int VOP_Relative_Aux1 = 264;
private const int VOP_Relative_Aux2 = 265;
private const int VOP_NUM = 266;
//opcode bytes.. theoretically redundant with the temp variables? who knows.
public int opcode;
@ -524,7 +529,7 @@ namespace BizHawk.Emulation.Cores.Components.M6502
private bool interrupt_pending;
private bool branch_irq_hack; //see Uop.RelBranch_Stage3 for more details
private bool Interrupted => RDY && (NMI || (IRQ && !FlagI));
private bool Interrupted => NMI || (IRQ && !FlagI);
private void FetchDummy()
{
@ -1205,27 +1210,43 @@ namespace BizHawk.Emulation.Cores.Components.M6502
}
private void RelBranch_Stage3()
{
alu_temp = (byte)PC + (int)(sbyte)opcode2;
PC &= 0xFF00;
PC |= (ushort)((alu_temp & 0xFF));
if (alu_temp.Bit(8))
{
opcode = VOP_Relative_Aux1;
mi = 0;
RelBranch_Aux1();
}
else
{
//to pass cpu_interrupts_v2/5-branch_delays_irq we need to handle a quirk here
//if we decide to interrupt in the next cycle, this condition will cause it to get deferred by one instruction
if (!interrupt_pending)
branch_irq_hack = true;
opcode = VOP_Relative_Aux2;
mi = 0;
FetchDummy();
//if (!RDY) { Console.WriteLine("not rdy " + TotalExecutedCycles);}
}
}
private void RelBranch_Aux1()
{
rdy_freeze = !RDY;
if (RDY)
{
_link.DummyReadMemory(PC);
alu_temp = (byte)PC + (int)(sbyte)opcode2;
PC &= 0xFF00;
PC |= (ushort)((alu_temp & 0xFF));
if (alu_temp.Bit(8))
{
//we need to carry the add, and then we'll be ready to fetch the next instruction
opcode = VOP_RelativeStuff2;
mi = -1;
}
else
{
//to pass cpu_interrupts_v2/5-branch_delays_irq we need to handle a quirk here
//if we decide to interrupt in the next cycle, this condition will cause it to get deferred by one instruction
if (!interrupt_pending)
branch_irq_hack = true;
}
opcode = VOP_RelativeStuff2;
mi = -1;
}
}
@ -3121,8 +3142,8 @@ namespace BizHawk.Emulation.Cores.Components.M6502
case Uop.End_ISpecial: End_ISpecial(); break;
case Uop.End_SuppressInterrupt: End_SuppressInterrupt(); break;
case Uop.End: End(); break;
case Uop.End_BranchSpecial: End_BranchSpecial(); break;
case Uop.Jam: Jam(); break;
case Uop.RelBranch_Aux1: RelBranch_Aux1(); break;
}
}

View File

@ -1195,8 +1195,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public void NESHardReset()
{
// "at power on it is as if $00 was written to $4017 9-12 cycles before the reset vector"
// that translates to a starting value for the counter of -3
sequencer_counter = -1;
// DMC seems to run for a couple cycles after reset, so aim for the upper end of that range (12)
sequencer_counter = 2;
sequencer_check_1 = (sequencer_lut[0][1] - 1);
@ -1339,7 +1339,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
// the current code simply matches known behaviour
if (pending_reg != -1)
{
if ( pending_reg == 0x4003 || pending_reg == 0x4007 || pending_reg == 0x4015 || pending_reg == 0x4017)
if ( pending_reg == 0x4003 || pending_reg == 0x4007 || pending_reg == 0x4010 || pending_reg == 0x4015 || pending_reg == 0x4017)
{
_WriteReg(pending_reg, pending_val);
pending_reg = -1;