From 4c226bcc952a5f7084795a17bf30dce1d654e689 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Mon, 29 Aug 2016 18:32:16 +0700 Subject: [PATCH] Do not show rightmost pixels in frame buffer when AA and divots elimination enabled in VI. Problem: Some games have strange glitch, which looks like vertical line of pixels outside of right bound of the image. Examples: JFG title screen, both Zelda games when new game started. Software plugin has the same issue, but when image passes VI stage, the problem disappears. Most likely VI filters somehow eat the rightmost pixels. I suspect that it is result of divots elimination. Thus, the fix works like this: when divot flag is set the rightmost column of pixels is not shown. --- src/FrameBuffer.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 9a6f154e..3aab5da0 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -792,6 +792,7 @@ void FrameBufferList::renderBuffer(u32 _address) GLint srcY0, srcY1, dstY0, dstY1; GLint X0, X1, Xwidth; GLint Xoffset = 0; + GLint Xdivot = 0; GLint srcPartHeight = 0; GLint dstPartHeight = 0; @@ -844,6 +845,11 @@ void FrameBufferList::renderBuffer(u32 _address) FrameBuffer * pFilteredBuffer = PostProcessor::get().doBlur(PostProcessor::get().doGammaCorrection(pBuffer)); + const bool vi_fsaa = (*REG.VI_STATUS & 512) == 0; + const bool vi_divot = (*REG.VI_STATUS & 16) != 0; + if (vi_fsaa && vi_divot) + Xdivot = 1; + const f32 viScaleX = _FIXED2FLOAT(_SHIFTR(*REG.VI_X_SCALE, 0, 12), 10); const f32 srcScaleX = pFilteredBuffer->m_scaleX; const f32 dstScaleX = ogl.getScaleX(); @@ -851,7 +857,7 @@ void FrameBufferList::renderBuffer(u32 _address) const s32 hx0 = max(0, hStart - h0); const s32 hx1 = max(0, h0 + 640 - hEnd); X0 = (GLint)((hx0 * viScaleX + Xoffset) * dstScaleX); - Xwidth = (GLint)((min((f32)VI.width, (hEnd - hStart)*viScaleX - Xoffset)) * srcScaleX); + Xwidth = (GLint)((min((f32)VI.width, (hEnd - hStart)*viScaleX - Xoffset - Xdivot)) * srcScaleX); X1 = ogl.getWidth() - (GLint)(hx1 *viScaleX * dstScaleX); const f32 srcScaleY = pFilteredBuffer->m_scaleY;