mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 23:25:41 +00:00
GPU: Fix timer 1 IRQs sometimes triggering late
Should hopefully fix missing voices in Akuji the Heartless.
This commit is contained in:
parent
a5ff904b33
commit
5a1b00825d
|
@ -568,20 +568,26 @@ TickCount GPU::GetPendingGPUTicks() const
|
||||||
|
|
||||||
void GPU::UpdateSliceTicks()
|
void GPU::UpdateSliceTicks()
|
||||||
{
|
{
|
||||||
// figure out how many GPU ticks until the next vblank
|
// figure out how many GPU ticks until the next vblank or event
|
||||||
const TickCount lines_until_vblank =
|
const TickCount lines_until_vblank =
|
||||||
(m_crtc_state.current_scanline >= m_crtc_state.vertical_display_end ?
|
(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_total - m_crtc_state.current_scanline + m_crtc_state.vertical_display_end) :
|
||||||
(m_crtc_state.vertical_display_end - m_crtc_state.current_scanline));
|
(m_crtc_state.vertical_display_end - m_crtc_state.current_scanline));
|
||||||
const TickCount ticks_until_vblank =
|
const TickCount lines_until_event = m_timers->IsExternalIRQEnabled(HBLANK_TIMER_INDEX) ?
|
||||||
lines_until_vblank * m_crtc_state.horizontal_total - m_crtc_state.current_tick_in_scanline;
|
std::min(m_timers->GetTicksUntilIRQ(HBLANK_TIMER_INDEX), lines_until_vblank) :
|
||||||
|
lines_until_vblank;
|
||||||
|
const TickCount ticks_until_event =
|
||||||
|
lines_until_event * m_crtc_state.horizontal_total - m_crtc_state.current_tick_in_scanline;
|
||||||
|
|
||||||
|
#if 0
|
||||||
const TickCount ticks_until_hblank =
|
const TickCount ticks_until_hblank =
|
||||||
(m_crtc_state.current_tick_in_scanline >= m_crtc_state.horizontal_display_end) ?
|
(m_crtc_state.current_tick_in_scanline >= m_crtc_state.horizontal_display_end) ?
|
||||||
(m_crtc_state.horizontal_total - m_crtc_state.current_tick_in_scanline + m_crtc_state.horizontal_display_end) :
|
(m_crtc_state.horizontal_total - m_crtc_state.current_tick_in_scanline + m_crtc_state.horizontal_display_end) :
|
||||||
(m_crtc_state.horizontal_display_end - m_crtc_state.current_tick_in_scanline);
|
(m_crtc_state.horizontal_display_end - m_crtc_state.current_tick_in_scanline);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_tick_event->Schedule(
|
m_tick_event->Schedule(
|
||||||
GPUTicksToSystemTicks((m_command_ticks > 0) ? std::min(m_command_ticks, ticks_until_vblank) : ticks_until_vblank));
|
GPUTicksToSystemTicks((m_command_ticks > 0) ? std::min(m_command_ticks, ticks_until_event) : ticks_until_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU::IsRasterScanlinePending() const
|
bool GPU::IsRasterScanlinePending() const
|
||||||
|
|
|
@ -89,6 +89,21 @@ void Timers::SetGate(u32 timer, bool state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TickCount Timers::GetTicksUntilIRQ(u32 timer) const
|
||||||
|
{
|
||||||
|
const CounterState& cs = m_states[timer];
|
||||||
|
if (!cs.counting_enabled)
|
||||||
|
return std::numeric_limits<TickCount>::max();
|
||||||
|
|
||||||
|
TickCount ticks_until_irq = std::numeric_limits<TickCount>::max();
|
||||||
|
if (cs.mode.irq_at_target)
|
||||||
|
ticks_until_irq = static_cast<TickCount>(cs.target - cs.counter);
|
||||||
|
if (cs.mode.irq_on_overflow)
|
||||||
|
ticks_until_irq = std::min(ticks_until_irq, static_cast<TickCount>(0xFFFFu - cs.counter));
|
||||||
|
|
||||||
|
return ticks_until_irq;
|
||||||
|
}
|
||||||
|
|
||||||
void Timers::AddTicks(u32 timer, TickCount count)
|
void Timers::AddTicks(u32 timer, TickCount count)
|
||||||
{
|
{
|
||||||
CounterState& cs = m_states[timer];
|
CounterState& cs = m_states[timer];
|
||||||
|
|
|
@ -27,6 +27,16 @@ public:
|
||||||
|
|
||||||
// dot clock/hblank/sysclk div 8
|
// dot clock/hblank/sysclk div 8
|
||||||
bool IsUsingExternalClock(u32 timer) const { return m_states[timer].external_counting_enabled; }
|
bool IsUsingExternalClock(u32 timer) const { return m_states[timer].external_counting_enabled; }
|
||||||
|
|
||||||
|
// queries for GPU
|
||||||
|
bool IsExternalIRQEnabled(u32 timer) const
|
||||||
|
{
|
||||||
|
const CounterState& cs = m_states[timer];
|
||||||
|
return (cs.external_counting_enabled && (cs.mode.bits & ((1u << 4) | (1u << 5))) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TickCount GetTicksUntilIRQ(u32 timer) const;
|
||||||
|
|
||||||
void AddTicks(u32 timer, TickCount ticks);
|
void AddTicks(u32 timer, TickCount ticks);
|
||||||
|
|
||||||
u32 ReadRegister(u32 offset);
|
u32 ReadRegister(u32 offset);
|
||||||
|
@ -89,5 +99,5 @@ private:
|
||||||
std::unique_ptr<TimingEvent> m_sysclk_event;
|
std::unique_ptr<TimingEvent> m_sysclk_event;
|
||||||
|
|
||||||
std::array<CounterState, NUM_TIMERS> m_states{};
|
std::array<CounterState, NUM_TIMERS> m_states{};
|
||||||
u32 m_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8
|
u32 m_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue