You don't need to disable NMIs if your NMI handler is "well behaved" and doesn't do PPU stuff unless it's told to by the main program via different flags.
Anyway, the best approach will depend on how you're currently dividing the logic and the drawing. If I remember correctly, Nerdy Nights starts out with the worst possible program structure, which puts logic and drawing in the NMI handler, in that order (which only allows you to use 7.6% of the total CPU time!). I don't know if that changes later on, but if that happens to be the structure you're using, I suggest you fix that immediately, and switch to a program structure that allows you to use the full CPU time.
The most newbie-friendly program structure IMO is the one where the NMI just updates a counter:
Code:
NMI:
inc FrameCount
rti
Then you can just wait for this counter to change whenever you need to wait for vblank:
Code:
lda FrameCount
WaitForVblank:
cmp FrameCount
beq WaitForVblank
This structure is great because you can have completely independent game modes (no shared NMI handler that needs to cater to the needs of every mode), and there's no risk of conflicts between the main thread and the NMI thread because the NMI thread only does literally one thing, and never touches anything the main thread might be using.
The only disadvantage of this program structure is that it can't handle lag frames. If you take longer than a hardware frame to process a game frame, you'll completely miss one vertical blank, meaning that the music will slow down and any raster effects not triggered by IRQs (such as sprite 0 hit status bars) will glitch.
Anyway, since program modes can be completely independent from each other, you can easily code separate blocks of initialization->logic->drawing, one for each mode. Something like this:
Code:
TitleScreenInitialization:
;wait for vblank
;disable rendering
;draw name table
;setup objects (menu cursor, etc.)
;wait for vblank
;set the scroll
;enable rendering
TitleScreenLogic:
;read the controllers
;update objects
;if an end condition is met (e.g. start is pressed), jump to the initialization of another game mode
TitleScreenDrawing:
;wait for vblank
;do a sprite DMA
;set the scroll
;play music/sfx
jmp TitleScreenLogic
And this is the basic idea... Just implement as many game modes as you need and jump between them.
If you want to have fade transitions, you can't immediately jump to another game mode, you have to somehow signal the intention to switch to another mode (use a NextGameMode variable or something) and initialize the fading animation, and once that finishes the next game mode is called.