Using DMC IRQs for raster effects requires a significant amount of voodoo that I could never fully grasp, and it comes with plenty of downsides even when pulled off correctly.
Well the $2006 only approach has the advantage of allowing very short irqs, something like
Code: Select all
sta zp_save_a ; 3
lda scroll_l ; 6
sta $2006 ; 10
clc ; 12
adc #$20 ; 14
sta scroll_l ; 17
lda scroll_h ; 20
adc #$00 ; 22
sta $2006 ; 26
; retrigger MMC3 IRQ 2 lines latter here (I'm not familiar with the mapper)
becomes possible. I don't know whether 26 cycles delay between IRQ start and the $2006.2 store is acceptable, but it's definitely faster than f***ing with $2005.
You can't do that because the IRQ latency will cause the scroll change to take place between the automatic X scroll increments that happen at the end of hblank. This is the very problem I described in the first post, which makes the waiting for the next hblank necessary.
And unlike DMC IRQs, I have a lot of practice with $2006/5/5/6 scroll changes and nothing but success when doing it. It's a very simple and reliable trick, and really easy to align with hblank, considering that only the final 2 writes must take place during hblank (if the X scroll doesn't change, only the last cycle of the last write needs to happen during hblank!).
You might also consider 3-pixel tall metapixels, it seems you had only considered 2 or 4 so far.
I considered 3, but that would align poorly with the sprites, interfering with sprite clipping. And in my tests, honestly, 3 didn't look much better than 4.
If this is still not enough the only suggestion I have is changing the mapper to something capable of triggering an IRQ at a given CPU cycle time, such as Konami VRC mappers or the Famicom Disk System.
But then that introduces the problem of IRQ latency buildup, unless there's a mapper out there that automatically reloads the previous cycle count and keeps counting without interference from the programmer, but I'm not aware of any.
You could interleave your code computing the raycast with code dealing with scrolling writes like I did for the second version of my rotation demo, but I highly disrecommand this as this makes code that is extremely unmaintenable and inflexible.
You mean using timed code for the raycasting logic? Yeah, I considered that, but I'm afraid it would cause even more cycles to be wasted than if waiting for the next hblank after an MMC3 IRQ.
Fiskbit wrote: ↑
Thu May 07, 2020 1:31 am
If you do have to burn full scanlines, I'd suggest swapping the BG and sprite tables (sprites at $0000, BG at $1000) to make the scanline IRQ trigger later, reducing the amount of time you have to waste. I'd also see if maybe there's a way you can do fixed-time work during the waiting period so it's not all wasted, even if there's some overhead to it.
Yeah, that's probably what I'll end up doing. I'll definitely be doing all scrolling-related tasks during that time (updating counters, computing the values to be written to the PPU registers, and so on. I'll see if I can fit anything else in there.
I know you really want to use MMC3, but if there isn't a good solution here, the CPU gains in choosing a more suitable mapper might be very worth it.
Due to the large amount of IRQs necessary (30 or so), IRQ latency buildup becomes a serious problem with mappers using cycle-based counters. The MMC3 may have it's issues, but makes it makes it easy to trigger IRQs every N scanlines, and you almost don't have to care whether the console is NTSC or PAL.