GPU: Tweaks to ODE handling
Fixes Team Buddies and The Next Tetris.
This commit is contained in:
parent
a8699d9908
commit
d4665e8b22
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 = {};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue