b-em icon indicating copy to clipboard operation
b-em copied to clipboard

Minor 6522 VIA bug

Open hoglet67 opened this issue 3 years ago • 5 comments

The following program gives different results on a real BBC and B-Em: capture5

Screenshot from 2022-04-25 15-44-37

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

hoglet67 avatar Apr 25 '22 14:04 hoglet67

Related to: https://github.com/stardot/b-em/issues/168

hoglet67 avatar Apr 27 '22 16:04 hoglet67

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.

SteveFosdick avatar Apr 27 '22 19:04 SteveFosdick

For reference, the currently deployed JSBEEB gets this correct: Screenshot from 2022-04-28 10-31-17

As does a recent build (1ff3a110) of BeebJIT: Screenshot from 2022-04-28 10-33-25

hoglet67 avatar Apr 28 '22 09:04 hoglet67

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.

hoglet67 avatar Apr 28 '22 09:04 hoglet67

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

SteveFosdick avatar Sep 03 '22 20:09 SteveFosdick