You set up your first IRQ here in your main thread code. This happens directly after the NMI returns:
Code: Select all
00:9BB8: 20 C0 E3 JSR $E3C0 ; wait for NMI
>00:9BBB: A9 01 LDA #$01 ; setup first interrupt
00:9BBD: 8D 00 E0 STA $E000
00:9BC0: 8D 00 C0 STA $C000
00:9BC3: A9 00 LDA #$00
00:9BC5: 8D 01 C0 STA $C001
00:9BC8: A9 01 LDA #$01
00:9BCA: 8D 01 E0 STA $E001
00:9BCD: A9 00 LDA #$00
00:9BCF: 85 74 STA $74
The solution should be to put this inside your NMI handler. See my last suggestion from my previous post, you should still add that CLI and RTI, but right there above the suggested CLI do this first IRQ setup right there, when you know you're still in vblank (i.e. before scanline 0) and you haven't yet run the music routine. This will allow that first IRQ to fire on scanline 0 (which will sometimes be within the music routine, but it is perfectly okay to interrupt that).
Alternative option is to put the music playback call in your main thread just after that STA $74. This will get your NMI handler returning earlier again.
Ideally both of these things should be within the NMI, though. Having the IRQs set off by the NMI will prevent them from failling if your main thread ever runs too long (slowdown), and similar with music having it in the NMI makes it slowdown resitant. However, if you can guarantee the main thread will never run long it doesn't matter either way.