I've finally gotten the ultimate clock timing code working on the NES. With it, you can find out how many clocks a piece of code took, only executing it once. It uses the DMC as a timebase, and can measure from 0 to around 3380 clocks. nes_code_timer.zip (ca65 source only)
For example, this measures how long sprite DMA takes:
I've found some interesting things with it:
* Sprite DMA takes 513/514 clocks, depending on whether it's started on an even or odd clock.
* DMC DMA read normally takes 4 clocks, but only 3 if a memory write is occurring at a critical moment (the write probably cuts the DMA read short).
* Starting a DMC sample can add 3 or 4 clocks if the sample byte needs to be read immediately. It seems to depend on whether the write is on an even or odd clock.
It's also a convenient way to time a short routine (assuming you can quickly upload new code to your NES, that is). Don't expect it to work on emulators yet, as it probably depends on some aspects of the DMC not yet fully documented.
The timing technique is fairly simple. It is composed of two parts: synchronization and elapsed time determination.
Synchronization: Let's say there's a digital clock that only shows minutes (no seconds), and you want to be looking at it right when the minutes change, but you can only look at it for a second at a time, and must wait at least 10 seconds between checks. How do you efficiently arrange it so you're looking at it the moment the minutes change? First, make a note of the current time, then check it every 10 seconds until the time has changed sometime between checks. At that point, begin checking it every 59 seconds. Within ten minutes you will be observing it the moment the minutes change.
Elapsed time: Now that you looked at the clock the moment the minutes changed, you can go do some short task that takes under a minute, then come back to the clock and determine how long the task took, to an accuracy of one second, even though you can only look at the clock no more often than once every 10 seconds. How? Check the clock once every 59 seconds until the minutes change as you're watching. The number of times you check is the number of seconds the task took.
The key concept here is that even though we can't check every second, we can effectively check every second by checking every 59 seconds, since the 59th second is equivalent to the previous second, relative to a change in minutes.
For example, this measures how long sprite DMA takes:
Code:
jsr time_code_begin
lda #1
sta $4014
jsr time_code_end
jsr print_dec_xa ; prints 520
lda #1
sta $4014
jsr time_code_end
jsr print_dec_xa ; prints 520
I've found some interesting things with it:
* Sprite DMA takes 513/514 clocks, depending on whether it's started on an even or odd clock.
* DMC DMA read normally takes 4 clocks, but only 3 if a memory write is occurring at a critical moment (the write probably cuts the DMA read short).
* Starting a DMC sample can add 3 or 4 clocks if the sample byte needs to be read immediately. It seems to depend on whether the write is on an even or odd clock.
It's also a convenient way to time a short routine (assuming you can quickly upload new code to your NES, that is). Don't expect it to work on emulators yet, as it probably depends on some aspects of the DMC not yet fully documented.
The timing technique is fairly simple. It is composed of two parts: synchronization and elapsed time determination.
Synchronization: Let's say there's a digital clock that only shows minutes (no seconds), and you want to be looking at it right when the minutes change, but you can only look at it for a second at a time, and must wait at least 10 seconds between checks. How do you efficiently arrange it so you're looking at it the moment the minutes change? First, make a note of the current time, then check it every 10 seconds until the time has changed sometime between checks. At that point, begin checking it every 59 seconds. Within ten minutes you will be observing it the moment the minutes change.
Code:
Check ------C----------C----------C----------C
Minutes ---M-----------M-----------M-----------M
Minutes ---M-----------M-----------M-----------M
Elapsed time: Now that you looked at the clock the moment the minutes changed, you can go do some short task that takes under a minute, then come back to the clock and determine how long the task took, to an accuracy of one second, even though you can only look at the clock no more often than once every 10 seconds. How? Check the clock once every 59 seconds until the minutes change as you're watching. The number of times you check is the number of seconds the task took.
Code:
Check -------C----------C----------C----------C----------C
Minutes ---M-----------M-----------M-----------M-----------M
Minutes ---M-----------M-----------M-----------M-----------M
The key concept here is that even though we can't check every second, we can effectively check every second by checking every 59 seconds, since the 59th second is equivalent to the previous second, relative to a change in minutes.