GPU: Tweaks to ODE handling

Fixes Team Buddies and The Next Tetris.
This commit is contained in:
Connor McLaughlin 2020-08-15 14:56:20 +10:00
parent a8699d9908
commit d4665e8b22
5 changed files with 25 additions and 17 deletions

View File

@ -162,6 +162,7 @@ bool GPU::DoState(StateWrapper& sw)
sw.Do(&m_crtc_state.in_hblank);
sw.Do(&m_crtc_state.in_vblank);
sw.Do(&m_crtc_state.interlaced_field);
sw.Do(&m_crtc_state.interlaced_display_field);
sw.Do(&m_crtc_state.active_line_lsb);
sw.Do(&m_blitter_state);
@ -734,10 +735,10 @@ void GPU::CRTCTickEvent(TickCount ticks)
System::FrameDone();
// switch fields early. this is needed so we draw to the correct one.
if (m_GPUSTAT.vertical_interlace)
m_crtc_state.interlaced_field ^= 1u;
if (m_GPUSTAT.InInterleaved480iMode())
m_crtc_state.interlaced_display_field = m_crtc_state.interlaced_field ^ 1u;
else
m_crtc_state.interlaced_field = 0;
m_crtc_state.interlaced_display_field = 0;
}
g_timers.SetGate(HBLANK_TIMER_INDEX, new_vblank);
@ -749,15 +750,20 @@ void GPU::CRTCTickEvent(TickCount ticks)
{
// start the new frame
m_crtc_state.current_scanline = 0;
if (m_GPUSTAT.vertical_interlace)
m_crtc_state.interlaced_field ^= 1u;
else
m_crtc_state.interlaced_field = 0;
}
}
// alternating even line bit in 240-line mode
if (m_GPUSTAT.vertical_interlace)
if (m_GPUSTAT.InInterleaved480iMode())
{
m_crtc_state.active_line_lsb =
ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(m_crtc_state.interlaced_field)) & u32(1));
m_GPUSTAT.display_line_lsb = m_crtc_state.active_line_lsb && !m_crtc_state.in_vblank;
Truncate8((m_crtc_state.regs.Y + BoolToUInt32(m_crtc_state.interlaced_display_field)) & u32(1));
m_GPUSTAT.display_line_lsb = ConvertToBoolUnchecked(
(m_crtc_state.regs.Y + (BoolToUInt8(m_crtc_state.in_vblank) ^ m_crtc_state.interlaced_display_field)) & u32(1));
}
else
{

View File

@ -513,6 +513,11 @@ protected:
static constexpr u32 ACTIVE = (1 << 19) | (1 << 22);
return ((bits & MASK) == ACTIVE);
}
bool InInterleaved480iMode() const
{
static constexpr u32 ACTIVE = (1 << 19) | (1 << 22);
return ((bits & ACTIVE) == ACTIVE);
}
// During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or }
u16 GetMaskAND() const
@ -694,6 +699,7 @@ protected:
bool in_vblank;
u8 interlaced_field; // 0 = odd, 1 = even
u8 interlaced_display_field;
u8 active_line_lsb;
} m_crtc_state = {};

View File

@ -227,7 +227,7 @@ bool RecreateGPU(GPURenderer renderer)
// save current state
std::unique_ptr<ByteStream> state_stream = ByteStream_CreateGrowableMemoryStream();
StateWrapper sw(state_stream.get(), StateWrapper::Mode::Write);
const bool state_valid = g_gpu->DoState(sw) && TimingEvents::DoState(sw, TimingEvents::GetGlobalTickCounter());
const bool state_valid = g_gpu->DoState(sw) && TimingEvents::DoState(sw);
if (!state_valid)
Log_ErrorPrintf("Failed to save old GPU state when switching renderers");
@ -247,7 +247,7 @@ bool RecreateGPU(GPURenderer renderer)
sw.SetMode(StateWrapper::Mode::Read);
g_gpu->RestoreGraphicsAPIState();
g_gpu->DoState(sw);
TimingEvents::DoState(sw, TimingEvents::GetGlobalTickCounter());
TimingEvents::DoState(sw);
g_gpu->ResetGraphicsAPIState();
}
@ -540,13 +540,9 @@ bool DoState(StateWrapper& sw)
if (!sw.DoMarker("System"))
return false;
// TODO: Move this into timing state
u32 global_tick_counter = TimingEvents::GetGlobalTickCounter();
sw.Do(&s_region);
sw.Do(&s_frame_number);
sw.Do(&s_internal_frame_number);
sw.Do(&global_tick_counter);
if (!sw.DoMarker("CPU") || !CPU::DoState(sw))
return false;
@ -584,7 +580,7 @@ bool DoState(StateWrapper& sw)
if (!sw.DoMarker("SIO") || !g_sio.DoState(sw))
return false;
if (!sw.DoMarker("Events") || !TimingEvents::DoState(sw, global_tick_counter))
if (!sw.DoMarker("Events") || !TimingEvents::DoState(sw))
return false;
return !sw.HasError();

View File

@ -172,12 +172,12 @@ void RunEvents()
UpdateCPUDowncount();
}
bool DoState(StateWrapper& sw, u32 global_tick_counter)
bool DoState(StateWrapper& sw)
{
sw.Do(&s_global_tick_counter);
if (sw.IsReading())
{
s_global_tick_counter = global_tick_counter;
// Load timestamps for the clock events.
// Any oneshot events should be recreated by the load state method, so we can fix up their times here.
u32 event_count = 0;

View File

@ -79,7 +79,7 @@ std::unique_ptr<TimingEvent> CreateTimingEvent(std::string name, TickCount perio
TimingEventCallback callback, bool activate);
/// Serialization.
bool DoState(StateWrapper& sw, u32 global_tick_counter);
bool DoState(StateWrapper& sw);
void RunEvents();