When timer2 counts down to zero it continues into the negative so that it is possible to determine how many cycles ago it reached zero.
However, if an internal clock overflow occurs while the timer2 is in the negative then it is not updated correctly and will contain the wrong cycle count. I think the problem is in the internal function viacore_clk_overflow_callback in viacore.c that is supposed to fix the overflow condition. It seems to handle timer2 as if it behaves like timer1 which I think is wrong.
Here's a link to a test program that uses the negative count to adjust the value used to program the next timer2 value to keep it in sync with the raster. It also waits half a frame in the handler before reading and reprogramming the timer in order to trigger the bug more reliably. When run for about 2^32 cycles (use warp-speed) the stable bckground/border color change will jump visibly due to the bad overflow fixup and stabilize at a different position.
Here's a patch to viacore.c that fixes the problem for me. (I have not run any other tests with it so it might break other things)
Code: Select all
Index: src/core/viacore.c
===================================================================
--- src/core/viacore.c (revision 22723)
+++ src/core/viacore.c (arbetskopia)
@@ -843,9 +843,7 @@
((*(via_context->clk_ptr) + sub - via_context->tau)
% (via_context->tal + 2));
- via_context->tbu = via_context->tbl + 2 -
- ((*(via_context->clk_ptr) + sub - via_context->tbu)
- % (via_context->tbl + 2));
+ via_context->tbu -= sub;
if (via_context->tai) {
via_context->tai -= sub;