gsdx hw: CRC based solution to solve half screen issue on FFVII Dirge Of Cerberus

The trick is that the depth buffer is actually the right of the frame buffer
This commit is contained in:
Gregory Hainaut 2016-09-16 23:57:33 +02:00
parent 07d54587bd
commit 7b9654f164
2 changed files with 64 additions and 0 deletions

View File

@ -787,6 +787,7 @@ GSRendererHW::Hacks::Hacks()
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::SuperManReturns, CRC::RegionCount, &GSRendererHW::OI_SuperManReturns)); m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::SuperManReturns, CRC::RegionCount, &GSRendererHW::OI_SuperManReturns));
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::ArTonelico2, CRC::RegionCount, &GSRendererHW::OI_ArTonelico2)); m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::ArTonelico2, CRC::RegionCount, &GSRendererHW::OI_ArTonelico2));
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::ItadakiStreet, CRC::RegionCount, &GSRendererHW::OI_ItadakiStreet)); m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::ItadakiStreet, CRC::RegionCount, &GSRendererHW::OI_ItadakiStreet));
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::FFVIIDoC, CRC::RegionCount, &GSRendererHW::OI_FFVIIDoC));
if (!can_handle_depth) if (!can_handle_depth)
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::SMTNocturne, CRC::RegionCount, &GSRendererHW::OI_SMTNocturne)); m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::SMTNocturne, CRC::RegionCount, &GSRendererHW::OI_SMTNocturne));
@ -842,6 +843,7 @@ bool GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCac
// like FBW * 64 pixels * ratio / 32 pixels / 2 = FBW * ratio // like FBW * 64 pixels * ratio / 32 pixels / 2 = FBW * ratio
// It is hard to predict the ratio, so I round it to 1. And I use // It is hard to predict the ratio, so I round it to 1. And I use
// <= comparison below. // <= comparison below.
// FIXME: I don't understand anymore what I used it
uint32 h_pages = m_context->FRAME.FBW; uint32 h_pages = m_context->FRAME.FBW;
uint32 base; uint32 base;
@ -869,6 +871,61 @@ bool GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCac
return true; return true;
} }
// Same as above but instead to split the screen in top/bottom. The screen is splitted in left/right
// FIXME: Maybe it could be merged with the above code. The difference is the initial FBW check and the way to compute h_page
// However I'm not sure above code is correct. Let's keep them separately until I managed to test others games impacted by this
// half screen issue.
bool GSRendererHW::OI_DoubleHalfClear_Vertical(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{
// So far only used by FFVII dirge of cerberus
if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME && !m_context->ZBUF.ZMSK && (m_context->FRAME.FBW <= 4) && rt) {
GSVertex* v = &m_vertex.buff[0];
//GL_INS("OI_DoubleHalfClear: psm:%s. Z:%d R:%d G:%d B:%d A:%d", psm_str(m_context->FRAME.PSM),
// v[1].XYZ.Z, v[1].RGBAQ.R, v[1].RGBAQ.G, v[1].RGBAQ.B, v[1].RGBAQ.A);
// Check it is a clear on the first primitive only
if (v[1].XYZ.Z || v[1].RGBAQ.R || v[1].RGBAQ.G || v[1].RGBAQ.B || v[1].RGBAQ.A) {
return true;
}
// Only 32 bits format is supported otherwise it is complicated
if (m_context->FRAME.PSM & 2)
return true;
// FIXME might need some rounding
// In 32 bits pages are 64x32 pixels. In theory, it must be somethings
// like FBW * 64 pixels * ratio / 32 pixels / 2 = FBW * ratio
// It is hard to predict the ratio, so I round it to 1. And I use
// <= comparison below.
uint32 h_pages = roundf(m_vt.m_max.p.y / 32.0f);
uint32 base;
uint32 half;
if (m_context->FRAME.FBP > m_context->ZBUF.ZBP) {
base = m_context->ZBUF.ZBP;
half = m_context->FRAME.FBP;
} else {
base = m_context->FRAME.FBP;
half = m_context->ZBUF.ZBP;
}
if (half <= (base + h_pages * m_context->FRAME.FBW)) {
GL_INS("OI_DoubleHalfClear: base %x half %x. h_pages %d fbw %d", base, half, h_pages, m_context->FRAME.FBW);
if (m_context->FRAME.FBP > m_context->ZBUF.ZBP) {
m_dev->ClearDepth(ds);
} else {
m_dev->ClearRenderTarget(rt, 0);
}
// Don't return false, it will break the rendering. I guess that it misses texture
// invalidation
//return false;
}
}
return true;
}
// Note: hack is safe, but it could impact the perf a little (normally games do only a couple of clear by frame) // Note: hack is safe, but it could impact the perf a little (normally games do only a couple of clear by frame)
void GSRendererHW::OI_GsMemClear() void GSRendererHW::OI_GsMemClear()
{ {
@ -1569,6 +1626,11 @@ bool GSRendererHW::OI_ItadakiStreet(GSTexture* rt, GSTexture* ds, GSTextureCache
return true; return true;
} }
bool GSRendererHW::OI_FFVIIDoC(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{
return OI_DoubleHalfClear_Vertical(rt, ds, t);
}
// OO (others output?) hacks: invalidate extra local memory after the draw call // OO (others output?) hacks: invalidate extra local memory after the draw call

View File

@ -52,6 +52,7 @@ private:
void OI_GsMemClear(); // always on void OI_GsMemClear(); // always on
bool OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_DoubleHalfClear_Vertical(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
@ -73,6 +74,7 @@ private:
bool OI_SuperManReturns(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_SuperManReturns(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_ArTonelico2(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_ArTonelico2(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_ItadakiStreet(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_ItadakiStreet(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
bool OI_FFVIIDoC(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
void OO_DBZBT2(); void OO_DBZBT2();
void OO_MajokkoALaMode2(); void OO_MajokkoALaMode2();