Skip to content

Commit

Permalink
Timer: handle timer overflow during one cycle enable delay (thanks al…
Browse files Browse the repository at this point in the history
…yosha) (fixes #331)
  • Loading branch information
fleroviux committed Oct 5, 2023
1 parent e0af850 commit 8fb8743
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions src/nba/src/hw/timer/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,28 @@ void Timer::OnControlWritten(u64 chan_id) {
channel.mask = g_ticks_mask[control.frequency];

if(control.enable) {
if(!enable_previous) {
channel.counter = channel.reload;
}
const int late = scheduler.GetTimestampNow() & channel.mask;

if(!control.cascade) {
auto late = (scheduler.GetTimestampNow() & channel.mask);
if(!enable_previous) {
late -= 1;
if(enable_previous) {
if(!control.cascade) {
StartChannel(channel, late);
}
} else {
if(control.cascade) {
channel.counter = channel.reload;
} else if(channel.counter == 0xFFFF && late == 0) {
/**
* After enabling a timer, it takes one cycle to load the reload value into the counter.
* During this cycle, the timer can tick and may even overflow.
* We handle this edge-case here.
*
* See: https://github.com/nba-emu/NanoBoyAdvance/issues/331
*/
StartChannel(channel, 0);
} else {
channel.counter = channel.reload;
StartChannel(channel, late - 1);
}
StartChannel(channel, late);
}
}
}
Expand Down

0 comments on commit 8fb8743

Please sign in to comment.