Closed ullenius closed 1 year ago
const long timertc = (256 - tma) * (16 << (((tac) & 3) << 1));
Thats not actually the code in gbs.c, which version of the code were you looking at?
The actual code in gbs.c is:
long timertc = (256-gbs->tma) * (16 << (((gbs->tac+3) & 3) << 1));
which also matches gbhw.c:
gbhw->timertc = 16 << (((val+3) & 3) << 1);
The first thing it does is rotate the value by three, so the table (for modified val) becomes regular:
00: 262144 01: 65536 10: 16384 11: 4096
The actual timer base Hz is the GBHW_CLOCK / timertc, so the formula (ignoring TMA for now) then becomes:
const long timerbase = (4194304 / (16 << (((tac + 3) & 3) << 1)));
printf("timerbase: %ld\n", timerbase);
Adjusting your code for that I get:
$ gcc -o /tmp/tac /tmp/tac.c
$ /tmp/tac
00: 4096
01: 262144
10: 65536
11: 16384
----current code---
tac: 0
timerbase: 4096
tac: 1
timerbase: 262144
tac: 2
timerbase: 65536
tac: 3
timerbase: 16384
Which matches (so the code in ghbw.c is correct) and is the rate at which TIMA increases. Now TMA is reload value for TIMA when it overflows, so effectively the divider: TMA 0 -> 256 base clocks per interrupt, TIMA restarts at 0 TMA 1 -> 255 base clocks per interrupt, TIMA restarts at 1 TMA 255 -> 1 base clock per interrupt, TIMA restarts at 255
So the correct full formula should be:
const double timerirqhz = (4194304.0 / (16 << (((tac + 3) & 3) << 1))) / (256 - tma)
What gbs.c currently does is:
long timertc = (256-gbs->tma) * (16 << (((gbs->tac+3) & 3) << 1));
float hz = GBHW_CLOCK / (float)timertc;
So that is 4194304.0 / ((256 - tma) * (16 << (((tac+3) & 3) << 1)
.
I can reorder the multiplication:
4194304.0 / ((16 << (((tac+3) & 3) << 1)) * (256 - tma))
And move it out of the brackets:
4194304.0 / (16 << (((tac+3) & 3) << 1) / (256 - tma)
And now we can see that it should be correct already (same as the "correct full formula" above).
(Unless I made a mistake here somewhere)
Granted, the existing code is a bit hard to follow...
From the 1.04u spec (url )
I believe there's a bug in this line in
gbs.c
We extract this code to a separate function. And then compare it to a more explicit mapping we get different results.
Running this results in:
TL;DR
The current code has swapped the mappings for tac 01 and 11 (see results above).