Different IRQ handling.

This commit is contained in:
Brandon Wright 2018-05-18 14:53:27 -05:00
parent aaae363257
commit f6864c422f
10 changed files with 66 additions and 74 deletions

View File

@ -229,8 +229,6 @@ static void S9xSoftResetCPU (void)
CPU.PCBase = NULL; CPU.PCBase = NULL;
CPU.NMIPending = FALSE; CPU.NMIPending = FALSE;
CPU.IRQLine = FALSE; CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
CPU.IRQLastState = FALSE;
CPU.IRQExternal = FALSE; CPU.IRQExternal = FALSE;
CPU.IRQPending = Timings.IRQPendCount; CPU.IRQPending = Timings.IRQPendCount;
CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeed = SLOW_ONE_CYCLE;
@ -268,6 +266,7 @@ static void S9xSoftResetCPU (void)
Timings.H_Max = Timings.H_Max_Master; Timings.H_Max = Timings.H_Max_Master;
Timings.V_Max = Timings.V_Max_Master; Timings.V_Max = Timings.V_Max_Master;
Timings.NMITriggerPos = 0xffff; Timings.NMITriggerPos = 0xffff;
Timings.NextTimer = 0xffff;
if (Model->_5A22 == 2) if (Model->_5A22 == 2)
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2;
else else

View File

@ -229,7 +229,7 @@ void S9xMainLoop (void)
} }
} }
if (CPU.IRQTransition || CPU.IRQExternal) if (CPU.Cycles >= Timings.NextTimer || CPU.IRQExternal)
{ {
if (CPU.IRQPending) if (CPU.IRQPending)
CPU.IRQPending--; CPU.IRQPending--;
@ -241,7 +241,7 @@ void S9xMainLoop (void)
Registers.PCw++; Registers.PCw++;
} }
CPU.IRQTransition = FALSE; S9xUpdateIRQPositions();
CPU.IRQPending = Timings.IRQPendCount; CPU.IRQPending = Timings.IRQPendCount;
if (!CheckFlag(IRQ)) if (!CheckFlag(IRQ))
@ -288,9 +288,7 @@ void S9xMainLoop (void)
if (CPU.PCBase) if (CPU.PCBase)
{ {
Op = CPU.PCBase[Registers.PCw]; Op = CPU.PCBase[Registers.PCw];
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += CPU.MemSpeed; CPU.Cycles += CPU.MemSpeed;
S9xCheckInterrupts();
Opcodes = ICPU.S9xOpcodes; Opcodes = ICPU.S9xOpcodes;
} }
else else
@ -414,9 +412,10 @@ void S9xDoHEventProcessing (void)
S9xAPUEndScanline(); S9xAPUEndScanline();
CPU.Cycles -= Timings.H_Max; CPU.Cycles -= Timings.H_Max;
CPU.PrevCycles -= Timings.H_Max;
if (Timings.NMITriggerPos != 0xffff) if (Timings.NMITriggerPos != 0xffff)
Timings.NMITriggerPos -= Timings.H_Max; Timings.NMITriggerPos -= Timings.H_Max;
if (Timings.NextTimer != 0xffff)
Timings.NextTimer -= Timings.H_Max;
S9xAPUSetReferenceTime(CPU.Cycles); S9xAPUSetReferenceTime(CPU.Cycles);
CPU.V_Counter++; CPU.V_Counter++;
@ -557,9 +556,7 @@ void S9xDoHEventProcessing (void)
S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles);
#endif #endif
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
S9xCheckInterrupts();
S9xReschedule(); S9xReschedule();

View File

