Minor 6522 VIA bug
The following program gives different results on a real BBC and B-Em:


I first noticed this bug when writing a VIA driven memory test on the Atom - Atomulator also suffers as well.
In both implements (which originate from Sarah) when T2-Latch is transferred to T2-Counter, then +1 is added.
This may be correct if T2 is in counter mode (actually I doubt this), but it's wrong if T2 is in free-running mode.
I don't yet have a fix for Atomulator.
Dave
Related to: https://github.com/stardot/b-em/issues/168
Dave, Sorry I did read this earlier, then concluded that it may be more complicated than it first appears to so didn't examine it further as I was about to do something else.
I have a vague memory that someone pointed out previously that there was an off-by-one error in the way the 6502 in B-Em responded to timer interrupts and yet attempts to correct this stopped it from loading some protected game that was known to be particularly sensitive to this timing. It was suggested at the time that there may be a pair of compensating errors so that attempting to fix one without the other broke the timing overall.
This may very well be the other error of the pair but it means ideally we want to rediscover what the first error was, find the game that works as a test case, and fix them both.
For reference, the currently deployed JSBEEB gets this correct:

As does a recent build (1ff3a110) of BeebJIT:

In BeebJIT the +1 is only added if the counter is in free-running mode:
case k_via_T2CH:
if (!t2_firing) {
via_clear_interrupt(p_via, k_int_TIMER2);
}
p_via->T2L = ((val << 8) | (p_via->T2L & 0xFF));
timer_val = p_via->T2L;
/* Increment the value because it must take effect in 1 tick. */
if (!(p_via->ACR & 0x20)) {
timer_val++;
}
via_set_t2c(p_via, timer_val);
timing_set_firing(p_timing, p_via->t2_timer_id, 1);
break;
In JSBEEB it's a bit more complicated, because they seem to model half-ticks. In T2 pulse counting mode the +1 is in effect undone:
case T2CH:
self.t2l &= 0x1fe;
self.t2l |= (val << 9);
self.t2c = self.t2l + 1;
if (self.acr & 0x20) self.t2c -= 2;
if (!(self.justhit & 2)) {
self.ifr &= ~TIMER2INT;
self.updateIFR();
}
self.t2hit = false;
break;
I'll do something similar to beebjit in Atomulator.
I found the test I was thunking of - Nighshade. I have fixed this and Nightshade still works. See https://github.com/stardot/b-em/commit/415f523bdc5bae5800a2e496e6f66bc4a6a4e30e