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 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 hRender; // time from hblank end to hblank start (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 Blank = Scanline * (gsVideoMode == GS_VideoMode::NTSC ? 26 : 22);
|
||||
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.
|
||||
// (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
|
||||
//as needed for each scheduled v/hsync related event. Much better to handle than this messed state.
|
||||
info->Framerate = framesPerSecond;
|
||||
info->GSBlank = (u32)(GSBlank / 10000);
|
||||
info->Render = (u32)(Render / 10000);
|
||||
info->Blank = (u32)(Blank / 10000);
|
||||
|
||||
|
@ -454,13 +458,6 @@ static __fi void VSyncStart(u32 sCycle)
|
|||
CpuVU0->Vsync();
|
||||
CpuVU1->Vsync();
|
||||
|
||||
if (!CSRreg.VSINT)
|
||||
{
|
||||
CSRreg.VSINT = true;
|
||||
if (!GSIMR.VSMSK)
|
||||
gsIrq();
|
||||
}
|
||||
|
||||
hwIntcIrq(INTC_VBLANK_S);
|
||||
psxVBlankStart();
|
||||
gsPostVsyncStart();
|
||||
|
@ -486,6 +483,19 @@ static __fi void VSyncStart(u32 sCycle)
|
|||
// 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)
|
||||
{
|
||||
if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll)
|
||||
|
@ -506,8 +516,6 @@ static __fi void VSyncEnd(u32 sCycle)
|
|||
|
||||
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
|
||||
// vsyncstart irq.
|
||||
//cpuRegs.eCycle[30] = 2;
|
||||
|
@ -567,22 +575,27 @@ __fi void rcntUpdate_vSync()
|
|||
vsyncCounter.CycleT = vSyncInfo.Render;
|
||||
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
|
||||
{
|
||||
|
||||
#ifndef DISABLE_RECORDING
|
||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||
{
|
||||
g_RecordingControls.HandleFrameAdvanceAndStop();
|
||||
}
|
||||
#endif
|
||||
|
||||
VSyncStart(vsyncCounter.sCycle);
|
||||
|
||||
|
||||
vsyncCounter.sCycle += vSyncInfo.Render;
|
||||
vsyncCounter.CycleT = vSyncInfo.Blank;
|
||||
vsyncCounter.Mode = MODE_VSYNC;
|
||||
vsyncCounter.CycleT = vSyncInfo.GSBlank;
|
||||
vsyncCounter.Mode = MODE_GSBLANK;
|
||||
|
||||
// Accumulate hsync rounding errors:
|
||||
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
||||
|
|
|
@ -115,6 +115,7 @@ struct SyncCounter
|
|||
//------------------------------------------------------------------
|
||||
#define MODE_VRENDER 0x0 //Set during the Render/Frame 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_VBLANK1 0x0 //Set during the Blanking Scanlines (half-frame 1)
|
||||
#define MODE_VBLANK2 0x1 //Set during the Blanking Scanlines (half-frame 2)
|
||||
|
|
Loading…
Reference in New Issue