I made some changes to the neslib and nesdoug library files.
There was a bug where, if you called one of the sprite functions at the exact end of the frame, it could have placed only half of a sprite’s data in the sprite buffer before the nmi sent it to the OAM RAM for the next frame. This could cause an incorrect sprite to be be shown.
The nmi code has been modified so that it will only DMA the OAM (sprite data) if you have reached the next ppu_wait_frame() or ppu_wait_nmi(). Now, a lag frame will just result in the previous frame being shown twice, with no changes.
Another change — I removed clear_vram_buffer(). I feel like this is something that should be done automatically, when the vram buffer is copied to the PPU. I have seen people confused as to when to use clear_vram_buffer(), so this should clear up any confusion, it will manage itself.
If you need clear_vram_buffer() for some reason, the code is still there, it’s just commented out (in nesdoug.h and nesdoug.s… and I removed the .export _clear_vram_buffer). You can easily put it back in.
And, I changed the name of flush_vram_update_nmi() to flush_vram_update2(). The name was misleading, the way I was using it — entirely outside of the nmi (ie. pushing updates to the PPU with the screen off).
One caution — split screens still can’t handle lag frames. If you are using a sprite zero split screen, make sure that the code isn’t so complex that it runs past the bottom of the frame. I suppose you could rewrite the nmi code (in assembly) and put the split screen code directly there, to fix it.
I did make sure that the MMC3 code can handle lag frames and do split screens. That is because you can handle the split with IRQs. The nmi code still runs the IRQ function on lag frames.
Minor change — I redid the Full BG and Fade examples. The code is the same, but I thought I could make it look nicer if I used the NESIFIER tool that I made.