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; gsVideoMode = mode;
UpdateVSyncRate(); UpdateVSyncRate();
CSRreg.FIELD = 1;
} }
// Make sure framelimiter options are in sync with GS capabilities. // 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.Reset(true); // Don't think gif should be reset...
gifUnit.gsSIGNAL.queued = false; gifUnit.gsSIGNAL.queued = false;
GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0); GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0);
const u32 field = CSRreg.FIELD;
CSRreg.Reset(); CSRreg.Reset();
GSIMR.reset(); GSIMR.reset();
CSRreg.FIELD = field;
} }
if(csr.FLUSH) if(csr.FLUSH)
@ -326,19 +328,20 @@ __fi u16 gsRead16(u32 mem)
case GS_SIGLBLID: case GS_SIGLBLID:
return *(u16*)PS2GS_BASE(mem); return *(u16*)PS2GS_BASE(mem);
default: // Only SIGLBLID and CSR are readable, everything else mirrors CSR 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) __fi u32 gsRead32(u32 mem)
{ {
GIF_LOG("GS read 32 from %8.8lx value: %8.8lx", mem, *(u32*)PS2GS_BASE(mem)); GIF_LOG("GS read 32 from %8.8lx value: %8.8lx", mem, *(u32*)PS2GS_BASE(mem));
switch (mem & ~0xF) switch (mem & ~0xF)
{ {
case GS_SIGLBLID: case GS_SIGLBLID:
return *(u32*)PS2GS_BASE(mem); return *(u32*)PS2GS_BASE(mem);
default: // Only SIGLBLID and CSR are readable, everything else mirrors CSR 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)) // 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) ); 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) switch (mem & ~0xF)
{ {
case GS_SIGLBLID: case GS_SIGLBLID:
return *(u64*)PS2GS_BASE(mem); return *(u64*)PS2GS_BASE(mem);
default: // Only SIGLBLID and CSR are readable, everything else mirrors CSR 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) 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 if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic && (m_regs->SMODE2.FFMD)) // Auto interlace enabled / Odd frame interlace setting
{ {
int field2 = 0; constexpr int field2 = 1;
int mode = 2; constexpr int mode = 2;
g_gs_device->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); g_gs_device->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y);
} }
else else
{ {
bool scanmask = (m_scanmask_used && scanmsk_frame) && GSConfig.InterlaceMode == GSInterlaceMode::Automatic; const int field2 = scanmask ? 0 : 1 - ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1);
int field2 = 1 - ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1); const int offset = tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y;
int mode = scanmask ? 2 : (static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1; // -1 = None
g_gs_device->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); // 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(); g_gs_device->AgePool();
const bool blank_frame = !Merge(field ? 1 : 0); const bool blank_frame = !Merge(field);
const bool skip_frame = m_frameskip; const bool skip_frame = m_frameskip;
if (blank_frame || skip_frame) if (blank_frame || skip_frame)

View File

@ -441,7 +441,7 @@ void SysMtgsThread::ExecuteTaskInThread()
((GSRegSIGBLID&)RingBuffer.Regs[0x1080]) = (GSRegSIGBLID&)remainder[2]; ((GSRegSIGBLID&)RingBuffer.Regs[0x1080]) = (GSRegSIGBLID&)remainder[2];
// CSR & 0x2000; is the pageflip id. // 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(); gsFrameSkip();
m_QueuedFrameCount.fetch_sub(1); m_QueuedFrameCount.fetch_sub(1);

View File

@ -768,7 +768,7 @@ void Dialogs::GSDumpDialog::ProcessDumpEvent(const GSDumpFile::GSData& event, u8
} }
case GSType::VSync: 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++; g_FrameCount++;
break; break;
} }