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.NMIPending = FALSE;
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
CPU.IRQLastState = FALSE;
CPU.IRQExternal = FALSE;
CPU.IRQPending = Timings.IRQPendCount;
CPU.MemSpeed = SLOW_ONE_CYCLE;
@ -268,6 +266,7 @@ static void S9xSoftResetCPU (void)
Timings.H_Max = Timings.H_Max_Master;
Timings.V_Max = Timings.V_Max_Master;
Timings.NMITriggerPos = 0xffff;
Timings.NextTimer = 0xffff;
if (Model->_5A22 == 2)
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2;
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)
CPU.IRQPending--;
@ -241,7 +241,7 @@ void S9xMainLoop (void)
Registers.PCw++;
}
CPU.IRQTransition = FALSE;
S9xUpdateIRQPositions();
CPU.IRQPending = Timings.IRQPendCount;
if (!CheckFlag(IRQ))
@ -288,9 +288,7 @@ void S9xMainLoop (void)
if (CPU.PCBase)
{
Op = CPU.PCBase[Registers.PCw];
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += CPU.MemSpeed;
S9xCheckInterrupts();
Opcodes = ICPU.S9xOpcodes;
}
else
@ -414,9 +412,10 @@ void S9xDoHEventProcessing (void)
S9xAPUEndScanline();
CPU.Cycles -= Timings.H_Max;
CPU.PrevCycles -= Timings.H_Max;
if (Timings.NMITriggerPos != 0xffff)
Timings.NMITriggerPos -= Timings.H_Max;
if (Timings.NextTimer != 0xffff)
Timings.NextTimer -= Timings.H_Max;
S9xAPUSetReferenceTime(CPU.Cycles);
CPU.V_Counter++;
@ -557,9 +556,7 @@ void S9xDoHEventProcessing (void)
S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles);
#endif
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
S9xCheckInterrupts();
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

View File

@ -205,7 +205,7 @@
#ifdef SA1_OPCODES
#define AddCycles(n) { SA1.Cycles += (n); }
#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
#include "cpuaddr.h"

View File

@ -200,7 +200,7 @@
#include "missing.h"
#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 int HDMA_ModeByteCounts[8];

View File

@ -206,9 +206,7 @@
#define addCyclesInMemoryAccess \
if (!CPU.InDMAorHDMA) \
{ \
CPU.PrevCycles = CPU.Cycles; \
CPU.Cycles += speed; \
S9xCheckInterrupts(); \
while (CPU.Cycles >= CPU.NextEvent) \
S9xDoHEventProcessing(); \
}
@ -216,9 +214,7 @@
#define addCyclesInMemoryAccess_x2 \
if (!CPU.InDMAorHDMA) \
{ \
CPU.PrevCycles = CPU.Cycles; \
CPU.Cycles += speed << 1; \
S9xCheckInterrupts(); \
while (CPU.Cycles >= CPU.NextEvent) \
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;
if (Timings.H_Max == Timings.H_Max_Master) // 1364
@ -291,6 +327,16 @@ void S9xUpdateHVTimerPosition (void)
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
S9xTraceFormattedMessage("--- IRQ Timer set HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
@ -1502,14 +1548,10 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
else
PPU.HTimerEnabled = FALSE;
if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
CPU.IRQTransition = TRUE;
if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
{
if (!(Byte & 0x10) && !(Byte & 0x20))
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
}
S9xUpdateIRQPositions();
// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
@ -1576,7 +1618,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQHBeamPos;
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
if (PPU.IRQHBeamPos != pos)
S9xUpdateHVTimerPosition();
S9xUpdateIRQPositions();
#ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos;
#endif
@ -1586,7 +1628,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQHBeamPos;
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
if (PPU.IRQHBeamPos != pos)
S9xUpdateHVTimerPosition();
S9xUpdateIRQPositions();
#ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos;
#endif
@ -1596,7 +1638,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQVBeamPos;
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
if (PPU.IRQVBeamPos != pos)
S9xUpdateHVTimerPosition();
S9xUpdateIRQPositions();
#ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos;
#endif
@ -1606,7 +1648,7 @@ if (Settings.TraceHCEvent)
pos = PPU.IRQVBeamPos;
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
if (PPU.IRQVBeamPos != pos)
S9xUpdateHVTimerPosition();
S9xUpdateIRQPositions();
#ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos;
#endif
@ -1617,9 +1659,7 @@ if (Settings.TraceHCEvent)
return;
// XXX: Not quite right...
if (Byte) {
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += Timings.DMACPUSync;
S9xCheckInterrupts();
CPU.Cycles += Timings.DMACPUSync;
}
if (Byte & 0x01)
S9xDoDMA(0);
@ -1795,7 +1835,7 @@ uint8 S9xGetCPU (uint16 Address)
case 0x4211: // TIMEUP
byte = CPU.IRQLine ? 0x80 : 0;
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
S9xUpdateIRQPositions();
return (byte | (OpenBus & 0x7f));

2
ppu.h
View File

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

View File

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

View File

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