Timers: Handle target = 0 case
Fixes Super Gals! Kotobuki Ran Special - Ikemen Get You Gals Party hanging at boot.
This commit is contained in:
parent
537f833658
commit
ef97131c9d
|
@ -129,20 +129,21 @@ void Timers::AddTicks(u32 timer, TickCount count)
|
||||||
CounterState& cs = m_states[timer];
|
CounterState& cs = m_states[timer];
|
||||||
const u32 old_counter = cs.counter;
|
const u32 old_counter = cs.counter;
|
||||||
cs.counter += static_cast<u32>(count);
|
cs.counter += static_cast<u32>(count);
|
||||||
|
CheckForIRQ(timer, old_counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timers::CheckForIRQ(u32 timer, u32 old_counter)
|
||||||
|
{
|
||||||
|
CounterState& cs = m_states[timer];
|
||||||
|
|
||||||
bool interrupt_request = false;
|
bool interrupt_request = false;
|
||||||
if (cs.counter >= cs.target && old_counter < cs.target)
|
if (cs.counter >= cs.target && (old_counter < cs.target || cs.target == 0))
|
||||||
{
|
{
|
||||||
interrupt_request |= cs.mode.irq_at_target;
|
interrupt_request |= cs.mode.irq_at_target;
|
||||||
cs.mode.reached_target = true;
|
cs.mode.reached_target = true;
|
||||||
|
|
||||||
if (cs.mode.reset_at_target)
|
if (cs.mode.reset_at_target && cs.target > 0)
|
||||||
{
|
cs.counter %= cs.target;
|
||||||
if (cs.target > 0)
|
|
||||||
cs.counter %= cs.target;
|
|
||||||
else
|
|
||||||
cs.counter = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (cs.counter >= 0xFFFF)
|
if (cs.counter >= 0xFFFF)
|
||||||
{
|
{
|
||||||
|
@ -265,12 +266,15 @@ void Timers::WriteRegister(u32 offset, u32 value)
|
||||||
|
|
||||||
m_sysclk_event->InvokeEarly();
|
m_sysclk_event->InvokeEarly();
|
||||||
|
|
||||||
|
// Strictly speaking these IRQ checks should probably happen on the next tick.
|
||||||
switch (port_offset)
|
switch (port_offset)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
{
|
{
|
||||||
|
const u32 old_counter = cs.counter;
|
||||||
Log_DebugPrintf("Timer %u write counter %u", timer_index, value);
|
Log_DebugPrintf("Timer %u write counter %u", timer_index, value);
|
||||||
cs.counter = value & u32(0xFFFF);
|
cs.counter = value & u32(0xFFFF);
|
||||||
|
CheckForIRQ(timer_index, old_counter);
|
||||||
if (timer_index == 2 || !cs.external_counting_enabled)
|
if (timer_index == 2 || !cs.external_counting_enabled)
|
||||||
UpdateSysClkEvent();
|
UpdateSysClkEvent();
|
||||||
}
|
}
|
||||||
|
@ -287,6 +291,7 @@ void Timers::WriteRegister(u32 offset, u32 value)
|
||||||
cs.irq_done = false;
|
cs.irq_done = false;
|
||||||
|
|
||||||
UpdateCountingEnabled(cs);
|
UpdateCountingEnabled(cs);
|
||||||
|
CheckForIRQ(timer_index, cs.counter);
|
||||||
UpdateIRQ(timer_index);
|
UpdateIRQ(timer_index);
|
||||||
UpdateSysClkEvent();
|
UpdateSysClkEvent();
|
||||||
}
|
}
|
||||||
|
@ -296,6 +301,7 @@ void Timers::WriteRegister(u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("Timer %u write target 0x%04X", timer_index, ZeroExtend32(Truncate16(value)));
|
Log_DebugPrintf("Timer %u write target 0x%04X", timer_index, ZeroExtend32(Truncate16(value)));
|
||||||
cs.target = value & u32(0xFFFF);
|
cs.target = value & u32(0xFFFF);
|
||||||
|
CheckForIRQ(timer_index, cs.counter);
|
||||||
if (timer_index == 2 || !cs.external_counting_enabled)
|
if (timer_index == 2 || !cs.external_counting_enabled)
|
||||||
UpdateSysClkEvent();
|
UpdateSysClkEvent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void UpdateCountingEnabled(CounterState& cs);
|
void UpdateCountingEnabled(CounterState& cs);
|
||||||
|
void CheckForIRQ(u32 index, u32 old_counter);
|
||||||
void UpdateIRQ(u32 index);
|
void UpdateIRQ(u32 index);
|
||||||
|
|
||||||
void AddSysClkTicks(TickCount sysclk_ticks);
|
void AddSysClkTicks(TickCount sysclk_ticks);
|
||||||
|
|
Loading…
Reference in New Issue