diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index fc1977ec83..4aae5743f5 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -373,7 +373,7 @@ bool GSState::IsAnalogue() return GetVideoMode() == GSVideoMode::NTSC || GetVideoMode() == GSVideoMode::PAL || GetVideoMode() == GSVideoMode::HDTV_1080I; } -GSVector4i GSState::GetDisplayRectSize(int i) +GSVector4i GSState::GetDisplayMagnifiedRect(int i) { GSVector4i rectangle = { 0, 0, 0, 0 }; @@ -394,9 +394,12 @@ GSVector4i GSState::GetDisplayRectSize(int i) const int height = (DH / (VideoModeDividers[(int)videomode - 1].y + 1)); // Set up the display rectangle based on the values obtained from DISPLAY registers - + const auto& SMODE2 = m_regs->SMODE2; + int res_multi = 1; + if (isinterlaced() && m_regs->SMODE2.FFMD && height > 1) + res_multi = 2; rectangle.right = width; - rectangle.bottom = height; + rectangle.bottom = height / res_multi; //DevCon.Warning("Display Rect Size Returning w %d h %d", width, height); return rectangle; } @@ -428,9 +431,11 @@ GSVector4i GSState::GetDisplayRect(int i) const int width = DW / magnification.x; const int height = DH / magnification.y; + const GSVector2i offsets = GetResolutionOffset(i); // Set up the display rectangle based on the values obtained from DISPLAY registers - rectangle.left = DX; - rectangle.top = DY; + rectangle.left = offsets.x; + rectangle.top = offsets.y; + rectangle.right = rectangle.left + width; rectangle.bottom = rectangle.top + height; @@ -449,13 +454,13 @@ GSVector2i GSState::GetResolutionOffset(int i) GSVector2i offset; offset.x = (((int)DISP.DX - VideoModeOffsets[(int)videomode - 1].z) / (VideoModeDividers[(int)videomode - 1].x + 1)); - offset.y = (((int)DISP.DY - (VideoModeOffsets[(int)videomode - 1].w * (IsAnalogue() ? res_multi : 1))) / (VideoModeDividers[(int)videomode - 1].y + 1)); - //DevCon.Warning("Res Offset X %d Video mode %d Y %d Video mode %d", DISP.DX, VideoModeOffsets[(int)videomode - 1].z, DISP.DY, (VideoModeOffsets[(int)videomode - 1].w * (IsAnalogue() ? res_multi : 1))); + offset.y = ((int)DISP.DY - (VideoModeOffsets[(int)videomode - 1].w * ((IsAnalogue() && res_multi) ? res_multi : 1))) / (VideoModeDividers[(int)videomode - 1].y + 1); + //DevCon.Warning("Res Offset X %d Video mode %d Y %d Video mode %d returning x %d y %d", DISP.DX, VideoModeOffsets[(int)videomode - 1].z, DISP.DY, (VideoModeOffsets[(int)videomode - 1].w * (IsAnalogue() ? res_multi : 1)), offset.x, offset.y); return offset; } -GSVector2i GSState::GetResolution() +GSVector2i GSState::GetResolution(bool include_interlace) { const GSVideoMode videomode = GetVideoMode(); const auto& SMODE2 = m_regs->SMODE2; @@ -464,7 +469,10 @@ GSVector2i GSState::GetResolution() GSVector2i resolution; resolution.x = VideoModeOffsets[(int)videomode - 1].x; - resolution.y = VideoModeOffsets[(int)videomode - 1].y * ((IsAnalogue() && res_multi) ? res_multi : 1); + resolution.y = VideoModeOffsets[(int)videomode - 1].y; + + if(include_interlace && !m_regs->SMODE2.FFMD) + resolution.y *= ((IsAnalogue() && res_multi) ? res_multi : 1); //DevCon.Warning("Getting Resolution X %d Y %d", resolution.x, resolution.y); return resolution; } @@ -475,7 +483,7 @@ GSVector4i GSState::GetFrameRect(int i) if (i == -1) return GetFrameRect(0).runion(GetFrameRect(1)); - GSVector4i rectangle = GetDisplayRect(i); + GSVector4i rectangle; const auto& DISP = m_regs->DISP[i].DISPLAY; @@ -492,16 +500,15 @@ GSVector4i GSState::GetFrameRect(int i) rectangle.left = DBX; rectangle.top = DBY; + rectangle.right = rectangle.left + w; + rectangle.bottom = rectangle.top + h; + if (isinterlaced() && m_regs->SMODE2.FFMD && h > 1) { - h >>= 1; + rectangle.bottom >>= 1; } - // Round down as this is the reading rect, so we want 0-639 and 0-479 for an example - rectangle.right = rectangle.left + w - 1; - rectangle.bottom = rectangle.top + h - 1; - - //DevCon.Warning("Frame Rect left %d right %d top %d bottom %d DBX %d DBY %d", rectangle.left, rectangle.right, rectangle.top, rectangle.bottom, DBX, DBY); + //DevCon.Warning("Frame %d Rect left %d right %d top %d bottom %d DBX %d DBY %d", i, rectangle.left, rectangle.right, rectangle.top, rectangle.bottom, DBX, DBY); return rectangle; } diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index a08b23c1c0..23da5443a3 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -289,9 +289,9 @@ public: int GetFramebufferHeight(); GSVector4i GetDisplayRect(int i = -1); - GSVector4i GetDisplayRectSize(int i = -1); + GSVector4i GetDisplayMagnifiedRect(int i = -1); GSVector2i GetResolutionOffset(int i = -1); - GSVector2i GetResolution(); + GSVector2i GetResolution(bool include_interlace = false); GSVector4i GetFrameRect(int i = -1); GSVideoMode GetVideoMode(); diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.cpp b/pcsx2/GS/Renderers/Common/GSRenderer.cpp index efb85a7790..05f37293d5 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.cpp +++ b/pcsx2/GS/Renderers/Common/GSRenderer.cpp @@ -89,8 +89,8 @@ bool GSRenderer::Merge(int field) fr[i] = GetFrameRect(i); dr[i] = GetDisplayRect(i); - display_combined.x = std::max(GetDisplayRectSize(i).right + abs(GetResolutionOffset(i).x), display_combined.x); - display_combined.y = std::max(GetDisplayRectSize(i).bottom + abs(GetResolutionOffset(i).y), display_combined.y); + display_combined.x = std::max(GetDisplayMagnifiedRect(i).right + abs(GetResolutionOffset(i).x), display_combined.x); + display_combined.y = std::max(GetDisplayMagnifiedRect(i).bottom + abs(GetResolutionOffset(i).y), display_combined.y); display_baseline.x = std::min(dr[i].left, display_baseline.x); display_baseline.y = std::min(dr[i].top, display_baseline.y); frame_baseline.x = std::min(fr[i].left, frame_baseline.x); @@ -196,8 +196,8 @@ bool GSRenderer::Merge(int field) if (!en[i] || !tex[i]) continue; - const GSVector2i resolution(GetResolution()); - GSVector4i r = GetDisplayRectSize(i); + const GSVector2i resolution(GetResolution(true)); + GSVector4i r = GetDisplayMagnifiedRect(i); GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy(); bool ignore_offset = !GSConfig.PCRTCOffsets; @@ -217,15 +217,13 @@ bool GSRenderer::Merge(int field) if (!ignore_offset) off.y &= ~1; } - - display_diff.x /= (VideoModeDividers[(int)videomode - 1].x + 1); - display_diff.y /= (VideoModeDividers[(int)videomode - 1].y + 1); - - if (!ignore_offset && display_combined.y < resolution.y && display_combined.x < resolution.x) + + if (!ignore_offset && display_combined.y < (resolution.y-1) && display_combined.x < (resolution.x-1)) { float difference[2]; difference[0] = resolution.x / (float)display_combined.x; difference[1] = resolution.y / (float)display_combined.y; + //DevCon.Warning("Difference x %f y %f old size x %d y %d res x %d y %d off x %d y %d", difference[0], difference[1], r.right, r.bottom, resolution.x, resolution.y, off.x, off.y); if (difference[0] > 1.0f) { @@ -330,17 +328,23 @@ bool GSRenderer::Merge(int field) if (frame_diff.y == 1) off.y += 1; } + + if (m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) + { + off.y /= 2; + } // Src is the size for output - src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy(); + src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy();; + // Src_hw is the size which we're really reading src_hw[i] = (GSVector4(fr[i]) + GSVector4(0, y_offset[i], 0, y_offset[i])) * scale / GSVector4(tex[i]->GetSize()).xyxy(); - - dst[i] = scale * (GSVector4(off).xyxy() + GSVector4(r.rsize())); + + dst[i] = GSVector4(off).xyxy() + (scale * GSVector4(r.rsize())); if (m_scanmask_used && interlace_offset) - dst[i] += GSVector4(0.0f, 1.0f, 0.0f, 1.0f); - //DevCon.Warning("Offset final x %d y %d Display x %d y %d Frame x %d y %d rect x %d y %d z %d w %d", off.x, off.y, display_diff.x, display_diff.x, frame_diff.y, frame_diff.y, r.x, r.y, r.z, r.w); + dst[i] -= GSVector4(0.0f, 1.0f, 0.0f, 1.0f); + //DevCon.Warning("Offset final x %d y %d Display Diff x %d y %d Frame Diff x %d y %d Frame Rect x %d y %d z %d w %d Display rect x %d y %d z %d w %d", off.x, off.y, display_diff.x, display_diff.x, frame_diff.y, frame_diff.y, fr[i].x, fr[i].y, fr[i].z, fr[i].w, r.x, r.y, r.z, r.w); } if (feedback_merge && tex[2]) @@ -356,15 +360,17 @@ bool GSRenderer::Merge(int field) dst[2] = GSVector4(scale * GSVector4(feedback_rect.rsize())); } - fs = GetResolution() * GSVector2i(GetUpscaleMultiplier()); + fs = GetResolution(true) * GSVector2i(GetUpscaleMultiplier()); //DevCon.Warning("Res x %d y %d", fs.x, fs.y); ds = fs; - m_real_size = ds; if (m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) { ds.y *= 2; } + + m_real_size = ds; + if (tex[0] || tex[1]) { if ((tex[0] == tex[1]) && (src[0] == src[1]).alltrue() && (dst[0] == dst[1]).alltrue() && !feedback_merge && !slbg)