I am having difficulty passing Gekkio's rapid_toggle timer test. The test sets BC to $FFFF and then it rapidly toggles the timer on and off, decrementing BC during each iteration:
The idea is that toggling the timer in this manner affects TIMA; i.e. from the wiki, "When writing to TAC, if the previously selected multiplexer input was '1' and the new input is '0', TIMA will increase too."
Incrementing TIMA decreases the amount of time until the Timer Interrupt gets triggered, which terminates the test. At the end of the test, BC is expected to be $FFD9. But, I'm getting $FFD8; DEC BC executes one too many times.
Since TIMA is incremented based on a falling bit value, that means that the Timer Interrupt needs to happen between LDH (<TAC), A and DEC BC. And, that would be possible if the TAC write immediately set IF. But, according to the wiki, it doesn't: "When TIMA overflows, the value from TMA is loaded and IF timer flag is set to 1, but this doesn't happen immediately. Timer interrupt is delayed 1 cycle (4 clocks) from the TIMA overflow. The TMA reload to TIMA is also delayed. For one cycle, after overflowing TIMA, the value in TIMA is 00h, not TMA. This happens only when an overflow happens, not when the upper bit goes from 1 to 0, it can't be done manually writing to TIMA, the timer has to increment itself."
In other words, the wiki suggests that the Timer Interrupt would be delayed until after DEC BC, which is what my emulation is experiencing. What am I missing?!
Code:
ld bc, $FFFF
ei
- ld a, %00000100 ; Start 4096 Hz timer
ldh (<TAC), a
ld a, %00000000 ; Stop timer
ldh (<TAC), a
dec bc
ld a, c
or b
jr nz, -
ei
- ld a, %00000100 ; Start 4096 Hz timer
ldh (<TAC), a
ld a, %00000000 ; Stop timer
ldh (<TAC), a
dec bc
ld a, c
or b
jr nz, -
The idea is that toggling the timer in this manner affects TIMA; i.e. from the wiki, "When writing to TAC, if the previously selected multiplexer input was '1' and the new input is '0', TIMA will increase too."
Incrementing TIMA decreases the amount of time until the Timer Interrupt gets triggered, which terminates the test. At the end of the test, BC is expected to be $FFD9. But, I'm getting $FFD8; DEC BC executes one too many times.
Since TIMA is incremented based on a falling bit value, that means that the Timer Interrupt needs to happen between LDH (<TAC), A and DEC BC. And, that would be possible if the TAC write immediately set IF. But, according to the wiki, it doesn't: "When TIMA overflows, the value from TMA is loaded and IF timer flag is set to 1, but this doesn't happen immediately. Timer interrupt is delayed 1 cycle (4 clocks) from the TIMA overflow. The TMA reload to TIMA is also delayed. For one cycle, after overflowing TIMA, the value in TIMA is 00h, not TMA. This happens only when an overflow happens, not when the upper bit goes from 1 to 0, it can't be done manually writing to TIMA, the timer has to increment itself."
In other words, the wiki suggests that the Timer Interrupt would be delayed until after DEC BC, which is what my emulation is experiencing. What am I missing?!