mirror of https://github.com/PCSX2/pcsx2.git
GS/Counters: Fix CSR Swap and VBlank Interrupt timing
This commit is contained in:
parent
197eaf3899
commit
1b6b3f692d
|
@ -182,6 +182,8 @@ struct vSyncTimingInfo
|
||||||
u32 Render; // time from vblank end to vblank start (cycles)
|
u32 Render; // time from vblank end to vblank start (cycles)
|
||||||
u32 Blank; // time from vblank start to vblank end (cycles)
|
u32 Blank; // time from vblank start to vblank end (cycles)
|
||||||
|
|
||||||
|
u32 GSBlank; // GS CSR is swapped roughly 3.5 hblank's after vblank start
|
||||||
|
|
||||||
u32 hSyncError; // rounding error after the duration of a rendered frame (cycles)
|
u32 hSyncError; // rounding error after the duration of a rendered frame (cycles)
|
||||||
u32 hRender; // time from hblank end to hblank start (cycles)
|
u32 hRender; // time from hblank end to hblank start (cycles)
|
||||||
u32 hBlank; // time from hblank start to hblank end (cycles)
|
u32 hBlank; // time from hblank start to hblank end (cycles)
|
||||||
|
@ -210,6 +212,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 s
|
||||||
const u64 HalfFrame = Frame / 2;
|
const u64 HalfFrame = Frame / 2;
|
||||||
const u64 Blank = Scanline * (gsVideoMode == GS_VideoMode::NTSC ? 26 : 22);
|
const u64 Blank = Scanline * (gsVideoMode == GS_VideoMode::NTSC ? 26 : 22);
|
||||||
const u64 Render = HalfFrame - Blank;
|
const u64 Render = HalfFrame - Blank;
|
||||||
|
const u64 GSBlank = Scanline * 3.5; // GS VBlank/CSR Swap happens roughly 3.5 Scanlines after VBlank Start
|
||||||
|
|
||||||
// Important! The hRender/hBlank timers should be 50/50 for best results.
|
// Important! The hRender/hBlank timers should be 50/50 for best results.
|
||||||
// (this appears to be what the real EE's timing crystal does anyway)
|
// (this appears to be what the real EE's timing crystal does anyway)
|
||||||
|
@ -226,6 +229,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 s
|
||||||
//TODO: Carry fixed-point math all the way through the entire vsync and hsync counting processes, and continually apply rounding
|
//TODO: Carry fixed-point math all the way through the entire vsync and hsync counting processes, and continually apply rounding
|
||||||
//as needed for each scheduled v/hsync related event. Much better to handle than this messed state.
|
//as needed for each scheduled v/hsync related event. Much better to handle than this messed state.
|
||||||
info->Framerate = framesPerSecond;
|
info->Framerate = framesPerSecond;
|
||||||
|
info->GSBlank = (u32)(GSBlank / 10000);
|
||||||
info->Render = (u32)(Render / 10000);
|
info->Render = (u32)(Render / 10000);
|
||||||
info->Blank = (u32)(Blank / 10000);
|
info->Blank = (u32)(Blank / 10000);
|
||||||
|
|
||||||
|
@ -454,13 +458,6 @@ static __fi void VSyncStart(u32 sCycle)
|
||||||
CpuVU0->Vsync();
|
CpuVU0->Vsync();
|
||||||
CpuVU1->Vsync();
|
CpuVU1->Vsync();
|
||||||
|
|
||||||
if (!CSRreg.VSINT)
|
|
||||||
{
|
|
||||||
CSRreg.VSINT = true;
|
|
||||||
if (!GSIMR.VSMSK)
|
|
||||||
gsIrq();
|
|
||||||
}
|
|
||||||
|
|
||||||
hwIntcIrq(INTC_VBLANK_S);
|
hwIntcIrq(INTC_VBLANK_S);
|
||||||
psxVBlankStart();
|
psxVBlankStart();
|
||||||
gsPostVsyncStart();
|
gsPostVsyncStart();
|
||||||
|
@ -486,6 +483,19 @@ static __fi void VSyncStart(u32 sCycle)
|
||||||
// Should no longer be required (Refraction)
|
// Should no longer be required (Refraction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __fi void GSVSync()
|
||||||
|
{
|
||||||
|
// CSR is swapped and GS vBlank IRQ is triggered roughly 3.5 hblanks after VSync Start
|
||||||
|
CSRreg.SwapField();
|
||||||
|
|
||||||
|
if (!CSRreg.VSINT)
|
||||||
|
{
|
||||||
|
CSRreg.VSINT = true;
|
||||||
|
if (!GSIMR.VSMSK)
|
||||||
|
gsIrq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static __fi void VSyncEnd(u32 sCycle)
|
static __fi void VSyncEnd(u32 sCycle)
|
||||||
{
|
{
|
||||||
if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
|
if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
|
||||||
|
@ -506,8 +516,6 @@ static __fi void VSyncEnd(u32 sCycle)
|
||||||
|
|
||||||
frameLimit(); // limit FPS
|
frameLimit(); // limit FPS
|
||||||
|
|
||||||
//Do this here, breaks Dynasty Warriors otherwise.
|
|
||||||
CSRreg.SwapField();
|
|
||||||
// This doesn't seem to be needed here. Games only seem to break with regard to the
|
// This doesn't seem to be needed here. Games only seem to break with regard to the
|
||||||
// vsyncstart irq.
|
// vsyncstart irq.
|
||||||
//cpuRegs.eCycle[30] = 2;
|
//cpuRegs.eCycle[30] = 2;
|
||||||
|
@ -567,22 +575,27 @@ __fi void rcntUpdate_vSync()
|
||||||
vsyncCounter.CycleT = vSyncInfo.Render;
|
vsyncCounter.CycleT = vSyncInfo.Render;
|
||||||
vsyncCounter.Mode = MODE_VRENDER;
|
vsyncCounter.Mode = MODE_VRENDER;
|
||||||
}
|
}
|
||||||
|
else if (vsyncCounter.Mode == MODE_GSBLANK) // GS CSR Swap and interrupt
|
||||||
|
{
|
||||||
|
GSVSync();
|
||||||
|
|
||||||
|
vsyncCounter.Mode = MODE_VSYNC;
|
||||||
|
// Don't set the start cycle, makes it easier to calculate the correct Vsync End time
|
||||||
|
vsyncCounter.CycleT = vSyncInfo.Blank;
|
||||||
|
}
|
||||||
else // VSYNC end / VRENDER begin
|
else // VSYNC end / VRENDER begin
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
g_RecordingControls.HandleFrameAdvanceAndStop();
|
g_RecordingControls.HandleFrameAdvanceAndStop();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VSyncStart(vsyncCounter.sCycle);
|
VSyncStart(vsyncCounter.sCycle);
|
||||||
|
|
||||||
|
|
||||||
vsyncCounter.sCycle += vSyncInfo.Render;
|
vsyncCounter.sCycle += vSyncInfo.Render;
|
||||||
vsyncCounter.CycleT = vSyncInfo.Blank;
|
vsyncCounter.CycleT = vSyncInfo.GSBlank;
|
||||||
vsyncCounter.Mode = MODE_VSYNC;
|
vsyncCounter.Mode = MODE_GSBLANK;
|
||||||
|
|
||||||
// Accumulate hsync rounding errors:
|
// Accumulate hsync rounding errors:
|
||||||
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
||||||
|
|
|
@ -115,6 +115,7 @@ struct SyncCounter
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
#define MODE_VRENDER 0x0 //Set during the Render/Frame Scanlines
|
#define MODE_VRENDER 0x0 //Set during the Render/Frame Scanlines
|
||||||
#define MODE_VBLANK 0x1 //Set during the Blanking Scanlines
|
#define MODE_VBLANK 0x1 //Set during the Blanking Scanlines
|
||||||
|
#define MODE_GSBLANK 0x2 //Set during the Syncing Scanlines (Delayed GS CSR Swap)
|
||||||
#define MODE_VSYNC 0x3 //Set during the Syncing Scanlines
|
#define MODE_VSYNC 0x3 //Set during the Syncing Scanlines
|
||||||
#define MODE_VBLANK1 0x0 //Set during the Blanking Scanlines (half-frame 1)
|
#define MODE_VBLANK1 0x0 //Set during the Blanking Scanlines (half-frame 1)
|
||||||
#define MODE_VBLANK2 0x1 //Set during the Blanking Scanlines (half-frame 2)
|
#define MODE_VBLANK2 0x1 //Set during the Blanking Scanlines (half-frame 2)
|
||||||
|
|
Loading…
Reference in New Issue