mirror of https://github.com/PCSX2/pcsx2.git
GS: Correctly handle field/deinterlace for progressive/interlaced mode.
Also correct the number of scanlines for progressive (double strike) and how long vblank is.
This commit is contained in:
parent
394f1f2049
commit
cf3cfdb2bc
|
@ -78,7 +78,9 @@ static bool IsInterlacedVideoMode()
|
|||
|
||||
static bool IsProgressiveVideoMode()
|
||||
{
|
||||
return (gsVideoMode == GS_VideoMode::VESA || gsVideoMode == GS_VideoMode::SDTV_480P || gsVideoMode == GS_VideoMode::SDTV_576P || gsVideoMode == GS_VideoMode::HDTV_720P || gsVideoMode == GS_VideoMode::HDTV_1080P);
|
||||
// The FIELD register only flips if the CMOD field in SMODE1 is set to anything but 0 and Front Porch bottom bit in SYNCV is set.
|
||||
// Also see "isReallyInterlaced()" in GSState.cpp
|
||||
return !(*(u32*)PS2GS_BASE(GS_SYNCV) & 0x1) || !(*(u32*)PS2GS_BASE(GS_SMODE1) & 0x6000);
|
||||
}
|
||||
|
||||
void rcntReset(int index) {
|
||||
|
@ -231,7 +233,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
|
|||
// Jak II - random speedups
|
||||
// Shadow of Rome - FMV audio issues
|
||||
const u64 HalfFrame = Frame / 2;
|
||||
const u64 Blank = Scanline * (gsVideoMode == GS_VideoMode::NTSC ? 22 : 26);
|
||||
const u64 Blank = Scanline *((gsVideoMode == GS_VideoMode::NTSC ? 22 : 25) + static_cast<int>(gsIsInterlaced));
|
||||
const u64 Render = HalfFrame - Blank;
|
||||
const u64 GSBlank = Scanline * 3.5; // GS VBlank/CSR Swap happens roughly 3.5 Scanlines after VBlank Start
|
||||
|
||||
|
@ -404,23 +406,32 @@ u32 UpdateVSyncRate()
|
|||
switch (gsVideoMode)
|
||||
{
|
||||
case GS_VideoMode::Uninitialized: // SYSCALL instruction hasn't executed yet, give some temporary values.
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC;
|
||||
if(gsIsInterlaced)
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_I;
|
||||
else
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_NI;
|
||||
break;
|
||||
case GS_VideoMode::PAL:
|
||||
case GS_VideoMode::DVD_PAL:
|
||||
custom = (EmuConfig.GS.FrameratePAL != 50.0);
|
||||
total_scanlines = SCANLINES_TOTAL_PAL;
|
||||
if (gsIsInterlaced)
|
||||
total_scanlines = SCANLINES_TOTAL_PAL_I;
|
||||
else
|
||||
total_scanlines = SCANLINES_TOTAL_PAL_NI;
|
||||
break;
|
||||
case GS_VideoMode::NTSC:
|
||||
case GS_VideoMode::DVD_NTSC:
|
||||
custom = (EmuConfig.GS.FramerateNTSC != 59.94);
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC;
|
||||
if (gsIsInterlaced)
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_I;
|
||||
else
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_NI;
|
||||
break;
|
||||
case GS_VideoMode::SDTV_480P:
|
||||
case GS_VideoMode::SDTV_576P:
|
||||
case GS_VideoMode::HDTV_720P:
|
||||
case GS_VideoMode::VESA:
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC;
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_I;
|
||||
break;
|
||||
case GS_VideoMode::HDTV_1080P:
|
||||
case GS_VideoMode::HDTV_1080I:
|
||||
|
@ -428,7 +439,10 @@ u32 UpdateVSyncRate()
|
|||
break;
|
||||
case GS_VideoMode::Unknown:
|
||||
default:
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC;
|
||||
if (gsIsInterlaced)
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_I;
|
||||
else
|
||||
total_scanlines = SCANLINES_TOTAL_NTSC_NI;
|
||||
Console.Error("PCSX2-Counters: Unknown video mode detected");
|
||||
pxAssertDev(false , "Unknown video mode detected via SetGsCrt");
|
||||
}
|
||||
|
@ -728,8 +742,7 @@ __fi void rcntUpdate_hScanline()
|
|||
|
||||
__fi void rcntUpdate_vSync()
|
||||
{
|
||||
s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
|
||||
if( diff < vsyncCounter.CycleT ) return;
|
||||
if (!cpuTestCycle(vsyncCounter.sCycle, vsyncCounter.CycleT)) return;
|
||||
|
||||
if (vsyncCounter.Mode == MODE_VSYNC)
|
||||
{
|
||||
|
|
|
@ -96,7 +96,8 @@ struct SyncCounter
|
|||
//------------------------------------------------------------------
|
||||
#define FRAMERATE_NTSC 29.97 // frames per second
|
||||
|
||||
#define SCANLINES_TOTAL_NTSC 525 // total number of scanlines
|
||||
#define SCANLINES_TOTAL_NTSC_I 525 // total number of scanlines (Interlaced)
|
||||
#define SCANLINES_TOTAL_NTSC_NI 526 // total number of scanlines (Interlaced)
|
||||
#define SCANLINES_VSYNC_NTSC 3 // scanlines that are used for syncing every half-frame
|
||||
#define SCANLINES_VRENDER_NTSC 240 // scanlines in a half-frame (because of interlacing)
|
||||
#define SCANLINES_VBLANK1_NTSC 19 // scanlines used for vblank1 (even interlace)
|
||||
|
@ -107,7 +108,8 @@ struct SyncCounter
|
|||
//------------------------------------------------------------------
|
||||
#define FRAMERATE_PAL 25.0// frames per second * 100 (25)
|
||||
|
||||
#define SCANLINES_TOTAL_PAL 625 // total number of scanlines per frame
|
||||
#define SCANLINES_TOTAL_PAL_I 625 // total number of scanlines per frame (Interlaced)
|
||||
#define SCANLINES_TOTAL_PAL_NI 628 // total number of scanlines per frame (Not Interlaced)
|
||||
#define SCANLINES_VSYNC_PAL 5 // scanlines that are used for syncing every half-frame
|
||||
#define SCANLINES_VRENDER_PAL 288 // scanlines in a half-frame (because of interlacing)
|
||||
#define SCANLINES_VBLANK1_PAL 19 // scanlines used for vblank1 (even interlace)
|
||||
|
|
|
@ -340,6 +340,12 @@ bool GSState::isinterlaced()
|
|||
return !!m_regs->SMODE2.INT;
|
||||
}
|
||||
|
||||
bool GSState::isReallyInterlaced()
|
||||
{
|
||||
// The FIELD register only flips if the CMOD field in SMODE1 is set to anything but 0 and Front Porch bottom bit in SYNCV is set.
|
||||
return (m_regs->SYNCV.VFP & 0x1) && m_regs->SMODE1.CMOD;
|
||||
}
|
||||
|
||||
GSVideoMode GSState::GetVideoMode()
|
||||
{
|
||||
// TODO: Get confirmation of videomode from SYSCALL ? not necessary but would be nice.
|
||||
|
|
|
@ -298,6 +298,7 @@ public:
|
|||
|
||||
bool IsEnabled(int i);
|
||||
bool isinterlaced();
|
||||
bool isReallyInterlaced();
|
||||
bool IsAnalogue();
|
||||
|
||||
float GetTvRefreshRate();
|
||||
|
|
|
@ -337,7 +337,7 @@ bool GSRenderer::Merge(int field)
|
|||
// Offset is not compatible with scanmsk, as scanmsk renders every other line, but at x7 the interlace offset will be 7 lines
|
||||
const int offset = (m_scanmask_used || !m_regs->SMODE2.FFMD) ? 0 : (int)(tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y);
|
||||
|
||||
if (m_regs->SMODE2.INT && GSConfig.InterlaceMode != GSInterlaceMode::Off)
|
||||
if (isReallyInterlaced() && GSConfig.InterlaceMode != GSInterlaceMode::Off)
|
||||
{
|
||||
const bool scanmask = m_scanmask_used && scanmask_frame && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
||||
|
||||
|
|
Loading…
Reference in New Issue