mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
GPU: Implement dot clock timer (Timer 0)
Fixes softlock in Evil Dead - Hail to the King.
This commit is contained in:
parent
8b3426a96e
commit
d757056891
|
@ -91,6 +91,7 @@ void GPU::SoftReset()
|
|||
m_crtc_state.regs.horizontal_display_range = 0xC60260;
|
||||
m_crtc_state.regs.vertical_display_range = 0x3FC10;
|
||||
m_crtc_state.fractional_ticks = 0;
|
||||
m_crtc_state.fractional_dot_ticks = 0;
|
||||
m_crtc_state.current_tick_in_scanline = 0;
|
||||
m_crtc_state.current_scanline = 0;
|
||||
m_crtc_state.in_hblank = false;
|
||||
|
@ -172,6 +173,7 @@ bool GPU::DoState(StateWrapper& sw, bool update_display)
|
|||
sw.Do(&m_crtc_state.fractional_ticks);
|
||||
sw.Do(&m_crtc_state.current_tick_in_scanline);
|
||||
sw.Do(&m_crtc_state.current_scanline);
|
||||
sw.DoEx(&m_crtc_state.fractional_dot_ticks, 46, 0);
|
||||
sw.Do(&m_crtc_state.in_hblank);
|
||||
sw.Do(&m_crtc_state.in_vblank);
|
||||
sw.Do(&m_crtc_state.interlaced_field);
|
||||
|
@ -679,15 +681,21 @@ TickCount GPU::GetPendingCommandTicks() const
|
|||
void GPU::UpdateCRTCTickEvent()
|
||||
{
|
||||
// figure out how many GPU ticks until the next vblank or event
|
||||
const TickCount lines_until_vblank =
|
||||
TickCount lines_until_event =
|
||||
(m_crtc_state.current_scanline >= m_crtc_state.vertical_display_end ?
|
||||
(m_crtc_state.vertical_total - m_crtc_state.current_scanline + m_crtc_state.vertical_display_end) :
|
||||
(m_crtc_state.vertical_display_end - m_crtc_state.current_scanline));
|
||||
const TickCount lines_until_event = g_timers.IsExternalIRQEnabled(HBLANK_TIMER_INDEX) ?
|
||||
std::min(g_timers.GetTicksUntilIRQ(HBLANK_TIMER_INDEX), lines_until_vblank) :
|
||||
lines_until_vblank;
|
||||
const TickCount ticks_until_event =
|
||||
if (g_timers.IsExternalIRQEnabled(HBLANK_TIMER_INDEX))
|
||||
lines_until_event = std::min(lines_until_event, g_timers.GetTicksUntilIRQ(HBLANK_TIMER_INDEX));
|
||||
|
||||
TickCount ticks_until_event =
|
||||
lines_until_event * m_crtc_state.horizontal_total - m_crtc_state.current_tick_in_scanline;
|
||||
if (g_timers.IsExternalIRQEnabled(DOT_TIMER_INDEX))
|
||||
{
|
||||
const TickCount dots_until_irq = g_timers.GetTicksUntilIRQ(DOT_TIMER_INDEX);
|
||||
const TickCount ticks_until_irq = (dots_until_irq * m_crtc_state.dot_clock_divider) - m_crtc_state.fractional_dot_ticks;
|
||||
ticks_until_event = std::min(ticks_until_event, std::max<TickCount>(ticks_until_irq, 0));
|
||||
}
|
||||
|
||||
#if 0
|
||||
const TickCount ticks_until_hblank =
|
||||
|
@ -715,6 +723,15 @@ void GPU::CRTCTickEvent(TickCount ticks)
|
|||
{
|
||||
const TickCount gpu_ticks = SystemTicksToCRTCTicks(ticks, &m_crtc_state.fractional_ticks);
|
||||
m_crtc_state.current_tick_in_scanline += gpu_ticks;
|
||||
|
||||
if (g_timers.IsUsingExternalClock(DOT_TIMER_INDEX))
|
||||
{
|
||||
m_crtc_state.fractional_dot_ticks += gpu_ticks;
|
||||
const TickCount dots = m_crtc_state.fractional_dot_ticks / m_crtc_state.dot_clock_divider;
|
||||
m_crtc_state.fractional_dot_ticks = m_crtc_state.fractional_dot_ticks % m_crtc_state.dot_clock_divider;
|
||||
if (dots > 0)
|
||||
g_timers.AddTicks(DOT_TIMER_INDEX, dots);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_crtc_state.current_tick_in_scanline < m_crtc_state.horizontal_total)
|
||||
|
|
|
@ -501,6 +501,8 @@ protected:
|
|||
TickCount current_tick_in_scanline;
|
||||
u32 current_scanline;
|
||||
|
||||
TickCount fractional_dot_ticks; // only used when timer0 is enabled
|
||||
|
||||
bool in_hblank;
|
||||
bool in_vblank;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
|
||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 45;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 46;
|
||||
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
||||
|
||||
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
||||
|
|
Loading…
Reference in a new issue