Re: [stella] Timers "bug" discovered!

Subject: Re: [stella] Timers "bug" discovered!
From: Rodrigo Silva <stella@xxxxxxxxxxxxx>
Date: Wed, 24 Sep 2003 03:25:12 -0300
Hi All!

It seems I found out what was going wrong with the timers. As soon as you store a number in TIM64T, it *IMMEDIATLY* decrements it! So, in the following code:

lda #3
sta TIM64T

after the last instruction, accumulator value is 2, not 3 as it "should" be! From the Z26 trace log:

( 0 1 0 -68) ( 97 97 96 96 96) nvbdiZc 00 00 00 ff f000: a9 03 lda #03
( 0 1 2 -62) ( 97 97 96 96 96) nvbdizc 03 00 00 ff f002: 8d 96 02 sta TIM64T
( 0 1 6 -50) ( 97 97 96 96 96) nvbdizc 03 00 00 ff f005: ad 84 02 lda INTIM
( 0 1 10 -38) ( 97 97 96 96 96) nvbdizc 02 00 00 ff f008: 4c 00 f0 jmp f000

The column after "nvbdiZc" in each line shows the accumulator content right before executing the line's instruction, or, in other words, right after the execution of the previous instruction. And, in our example, it shows accumulator going from 0 to 3 to 2, even if we had just started the timer.

And why it acts this way?

I have a theory. From the Bibl... oops, Stella Programmers Guide:

"The PIA decrements the value or count loaded into it once each interval until it reaches 0. It holds that 0 counts for one interval, then the counter
flips to FF(HEX) and decrements once each clock cycle, rather than once per interval."

This way we have a full interval at 0, and *we must wait for it*. So, when we set the timer to 3, it immediatly decrements from 3 to 2, then it wait 64 cycles, go to 1, wait more 64, goes to zero, and then waits 64 cycles before flipping to FF.

If we use a BNE to test if the time is over, as we usually do, it would be triggered somewhere in the beggining of the last interval, and thus a lot less then 3*64 cycles would have passed! (actually, would have passed at most 2*64 + 4 or 5)

To fix this problem, one can do one of the following:

- Simply add +1 to the desired timer. So, if your math says you must wait 43 intervals (typical VBlank timer), go for 43+1 = 44

- Change the comparison from BNE to BPL. Then the wait loop will go on until timer goes from 0 to FF (-1). This way you will fully wait the last interval, and only stop when timer goes negative. I guess this is the "natural way", the way the timers were designed to be used (I dont think you were supposed to add +1 just for Stella decrement it as soon as the timer starts)

The only problem with this method is that you cant use the timer with a value higher then 128, because BPL would think it is a negative value, and timer loop would end in the first test.

This said, ive found something in the "Stella Programmers Guide" that, if its not wrong, its at least misleading:

"For example, if the value of 100 were written to TIM64T (HEX address 296) the timer would decrement to 0 in 6400 clocks (64 clocks per interval x 100 intervals)"

Nope... actually it would decrement to 0 in 99*64=6336 clocks. In 6400 clocks it would decrement *from* 0 to FF.

And also,

"The timer may be read any number of times after it is loaded of course, but the programmer is usually interested in whether or not the timer has reached 0."

Actually, he is usually interested when it reaches FF, not 0.

All of this were tested only with the TIM64T Timer, but it should hold true for the olher timers as well. Actually, its hard to test with such small timers as TIM8T, as the management loop (lda INTIM / BNE) would waste almost a full interval...

Btw... was this a known behaviour of the timers? If so, sorry for bothering you... I Tried to search the Stella archives, but find nothing about it... and guess the Stella guide is really misleading... so i guess its worth to post such a huge email with this "add +1 or change to BPL when using timers" hint ;)

Thats all folks..

PS: now my template works frawlessly! :)

Archives (includes files) at
Unsub & more at

Current Thread