Skip to content

Commit 23436f0

Browse files
committed
GPU/HW: More improvements to GPUSTAT.31
Fixes True Pinball without breaking intros to Final Fantasy 7/8.
1 parent 04f131f commit 23436f0

File tree

7 files changed

+34
-30
lines changed

7 files changed

+34
-30
lines changed

src/core/gpu.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ bool GPU::DoState(StateWrapper& sw)
158158
sw.Do(&m_crtc_state.current_scanline);
159159
sw.Do(&m_crtc_state.in_hblank);
160160
sw.Do(&m_crtc_state.in_vblank);
161-
sw.Do(&m_crtc_state.displaying_odd_field);
162-
sw.Do(&m_crtc_state.displaying_odd_lines);
161+
sw.Do(&m_crtc_state.interlaced_field);
162+
sw.Do(&m_crtc_state.active_line_lsb);
163163

164164
sw.Do(&m_blitter_state);
165165
sw.Do(&m_command_ticks);
@@ -693,9 +693,9 @@ void GPU::Execute(TickCount ticks)
693693

694694
// switch fields early. this is needed so we draw to the correct one.
695695
if (m_GPUSTAT.vertical_interlace)
696-
m_crtc_state.displaying_odd_field ^= true;
696+
m_crtc_state.interlaced_field ^= 1u;
697697
else
698-
m_crtc_state.displaying_odd_field = false;
698+
m_crtc_state.interlaced_field = 0;
699699
}
700700

701701
m_timers->SetGate(HBLANK_TIMER_INDEX, new_vblank);
@@ -713,15 +713,14 @@ void GPU::Execute(TickCount ticks)
713713
// alternating even line bit in 240-line mode
714714
if (m_GPUSTAT.vertical_interlace)
715715
{
716-
m_crtc_state.displaying_odd_lines =
717-
ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(m_crtc_state.displaying_odd_field)) & u32(1));
718-
m_GPUSTAT.drawing_odd_lines = !m_crtc_state.displaying_odd_lines && !m_crtc_state.in_vblank;
716+
m_crtc_state.active_line_lsb =
717+
ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(m_crtc_state.interlaced_field)) & u32(1));
718+
m_GPUSTAT.display_line_lsb = m_crtc_state.active_line_lsb && !m_crtc_state.in_vblank;
719719
}
720720
else
721721
{
722-
m_crtc_state.displaying_odd_lines = false;
723-
m_GPUSTAT.drawing_odd_lines =
724-
ConvertToBoolUnchecked((m_crtc_state.regs.Y + m_crtc_state.current_scanline) & u32(1));
722+
m_crtc_state.active_line_lsb = 0;
723+
m_GPUSTAT.display_line_lsb = ConvertToBoolUnchecked((m_crtc_state.regs.Y + m_crtc_state.current_scanline) & u32(1));
725724
}
726725

727726
UpdateSliceTicks();
@@ -1018,7 +1017,7 @@ void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
10181017
if (IsRasterScanlinePending())
10191018
Synchronize();
10201019

1021-
const u32 active_field = GetInterlacedDisplayLineOffset();
1020+
const u32 active_field = GetActiveLineLSB();
10221021
for (u32 yoffs = 0; yoffs < height; yoffs++)
10231022
{
10241023
const u32 row = (y + yoffs) % VRAM_HEIGHT;
@@ -1326,9 +1325,9 @@ void GPU::DrawDebugStateWindow()
13261325
const auto& cs = m_crtc_state;
13271326
ImGui::Text("Dot Clock Divider: %u", cs.dot_clock_divider);
13281327
ImGui::Text("Vertical Interlace: %s (%s field)", m_GPUSTAT.vertical_interlace ? "Yes" : "No",
1329-
m_crtc_state.displaying_odd_field ? "odd" : "even");
1328+
m_crtc_state.interlaced_field ? "odd" : "even");
13301329
ImGui::Text("Display Disable: %s", m_GPUSTAT.display_disable ? "Yes" : "No");
1331-
ImGui::Text("Displaying Odd Lines: %s", m_crtc_state.displaying_odd_lines ? "Yes" : "No");
1330+
ImGui::Text("Displaying Odd Lines: %s", m_crtc_state.active_line_lsb ? "Yes" : "No");
13321331
ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15);
13331332
ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
13341333
ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total,

src/core/gpu.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,11 @@ class GPU
356356
return (!m_force_progressive_scan) & m_GPUSTAT.SkipDrawingToActiveField();
357357
}
358358

