mirror of https://github.com/PCSX2/pcsx2.git
GS: Improve interlace handling and odd frames
This commit is contained in:
parent
05dab12b7c
commit
38b83af714
12
pcsx2/GS.cpp
12
pcsx2/GS.cpp
|
@ -32,6 +32,7 @@ void gsSetVideoMode(GS_VideoMode mode)
|
|||
{
|
||||
gsVideoMode = mode;
|
||||
UpdateVSyncRate();
|
||||
CSRreg.FIELD = 1;
|
||||
}
|
||||
|
||||
// Make sure framelimiter options are in sync with GS capabilities.
|
||||
|
@ -84,9 +85,10 @@ static __fi void gsCSRwrite( const tGS_CSR& csr )
|
|||
//gifUnit.Reset(true); // Don't think gif should be reset...
|
||||
gifUnit.gsSIGNAL.queued = false;
|
||||
GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0);
|
||||
|
||||
const u32 field = CSRreg.FIELD;
|
||||
CSRreg.Reset();
|
||||
GSIMR.reset();
|
||||
CSRreg.FIELD = field;
|
||||
}
|
||||
|
||||
if(csr.FLUSH)
|
||||
|
@ -326,19 +328,20 @@ __fi u16 gsRead16(u32 mem)
|
|||
case GS_SIGLBLID:
|
||||
return *(u16*)PS2GS_BASE(mem);
|
||||
default: // Only SIGLBLID and CSR are readable, everything else mirrors CSR
|
||||
return *(u16*)PS2GS_BASE(GS_CSR + (mem & 0xF));
|
||||
return *(u16*)PS2GS_BASE(GS_CSR + (mem & 0x7));
|
||||
}
|
||||
}
|
||||
|
||||
__fi u32 gsRead32(u32 mem)
|
||||
{
|
||||
GIF_LOG("GS read 32 from %8.8lx value: %8.8lx", mem, *(u32*)PS2GS_BASE(mem));
|
||||
|
||||
switch (mem & ~0xF)
|
||||
{
|
||||
case GS_SIGLBLID:
|
||||
return *(u32*)PS2GS_BASE(mem);
|
||||
default: // Only SIGLBLID and CSR are readable, everything else mirrors CSR
|
||||
return *(u32*)PS2GS_BASE(GS_CSR + (mem & 0xF));
|
||||
return *(u32*)PS2GS_BASE(GS_CSR + (mem & 0xC));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,12 +349,13 @@ __fi u64 gsRead64(u32 mem)
|
|||
{
|
||||
// fixme - PS2GS_BASE(mem+4) = (g_RealGSMem+(mem + 4 & 0x13ff))
|
||||
GIF_LOG("GS read 64 from %8.8lx value: %8.8lx_%8.8lx", mem, *(u32*)PS2GS_BASE(mem+4), *(u32*)PS2GS_BASE(mem) );
|
||||
|
||||
switch (mem & ~0xF)
|
||||
{
|
||||
case GS_SIGLBLID:
|
||||
return *(u64*)PS2GS_BASE(mem);
|
||||
default: // Only SIGLBLID and CSR are readable, everything else mirrors CSR
|
||||
return *(u64*)PS2GS_BASE(GS_CSR + (mem & 0xF));
|
||||
return *(u64*)PS2GS_BASE(GS_CSR + (mem & 0x8));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -264,18 +264,29 @@ bool GSRenderer::Merge(int field)
|
|||
|
||||
if (m_regs->SMODE2.INT && GSConfig.InterlaceMode != GSInterlaceMode::Off)
|
||||
{
|
||||
const bool scanmask = (m_scanmask_used && scanmsk_frame) && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
||||
|
||||
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic && (m_regs->SMODE2.FFMD)) // Auto interlace enabled / Odd frame interlace setting
|
||||
{
|
||||
int field2 = 0;
|
||||
int mode = 2;
|
||||
constexpr int field2 = 1;
|
||||
constexpr int mode = 2;
|
||||
g_gs_device->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool scanmask = (m_scanmask_used && scanmsk_frame) && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
||||
int field2 = 1 - ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1);
|
||||
int mode = scanmask ? 2 : (static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1;
|
||||
g_gs_device->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y);
|
||||
const int field2 = scanmask ? 0 : 1 - ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1);
|
||||
const int offset = tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y;
|
||||
// -1 = None
|
||||
// 0 = Weave
|
||||
// 1 = Bob
|
||||
// 2 = Blend
|
||||
int mode = scanmask ? 2 : std::clamp((static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1, -1, 2);
|
||||
|
||||
// If we're on auto, prefer no interlacing (bob, kinda), unless there is an offset or scanmsk, then retain blend
|
||||
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic && !(m_regs->SMODE2.FFMD) && !scanmask && !offset)
|
||||
mode = -1;
|
||||
|
||||
g_gs_device->Interlace(ds, field ^ field2, mode, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,7 +440,7 @@ void GSRenderer::VSync(u32 field, bool registers_written)
|
|||
|
||||
g_gs_device->AgePool();
|
||||
|
||||
const bool blank_frame = !Merge(field ? 1 : 0);
|
||||
const bool blank_frame = !Merge(field);
|
||||
const bool skip_frame = m_frameskip;
|
||||
|
||||
if (blank_frame || skip_frame)
|
||||
|
|
|
@ -441,7 +441,7 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
((GSRegSIGBLID&)RingBuffer.Regs[0x1080]) = (GSRegSIGBLID&)remainder[2];
|
||||
|
||||
// CSR & 0x2000; is the pageflip id.
|
||||
GSvsync(((u32&)RingBuffer.Regs[0x1000]) & 0x2000, remainder[4] != 0);
|
||||
GSvsync((((u32&)RingBuffer.Regs[0x1000]) & 0x2000) ? 0 : 1, remainder[4] != 0);
|
||||
gsFrameSkip();
|
||||
|
||||
m_QueuedFrameCount.fetch_sub(1);
|
||||
|
|
|
@ -768,7 +768,7 @@ void Dialogs::GSDumpDialog::ProcessDumpEvent(const GSDumpFile::GSData& event, u8
|
|||
}
|
||||
case GSType::VSync:
|
||||
{
|
||||
GSvsync((*((int*)(regs + 4096)) & 0x2000) > 0 ? (u8)1 : (u8)0, false);
|
||||
GSvsync((*((int*)(regs + 4096)) & 0x2000) > 0 ? (u8)0 : (u8)1, false);
|
||||
g_FrameCount++;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue