diff --git a/bin/resources/GameIndex.yaml b/bin/resources/GameIndex.yaml index 45e09e784d..ce726b1792 100644 --- a/bin/resources/GameIndex.yaml +++ b/bin/resources/GameIndex.yaml @@ -27852,8 +27852,6 @@ SLES-54812: SLES-54813: name: "NASCAR 08" region: "PAL-A-E" - gsHWFixes: - deinterlace: 8 # Game requires AdaptiveTFF de-interlacing when auto. SLES-54814: name: "Dead Eye Jim" region: "PAL-E" @@ -29206,8 +29204,6 @@ SLES-55199: name: "NASCAR 09" region: "PAL-M5" compat: 5 - gsHWFixes: - deinterlace: 8 # Game requires AdaptiveTFF de-interlacing when auto. SLES-55200: name: "Guitar Hero - Aerosmith" region: "PAL-M4" @@ -66483,7 +66479,6 @@ SLUS-20535: compat: 5 gsHWFixes: roundSprite: 1 # Fix horizontal and vertical lines when racing. - deinterlace: 8 # Fixes misdetection of game deinterlace. SLUS-20536: name: "NBA Live 2003" region: "NTSC-U" @@ -67683,7 +67678,6 @@ SLUS-20754: region: "NTSC-U" gsHWFixes: roundSprite: 1 # Fix horizontal and vertical lines when racing. - deinterlace: 8 # Fixes misdetection of game deinterlace. memcardFilters: - "PSCD10088" # Enables EA Sports BIO. - "SLUS-20754" @@ -68048,7 +68042,6 @@ SLUS-20824: region: "NTSC-U" gsHWFixes: roundSprite: 1 # Fix horizontal and vertical lines when racing. - deinterlace: 8 # Fixes misdetection of game deinterlace. memcardFilters: - "PSCD10088" # Enables EA Sports BIO. - "SLUS-20824" @@ -73096,8 +73089,6 @@ SLUS-21639: name: "NASCAR 08" region: "NTSC-U" compat: 5 - gsHWFixes: - deinterlace: 8 # Game requires AdaptiveTFF de-interlacing when auto. SLUS-21640: name: "Rugby 08" region: "NTSC-U" @@ -73665,8 +73656,6 @@ SLUS-21744: name: "NASCAR 09" region: "NTSC-U" compat: 5 - gsHWFixes: - deinterlace: 8 # Game requires AdaptiveTFF de-interlacing when auto. patches: 1B6C22B9: content: |- diff --git a/pcsx2/GS/GS.cpp b/pcsx2/GS/GS.cpp index 2dd04d24a6..2910e0de7f 100644 --- a/pcsx2/GS/GS.cpp +++ b/pcsx2/GS/GS.cpp @@ -442,7 +442,7 @@ void GSvsync(u32 field, bool registers_written) g_gs_renderer->PCRTCDisplays.SetRects(0, g_gs_renderer->m_regs->DISP[0].DISPLAY, g_gs_renderer->m_regs->DISP[0].DISPFB); g_gs_renderer->PCRTCDisplays.SetRects(1, g_gs_renderer->m_regs->DISP[1].DISPLAY, g_gs_renderer->m_regs->DISP[1].DISPFB); g_gs_renderer->PCRTCDisplays.CalculateDisplayOffset(g_gs_renderer->m_scanmask_used); - g_gs_renderer->PCRTCDisplays.CalculateFramebufferOffset(g_gs_renderer->m_scanmask_used); + g_gs_renderer->PCRTCDisplays.CalculateFramebufferOffset(g_gs_renderer->m_scanmask_used, g_gs_renderer->m_regs->DISP[0].DISPFB, g_gs_renderer->m_regs->DISP[1].DISPFB); // Do not move the flush into the VSync() method. It's here because EE transfers // get cleared in HW VSync, and may be needed for a buffered draw (FFX FMVs). diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index 1f55cb3478..09be5b9c8e 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -5961,44 +5961,36 @@ void GSState::GSPCRTCRegs::SetRects(int display, GSRegDISPLAY displayReg, GSRegD // Calculate framebuffer read offsets, should be considered if only one circuit is enabled, or difference is more than 1 line. // Only considered if "Anti-blur" is enabled. -void GSState::GSPCRTCRegs::CalculateFramebufferOffset(bool scanmask) +void GSState::GSPCRTCRegs::CalculateFramebufferOffset(bool scanmask, GSRegDISPFB framebuffer0Reg, GSRegDISPFB framebuffer1Reg) { + GSVector2i fb0 = GSVector2i(PCRTCDisplays[0].framebufferOffsets.x, PCRTCDisplays[0].framebufferOffsets.y); + GSVector2i fb1 = GSVector2i(PCRTCDisplays[1].framebufferOffsets.x, PCRTCDisplays[1].framebufferOffsets.y); + + if (fb0.x + PCRTCDisplays[0].displayRect.z > 2048) + { + fb0.x -= 2048; + PCRTCDisplays[0].framebufferOffsets.x = fb0.x; + } + if (fb0.y + PCRTCDisplays[0].displayRect.w > 2048) + { + fb0.y -= 2048; + PCRTCDisplays[0].framebufferOffsets.y = fb0.y; + } + if (fb1.x + PCRTCDisplays[1].displayRect.z > 2048) + { + fb1.x -= 2048; + PCRTCDisplays[1].framebufferOffsets.x = fb1.x; + } + if (fb1.y + PCRTCDisplays[1].displayRect.w > 2048) + { + fb1.y -= 2048; + PCRTCDisplays[1].framebufferOffsets.y = fb1.y; + } + if (GSConfig.PCRTCAntiBlur && PCRTCSameSrc && !scanmask) { - GSVector2i fb0 = GSVector2i(PCRTCDisplays[0].framebufferOffsets.x, PCRTCDisplays[0].framebufferOffsets.y); - GSVector2i fb1 = GSVector2i(PCRTCDisplays[1].framebufferOffsets.x, PCRTCDisplays[1].framebufferOffsets.y); - - if (fb0.x + PCRTCDisplays[0].displayRect.z > 2048) - { - fb0.x -= 2048; - fb0.x = abs(fb0.x); - } - if (fb0.y + PCRTCDisplays[0].displayRect.w > 2048) - { - fb0.y -= 2048; - fb0.y = abs(fb0.y); - } - if (fb1.x + PCRTCDisplays[1].displayRect.z > 2048) - { - fb1.x -= 2048; - fb1.x = abs(fb1.x); - } - if (fb1.y + PCRTCDisplays[1].displayRect.w > 2048) - { - fb1.y -= 2048; - fb1.y = abs(fb1.y); - } - - if (abs(fb1.y - fb0.y) == 1 - && PCRTCDisplays[0].displayRect.y == PCRTCDisplays[1].displayRect.y) - { - if (fb1.y < fb0.y) - PCRTCDisplays[0].framebufferOffsets.y = fb1.y; - else - PCRTCDisplays[1].framebufferOffsets.y = fb0.y; - } - if (abs(fb1.x - fb0.x) == 1 - && PCRTCDisplays[0].displayRect.x == PCRTCDisplays[1].displayRect.x) + + if (abs(fb1.x - fb0.x) == 1 && PCRTCDisplays[0].displayRect.x == PCRTCDisplays[1].displayRect.x) { if (fb1.x < fb0.x) PCRTCDisplays[0].framebufferOffsets.x = fb1.x; @@ -6015,6 +6007,20 @@ void GSState::GSPCRTCRegs::CalculateFramebufferOffset(bool scanmask) PCRTCDisplays[1].framebufferRect.z += PCRTCDisplays[1].framebufferOffsets.x; PCRTCDisplays[1].framebufferRect.y += PCRTCDisplays[1].framebufferOffsets.y; PCRTCDisplays[1].framebufferRect.w += PCRTCDisplays[1].framebufferOffsets.y; + + if (GSConfig.PCRTCAntiBlur && PCRTCSameSrc && !scanmask && abs(fb1.y - fb0.y) <= 1) + { + if (framebuffer0Reg.DBY != PCRTCDisplays[0].prevFramebufferReg.DBY) + { + PCRTCDisplays[0].framebufferRect.y = PCRTCDisplays[1].framebufferRect.y; + PCRTCDisplays[0].framebufferRect.w = PCRTCDisplays[1].framebufferRect.w; + } + else + { + PCRTCDisplays[1].framebufferRect.y = PCRTCDisplays[0].framebufferRect.y; + PCRTCDisplays[1].framebufferRect.w = PCRTCDisplays[0].framebufferRect.w; + } + } } // Used in software mode to align the buffer when reading. Offset is accounted for (block aligned) by GetOutput. diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index 01113e2c18..6a4c713374 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -408,7 +408,7 @@ public: // Calculate framebuffer read offsets, should be considered if only one circuit is enabled, or difference is more than 1 line. // Only considered if "Anti-blur" is enabled. - void CalculateFramebufferOffset(bool scanmask); + void CalculateFramebufferOffset(bool scanmask, GSRegDISPFB framebuffer0Reg, GSRegDISPFB framebuffer1Reg); // Used in software mode to align the buffer when reading. Offset is accounted for (block aligned) by GetOutput. void RemoveFramebufferOffset(int display); diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.cpp b/pcsx2/GS/Renderers/Common/GSRenderer.cpp index 21ee53fade..6364051cc6 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.cpp +++ b/pcsx2/GS/Renderers/Common/GSRenderer.cpp @@ -94,8 +94,8 @@ bool GSRenderer::Merge(int field) } // Need to do this here, if the user has Anti-Blur enabled, these offsets can get wiped out/changed. - const bool game_deinterlacing = (m_regs->DISP[0].DISPFB.DBY != PCRTCDisplays.PCRTCDisplays[0].prevFramebufferReg.DBY) != - (m_regs->DISP[1].DISPFB.DBY != PCRTCDisplays.PCRTCDisplays[1].prevFramebufferReg.DBY); + const bool game_deinterlacing = (PCRTCDisplays.PCRTCDisplays[0].prevFramebufferOffsets.y != PCRTCDisplays.PCRTCDisplays[0].framebufferOffsets.y) != + (PCRTCDisplays.PCRTCDisplays[1].prevFramebufferOffsets.y != PCRTCDisplays.PCRTCDisplays[1].framebufferOffsets.y); // Only need to check the right/bottom on software renderer, hardware always gets the full texture then cuts a bit out later. if (PCRTCDisplays.FrameRectMatch() && !PCRTCDisplays.FrameWrap() && !feedback_merge) @@ -156,19 +156,10 @@ bool GSRenderer::Merge(int field) bool is_bob = GSConfig.InterlaceMode == GSInterlaceMode::BobTFF || GSConfig.InterlaceMode == GSInterlaceMode::BobBFF; // FFMD (half frames) requires blend deinterlacing, so automatically use that. Same when SCANMSK is used but not blended in the merge circuit (Alpine Racer 3). - if (GSConfig.InterlaceMode != GSInterlaceMode::Automatic || (!m_regs->SMODE2.FFMD && !scanmask_frame)) + if (GSConfig.InterlaceMode != GSInterlaceMode::Automatic || (!game_deinterlacing && !m_regs->SMODE2.FFMD && !scanmask_frame)) { - // If the game is offsetting each frame itself and we're using full height buffers, we can offset this with Bob. - if (game_deinterlacing && !scanmask_frame && GSConfig.InterlaceMode == GSInterlaceMode::Automatic) - { - mode = 1; // Bob. - is_bob = true; - } - else - { - field2 = ((static_cast(GSConfig.InterlaceMode) - 2) & 1); - mode = ((static_cast(GSConfig.InterlaceMode) - 2) >> 1); - } + field2 = ((static_cast(GSConfig.InterlaceMode) - 2) & 1); + mode = ((static_cast(GSConfig.InterlaceMode) - 2) >> 1); } for (int i = 0; i < 2; i++)