mirror of https://github.com/snes9xgit/snes9x.git
Different IRQ handling.
This commit is contained in:
parent
aaae363257
commit
f6864c422f
3
cpu.cpp
3
cpu.cpp
|
@ -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
|
||||||
|
|
11
cpuexec.cpp
11
cpuexec.cpp
|
@ -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();
|
||||||
|
|
||||||
|
|
42
cpuexec.h
42
cpuexec.h
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
2
dma.cpp
2
dma.cpp
|
@ -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];
|
||||||
|
|
4
getset.h
4
getset.h
|
@ -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
72
ppu.cpp
|
@ -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
2
ppu.h
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
1
snes9x.h
1
snes9x.h
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue