lidnariq wrote: ↑
Thu May 07, 2020 11:05 am
Even a perfect M2-based IRQ without slip will still have problems due to the noninteger M2 cycles per wanted IRQ.
Nothing that can't be easily compensated for by software though.
The real problem is that there's a latency of up to 7 CPU cycles when calling the IRQ handler, depending on the instruction the CPU is running (and how far into it the CPU is) when the interrupt request is made. That's 7 CPU cycles, or 21 pixels in NTSC. The PPU auto-increments the X scroll every 8 pixels, so it may end up incrementing several times in that 21-pixel window, and since the latency varies each time you can't predict what the X scroll should be at the time you update it, resulting in bad horizontal jitter in the scanlines where the scroll changes. Your theory about "always before" and "always after" doesn't hold up when auto-increments happen every 8 pixels and the latency is between 0 and 21 pixels! There's just no way to make the scroll change happen consistently between 2 specific auto-increments, no matter how far into the scanline.
Oh... I though for some reason there was a window void of auto-increments both before and after the reload. I suppose I didn't do enough nesdev lately. So I suppose the following would work (if you go for the IRQ each 4 lines, add two more tables and two $2005 writes inbetween).
Code: Select all
sta irq_zp_save_a ;3
stx irq_zp_save_x ;6
ldx irqnum ;9
lda scrolltableh,x ;13
sta $2006 ;17
; 2 $2005 writes can optionally be added there if needed
lda scrolltablel,x ;21
sta $2006 ;25
sta $2005 ; reset the horizontal scroll that might have been screwed up if the IRQ interupted a long instruction
sta $2005 ; (needed for latch alignment only; could be replaced with a bit $2002 at the start of the IRQ)
; (code to reload MMC3 IRQ here)
; (code to stop the chain of IRQ and set scroll/CHR bank for the HUD correctly)
Last but not least, it is seems rather simple to avoid 6502 instructions using 7 CPU cycles entierely :
- LSR $abcd,X
- ASL $abcd,X
- ROL $abcd,X
- ROR $abcd,X
- INC $abcd,X
- DEC $abcd,X
If you ever need to shift, rotate, increment or decrement an array put it in zero page. This would reduce possible jitter to 6 cycles or 18 pixels.