359-
/// Returns 0 if the currently-displayed field is on an even line, otherwise 1.
360-
ALWAYS_INLINE u32 GetInterlacedDisplayLineOffset() const { return BoolToUInt32(m_crtc_state.displaying_odd_lines); }
359+
/// Returns 0 if the currently-displayed field is on odd lines (1,3,5,...) or 1 if even (2,4,6,...).
360+
ALWAYS_INLINE u32 GetInterlacedDisplayField() const { return ZeroExtend32(m_crtc_state.interlaced_field); }
361+
362+
/// Returns 0 if the currently-displayed field is on an even line in VRAM, otherwise 1.
363+
ALWAYS_INLINE u32 GetActiveLineLSB() const { return ZeroExtend32(m_crtc_state.active_line_lsb); }
361364

362365
/// Sets/decodes GP0(E1h) (set draw mode).
363366
void SetDrawMode(u16 bits);
@@ -446,7 +449,7 @@ class GPU
446449
BitField<u32, bool, 27, 1> ready_to_send_vram;
447450
BitField<u32, bool, 28, 1> ready_to_recieve_dma;
448451
BitField<u32, DMADirection, 29, 2> dma_direction;
449-
BitField<u32, bool, 31, 1> drawing_odd_lines;
452+
BitField<u32, bool, 31, 1> display_line_lsb;
450453

451454
bool IsMaskingEnabled() const
452455
{
@@ -638,8 +641,8 @@ class GPU
638641
bool in_hblank;
639642
bool in_vblank;
640643

641-
bool displaying_odd_field;
642-
bool displaying_odd_lines;
644+
u8 interlaced_field; // 0 = odd, 1 = even
645+
u8 active_line_lsb;
643646
} m_crtc_state = {};
644647

645648
BlitterState m_blitter_state = BlitterState::Idle;

src/core/gpu_hw.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ void GPU_HW::DispatchRenderCommand()
713713
m_batch.interlacing = IsInterlacedRenderingEnabled();
714714
if (m_batch.interlacing)
715715
{
716-
const u32 displayed_field = GetInterlacedDisplayLineOffset();
716+
const u32 displayed_field = GetActiveLineLSB();
717717
m_batch_ubo_dirty |= (m_batch_ubo_data.u_interlaced_displayed_field != displayed_field);
718718
m_batch_ubo_data.u_interlaced_displayed_field = displayed_field;
719719
}

src/core/gpu_hw_d3d11.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ void GPU_HW_D3D11::UpdateDisplay()
583583
else
584584
{
585585
const u32 vram_offset_x = m_crtc_state.display_vram_left;
586-
const u32 vram_offset_y = m_crtc_state.display_vram_top;
586+
const u32 vram_offset_y = m_crtc_state.display_vram_top + GetActiveLineLSB();
587587
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
588588
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
589589
const u32 display_width = m_crtc_state.display_vram_width;
@@ -610,7 +610,7 @@ void GPU_HW_D3D11::UpdateDisplay()
610610
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
611611
m_context->PSSetShaderResources(0, 1, m_vram_texture.GetD3DSRVArray());
612612

613-
const u32 reinterpret_field_offset = GetInterlacedDisplayLineOffset();
613+
const u32 reinterpret_field_offset = GetInterlacedDisplayField();
614614
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
615615
const u32 reinterpret_crop_left = (m_crtc_state.display_vram_left - m_crtc_state.regs.X) * m_resolution_scale;
616616
const u32 uniforms[4] = {reinterpret_start_x, scaled_vram_offset_y, reinterpret_crop_left,
@@ -694,7 +694,7 @@ void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
694694
Uniforms uniforms;
695695
std::tie(uniforms.u_fill_color[0], uniforms.u_fill_color[1], uniforms.u_fill_color[2], uniforms.u_fill_color[3]) =
696696
RGBA8ToFloat(color);
697-
uniforms.u_interlaced_displayed_field = GetInterlacedDisplayLineOffset();
697+
uniforms.u_interlaced_displayed_field = GetActiveLineLSB();
698698

699699
m_context->OMSetDepthStencilState(m_depth_test_always_state.Get(), 0);
700700

src/core/gpu_hw_opengl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
580580
else
581581
{
582582
const u32 vram_offset_x = m_crtc_state.display_vram_left;
583-
const u32 vram_offset_y = m_crtc_state.display_vram_top;
583+
const u32 vram_offset_y = m_crtc_state.display_vram_top + GetActiveLineLSB();
584584
const u32 scaled_vram_offset_x = vram_offset_x * m_resolution_scale;
585585
const u32 scaled_vram_offset_y = vram_offset_y * m_resolution_scale;
586586
const u32 display_width = m_crtc_state.display_vram_width;
@@ -616,7 +616,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
616616
const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - (display_height >> height_div2);
617617
const u32 scaled_flipped_vram_offset_y =
618618
m_vram_texture.GetHeight() - scaled_vram_offset_y - (scaled_display_height >> height_div2);
619-
const u32 reinterpret_field_offset = GetInterlacedDisplayLineOffset();
619+
const u32 reinterpret_field_offset = GetInterlacedDisplayField();
620620
const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale;
621621
const u32 reinterpret_crop_left = (m_crtc_state.display_vram_left - m_crtc_state.regs.X) * m_resolution_scale;
622622
const u32 uniforms[4] = {reinterpret_start_x, scaled_flipped_vram_offset_y, reinterpret_crop_left,
@@ -724,7 +724,7 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
724724
Uniforms uniforms;
725725
std::tie(uniforms.u_fill_color[0], uniforms.u_fill_color[1], uniforms.u_fill_color[2], uniforms.u_fill_color[3]) =
726726
RGBA8ToFloat(color);
727-
uniforms.u_interlaced_displayed_field = GetInterlacedDisplayLineOffset();
727+
uniforms.u_interlaced_displayed_field = GetActiveLineLSB();
728728

729729
m_vram_interlaced_fill_program.Bind();
730730
UploadUniformBuffer(&uniforms, sizeof(uniforms));

src/core/gpu_hw_shadergen.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,8 @@ std::string GPU_HW_ShaderGen::GenerateDisplayFragmentShader(bool depth_24bit, GP
10311031
10321032
#if !INTERLEAVED
10331033
icoords.y /= 2u;
1034+
#else
1035+
icoords.y &= ~1u;
10341036
#endif
10351037
#endif
10361038

src/core/gpu_sw.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,22 +157,22 @@ void GPU_SW::UpdateDisplay()
157157
}
158158

159159
const u32 vram_offset_x = m_crtc_state.display_vram_left;
160-
const u32 vram_offset_y = m_crtc_state.display_vram_top;
160+
const u32 vram_offset_y = m_crtc_state.display_vram_top + GetActiveLineLSB();
161161
const u32 display_width = m_crtc_state.display_vram_width;
162162
const u32 display_height = m_crtc_state.display_vram_height;
163163
const u32 texture_offset_x = m_crtc_state.display_vram_left - m_crtc_state.regs.X;
164164
if (IsInterlacedDisplayEnabled())
165165
{
166-
const u32 field = GetInterlacedDisplayLineOffset();
166+
const u32 field = GetInterlacedDisplayField();
167167
if (m_GPUSTAT.display_area_color_depth_24)
168168
{
169-
CopyOut24Bit(m_crtc_state.regs.X, vram_offset_y + (m_GPUSTAT.vertical_resolution ? field : 0u),
169+
CopyOut24Bit(m_crtc_state.regs.X, vram_offset_y,
170170
m_display_texture_buffer.data() + field * VRAM_WIDTH, VRAM_WIDTH, display_width + texture_offset_x,
171171
display_height, true, m_GPUSTAT.vertical_resolution);
172172
}
173173
else
174174
{
175-
CopyOut15Bit(m_crtc_state.regs.X, vram_offset_y + (m_GPUSTAT.vertical_resolution ? field : 0u),
175+
CopyOut15Bit(m_crtc_state.regs.X, vram_offset_y,
176176
m_display_texture_buffer.data() + field * VRAM_WIDTH, VRAM_WIDTH, display_width + texture_offset_x,
177177
display_height, true, m_GPUSTAT.vertical_resolution);
178178
}
@@ -716,7 +716,7 @@ void GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color_g, u8 color_b, u8 tex
716716
if ((bg_color.bits & mask_and) != 0)
717717
return;
718718

719-
if (IsInterlacedRenderingEnabled() && GetInterlacedDisplayLineOffset() == (static_cast<u32>(y) & 1u))
719+
if (IsInterlacedRenderingEnabled() && GetActiveLineLSB() == (static_cast<u32>(y) & 1u))
720720
return;
721721

722722
SetPixel(static_cast<u32>(x), static_cast<u32>(y), color.bits | m_GPUSTAT.GetMaskOR());

0 commit comments

Comments
 (0)