GS: Improve interlace handling and odd frames

This commit is contained in:
refractionpcsx2 2022-03-24 18:28:18 +00:00
parent 05dab12b7c
commit 38b83af714
4 changed files with 28 additions and 13 deletions

View File

@ -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));
}
}

View File

@ -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)

View File

@ -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);

View File

@ -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;
}