@ -287,46 +287,4 @@ static inline void S9xFixCycles (void)
} }
} }
static inline void S9xCheckInterrupts (void)
{
bool8 thisIRQ = PPU.HTimerEnabled | PPU.VTimerEnabled;
if (CPU.IRQLine & thisIRQ)
CPU.IRQTransition = TRUE;
if (PPU.HTimerEnabled)
{
int32 htimepos = PPU.HTimerPosition;
if ((CPU.Cycles >= Timings.H_Max) & (htimepos < CPU.PrevCycles))
htimepos += Timings.H_Max;
if ((CPU.PrevCycles >= htimepos) | (CPU.Cycles < htimepos))
thisIRQ = FALSE;
}
if (PPU.VTimerEnabled)
{
int32 vcounter = CPU.V_Counter;
if ((CPU.Cycles >= Timings.H_Max) & ((!PPU.HTimerEnabled) | (PPU.HTimerPosition < CPU.PrevCycles))) {
vcounter++;
if(vcounter >= Timings.V_Max)
vcounter = 0;
}
if (vcounter != PPU.VTimerPosition)
thisIRQ = FALSE;
}
if ((!CPU.IRQLastState) & thisIRQ)
{
#ifdef DEBUGGER
S9xTraceFormattedMessage("--- /IRQ High->Low prev HC:%04d curr HC:%04d HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
CPU.PrevCycles, CPU.Cycles, PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
#endif
CPU.IRQLine = TRUE;
}
CPU.IRQLastState = thisIRQ;
}
#endif #endif

View File

@ -205,7 +205,7 @@
#ifdef SA1_OPCODES #ifdef SA1_OPCODES
#define AddCycles(n) { SA1.Cycles += (n); } #define AddCycles(n) { SA1.Cycles += (n); }
#else #else
#define AddCycles(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } #define AddCycles(n) { CPU.Cycles += (n); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
#endif #endif
#include "cpuaddr.h" #include "cpuaddr.h"

View File

@ -200,7 +200,7 @@
#include "missing.h" #include "missing.h"
#endif #endif
#define ADD_CYCLES(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); } #define ADD_CYCLES(n) { CPU.Cycles += (n); }
extern uint8 *HDMAMemPointers[8]; extern uint8 *HDMAMemPointers[8];
extern int HDMA_ModeByteCounts[8]; extern int HDMA_ModeByteCounts[8];

View File

@ -206,9 +206,7 @@
#define addCyclesInMemoryAccess \ #define addCyclesInMemoryAccess \
if (!CPU.InDMAorHDMA) \ if (!CPU.InDMAorHDMA) \
{ \ { \
CPU.PrevCycles = CPU.Cycles; \
CPU.Cycles += speed; \ CPU.Cycles += speed; \
S9xCheckInterrupts(); \
while (CPU.Cycles >= CPU.NextEvent) \ while (CPU.Cycles >= CPU.NextEvent) \
S9xDoHEventProcessing(); \ S9xDoHEventProcessing(); \
} }
@ -216,9 +214,7 @@
#define addCyclesInMemoryAccess_x2 \ #define addCyclesInMemoryAccess_x2 \
if (!CPU.InDMAorHDMA) \ if (!CPU.InDMAorHDMA) \
{ \ { \
CPU.PrevCycles = CPU.Cycles; \
CPU.Cycles += speed << 1; \ CPU.Cycles += speed << 1; \
S9xCheckInterrupts(); \
while (CPU.Cycles >= CPU.NextEvent) \ while (CPU.Cycles >= CPU.NextEvent) \
S9xDoHEventProcessing(); \ S9xDoHEventProcessing(); \
} }

72
ppu.cpp
View File

@ -269,7 +269,43 @@ static inline void S9xTryGunLatch (bool force)
} }
} }
void S9xUpdateHVTimerPosition (void) static int CyclesUntilNext (int hc, int vc)
{
int32 total = 0;
int vpos = CPU.V_Counter;
// Advance to next hc
total = (hc - CPU.Cycles);
if (total < 0)
{
total += Timings.H_Max;
vpos++;
}
if (vc - vpos >= 0)
{
// It's still in this frame */
// Add number of lines
total += (vc - vpos) * Timings.H_Max;
// If line 240 is in there and we're odd, subtract a dot
if (vpos <= 240 && vc > 240 && Timings.InterlaceField)
total -= ONE_DOT_CYCLE;
}
else
{
total += (Timings.V_Max - vpos) * Timings.H_Max;
if (vpos <= 240 && Timings.InterlaceField)
total -= ONE_DOT_CYCLE;
total += (vc) * Timings.H_Max;
if (vc > 240 && !Timings.InterlaceField)
total -= ONE_DOT_CYCLE;
}
return total;
}
void S9xUpdateIRQPositions (void)
{ {
PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles; PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
if (Timings.H_Max == Timings.H_Max_Master) // 1364 if (Timings.H_Max == Timings.H_Max_Master) // 1364
@ -291,6 +327,16 @@ void S9xUpdateHVTimerPosition (void)
PPU.VTimerPosition = 0; PPU.VTimerPosition = 0;
} }
if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
{
Timings.NextTimer = 0xffff;
}
else
{
Timings.NextTimer =
CyclesUntilNext (PPU.HTimerEnabled ? PPU.HTimerPosition : 0,
PPU.VTimerEnabled ? PPU.VTimerPosition : 0);
}
#ifdef DEBUGGER #ifdef DEBUGGER
S9xTraceFormattedMessage("--- IRQ Timer set HTimer:%d Pos:%04d VTimer:%d Pos:%03d", S9xTraceFormattedMessage("--- IRQ Timer set HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition); PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
@ -1502,14 +1548,10 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
else else
PPU.HTimerEnabled = FALSE; PPU.HTimerEnabled = FALSE;
if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled) if (!(Byte & 0x10) && !(Byte & 0x20))
CPU.IRQTransition = TRUE;
if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
{
CPU.IRQLine = FALSE; CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
} S9xUpdateIRQPositions();
// 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) &&
@ -1576,7 +1618,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)
S9xUpdateHVTimerPosition(); S9xUpdateIRQPositions();
#ifdef DEBUGGER #ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos; missing.hirq_pos = PPU.IRQHBeamPos;
#endif #endif
@ -1586,7 +1628,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)
S9xUpdateHVTimerPosition(); S9xUpdateIRQPositions();
#ifdef DEBUGGER #ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos; missing.hirq_pos = PPU.IRQHBeamPos;
#endif #endif
@ -1596,7 +1638,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)
S9xUpdateHVTimerPosition(); S9xUpdateIRQPositions();
#ifdef DEBUGGER #ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos; missing.virq_pos = PPU.IRQVBeamPos;
#endif #endif
@ -1606,7 +1648,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)
S9xUpdateHVTimerPosition(); S9xUpdateIRQPositions();
#ifdef DEBUGGER #ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos; missing.virq_pos = PPU.IRQVBeamPos;
#endif #endif
@ -1617,9 +1659,7 @@ if (Settings.TraceHCEvent)
return; return;
// XXX: Not quite right... // XXX: Not quite right...
if (Byte) { if (Byte) {
CPU.PrevCycles = CPU.Cycles; CPU.Cycles += Timings.DMACPUSync;
CPU.Cycles += Timings.DMACPUSync;
S9xCheckInterrupts();
} }
if (Byte & 0x01) if (Byte & 0x01)
S9xDoDMA(0); S9xDoDMA(0);
@ -1795,7 +1835,7 @@ uint8 S9xGetCPU (uint16 Address)
case 0x4211: // TIMEUP case 0x4211: // TIMEUP
byte = CPU.IRQLine ? 0x80 : 0; byte = CPU.IRQLine ? 0x80 : 0;
CPU.IRQLine = FALSE; CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE; S9xUpdateIRQPositions();
return (byte | (OpenBus & 0x7f)); return (byte | (OpenBus & 0x7f));

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 S9xUpdateHVTimerPosition (void); void S9xUpdateIRQPositions (void);
void S9xFixColourBrightness (void); void S9xFixColourBrightness (void);
void S9xDoAutoJoypad (void); void S9xDoAutoJoypad (void);

View File

@ -1780,6 +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();
S9xFixCycles(); S9xFixCycles();
for (int d = 0; d < 8; d++) for (int d = 0; d < 8; d++)

View File

@ -346,6 +346,7 @@ struct STimings
int32 HDMAInit; int32 HDMAInit;
int32 HDMAStart; int32 HDMAStart;
int32 NMITriggerPos; int32 NMITriggerPos;
int32 NextTimer;
int32 IRQTriggerCycles; int32 IRQTriggerCycles;
int32 WRAMRefreshPos; int32 WRAMRefreshPos;
int32 RenderPos; int32 RenderPos;