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()
|
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) {
|
void rcntReset(int index) {
|
||||||
|
@ -231,7 +233,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
|
||||||
// Jak II - random speedups
|
// Jak II - random speedups
|
||||||
// Shadow of Rome - FMV audio issues
|
// Shadow of Rome - FMV audio issues
|
||||||
const u64 HalfFrame = Frame / 2;
|
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 Render = HalfFrame - Blank;
|
||||||
const u64 GSBlank = Scanline * 3.5; // GS VBlank/CSR Swap happens roughly 3.5 Scanlines after VBlank Start
|
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)
|
switch (gsVideoMode)
|
||||||
{
|
{
|
||||||
case GS_VideoMode::Uninitialized: // SYSCALL instruction hasn't executed yet, give some temporary values.
|
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;
|
break;
|
||||||
case GS_VideoMode::PAL:
|
case GS_VideoMode::PAL:
|
||||||
case GS_VideoMode::DVD_PAL:
|
case GS_VideoMode::DVD_PAL:
|
||||||
custom = (EmuConfig.GS.FrameratePAL != 50.0);
|
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;
|
break;
|
||||||
case GS_VideoMode::NTSC:
|
case GS_VideoMode::NTSC:
|
||||||
case GS_VideoMode::DVD_NTSC:
|
case GS_VideoMode::DVD_NTSC:
|
||||||
custom = (EmuConfig.GS.FramerateNTSC != 59.94);
|
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;
|
break;
|
||||||
case GS_VideoMode::SDTV_480P:
|
case GS_VideoMode::SDTV_480P:
|
||||||
case GS_VideoMode::SDTV_576P:
|
case GS_VideoMode::SDTV_576P:
|
||||||
case GS_VideoMode::HDTV_720P:
|
case GS_VideoMode::HDTV_720P:
|
||||||
case GS_VideoMode::VESA:
|
case GS_VideoMode::VESA:
|
||||||
total_scanlines = SCANLINES_TOTAL_NTSC;
|
total_scanlines = SCANLINES_TOTAL_NTSC_I;
|
||||||
break;
|
break;
|
||||||
case GS_VideoMode::HDTV_1080P:
|
case GS_VideoMode::HDTV_1080P:
|
||||||
case GS_VideoMode::HDTV_1080I:
|
case GS_VideoMode::HDTV_1080I:
|
||||||
|
@ -428,7 +439,10 @@ u32 UpdateVSyncRate()
|
||||||
break;
|
break;
|
||||||
case GS_VideoMode::Unknown:
|
case GS_VideoMode::Unknown:
|
||||||
default:
|
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");
|
Console.Error("PCSX2-Counters: Unknown video mode detected");
|
||||||
pxAssertDev(false , "Unknown video mode detected via SetGsCrt");
|
pxAssertDev(false , "Unknown video mode detected via SetGsCrt");
|
||||||
}
|
}
|
||||||
|
@ -728,8 +742,7 @@ __fi void rcntUpdate_hScanline()
|
||||||
|
|
||||||
__fi void rcntUpdate_vSync()
|
__fi void rcntUpdate_vSync()
|
||||||
{
|
{
|
||||||
s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
|
if (!cpuTestCycle(vsyncCounter.sCycle, vsyncCounter.CycleT)) return;
|
||||||
if( diff < vsyncCounter.CycleT ) return;
|
|
||||||
|
|
||||||
if (vsyncCounter.Mode == MODE_VSYNC)
|
if (vsyncCounter.Mode == MODE_VSYNC)
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,7 +96,8 @@ struct SyncCounter
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
#define FRAMERATE_NTSC 29.97 // frames per second
|
#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_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_VRENDER_NTSC 240 // scanlines in a half-frame (because of interlacing)
|
||||||
#define SCANLINES_VBLANK1_NTSC 19 // scanlines used for vblank1 (even interlace)
|
#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 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_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_VRENDER_PAL 288 // scanlines in a half-frame (because of interlacing)
|
||||||
#define SCANLINES_VBLANK1_PAL 19 // scanlines used for vblank1 (even interlace)
|
#define SCANLINES_VBLANK1_PAL 19 // scanlines used for vblank1 (even interlace)
|
||||||
|
|
|
@ -340,6 +340,12 @@ bool GSState::isinterlaced()
|
||||||
return !!m_regs->SMODE2.INT;
|
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()
|
GSVideoMode GSState::GetVideoMode()
|
||||||
{
|
{
|
||||||
// TODO: Get confirmation of videomode from SYSCALL ? not necessary but would be nice.
|
// TODO: Get confirmation of videomode from SYSCALL ? not necessary but would be nice.
|
||||||
|
|
|
@ -298,6 +298,7 @@ public:
|
||||||
|
|
||||||
bool IsEnabled(int i);
|
bool IsEnabled(int i);
|
||||||
bool isinterlaced();
|
bool isinterlaced();
|
||||||
|
bool isReallyInterlaced();
|
||||||
bool IsAnalogue();
|
bool IsAnalogue();
|
||||||
|
|
||||||
float GetTvRefreshRate();
|
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
|
// 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);
|
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;
|
const bool scanmask = m_scanmask_used && scanmask_frame && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue