Go back to allowing writes to 4200 and vtimerpos to trigger immediately.

This commit is contained in:
Brandon Wright 2018-06-02 18:44:13 -05:00
parent 7d5128d294
commit 756f370021
4 changed files with 32 additions and 28 deletions

View File

@ -245,11 +245,11 @@ void S9xMainLoop (void)
if ((CPU.Cycles >= Timings.NextIRQTimer)) if ((CPU.Cycles >= Timings.NextIRQTimer))
{ {
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(false);
#ifdef DEBUGGER #ifdef DEBUGGER
S9xTraceMessage ("Timer triggered\n"); S9xTraceMessage ("Timer triggered\n");
#endif #endif
if (CPU.WaitingForInterrupt) if (CPU.WaitingForInterrupt)
{ {

50
ppu.cpp
View File

@ -285,7 +285,7 @@ static int CyclesUntilNext (int hc, int vc)
} }
else else
{ {
if (vc == vpos && (hc > CPU.Cycles || !PPU.HTimerEnabled)) if (vc == vpos && (hc > CPU.Cycles))
{ {
return hc; return hc;
} }
@ -304,7 +304,7 @@ static int CyclesUntilNext (int hc, int vc)
return total; return total;
} }
void S9xUpdateIRQPositions () void S9xUpdateIRQPositions (bool initial)
{ {
PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles; PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
PPU.HTimerPosition -= PPU.IRQHBeamPos ? 0 : ONE_DOT_CYCLE; PPU.HTimerPosition -= PPU.IRQHBeamPos ? 0 : ONE_DOT_CYCLE;
@ -336,7 +336,10 @@ void S9xUpdateIRQPositions ()
} }
else if (!PPU.HTimerEnabled && PPU.VTimerEnabled) else if (!PPU.HTimerEnabled && PPU.VTimerEnabled)
{ {
Timings.NextIRQTimer = CyclesUntilNext (Timings.IRQTriggerCycles, PPU.VTimerPosition); if (CPU.V_Counter == PPU.VTimerPosition && initial)
Timings.NextIRQTimer = CPU.Cycles + Timings.IRQTriggerCycles;
else
Timings.NextIRQTimer = CyclesUntilNext (Timings.IRQTriggerCycles, PPU.VTimerPosition);
} }
else else
{ {
@ -1545,15 +1548,17 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
case 0x4200: // NMITIMEN case 0x4200: // NMITIMEN
#ifdef DEBUGGER #ifdef DEBUGGER
if (Settings.TraceHCEvent) if (Settings.TraceHCEvent)
S9xTraceFormattedMessage("Write to 0x4200. Byte is %2x was %2x\n", Byte, Memory.FillRAM[Address]); S9xTraceFormattedMessage("Write to 0x4200. Byte is %2x was %2x\n", Byte, Memory.FillRAM[Address]);
#endif #endif
if (Byte & 0x20) if (Byte & 0x20)
{ {
PPU.VTimerEnabled = TRUE; PPU.VTimerEnabled = TRUE;
#ifdef DEBUGGER
#ifdef DEBUGGER
missing.virq = 1; missing.virq = 1;
missing.virq_pos = PPU.IRQVBeamPos; missing.virq_pos = PPU.IRQVBeamPos;
#endif #endif
} }
else else
PPU.VTimerEnabled = FALSE; PPU.VTimerEnabled = FALSE;
@ -1561,10 +1566,11 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
if (Byte & 0x10) if (Byte & 0x10)
{ {
PPU.HTimerEnabled = TRUE; PPU.HTimerEnabled = TRUE;
#ifdef DEBUGGER
#ifdef DEBUGGER
missing.hirq = 1; missing.hirq = 1;
missing.hirq_pos = PPU.IRQHBeamPos; missing.hirq_pos = PPU.IRQHBeamPos;
#endif #endif
} }
else else
PPU.HTimerEnabled = FALSE; PPU.HTimerEnabled = FALSE;
@ -1575,29 +1581,27 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
CPU.IRQTransition = FALSE; CPU.IRQTransition = FALSE;
} }
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(true);
// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard. // NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
(CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80)) (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80))
{ {
// FIXME: triggered at HC+=6, checked just before the final CPU cycle, // FIXME: triggered at HC+=6, checked just before the final CPU cycle,
// then, when to call S9xOpcode_NMI()? // then, when to call S9xOpcode_NMI()?
CPU.NMIPending = TRUE; CPU.NMIPending = TRUE;
Timings.NMITriggerPos = CPU.Cycles + 6 + 6; Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
#ifdef DEBUGGER #ifdef DEBUGGER
if (Settings.TraceHCEvent) if (Settings.TraceHCEvent)
S9xTraceFormattedMessage("NMI Triggered on low-to-high occurring at next HC=%d\n", Timings.NMITriggerPos); S9xTraceFormattedMessage("NMI Triggered on low-to-high occurring at next HC=%d\n", Timings.NMITriggerPos);
#endif #endif
} }
#ifdef DEBUGGER #ifdef DEBUGGER
S9xTraceFormattedMessage("--- IRQ Timer Enable HTimer:%d Pos:%04d VTimer:%d Pos:%03d", S9xTraceFormattedMessage("--- IRQ Timer Enable HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition); PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
#endif #endif
break; break;
@ -1642,7 +1646,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQHBeamPos; pos = PPU.IRQHBeamPos;
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte; PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
if (PPU.IRQHBeamPos != pos) if (PPU.IRQHBeamPos != pos)
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(false);
#ifdef DEBUGGER #ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos; missing.hirq_pos = PPU.IRQHBeamPos;
#endif #endif
@ -1652,7 +1656,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQHBeamPos; pos = PPU.IRQHBeamPos;
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8); PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
if (PPU.IRQHBeamPos != pos) if (PPU.IRQHBeamPos != pos)
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(false);
#ifdef DEBUGGER #ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos; missing.hirq_pos = PPU.IRQHBeamPos;
#endif #endif
@ -1662,7 +1666,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQVBeamPos; pos = PPU.IRQVBeamPos;
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte; PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
if (PPU.IRQVBeamPos != pos) if (PPU.IRQVBeamPos != pos)
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(true);
#ifdef DEBUGGER #ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos; missing.virq_pos = PPU.IRQVBeamPos;
#endif #endif
@ -1672,7 +1676,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQVBeamPos; pos = PPU.IRQVBeamPos;
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8); PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
if (PPU.IRQVBeamPos != pos) if (PPU.IRQVBeamPos != pos)
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(true);
#ifdef DEBUGGER #ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos; missing.virq_pos = PPU.IRQVBeamPos;
#endif #endif

2
ppu.h
View File

@ -389,7 +389,7 @@ void S9xSetPPU (uint8, uint16);
uint8 S9xGetPPU (uint16); uint8 S9xGetPPU (uint16);
void S9xSetCPU (uint8, uint16); void S9xSetCPU (uint8, uint16);
uint8 S9xGetCPU (uint16); uint8 S9xGetCPU (uint16);
void S9xUpdateIRQPositions (); void S9xUpdateIRQPositions (bool initial);
void S9xFixColourBrightness (void); void S9xFixColourBrightness (void);
void S9xDoAutoJoypad (void); void S9xDoAutoJoypad (void);

View File

@ -1780,7 +1780,7 @@ int S9xUnfreezeFromStream (STREAM stream)
ICPU.ShiftedDB = Registers.DB << 16; ICPU.ShiftedDB = Registers.DB << 16;
S9xSetPCBase(Registers.PBPC); S9xSetPCBase(Registers.PBPC);
S9xUnpackStatus(); S9xUnpackStatus();
S9xUpdateIRQPositions(); S9xUpdateIRQPositions(false);
S9xFixCycles(); S9xFixCycles();
for (int d = 0; d < 8; d++) for (int d = 0; d < 8; d++)