The main problem seems to be that your NMI returns using RTS instead of RTI. Interrupts put 3 things on the stack, not 2, and so you need to use RTI for them. (The format of the return address also slightly differs between them.) Interrupt handlers should also be saving A, X, and Y at the start and restoring them at the end because interrupts can happen anytime during code, and so if you don't save and restore registers, then when you return from the interrupt, the registers the code was using are trashed and that code will misbehave.
Once you fix the RTI problem, then the game seems to just return to an infinite loop, so while it reads joypads, it never does anything with the result. I'm not exactly sure why we see the symptom that it crashes when right is pressed (right is the last button read and may change register state when mistakenly RTS'ing from the function), but it's not important to dig into that.
If it helps, I wrote up some skeleton code
here showing the basics of how a game might be laid out, covering an NMI and the main loop that handles joypad reading and mode dispatch. Note that you normally want to read your joypads in your main loop, so unless all of your game logic is in your NMI, it shouldn't live in the NMI. I also don't normally recommend having everything in your NMI because it makes it hard to run your sound engine on lag frames, and laggy sound makes slowdown feel much worse.