From 7152d54104dbffb76585b90c39b168f562a63f7b Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 14 Nov 2019 00:58:15 +1000 Subject: [PATCH] GPU: Simplify 480i mode handling in CRTC --- src/core/gpu.cpp | 22 +++++++++++++++------- src/core/gpu.h | 2 ++ src/core/gpu_hw_d3d11.cpp | 3 +-- src/core/gpu_hw_opengl.cpp | 3 +-- src/core/gpu_sw.cpp | 3 +-- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 45d71b095..a5daa9f9c 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -336,8 +336,9 @@ void GPU::UpdateCRTCConfig() // check for a change in resolution const u32 old_horizontal_resolution = cs.display_width; const u32 old_vertical_resolution = cs.display_height; + const u32 visible_lines = cs.regs.Y2 - cs.regs.Y1; cs.display_width = std::max((cs.regs.X2 - cs.regs.X1) / cs.dot_clock_divider, 1); - cs.display_height = cs.regs.Y2 - cs.regs.Y1; + cs.display_height = visible_lines << BoolToUInt8(m_GPUSTAT.In480iMode()); if (cs.display_width != old_horizontal_resolution || cs.display_height != old_vertical_resolution) Log_InfoPrintf("Visible resolution is now %ux%u", cs.display_width, cs.display_height); @@ -354,7 +355,7 @@ void GPU::UpdateCRTCConfig() // Convert active dots/lines to time. const float visible_dots_per_scanline = static_cast(cs.display_width); const float horizontal_active_time = horizontal_period * visible_dots_per_scanline; - const float vertical_active_time = horizontal_active_time * static_cast(cs.display_height); + const float vertical_active_time = horizontal_active_time * static_cast(visible_lines); // Use the reference active time/lines for the signal to work out the border area, and thus aspect ratio // transformation for the active area in our framebuffer. For the purposes of these calculations, we're assuming @@ -435,11 +436,18 @@ void GPU::Execute(TickCount ticks) // start the new frame m_crtc_state.current_scanline = 0; - if (m_GPUSTAT.vertical_interlace & m_GPUSTAT.vertical_resolution) + // switch fields for interlaced modes + if (m_GPUSTAT.vertical_interlace) { - // extra line for NTSC - m_crtc_state.current_scanline = BoolToUInt32(m_GPUSTAT.drawing_even_line); - m_GPUSTAT.drawing_even_line ^= true; + m_GPUSTAT.interlaced_field ^= true; + m_crtc_state.current_scanline = BoolToUInt32(m_GPUSTAT.interlaced_field); + + if (m_GPUSTAT.vertical_resolution) + m_GPUSTAT.drawing_even_line = m_GPUSTAT.interlaced_field; + } + else + { + m_GPUSTAT.interlaced_field = false; } } @@ -464,7 +472,7 @@ void GPU::Execute(TickCount ticks) } // alternating even line bit in 240-line mode - if (!(m_GPUSTAT.vertical_interlace & m_GPUSTAT.vertical_resolution)) + if (!m_GPUSTAT.In480iMode()) m_GPUSTAT.drawing_even_line = ConvertToBoolUnchecked(m_crtc_state.current_scanline & u32(1)); } diff --git a/src/core/gpu.h b/src/core/gpu.h index 6dd77287a..126c5f6a5 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -331,6 +331,8 @@ protected: BitField ready_to_recieve_dma; BitField dma_direction; BitField drawing_even_line; + + bool In480iMode() const { return vertical_interlace & vertical_resolution; } } m_GPUSTAT = {}; struct RenderState diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index c1b88d252..9bb9c9717 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -519,8 +519,7 @@ void GPU_HW_D3D11::UpdateDisplay() const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale; const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale; const u32 display_width = std::min(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x); - const u32 display_height = std::min(m_crtc_state.display_height << BoolToUInt8(m_GPUSTAT.vertical_interlace), - VRAM_HEIGHT - vram_offset_y); + const u32 display_height = std::min(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y); const u32 scaled_display_width = display_width * m_resolution_scale; const u32 scaled_display_height = display_height * m_resolution_scale; diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index 464d246b8..f988e7e08 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -427,8 +427,7 @@ void GPU_HW_OpenGL::UpdateDisplay() const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale; const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale; const u32 display_width = std::min(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x); - const u32 display_height = std::min(m_crtc_state.display_height << BoolToUInt8(m_GPUSTAT.vertical_interlace), - VRAM_HEIGHT - vram_offset_y); + const u32 display_height = std::min(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y); const u32 scaled_display_width = display_width * m_resolution_scale; const u32 scaled_display_height = display_height * m_resolution_scale; diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index 5c04542b3..4df707786 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -125,8 +125,7 @@ void GPU_SW::UpdateDisplay() const u32 vram_offset_x = m_crtc_state.regs.X; const u32 vram_offset_y = m_crtc_state.regs.Y; display_width = std::min(m_crtc_state.display_width, VRAM_WIDTH - vram_offset_x); - display_height = std::min(m_crtc_state.display_height << BoolToUInt8(m_GPUSTAT.vertical_interlace), - VRAM_HEIGHT - vram_offset_y); + display_height = std::min(m_crtc_state.display_height, VRAM_HEIGHT - vram_offset_y); display_aspect_ratio = m_crtc_state.display_aspect_ratio; if (m_GPUSTAT.display_disable)